-DLLAMA_BUILD_SERVER=OFF \
-DCMAKE_OSX_ARCHITECTURES="arm64;x86_64"
cmake --build build --config Release -j $(sysctl -n hw.logicalcpu)
- sudo cmake --install build --config Release
- name: xcodebuild for swift package
id: xcodebuild
run: |
- xcodebuild -scheme llama-Package -destination "${{ matrix.destination }}"
+ ./build-xcframework.sh
+
+ - name: Determine tag name
+ id: tag
+ shell: bash
+ run: |
+ BUILD_NUMBER="$(git rev-list --count HEAD)"
+ SHORT_HASH="$(git rev-parse --short=7 HEAD)"
+ if [[ "${{ env.BRANCH_NAME }}" == "master" ]]; then
+ echo "name=b${BUILD_NUMBER}" >> $GITHUB_OUTPUT
+ else
+ SAFE_NAME=$(echo "${{ env.BRANCH_NAME }}" | tr '/' '-')
+ echo "name=${SAFE_NAME}-b${BUILD_NUMBER}-${SHORT_HASH}" >> $GITHUB_OUTPUT
+ fi
+
+ - name: Pack artifacts
+ id: pack_artifacts
+ if: ${{ ( github.event_name == 'push' && github.ref == 'refs/heads/master' ) || github.event.inputs.create_release == 'true' }}
+ run: |
+ zip -r llama-${{ steps.tag.outputs.name }}-xcframework.zip build-apple/llama.xcframework
+
+ - name: Upload artifacts
+ if: ${{ ( github.event_name == 'push' && github.ref == 'refs/heads/master' ) || github.event.inputs.create_release == 'true' }}
+ uses: actions/upload-artifact@v4
+ with:
+ path: llama-${{ steps.tag.outputs.name }}-xcframework.zip
windows-msys2:
runs-on: windows-latest
-DCMAKE_OSX_DEPLOYMENT_TARGET=14.0 \
-DCMAKE_XCODE_ATTRIBUTE_DEVELOPMENT_TEAM=ggml
cmake --build build --config Release -j $(sysctl -n hw.logicalcpu) -- CODE_SIGNING_ALLOWED=NO
- sudo cmake --install build --config Release
- name: xcodebuild for swift package
id: xcodebuild
run: |
- xcodebuild -scheme llama-Package -destination 'generic/platform=iOS'
+ ./build-xcframework.sh
- name: Build Xcode project
- run: xcodebuild -project examples/llama.swiftui/llama.swiftui.xcodeproj -scheme llama.swiftui -sdk iphoneos CODE_SIGNING_REQUIRED=NO CODE_SIGN_IDENTITY= -destination 'generic/platform=iOS' build
+ run: xcodebuild -project examples/llama.swiftui/llama.swiftui.xcodeproj -scheme llama.swiftui -sdk iphoneos CODE_SIGNING_REQUIRED=NO CODE_SIGN_IDENTITY= -destination 'generic/platform=iOS' FRAMEWORK_FOLDER_PATH=./build-ios build
android-build:
runs-on: ubuntu-latest
+++ /dev/null
-// swift-tools-version:5.5
-
-import PackageDescription
-
-let package = Package(
- name: "llama",
- platforms: [
- .macOS(.v12),
- .iOS(.v14),
- .watchOS(.v4),
- .tvOS(.v14)
- ],
- products: [
- .library(name: "llama", targets: ["llama"]),
- ],
- targets: [
- .systemLibrary(name: "llama", pkgConfig: "llama"),
- ]
-)
+++ /dev/null
-#pragma once
-
-#include <llama.h>
-
+++ /dev/null
-module llama [system] {
- header "llama.h"
- link "llama"
- export *
-}
--- /dev/null
+#!/bin/bash
+#
+# 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_EXAMPLES=OFF
+LLAMA_BUILD_TESTS=OFF
+LLAMA_BUILD_SERVER=OFF
+GGML_METAL=ON
+GGML_METAL_EMBED_LIBRARY=ON
+GGML_BLAS_DEFAULT=ON
+GGML_METAL_USE_BF16=ON
+GGML_OPENMP=OFF
+
+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_EXAMPLES=${LLAMA_BUILD_EXAMPLES}
+ -DLLAMA_BUILD_TESTS=${LLAMA_BUILD_TESTS}
+ -DLLAMA_BUILD_SERVER=${LLAMA_BUILD_SERVER}
+ -DGGML_METAL_EMBED_LIBRARY=${GGML_METAL_EMBED_LIBRARY}
+ -DGGML_BLAS_DEFAULT=${GGML_BLAS_DEFAULT}
+ -DGGML_METAL=${GGML_METAL}
+ -DGGML_METAL_USE_BF16=${GGML_METAL_USE_BF16}
+ -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 "xcodebuild" "Please install Xcode and Xcode Command Line Tools (xcode-select --install)"
+check_required_tool "libtool" "Please install libtool which should be available with Xcode Command Line Tools (CLT). Make sure Xcode CLT is installed (xcode-select --install)"
+check_required_tool "dsymutil" "Please install Xcode and Xcode Command Line Tools (xcode-select --install)"
+
+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-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}
+
+ # Create module map (common for all platforms)
+ cat > ${module_path}module.modulemap << EOF
+framework module llama {
+ header "llama.h"
+ header "ggml.h"
+ header "ggml-alloc.h"
+ header "ggml-backend.h"
+ header "ggml-metal.h"
+ header "ggml-cpu.h"
+ header "ggml-blas.h"
+ header "gguf.h"
+
+ 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"
+ )
+
+ # 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.
+ 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 command -v vtool &>/dev/null; then
+ case "$platform" in
+ "ios")
+ echo "Marking binary as a framework binary for iOS..."
+ 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..."
+ vtool -set-build-version xros ${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..."
+ 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}"
+}
+
+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}" \
+ -S .
+cmake --build build-ios-sim --config Release -- -quiet
+
+echo "Building for iOS devices..."
+cmake -B build-ios-device -G Xcode \
+ "${COMMON_CMAKE_ARGS[@]}" \
+ -DCMAKE_OSX_DEPLOYMENT_TARGET=${IOS_MIN_OS_VERSION} \
+ -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}" \
+ -S .
+cmake --build build-ios-device --config Release -- -quiet
+
+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}" \
+ -S .
+cmake --build build-macos --config Release -- -quiet
+
+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="-D_XOPEN_SOURCE=700 -Du_int=unsigned\ int -Du_char=unsigned\ char -Du_short=unsigned\ short ${COMMON_C_FLAGS}" \
+ -DCMAKE_CXX_FLAGS="-D_XOPEN_SOURCE=700 -Du_int=unsigned\ int -Du_char=unsigned\ char -Du_short=unsigned\ short ${COMMON_CXX_FLAGS}" \
+ -S .
+cmake --build build-visionos --config Release -- -quiet
+
+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="-D_XOPEN_SOURCE=700 -Du_int=unsigned\ int -Du_char=unsigned\ char -Du_short=unsigned\ short ${COMMON_C_FLAGS}" \
+ -DCMAKE_CXX_FLAGS="-D_XOPEN_SOURCE=700 -Du_int=unsigned\ int -Du_char=unsigned\ char -Du_short=unsigned\ short ${COMMON_CXX_FLAGS}" \
+ -S .
+cmake --build build-visionos-sim --config Release -- -quiet
+
+# Add tvOS builds (might need the same u_int definitions as watchOS and visionOS)
+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}" \
+ -S .
+cmake --build build-tvos-sim --config Release -- -quiet
+
+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}" \
+ -S .
+cmake --build build-tvos-device --config Release -- -quiet
+
+# Setup frameworks and copy binaries and headers
+echo "Setting up framework structures..."
+setup_framework_structure "build-ios-sim" ${IOS_MIN_OS_VERSION} "ios"
+setup_framework_structure "build-ios-device" ${IOS_MIN_OS_VERSION} "ios"
+setup_framework_structure "build-macos" ${MACOS_MIN_OS_VERSION} "macos"
+setup_framework_structure "build-visionos" ${VISIONOS_MIN_OS_VERSION} "visionos"
+setup_framework_structure "build-visionos-sim" ${VISIONOS_MIN_OS_VERSION} "visionos"
+setup_framework_structure "build-tvos-sim" ${TVOS_MIN_OS_VERSION} "tvos"
+setup_framework_structure "build-tvos-device" ${TVOS_MIN_OS_VERSION} "tvos"
+
+# Create dynamic libraries from static libraries
+echo "Creating dynamic libraries from static libraries..."
+combine_static_libraries "build-ios-sim" "Release-iphonesimulator" "ios" "true"
+combine_static_libraries "build-ios-device" "Release-iphoneos" "ios" "false"
+combine_static_libraries "build-macos" "Release" "macos" "false"
+combine_static_libraries "build-visionos" "Release-xros" "visionos" "false"
+combine_static_libraries "build-visionos-sim" "Release-xrsimulator" "visionos" "true"
+combine_static_libraries "build-tvos-sim" "Release-appletvsimulator" "tvos" "true"
+combine_static_libraries "build-tvos-device" "Release-appletvos" "tvos" "false"
+
+# Create XCFramework with correct debug symbols paths
+echo "Creating XCFramework..."
+xcodebuild -create-xcframework \
+ -framework $(pwd)/build-ios-sim/framework/llama.framework \
+ -debug-symbols $(pwd)/build-ios-sim/dSYMs/llama.dSYM \
+ -framework $(pwd)/build-ios-device/framework/llama.framework \
+ -debug-symbols $(pwd)/build-ios-device/dSYMs/llama.dSYM \
+ -framework $(pwd)/build-macos/framework/llama.framework \
+ -debug-symbols $(pwd)/build-macos/dSYMS/llama.dSYM \
+ -framework $(pwd)/build-visionos/framework/llama.framework \
+ -debug-symbols $(pwd)/build-visionos/dSYMs/llama.dSYM \
+ -framework $(pwd)/build-visionos-sim/framework/llama.framework \
+ -debug-symbols $(pwd)/build-visionos-sim/dSYMs/llama.dSYM \
+ -framework $(pwd)/build-tvos-device/framework/llama.framework \
+ -debug-symbols $(pwd)/build-tvos-device/dSYMs/llama.dSYM \
+ -framework $(pwd)/build-tvos-sim/framework/llama.framework \
+ -debug-symbols $(pwd)/build-tvos-sim/dSYMs/llama.dSYM \
+ -output $(pwd)/build-apple/llama.xcframework
For usage instructions and performance stats, check the following discussion: https://github.com/ggml-org/llama.cpp/discussions/4508
+
+### Building
+First llama.cpp need to be built and a XCFramework needs to be created. This can be done by running
+the following script from the llama.cpp project root:
+```console
+$ ./build-xcframework.sh
+```
+Open `llama.swiftui.xcodeproj` project in Xcode and you should be able to build and run the app on
+a simulator or a real device.
+
+To use the framework with a different project, the XCFramework can be added to the project by
+adding `build-ios/llama.xcframework` by dragging and dropping it into the project navigator, or
+by manually selecting the framework in the "Frameworks, Libraries, and Embedded Content" section
+of the project settings.
+

