#!/usr/bin/env bash set -euo pipefail ts() { date +"%H:%M:%S"; } lower() { echo "$1" | tr '[:upper:]' '[:lower:]'; } script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" repo_root="$(cd -- "${script_dir}/../.." && pwd)" usage() { cat <<'EOF' Usage: ./build/macos/build_app.sh [--debug|--release] [--deploy] [--dmg] [--clean] [--build-dir ] What it does: - Configures and builds Strawberry with CMake + Ninja - Optional: runs CMake targets 'deploy' (bundle deps) and 'dmg' (create DMG) Options: --release Release build (default) --debug Debug build --deploy Run: cmake --build --target deploy --dmg Run: cmake --build --target dmg (implies --deploy) --clean Delete the build dir before configuring --build-dir Override build directory (default: /cmake-build-macos-) -h, --help Show help EOF } config="Release" do_deploy=0 do_dmg=0 do_clean=0 build_dir="" while [[ $# -gt 0 ]]; do case "$1" in --release) config="Release"; shift ;; --debug) config="Debug"; shift ;; --deploy) do_deploy=1; shift ;; --dmg) do_dmg=1; do_deploy=1; shift ;; --clean) do_clean=1; shift ;; --build-dir) build_dir="${2:-}"; shift 2 ;; -h|--help) usage; exit 0 ;; *) echo "Unknown arg: $1" >&2; usage; exit 2 ;; esac done if [[ "$(uname -s)" != "Darwin" ]]; then echo "Error: This script is for macOS only." >&2 exit 1 fi if ! command -v xcode-select >/dev/null 2>&1 || ! xcode-select -p >/dev/null 2>&1; then echo "Error: Xcode Command Line Tools not found." >&2 echo "Install them first: xcode-select --install" >&2 exit 1 fi if ! command -v brew >/dev/null 2>&1; then echo "Error: Homebrew ('brew') not found in PATH." >&2 echo "Install Homebrew first: https://brew.sh/" >&2 exit 1 fi if ! command -v cmake >/dev/null 2>&1; then echo "Error: cmake not found. Did you run ./build/macos/install_brew_deps.sh ?" >&2 exit 1 fi if ! command -v ninja >/dev/null 2>&1; then echo "Error: ninja not found. Did you run ./build/macos/install_brew_deps.sh ?" >&2 exit 1 fi brew_prefix="$(brew --prefix)" qt_prefix="$(brew --prefix qt)" icu_prefix="$(brew --prefix icu4c || true)" if [[ -z "$build_dir" ]]; then build_dir="${repo_root}/cmake-build-macos-$(lower "$config")" fi echo "==> [$(ts)] Repo: ${repo_root}" echo "==> [$(ts)] Build dir: ${build_dir}" echo "==> [$(ts)] Config: ${config}" if [[ "$do_clean" -eq 1 ]]; then echo "==> [$(ts)] Cleaning build dir" rm -rf "$build_dir" fi mkdir -p "$build_dir" # Make pkg-config more reliable with Homebrew. export PKG_CONFIG_PATH="${brew_prefix}/lib/pkgconfig:${brew_prefix}/share/pkgconfig:${PKG_CONFIG_PATH:-}" # For dist/CMakeLists.txt Info.plist minimum version logic. export MACOSX_DEPLOYMENT_TARGET="${MACOSX_DEPLOYMENT_TARGET:-12.0}" cmake_prefix_path="${qt_prefix};${brew_prefix}" echo "==> [$(ts)] Configuring (CMAKE_PREFIX_PATH=${cmake_prefix_path})" cmake_extra_args=() # Optional: override Sparkle update feed / key for your own published builds. # Example: # export SPARKLE_FEED_URL="https://example.com/appcast.xml" # export SPARKLE_PUBLIC_ED25519_KEY="base64==" if [[ -n "${SPARKLE_FEED_URL:-}" ]]; then cmake_extra_args+=("-DSPARKLE_FEED_URL=${SPARKLE_FEED_URL}") fi if [[ -n "${SPARKLE_PUBLIC_ED25519_KEY:-}" ]]; then cmake_extra_args+=("-DSPARKLE_PUBLIC_ED25519_KEY=${SPARKLE_PUBLIC_ED25519_KEY}") fi cmake -S "$repo_root" -B "$build_dir" -G Ninja \ -DCMAKE_BUILD_TYPE="$config" \ -DCMAKE_PREFIX_PATH="$cmake_prefix_path" \ -DCMAKE_FRAMEWORK_PATH="${brew_prefix}/Frameworks;${brew_prefix}/opt/sparkle-framework/Frameworks" \ -DOPTIONAL_COMPONENTS_MISSING_DEPS_ARE_FATAL=OFF \ ${cmake_extra_args+"${cmake_extra_args[@]}"} \ ${icu_prefix:+-DICU_ROOT="$icu_prefix"} echo "==> [$(ts)] Building" cmake --build "$build_dir" --parallel if [[ "$do_deploy" -eq 1 ]]; then echo "==> [$(ts)] Preparing env for 'deploy' target (GIO/GStreamer)" export GIO_EXTRA_MODULES="${brew_prefix}/lib/gio/modules" export GST_PLUGIN_SCANNER="${brew_prefix}/opt/gstreamer/libexec/gstreamer-1.0/gst-plugin-scanner" export GST_PLUGIN_PATH="${brew_prefix}/lib/gstreamer-1.0" # Optional, but helps dist/macos/macgstcopy.sh bundle libsoup which GStreamer loads dynamically. libsoup_prefix="$(brew --prefix libsoup 2>/dev/null || true)" if [[ -n "${libsoup_prefix}" ]]; then libsoup_dylib="$(ls -1 "${libsoup_prefix}"/lib/libsoup-*.dylib 2>/dev/null | head -n 1 || true)" if [[ -n "${libsoup_dylib}" ]]; then export LIBSOUP_LIBRARY_PATH="${libsoup_dylib}" fi fi echo "==> [$(ts)] Running: deploy" cmake --build "$build_dir" --target deploy fi if [[ "$do_dmg" -eq 1 ]]; then echo "==> [$(ts)] Running: dmg" cmake --build "$build_dir" --target dmg fi echo "==> [$(ts)] Done" echo "Built app:" echo " ${build_dir}/strawberry.app"