build(lite): wire macOS --lite packaging in build.sh (M5b)
The mac-release path was mostly ObsidianDragon-hardcoded, so `--lite --mac-release`
would produce a broken bundle. Make it variant-aware, mirroring the linux/win lite
handling that already keys off APP_BASENAME + should_bundle_full_node_assets:
- SDL3 rpath fix, the launcher script + its .bin pair, and CFBundleExecutable now
follow ${APP_BASENAME} (ObsidianDragonLite), so the bundle's executable resolves.
- Lite variant gets its own CFBundleName/CFBundleDisplayName ("DragonX Wallet Lite"),
CFBundleIdentifier (is.hush.dragonx.lite), DMG filename (DragonX_Wallet_Lite-…)
and volume name, so it can coexist with the full-node app.
- Full-node assets (daemon, Sapling params, asmap) were already gated out for lite;
the lite backend artifact is auto-selected for the macos platform by the existing
--lite-backend logic, and CMAKE_LITE_ARGS already reaches the mac configure.
Authored + validated on Linux (bash -n; launcher heredoc, plist, and DMG naming
render correctly for the lite variant) but NOT yet built/run — that needs macOS or
osxcross, neither available here. CLAUDE.md updated to reflect the wired-but-unverified
status; remaining M5b is verifying it on a Mac plus CI backend-artifact build + signing.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -70,9 +70,9 @@ Guard full-node-only code paths with `#if DRAGONX_LITE_BUILD` / chat code with `
|
||||
|
||||
The Lite variant is **functionally complete and runtime-verified on Linux + Windows** (work lives on branch `cleanup/lite-plan-churn`, **local-only — not pushed yet**):
|
||||
- **Implemented:** lifecycle (create/open/restore + auto-open on startup), sync, refresh, send / shield / import / export / seed, persistence (the backend does *not* auto-save after sync/send/shield — the controller triggers `save` at those points), and passphrase **encryption** (encrypt/unlock/lock/decrypt + Settings UI + send-time & startup unlock; the backend locks immediately on `encrypt`). All controller-tested against the fake backend (`tests/fake_lite_backend.h`) and smoke-verified against the real SDXL backend via `tools/lite_smoke` (incl. a full sync). GUI is wired end-to-end with lite-appropriate wording; the full-node RPC connect loop / wizard / daemon strings are gated out of lite (lite "online" is derived from `lite_wallet_->walletOpen()`, not RPC).
|
||||
- **Packaging (verified):** `./build.sh --lite-backend --linux-release` (zip + AppImage) and `--win-release` (cross-compiled `.exe`; first build the Windows backend artifact with `scripts/build-lite-backend-artifact.sh --platform windows`). Both correctly exclude full-node assets.
|
||||
- **Packaging:** `./build.sh --lite-backend --linux-release` (zip + AppImage, **verified**) and `--win-release` (cross-compiled `.exe`, **verified**; first build the Windows backend artifact with `scripts/build-lite-backend-artifact.sh --platform windows`). macOS `--lite-backend --mac-release` is **wired but not yet verified on this Linux box** (needs macOS/osxcross): the `.app`/launcher/rpath/`CFBundleExecutable` follow `ObsidianDragonLite`, full-node assets are skipped, and the lite variant gets its own `CFBundleName` ("DragonX Wallet Lite"), bundle id (`is.hush.dragonx.lite`), and DMG name so it can coexist with the full-node app. All variants correctly exclude full-node assets.
|
||||
- **Rollout / kill-switch (implemented):** `wallet/lite_rollout_policy.{h,cpp}` is a pure, fail-open gate (local-only, no network) feeding `LiteWalletLifecycleService::availability()` (new `RolloutDisabled` reason). Inputs: the emergency env var `DRAGONX_LITE_KILL_SWITCH` (absolute — not even `force_on` bypasses it); a `lite_rollout` setting (`auto`/`force_on`/`force_off`); and an optional **locally-cached** manifest at `<config-dir>/lite_rollout.json` (`global_enabled`, `min_version`/`max_version`, `blocked_versions`, `rollout_permille`, `message`) keyed for staged rollout on a hashed, never-transmitted per-install id. A signed remote fetcher can populate that cache later without touching the policy. Resolved in `App::rebuildLiteWallet()`; the disable message surfaces via the lifecycle status. Unit-tested + runtime-verified (env / manifest / control).
|
||||
- **Remaining (M5b):** macOS packaging, CI backend-artifact build + signing.
|
||||
- **Remaining (M5b):** verify the wired macOS `--lite` packaging on a Mac/osxcross, CI backend-artifact build + signing.
|
||||
- **To publish:** rename branch → `feat/lite-wallet`, base the PR on `dev` (the full-node UX is already there), and handle the dormant gated-OFF HushChat content bundled in commit `af06b8b`.
|
||||
|
||||
The detailed milestone plan and design history (the v2 plan, backend artifact/ABI/signing design docs, the v1 plan, chat specs, etc.) are kept **untracked** under `docs/_archive/`.
|
||||
|
||||
51
build.sh
51
build.sh
@@ -80,6 +80,7 @@ Examples:
|
||||
$0 --linux-release # Linux release (zip + AppImage)
|
||||
$0 --win-release # Windows cross-compile
|
||||
$0 --mac-release # macOS bundle + DMG (native or osxcross)
|
||||
$0 --lite-backend --mac-release # macOS ObsidianDragonLite.app + DMG (lite backend)
|
||||
$0 --clean --linux-release --win-release # Clean + both
|
||||
EOF
|
||||
exit 0
|
||||
@@ -1045,26 +1046,34 @@ TOOLCHAIN
|
||||
# Fix the rpath so the binary finds SDL3 in Frameworks/
|
||||
if $IS_CROSS; then
|
||||
local INSTALL_NAME_TOOL="${OSXCROSS}/target/bin/${OSXCROSS_TRIPLE}-install_name_tool"
|
||||
[[ -x "$INSTALL_NAME_TOOL" ]] && "$INSTALL_NAME_TOOL" -change "@rpath/$sdl_name" "@executable_path/../Frameworks/$sdl_name" "$MACOS/ObsidianDragon" 2>/dev/null || true
|
||||
[[ -x "$INSTALL_NAME_TOOL" ]] && "$INSTALL_NAME_TOOL" -change "@rpath/$sdl_name" "@executable_path/../Frameworks/$sdl_name" "$MACOS/${APP_BASENAME}" 2>/dev/null || true
|
||||
else
|
||||
install_name_tool -change "@rpath/$sdl_name" "@executable_path/../Frameworks/$sdl_name" "$MACOS/ObsidianDragon" 2>/dev/null || true
|
||||
install_name_tool -change "@rpath/$sdl_name" "@executable_path/../Frameworks/$sdl_name" "$MACOS/${APP_BASENAME}" 2>/dev/null || true
|
||||
fi
|
||||
info " Bundled $sdl_name"
|
||||
fi
|
||||
|
||||
# Launcher script (ensures working dir + dylib path)
|
||||
mv "$MACOS/ObsidianDragon" "$MACOS/ObsidianDragon.bin"
|
||||
cat > "$MACOS/ObsidianDragon" <<'LAUNCH'
|
||||
# Launcher script (ensures working dir + dylib path). Uses ${APP_BASENAME} so the lite
|
||||
# variant (ObsidianDragonLite) gets a correctly-named launcher + .bin pair.
|
||||
mv "$MACOS/${APP_BASENAME}" "$MACOS/${APP_BASENAME}.bin"
|
||||
cat > "$MACOS/${APP_BASENAME}" <<LAUNCH
|
||||
#!/bin/bash
|
||||
DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
export DYLD_LIBRARY_PATH="$DIR/../Frameworks:$DYLD_LIBRARY_PATH"
|
||||
export DRAGONX_RES_PATH="$DIR/../Resources/res"
|
||||
cd "$DIR/../Resources"
|
||||
exec "$DIR/ObsidianDragon.bin" "$@"
|
||||
DIR="\$(cd "\$(dirname "\$0")" && pwd)"
|
||||
export DYLD_LIBRARY_PATH="\$DIR/../Frameworks:\$DYLD_LIBRARY_PATH"
|
||||
export DRAGONX_RES_PATH="\$DIR/../Resources/res"
|
||||
cd "\$DIR/../Resources"
|
||||
exec "\$DIR/${APP_BASENAME}.bin" "\$@"
|
||||
LAUNCH
|
||||
chmod +x "$MACOS/ObsidianDragon"
|
||||
chmod +x "$MACOS/${APP_BASENAME}"
|
||||
|
||||
# Info.plist
|
||||
# Info.plist — display name + bundle id differ per variant so lite and full-node .apps
|
||||
# can coexist; the executable matches the launcher (${APP_BASENAME}); the icon is shared.
|
||||
local APP_DISPLAY_NAME="DragonX Wallet"
|
||||
local APP_BUNDLE_ID="is.hush.dragonx"
|
||||
if $DO_LITE; then
|
||||
APP_DISPLAY_NAME="DragonX Wallet Lite"
|
||||
APP_BUNDLE_ID="is.hush.dragonx.lite"
|
||||
fi
|
||||
cat > "$CONTENTS/Info.plist" <<PLIST
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
|
||||
@@ -1072,17 +1081,17 @@ LAUNCH
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleName</key>
|
||||
<string>DragonX Wallet</string>
|
||||
<string>${APP_DISPLAY_NAME}</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>DragonX Wallet</string>
|
||||
<string>${APP_DISPLAY_NAME}</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>is.hush.dragonx</string>
|
||||
<string>${APP_BUNDLE_ID}</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>${VERSION}</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>${VERSION}</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>ObsidianDragon</string>
|
||||
<string>${APP_BASENAME}</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>ObsidianDragon</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
@@ -1151,13 +1160,15 @@ PLIST
|
||||
fi
|
||||
|
||||
# ── Create DMG ───────────────────────────────────────────────────────────
|
||||
local DMG_NAME="DragonX_Wallet-${VERSION}-macOS-${MAC_ARCH}.dmg"
|
||||
local DMG_BASENAME="DragonX_Wallet"
|
||||
$DO_LITE && DMG_BASENAME="DragonX_Wallet_Lite"
|
||||
local DMG_NAME="${DMG_BASENAME}-${VERSION}-macOS-${MAC_ARCH}.dmg"
|
||||
|
||||
if command -v create-dmg &>/dev/null; then
|
||||
# create-dmg (works on macOS; also available on Linux via npm)
|
||||
info "Creating DMG with create-dmg ..."
|
||||
create-dmg \
|
||||
--volname "DragonX Wallet" \
|
||||
--volname "${APP_DISPLAY_NAME}" \
|
||||
--volicon "$RESOURCES/ObsidianDragon.icns" \
|
||||
--window-pos 200 120 \
|
||||
--window-size 600 400 \
|
||||
@@ -1177,7 +1188,7 @@ PLIST
|
||||
mkdir -p "$staging"
|
||||
cp -a "$APP" "$staging/"
|
||||
ln -s /Applications "$staging/Applications"
|
||||
hdiutil create -volname "DragonX Wallet" \
|
||||
hdiutil create -volname "${APP_DISPLAY_NAME}" \
|
||||
-srcfolder "$staging" \
|
||||
-ov -format UDZO \
|
||||
"$out/$DMG_NAME" 2>/dev/null && {
|
||||
@@ -1193,7 +1204,7 @@ PLIST
|
||||
cp -a "$APP" "$staging/"
|
||||
# Can't create a real symlink to /Applications in an ISO, but the .app
|
||||
# is the important part — users drag it to Applications manually.
|
||||
genisoimage -V "DragonX Wallet" \
|
||||
genisoimage -V "${APP_DISPLAY_NAME}" \
|
||||
-D -R -apple -no-pad \
|
||||
-o "$out/$DMG_NAME" \
|
||||
"$staging" 2>/dev/null && {
|
||||
|
||||
Reference in New Issue
Block a user