Video demonstration:
objects = {
/* Begin PBXBuildFile section */
- 1809696D2D05A39F00400EE8 /* llama in Frameworks */ = {isa = PBXBuildFile; productRef = 1809696C2D05A39F00400EE8 /* llama */; };
549479CB2AC9E16000E0F78B /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 549479CA2AC9E16000E0F78B /* Metal.framework */; };
79E1D9CD2B4CD16E005F8E46 /* InputButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79E1D9CC2B4CD16E005F8E46 /* InputButton.swift */; };
7FA3D2B32B2EA2F600543F92 /* DownloadButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FA3D2B22B2EA2F600543F92 /* DownloadButton.swift */; };
8A3F84242AC4C891005E2EE8 /* models in Resources */ = {isa = PBXBuildFile; fileRef = 8A3F84232AC4C891005E2EE8 /* models */; };
8A907F332AC7138A006146EA /* LibLlama.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A907F322AC7134E006146EA /* LibLlama.swift */; };
8A9F7C4D2AC332EE008AE1EA /* LlamaState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A9F7C4C2AC332EE008AE1EA /* LlamaState.swift */; };
+ DD84C9FD2D747FED007778EC /* llama.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD84C9FC2D747FED007778EC /* llama.xcframework */; };
+ DD84C9FE2D747FED007778EC /* llama.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = DD84C9FC2D747FED007778EC /* llama.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
F1FE20E22B465ECA00B45541 /* LoadCustomButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1FE20E12B465EC900B45541 /* LoadCustomButton.swift */; };
/* End PBXBuildFile section */
+/* Begin PBXCopyFilesBuildPhase section */
+ DD84C9FF2D747FED007778EC /* Embed Frameworks */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 10;
+ files = (
+ DD84C9FE2D747FED007778EC /* llama.xcframework in Embed Frameworks */,
+ );
+ name = "Embed Frameworks";
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
/* Begin PBXFileReference section */
549479CA2AC9E16000E0F78B /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = System/Library/Frameworks/Metal.framework; sourceTree = SDKROOT; };
79E1D9CC2B4CD16E005F8E46 /* InputButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InputButton.swift; sourceTree = "<group>"; };
8A3F84232AC4C891005E2EE8 /* models */ = {isa = PBXFileReference; lastKnownFileType = folder; name = models; path = llama.swiftui/Resources/models; sourceTree = "<group>"; };
8A907F322AC7134E006146EA /* LibLlama.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LibLlama.swift; sourceTree = "<group>"; };
8A9F7C4C2AC332EE008AE1EA /* LlamaState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LlamaState.swift; sourceTree = "<group>"; };
+ DD84C9FC2D747FED007778EC /* llama.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = llama.xcframework; path = "../../build-apple/llama.xcframework"; sourceTree = "<group>"; };
DF2D2FE72B4A59BE00FCB72D /* llama.cpp */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = llama.cpp; path = ../..; sourceTree = "<group>"; };
F1FE20E12B465EC900B45541 /* LoadCustomButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadCustomButton.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
- 1809696D2D05A39F00400EE8 /* llama in Frameworks */,
549479CB2AC9E16000E0F78B /* Metal.framework in Frameworks */,
8A39BE0A2AC7601100BFEB40 /* Accelerate.framework in Frameworks */,
+ DD84C9FD2D747FED007778EC /* llama.xcframework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
8A39BE082AC7601000BFEB40 /* Frameworks */ = {
isa = PBXGroup;
children = (
+ DD84C9FC2D747FED007778EC /* llama.xcframework */,
549479CA2AC9E16000E0F78B /* Metal.framework */,
8A39BE092AC7601000BFEB40 /* Accelerate.framework */,
);
8A1C836F2AC328BD0096AF73 /* Sources */,
8A1C83702AC328BD0096AF73 /* Frameworks */,
8A1C83712AC328BD0096AF73 /* Resources */,
+ DD84C9FF2D747FED007778EC /* Embed Frameworks */,
);
buildRules = (
);
);
name = llama.swiftui;
packageProductDependencies = (
- 1809696C2D05A39F00400EE8 /* llama */,
);
productName = llama.swiftui;
productReference = 8A1C83732AC328BD0096AF73 /* llama.swiftui.app */;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
-
-/* Begin XCSwiftPackageProductDependency section */
- 1809696C2D05A39F00400EE8 /* llama */ = {
- isa = XCSwiftPackageProductDependency;
- productName = llama;
- };
-/* End XCSwiftPackageProductDependency section */
};
rootObject = 8A1C836B2AC328BD0096AF73 /* Project object */;
}
--- /dev/null
+#!/bin/bash
+./scripts/apple/validate-ios.sh
+./scripts/apple/validate-macos.sh
+./scripts/apple/validate-visionos.sh
+./scripts/apple/validate-tvos.sh
--- /dev/null
+#!/bin/bash
+# validate-ios.sh - Validate iOS Application with embedded llama.xcframework using SwiftUI
+
+# Authentication options (optional) (can be set via environment variables)
+# To use: export APPLE_ID=your.email@example.com
+# export APPLE_PASSWORD=your-app-specific-password
+# ./validate-ios.sh
+APPLE_ID=${APPLE_ID:-""}
+APPLE_PASSWORD=${APPLE_PASSWORD:-""}
+
+# Ensure the script exits on error
+set -e
+
+# Function to print usage instructions
+print_usage() {
+ echo "Usage: ./validate-ios.sh [OPTIONS]"
+ echo ""
+ echo "Options:"
+ echo " --help Show this help message"
+ echo " --apple-id EMAIL Apple ID email for validation"
+ echo " --apple-password PWD App-specific password for Apple ID"
+ echo ""
+ echo "Environment variables:"
+ echo " APPLE_ID Apple ID email for validation"
+ echo " APPLE_PASSWORD App-specific password for Apple ID"
+ echo ""
+ echo "Notes:"
+ echo " - Command line options take precedence over environment variables"
+ echo " - Authentication is optional. If not provided, alternative validation will be performed"
+ echo " - For APPLE_PASSWORD, use an app-specific password generated at https://appleid.apple.com/account/manage"
+}
+
+# Parse command line arguments
+while [[ $# -gt 0 ]]; do
+ case $1 in
+ --help)
+ print_usage
+ exit 0
+ ;;
+ --apple-id)
+ APPLE_ID="$2"
+ shift 2
+ ;;
+ --apple-password)
+ APPLE_PASSWORD="$2"
+ shift 2
+ ;;
+ *)
+ echo "Unknown option: $1"
+ print_usage
+ exit 1
+ ;;
+ esac
+done
+
+# Function to clean up in case of error
+cleanup() {
+ # Don't clean up temp files on error to help with debugging
+ echo "===== iOS Validation Process Failed ====="
+ exit 1
+}
+
+# Set up trap to call cleanup function on error
+trap cleanup ERR
+
+set -e # Exit on any error
+
+ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/../.." && pwd )"
+BUILD_DIR="${ROOT_DIR}/validation-builds/ios"
+
+# Configuration
+APP_NAME="iOSLlamaTest"
+BUNDLE_ID="org.ggml.iOSLlamaTest"
+XCFRAMEWORK_PATH="${ROOT_DIR}/build-apple/llama.xcframework"
+TEMP_DIR="${BUILD_DIR}/temp"
+ARCHIVE_PATH="${BUILD_DIR}/${APP_NAME}.xcarchive"
+IPA_PATH="${BUILD_DIR}/${APP_NAME}.ipa"
+VALIDATION_DIR="${BUILD_DIR}/validation"
+
+# Create necessary directories
+mkdir -p "${BUILD_DIR}"
+mkdir -p "${TEMP_DIR}"
+mkdir -p "${VALIDATION_DIR}"
+
+echo "===== iOS Validation Process Started ====="
+
+# 1. Create a simple test app project
+echo "Creating test iOS app project..."
+mkdir -p "${TEMP_DIR}/${APP_NAME}/${APP_NAME}"
+cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Info.plist" << 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>${APP_NAME}</string>
+ <key>CFBundleIdentifier</key>
+ <string>${BUNDLE_ID}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>${APP_NAME}</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleVersion</key>
+ <string>1</string>
+ <key>LSRequiresIPhoneOS</key>
+ <true/>
+ <key>UILaunchScreen</key>
+ <dict/>
+ <key>UIRequiredDeviceCapabilities</key>
+ <array>
+ <string>armv7</string>
+ </array>
+ <key>UISupportedInterfaceOrientations</key>
+ <array>
+ <string>UIInterfaceOrientationPortrait</string>
+ </array>
+</dict>
+</plist>
+EOF
+
+# Create SwiftUI app files
+mkdir -p "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Sources"
+
+# Create App.swift
+cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Sources/App.swift" << EOF
+import SwiftUI
+import llama
+
+@main
+struct LlamaTestApp: App {
+ var body: some Scene {
+ WindowGroup {
+ ContentView()
+ }
+ }
+}
+EOF
+
+# Create ContentView.swift
+cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Sources/ContentView.swift" << EOF
+import SwiftUI
+import llama
+
+struct ContentView: View {
+ // Test that we can initialize a llama context params struct
+ let params = llama_context_default_params()
+
+ var body: some View {
+ VStack(spacing: 20) {
+ Text("Llama Framework Test")
+ .font(.largeTitle)
+ .padding()
+
+ Text("llama_context_default_params() created successfully")
+ .font(.headline)
+ .multilineTextAlignment(.center)
+ .padding()
+
+ // Display some param values to confirm the framework is working
+ Text("n_ctx: \(params.n_ctx)")
+ .font(.body)
+
+ Text("n_batch: \(params.n_batch)")
+ .font(.body)
+
+ Spacer()
+ }
+ .padding()
+ }
+}
+
+struct ContentView_Previews: PreviewProvider {
+ static var previews: some View {
+ ContentView()
+ }
+}
+EOF
+
+# Create project.pbxproj, fixing the framework search paths issues
+mkdir -p "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj"
+cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF'
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 54;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 11111111111111111111111 /* App.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22222222222222222222222; };
+ 33333333333333333333333 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44444444444444444444444; };
+ 55555555555555555555555 /* llama.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 66666666666666666666666; };
+ 77777777777777777777777 /* llama.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 66666666666666666666666; };
+/* End PBXBuildFile section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+ 88888888888888888888888 /* Embed Frameworks */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 10;
+ files = (
+ 77777777777777777777777 /* llama.xcframework in Embed Frameworks */,
+ );
+ name = "Embed Frameworks";
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+EOF
+
+# Continue with the project.pbxproj file, using the APP_NAME variable appropriately
+cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF
+ 99999999999999999999999 /* ${APP_NAME}.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "${APP_NAME}.app"; sourceTree = BUILT_PRODUCTS_DIR; };
+ 22222222222222222222222 /* App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App.swift; sourceTree = "<group>"; };
+ 44444444444444444444444 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
+ AAAAAAAAAAAAAAAAAAAAAAA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+ 66666666666666666666666 /* llama.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = llama.xcframework; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+EOF
+
+# Add the rest of the project file with fixed framework search paths
+cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF'
+/* Begin PBXFrameworksBuildPhase section */
+ BBBBBBBBBBBBBBBBBBBBBBBB /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 55555555555555555555555 /* llama.xcframework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+EOF
+
+# Continue with the project.pbxproj file, using the APP_NAME variable appropriately
+cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF
+ CCCCCCCCCCCCCCCCCCCCCCCC /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 99999999999999999999999 /* ${APP_NAME}.app */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+EOF
+
+cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF'
+ DDDDDDDDDDDDDDDDDDDDDDDD /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 66666666666666666666666 /* llama.xcframework */,
+ );
+ name = Frameworks;
+ sourceTree = "<group>";
+ };
+ EEEEEEEEEEEEEEEEEEEEEEEE = {
+ isa = PBXGroup;
+ children = (
+ FFFFFFFFFFFFFFFFFFFFFFFF /* iOSLlamaTest */,
+ CCCCCCCCCCCCCCCCCCCCCCCC /* Products */,
+ DDDDDDDDDDDDDDDDDDDDDDDD /* Frameworks */,
+ );
+ sourceTree = "<group>";
+ };
+ FFFFFFFFFFFFFFFFFFFFFFFF /* iOSLlamaTest */ = {
+ isa = PBXGroup;
+ children = (
+ 1111111111111111111111AA /* Sources */,
+ AAAAAAAAAAAAAAAAAAAAAAA /* Info.plist */,
+ );
+ path = "iOSLlamaTest";
+ sourceTree = "<group>";
+ };
+ 1111111111111111111111AA /* Sources */ = {
+ isa = PBXGroup;
+ children = (
+ 22222222222222222222222 /* App.swift */,
+ 44444444444444444444444 /* ContentView.swift */,
+ );
+ path = Sources;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+EOF
+
+# Continue with the project.pbxproj file, using the APP_NAME variable appropriately
+cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF
+/* Begin PBXNativeTarget section */
+ 3333333333333333333333AA /* ${APP_NAME} */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 4444444444444444444444AA /* Build configuration list for PBXNativeTarget "${APP_NAME}" */;
+ buildPhases = (
+ 5555555555555555555555AA /* Sources */,
+ BBBBBBBBBBBBBBBBBBBBBBBB /* Frameworks */,
+ 6666666666666666666666AA /* Resources */,
+ 88888888888888888888888 /* Embed Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "${APP_NAME}";
+ productName = "${APP_NAME}";
+ productReference = 99999999999999999999999 /* ${APP_NAME}.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 7777777777777777777777AA /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastSwiftUpdateCheck = 1240;
+ LastUpgradeCheck = 1240;
+ TargetAttributes = {
+ 3333333333333333333333AA = {
+ CreatedOnToolsVersion = 12.4;
+ };
+ };
+ };
+ buildConfigurationList = 8888888888888888888888AA /* Build configuration list for PBXProject "${APP_NAME}" */;
+ compatibilityVersion = "Xcode 12.0";
+ developmentRegion = en;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ Base,
+ );
+ mainGroup = EEEEEEEEEEEEEEEEEEEEEEEE;
+ productRefGroup = CCCCCCCCCCCCCCCCCCCCCCCC /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 3333333333333333333333AA /* ${APP_NAME} */,
+ );
+ };
+/* End PBXProject section */
+EOF
+
+# Add the rest of the file with correct FRAMEWORK_SEARCH_PATHS
+cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF'
+/* Begin PBXResourcesBuildPhase section */
+ 6666666666666666666666AA /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 5555555555555555555555AA /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 33333333333333333333333 /* ContentView.swift in Sources */,
+ 11111111111111111111111 /* App.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ 9999999999999999999999AA /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 16.4;
+ MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+ MTL_FAST_MATH = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = iphoneos;
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ };
+ name = Debug;
+ };
+ AAAAAAAAAAAAAAAAAAAAABBB /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 16.4;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ MTL_FAST_MATH = YES;
+ SDKROOT = iphoneos;
+ SWIFT_COMPILATION_MODE = wholemodule;
+ SWIFT_OPTIMIZATION_LEVEL = "-O";
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+ BBBBBBBBBBBBBBBBBBBBBBCCC /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
+ CODE_SIGN_STYLE = Manual;
+ DEVELOPMENT_TEAM = "";
+ ENABLE_PREVIEWS = YES;
+ FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)";
+ INFOPLIST_FILE = "iOSLlamaTest/Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = "org.ggml.iOSLlamaTest";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ CCCCCCCCCCCCCCCCCCCCCCDDD /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
+ CODE_SIGN_STYLE = Manual;
+ DEVELOPMENT_TEAM = "";
+ ENABLE_PREVIEWS = YES;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(PROJECT_DIR)",
+ );
+ INFOPLIST_FILE = "iOSLlamaTest/Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = "org.ggml.iOSLlamaTest";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+EOF
+
+# Finish the project.pbxproj file
+cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF
+/* Begin XCConfigurationList section */
+ 8888888888888888888888AA /* Build configuration list for PBXProject "${APP_NAME}" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 9999999999999999999999AA /* Debug */,
+ AAAAAAAAAAAAAAAAAAAAABBB /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 4444444444444444444444AA /* Build configuration list for PBXNativeTarget "${APP_NAME}" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ BBBBBBBBBBBBBBBBBBBBBBCCC /* Debug */,
+ CCCCCCCCCCCCCCCCCCCCCCDDD /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 7777777777777777777777AA /* Project object */;
+}
+EOF
+
+# 2. Copy XCFramework to test project
+echo "Copying XCFramework to test project..."
+cp -R "${XCFRAMEWORK_PATH}" "${TEMP_DIR}/${APP_NAME}/"
+
+# 3. Build and archive the app
+echo "Building and archiving test app..."
+cd "${TEMP_DIR}/${APP_NAME}"
+
+# Create a simple xcscheme file to avoid xcodebuild scheme issues
+mkdir -p "${APP_NAME}.xcodeproj/xcshareddata/xcschemes"
+cat > "${APP_NAME}.xcodeproj/xcshareddata/xcschemes/${APP_NAME}.xcscheme" << EOF
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ LastUpgradeVersion = "1240"
+ version = "1.3">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "YES">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "YES"
+ buildForArchiving = "YES"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "3333333333333333333333AA"
+ BuildableName = "${APP_NAME}.app"
+ BlueprintName = "${APP_NAME}"
+ ReferencedContainer = "container:${APP_NAME}.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ buildConfiguration = "Debug"
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES">
+ <Testables>
+ </Testables>
+ </TestAction>
+ <LaunchAction
+ buildConfiguration = "Debug"
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ debugServiceExtension = "internal"
+ allowLocationSimulation = "YES">
+ <BuildableProductRunnable
+ runnableDebuggingMode = "0">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "3333333333333333333333AA"
+ BuildableName = "${APP_NAME}.app"
+ BlueprintName = "${APP_NAME}"
+ ReferencedContainer = "container:${APP_NAME}.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ </LaunchAction>
+ <ProfileAction
+ buildConfiguration = "Release"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ debugDocumentVersioning = "YES">
+ <BuildableProductRunnable
+ runnableDebuggingMode = "0">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "3333333333333333333333AA"
+ BuildableName = "${APP_NAME}.app"
+ BlueprintName = "${APP_NAME}"
+ ReferencedContainer = "container:${APP_NAME}.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Debug">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Release"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+</Scheme>
+EOF
+
+# Now use xcodebuild with an explicitly defined product name
+xcodebuild -project "${APP_NAME}.xcodeproj" -scheme "${APP_NAME}" -sdk iphoneos -configuration Release archive -archivePath "${ARCHIVE_PATH}" CODE_SIGN_IDENTITY="-" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO PRODUCT_NAME="${APP_NAME}" SWIFT_OPTIMIZATION_LEVEL="-Onone" -quiet
+
+# 4. Create IPA from archive
+echo "Creating IPA from archive..."
+mkdir -p "${TEMP_DIR}/Payload"
+cp -R "${ARCHIVE_PATH}/Products/Applications/${APP_NAME}.app" "${TEMP_DIR}/Payload/"
+
+# Check and log app structure before zipping
+echo "App structure:"
+ls -la "${TEMP_DIR}/Payload/${APP_NAME}.app/"
+echo "Frameworks:"
+ls -la "${TEMP_DIR}/Payload/${APP_NAME}.app/Frameworks/" 2>/dev/null || echo "No Frameworks directory found"
+
+cd "${TEMP_DIR}"
+zip -r "${IPA_PATH}" Payload
+
+# Check embedded provisioning profile
+echo "Checking provisioning profile (if any)..."
+PROVISIONING_PROFILE=$(find "${ARCHIVE_PATH}/Products/Applications/${APP_NAME}.app" -name "embedded.mobileprovision" 2>/dev/null)
+if [ -n "$PROVISIONING_PROFILE" ]; then
+ echo "Found embedded provisioning profile:"
+ security cms -D -i "$PROVISIONING_PROFILE" || echo "Unable to decode provisioning profile"
+else
+ echo "No embedded provisioning profile found (expected for ad-hoc builds)"
+fi
+
+# 5. Validate the IPA
+echo "Validating IPA..."
+VALIDATION_OUTPUT="${VALIDATION_DIR}/validation_output.txt"
+
+# Check if authentication credentials are provided
+AUTH_ARGS=""
+if [ -n "$APPLE_ID" ] && [ -n "$APPLE_PASSWORD" ]; then
+ echo "Using Apple ID authentication for validation..."
+ AUTH_ARGS="--username \"$APPLE_ID\" --password \"$APPLE_PASSWORD\""
+else
+ echo "No authentication credentials provided. Will perform basic validation."
+ echo "To use your personal developer account, you can run the script with:"
+ echo " APPLE_ID='your.email@example.com' APPLE_PASSWORD='your-app-specific-password' ./validate-ios.sh"
+ echo "Note: You need to create an app-specific password at https://appleid.apple.com/account/manage"
+fi
+
+# Run validation with detailed output
+echo "Running validation with altool..."
+if [ -n "$AUTH_ARGS" ]; then
+ # Use eval to properly handle the quoted arguments
+ eval "xcrun altool --validate-app -f \"${IPA_PATH}\" --type ios --output-format xml $AUTH_ARGS" 2>&1 | tee "${VALIDATION_OUTPUT}"
+else
+ xcrun altool --validate-app -f "${IPA_PATH}" --type ios --output-format xml 2>&1 | tee "${VALIDATION_OUTPUT}"
+fi
+VALIDATION_RESULT=$?
+
+# Final validation result
+FINAL_VALIDATION_RESULT=0
+
+# Check if validation failed because the app isn't in App Store Connect
+if grep -q "No suitable application records were found" "${VALIDATION_OUTPUT}"; then
+ echo "⚠️ App Store Connect Warning: The app bundle identifier is not found in App Store Connect"
+ echo "This is expected for apps that haven't been registered in App Store Connect yet."
+ echo "This doesn't indicate a problem with the build or framework."
+
+ # Perform alternative validation
+ echo "Performing alternative validation checks..."
+
+ # Check if IPA was created successfully
+ if [ -f "${IPA_PATH}" ] && [ -s "${IPA_PATH}" ]; then
+ echo "✅ IPA file created successfully"
+ else
+ echo "❌ IPA file not created or empty"
+ FINAL_VALIDATION_RESULT=1
+ fi
+
+ # Check if app binary exists and is executable
+ if [ -f "${TEMP_DIR}/Payload/${APP_NAME}.app/${APP_NAME}" ] && [ -x "${TEMP_DIR}/Payload/${APP_NAME}.app/${APP_NAME}" ]; then
+ echo "✅ App binary exists and is executable"
+ else
+ echo "❌ App binary missing or not executable"
+ FINAL_VALIDATION_RESULT=1
+ fi
+
+ # Check if framework was properly embedded
+ if [ -d "${TEMP_DIR}/Payload/${APP_NAME}.app/Frameworks/llama.framework" ]; then
+ echo "✅ llama.framework properly embedded"
+ else
+ echo "❌ llama.framework not properly embedded"
+ FINAL_VALIDATION_RESULT=1
+ fi
+
+ # Check if framework binary exists
+ if [ -f "${TEMP_DIR}/Payload/${APP_NAME}.app/Frameworks/llama.framework/llama" ]; then
+ echo "✅ Framework binary exists"
+
+ # Further validate framework by checking architecture
+ ARCHS=$(lipo -info "${TEMP_DIR}/Payload/${APP_NAME}.app/Frameworks/llama.framework/llama" 2>/dev/null | grep -o "arm64\\|armv7\\|x86_64" | tr '\n' ' ')
+ if [ -n "$ARCHS" ]; then
+ echo "✅ Framework architecture(s): $ARCHS"
+ else
+ echo "⚠️ Could not determine framework architecture"
+ fi
+ else
+ echo "❌ Framework binary missing"
+ FINAL_VALIDATION_RESULT=1
+ fi
+
+ if [ $FINAL_VALIDATION_RESULT -eq 0 ]; then
+ echo "✅ Alternative validation PASSED: App built successfully with embedded framework"
+ else
+ echo "❌ Alternative validation FAILED: Issues found with the app or framework"
+ fi
+elif grep -q "You must specify authentication credentials" "${VALIDATION_OUTPUT}" && [ -z "$AUTH_ARGS" ]; then
+ echo "✅ iOS Validation PASSED: IPA successfully validated"
+ echo "Results saved to ${VALIDATION_OUTPUT}"
+else
+ echo "❌ iOS Validation FAILED: IPA validation found issues"
+ echo "See validation output at ${VALIDATION_OUTPUT}"
+ echo ""
+ echo "==== VALIDATION ERRORS ===="
+
+ # Try to extract specific errors from the output
+ if grep -q "Error" "${VALIDATION_OUTPUT}"; then
+ grep -A 5 "Error" "${VALIDATION_OUTPUT}"
+ else
+ # If no specific error found, show the whole log
+ cat "${VALIDATION_OUTPUT}"
+ fi
+
+ # Additional debugging: check IPA contents
+ echo ""
+ echo "==== IPA CONTENTS ===="
+ mkdir -p "${TEMP_DIR}/ipa_contents"
+ unzip -q "${IPA_PATH}" -d "${TEMP_DIR}/ipa_contents"
+ ls -la "${TEMP_DIR}/ipa_contents/Payload/${APP_NAME}.app/"
+
+ # Check for code signing issues
+ echo ""
+ echo "==== CODE SIGNING INFO ===="
+ codesign -vv -d "${TEMP_DIR}/ipa_contents/Payload/${APP_NAME}.app" 2>&1 || echo "Code signing verification failed"
+
+ # Check embedded frameworks
+ echo ""
+ echo "==== FRAMEWORK INFO ===="
+ ls -la "${TEMP_DIR}/ipa_contents/Payload/${APP_NAME}.app/Frameworks/" 2>/dev/null || echo "No Frameworks directory found"
+fi
+
+# Don't clean up on error to allow inspection
+if [ $FINAL_VALIDATION_RESULT -ne 0 ]; then
+ echo ""
+ echo "Temporary files kept for inspection at: ${TEMP_DIR}"
+ echo "===== iOS Validation Process Failed ====="
+ exit 1
+fi
+
+# Clean up temporary files but keep build artifacts
+if [ $FINAL_VALIDATION_RESULT -eq 0 ]; then
+ echo "Cleaning up temporary files..."
+ #rm -rf "${TEMP_DIR}"
+fi
+
+echo "===== iOS Validation Process Completed ====="
+exit $FINAL_VALIDATION_RESULT
--- /dev/null
+#!/bin/bash
+# validate-macos.sh - Validate macOS Application with embedded llama.xcframework using SwiftUI
+
+# Authentication options (optional) (can be set via environment variables)
+# To use: export APPLE_ID=your.email@example.com
+# export APPLE_PASSWORD=your-app-specific-password
+# ./validate-macos.sh
+APPLE_ID=${APPLE_ID:-""}
+APPLE_PASSWORD=${APPLE_PASSWORD:-""}
+
+# Ensure the script exits on error
+set -e
+
+# Function to print usage instructions
+print_usage() {
+ echo "Usage: ./validate-macos.sh [OPTIONS]"
+ echo ""
+ echo "Options:"
+ echo " --help Show this help message"
+ echo " --apple-id EMAIL Apple ID email for validation"
+ echo " --apple-password PWD App-specific password for Apple ID"
+ echo ""
+ echo "Environment variables:"
+ echo " APPLE_ID Apple ID email for validation"
+ echo " APPLE_PASSWORD App-specific password for Apple ID"
+ echo ""
+ echo "Notes:"
+ echo " - Command line options take precedence over environment variables"
+ echo " - Authentication is optional. If not provided, alternative validation will be performed"
+ echo " - For APPLE_PASSWORD, use an app-specific password generated at https://appleid.apple.com/account/manage"
+}
+
+# Parse command line arguments
+while [[ $# -gt 0 ]]; do
+ case $1 in
+ --help)
+ print_usage
+ exit 0
+ ;;
+ --apple-id)
+ APPLE_ID="$2"
+ shift 2
+ ;;
+ --apple-password)
+ APPLE_PASSWORD="$2"
+ shift 2
+ ;;
+ *)
+ echo "Unknown option: $1"
+ print_usage
+ exit 1
+ ;;
+ esac
+done
+
+# Function to clean up in case of error
+cleanup() {
+ # Don't clean up temp files on error to help with debugging
+ echo "===== macOS Validation Process Failed ====="
+ exit 1
+}
+
+# Set up trap to call cleanup function on error
+trap cleanup ERR
+
+set -e # Exit on any error
+
+ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/../.." && pwd )"
+BUILD_DIR="${ROOT_DIR}/validation-builds/ios"
+
+# Configuration
+APP_NAME="MacOSLlamaTest"
+BUNDLE_ID="org.ggml.MacOSLlamaTest"
+XCFRAMEWORK_PATH="${ROOT_DIR}/build-apple/llama.xcframework"
+TEMP_DIR="${BUILD_DIR}/temp"
+ARCHIVE_PATH="${BUILD_DIR}/${APP_NAME}.xcarchive"
+APP_PATH="${BUILD_DIR}/${APP_NAME}.app"
+ZIP_PATH="${BUILD_DIR}/${APP_NAME}.zip"
+VALIDATION_DIR="${BUILD_DIR}/validation"
+
+# Create necessary directories
+mkdir -p "${BUILD_DIR}"
+mkdir -p "${TEMP_DIR}"
+mkdir -p "${VALIDATION_DIR}"
+
+echo "===== macOS Validation Process Started ====="
+
+# 1. Create a simple test app project
+echo "Creating test macOS app project..."
+mkdir -p "${TEMP_DIR}/${APP_NAME}/${APP_NAME}"
+cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Info.plist" << 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>${APP_NAME}</string>
+ <key>CFBundleIdentifier</key>
+ <string>${BUNDLE_ID}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>${APP_NAME}</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleVersion</key>
+ <string>1</string>
+ <key>LSMinimumSystemVersion</key>
+ <string>12.0</string>
+ <key>NSHumanReadableCopyright</key>
+ <string>Copyright © 2025 GGML. All rights reserved.</string>
+ <key>NSPrincipalClass</key>
+ <string>NSApplication</string>
+</dict>
+</plist>
+EOF
+
+# Create SwiftUI app files
+mkdir -p "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Sources"
+
+# Create App.swift
+cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Sources/App.swift" << EOF
+import SwiftUI
+import llama
+
+@main
+struct LlamaTestApp: App {
+ var body: some Scene {
+ WindowGroup {
+ ContentView()
+ }
+ }
+}
+EOF
+
+# Create ContentView.swift with macOS specific elements
+cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Sources/ContentView.swift" << EOF
+import SwiftUI
+import llama
+
+struct ContentView: View {
+ // Test that we can initialize a llama context params struct
+ let params = llama_context_default_params()
+
+ var body: some View {
+ VStack(spacing: 20) {
+ Text("Llama Framework Test on macOS")
+ .font(.largeTitle)
+ .padding()
+
+ Text("llama_context_default_params() created successfully")
+ .font(.headline)
+ .multilineTextAlignment(.center)
+ .padding()
+
+ // Display some param values to confirm the framework is working
+ Text("n_ctx: \(params.n_ctx)")
+ .font(.body)
+
+ Text("n_batch: \(params.n_batch)")
+ .font(.body)
+
+ Spacer()
+ }
+ .padding()
+ .frame(width: 600, height: 400)
+ }
+}
+
+struct ContentView_Previews: PreviewProvider {
+ static var previews: some View {
+ ContentView()
+ }
+}
+EOF
+
+# Create project.pbxproj, fixing the framework search paths issues
+mkdir -p "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj"
+cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF'
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 54;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 11111111111111111111111 /* App.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22222222222222222222222; };
+ 33333333333333333333333 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44444444444444444444444; };
+ 55555555555555555555555 /* llama.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 66666666666666666666666; };
+ 77777777777777777777777 /* llama.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 66666666666666666666666; };
+/* End PBXBuildFile section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+ 88888888888888888888888 /* Embed Frameworks */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 10;
+ files = (
+ 77777777777777777777777 /* llama.xcframework in Embed Frameworks */,
+ );
+ name = "Embed Frameworks";
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+EOF
+
+# Continue with the project.pbxproj file, using the APP_NAME variable appropriately
+cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF
+ 99999999999999999999999 /* ${APP_NAME}.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "${APP_NAME}.app"; sourceTree = BUILT_PRODUCTS_DIR; };
+ 22222222222222222222222 /* App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App.swift; sourceTree = "<group>"; };
+ 44444444444444444444444 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
+ AAAAAAAAAAAAAAAAAAAAAAA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+ 66666666666666666666666 /* llama.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = llama.xcframework; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+EOF
+
+# Add the rest of the project file with fixed framework search paths
+cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF'
+/* Begin PBXFrameworksBuildPhase section */
+ BBBBBBBBBBBBBBBBBBBBBBBB /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 55555555555555555555555 /* llama.xcframework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+EOF
+
+# Continue with the project.pbxproj file, using the APP_NAME variable appropriately
+cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF
+ CCCCCCCCCCCCCCCCCCCCCCCC /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 99999999999999999999999 /* ${APP_NAME}.app */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+EOF
+
+cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF'
+ DDDDDDDDDDDDDDDDDDDDDDDD /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 66666666666666666666666 /* llama.xcframework */,
+ );
+ name = Frameworks;
+ sourceTree = "<group>";
+ };
+ EEEEEEEEEEEEEEEEEEEEEEEE = {
+ isa = PBXGroup;
+ children = (
+ FFFFFFFFFFFFFFFFFFFFFFFF /* MacOSLlamaTest */,
+ CCCCCCCCCCCCCCCCCCCCCCCC /* Products */,
+ DDDDDDDDDDDDDDDDDDDDDDDD /* Frameworks */,
+ );
+ sourceTree = "<group>";
+ };
+ FFFFFFFFFFFFFFFFFFFFFFFF /* MacOSLlamaTest */ = {
+ isa = PBXGroup;
+ children = (
+ 1111111111111111111111AA /* Sources */,
+ AAAAAAAAAAAAAAAAAAAAAAA /* Info.plist */,
+ );
+ path = "MacOSLlamaTest";
+ sourceTree = "<group>";
+ };
+ 1111111111111111111111AA /* Sources */ = {
+ isa = PBXGroup;
+ children = (
+ 22222222222222222222222 /* App.swift */,
+ 44444444444444444444444 /* ContentView.swift */,
+ );
+ path = Sources;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+EOF
+
+# Continue with the project.pbxproj file, using the APP_NAME variable appropriately
+cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF
+/* Begin PBXNativeTarget section */
+ 3333333333333333333333AA /* ${APP_NAME} */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 4444444444444444444444AA /* Build configuration list for PBXNativeTarget "${APP_NAME}" */;
+ buildPhases = (
+ 5555555555555555555555AA /* Sources */,
+ BBBBBBBBBBBBBBBBBBBBBBBB /* Frameworks */,
+ 6666666666666666666666AA /* Resources */,
+ 88888888888888888888888 /* Embed Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "${APP_NAME}";
+ productName = "${APP_NAME}";
+ productReference = 99999999999999999999999 /* ${APP_NAME}.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 7777777777777777777777AA /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastSwiftUpdateCheck = 1240;
+ LastUpgradeCheck = 1240;
+ TargetAttributes = {
+ 3333333333333333333333AA = {
+ CreatedOnToolsVersion = 12.4;
+ };
+ };
+ };
+ buildConfigurationList = 8888888888888888888888AA /* Build configuration list for PBXProject "${APP_NAME}" */;
+ compatibilityVersion = "Xcode 12.0";
+ developmentRegion = en;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ Base,
+ );
+ mainGroup = EEEEEEEEEEEEEEEEEEEEEEEE;
+ productRefGroup = CCCCCCCCCCCCCCCCCCCCCCCC /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 3333333333333333333333AA /* ${APP_NAME} */,
+ );
+ };
+/* End PBXProject section */
+EOF
+
+# Add the rest of the file with correct FRAMEWORK_SEARCH_PATHS and macOS settings
+cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF'
+/* Begin PBXResourcesBuildPhase section */
+ 6666666666666666666666AA /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 5555555555555555555555AA /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 33333333333333333333333 /* ContentView.swift in Sources */,
+ 11111111111111111111111 /* App.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ 9999999999999999999999AA /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET = 12.0;
+ MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+ MTL_FAST_MATH = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = macosx;
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ };
+ name = Debug;
+ };
+ AAAAAAAAAAAAAAAAAAAAABBB /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET = 12.0;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ MTL_FAST_MATH = YES;
+ SDKROOT = macosx;
+ SWIFT_COMPILATION_MODE = wholemodule;
+ SWIFT_OPTIMIZATION_LEVEL = "-O";
+ };
+ name = Release;
+ };
+ BBBBBBBBBBBBBBBBBBBBBBCCC /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
+ CODE_SIGN_STYLE = Manual;
+ COMBINE_HIDPI_IMAGES = YES;
+ DEVELOPMENT_TEAM = "";
+ ENABLE_HARDENED_RUNTIME = YES;
+ ENABLE_PREVIEWS = YES;
+ FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)";
+ INFOPLIST_FILE = "MacOSLlamaTest/Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/../Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = "org.ggml.MacOSLlamaTest";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ SWIFT_VERSION = 5.0;
+ };
+ name = Debug;
+ };
+ CCCCCCCCCCCCCCCCCCCCCCDDD /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
+ CODE_SIGN_STYLE = Manual;
+ COMBINE_HIDPI_IMAGES = YES;
+ DEVELOPMENT_TEAM = "";
+ ENABLE_HARDENED_RUNTIME = YES;
+ ENABLE_PREVIEWS = YES;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(PROJECT_DIR)",
+ );
+ INFOPLIST_FILE = "MacOSLlamaTest/Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/../Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = "org.ggml.MacOSLlamaTest";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ SWIFT_VERSION = 5.0;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+EOF
+
+# Finish the project.pbxproj file
+cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF
+/* Begin XCConfigurationList section */
+ 8888888888888888888888AA /* Build configuration list for PBXProject "${APP_NAME}" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 9999999999999999999999AA /* Debug */,
+ AAAAAAAAAAAAAAAAAAAAABBB /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 4444444444444444444444AA /* Build configuration list for PBXNativeTarget "${APP_NAME}" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ BBBBBBBBBBBBBBBBBBBBBBCCC /* Debug */,
+ CCCCCCCCCCCCCCCCCCCCCCDDD /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 7777777777777777777777AA /* Project object */;
+}
+EOF
+
+# 2. Copy XCFramework to test project
+echo "Copying XCFramework to test project..."
+cp -R "${XCFRAMEWORK_PATH}" "${TEMP_DIR}/${APP_NAME}/"
+
+# 3. Build and archive the app
+echo "Building and archiving test app..."
+cd "${TEMP_DIR}/${APP_NAME}"
+
+# Create a simple xcscheme file to avoid xcodebuild scheme issues
+mkdir -p "${APP_NAME}.xcodeproj/xcshareddata/xcschemes"
+cat > "${APP_NAME}.xcodeproj/xcshareddata/xcschemes/${APP_NAME}.xcscheme" << EOF
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ LastUpgradeVersion = "1240"
+ version = "1.3">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "YES">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "YES"
+ buildForArchiving = "YES"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "3333333333333333333333AA"
+ BuildableName = "${APP_NAME}.app"
+ BlueprintName = "${APP_NAME}"
+ ReferencedContainer = "container:${APP_NAME}.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ buildConfiguration = "Debug"
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES">
+ <Testables>
+ </Testables>
+ </TestAction>
+ <LaunchAction
+ buildConfiguration = "Debug"
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ debugServiceExtension = "internal"
+ allowLocationSimulation = "YES">
+ <BuildableProductRunnable
+ runnableDebuggingMode = "0">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "3333333333333333333333AA"
+ BuildableName = "${APP_NAME}.app"
+ BlueprintName = "${APP_NAME}"
+ ReferencedContainer = "container:${APP_NAME}.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ </LaunchAction>
+ <ProfileAction
+ buildConfiguration = "Release"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ debugDocumentVersioning = "YES">
+ <BuildableProductRunnable
+ runnableDebuggingMode = "0">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "3333333333333333333333AA"
+ BuildableName = "${APP_NAME}.app"
+ BlueprintName = "${APP_NAME}"
+ ReferencedContainer = "container:${APP_NAME}.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Debug">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Release"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+</Scheme>
+EOF
+
+# Now use xcodebuild with an explicitly defined product name for macOS
+xcodebuild -project "${APP_NAME}.xcodeproj" -scheme "${APP_NAME}" -sdk macosx -configuration Release archive -archivePath "${ARCHIVE_PATH}" CODE_SIGN_IDENTITY="-" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO PRODUCT_NAME="${APP_NAME}" SWIFT_OPTIMIZATION_LEVEL="-Onone" -quiet
+
+# 4. Create a package for distribution
+echo "Creating distributable package from archive..."
+cp -R "${ARCHIVE_PATH}/Products/Applications/${APP_NAME}.app" "${APP_PATH}"
+
+# Check and log app structure
+echo "App structure:"
+ls -la "${APP_PATH}"
+echo "Frameworks:"
+ls -la "${APP_PATH}/Contents/Frameworks/" 2>/dev/null || echo "No Frameworks directory found"
+
+# Create a zip file for potential distribution
+cd "${BUILD_DIR}"
+zip -r "${ZIP_PATH}" "${APP_NAME}.app"
+
+# Check embedded provisioning profile
+echo "Checking provisioning profile (if any)..."
+PROVISIONING_PROFILE=$(find "${APP_PATH}/Contents" -name "embedded.provisionprofile" 2>/dev/null)
+if [ -n "$PROVISIONING_PROFILE" ]; then
+ echo "Found embedded provisioning profile:"
+ security cms -D -i "$PROVISIONING_PROFILE" || echo "Unable to decode provisioning profile"
+else
+ echo "No embedded provisioning profile found (expected for ad-hoc builds)"
+fi
+
+# 5. Validate the app
+echo "Validating macOS app..."
+VALIDATION_OUTPUT="${VALIDATION_DIR}/validation_output.txt"
+
+# Check if authentication credentials are provided
+AUTH_ARGS=""
+if [ -n "$APPLE_ID" ] && [ -n "$APPLE_PASSWORD" ]; then
+ echo "Using Apple ID authentication for validation..."
+ AUTH_ARGS="--username \"$APPLE_ID\" --password \"$APPLE_PASSWORD\""
+else
+ echo "No authentication credentials provided. Will perform basic validation."
+ echo "To use your personal developer account, you can run the script with:"
+ echo " APPLE_ID='your.email@example.com' APPLE_PASSWORD='your-app-specific-password' ./validate-macos.sh"
+ echo "Note: You need to create an app-specific password at https://appleid.apple.com/account/manage"
+fi
+
+# For macOS we need to use notarytool or alternative checks because altool doesn't support macOS apps in the same way
+echo "Note: For macOS, formal notarization process would require Apple Developer credentials."
+echo "Performing alternative validation checks..."
+
+# Final validation result
+FINAL_VALIDATION_RESULT=0
+
+# Check if app was created successfully
+if [ -d "${APP_PATH}" ] && [ -s "${APP_PATH}/Contents/MacOS/${APP_NAME}" ]; then
+ echo "✅ App package created successfully"
+else
+ echo "❌ App package not created or binary missing"
+ FINAL_VALIDATION_RESULT=1
+fi
+
+# Check if app binary exists and is executable
+if [ -f "${APP_PATH}/Contents/MacOS/${APP_NAME}" ] && [ -x "${APP_PATH}/Contents/MacOS/${APP_NAME}" ]; then
+ echo "✅ App binary exists and is executable"
+else
+ echo "❌ App binary missing or not executable"
+ FINAL_VALIDATION_RESULT=1
+fi
+
+# Check if framework was properly embedded
+if [ -d "${APP_PATH}/Contents/Frameworks/llama.framework" ]; then
+ echo "✅ llama.framework properly embedded"
+else
+ echo "❌ llama.framework not properly embedded"
+ FINAL_VALIDATION_RESULT=1
+fi
+
+# Check if framework binary exists
+if [ -f "${APP_PATH}/Contents/Frameworks/llama.framework/Versions/A/llama" ]; then
+ echo "✅ Framework binary exists"
+
+ # Further validate framework by checking architecture
+ ARCHS=$(lipo -info "${APP_PATH}/Contents/Frameworks/llama.framework/Versions/A/llama" 2>/dev/null | grep -o "arm64\\|x86_64" | tr '\n' ' ')
+ if [ -n "$ARCHS" ]; then
+ echo "✅ Framework architecture(s): $ARCHS"
+ else
+ echo "⚠️ Could not determine framework architecture"
+ fi
+else
+ echo "❌ Framework binary missing"
+ FINAL_VALIDATION_RESULT=1
+fi
+
+# Check code signing
+echo ""
+echo "==== CODE SIGNING INFO ===="
+codesign -vv -d "${APP_PATH}" 2>&1 || echo "Code signing verification not available (expected for ad-hoc builds)"
+
+if [ $FINAL_VALIDATION_RESULT -eq 0 ]; then
+ if [ -n "$AUTH_ARGS" ]; then
+ echo ""
+ echo "To notarize this app with Apple (requires Apple Developer account):"
+ echo "xcrun notarytool submit \"${ZIP_PATH}\" --apple-id \"your-apple-id\" --password \"your-app-specific-password\" --team-id \"your-team-id\" --wait"
+ echo ""
+ fi
+ echo "✅ Validation PASSED: macOS app built successfully with embedded framework"
+else
+ echo "❌ Validation FAILED: Issues found with the app or framework"
+fi
+
+# Don't clean up on error to allow inspection
+if [ $FINAL_VALIDATION_RESULT -ne 0 ]; then
+ echo ""
+ echo "Temporary files kept for inspection at: ${TEMP_DIR}"
+ echo "===== macOS Validation Process Failed ====="
+ exit 1
+fi
+
+# Clean up temporary files but keep build artifacts
+if [ $FINAL_VALIDATION_RESULT -eq 0 ]; then
+ echo "Cleaning up temporary files..."
+ #rm -rf "${TEMP_DIR}"
+fi
+
+echo "===== macOS Validation Process Completed ====="
+echo "App package available at: ${APP_PATH}"
+echo "Zipped app available at: ${ZIP_PATH}"
+exit $FINAL_VALIDATION_RESULT
--- /dev/null
+#!/bin/bash
+# validate-tvos.sh - Validate tvOS Application with embedded llama.xcframework using SwiftUI
+
+# Authentication options (optional) (can be set via environment variables)
+# To use: export APPLE_ID=your.email@example.com
+# export APPLE_PASSWORD=your-app-specific-password
+# ./validate-tvos.sh
+APPLE_ID=${APPLE_ID:-""}
+APPLE_PASSWORD=${APPLE_PASSWORD:-""}
+
+# Ensure the script exits on error
+set -e
+
+# Function to print usage instructions
+print_usage() {
+ echo "Usage: ./validate-tvos.sh [OPTIONS]"
+ echo ""
+ echo "Options:"
+ echo " --help Show this help message"
+ echo " --apple-id EMAIL Apple ID email for validation"
+ echo " --apple-password PWD App-specific password for Apple ID"
+ echo ""
+ echo "Environment variables:"
+ echo " APPLE_ID Apple ID email for validation"
+ echo " APPLE_PASSWORD App-specific password for Apple ID"
+ echo ""
+ echo "Notes:"
+ echo " - Command line options take precedence over environment variables"
+ echo " - Authentication is optional. If not provided, alternative validation will be performed"
+ echo " - For APPLE_PASSWORD, use an app-specific password generated at https://appleid.apple.com/account/manage"
+}
+
+# Parse command line arguments
+while [[ $# -gt 0 ]]; do
+ case $1 in
+ --help)
+ print_usage
+ exit 0
+ ;;
+ --apple-id)
+ APPLE_ID="$2"
+ shift 2
+ ;;
+ --apple-password)
+ APPLE_PASSWORD="$2"
+ shift 2
+ ;;
+ *)
+ echo "Unknown option: $1"
+ print_usage
+ exit 1
+ ;;
+ esac
+done
+
+# Function to clean up in case of error
+cleanup() {
+ # Don't clean up temp files on error to help with debugging
+ echo "===== tvOS Validation Process Failed ====="
+ exit 1
+}
+
+# Set up trap to call cleanup function on error
+trap cleanup ERR
+
+set -e # Exit on any error
+
+ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/../.." && pwd )"
+BUILD_DIR="${ROOT_DIR}/validation-builds/ios"
+
+# Configuration
+APP_NAME="TVOSLlamaTest"
+BUNDLE_ID="org.ggml.TVOSLlamaTest"
+XCFRAMEWORK_PATH="${ROOT_DIR}/build-apple/llama.xcframework"
+TEMP_DIR="${BUILD_DIR}/temp"
+ARCHIVE_PATH="${BUILD_DIR}/${APP_NAME}.xcarchive"
+IPA_PATH="${BUILD_DIR}/${APP_NAME}.ipa"
+VALIDATION_DIR="${BUILD_DIR}/validation"
+
+# Create necessary directories
+mkdir -p "${BUILD_DIR}"
+mkdir -p "${TEMP_DIR}"
+mkdir -p "${VALIDATION_DIR}"
+
+echo "===== tvOS Validation Process Started ====="
+
+# 1. Create a simple test app project
+echo "Creating test tvOS app project..."
+mkdir -p "${TEMP_DIR}/${APP_NAME}/${APP_NAME}"
+cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Info.plist" << 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>${APP_NAME}</string>
+ <key>CFBundleIdentifier</key>
+ <string>${BUNDLE_ID}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>${APP_NAME}</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleVersion</key>
+ <string>1</string>
+ <key>UIRequiredDeviceCapabilities</key>
+ <array>
+ <string>arm64</string>
+ </array>
+</dict>
+</plist>
+EOF
+
+# Create SwiftUI app files
+mkdir -p "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Sources"
+
+# Create App.swift
+cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Sources/App.swift" << EOF
+import SwiftUI
+import llama
+
+@main
+struct LlamaTestApp: App {
+ var body: some Scene {
+ WindowGroup {
+ ContentView()
+ }
+ }
+}
+EOF
+
+# Create ContentView.swift with tvOS specific elements
+cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Sources/ContentView.swift" << EOF
+import SwiftUI
+import llama
+
+struct ContentView: View {
+ // Test that we can initialize a llama context params struct
+ let params = llama_context_default_params()
+
+ var body: some View {
+ VStack(spacing: 40) {
+ Text("Llama Framework Test on tvOS")
+ .font(.largeTitle)
+ .padding()
+
+ Text("llama_context_default_params() created successfully")
+ .font(.headline)
+ .multilineTextAlignment(.center)
+ .padding()
+
+ // Display some param values to confirm the framework is working
+ Text("n_ctx: \(params.n_ctx)")
+ .font(.title2)
+
+ Text("n_batch: \(params.n_batch)")
+ .font(.title2)
+
+ Spacer()
+ }
+ .padding(50)
+ // Larger size suitable for TV display
+ }
+}
+
+struct ContentView_Previews: PreviewProvider {
+ static var previews: some View {
+ ContentView()
+ }
+}
+EOF
+
+# Create project.pbxproj, fixing the framework search paths issues
+mkdir -p "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj"
+cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF'
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 54;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 11111111111111111111111 /* App.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22222222222222222222222; };
+ 33333333333333333333333 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44444444444444444444444; };
+ 55555555555555555555555 /* llama.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 66666666666666666666666; };
+ 77777777777777777777777 /* llama.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 66666666666666666666666; };
+/* End PBXBuildFile section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+ 88888888888888888888888 /* Embed Frameworks */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 10;
+ files = (
+ 77777777777777777777777 /* llama.xcframework in Embed Frameworks */,
+ );
+ name = "Embed Frameworks";
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+EOF
+
+# Continue with the project.pbxproj file, using the APP_NAME variable appropriately
+cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF
+ 99999999999999999999999 /* ${APP_NAME}.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "${APP_NAME}.app"; sourceTree = BUILT_PRODUCTS_DIR; };
+ 22222222222222222222222 /* App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App.swift; sourceTree = "<group>"; };
+ 44444444444444444444444 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
+ AAAAAAAAAAAAAAAAAAAAAAA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+ 66666666666666666666666 /* llama.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = llama.xcframework; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+EOF
+
+# Add the rest of the project file with fixed framework search paths
+cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF'
+/* Begin PBXFrameworksBuildPhase section */
+ BBBBBBBBBBBBBBBBBBBBBBBB /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 55555555555555555555555 /* llama.xcframework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+EOF
+
+# Continue with the project.pbxproj file, using the APP_NAME variable appropriately
+cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF
+ CCCCCCCCCCCCCCCCCCCCCCCC /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 99999999999999999999999 /* ${APP_NAME}.app */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+EOF
+
+cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF'
+ DDDDDDDDDDDDDDDDDDDDDDDD /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 66666666666666666666666 /* llama.xcframework */,
+ );
+ name = Frameworks;
+ sourceTree = "<group>";
+ };
+ EEEEEEEEEEEEEEEEEEEEEEEE = {
+ isa = PBXGroup;
+ children = (
+ FFFFFFFFFFFFFFFFFFFFFFFF /* TVOSLlamaTest */,
+ CCCCCCCCCCCCCCCCCCCCCCCC /* Products */,
+ DDDDDDDDDDDDDDDDDDDDDDDD /* Frameworks */,
+ );
+ sourceTree = "<group>";
+ };
+ FFFFFFFFFFFFFFFFFFFFFFFF /* TVOSLlamaTest */ = {
+ isa = PBXGroup;
+ children = (
+ 1111111111111111111111AA /* Sources */,
+ AAAAAAAAAAAAAAAAAAAAAAA /* Info.plist */,
+ );
+ path = "TVOSLlamaTest";
+ sourceTree = "<group>";
+ };
+ 1111111111111111111111AA /* Sources */ = {
+ isa = PBXGroup;
+ children = (
+ 22222222222222222222222 /* App.swift */,
+ 44444444444444444444444 /* ContentView.swift */,
+ );
+ path = Sources;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+EOF
+
+# Continue with the project.pbxproj file, using the APP_NAME variable appropriately
+cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF
+/* Begin PBXNativeTarget section */
+ 3333333333333333333333AA /* ${APP_NAME} */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 4444444444444444444444AA /* Build configuration list for PBXNativeTarget "${APP_NAME}" */;
+ buildPhases = (
+ 5555555555555555555555AA /* Sources */,
+ BBBBBBBBBBBBBBBBBBBBBBBB /* Frameworks */,
+ 6666666666666666666666AA /* Resources */,
+ 88888888888888888888888 /* Embed Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "${APP_NAME}";
+ productName = "${APP_NAME}";
+ productReference = 99999999999999999999999 /* ${APP_NAME}.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 7777777777777777777777AA /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastSwiftUpdateCheck = 1240;
+ LastUpgradeCheck = 1240;
+ TargetAttributes = {
+ 3333333333333333333333AA = {
+ CreatedOnToolsVersion = 12.4;
+ };
+ };
+ };
+ buildConfigurationList = 8888888888888888888888AA /* Build configuration list for PBXProject "${APP_NAME}" */;
+ compatibilityVersion = "Xcode 12.0";
+ developmentRegion = en;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ Base,
+ );
+ mainGroup = EEEEEEEEEEEEEEEEEEEEEEEE;
+ productRefGroup = CCCCCCCCCCCCCCCCCCCCCCCC /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 3333333333333333333333AA /* ${APP_NAME} */,
+ );
+ };
+/* End PBXProject section */
+EOF
+
+# Add the rest of the file with correct FRAMEWORK_SEARCH_PATHS and tvOS settings
+cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF'
+/* Begin PBXResourcesBuildPhase section */
+ 6666666666666666666666AA /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 5555555555555555555555AA /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 33333333333333333333333 /* ContentView.swift in Sources */,
+ 11111111111111111111111 /* App.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ 9999999999999999999999AA /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ TVOS_DEPLOYMENT_TARGET = 15.0;
+ MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+ MTL_FAST_MATH = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = appletvos;
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ };
+ name = Debug;
+ };
+ AAAAAAAAAAAAAAAAAAAAABBB /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ TVOS_DEPLOYMENT_TARGET = 15.0;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ MTL_FAST_MATH = YES;
+ SDKROOT = appletvos;
+ SWIFT_COMPILATION_MODE = wholemodule;
+ SWIFT_OPTIMIZATION_LEVEL = "-O";
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+ BBBBBBBBBBBBBBBBBBBBBBCCC /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
+ CODE_SIGN_STYLE = Manual;
+ DEVELOPMENT_TEAM = "";
+ ENABLE_PREVIEWS = YES;
+ FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)";
+ INFOPLIST_FILE = "TVOSLlamaTest/Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = "org.ggml.TVOSLlamaTest";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = 3;
+ };
+ name = Debug;
+ };
+ CCCCCCCCCCCCCCCCCCCCCCDDD /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
+ CODE_SIGN_STYLE = Manual;
+ DEVELOPMENT_TEAM = "";
+ ENABLE_PREVIEWS = YES;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(PROJECT_DIR)",
+ );
+ INFOPLIST_FILE = "TVOSLlamaTest/Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = "org.ggml.TVOSLlamaTest";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = 3;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+EOF
+
+# Finish the project.pbxproj file
+cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF
+/* Begin XCConfigurationList section */
+ 8888888888888888888888AA /* Build configuration list for PBXProject "${APP_NAME}" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 9999999999999999999999AA /* Debug */,
+ AAAAAAAAAAAAAAAAAAAAABBB /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 4444444444444444444444AA /* Build configuration list for PBXNativeTarget "${APP_NAME}" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ BBBBBBBBBBBBBBBBBBBBBBCCC /* Debug */,
+ CCCCCCCCCCCCCCCCCCCCCCDDD /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 7777777777777777777777AA /* Project object */;
+}
+EOF
+
+# 2. Copy XCFramework to test project
+echo "Copying XCFramework to test project..."
+cp -R "${XCFRAMEWORK_PATH}" "${TEMP_DIR}/${APP_NAME}/"
+
+# 3. Build and archive the app
+echo "Building and archiving test app..."
+cd "${TEMP_DIR}/${APP_NAME}"
+
+# Create a simple xcscheme file to avoid xcodebuild scheme issues
+mkdir -p "${APP_NAME}.xcodeproj/xcshareddata/xcschemes"
+cat > "${APP_NAME}.xcodeproj/xcshareddata/xcschemes/${APP_NAME}.xcscheme" << EOF
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ LastUpgradeVersion = "1240"
+ version = "1.3">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "YES">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "YES"
+ buildForArchiving = "YES"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "3333333333333333333333AA"
+ BuildableName = "${APP_NAME}.app"
+ BlueprintName = "${APP_NAME}"
+ ReferencedContainer = "container:${APP_NAME}.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ buildConfiguration = "Debug"
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES">
+ <Testables>
+ </Testables>
+ </TestAction>
+ <LaunchAction
+ buildConfiguration = "Debug"
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ debugServiceExtension = "internal"
+ allowLocationSimulation = "YES">
+ <BuildableProductRunnable
+ runnableDebuggingMode = "0">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "3333333333333333333333AA"
+ BuildableName = "${APP_NAME}.app"
+ BlueprintName = "${APP_NAME}"
+ ReferencedContainer = "container:${APP_NAME}.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ </LaunchAction>
+ <ProfileAction
+ buildConfiguration = "Release"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ debugDocumentVersioning = "YES">
+ <BuildableProductRunnable
+ runnableDebuggingMode = "0">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "3333333333333333333333AA"
+ BuildableName = "${APP_NAME}.app"
+ BlueprintName = "${APP_NAME}"
+ ReferencedContainer = "container:${APP_NAME}.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Debug">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Release"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+</Scheme>
+EOF
+
+# Now use xcodebuild with an explicitly defined product name for tvOS
+xcodebuild -project "${APP_NAME}.xcodeproj" -scheme "${APP_NAME}" -sdk appletvos -configuration Release archive -archivePath "${ARCHIVE_PATH}" CODE_SIGN_IDENTITY="-" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO PRODUCT_NAME="${APP_NAME}" SWIFT_OPTIMIZATION_LEVEL="-Onone" -quiet
+
+# 4. Create IPA from archive
+echo "Creating IPA from archive..."
+mkdir -p "${TEMP_DIR}/Payload"
+cp -R "${ARCHIVE_PATH}/Products/Applications/${APP_NAME}.app" "${TEMP_DIR}/Payload/"
+
+# Check and log app structure before zipping
+echo "App structure:"
+ls -la "${TEMP_DIR}/Payload/${APP_NAME}.app/"
+echo "Frameworks:"
+ls -la "${TEMP_DIR}/Payload/${APP_NAME}.app/Frameworks/" 2>/dev/null || echo "No Frameworks directory found"
+
+cd "${TEMP_DIR}"
+zip -r "${IPA_PATH}" Payload
+
+# Check embedded provisioning profile
+echo "Checking provisioning profile (if any)..."
+PROVISIONING_PROFILE=$(find "${ARCHIVE_PATH}/Products/Applications/${APP_NAME}.app" -name "embedded.mobileprovision" 2>/dev/null)
+if [ -n "$PROVISIONING_PROFILE" ]; then
+ echo "Found embedded provisioning profile:"
+ security cms -D -i "$PROVISIONING_PROFILE" || echo "Unable to decode provisioning profile"
+else
+ echo "No embedded provisioning profile found (expected for ad-hoc builds)"
+fi
+
+# 5. Validate the IPA
+echo "Validating IPA..."
+VALIDATION_OUTPUT="${VALIDATION_DIR}/validation_output.txt"
+
+# Check if authentication credentials are provided
+AUTH_ARGS=""
+if [ -n "$APPLE_ID" ] && [ -n "$APPLE_PASSWORD" ]; then
+ echo "Using Apple ID authentication for validation..."
+ AUTH_ARGS="--username \"$APPLE_ID\" --password \"$APPLE_PASSWORD\""
+else
+ echo "No authentication credentials provided. Will perform basic validation."
+ echo "To use your personal developer account, you can run the script with:"
+ echo " APPLE_ID='your.email@example.com' APPLE_PASSWORD='your-app-specific-password' ./validate-tvos.sh"
+ echo "Note: You need to create an app-specific password at https://appleid.apple.com/account/manage"
+fi
+
+# Run validation with detailed output
+echo "Running validation with altool..."
+if [ -n "$AUTH_ARGS" ]; then
+ # Use eval to properly handle the quoted arguments
+ eval "xcrun altool --validate-app -f \"${IPA_PATH}\" --type tvos --output-format xml $AUTH_ARGS" 2>&1 | tee "${VALIDATION_OUTPUT}"
+else
+ xcrun altool --validate-app -f "${IPA_PATH}" --type tvos --output-format xml 2>&1 | tee "${VALIDATION_OUTPUT}"
+fi
+VALIDATION_RESULT=$?
+
+# Final validation result
+FINAL_VALIDATION_RESULT=0
+
+# Check if validation failed because the app isn't in App Store Connect
+if grep -q "No suitable application records were found" "${VALIDATION_OUTPUT}"; then
+ echo "⚠️ App Store Connect Warning: The app bundle identifier is not found in App Store Connect"
+ echo "This is expected for apps that haven't been registered in App Store Connect yet."
+ echo "This doesn't indicate a problem with the build or framework."
+
+ # Perform alternative validation
+ echo "Performing alternative validation checks..."
+
+ # Check if IPA was created successfully
+ if [ -f "${IPA_PATH}" ] && [ -s "${IPA_PATH}" ]; then
+ echo "✅ IPA file created successfully"
+ else
+ echo "❌ IPA file not created or empty"
+ FINAL_VALIDATION_RESULT=1
+ fi
+
+ # Check if app binary exists and is executable
+ if [ -f "${TEMP_DIR}/Payload/${APP_NAME}.app/${APP_NAME}" ] && [ -x "${TEMP_DIR}/Payload/${APP_NAME}.app/${APP_NAME}" ]; then
+ echo "✅ App binary exists and is executable"
+ else
+ echo "❌ App binary missing or not executable"
+ FINAL_VALIDATION_RESULT=1
+ fi
+
+ # Check if framework was properly embedded
+ if [ -d "${TEMP_DIR}/Payload/${APP_NAME}.app/Frameworks/llama.framework" ]; then
+ echo "✅ llama.framework properly embedded"
+ else
+ echo "❌ llama.framework not properly embedded"
+ FINAL_VALIDATION_RESULT=1
+ fi
+
+ # Check if framework binary exists
+ if [ -f "${TEMP_DIR}/Payload/${APP_NAME}.app/Frameworks/llama.framework/llama" ]; then
+ echo "✅ Framework binary exists"
+
+ # Further validate framework by checking architecture
+ ARCHS=$(lipo -info "${TEMP_DIR}/Payload/${APP_NAME}.app/Frameworks/llama.framework/llama" 2>/dev/null | grep -o "arm64\\|x86_64" | tr '\n' ' ')
+ if [ -n "$ARCHS" ]; then
+ echo "✅ Framework architecture(s): $ARCHS"
+ else
+ echo "⚠️ Could not determine framework architecture"
+ fi
+ else
+ echo "❌ Framework binary missing"
+ FINAL_VALIDATION_RESULT=1
+ fi
+
+ if [ $FINAL_VALIDATION_RESULT -eq 0 ]; then
+ echo "✅ Alternative validation PASSED: App built successfully with embedded framework"
+ else
+ echo "❌ Alternative validation FAILED: Issues found with the app or framework"
+ fi
+elif grep -q "You must specify authentication credentials" "${VALIDATION_OUTPUT}" && [ -z "$AUTH_ARGS" ]; then
+ echo "✅ tvOS Validation PASSED: IPA successfully validated"
+ echo "Results saved to ${VALIDATION_OUTPUT}"
+else
+ echo "❌ tvOS Validation FAILED: IPA validation found issues"
+ echo "See validation output at ${VALIDATION_OUTPUT}"
+ echo ""
+ echo "==== VALIDATION ERRORS ===="
+
+ # Try to extract specific errors from the output
+ if grep -q "Error" "${VALIDATION_OUTPUT}"; then
+ grep -A 5 "Error" "${VALIDATION_OUTPUT}"
+ else
+ # If no specific error found, show the whole log
+ cat "${VALIDATION_OUTPUT}"
+ fi
+
+ # Additional debugging: check IPA contents
+ echo ""
+ echo "==== IPA CONTENTS ===="
+ mkdir -p "${TEMP_DIR}/ipa_contents"
+ unzip -q "${IPA_PATH}" -d "${TEMP_DIR}/ipa_contents"
+ ls -la "${TEMP_DIR}/ipa_contents/Payload/${APP_NAME}.app/"
+
+ # Check for code signing issues
+ echo ""
+ echo "==== CODE SIGNING INFO ===="
+ codesign -vv -d "${TEMP_DIR}/ipa_contents/Payload/${APP_NAME}.app" 2>&1 || echo "Code signing verification failed"
+
+ # Check embedded frameworks
+ echo ""
+ echo "==== FRAMEWORK INFO ===="
+ ls -la "${TEMP_DIR}/ipa_contents/Payload/${APP_NAME}.app/Frameworks/" 2>/dev/null || echo "No Frameworks directory found"
+fi
+
+# Don't clean up on error to allow inspection
+if [ $FINAL_VALIDATION_RESULT -ne 0 ]; then
+ echo ""
+ echo "Temporary files kept for inspection at: ${TEMP_DIR}"
+ echo "===== tvOS Validation Process Failed ====="
+ exit 1
+fi
+
+# Clean up temporary files but keep build artifacts
+if [ $FINAL_VALIDATION_RESULT -eq 0 ]; then
+ echo "Cleaning up temporary files..."
+ #rm -rf "${TEMP_DIR}"
+fi
+
+echo "===== tvOS Validation Process Completed ====="
+exit $FINAL_VALIDATION_RESULT
--- /dev/null
+#!/bin/bash
+# validate-visionos.sh - Validate visionOS Application with embedded llama.xcframework using SwiftUI
+
+# Authentication options (optional) (can be set via environment variables)
+# To use: export APPLE_ID=your.email@example.com
+# export APPLE_PASSWORD=your-app-specific-password
+# ./validate-visionos.sh
+APPLE_ID=${APPLE_ID:-""}
+APPLE_PASSWORD=${APPLE_PASSWORD:-""}
+
+# Ensure the script exits on error
+set -e
+
+# Function to print usage instructions
+print_usage() {
+ echo "Usage: ./validate-visionos.sh [OPTIONS]"
+ echo ""
+ echo "Options:"
+ echo " --help Show this help message"
+ echo " --apple-id EMAIL Apple ID email for validation"
+ echo " --apple-password PWD App-specific password for Apple ID"
+ echo ""
+ echo "Environment variables:"
+ echo " APPLE_ID Apple ID email for validation"
+ echo " APPLE_PASSWORD App-specific password for Apple ID"
+ echo ""
+ echo "Notes:"
+ echo " - Command line options take precedence over environment variables"
+ echo " - Authentication is optional. If not provided, alternative validation will be performed"
+ echo " - For APPLE_PASSWORD, use an app-specific password generated at https://appleid.apple.com/account/manage"
+}
+
+# Parse command line arguments
+while [[ $# -gt 0 ]]; do
+ case $1 in
+ --help)
+ print_usage
+ exit 0
+ ;;
+ --apple-id)
+ APPLE_ID="$2"
+ shift 2
+ ;;
+ --apple-password)
+ APPLE_PASSWORD="$2"
+ shift 2
+ ;;
+ *)
+ echo "Unknown option: $1"
+ print_usage
+ exit 1
+ ;;
+ esac
+done
+
+# Function to clean up in case of error
+cleanup() {
+ # Don't clean up temp files on error to help with debugging
+ echo "===== visionOS Validation Process Failed ====="
+ exit 1
+}
+
+# Set up trap to call cleanup function on error
+trap cleanup ERR
+
+set -e # Exit on any error
+
+ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/../.." && pwd )"
+BUILD_DIR="${ROOT_DIR}/validation-builds/visionos"
+
+# Configuration
+APP_NAME="VisionOSLlamaTest"
+BUNDLE_ID="org.ggml.VisionOSLlamaTest"
+XCFRAMEWORK_PATH="${ROOT_DIR}/build-apple/llama.xcframework"
+TEMP_DIR="${BUILD_DIR}/temp"
+ARCHIVE_PATH="${BUILD_DIR}/${APP_NAME}.xcarchive"
+IPA_PATH="${BUILD_DIR}/${APP_NAME}.ipa"
+VALIDATION_DIR="${BUILD_DIR}/validation"
+
+# Create necessary directories
+mkdir -p "${BUILD_DIR}"
+mkdir -p "${TEMP_DIR}"
+mkdir -p "${VALIDATION_DIR}"
+
+echo "===== visionOS Validation Process Started ====="
+
+# 1. Create a simple test app project
+echo "Creating test visionOS app project..."
+mkdir -p "${TEMP_DIR}/${APP_NAME}/${APP_NAME}"
+cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Info.plist" << 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>${APP_NAME}</string>
+ <key>CFBundleIdentifier</key>
+ <string>${BUNDLE_ID}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>${APP_NAME}</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleVersion</key>
+ <string>1</string>
+</dict>
+</plist>
+EOF
+
+# Create SwiftUI app files
+mkdir -p "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Sources"
+
+# Create App.swift
+cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Sources/App.swift" << EOF
+import SwiftUI
+import llama
+
+@main
+struct LlamaTestApp: App {
+ var body: some Scene {
+ WindowGroup {
+ ContentView()
+ }
+ }
+}
+EOF
+
+# Create ContentView.swift with visionOS specific elements
+cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Sources/ContentView.swift" << EOF
+import SwiftUI
+import llama
+
+struct ContentView: View {
+ // Test that we can initialize a llama context params struct
+ let params = llama_context_default_params()
+
+ var body: some View {
+ VStack(spacing: 20) {
+ Text("Llama Framework Test on visionOS")
+ .font(.largeTitle)
+ .padding()
+
+ Text("llama_context_default_params() created successfully")
+ .font(.headline)
+ .multilineTextAlignment(.center)
+ .padding()
+
+ // Display some param values to confirm the framework is working
+ Text("n_ctx: \(params.n_ctx)")
+ .font(.body)
+
+ Text("n_batch: \(params.n_batch)")
+ .font(.body)
+
+ Spacer()
+ }
+ .padding()
+ .frame(width: 500, height: 400)
+ }
+}
+
+struct ContentView_Previews: PreviewProvider {
+ static var previews: some View {
+ ContentView()
+ }
+}
+EOF
+
+# Create project.pbxproj, fixing the framework search paths issues
+mkdir -p "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj"
+cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF'
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 54;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 11111111111111111111111 /* App.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22222222222222222222222; };
+ 33333333333333333333333 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44444444444444444444444; };
+ 55555555555555555555555 /* llama.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 66666666666666666666666; };
+ 77777777777777777777777 /* llama.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 66666666666666666666666; };
+/* End PBXBuildFile section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+ 88888888888888888888888 /* Embed Frameworks */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 10;
+ files = (
+ 77777777777777777777777 /* llama.xcframework in Embed Frameworks */,
+ );
+ name = "Embed Frameworks";
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+EOF
+
+# Continue with the project.pbxproj file, using the APP_NAME variable appropriately
+cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF
+ 99999999999999999999999 /* ${APP_NAME}.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "${APP_NAME}.app"; sourceTree = BUILT_PRODUCTS_DIR; };
+ 22222222222222222222222 /* App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App.swift; sourceTree = "<group>"; };
+ 44444444444444444444444 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
+ AAAAAAAAAAAAAAAAAAAAAAA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+ 66666666666666666666666 /* llama.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = llama.xcframework; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+EOF
+
+# Add the rest of the project file with fixed framework search paths
+cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF'
+/* Begin PBXFrameworksBuildPhase section */
+ BBBBBBBBBBBBBBBBBBBBBBBB /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 55555555555555555555555 /* llama.xcframework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+EOF
+
+# Continue with the project.pbxproj file, using the APP_NAME variable appropriately
+cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF
+ CCCCCCCCCCCCCCCCCCCCCCCC /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 99999999999999999999999 /* ${APP_NAME}.app */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+EOF
+
+cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF'
+ DDDDDDDDDDDDDDDDDDDDDDDD /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 66666666666666666666666 /* llama.xcframework */,
+ );
+ name = Frameworks;
+ sourceTree = "<group>";
+ };
+ EEEEEEEEEEEEEEEEEEEEEEEE = {
+ isa = PBXGroup;
+ children = (
+ FFFFFFFFFFFFFFFFFFFFFFFF /* VisionOSLlamaTest */,
+ CCCCCCCCCCCCCCCCCCCCCCCC /* Products */,
+ DDDDDDDDDDDDDDDDDDDDDDDD /* Frameworks */,
+ );
+ sourceTree = "<group>";
+ };
+ FFFFFFFFFFFFFFFFFFFFFFFF /* VisionOSLlamaTest */ = {
+ isa = PBXGroup;
+ children = (
+ 1111111111111111111111AA /* Sources */,
+ AAAAAAAAAAAAAAAAAAAAAAA /* Info.plist */,
+ );
+ path = "VisionOSLlamaTest";
+ sourceTree = "<group>";
+ };
+ 1111111111111111111111AA /* Sources */ = {
+ isa = PBXGroup;
+ children = (
+ 22222222222222222222222 /* App.swift */,
+ 44444444444444444444444 /* ContentView.swift */,
+ );
+ path = Sources;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+EOF
+
+# Continue with the project.pbxproj file, using the APP_NAME variable appropriately
+cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF
+/* Begin PBXNativeTarget section */
+ 3333333333333333333333AA /* ${APP_NAME} */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 4444444444444444444444AA /* Build configuration list for PBXNativeTarget "${APP_NAME}" */;
+ buildPhases = (
+ 5555555555555555555555AA /* Sources */,
+ BBBBBBBBBBBBBBBBBBBBBBBB /* Frameworks */,
+ 6666666666666666666666AA /* Resources */,
+ 88888888888888888888888 /* Embed Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "${APP_NAME}";
+ productName = "${APP_NAME}";
+ productReference = 99999999999999999999999 /* ${APP_NAME}.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 7777777777777777777777AA /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastSwiftUpdateCheck = 1510;
+ LastUpgradeCheck = 1510;
+ TargetAttributes = {
+ 3333333333333333333333AA = {
+ CreatedOnToolsVersion = 15.1;
+ };
+ };
+ };
+ buildConfigurationList = 8888888888888888888888AA /* Build configuration list for PBXProject "${APP_NAME}" */;
+ compatibilityVersion = "Xcode 15.0";
+ developmentRegion = en;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ Base,
+ );
+ mainGroup = EEEEEEEEEEEEEEEEEEEEEEEE;
+ productRefGroup = CCCCCCCCCCCCCCCCCCCCCCCC /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 3333333333333333333333AA /* ${APP_NAME} */,
+ );
+ };
+/* End PBXProject section */
+EOF
+
+# Add the rest of the file with correct FRAMEWORK_SEARCH_PATHS
+cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF'
+/* Begin PBXResourcesBuildPhase section */
+ 6666666666666666666666AA /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 5555555555555555555555AA /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 33333333333333333333333 /* ContentView.swift in Sources */,
+ 11111111111111111111111 /* App.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ 9999999999999999999999AA /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+ MTL_FAST_MATH = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = xros;
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ XROS_DEPLOYMENT_TARGET = 1.0;
+ };
+ name = Debug;
+ };
+ AAAAAAAAAAAAAAAAAAAAABBB /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ MTL_FAST_MATH = YES;
+ SDKROOT = xros;
+ SWIFT_COMPILATION_MODE = wholemodule;
+ SWIFT_OPTIMIZATION_LEVEL = "-O";
+ VALIDATE_PRODUCT = YES;
+ XROS_DEPLOYMENT_TARGET = 1.0;
+ };
+ name = Release;
+ };
+ BBBBBBBBBBBBBBBBBBBBBBCCC /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
+ CODE_SIGN_STYLE = Manual;
+ DEVELOPMENT_TEAM = "";
+ ENABLE_PREVIEWS = YES;
+ FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)";
+ INFOPLIST_FILE = "VisionOSLlamaTest/Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = "org.ggml.VisionOSLlamaTest";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ SUPPORTED_PLATFORMS = "xros xrsimulator";
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2,7";
+ };
+ name = Debug;
+ };
+ CCCCCCCCCCCCCCCCCCCCCCDDD /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
+ CODE_SIGN_STYLE = Manual;
+ DEVELOPMENT_TEAM = "";
+ ENABLE_PREVIEWS = YES;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(PROJECT_DIR)",
+ );
+ INFOPLIST_FILE = "VisionOSLlamaTest/Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = "org.ggml.VisionOSLlamaTest";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ SUPPORTED_PLATFORMS = "xros xrsimulator";
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2,7";
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+EOF
+
+# Finish the project.pbxproj file
+cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF
+/* Begin XCConfigurationList section */
+ 8888888888888888888888AA /* Build configuration list for PBXProject "${APP_NAME}" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 9999999999999999999999AA /* Debug */,
+ AAAAAAAAAAAAAAAAAAAAABBB /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 4444444444444444444444AA /* Build configuration list for PBXNativeTarget "${APP_NAME}" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ BBBBBBBBBBBBBBBBBBBBBBCCC /* Debug */,
+ CCCCCCCCCCCCCCCCCCCCCCDDD /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 7777777777777777777777AA /* Project object */;
+}
+EOF
+
+# 2. Copy XCFramework to test project
+echo "Copying XCFramework to test project..."
+cp -R "${XCFRAMEWORK_PATH}" "${TEMP_DIR}/${APP_NAME}/"
+
+# 3. Build and archive the app
+echo "Building and archiving test app..."
+cd "${TEMP_DIR}/${APP_NAME}"
+
+# Create a simple xcscheme file to avoid xcodebuild scheme issues
+mkdir -p "${APP_NAME}.xcodeproj/xcshareddata/xcschemes"
+cat > "${APP_NAME}.xcodeproj/xcshareddata/xcschemes/${APP_NAME}.xcscheme" << EOF
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ LastUpgradeVersion = "1510"
+ version = "1.3">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "YES">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "YES"
+ buildForArchiving = "YES"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "3333333333333333333333AA"
+ BuildableName = "${APP_NAME}.app"
+ BlueprintName = "${APP_NAME}"
+ ReferencedContainer = "container:${APP_NAME}.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ buildConfiguration = "Debug"
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES">
+ <Testables>
+ </Testables>
+ </TestAction>
+ <LaunchAction
+ buildConfiguration = "Debug"
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ debugServiceExtension = "internal"
+ allowLocationSimulation = "YES">
+ <BuildableProductRunnable
+ runnableDebuggingMode = "0">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "3333333333333333333333AA"
+ BuildableName = "${APP_NAME}.app"
+ BlueprintName = "${APP_NAME}"
+ ReferencedContainer = "container:${APP_NAME}.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ </LaunchAction>
+ <ProfileAction
+ buildConfiguration = "Release"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ debugDocumentVersioning = "YES">
+ <BuildableProductRunnable
+ runnableDebuggingMode = "0">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "3333333333333333333333AA"
+ BuildableName = "${APP_NAME}.app"
+ BlueprintName = "${APP_NAME}"
+ ReferencedContainer = "container:${APP_NAME}.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Debug">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Release"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+</Scheme>
+EOF
+
+# Now use xcodebuild with an explicitly defined product name for visionOS
+xcodebuild -project "${APP_NAME}.xcodeproj" -scheme "${APP_NAME}" -sdk xros -configuration Release archive -archivePath "${ARCHIVE_PATH}" CODE_SIGN_IDENTITY="-" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO PRODUCT_NAME="${APP_NAME}" SWIFT_OPTIMIZATION_LEVEL="-Onone" -quiet
+
+# 4. Create IPA from archive
+echo "Creating IPA from archive..."
+mkdir -p "${TEMP_DIR}/Payload"
+cp -R "${ARCHIVE_PATH}/Products/Applications/${APP_NAME}.app" "${TEMP_DIR}/Payload/"
+
+# Check and log app structure before zipping
+echo "App structure:"
+ls -la "${TEMP_DIR}/Payload/${APP_NAME}.app/"
+echo "Frameworks:"
+ls -la "${TEMP_DIR}/Payload/${APP_NAME}.app/Frameworks/" 2>/dev/null || echo "No Frameworks directory found"
+
+cd "${TEMP_DIR}"
+zip -r "${IPA_PATH}" Payload
+
+# Check embedded provisioning profile
+echo "Checking provisioning profile (if any)..."
+PROVISIONING_PROFILE=$(find "${ARCHIVE_PATH}/Products/Applications/${APP_NAME}.app" -name "embedded.mobileprovision" 2>/dev/null)
+if [ -n "$PROVISIONING_PROFILE" ]; then
+ echo "Found embedded provisioning profile:"
+ security cms -D -i "$PROVISIONING_PROFILE" || echo "Unable to decode provisioning profile"
+else
+ echo "No embedded provisioning profile found (expected for ad-hoc builds)"
+fi
+
+# 5. Validate the IPA
+echo "Validating IPA..."
+VALIDATION_OUTPUT="${VALIDATION_DIR}/validation_output.txt"
+
+# Check if authentication credentials are provided
+AUTH_ARGS=""
+if [ -n "$APPLE_ID" ] && [ -n "$APPLE_PASSWORD" ]; then
+ echo "Using Apple ID authentication for validation..."
+ AUTH_ARGS="--username \"$APPLE_ID\" --password \"$APPLE_PASSWORD\""
+else
+ echo "No authentication credentials provided. Will perform basic validation."
+ echo "To use your personal developer account, you can run the script with:"
+ echo " APPLE_ID='your.email@example.com' APPLE_PASSWORD='your-app-specific-password' ./validate-visionos.sh"
+ echo "Note: You need to create an app-specific password at https://appleid.apple.com/account/manage"
+fi
+
+# Run validation with detailed output
+echo "Running validation with altool..."
+if [ -n "$AUTH_ARGS" ]; then
+ # Use eval to properly handle the quoted arguments
+ eval "xcrun altool --validate-app -f \"${IPA_PATH}\" --type visionos --output-format xml $AUTH_ARGS" 2>&1 | tee "${VALIDATION_OUTPUT}"
+else
+ xcrun altool --validate-app -f "${IPA_PATH}" --type visionos --output-format xml 2>&1 | tee "${VALIDATION_OUTPUT}"
+fi
+VALIDATION_RESULT=$?
+
+# Final validation result
+FINAL_VALIDATION_RESULT=0
+
+# Check if validation failed because the app isn't in App Store Connect
+if grep -q "No suitable application records were found" "${VALIDATION_OUTPUT}"; then
+ echo "⚠️ App Store Connect Warning: The app bundle identifier is not found in App Store Connect"
+ echo "This is expected for apps that haven't been registered in App Store Connect yet."
+ echo "This doesn't indicate a problem with the build or framework."
+
+ # Perform alternative validation
+ echo "Performing alternative validation checks..."
+
+ # Check if IPA was created successfully
+ if [ -f "${IPA_PATH}" ] && [ -s "${IPA_PATH}" ]; then
+ echo "✅ IPA file created successfully"
+ else
+ echo "❌ IPA file not created or empty"
+ FINAL_VALIDATION_RESULT=1
+ fi
+
+ # Check if app binary exists and is executable
+ if [ -f "${TEMP_DIR}/Payload/${APP_NAME}.app/${APP_NAME}" ] && [ -x "${TEMP_DIR}/Payload/${APP_NAME}.app/${APP_NAME}" ]; then
+ echo "✅ App binary exists and is executable"
+ else
+ echo "❌ App binary missing or not executable"
+ FINAL_VALIDATION_RESULT=1
+ fi
+
+ # Check if framework was properly embedded
+ if [ -d "${TEMP_DIR}/Payload/${APP_NAME}.app/Frameworks/llama.framework" ]; then
+ echo "✅ llama.framework properly embedded"
+ else
+ echo "❌ llama.framework not properly embedded"
+ FINAL_VALIDATION_RESULT=1
+ fi
+
+ # Check if framework binary exists
+ if [ -f "${TEMP_DIR}/Payload/${APP_NAME}.app/Frameworks/llama.framework/llama" ]; then
+ echo "✅ Framework binary exists"
+
+ # Further validate framework by checking architecture
+ ARCHS=$(lipo -info "${TEMP_DIR}/Payload/${APP_NAME}.app/Frameworks/llama.framework/llama" 2>/dev/null | grep -o "arm64\\|x86_64" | tr '\n' ' ')
+ if [ -n "$ARCHS" ]; then
+ echo "✅ Framework architecture(s): $ARCHS"
+ else
+ echo "⚠️ Could not determine framework architecture"
+ fi
+ else
+ echo "❌ Framework binary missing"
+ FINAL_VALIDATION_RESULT=1
+ fi
+
+ if [ $FINAL_VALIDATION_RESULT -eq 0 ]; then
+ echo "✅ Alternative validation PASSED: App built successfully with embedded framework"
+ else
+ echo "❌ Alternative validation FAILED: Issues found with the app or framework"
+ fi
+elif grep -q "You must specify authentication credentials" "${VALIDATION_OUTPUT}" && [ -z "$AUTH_ARGS" ]; then
+ echo "✅ visionOS Validation PASSED: IPA successfully validated"
+ echo "Results saved to ${VALIDATION_OUTPUT}"
+else
+ echo "❌ visionOS Validation FAILED: IPA validation found issues"
+ echo "See validation output at ${VALIDATION_OUTPUT}"
+ echo ""
+ echo "==== VALIDATION ERRORS ===="
+
+ # Try to extract specific errors from the output
+ if grep -q "Error" "${VALIDATION_OUTPUT}"; then
+ grep -A 5 "Error" "${VALIDATION_OUTPUT}"
+ else
+ # If no specific error found, show the whole log
+ cat "${VALIDATION_OUTPUT}"
+ fi
+
+ # Additional debugging: check IPA contents
+ echo ""
+ echo "==== IPA CONTENTS ===="
+ mkdir -p "${TEMP_DIR}/ipa_contents"
+ unzip -q "${IPA_PATH}" -d "${TEMP_DIR}/ipa_contents"
+ ls -la "${TEMP_DIR}/ipa_contents/Payload/${APP_NAME}.app/"
+
+ # Check for code signing issues
+ echo ""
+ echo "==== CODE SIGNING INFO ===="
+ codesign -vv -d "${TEMP_DIR}/ipa_contents/Payload/${APP_NAME}.app" 2>&1 || echo "Code signing verification failed"
+
+ # Check embedded frameworks
+ echo ""
+ echo "==== FRAMEWORK INFO ===="
+ ls -la "${TEMP_DIR}/ipa_contents/Payload/${APP_NAME}.app/Frameworks/" 2>/dev/null || echo "No Frameworks directory found"
+fi
+
+# Don't clean up on error to allow inspection
+if [ $FINAL_VALIDATION_RESULT -ne 0 ]; then
+ echo ""
+ echo "Temporary files kept for inspection at: ${TEMP_DIR}"
+ echo "===== visionOS Validation Process Failed ====="
+ exit 1
+fi
+
+# Clean up temporary files but keep build artifacts
+if [ $FINAL_VALIDATION_RESULT -eq 0 ]; then
+ echo "Cleaning up temporary files..."
+ #rm -rf "${TEMP_DIR}"
+fi
+
+echo "===== visionOS Validation Process Completed ====="
+exit $FINAL_VALIDATION_RESULT
+++ /dev/null
-../ggml/include/ggml-alloc.h
\ No newline at end of file
+++ /dev/null
-../ggml/include/ggml-backend.h
\ No newline at end of file
+++ /dev/null
-../ggml/include/ggml-cpp.h
\ No newline at end of file
+++ /dev/null
-../ggml/include/ggml-cpu.h
\ No newline at end of file
+++ /dev/null
-../ggml/include/ggml-metal.h
\ No newline at end of file
+++ /dev/null
-../ggml/include/ggml.h
\ No newline at end of file
+++ /dev/null
-../include/llama.h
\ No newline at end of file
#include <io.h>
#endif
+#if defined(__APPLE__)
+#include <TargetConditionals.h>
+#endif
+
// TODO: consider moving to llama-impl.h if needed in more places
#if defined(_WIN32)
static std::string llama_format_win_err(DWORD err) {
char* errmsg = std::strerror(errno);
bool suggest = (errno == ENOMEM);
-
+#if defined(TARGET_OS_VISION) || defined(TARGET_OS_TV)
+ // visionOS/tvOS dont't support RLIMIT_MEMLOCK
+ // Skip resource limit checks on visionOS/tvOS
+ suggest = false;
+#else
struct rlimit lock_limit;
if (suggest && getrlimit(RLIMIT_MEMLOCK, &lock_limit)) {
suggest = false;
if (suggest && (lock_limit.rlim_max > lock_limit.rlim_cur + size)) {
suggest = false;
}
+#endif
LLAMA_LOG_WARN("warning: failed to mlock %zu-byte buffer (after previously locking %zu bytes): %s\n%s",
size, this->size, errmsg, suggest ? MLOCK_SUGGESTION : "");