# 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: ```text 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`: ```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`: ```zsh #!/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' CFBundleDevelopmentRegion en CFBundleDisplayName music-assistant CFBundleExecutable music-assistant CFBundleIdentifier com.music-assistant.app CFBundleInfoDictionaryVersion 6.0 CFBundleIconFile music-assistant CFBundleName music-assistant CFBundlePackageType APPL CFBundleShortVersionString 1.0 CFBundleVersion 1 LSMinimumSystemVersion 14.0 NSHighResolutionCapable NSPrincipalClass NSApplication 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`: ```zsh #!/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' CFBundleDevelopmentRegion en CFBundleDisplayName music-assistant CFBundleExecutable music-assistant CFBundleIdentifier com.music-assistant.app CFBundleInfoDictionaryVersion 6.0 CFBundleIconFile music-assistant CFBundleName music-assistant CFBundlePackageType APPL CFBundleShortVersionString 1.0 CFBundleVersion 1 LSMinimumSystemVersion 14.0 NSHighResolutionCapable NSPrincipalClass NSApplication 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: ```bash chmod +x clean_rebuild.sh dev_rebuild.sh ``` Then use: ```bash 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.swift` is different, change `PRODUCT_NAME` in both scripts. - If the app needs permissions, add the matching usage-description keys to the generated `Info.plist`.