From 43f8b045dab10d2491839dea2fff6ef1d08865be Mon Sep 17 00:00:00 2001 From: Charliechen114514 <725610365@qq.com> Date: Sat, 4 Jul 2026 21:05:54 +0800 Subject: [PATCH] fix: better apps import policy --- .gitignore | 6 +++ apps/README.md | 35 ---------------- .../path/src/desktop_main_path_resolvers.cpp | 6 +++ desktop/ui/components/launcher/CMakeLists.txt | 1 + .../ui/components/launcher/app_discoverer.cpp | 20 ++++++--- .../ui/components/launcher/app_discoverer.h | 10 ++--- third_party/apps/README.md | 41 +++++++++++++++++++ 7 files changed, 73 insertions(+), 46 deletions(-) delete mode 100644 apps/README.md create mode 100644 third_party/apps/README.md diff --git a/.gitignore b/.gitignore index 5e3fcc80d..51f1dc944 100644 --- a/.gitignore +++ b/.gitignore @@ -27,6 +27,12 @@ document/api/ third_party/*/ !third_party/aex/ !third_party/QuarkWidgets/ +!third_party/apps/ +# third_party/apps/ is a local parking spot for cloned app source trees +# (CFDeskit, future pdfReader/MediaPlayer/...). Only the README is tracked; +# each developer clones their own app repos, content stays untracked. +third_party/apps/* +!third_party/apps/README.md !third_party/.gitkeep __pycache__/ diff --git a/apps/README.md b/apps/README.md deleted file mode 100644 index af02052bd..000000000 --- a/apps/README.md +++ /dev/null @@ -1,35 +0,0 @@ -# apps/ — deployment target (no source) - -This directory is the **runtime deployment target** for standalone desktop apps. -App sources no longer live in this repo — they were extracted to the separate -[`CFDeskit`](https://github.com/Awesome-Embedded-Learning-Studio/CFDeskit) -repository (calculator, noter, alarm_clock, calendar, system_state). - -## Deployment contract - -`AppDiscoverer` (in `desktop/ui/components/launcher/`) scans -`/../apps//app.json` at startup. Each app ships as a self-contained -package: - -``` -/apps/ - libquarkwidgets.so # shared by all apps (rpath $ORIGIN/..) - / - # executable - app.json # manifest (app_id, display_name, exec, launch_kind) -``` - -## How to deploy - -Build CFDeskit and install (or copy) its `apps/` tree here: - -```bash -# clean install: -( cd ~/CFDeskit && cmake --install build --prefix ) -# quick local test against an existing CFDesktop build tree: -cp -r ~/CFDeskit/build/apps/. /out/build_develop/apps/ -``` - -Apps resolve `libquarkwidgets.so` via rpath `$ORIGIN/..` and runtime-verify the -ABI version (`abi_check.hpp`), so the apps' QuarkWidgets version is fully -decoupled from the desktop's `bin/libquarkwidgets.so`. diff --git a/desktop/base/path/src/desktop_main_path_resolvers.cpp b/desktop/base/path/src/desktop_main_path_resolvers.cpp index e82e29df8..45b1e0755 100644 --- a/desktop/base/path/src/desktop_main_path_resolvers.cpp +++ b/desktop/base/path/src/desktop_main_path_resolvers.cpp @@ -41,6 +41,12 @@ bool DesktopMainPathProvider::request_created(const PathType p) { } QString DesktopMainPathProvider::absolutePath(const PathType p) { + // Apps is the runtime deployment target for standalone apps — lowercase to + // match the unix-style "apps" directory convention. Other PathTypes use + // their X-macro stringified name (Home, Desktop, Documents, ...). + if (p == PathType::Apps) { + return make(root, "apps"); + } return make(root, DesktopMainPathProvider::kPathNames[static_cast(p)]); } diff --git a/desktop/ui/components/launcher/CMakeLists.txt b/desktop/ui/components/launcher/CMakeLists.txt index 0e0aaca99..6677d4924 100644 --- a/desktop/ui/components/launcher/CMakeLists.txt +++ b/desktop/ui/components/launcher/CMakeLists.txt @@ -21,4 +21,5 @@ PRIVATE QuarkWidgets::quarkwidgets # ThemeManager + Material tokens for the popup/tiles cfbase # aex::expected / WeakPtrFactory (propagated via cfbase -> aex::aex) cflogger # Diagnostic logging for launch success/failure + cfpath # DesktopMainPathProvider: third_party/apps discovery path ) diff --git a/desktop/ui/components/launcher/app_discoverer.cpp b/desktop/ui/components/launcher/app_discoverer.cpp index c4da9a6df..e9212ffeb 100644 --- a/desktop/ui/components/launcher/app_discoverer.cpp +++ b/desktop/ui/components/launcher/app_discoverer.cpp @@ -12,8 +12,8 @@ #include "app_discoverer.h" #include "cflog.h" +#include "cfpath/desktop_main_path_resolvers.h" -#include #include #include #include @@ -30,18 +30,24 @@ constexpr const char* kManifestName = "app.json"; } // namespace QList AppDiscoverer::discover() { - const QString apps_dir = QCoreApplication::applicationDirPath() + QStringLiteral("/../apps"); + // Apps deployment target: /apps//{exe, app.json}. This is + // where installed/built apps land (e.g. via CFDeskit's cmake --install). + const QString apps_dir = cf::desktop::path::DesktopMainPathProvider::instance().absolutePath( + cf::desktop::path::DesktopMainPathProvider::PathType::Apps); return discoverFrom(apps_dir); } QList AppDiscoverer::discoverFrom(const QString& apps_dir) { QList result; - QDir dir(apps_dir); - if (!dir.exists()) { + if (!QDir(apps_dir).exists()) { + // Apps are optional — a missing apps directory is normal (nothing + // deployed yet). Log INFO, not a warning, and return empty. + log::infoftag(kLogTag, "Apps directory '{}' not found; no apps to discover", + apps_dir.toStdString()); return result; } - const QFileInfoList subdirs = dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot); + const QFileInfoList subdirs = QDir(apps_dir).entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot); for (const auto& sub : subdirs) { const QString app_dir = sub.absoluteFilePath(); const QString manifest_path = @@ -85,6 +91,10 @@ QList AppDiscoverer::discoverFrom(const QString& apps_dir) { result.append(entry); } + + if (result.isEmpty()) { + log::infoftag(kLogTag, "No apps discovered under '{}'", apps_dir.toStdString()); + } return result; } diff --git a/desktop/ui/components/launcher/app_discoverer.h b/desktop/ui/components/launcher/app_discoverer.h index 219b46363..f1a50a803 100644 --- a/desktop/ui/components/launcher/app_discoverer.h +++ b/desktop/ui/components/launcher/app_discoverer.h @@ -27,13 +27,15 @@ namespace cf::desktop::desktop_component { * @brief Discovers standalone apps from per-app @c app.json manifests. * * The discovery contract: - * - @c //app.json is the manifest (JSON object). + * - Scans @c /apps//app.json (the runtime deployment target + * — where built apps are installed, e.g. via CFDeskit's @c cmake --install). * - Fields: @c app_id, @c display_name, @c icon (relative to manifest), * @c exec (relative to manifest). * - @c icon_path / @c exec_command are resolved to absolute paths * (@c /). * - Subdirs without @c app.json are skipped silently; manifests missing * @c app_id or @c exec are skipped with a warning (no silent fallback). + * - Empty/missing apps directory → INFO log, empty result (apps are optional). * * @ingroup components */ @@ -42,13 +44,11 @@ class AppDiscoverer { AppDiscoverer() = delete; /** - * @brief Discovers apps under @c /../apps//app.json. + * @brief Discovers apps under @c /apps//app.json. * * @return Parsed AppEntry list (icon/exec resolved to absolute paths); * empty if the apps directory is absent or has no manifests. - * * @throws None. - * * @since 0.20 * @ingroup components */ @@ -58,9 +58,7 @@ class AppDiscoverer { * @brief Discovers apps under @p apps_dir. * * @param[in] apps_dir Directory containing / subdirs with app.json. - * * @return Parsed AppEntry list. - * * @throws None. * @note Used by discover(); exposed for unit tests. * @since 0.20 diff --git a/third_party/apps/README.md b/third_party/apps/README.md new file mode 100644 index 000000000..dda2d7990 --- /dev/null +++ b/third_party/apps/README.md @@ -0,0 +1,41 @@ +# third_party/apps/ — local app source parking (untracked) + +This directory is a **local parking spot for app source trees**. Clone any +standalone app repo here and build it; then deploy (install/copy) the built +apps to the **runtime apps directory** (`/apps/`, e.g. +`~/desktop/apps/`) where `AppDiscoverer` scans at startup. + +**Not a submodule, not tracked** (see `.gitignore`) — every developer clones +their own. The main repo stays free of app sources. + +## Workflow + +```bash +# 1. clone an app repo here (source parking) +git clone https://github.com/Awesome-Embedded-Learning-Studio/CFDeskit.git \ + third_party/apps/CFDeskit + +# 2. build it +cmake -S third_party/apps/CFDeskit -B third_party/apps/CFDeskit/build +cmake --build third_party/apps/CFDeskit/build -j + +# 3. deploy to the runtime apps dir (/apps/) +cmake --install third_party/apps/CFDeskit/build --prefix "$HOME/desktop" +# or, for a quick copy: +cp -r third_party/apps/CFDeskit/build/apps/. "$HOME/desktop/apps/" +``` + +The desktop discovers apps under `/apps//app.json` — that's +where built executables + their manifests must land. This `third_party/apps/` +directory is **only source parking**; the desktop does NOT scan here. + +## One rule, all apps + +Same flow for any app repo: CFDeskit today; `pdfReader` / `MediaPlayer` / +embedded tools in the future. Clone here, build, deploy to `~/desktop/apps/`. +No per-app wiring in the main repo. + +## If `~/desktop/apps/` is empty + +The desktop logs `INFO: No apps discovered under '.../apps'` and continues — +**no error, no crash**. Deploy an app whenever you need it.