commit 165dc1f1fb1ce38e66667530190be33c2aa25c37
parent e1b005d2be44bc987901508f05e8f018b44e1f1d
Author: triesap <tyson@radroots.org>
Date: Fri, 17 Apr 2026 22:55:04 +0000
app: add macos host bundle launcher
Diffstat:
5 files changed, 168 insertions(+), 1 deletion(-)
diff --git a/platforms/macos/App/Resources/Info.plist b/platforms/macos/App/Resources/Info.plist
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>en</string>
+ <key>CFBundleExecutable</key>
+ <string>Radroots</string>
+ <key>CFBundleIdentifier</key>
+ <string>org.radroots.app.macos</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>Radroots</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>0.1.0</string>
+ <key>CFBundleVersion</key>
+ <string>1</string>
+ <key>LSMinimumSystemVersion</key>
+ <string>15.0</string>
+ <key>NSPrincipalClass</key>
+ <string>NSApplication</string>
+</dict>
+</plist>
diff --git a/platforms/macos/Scripts/build-macos-host.sh b/platforms/macos/Scripts/build-macos-host.sh
@@ -0,0 +1,72 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
+platform_root="$(cd "${script_dir}/.." && pwd -P)"
+repo_root="$(git -C "${script_dir}" rev-parse --show-toplevel)"
+configuration="${CONFIGURATION:-Debug}"
+bundle_name="Radroots.app"
+bundle_root="${platform_root}/.derived-data/Build/Products/${configuration}/${bundle_name}"
+contents_root="${bundle_root}/Contents"
+executable_root="${contents_root}/MacOS"
+resources_root="${contents_root}/Resources"
+plist_template="${platform_root}/App/Resources/Info.plist"
+plist_path="${contents_root}/Info.plist"
+binary_target="${executable_root}/Radroots"
+
+require_command() {
+ if command -v "$1" >/dev/null 2>&1; then
+ return
+ fi
+ echo "missing required command: $1" >&2
+ exit 1
+}
+
+workspace_version() {
+ python3 - <<'PY' "${repo_root}/Cargo.toml"
+import re
+import sys
+
+path = sys.argv[1]
+with open(path, "r", encoding="utf-8") as handle:
+ cargo_toml = handle.read()
+
+match = re.search(r'^\[workspace\.package\][\s\S]*?^version\s*=\s*"([^"]+)"', cargo_toml, re.MULTILINE)
+if not match:
+ raise SystemExit("missing workspace.package.version")
+
+print(match.group(1), end="")
+PY
+}
+
+cargo_target_dir() {
+ cargo metadata --format-version 1 --no-deps | python3 -c 'import json, sys; print(json.load(sys.stdin)["target_directory"], end="")'
+}
+
+require_command cargo
+require_command git
+require_command python3
+require_command /usr/libexec/PlistBuddy
+
+(
+ cd "${repo_root}"
+ cargo build -p radroots_app
+)
+
+binary_source="$(cargo_target_dir)/debug/radroots_app"
+
+if [[ ! -x "${binary_source}" ]]; then
+ echo "missing desktop launcher binary: ${binary_source}" >&2
+ exit 1
+fi
+
+rm -rf "${bundle_root}"
+mkdir -p "${executable_root}" "${resources_root}"
+cp "${plist_template}" "${plist_path}"
+cp "${binary_source}" "${binary_target}"
+chmod +x "${binary_target}"
+
+/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $(workspace_version)" "${plist_path}"
+/usr/libexec/PlistBuddy -c "Set :CFBundleVersion ${RADROOTS_APP_BUILD:-1}" "${plist_path}"
+
+printf '%s\n' "${bundle_root}"
diff --git a/platforms/macos/Scripts/run-macos-host.sh b/platforms/macos/Scripts/run-macos-host.sh
@@ -0,0 +1,23 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
+
+require_command() {
+ if command -v "$1" >/dev/null 2>&1; then
+ return
+ fi
+ echo "missing required command: $1" >&2
+ exit 1
+}
+
+require_command /usr/libexec/PlistBuddy
+
+app_path="$("${script_dir}/build-macos-host.sh")"
+plist_path="${app_path}/Contents/Info.plist"
+executable_name="$(
+ /usr/libexec/PlistBuddy -c 'Print :CFBundleExecutable' "${plist_path}"
+)"
+executable_path="${app_path}/Contents/MacOS/${executable_name}"
+
+exec "${executable_path}" "$@"
diff --git a/platforms/macos/Scripts/test-macos-host.sh b/platforms/macos/Scripts/test-macos-host.sh
@@ -0,0 +1,41 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
+
+require_command() {
+ if command -v "$1" >/dev/null 2>&1; then
+ return
+ fi
+ echo "missing required command: $1" >&2
+ exit 1
+}
+
+require_command /usr/libexec/PlistBuddy
+
+app_path="$("${script_dir}/build-macos-host.sh")"
+plist_path="${app_path}/Contents/Info.plist"
+executable_name="$(
+ /usr/libexec/PlistBuddy -c 'Print :CFBundleExecutable' "${plist_path}"
+)"
+bundle_name="$(
+ /usr/libexec/PlistBuddy -c 'Print :CFBundleName' "${plist_path}"
+)"
+bundle_id="$(
+ /usr/libexec/PlistBuddy -c 'Print :CFBundleIdentifier' "${plist_path}"
+)"
+
+[[ "${bundle_name}" == "Radroots" ]] || {
+ echo "unexpected CFBundleName: ${bundle_name}" >&2
+ exit 1
+}
+
+[[ "${bundle_id}" == "org.radroots.app.macos" ]] || {
+ echo "unexpected CFBundleIdentifier: ${bundle_id}" >&2
+ exit 1
+}
+
+[[ -x "${app_path}/Contents/MacOS/${executable_name}" ]] || {
+ echo "missing bundle executable: ${app_path}/Contents/MacOS/${executable_name}" >&2
+ exit 1
+}
diff --git a/scripts/run.sh b/scripts/run.sh
@@ -5,4 +5,9 @@ script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
repo_root="$(git -C "${script_dir}" rev-parse --show-toplevel)"
cd "${repo_root}"
-cargo run -p radroots_app -- "$@"
+
+if [[ "$(uname -s)" == "Darwin" ]]; then
+ exec "${repo_root}/platforms/macos/Scripts/run-macos-host.sh" "$@"
+fi
+
+exec cargo run -p radroots_app -- "$@"