From 341bcacafe522aa81cca025823d588c6c8a0c910 Mon Sep 17 00:00:00 2001 From: magdev Date: Sun, 3 May 2026 13:43:48 +0200 Subject: [PATCH] skeleton: bring AppImage parity, scaffolded apps inherit the packaging flow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The v0.1.0 shakedown fixes for AppImage assembly (path-repo symlink:false sed, writable-cache redirect) all landed in examples/todo. The skeleton — which is what bin/php-qml-init copies when scaffolding a new app — had no `appimage` target at all, so every scaffolded app would have to either copy the example's Makefile by hand or re-discover the same shakedown bugs. Brings parity: - framework/skeleton/Makefile gains `staging-symfony` and `appimage` targets, mirroring the example's. Two new variables (BUNDLE_SRC, PACKAGING) parameterise the framework-tree paths so bin/php-qml-init can rewrite them at scaffold time without sed-touching the recipe. - framework/skeleton/packaging/skeleton.{desktop,png} added — minimum surface for the AppImage assembly to succeed without the user needing to author them. - framework/skeleton/Makefile's staging-symfony recipe handles both relative (framework default `../../php`) and absolute (post-scaffold) BUNDLE_SRC values via a case statement. - bin/php-qml-init renames packaging/skeleton.* → packaging/$NAME.*, rewrites the .desktop file's Name/Exec/Icon, and updates the Makefile's --app-name / --output / --desktop / --icon flags + BUNDLE_SRC + PACKAGING variables. For --vendor mode, framework's packaging/linux/ is also vendored to .bridge-packaging/ alongside the existing .bridge/ + .bridge-qml/. Verified by scaffolding both modes: - non-vendored: BUNDLE_SRC + PACKAGING absolute paths - --vendor: BUNDLE_SRC=../.bridge, PACKAGING=.bridge-packaging, .bridge-packaging/ contains build-appimage.sh Skeleton's `make quality` still green; staging-symfony works locally (vendor/php-qml/bridge resolves to a real directory, not a symlink). Closes the v0.1.1 follow-up "bin/php-qml-init parity" tracked in PLAN.md §13. Bundled drive-by: docs/makers.md picked up two markdownlint auto-fixes (blank lines around lists) when the IDE saved. Co-Authored-By: Claude Opus 4.7 (1M context) --- bin/php-qml-init | 38 +++++++++++++++- docs/makers.md | 2 + framework/skeleton/Makefile | 43 +++++++++++++++++- framework/skeleton/packaging/skeleton.desktop | 8 ++++ framework/skeleton/packaging/skeleton.png | Bin 0 -> 209 bytes 5 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 framework/skeleton/packaging/skeleton.desktop create mode 100644 framework/skeleton/packaging/skeleton.png diff --git a/bin/php-qml-init b/bin/php-qml-init index 64aafdf..982c9e6 100755 --- a/bin/php-qml-init +++ b/bin/php-qml-init @@ -146,11 +146,31 @@ sed -i \ -e "s|php-qml — skeleton|php-qml — $NAME|g" \ "$TARGET/qml/Main.qml" -# Makefile: $(BUILD_DIR)/skeleton → $(BUILD_DIR)/$NAME. +# Makefile: rewrite identifiers for the appimage target — binary name, +# packaging filenames, AppImage output filename. The path-repo + packaging +# absolute paths are handled later (after we know vendor vs absolute mode). sed -i \ -e "s|\$(BUILD_DIR)/skeleton|\$(BUILD_DIR)/$NAME|g" \ + -e "s|--app-name skeleton|--app-name $NAME|g" \ + -e "s|packaging/skeleton.desktop|packaging/$NAME.desktop|g" \ + -e "s|packaging/skeleton.png|packaging/$NAME.png|g" \ + -e "s|build/Skeleton-x86_64.AppImage|build/$PASCAL-x86_64.AppImage|g" \ "$TARGET/Makefile" +# Rename packaging files to match the app name + rewrite the Exec/Icon +# fields in the .desktop file (XDG-launched binary lookup uses these). +if [ -f "$TARGET/packaging/skeleton.desktop" ]; then + mv "$TARGET/packaging/skeleton.desktop" "$TARGET/packaging/$NAME.desktop" + sed -i \ + -e "s|^Name=php-qml Skeleton|Name=php-qml $PASCAL|" \ + -e "s|^Exec=skeleton|Exec=$NAME|" \ + -e "s|^Icon=skeleton|Icon=$NAME|" \ + "$TARGET/packaging/$NAME.desktop" +fi +if [ -f "$TARGET/packaging/skeleton.png" ]; then + mv "$TARGET/packaging/skeleton.png" "$TARGET/packaging/$NAME.png" +fi + # .vscode/launch.json: binary path + config label both mention `skeleton`. if [ -f "$TARGET/.vscode/launch.json" ]; then sed -i \ @@ -168,6 +188,8 @@ if [ "$VENDOR" -eq 1 ]; then mkdir -p "$TARGET/.bridge" say "vendoring framework/qml → $NAME/.bridge-qml/" mkdir -p "$TARGET/.bridge-qml" + say "vendoring framework/packaging → $NAME/.bridge-packaging/" + mkdir -p "$TARGET/.bridge-packaging" if command -v rsync >/dev/null 2>&1; then rsync -a --delete \ --exclude 'vendor/' --exclude '.phpunit.cache/' \ @@ -176,18 +198,23 @@ if [ "$VENDOR" -eq 1 ]; then rsync -a --delete \ --exclude 'build/' \ "$FRAMEWORK/framework/qml/" "$TARGET/.bridge-qml/" + rsync -a --delete \ + "$FRAMEWORK/packaging/linux/" "$TARGET/.bridge-packaging/" else cp -R "$FRAMEWORK/framework/php/." "$TARGET/.bridge/" cp -R "$FRAMEWORK/framework/qml/." "$TARGET/.bridge-qml/" + cp -R "$FRAMEWORK/packaging/linux/." "$TARGET/.bridge-packaging/" rm -rf "$TARGET/.bridge/vendor" "$TARGET/.bridge-qml/build" 2>/dev/null || true fi BUNDLE_URL="../.bridge" # qml/CMakeLists.txt lives at $TARGET/qml/, vendored qml module at # $TARGET/.bridge-qml/, so the relative path from the consumer is ../.bridge-qml. QML_FW_PATH="\${CMAKE_CURRENT_SOURCE_DIR}/../.bridge-qml" + PACKAGING_PATH=".bridge-packaging" else BUNDLE_URL="$FRAMEWORK/framework/php" QML_FW_PATH="$FRAMEWORK/framework/qml" + PACKAGING_PATH="$FRAMEWORK/packaging/linux" fi say "path-repo → $BUNDLE_URL" # Replace the original "../../php" path-repo URL. The skeleton's @@ -206,6 +233,15 @@ sed -i \ -e "s|\${CMAKE_CURRENT_SOURCE_DIR}/../../qml|$QML_FW_PATH|g" \ "$TARGET/qml/CMakeLists.txt" +# Makefile: BUNDLE_SRC + PACKAGING were framework-tree relative; rewrite +# to absolute (or the vendored path). Both are matched against the literal +# values in the skeleton Makefile. +say "appimage paths → bundle=$BUNDLE_URL packaging=$PACKAGING_PATH" +sed -i \ + -e "s|^BUNDLE_SRC := ../../php\$|BUNDLE_SRC := $BUNDLE_URL|" \ + -e "s|^PACKAGING := ../../packaging/linux\$|PACKAGING := $PACKAGING_PATH|" \ + "$TARGET/Makefile" + # ── Composer install + first-run migrations ────────────────────────── if [ "$SKIP_INSTALL" -eq 1 ]; then say "skipping composer install (--skip-install)" diff --git a/docs/makers.md b/docs/makers.md index 3f9955f..a4775c1 100644 --- a/docs/makers.md +++ b/docs/makers.md @@ -61,6 +61,7 @@ bin/console make:bridge:resource Todo --int-id ``` When to use which: + - **UUIDv7 (default)** — distributed-friendly, exposes no insertion-order leak, sortable. Good for anything an end-user might sync between machines. - **Integer ID** — easier to debug from a shell; smaller wire size; no client-side ID generation needed. Pick this for purely-local single-machine apps. @@ -179,6 +180,7 @@ bin/console make:bridge:window Settings ``` The generated QML window: + - Imports `PhpQml.Bridge`. - Wraps content in `AppShell` (so it shows the same Reconnecting / Offline chrome as the main window). - Has its own RestClient + a `Connections { target: SingleInstance ... }` block for launch-arg forwarding. diff --git a/framework/skeleton/Makefile b/framework/skeleton/Makefile index 19b2014..0e7f122 100644 --- a/framework/skeleton/Makefile +++ b/framework/skeleton/Makefile @@ -6,6 +6,11 @@ SYMFONY_DIR := symfony QML_SRC_DIR := qml BUILD_DIR := build/qml QT_BIN := $(BUILD_DIR)/skeleton +# Path to framework/php (path-repo source) and packaging/linux (build-appimage.sh). +# Both are framework-tree relative; bin/php-qml-init rewrites them at scaffold time +# to either an absolute framework path (default) or a vendored copy under .bridge/. +BUNDLE_SRC := ../../php +PACKAGING := ../../packaging/linux .PHONY: help help: ## Show available targets @@ -34,7 +39,43 @@ doctor-connect: ## Run bridge:doctor with backend connectivity probe .PHONY: clean clean: ## Remove build artefacts - rm -rf $(BUILD_DIR) + rm -rf $(BUILD_DIR) build/staging-symfony + +.PHONY: staging-symfony +staging-symfony: ## Stage a --no-dev composer copy of symfony for AppImage assembly + # See examples/todo/Makefile for the rationale; same logic, mirrored here + # so scaffolded apps inherit a working AppImage flow without copy-paste. + # BUNDLE_SRC may be absolute (after `php-qml-init` rewrites it for a + # scaffolded app) or relative-to-symfony (framework default `../../php`); + # the case-statement handles both. + rm -rf build/staging-symfony + rsync -a --delete \ + --exclude='vendor/' \ + --exclude='var/cache/' --exclude='var/log/' \ + $(SYMFONY_DIR)/ build/staging-symfony/ + set -e; case "$(BUNDLE_SRC)" in \ + /*) BUNDLE_ABS="$(BUNDLE_SRC)" ;; \ + *) BUNDLE_ABS="$$(cd $(SYMFONY_DIR)/$(BUNDLE_SRC) && pwd)" ;; \ + esac; \ + sed -i "s|\"$(BUNDLE_SRC)\"|\"$$BUNDLE_ABS\"|" build/staging-symfony/composer.json + sed -i 's|"symlink": true|"symlink": false|' build/staging-symfony/composer.json + rm -f build/staging-symfony/composer.lock + cd build/staging-symfony && composer install --no-dev --no-interaction --classmap-authoritative + +.PHONY: appimage +appimage: build staging-symfony ## Package as a single-file Linux AppImage at build/Skeleton-x86_64.AppImage + $(PACKAGING)/build-appimage.sh \ + --app-name skeleton \ + --host-binary $(QT_BIN) \ + --symfony-dir build/staging-symfony \ + --frankenphp $${FRANKENPHP:-frankenphp} \ + --caddyfile Caddyfile \ + --desktop packaging/skeleton.desktop \ + --icon packaging/skeleton.png \ + --output build/Skeleton-x86_64.AppImage \ + $${APPIMAGE_UPDATE_INFO:+--update-info "$$APPIMAGE_UPDATE_INFO"} + @echo + @echo "AppImage built. Test with: ./build/Skeleton-x86_64.AppImage" .PHONY: quality quality: build ## Run PHPStan, php-cs-fixer (check), PHPUnit, qmllint, maker snapshots diff --git a/framework/skeleton/packaging/skeleton.desktop b/framework/skeleton/packaging/skeleton.desktop new file mode 100644 index 0000000..e1bef28 --- /dev/null +++ b/framework/skeleton/packaging/skeleton.desktop @@ -0,0 +1,8 @@ +[Desktop Entry] +Type=Application +Name=php-qml Skeleton +Comment=php-qml application scaffold (replace with your own) +Exec=skeleton +Icon=skeleton +Categories=Utility; +Terminal=false diff --git a/framework/skeleton/packaging/skeleton.png b/framework/skeleton/packaging/skeleton.png new file mode 100644 index 0000000000000000000000000000000000000000..9d717b8ac1a57f78621aa288788ddf6e4b4b8dfa GIT binary patch literal 209 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=Gdx`!Ln`LHy5ZwTyJ)zGYOi*!X|F1N#f08yP%Z{an^L HB{Ts5$-70z literal 0 HcmV?d00001