commit 6492564a3007fe20ef83c1b8676c486b0603838a
parent 92c4051d65f247312fe3428835f524beba66f4ae
Author: triesap <tyson@radroots.org>
Date: Fri, 17 Apr 2026 23:00:44 +0000
app: add macos app icon
Diffstat:
4 files changed, 92 insertions(+), 0 deletions(-)
diff --git a/platforms/macos/App/Resources/Info.plist b/platforms/macos/App/Resources/Info.plist
@@ -8,6 +8,8 @@
<string>Radroots</string>
<key>CFBundleIdentifier</key>
<string>org.radroots.app.macos</string>
+ <key>CFBundleIconFile</key>
+ <string>AppIcon</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
diff --git a/platforms/macos/Scripts/build-macos-host.sh b/platforms/macos/Scripts/build-macos-host.sh
@@ -13,6 +13,7 @@ resources_root="${contents_root}/Resources"
plist_template="${platform_root}/App/Resources/Info.plist"
plist_path="${contents_root}/Info.plist"
binary_target="${executable_root}/Radroots"
+app_icon_path="${resources_root}/AppIcon.icns"
require_command() {
if command -v "$1" >/dev/null 2>&1; then
@@ -65,6 +66,7 @@ mkdir -p "${executable_root}" "${resources_root}"
cp "${plist_template}" "${plist_path}"
cp "${binary_source}" "${binary_target}"
chmod +x "${binary_target}"
+"${script_dir}/generate-macos-app-icon.sh" "${app_icon_path}"
/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $(workspace_version)" "${plist_path}"
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion ${RADROOTS_APP_BUILD:-1}" "${plist_path}"
diff --git a/platforms/macos/Scripts/generate-macos-app-icon.sh b/platforms/macos/Scripts/generate-macos-app-icon.sh
@@ -0,0 +1,80 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
+repo_root="$(git -C "${script_dir}" rev-parse --show-toplevel)"
+superproject_root="$(git -C "${script_dir}" rev-parse --show-superproject-working-tree || true)"
+output_path="${1:-}"
+
+require_command() {
+ if command -v "$1" >/dev/null 2>&1; then
+ return
+ fi
+ echo "missing required command: $1" >&2
+ exit 1
+}
+
+require_command git
+require_command sips
+require_command iconutil
+
+if [[ -n "${superproject_root}" && -f "${superproject_root}/logo.png" ]]; then
+ source_artwork="${superproject_root}/logo.png"
+else
+ source_artwork="${repo_root}/logo.png"
+fi
+
+if [[ -z "${output_path}" ]]; then
+ echo "usage: $0 <output-icns-path>" >&2
+ exit 1
+fi
+
+if [[ ! -f "${source_artwork}" ]]; then
+ echo "missing source artwork: ${source_artwork}" >&2
+ exit 1
+fi
+
+tmp_dir="$(mktemp -d)"
+cleanup() {
+ rm -rf "${tmp_dir}"
+}
+trap cleanup EXIT
+
+normalized_png="${tmp_dir}/logo.normalized.png"
+iconset_dir="${tmp_dir}/AppIcon.iconset"
+
+mkdir -p "${iconset_dir}" "$(dirname "${output_path}")"
+sips -s format png "${source_artwork}" --out "${normalized_png}" >/dev/null
+
+source_width="$(
+ sips -g pixelWidth "${normalized_png}" | awk '/pixelWidth/ {print $2}'
+)"
+source_height="$(
+ sips -g pixelHeight "${normalized_png}" | awk '/pixelHeight/ {print $2}'
+)"
+
+if [[ "${source_width}" -lt 1024 || "${source_height}" -lt 1024 ]]; then
+ printf '%s\n' \
+ "warning: macos icon source is ${source_width}x${source_height}; 1024x1024 is recommended for crisp AppIcon.icns output" \
+ >&2
+fi
+
+generate_icon() {
+ local filename="$1"
+ local size_px="$2"
+ sips -z "${size_px}" "${size_px}" "${normalized_png}" \
+ --out "${iconset_dir}/${filename}" >/dev/null
+}
+
+generate_icon "icon_16x16.png" 16
+generate_icon "icon_16x16@2x.png" 32
+generate_icon "icon_32x32.png" 32
+generate_icon "icon_32x32@2x.png" 64
+generate_icon "icon_128x128.png" 128
+generate_icon "icon_128x128@2x.png" 256
+generate_icon "icon_256x256.png" 256
+generate_icon "icon_256x256@2x.png" 512
+generate_icon "icon_512x512.png" 512
+generate_icon "icon_512x512@2x.png" 1024
+
+iconutil -c icns "${iconset_dir}" -o "${output_path}"
diff --git a/platforms/macos/Scripts/test-macos-host.sh b/platforms/macos/Scripts/test-macos-host.sh
@@ -24,6 +24,9 @@ bundle_name="$(
bundle_id="$(
/usr/libexec/PlistBuddy -c 'Print :CFBundleIdentifier' "${plist_path}"
)"
+icon_name="$(
+ /usr/libexec/PlistBuddy -c 'Print :CFBundleIconFile' "${plist_path}"
+)"
[[ "${bundle_name}" == "Radroots" ]] || {
echo "unexpected CFBundleName: ${bundle_name}" >&2
@@ -39,3 +42,8 @@ bundle_id="$(
echo "missing bundle executable: ${app_path}/Contents/MacOS/${executable_name}" >&2
exit 1
}
+
+[[ -f "${app_path}/Contents/Resources/${icon_name}.icns" ]] || {
+ echo "missing bundle icon: ${app_path}/Contents/Resources/${icon_name}.icns" >&2
+ exit 1
+}