Some checks failed
Linux Build / Linux cpu (push) Has been cancelled
Linux Build / Linux cpu-clang (push) Has been cancelled
Linux Build / Linux vulkan (push) Has been cancelled
mac-build / macOS CPU (push) Has been cancelled
Nix Build / Nix (cpu) (push) Has been cancelled
Nix Build / Nix (vulkan) (push) Has been cancelled
windows-build / Windows CPU (push) Has been cancelled
329 lines
9.6 KiB
Bash
Executable file
329 lines
9.6 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
|
|
BUILD_DIR=""
|
|
BUILD_TYPE="RelWithDebInfo"
|
|
WITH_TESTS="OFF"
|
|
WITH_EXAMPLES="OFF"
|
|
WITH_WARMBENCH="OFF"
|
|
AUDIOCPP_DEPLOYMENT_BUILD="OFF"
|
|
AUDIOCPP_BUILD_NATIVE_MODEL_MANAGER="OFF"
|
|
AUDIOCPP_USE_SYSTEM_OPENSSL="OFF"
|
|
AUDIOCPP_BORINGSSL_ARCHIVE=""
|
|
AUDIOCPP_MODEL_SET="full"
|
|
AUDIOCPP_MODELS=""
|
|
OPENMP_MODE="off"
|
|
LLAMAFILE="ON"
|
|
NATIVE_CPU="ON"
|
|
METAL_EMBED_LIBRARY="ON"
|
|
DEPLOYMENT_TARGET=""
|
|
ARCHS=""
|
|
TARGETS=()
|
|
JOBS="$(sysctl -n hw.logicalcpu 2>/dev/null || echo 8)"
|
|
|
|
usage() {
|
|
cat <<'EOF'
|
|
Usage: scripts/build_metal.sh [options]
|
|
|
|
Build audio.cpp on macOS with the ggml Metal backend enabled.
|
|
|
|
Options:
|
|
--build-dir <path> CMake build directory.
|
|
Default: build/macos-metal-<build-type>
|
|
--build-type <type> CMake build type.
|
|
Default: RelWithDebInfo
|
|
--deployment-target <v> Minimum macOS deployment target.
|
|
--archs "<list>" Space or comma separated macOS architectures.
|
|
Default: CMake/native default
|
|
--openmp ON|OFF|auto Enable OpenMP host parallelism.
|
|
Default: OFF
|
|
--llamafile ON|OFF Enable ggml llamafile SGEMM.
|
|
Default: ON
|
|
--native-cpu ON|OFF Build ggml CPU kernels with native host ISA flags.
|
|
Default: ON
|
|
--embed-metal ON|OFF Embed ggml Metal shader library.
|
|
Default: ON
|
|
--with-tests Build framework unit tests.
|
|
--with-examples Build example binaries.
|
|
--with-warmbench Build warmbench helper binaries.
|
|
--deployment-build Embed package specs for standalone GGUF/model loading.
|
|
--native-model-manager Build native model manager and managed WebUI downloads.
|
|
--system-openssl Use system OpenSSL for native model management.
|
|
--boringssl-archive <p> Use a local BoringSSL source archive for native model
|
|
management instead of downloading at configure time.
|
|
--model-set full|core|custom
|
|
Model composite to build.
|
|
Default: full
|
|
--models "<list>" Comma or semicolon separated model targets when
|
|
--model-set custom is used.
|
|
--target <name> Build a specific CMake target. May be repeated.
|
|
-j, --jobs <n> Parallel build jobs.
|
|
-h, --help Show this help.
|
|
|
|
Examples:
|
|
scripts/build_metal.sh
|
|
scripts/build_metal.sh --target audiocpp_cli
|
|
scripts/build_metal.sh --build-type Release --archs arm64
|
|
EOF
|
|
}
|
|
|
|
normalize_on_off() {
|
|
local name="$1"
|
|
local value="$2"
|
|
case "$value" in
|
|
ON|on|On|1|true|TRUE|yes|YES)
|
|
printf 'ON'
|
|
;;
|
|
OFF|off|Off|0|false|FALSE|no|NO)
|
|
printf 'OFF'
|
|
;;
|
|
*)
|
|
echo "$name must be ON or OFF" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--build-dir)
|
|
BUILD_DIR="$2"
|
|
shift 2
|
|
;;
|
|
--build-type)
|
|
BUILD_TYPE="$2"
|
|
shift 2
|
|
;;
|
|
--deployment-target)
|
|
DEPLOYMENT_TARGET="$2"
|
|
shift 2
|
|
;;
|
|
--archs)
|
|
ARCHS="$2"
|
|
shift 2
|
|
;;
|
|
--openmp)
|
|
OPENMP_MODE="$2"
|
|
shift 2
|
|
;;
|
|
--llamafile)
|
|
LLAMAFILE="$(normalize_on_off --llamafile "$2")"
|
|
shift 2
|
|
;;
|
|
--native-cpu)
|
|
NATIVE_CPU="$(normalize_on_off --native-cpu "$2")"
|
|
shift 2
|
|
;;
|
|
--embed-metal)
|
|
METAL_EMBED_LIBRARY="$(normalize_on_off --embed-metal "$2")"
|
|
shift 2
|
|
;;
|
|
--with-tests)
|
|
WITH_TESTS="ON"
|
|
shift
|
|
;;
|
|
--with-examples)
|
|
WITH_EXAMPLES="ON"
|
|
shift
|
|
;;
|
|
--with-warmbench)
|
|
WITH_WARMBENCH="ON"
|
|
shift
|
|
;;
|
|
--deployment-build)
|
|
AUDIOCPP_DEPLOYMENT_BUILD="ON"
|
|
shift
|
|
;;
|
|
--native-model-manager)
|
|
AUDIOCPP_BUILD_NATIVE_MODEL_MANAGER="ON"
|
|
shift
|
|
;;
|
|
--system-openssl)
|
|
AUDIOCPP_USE_SYSTEM_OPENSSL="ON"
|
|
shift
|
|
;;
|
|
--boringssl-archive)
|
|
AUDIOCPP_BORINGSSL_ARCHIVE="$2"
|
|
shift 2
|
|
;;
|
|
--model-set)
|
|
case "$2" in
|
|
full|core|custom)
|
|
AUDIOCPP_MODEL_SET="$2"
|
|
;;
|
|
*)
|
|
echo "--model-set must be full, core, or custom" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
shift 2
|
|
;;
|
|
--models)
|
|
AUDIOCPP_MODELS="$2"
|
|
shift 2
|
|
;;
|
|
--target)
|
|
TARGETS+=("$2")
|
|
shift 2
|
|
;;
|
|
-j|--jobs)
|
|
JOBS="$2"
|
|
shift 2
|
|
;;
|
|
-h|--help)
|
|
usage
|
|
exit 0
|
|
;;
|
|
*)
|
|
echo "Unknown argument: $1" >&2
|
|
usage >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
if [[ "$AUDIOCPP_BUILD_NATIVE_MODEL_MANAGER" != "ON" ]]; then
|
|
if [[ "$AUDIOCPP_USE_SYSTEM_OPENSSL" == "ON" ]]; then
|
|
echo "--system-openssl requires --native-model-manager" >&2
|
|
exit 1
|
|
fi
|
|
if [[ -n "$AUDIOCPP_BORINGSSL_ARCHIVE" ]]; then
|
|
echo "--boringssl-archive requires --native-model-manager" >&2
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
if [[ "$(uname -s)" != "Darwin" ]]; then
|
|
echo "audio.cpp Metal builds require macOS." >&2
|
|
exit 1
|
|
fi
|
|
|
|
for tool in cmake xcrun; do
|
|
if ! command -v "$tool" >/dev/null 2>&1; then
|
|
echo "Required tool not found on PATH: $tool" >&2
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
if ! xcrun --sdk macosx --find metal >/dev/null 2>&1; then
|
|
echo "Xcode Metal toolchain was not found. Install Xcode or the Command Line Tools." >&2
|
|
exit 1
|
|
fi
|
|
|
|
case "$OPENMP_MODE" in
|
|
ON|on|On)
|
|
ENGINE_ENABLE_OPENMP="ON"
|
|
;;
|
|
OFF|off|Off)
|
|
ENGINE_ENABLE_OPENMP="OFF"
|
|
;;
|
|
auto)
|
|
ENGINE_ENABLE_OPENMP="OFF"
|
|
if command -v brew >/dev/null 2>&1; then
|
|
LIBOMP_PREFIX="$(brew --prefix libomp 2>/dev/null || true)"
|
|
if [[ -n "$LIBOMP_PREFIX" && -d "$LIBOMP_PREFIX" ]]; then
|
|
ENGINE_ENABLE_OPENMP="ON"
|
|
fi
|
|
fi
|
|
;;
|
|
*)
|
|
echo "--openmp must be ON, OFF, or auto" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
BUILD_TYPE_NAME="$(printf '%s' "$BUILD_TYPE" | tr '[:upper:]' '[:lower:]')"
|
|
if [[ "$BUILD_TYPE_NAME" == "relwithdebinfo" ]]; then
|
|
BUILD_TYPE_NAME="release"
|
|
fi
|
|
|
|
if [[ -z "$BUILD_DIR" ]]; then
|
|
BUILD_DIR="$REPO_ROOT/build/macos-metal-${BUILD_TYPE_NAME}"
|
|
fi
|
|
|
|
GENERATOR=""
|
|
if command -v ninja >/dev/null 2>&1; then
|
|
GENERATOR="Ninja"
|
|
fi
|
|
|
|
CMAKE_CMD=(
|
|
cmake
|
|
-S "$REPO_ROOT"
|
|
-B "$BUILD_DIR"
|
|
-DCMAKE_BUILD_TYPE="$BUILD_TYPE"
|
|
-DENGINE_ENABLE_CUDA=OFF
|
|
-DENGINE_ENABLE_VULKAN=OFF
|
|
-DENGINE_ENABLE_METAL=ON
|
|
-DENGINE_ENABLE_OPENMP="$ENGINE_ENABLE_OPENMP"
|
|
-DENGINE_ENABLE_LLAMAFILE="$LLAMAFILE"
|
|
-DENGINE_ENABLE_NATIVE_CPU="$NATIVE_CPU"
|
|
-DGGML_OPENMP="$ENGINE_ENABLE_OPENMP"
|
|
-DGGML_METAL_EMBED_LIBRARY="$METAL_EMBED_LIBRARY"
|
|
-DENGINE_BUILD_TESTS="$WITH_TESTS"
|
|
-DENGINE_BUILD_EXAMPLES="$WITH_EXAMPLES"
|
|
-DENGINE_BUILD_WARMBENCH="$WITH_WARMBENCH"
|
|
-DAUDIOCPP_DEPLOYMENT_BUILD="$AUDIOCPP_DEPLOYMENT_BUILD"
|
|
-DAUDIOCPP_BUILD_NATIVE_MODEL_MANAGER="$AUDIOCPP_BUILD_NATIVE_MODEL_MANAGER"
|
|
-DAUDIOCPP_USE_SYSTEM_OPENSSL="$AUDIOCPP_USE_SYSTEM_OPENSSL"
|
|
-UAUDIOCPP_BORINGSSL_ARCHIVE
|
|
-DAUDIOCPP_MODEL_SET="$AUDIOCPP_MODEL_SET"
|
|
-DAUDIOCPP_MODELS="$AUDIOCPP_MODELS"
|
|
)
|
|
if [[ -n "$AUDIOCPP_BORINGSSL_ARCHIVE" ]]; then
|
|
CMAKE_CMD+=(-DAUDIOCPP_BORINGSSL_ARCHIVE="$AUDIOCPP_BORINGSSL_ARCHIVE")
|
|
fi
|
|
|
|
if [[ -n "$GENERATOR" ]]; then
|
|
CMAKE_CMD+=(-G "$GENERATOR")
|
|
fi
|
|
if [[ -n "$DEPLOYMENT_TARGET" ]]; then
|
|
CMAKE_CMD+=(-DCMAKE_OSX_DEPLOYMENT_TARGET="$DEPLOYMENT_TARGET")
|
|
fi
|
|
if [[ -n "$ARCHS" ]]; then
|
|
CMAKE_CMD+=(-DCMAKE_OSX_ARCHITECTURES="${ARCHS//,/;}")
|
|
fi
|
|
if [[ "$OPENMP_MODE" == "auto" && "${ENGINE_ENABLE_OPENMP}" == "ON" ]]; then
|
|
CMAKE_CMD+=(-DOpenMP_ROOT="$LIBOMP_PREFIX")
|
|
fi
|
|
|
|
echo "Using source dir: $REPO_ROOT"
|
|
echo "Using build dir: $BUILD_DIR"
|
|
if [[ -n "$GENERATOR" ]]; then
|
|
echo "Using generator: $GENERATOR"
|
|
else
|
|
echo "Using generator: CMake default"
|
|
fi
|
|
echo "Including Metal backend: ON"
|
|
echo "Embedding Metal library: $METAL_EMBED_LIBRARY"
|
|
echo "Including OpenMP: $ENGINE_ENABLE_OPENMP"
|
|
echo "Including llamafile: $LLAMAFILE"
|
|
echo "Native CPU optimization: $NATIVE_CPU"
|
|
echo "Building examples: $WITH_EXAMPLES"
|
|
echo "Building tests: $WITH_TESTS"
|
|
echo "Building warmbench: $WITH_WARMBENCH"
|
|
echo "Deployment build: $AUDIOCPP_DEPLOYMENT_BUILD"
|
|
echo "Native model manager: $AUDIOCPP_BUILD_NATIVE_MODEL_MANAGER"
|
|
if [[ "$AUDIOCPP_BUILD_NATIVE_MODEL_MANAGER" == "ON" ]]; then
|
|
echo "System OpenSSL: $AUDIOCPP_USE_SYSTEM_OPENSSL"
|
|
echo "BoringSSL archive: ${AUDIOCPP_BORINGSSL_ARCHIVE:-<download at configure time>}"
|
|
fi
|
|
echo "Model composite: $AUDIOCPP_MODEL_SET"
|
|
if [[ -n "$AUDIOCPP_MODELS" ]]; then
|
|
echo "Selected models: $AUDIOCPP_MODELS"
|
|
fi
|
|
|
|
"${CMAKE_CMD[@]}"
|
|
|
|
BUILD_CMD=(cmake --build "$BUILD_DIR" --parallel "$JOBS")
|
|
# --target is optional, so TARGETS is usually empty. bash 3.2 (stock macOS
|
|
# /bin/bash) and bash < 4.4 report an empty array as unbound under `set -u`;
|
|
# the ${arr[@]+"${arr[@]}"} form expands to nothing instead of failing.
|
|
for target in ${TARGETS[@]+"${TARGETS[@]}"}; do
|
|
BUILD_CMD+=(--target "$target")
|
|
done
|
|
|
|
"${BUILD_CMD[@]}"
|