mirror of
https://github.com/ggml-org/llama.cpp.git
synced 2026-08-27 07:31:24 +02:00
27e345b574
* xcframework : fix build * mtmd : remove unused include path * vendor : use vendor::hash alias target in cmake CMake reserves "::" in target names for imported/alias targets, so the real target keeps the name vendor-hash and a vendor::hash ALIAS target is added. Consumers (mtmd, llama-gguf-hash) now link against the namespaced alias. Assisted-by: pi:llama.cpp/Qwen3.8-27B * vendor : add cmake targets for all vendored libs with vendor:: aliases Add INTERFACE targets for the header-only vendor libs (miniaudio, nlohmann, sheredom, stb) and ALIAS targets named vendor::<lib> for all of them, including cpp-httplib and hash. Each exposes the vendor/ root so includes are namespaced, e.g. <nlohmann/json.hpp>. Consolidate the per-lib add_subdirectory calls into a single add_subdirectory(vendor), keeping the cpp-httplib gate on LLAMA_BUILD_COMMON. Consumers (llama-common, mtmd) now link the aliases instead of relying on raw vendor/ include paths. hash: consumers now include via "hash/hash.h"; the vendor/hash dir is kept as a PRIVATE include so the synced upstream sources compile unmodified. Assisted-by: pi:llama.cpp/Qwen3.8-27B * readme : use foo/bar names in acknowledgements Assisted-by: pi:llama.cpp/Qwen3.8-27B * ocd : fix valign
631 lines
24 KiB
Bash
Executable File
631 lines
24 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
#
|
|
# usage: ./build-xcframework.sh [BUILD ...] (default: all builds)
|
|
# builds: ios-sim ios-device macos visionos visionos-sim tvos-sim tvos-device
|
|
#
|
|
# Options
|
|
IOS_MIN_OS_VERSION=16.4
|
|
MACOS_MIN_OS_VERSION=13.3
|
|
VISIONOS_MIN_OS_VERSION=1.0
|
|
TVOS_MIN_OS_VERSION=16.4
|
|
|
|
BUILD_SHARED_LIBS=OFF
|
|
LLAMA_BUILD_APP=OFF
|
|
LLAMA_BUILD_COMMON=OFF
|
|
LLAMA_BUILD_EXAMPLES=OFF
|
|
LLAMA_BUILD_TOOLS=OFF
|
|
LLAMA_BUILD_TESTS=OFF
|
|
LLAMA_BUILD_SERVER=OFF
|
|
LLAMA_BUILD_MTMD=ON
|
|
GGML_METAL=ON
|
|
GGML_METAL_EMBED_LIBRARY=ON
|
|
GGML_BLAS_DEFAULT=ON
|
|
GGML_OPENMP=OFF
|
|
|
|
# Max number of concurrent platform builds
|
|
MAX_PARALLEL_BUILDS=1
|
|
|
|
# Split the available cores between the concurrent builds (min 1)
|
|
JOBS_PER_BUILD=$(( $(sysctl -n hw.logicalcpu) / MAX_PARALLEL_BUILDS ))
|
|
if [[ "$JOBS_PER_BUILD" -lt 1 ]]; then
|
|
JOBS_PER_BUILD=1
|
|
fi
|
|
|
|
# echo "build_fn build_dir release_dir platform is_simulator min_os" for a build name
|
|
build_spec() {
|
|
case "$1" in
|
|
ios-sim) echo "build_ios_sim build-ios-sim Release-iphonesimulator ios true ${IOS_MIN_OS_VERSION}" ;;
|
|
ios-device) echo "build_ios_device build-ios-device Release-iphoneos ios false ${IOS_MIN_OS_VERSION}" ;;
|
|
macos) echo "build_macos build-macos Release macos false ${MACOS_MIN_OS_VERSION}" ;;
|
|
visionos) echo "build_visionos build-visionos Release-xros visionos false ${VISIONOS_MIN_OS_VERSION}" ;;
|
|
visionos-sim) echo "build_visionos_sim build-visionos-sim Release-xrsimulator visionos true ${VISIONOS_MIN_OS_VERSION}" ;;
|
|
tvos-sim) echo "build_tvos_sim build-tvos-sim Release-appletvsimulator tvos true ${TVOS_MIN_OS_VERSION}" ;;
|
|
tvos-device) echo "build_tvos_device build-tvos-device Release-appletvos tvos false ${TVOS_MIN_OS_VERSION}" ;;
|
|
*) return 1 ;;
|
|
esac
|
|
}
|
|
|
|
# Default: build everything
|
|
if [[ $# -eq 0 ]]; then
|
|
BUILDS=(ios-sim ios-device macos visionos visionos-sim tvos-sim tvos-device)
|
|
else
|
|
BUILDS=("$@")
|
|
fi
|
|
for b in "${BUILDS[@]}"; do
|
|
if ! build_spec "$b" >/dev/null; then
|
|
echo "Error: unknown build '$b'" >&2
|
|
echo "Valid builds: ios-sim ios-device macos visionos visionos-sim tvos-sim tvos-device" >&2
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
COMMON_C_FLAGS="-Wno-macro-redefined -Wno-shorten-64-to-32 -Wno-unused-command-line-argument -g"
|
|
COMMON_CXX_FLAGS="-Wno-macro-redefined -Wno-shorten-64-to-32 -Wno-unused-command-line-argument -g"
|
|
|
|
# Common options for all builds
|
|
COMMON_CMAKE_ARGS=(
|
|
-DCMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED=NO
|
|
-DCMAKE_XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY=""
|
|
-DCMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED=NO
|
|
-DCMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT="dwarf-with-dsym"
|
|
-DCMAKE_XCODE_ATTRIBUTE_GCC_GENERATE_DEBUGGING_SYMBOLS=YES
|
|
-DCMAKE_XCODE_ATTRIBUTE_COPY_PHASE_STRIP=NO
|
|
-DCMAKE_XCODE_ATTRIBUTE_STRIP_INSTALLED_PRODUCT=NO
|
|
-DCMAKE_XCODE_ATTRIBUTE_DEVELOPMENT_TEAM=ggml
|
|
-DBUILD_SHARED_LIBS=${BUILD_SHARED_LIBS}
|
|
-DLLAMA_BUILD_APP=${LLAMA_BUILD_APP}
|
|
-DLLAMA_BUILD_COMMON=${LLAMA_BUILD_COMMON}
|
|
-DLLAMA_BUILD_EXAMPLES=${LLAMA_BUILD_EXAMPLES}
|
|
-DLLAMA_BUILD_TOOLS=${LLAMA_BUILD_TOOLS}
|
|
-DLLAMA_BUILD_TESTS=${LLAMA_BUILD_TESTS}
|
|
-DLLAMA_BUILD_SERVER=${LLAMA_BUILD_SERVER}
|
|
-DLLAMA_BUILD_MTMD=${LLAMA_BUILD_MTMD}
|
|
-DGGML_METAL_EMBED_LIBRARY=${GGML_METAL_EMBED_LIBRARY}
|
|
-DGGML_BLAS_DEFAULT=${GGML_BLAS_DEFAULT}
|
|
-DGGML_METAL=${GGML_METAL}
|
|
-DGGML_NATIVE=OFF
|
|
-DGGML_OPENMP=${GGML_OPENMP}
|
|
)
|
|
|
|
check_required_tool() {
|
|
local tool=$1
|
|
local install_message=$2
|
|
|
|
if ! command -v $tool &> /dev/null; then
|
|
echo "Error: $tool is required but not found."
|
|
echo "$install_message"
|
|
exit 1
|
|
fi
|
|
}
|
|
echo "Checking for required tools..."
|
|
check_required_tool "cmake" "Please install CMake 3.28.0 or later (brew install cmake)"
|
|
check_required_tool "xcrun" "Please install Xcode and Xcode Command Line Tools (xcode-select --install)"
|
|
|
|
XCODE_VERSION=$(xcrun xcodebuild -version 2>/dev/null | head -n1 | awk '{ print $2 }')
|
|
MAJOR_VERSION=$(echo $XCODE_VERSION | cut -d. -f1)
|
|
MINOR_VERSION=$(echo $XCODE_VERSION | cut -d. -f2)
|
|
echo "Detected Xcode version: $XCODE_VERSION"
|
|
|
|
set -e
|
|
|
|
## Clean up previous builds
|
|
rm -rf build-apple
|
|
rm -rf build-ios-sim
|
|
rm -rf build-ios-device
|
|
rm -rf build-macos
|
|
rm -rf build-visionos
|
|
rm -rf build-visionos-sim
|
|
rm -rf build-tvos-sim
|
|
rm -rf build-tvos-device
|
|
|
|
# Setup the xcframework build directory structure
|
|
setup_framework_structure() {
|
|
local build_dir=$1
|
|
local min_os_version=$2
|
|
local platform=$3 # "ios", "macos", "visionos", or "tvos"
|
|
local framework_name="llama"
|
|
|
|
echo "Creating ${platform}-style framework structure for ${build_dir}"
|
|
|
|
if [[ "$platform" == "macos" ]]; then
|
|
# macOS versioned structure uses versioned directories
|
|
mkdir -p ${build_dir}/framework/${framework_name}.framework/Versions/A/Headers
|
|
mkdir -p ${build_dir}/framework/${framework_name}.framework/Versions/A/Modules
|
|
mkdir -p ${build_dir}/framework/${framework_name}.framework/Versions/A/Resources
|
|
|
|
# Create symbolic links
|
|
ln -sf A ${build_dir}/framework/${framework_name}.framework/Versions/Current
|
|
ln -sf Versions/Current/Headers ${build_dir}/framework/${framework_name}.framework/Headers
|
|
ln -sf Versions/Current/Modules ${build_dir}/framework/${framework_name}.framework/Modules
|
|
ln -sf Versions/Current/Resources ${build_dir}/framework/${framework_name}.framework/Resources
|
|
ln -sf Versions/Current/${framework_name} ${build_dir}/framework/${framework_name}.framework/${framework_name}
|
|
|
|
# Set header and module paths
|
|
local header_path=${build_dir}/framework/${framework_name}.framework/Versions/A/Headers/
|
|
local module_path=${build_dir}/framework/${framework_name}.framework/Versions/A/Modules/
|
|
else
|
|
# iOS/VisionOS/tvOS use a flat structure
|
|
mkdir -p ${build_dir}/framework/${framework_name}.framework/Headers
|
|
mkdir -p ${build_dir}/framework/${framework_name}.framework/Modules
|
|
|
|
# Remove any existing structure to ensure clean build
|
|
rm -rf ${build_dir}/framework/${framework_name}.framework/Versions
|
|
|
|
# Set header and module paths
|
|
local header_path=${build_dir}/framework/${framework_name}.framework/Headers/
|
|
local module_path=${build_dir}/framework/${framework_name}.framework/Modules/
|
|
fi
|
|
|
|
# Copy all required headers (common for all platforms)
|
|
cp include/llama.h ${header_path}
|
|
cp ggml/include/ggml.h ${header_path}
|
|
cp ggml/include/ggml-opt.h ${header_path}
|
|
cp ggml/include/ggml-alloc.h ${header_path}
|
|
cp ggml/include/ggml-backend.h ${header_path}
|
|
cp ggml/include/ggml-metal.h ${header_path}
|
|
cp ggml/include/ggml-cpu.h ${header_path}
|
|
cp ggml/include/ggml-blas.h ${header_path}
|
|
cp ggml/include/gguf.h ${header_path}
|
|
cp tools/mtmd/mtmd.h ${header_path}
|
|
cp tools/mtmd/mtmd-helper.h ${header_path}
|
|
|
|
# Create module map (common for all platforms)
|
|
cat > ${module_path}module.modulemap << EOF
|
|
framework module llama {
|
|
umbrella "Headers"
|
|
|
|
link "c++"
|
|
link framework "Accelerate"
|
|
link framework "Metal"
|
|
link framework "Foundation"
|
|
|
|
export *
|
|
}
|
|
EOF
|
|
|
|
# Platform-specific settings for Info.plist
|
|
local platform_name=""
|
|
local sdk_name=""
|
|
local supported_platform=""
|
|
|
|
case "$platform" in
|
|
"ios")
|
|
platform_name="iphoneos"
|
|
sdk_name="iphoneos${min_os_version}"
|
|
supported_platform="iPhoneOS"
|
|
local plist_path="${build_dir}/framework/${framework_name}.framework/Info.plist"
|
|
local device_family=' <key>UIDeviceFamily</key>
|
|
<array>
|
|
<integer>1</integer>
|
|
<integer>2</integer>
|
|
</array>'
|
|
;;
|
|
"macos")
|
|
platform_name="macosx"
|
|
sdk_name="macosx${min_os_version}"
|
|
supported_platform="MacOSX"
|
|
local plist_path="${build_dir}/framework/${framework_name}.framework/Versions/A/Resources/Info.plist"
|
|
local device_family=""
|
|
;;
|
|
"visionos")
|
|
platform_name="xros"
|
|
sdk_name="xros${min_os_version}"
|
|
supported_platform="XRPlatform"
|
|
local plist_path="${build_dir}/framework/${framework_name}.framework/Info.plist"
|
|
local device_family=""
|
|
;;
|
|
"tvos")
|
|
platform_name="appletvos"
|
|
sdk_name="appletvos${min_os_version}"
|
|
supported_platform="AppleTVOS"
|
|
local plist_path="${build_dir}/framework/${framework_name}.framework/Info.plist"
|
|
local device_family=' <key>UIDeviceFamily</key>
|
|
<array>
|
|
<integer>3</integer>
|
|
</array>'
|
|
;;
|
|
esac
|
|
|
|
# Create Info.plist
|
|
cat > ${plist_path} << EOF
|
|
<?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>CFBundleExecutable</key>
|
|
<string>llama</string>
|
|
<key>CFBundleIdentifier</key>
|
|
<string>org.ggml.llama</string>
|
|
<key>CFBundleInfoDictionaryVersion</key>
|
|
<string>6.0</string>
|
|
<key>CFBundleName</key>
|
|
<string>llama</string>
|
|
<key>CFBundlePackageType</key>
|
|
<string>FMWK</string>
|
|
<key>CFBundleShortVersionString</key>
|
|
<string>1.0</string>
|
|
<key>CFBundleVersion</key>
|
|
<string>1</string>
|
|
<key>MinimumOSVersion</key>
|
|
<string>${min_os_version}</string>
|
|
<key>CFBundleSupportedPlatforms</key>
|
|
<array>
|
|
<string>${supported_platform}</string>
|
|
</array>${device_family}
|
|
<key>DTPlatformName</key>
|
|
<string>${platform_name}</string>
|
|
<key>DTSDKName</key>
|
|
<string>${sdk_name}</string>
|
|
</dict>
|
|
</plist>
|
|
EOF
|
|
}
|
|
|
|
# Create dynamic libraries from static libraries.
|
|
combine_static_libraries() {
|
|
local build_dir="$1"
|
|
local release_dir="$2"
|
|
local platform="$3" # "ios", "macos", "visionos", or "tvos"
|
|
local is_simulator="$4"
|
|
local base_dir="$(pwd)"
|
|
local framework_name="llama"
|
|
|
|
# Determine output path based on platform
|
|
local output_lib=""
|
|
if [[ "$platform" == "macos" ]]; then
|
|
# macOS uses versioned structure
|
|
output_lib="${build_dir}/framework/${framework_name}.framework/Versions/A/${framework_name}"
|
|
else
|
|
# iOS, visionOS, and tvOS use a directory flat structure
|
|
output_lib="${build_dir}/framework/${framework_name}.framework/${framework_name}"
|
|
fi
|
|
|
|
local libs=(
|
|
"${base_dir}/${build_dir}/src/${release_dir}/libllama.a"
|
|
"${base_dir}/${build_dir}/ggml/src/${release_dir}/libggml.a"
|
|
"${base_dir}/${build_dir}/ggml/src/${release_dir}/libggml-base.a"
|
|
"${base_dir}/${build_dir}/ggml/src/${release_dir}/libggml-cpu.a"
|
|
"${base_dir}/${build_dir}/ggml/src/ggml-metal/${release_dir}/libggml-metal.a"
|
|
"${base_dir}/${build_dir}/ggml/src/ggml-blas/${release_dir}/libggml-blas.a"
|
|
"${base_dir}/${build_dir}/tools/mtmd/${release_dir}/libmtmd.a"
|
|
"${base_dir}/${build_dir}/vendor/hash/${release_dir}/libvendor-hash.a"
|
|
)
|
|
|
|
# Create temporary directory for processing
|
|
local temp_dir="${base_dir}/${build_dir}/temp"
|
|
mkdir -p "${temp_dir}"
|
|
|
|
# Since we have multiple architectures libtool will find object files that do not
|
|
# match the target architecture. We suppress these warnings.
|
|
xcrun libtool -static -o "${temp_dir}/combined.a" "${libs[@]}" 2> /dev/null
|
|
|
|
# Determine SDK, architectures, and install_name based on platform and simulator flag.
|
|
local sdk=""
|
|
local archs=""
|
|
local min_version_flag=""
|
|
local install_name=""
|
|
|
|
case "$platform" in
|
|
"ios")
|
|
if [[ "$is_simulator" == "true" ]]; then
|
|
sdk="iphonesimulator"
|
|
archs="arm64 x86_64"
|
|
min_version_flag="-mios-simulator-version-min=${IOS_MIN_OS_VERSION}"
|
|
else
|
|
sdk="iphoneos"
|
|
archs="arm64"
|
|
min_version_flag="-mios-version-min=${IOS_MIN_OS_VERSION}"
|
|
fi
|
|
install_name="@rpath/llama.framework/llama"
|
|
;;
|
|
"macos")
|
|
sdk="macosx"
|
|
archs="arm64 x86_64"
|
|
min_version_flag="-mmacosx-version-min=${MACOS_MIN_OS_VERSION}"
|
|
install_name="@rpath/llama.framework/Versions/Current/llama"
|
|
;;
|
|
"visionos")
|
|
if [[ "$is_simulator" == "true" ]]; then
|
|
sdk="xrsimulator"
|
|
archs="arm64 x86_64"
|
|
min_version_flag="-mtargetos=xros${VISIONOS_MIN_OS_VERSION}-simulator"
|
|
else
|
|
sdk="xros"
|
|
archs="arm64"
|
|
min_version_flag="-mtargetos=xros${VISIONOS_MIN_OS_VERSION}"
|
|
fi
|
|
# Use flat structure for visionOS, same as iOS
|
|
install_name="@rpath/llama.framework/llama"
|
|
;;
|
|
"tvos")
|
|
if [[ "$is_simulator" == "true" ]]; then
|
|
sdk="appletvsimulator"
|
|
archs="arm64 x86_64"
|
|
min_version_flag="-mtvos-simulator-version-min=${TVOS_MIN_OS_VERSION}"
|
|
else
|
|
sdk="appletvos"
|
|
archs="arm64"
|
|
min_version_flag="-mtvos-version-min=${TVOS_MIN_OS_VERSION}"
|
|
fi
|
|
install_name="@rpath/llama.framework/llama"
|
|
;;
|
|
esac
|
|
|
|
# Build architecture flags
|
|
local arch_flags=""
|
|
for arch in $archs; do
|
|
arch_flags+=" -arch $arch"
|
|
done
|
|
|
|
# Create dynamic library
|
|
echo "Creating dynamic library for ${platform}."
|
|
xcrun -sdk $sdk clang++ -dynamiclib \
|
|
-isysroot $(xcrun --sdk $sdk --show-sdk-path) \
|
|
$arch_flags \
|
|
$min_version_flag \
|
|
-Wl,-force_load,"${temp_dir}/combined.a" \
|
|
-framework Foundation -framework Metal -framework Accelerate \
|
|
-install_name "$install_name" \
|
|
-o "${base_dir}/${output_lib}"
|
|
|
|
# Platform-specific post-processing for device builds
|
|
if [[ "$is_simulator" == "false" ]]; then
|
|
if xcrun -f vtool &>/dev/null; then
|
|
case "$platform" in
|
|
"ios")
|
|
echo "Marking binary as a framework binary for iOS..."
|
|
xcrun vtool -set-build-version ios ${IOS_MIN_OS_VERSION} ${IOS_MIN_OS_VERSION} -replace \
|
|
-output "${base_dir}/${output_lib}" "${base_dir}/${output_lib}"
|
|
;;
|
|
"visionos")
|
|
echo "Marking binary as a framework binary for visionOS..."
|
|
if [[ "$MAJOR_VERSION" -gt 16 ]] || [[ "$MAJOR_VERSION" -eq 16 && "$MINOR_VERSION" -gt 2 ]]; then
|
|
echo "Xcode version greater than 16.2, using visionOS."
|
|
VISION_OS_BUILD_VERSION="visionos"
|
|
else
|
|
echo "Xcode version less than or equal to 16.2, using xros."
|
|
VISION_OS_BUILD_VERSION="xros"
|
|
fi
|
|
xcrun vtool -set-build-version ${VISION_OS_BUILD_VERSION} ${VISIONOS_MIN_OS_VERSION} ${VISIONOS_MIN_OS_VERSION} -replace \
|
|
-output "${base_dir}/${output_lib}" "${base_dir}/${output_lib}"
|
|
;;
|
|
"tvos")
|
|
echo "Marking binary as a framework binary for tvOS..."
|
|
xcrun vtool -set-build-version tvos ${TVOS_MIN_OS_VERSION} ${TVOS_MIN_OS_VERSION} -replace \
|
|
-output "${base_dir}/${output_lib}" "${base_dir}/${output_lib}"
|
|
;;
|
|
esac
|
|
else
|
|
echo "Warning: vtool not found. Binary may not pass App Store validation."
|
|
fi
|
|
fi
|
|
|
|
echo "Creating properly formatted dSYM..."
|
|
# Create a separate directory for dSYMs for all platforms
|
|
mkdir -p "${base_dir}/${build_dir}/dSYMs"
|
|
|
|
# iOS and visionOS style dSYM (flat structure)
|
|
if [[ "$platform" == "ios" || "$platform" == "visionos" || "$platform" == "tvos" ]]; then
|
|
# Generate dSYM in the dSYMs directory
|
|
xcrun dsymutil "${base_dir}/${output_lib}" -o "${base_dir}/${build_dir}/dSYMs/llama.dSYM"
|
|
|
|
# Create a copy of the binary that will be stripped
|
|
cp "${base_dir}/${output_lib}" "${temp_dir}/binary_to_strip"
|
|
|
|
# Strip debug symbols from the copy
|
|
xcrun strip -S "${temp_dir}/binary_to_strip" -o "${temp_dir}/stripped_lib"
|
|
|
|
# Replace the original with the stripped version
|
|
mv "${temp_dir}/stripped_lib" "${base_dir}/${output_lib}"
|
|
else
|
|
# macOS style dSYM
|
|
# First strip debug info to a separate file
|
|
xcrun strip -S "${base_dir}/${output_lib}" -o "${temp_dir}/stripped_lib"
|
|
|
|
# Generate dSYM in the dSYMs directory
|
|
xcrun dsymutil "${base_dir}/${output_lib}" -o "${base_dir}/${build_dir}/dSYMs/llama.dSYM"
|
|
|
|
# Replace original binary with stripped version
|
|
mv "${temp_dir}/stripped_lib" "${base_dir}/${output_lib}"
|
|
fi
|
|
|
|
# Remove any automatically generated dSYM files in the framework structure as they will
|
|
# otherwise case Invalid Bundle Structure validation errors.
|
|
if [ -d "${base_dir}/${output_lib}.dSYM" ]; then
|
|
echo "Removing generated dSYM file in framework structure: ${base_dir}/${output_lib}.dSYM"
|
|
rm -rf "${base_dir}/${output_lib}.dSYM"
|
|
fi
|
|
|
|
# Clean up
|
|
rm -rf "${temp_dir}"
|
|
}
|
|
|
|
build_ios_sim() {
|
|
echo "Building for iOS simulator..."
|
|
cmake -B build-ios-sim -G Xcode \
|
|
"${COMMON_CMAKE_ARGS[@]}" \
|
|
-DCMAKE_OSX_DEPLOYMENT_TARGET=${IOS_MIN_OS_VERSION} \
|
|
-DIOS=ON \
|
|
-DCMAKE_SYSTEM_NAME=iOS \
|
|
-DCMAKE_OSX_SYSROOT=iphonesimulator \
|
|
-DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" \
|
|
-DCMAKE_XCODE_ATTRIBUTE_SUPPORTED_PLATFORMS=iphonesimulator \
|
|
-DCMAKE_C_FLAGS="${COMMON_C_FLAGS}" \
|
|
-DCMAKE_CXX_FLAGS="${COMMON_CXX_FLAGS}" \
|
|
-DLLAMA_OPENSSL=OFF \
|
|
-DMTMD_VIDEO=OFF \
|
|
-S .
|
|
cmake --build build-ios-sim --config Release -j "${JOBS_PER_BUILD}" -- -quiet
|
|
}
|
|
|
|
build_ios_device() {
|
|
echo "Building for iOS devices..."
|
|
cmake -B build-ios-device -G Xcode \
|
|
"${COMMON_CMAKE_ARGS[@]}" \
|
|
-DCMAKE_OSX_DEPLOYMENT_TARGET=${IOS_MIN_OS_VERSION} \
|
|
-DCMAKE_SYSTEM_NAME=iOS \
|
|
-DCMAKE_OSX_SYSROOT=iphoneos \
|
|
-DCMAKE_OSX_ARCHITECTURES="arm64" \
|
|
-DCMAKE_XCODE_ATTRIBUTE_SUPPORTED_PLATFORMS=iphoneos \
|
|
-DCMAKE_C_FLAGS="${COMMON_C_FLAGS}" \
|
|
-DCMAKE_CXX_FLAGS="${COMMON_CXX_FLAGS}" \
|
|
-DLLAMA_OPENSSL=OFF \
|
|
-DMTMD_VIDEO=OFF \
|
|
-S .
|
|
cmake --build build-ios-device --config Release -j "${JOBS_PER_BUILD}" -- -quiet
|
|
}
|
|
|
|
build_macos() {
|
|
echo "Building for macOS..."
|
|
cmake -B build-macos -G Xcode \
|
|
"${COMMON_CMAKE_ARGS[@]}" \
|
|
-DCMAKE_OSX_DEPLOYMENT_TARGET=${MACOS_MIN_OS_VERSION} \
|
|
-DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" \
|
|
-DCMAKE_C_FLAGS="${COMMON_C_FLAGS}" \
|
|
-DCMAKE_CXX_FLAGS="${COMMON_CXX_FLAGS}" \
|
|
-DLLAMA_OPENSSL=OFF \
|
|
-S .
|
|
cmake --build build-macos --config Release -j "${JOBS_PER_BUILD}" -- -quiet
|
|
}
|
|
|
|
build_visionos() {
|
|
echo "Building for visionOS..."
|
|
cmake -B build-visionos -G Xcode \
|
|
"${COMMON_CMAKE_ARGS[@]}" \
|
|
-DCMAKE_OSX_DEPLOYMENT_TARGET=${VISIONOS_MIN_OS_VERSION} \
|
|
-DCMAKE_OSX_ARCHITECTURES="arm64" \
|
|
-DCMAKE_SYSTEM_NAME=visionOS \
|
|
-DCMAKE_OSX_SYSROOT=xros \
|
|
-DCMAKE_XCODE_ATTRIBUTE_SUPPORTED_PLATFORMS=xros \
|
|
-DCMAKE_C_FLAGS="${COMMON_C_FLAGS}" \
|
|
-DCMAKE_CXX_FLAGS="${COMMON_CXX_FLAGS}" \
|
|
-DLLAMA_OPENSSL=OFF \
|
|
-DLLAMA_BUILD_SERVER=OFF \
|
|
-DMTMD_VIDEO=OFF \
|
|
-S .
|
|
cmake --build build-visionos --config Release -j "${JOBS_PER_BUILD}" -- -quiet
|
|
}
|
|
|
|
build_visionos_sim() {
|
|
echo "Building for visionOS simulator..."
|
|
cmake -B build-visionos-sim -G Xcode \
|
|
"${COMMON_CMAKE_ARGS[@]}" \
|
|
-DCMAKE_OSX_DEPLOYMENT_TARGET=${VISIONOS_MIN_OS_VERSION} \
|
|
-DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" \
|
|
-DCMAKE_SYSTEM_NAME=visionOS \
|
|
-DCMAKE_OSX_SYSROOT=xrsimulator \
|
|
-DCMAKE_XCODE_ATTRIBUTE_SUPPORTED_PLATFORMS=xrsimulator \
|
|
-DCMAKE_C_FLAGS="${COMMON_C_FLAGS}" \
|
|
-DCMAKE_CXX_FLAGS="${COMMON_CXX_FLAGS}" \
|
|
-DLLAMA_OPENSSL=OFF \
|
|
-DLLAMA_BUILD_SERVER=OFF \
|
|
-DMTMD_VIDEO=OFF \
|
|
-S .
|
|
cmake --build build-visionos-sim --config Release -j "${JOBS_PER_BUILD}" -- -quiet
|
|
}
|
|
|
|
# Add tvOS builds (might need the same u_int definitions as watchOS and visionOS)
|
|
build_tvos_sim() {
|
|
echo "Building for tvOS simulator..."
|
|
cmake -B build-tvos-sim -G Xcode \
|
|
"${COMMON_CMAKE_ARGS[@]}" \
|
|
-DCMAKE_OSX_DEPLOYMENT_TARGET=${TVOS_MIN_OS_VERSION} \
|
|
-DCMAKE_SYSTEM_NAME=tvOS \
|
|
-DCMAKE_OSX_SYSROOT=appletvsimulator \
|
|
-DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" \
|
|
-DGGML_METAL=ON \
|
|
-DCMAKE_XCODE_ATTRIBUTE_SUPPORTED_PLATFORMS=appletvsimulator \
|
|
-DCMAKE_C_FLAGS="${COMMON_C_FLAGS}" \
|
|
-DCMAKE_CXX_FLAGS="${COMMON_CXX_FLAGS}" \
|
|
-DLLAMA_OPENSSL=OFF \
|
|
-DMTMD_VIDEO=OFF \
|
|
-S .
|
|
cmake --build build-tvos-sim --config Release -j "${JOBS_PER_BUILD}" -- -quiet
|
|
}
|
|
|
|
build_tvos_device() {
|
|
echo "Building for tvOS devices..."
|
|
cmake -B build-tvos-device -G Xcode \
|
|
"${COMMON_CMAKE_ARGS[@]}" \
|
|
-DCMAKE_OSX_DEPLOYMENT_TARGET=${TVOS_MIN_OS_VERSION} \
|
|
-DCMAKE_SYSTEM_NAME=tvOS \
|
|
-DCMAKE_OSX_SYSROOT=appletvos \
|
|
-DCMAKE_OSX_ARCHITECTURES="arm64" \
|
|
-DGGML_METAL=ON \
|
|
-DCMAKE_XCODE_ATTRIBUTE_SUPPORTED_PLATFORMS=appletvos \
|
|
-DCMAKE_C_FLAGS="${COMMON_C_FLAGS}" \
|
|
-DCMAKE_CXX_FLAGS="${COMMON_CXX_FLAGS}" \
|
|
-DLLAMA_OPENSSL=OFF \
|
|
-DMTMD_VIDEO=OFF \
|
|
-S .
|
|
cmake --build build-tvos-device --config Release -j "${JOBS_PER_BUILD}" -- -quiet
|
|
}
|
|
|
|
run_builds_parallel() {
|
|
local -a pids=()
|
|
local -a names=()
|
|
local name i
|
|
for name in "$@"; do
|
|
# Wait for the oldest running build to free a slot
|
|
if [[ "${#pids[@]}" -ge "$MAX_PARALLEL_BUILDS" ]]; then
|
|
if ! wait "${pids[0]}"; then
|
|
echo "ERROR: build '${names[0]}' failed, log follows (${names[0]}.log):" >&2
|
|
kill "${pids[@]}" 2>/dev/null || true
|
|
cat "${names[0]}.log" >&2
|
|
exit 1
|
|
fi
|
|
pids=("${pids[@]:1}")
|
|
names=("${names[@]:1}")
|
|
fi
|
|
echo "Starting build: $name (log: ${name}.log, -j ${JOBS_PER_BUILD})"
|
|
"$name" > "${name}.log" 2>&1 &
|
|
pids+=("$!")
|
|
names+=("$name")
|
|
done
|
|
# Wait for the remaining builds
|
|
for i in "${!pids[@]}"; do
|
|
if ! wait "${pids[$i]}"; then
|
|
echo "ERROR: build '${names[$i]}' failed, log follows (${names[$i]}.log):" >&2
|
|
kill "${pids[@]}" 2>/dev/null || true
|
|
cat "${names[$i]}.log" >&2
|
|
exit 1
|
|
fi
|
|
done
|
|
}
|
|
|
|
BUILD_FNS=()
|
|
for b in "${BUILDS[@]}"; do
|
|
read -r fn _ < <(build_spec "$b")
|
|
BUILD_FNS+=("$fn")
|
|
done
|
|
echo "Building: ${BUILDS[*]} (max ${MAX_PARALLEL_BUILDS} at a time, -j ${JOBS_PER_BUILD} each)..."
|
|
run_builds_parallel "${BUILD_FNS[@]}"
|
|
|
|
# Setup frameworks and copy binaries and headers
|
|
echo "Setting up framework structures..."
|
|
for b in "${BUILDS[@]}"; do
|
|
read -r _ bdir _ platform _ min_os < <(build_spec "$b")
|
|
setup_framework_structure "$bdir" "$min_os" "$platform"
|
|
done
|
|
|
|
# Create dynamic libraries from static libraries
|
|
echo "Creating dynamic libraries from static libraries..."
|
|
for b in "${BUILDS[@]}"; do
|
|
read -r _ bdir rdir platform is_sim _ < <(build_spec "$b")
|
|
combine_static_libraries "$bdir" "$rdir" "$platform" "$is_sim"
|
|
done
|
|
|
|
# Create XCFramework with correct debug symbols paths
|
|
echo "Creating XCFramework..."
|
|
XCFW_ARGS=()
|
|
for b in "${BUILDS[@]}"; do
|
|
read -r _ bdir _ _ _ _ < <(build_spec "$b")
|
|
XCFW_ARGS+=(-framework "$(pwd)/${bdir}/framework/llama.framework")
|
|
XCFW_ARGS+=(-debug-symbols "$(pwd)/${bdir}/dSYMs/llama.dSYM")
|
|
done
|
|
xcrun xcodebuild -create-xcframework \
|
|
"${XCFW_ARGS[@]}" \
|
|
-output "$(pwd)/build-apple/llama.xcframework"
|