11 KiB
11 KiB
Build Files Template for music-assistant
Use this document as the prompt/instruction file for an agent when you create the
music-assistant Swift macOS app project.
The target project does not need to match the Servery path. These files should be
created in the root of the future music-assistant project, next to
Package.swift.
Agent Request
Copy this request into the agent working inside the new project:
Create the same build-command structure for this Swift macOS app.
App name:
music-assistant
Product name:
music-assistant
Bundle identifier:
com.music-assistant.app
Requirements:
1. Create `Makefile` with `build`, `dev`, and `test` commands.
2. Create `clean_rebuild.sh` for a clean release build, packaging, signing,
installing into `/Applications`, and launching the app.
3. Create `dev_rebuild.sh` for a fast incremental debug build, packaging,
installing into `/Applications`, and launching the app.
4. Assume these files live in the project root next to `Package.swift`.
5. Use the app icon at `Resources/music-assistant.icns`.
6. If the app has additional resources, copy them into
`Contents/Resources` during packaging.
7. Make both shell scripts executable.
8. Keep the implementation small and local. Do not refactor unrelated project
files.
9. After creating the files, verify that the scripts reference the correct app
name, product name, bundle identifier, icon path, and install path.
Makefile
Create this file as Makefile:
.PHONY: build dev test
build:
./clean_rebuild.sh
dev:
./dev_rebuild.sh
test:
swift test
dev_rebuild.sh
Create this file as dev_rebuild.sh:
#!/bin/zsh
# Fast development rebuild: incremental DEBUG build, repackage, relaunch.
#
# This skips `swift package clean` and release-mode optimizations, so it reuses
# the incremental build cache and finishes quickly. Use it while iterating.
set -euo pipefail
PROJECT_ROOT="$(cd "$(dirname "$0")" && pwd)"
APP_NAME="music-assistant"
PRODUCT_NAME="music-assistant"
APP_BUNDLE_NAME="${APP_NAME}.app"
BUILD_DIR="${PROJECT_ROOT}/.build"
APP_BUNDLE="${BUILD_DIR}/${APP_BUNDLE_NAME}"
INSTALL_PATH="/Applications/${APP_BUNDLE_NAME}"
CONTENTS_DIR="${APP_BUNDLE}/Contents"
MACOS_DIR="${CONTENTS_DIR}/MacOS"
RESOURCES_DIR="${CONTENTS_DIR}/Resources"
APP_ICON="${PROJECT_ROOT}/Resources/music-assistant.icns"
fail() {
print -u2 -- "Error: $1"
exit 1
}
step() {
print -- "==> $1"
}
[[ -f "${PROJECT_ROOT}/Package.swift" ]] || fail "Package.swift was not found in ${PROJECT_ROOT}."
[[ -f "${APP_ICON}" ]] || fail "App icon was not found at ${APP_ICON}."
command -v swift >/dev/null 2>&1 || fail "Swift is required. Install Xcode or the Xcode Command Line Tools."
command -v codesign >/dev/null 2>&1 || fail "codesign is required and should be available with Xcode."
cd "${PROJECT_ROOT}"
step "Stopping any running ${APP_NAME} application"
if pgrep -x "${PRODUCT_NAME}" >/dev/null 2>&1; then
pkill -x "${PRODUCT_NAME}" || fail "Could not stop the running ${APP_NAME} application."
for _ in {1..20}; do
pgrep -x "${PRODUCT_NAME}" >/dev/null 2>&1 || break
sleep 0.1
done
pgrep -x "${PRODUCT_NAME}" >/dev/null 2>&1 && fail "${APP_NAME} is still running. Quit it and retry."
fi
step "Building ${PRODUCT_NAME} in debug mode (incremental)"
swift build || fail "Debug build failed. Review the Swift compiler diagnostics above."
BIN_PATH="$(swift build --show-bin-path 2>/dev/null | tail -n1)"
SOURCE_EXECUTABLE="${BIN_PATH}/${PRODUCT_NAME}"
[[ -x "${SOURCE_EXECUTABLE}" ]] || fail "Built executable was not found at ${SOURCE_EXECUTABLE}."
step "Packaging ${APP_BUNDLE_NAME}"
rm -rf "${APP_BUNDLE}"
mkdir -p "${MACOS_DIR}" "${RESOURCES_DIR}"
cp "${SOURCE_EXECUTABLE}" "${MACOS_DIR}/${PRODUCT_NAME}"
cp "${APP_ICON}" "${RESOURCES_DIR}/music-assistant.icns"
cat > "${CONTENTS_DIR}/Info.plist" <<'PLIST'
<?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>CFBundleDisplayName</key>
<string>music-assistant</string>
<key>CFBundleExecutable</key>
<string>music-assistant</string>
<key>CFBundleIdentifier</key>
<string>com.music-assistant.app</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleIconFile</key>
<string>music-assistant</string>
<key>CFBundleName</key>
<string>music-assistant</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSMinimumSystemVersion</key>
<string>14.0</string>
<key>NSHighResolutionCapable</key>
<true/>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>
PLIST
plutil -lint "${CONTENTS_DIR}/Info.plist" >/dev/null || fail "Generated Info.plist is invalid."
codesign --force --sign - --timestamp=none "${APP_BUNDLE}" || fail "Ad-hoc signing of ${APP_BUNDLE_NAME} failed."
[[ -x "${MACOS_DIR}/${PRODUCT_NAME}" ]] || fail "Packaged executable is missing."
step "Installing ${APP_BUNDLE_NAME} in /Applications"
rm -rf "${INSTALL_PATH}"
ditto "${APP_BUNDLE}" "${INSTALL_PATH}" || fail "Could not install ${APP_BUNDLE_NAME} in /Applications. Check permissions and retry."
step "Launching ${APP_NAME}"
open -n "${INSTALL_PATH}" || fail "${APP_NAME} was installed but could not be opened."
print -- "==> ${APP_NAME} was rebuilt (debug), installed, and launched successfully."
clean_rebuild.sh
Create this file as clean_rebuild.sh:
#!/bin/zsh
# Build, package, install, and launch the music-assistant macOS application.
set -euo pipefail
PROJECT_ROOT="$(cd "$(dirname "$0")" && pwd)"
APP_NAME="music-assistant"
PRODUCT_NAME="music-assistant"
APP_BUNDLE_NAME="${APP_NAME}.app"
BUILD_DIR="${PROJECT_ROOT}/.build"
APP_BUNDLE="${BUILD_DIR}/${APP_BUNDLE_NAME}"
INSTALL_PATH="/Applications/${APP_BUNDLE_NAME}"
CONTENTS_DIR="${APP_BUNDLE}/Contents"
MACOS_DIR="${CONTENTS_DIR}/MacOS"
RESOURCES_DIR="${CONTENTS_DIR}/Resources"
APP_ICON="${PROJECT_ROOT}/Resources/music-assistant.icns"
fail() {
print -u2 -- "Error: $1"
exit 1
}
step() {
print -- "==> $1"
}
[[ -f "${PROJECT_ROOT}/Package.swift" ]] || fail "Package.swift was not found in ${PROJECT_ROOT}."
[[ -f "${APP_ICON}" ]] || fail "App icon was not found at ${APP_ICON}."
command -v swift >/dev/null 2>&1 || fail "Swift is required. Install Xcode or the Xcode Command Line Tools."
command -v codesign >/dev/null 2>&1 || fail "codesign is required and should be available with Xcode."
cd "${PROJECT_ROOT}"
step "Stopping any running ${APP_NAME} application"
if pgrep -x "${PRODUCT_NAME}" >/dev/null 2>&1; then
pkill -x "${PRODUCT_NAME}" || fail "Could not stop the running ${APP_NAME} application."
for _ in {1..20}; do
pgrep -x "${PRODUCT_NAME}" >/dev/null 2>&1 || break
sleep 0.1
done
pgrep -x "${PRODUCT_NAME}" >/dev/null 2>&1 && fail "${APP_NAME} is still running. Quit it and retry."
fi
step "Removing stale installed copy"
if [[ -e "${INSTALL_PATH}" ]]; then
rm -rf "${INSTALL_PATH}" || fail "Could not remove ${INSTALL_PATH}. Check permissions and retry."
fi
step "Cleaning local Swift build artifacts"
swift package clean || fail "Swift Package Manager could not clean the local build artifacts."
step "Building ${PRODUCT_NAME} in release mode"
BIN_PATH="$(swift build -c release --show-bin-path 2>/dev/null | tail -n1)"
SOURCE_EXECUTABLE="${BIN_PATH}/${PRODUCT_NAME}"
built=0
for attempt in 1 2 3; do
swift build -c release || fail "Release build failed. Review the Swift compiler diagnostics above."
if [[ -x "${SOURCE_EXECUTABLE}" ]]; then built=1; break; fi
print -- "==> Executable not present after build (attempt ${attempt}); retrying"
sleep 1
done
[[ "${built}" -eq 1 ]] || fail "Built executable was not found at ${SOURCE_EXECUTABLE}."
step "Packaging ${APP_BUNDLE_NAME}"
rm -rf "${APP_BUNDLE}"
mkdir -p "${MACOS_DIR}" "${RESOURCES_DIR}"
cp "${SOURCE_EXECUTABLE}" "${MACOS_DIR}/${PRODUCT_NAME}"
cp "${APP_ICON}" "${RESOURCES_DIR}/music-assistant.icns"
cat > "${CONTENTS_DIR}/Info.plist" <<'PLIST'
<?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>CFBundleDisplayName</key>
<string>music-assistant</string>
<key>CFBundleExecutable</key>
<string>music-assistant</string>
<key>CFBundleIdentifier</key>
<string>com.music-assistant.app</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleIconFile</key>
<string>music-assistant</string>
<key>CFBundleName</key>
<string>music-assistant</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSMinimumSystemVersion</key>
<string>14.0</string>
<key>NSHighResolutionCapable</key>
<true/>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>
PLIST
plutil -lint "${CONTENTS_DIR}/Info.plist" >/dev/null || fail "Generated Info.plist is invalid."
codesign --force --sign - --timestamp=none "${APP_BUNDLE}" || fail "Ad-hoc signing of ${APP_BUNDLE_NAME} failed."
codesign --verify --deep --strict "${APP_BUNDLE}" || fail "Packaged ${APP_BUNDLE_NAME} failed code-signature verification."
[[ -x "${MACOS_DIR}/${PRODUCT_NAME}" ]] || fail "Packaged executable is missing."
step "Installing ${APP_BUNDLE_NAME} in /Applications"
ditto "${APP_BUNDLE}" "${INSTALL_PATH}" || fail "Could not install ${APP_BUNDLE_NAME} in /Applications. Check permissions and retry."
INSTALLED_EXECUTABLE="${INSTALL_PATH}/Contents/MacOS/${PRODUCT_NAME}"
[[ -x "${INSTALLED_EXECUTABLE}" ]] || fail "Installed executable is missing at ${INSTALLED_EXECUTABLE}."
SOURCE_HASH="$(shasum -a 256 "${MACOS_DIR}/${PRODUCT_NAME}" | awk '{print $1}')"
INSTALLED_HASH="$(shasum -a 256 "${INSTALLED_EXECUTABLE}" | awk '{print $1}')"
[[ "${SOURCE_HASH}" == "${INSTALLED_HASH}" ]] || fail "Installed executable does not match the newly built executable."
step "Launching ${APP_NAME}"
open -n "${INSTALL_PATH}" || fail "${APP_NAME} was installed but could not be opened."
print -- "==> ${APP_NAME} was rebuilt, installed, and launched successfully."
Required Terminal Step
After the files are created in the new project, run:
chmod +x clean_rebuild.sh dev_rebuild.sh
Then use:
make dev
make build
make test
Notes
- The future project must have
Package.swift. - The future project must have an icon at
Resources/music-assistant.icns. - If the executable product name in
Package.swiftis different, changePRODUCT_NAMEin both scripts. - If the app needs permissions, add the matching usage-description keys to the
generated
Info.plist.