snapshot of https://github.com/ggml-org/whisper.cpp.git @ da54572229bcf64ba367d96c7ef15770376c4280 (2026-09-15)
Some checks failed
Bindings Tests (Go) / ubuntu-22 (push) Failing after 31s
CI (sycl) / ubuntu-22-cmake-sycl (linux/arm/v7, icx, icpx, ON) (push) Failing after 3s
CI (sycl) / ubuntu-22-cmake-sycl (linux/ppc64le, icx, icpx, ON) (push) Failing after 2s
CI (sycl) / ubuntu-22-cmake-sycl-fp16 (linux/amd64, icx, icpx, ON) (push) Failing after 3s
CI (sycl) / ubuntu-22-cmake-sycl-fp16 (linux/arm/v7, icx, icpx, ON) (push) Failing after 3s
CI (sycl) / ubuntu-22-cmake-sycl-fp16 (linux/arm64, icx, icpx, ON) (push) Failing after 3s
CI (sycl) / ubuntu-22-cmake-sycl-fp16 (linux/ppc64le, icx, icpx, ON) (push) Failing after 3s
CI (vad) / vad (push) Failing after 3s
CI (wasm) / emscripten (Release) (push) Failing after 4s
Bindings Tests (Ruby) / ubuntu-22 (push) Failing after 37s
CI (android) / android (push) Failing after 16s
CI (android) / android_java (push) Failing after 3s
CI (clang) / ubuntu-22-clang (linux/amd64, Debug) (push) Failing after 3s
CI (clang) / ubuntu-22-clang (linux/amd64, Release) (push) Failing after 2s
CI (clang) / ubuntu-22-clang (linux/ppc64le, Debug) (push) Failing after 3s
CI (clang) / ubuntu-22-clang (linux/ppc64le, Release) (push) Failing after 3s
CI (cpu) / ggml-ci-x64-cpu-low-perf (push) Failing after 3s
CI (cpu) / ggml-ci-x64-cpu-high-perf (push) Failing after 2s
CI (gcc) / ubuntu-22-gcc (linux/amd64, Debug) (push) Failing after 3s
CI (gcc) / ubuntu-22-gcc (linux/amd64, Release) (push) Failing after 3s
CI (gcc) / ubuntu-22-gcc (linux/ppc64le, Debug) (push) Failing after 3s
CI (gcc) / ubuntu-22-gcc (linux/ppc64le, Release) (push) Failing after 4s
CI (gcc) / ubuntu-22-gcc-arm-v7 (linux/arm/v7, Debug) (push) Failing after 3s
CI (gcc) / ubuntu-22-gcc-arm-v7 (linux/arm/v7, Release) (push) Failing after 3s
CI (quantize) / quantize (push) Failing after 3s
CI (sanitize) / ubuntu-22-gcc-sanitized (ADDRESS) (push) Failing after 3s
CI (sanitize) / ubuntu-22-gcc-sanitized (THREAD) (push) Failing after 3s
CI (sanitize) / ubuntu-22-gcc-sanitized (UNDEFINED) (push) Failing after 2s
CI (sycl) / ubuntu-22-cmake-sycl (linux/amd64, icx, icpx, ON) (push) Failing after 3s
CI (sycl) / ubuntu-22-cmake-sycl (linux/arm64, icx, icpx, ON) (push) Failing after 3s
Examples WASM / deploy-wasm-github-pages (push) Failing after 3s
Examples Tests / addon_node-ubuntu-22 (20.x) (push) Failing after 3s
Examples Tests / addon_node-ubuntu-22 (22.x) (push) Failing after 2s
CI (coreml) / coreml-base-en (push) Has been cancelled
CI (self-hosted) / gpu-vulkan (push) Has been cancelled
CI (self-hosted) / npu-amd-windows (push) Has been cancelled
CI (self-hosted) / gpu-vulkan-nvidia-cm2 (push) Has been cancelled
CI (clang) / ubuntu-22-clang-arm64 (Debug) (push) Has been cancelled
CI (clang) / ubuntu-22-clang-arm64 (Release) (push) Has been cancelled
CI (self-hosted) / gpu-cuda (push) Has been cancelled
CI (self-hosted) / gpu-vulkan-nvidia-cm (push) Has been cancelled
CI (cpu) / ggml-ci-arm64-cpu-low-perf (push) Has been cancelled
CI (cpu) / ggml-ci-arm64-cpu-high-perf (push) Has been cancelled
CI (cpu) / ggml-ci-arm64-cpu-high-perf-sve (push) Has been cancelled
CI (freebsd) / freeBSD-latest (push) Has been cancelled
CI (self-hosted) / gpu-metal (push) Has been cancelled
CI (gcc) / ubuntu-22-gcc-arm64 (Debug) (push) Has been cancelled
CI (gcc) / ubuntu-22-gcc-arm64 (Release) (push) Has been cancelled
CI (macOS) / macOS-latest (generic/platform=iOS) (push) Has been cancelled
CI (macOS) / macOS-latest (generic/platform=macOS) (push) Has been cancelled
CI (macOS) / macOS-latest (generic/platform=tvOS) (push) Has been cancelled
CI (self-hosted) / npu-amd-linux (push) Has been cancelled
CI (windows) / windows-msys2 (Release, clang, clang-x86_64, CLANG64) (push) Has been cancelled
CI (windows) / windows-msys2 (Release, gcc, ucrt-x86_64, UCRT64) (push) Has been cancelled
Publish Docker image / Push Docker image to Docker Hub (map[dockerfile:.devops/main-cuda.Dockerfile platform:linux/amd64 runs_on:ubuntu-24.04 tag:main-cuda]) (push) Has been cancelled
Publish Docker image / Push Docker image to Docker Hub (map[dockerfile:.devops/main-intel.Dockerfile platform:linux/amd64 runs_on:ubuntu-24.04 tag:main-intel]) (push) Has been cancelled
Publish Docker image / Push Docker image to Docker Hub (map[dockerfile:.devops/main-musa.Dockerfile platform:linux/amd64 runs_on:ubuntu-24.04 tag:main-musa]) (push) Has been cancelled
Publish Docker image / Push Docker image to Docker Hub (map[dockerfile:.devops/main-vulkan.Dockerfile platform:linux/amd64 runs_on:ubuntu-24.04 tag:main-vulkan]) (push) Has been cancelled
Publish Docker image / Push Docker image to Docker Hub (map[dockerfile:.devops/main-vulkan.Dockerfile platform:linux/arm64 runs_on:ubuntu-24.04-arm tag:main-vulkan-arm64]) (push) Has been cancelled
Publish Docker image / Push Docker image to Docker Hub (map[dockerfile:.devops/main.Dockerfile platform:linux/amd64 runs_on:ubuntu-24.04 tag:main]) (push) Has been cancelled
Publish Docker image / Push Docker image to Docker Hub (map[dockerfile:.devops/main.Dockerfile platform:linux/arm64 runs_on:ubuntu-24.04-arm tag:main-arm64]) (push) Has been cancelled
Mark inactive issues stale / mark-issues (push) Failing after 1s
Some checks failed
Bindings Tests (Go) / ubuntu-22 (push) Failing after 31s
CI (sycl) / ubuntu-22-cmake-sycl (linux/arm/v7, icx, icpx, ON) (push) Failing after 3s
CI (sycl) / ubuntu-22-cmake-sycl (linux/ppc64le, icx, icpx, ON) (push) Failing after 2s
CI (sycl) / ubuntu-22-cmake-sycl-fp16 (linux/amd64, icx, icpx, ON) (push) Failing after 3s
CI (sycl) / ubuntu-22-cmake-sycl-fp16 (linux/arm/v7, icx, icpx, ON) (push) Failing after 3s
CI (sycl) / ubuntu-22-cmake-sycl-fp16 (linux/arm64, icx, icpx, ON) (push) Failing after 3s
CI (sycl) / ubuntu-22-cmake-sycl-fp16 (linux/ppc64le, icx, icpx, ON) (push) Failing after 3s
CI (vad) / vad (push) Failing after 3s
CI (wasm) / emscripten (Release) (push) Failing after 4s
Bindings Tests (Ruby) / ubuntu-22 (push) Failing after 37s
CI (android) / android (push) Failing after 16s
CI (android) / android_java (push) Failing after 3s
CI (clang) / ubuntu-22-clang (linux/amd64, Debug) (push) Failing after 3s
CI (clang) / ubuntu-22-clang (linux/amd64, Release) (push) Failing after 2s
CI (clang) / ubuntu-22-clang (linux/ppc64le, Debug) (push) Failing after 3s
CI (clang) / ubuntu-22-clang (linux/ppc64le, Release) (push) Failing after 3s
CI (cpu) / ggml-ci-x64-cpu-low-perf (push) Failing after 3s
CI (cpu) / ggml-ci-x64-cpu-high-perf (push) Failing after 2s
CI (gcc) / ubuntu-22-gcc (linux/amd64, Debug) (push) Failing after 3s
CI (gcc) / ubuntu-22-gcc (linux/amd64, Release) (push) Failing after 3s
CI (gcc) / ubuntu-22-gcc (linux/ppc64le, Debug) (push) Failing after 3s
CI (gcc) / ubuntu-22-gcc (linux/ppc64le, Release) (push) Failing after 4s
CI (gcc) / ubuntu-22-gcc-arm-v7 (linux/arm/v7, Debug) (push) Failing after 3s
CI (gcc) / ubuntu-22-gcc-arm-v7 (linux/arm/v7, Release) (push) Failing after 3s
CI (quantize) / quantize (push) Failing after 3s
CI (sanitize) / ubuntu-22-gcc-sanitized (ADDRESS) (push) Failing after 3s
CI (sanitize) / ubuntu-22-gcc-sanitized (THREAD) (push) Failing after 3s
CI (sanitize) / ubuntu-22-gcc-sanitized (UNDEFINED) (push) Failing after 2s
CI (sycl) / ubuntu-22-cmake-sycl (linux/amd64, icx, icpx, ON) (push) Failing after 3s
CI (sycl) / ubuntu-22-cmake-sycl (linux/arm64, icx, icpx, ON) (push) Failing after 3s
Examples WASM / deploy-wasm-github-pages (push) Failing after 3s
Examples Tests / addon_node-ubuntu-22 (20.x) (push) Failing after 3s
Examples Tests / addon_node-ubuntu-22 (22.x) (push) Failing after 2s
CI (coreml) / coreml-base-en (push) Has been cancelled
CI (self-hosted) / gpu-vulkan (push) Has been cancelled
CI (self-hosted) / npu-amd-windows (push) Has been cancelled
CI (self-hosted) / gpu-vulkan-nvidia-cm2 (push) Has been cancelled
CI (clang) / ubuntu-22-clang-arm64 (Debug) (push) Has been cancelled
CI (clang) / ubuntu-22-clang-arm64 (Release) (push) Has been cancelled
CI (self-hosted) / gpu-cuda (push) Has been cancelled
CI (self-hosted) / gpu-vulkan-nvidia-cm (push) Has been cancelled
CI (cpu) / ggml-ci-arm64-cpu-low-perf (push) Has been cancelled
CI (cpu) / ggml-ci-arm64-cpu-high-perf (push) Has been cancelled
CI (cpu) / ggml-ci-arm64-cpu-high-perf-sve (push) Has been cancelled
CI (freebsd) / freeBSD-latest (push) Has been cancelled
CI (self-hosted) / gpu-metal (push) Has been cancelled
CI (gcc) / ubuntu-22-gcc-arm64 (Debug) (push) Has been cancelled
CI (gcc) / ubuntu-22-gcc-arm64 (Release) (push) Has been cancelled
CI (macOS) / macOS-latest (generic/platform=iOS) (push) Has been cancelled
CI (macOS) / macOS-latest (generic/platform=macOS) (push) Has been cancelled
CI (macOS) / macOS-latest (generic/platform=tvOS) (push) Has been cancelled
CI (self-hosted) / npu-amd-linux (push) Has been cancelled
CI (windows) / windows-msys2 (Release, clang, clang-x86_64, CLANG64) (push) Has been cancelled
CI (windows) / windows-msys2 (Release, gcc, ucrt-x86_64, UCRT64) (push) Has been cancelled
Publish Docker image / Push Docker image to Docker Hub (map[dockerfile:.devops/main-cuda.Dockerfile platform:linux/amd64 runs_on:ubuntu-24.04 tag:main-cuda]) (push) Has been cancelled
Publish Docker image / Push Docker image to Docker Hub (map[dockerfile:.devops/main-intel.Dockerfile platform:linux/amd64 runs_on:ubuntu-24.04 tag:main-intel]) (push) Has been cancelled
Publish Docker image / Push Docker image to Docker Hub (map[dockerfile:.devops/main-musa.Dockerfile platform:linux/amd64 runs_on:ubuntu-24.04 tag:main-musa]) (push) Has been cancelled
Publish Docker image / Push Docker image to Docker Hub (map[dockerfile:.devops/main-vulkan.Dockerfile platform:linux/amd64 runs_on:ubuntu-24.04 tag:main-vulkan]) (push) Has been cancelled
Publish Docker image / Push Docker image to Docker Hub (map[dockerfile:.devops/main-vulkan.Dockerfile platform:linux/arm64 runs_on:ubuntu-24.04-arm tag:main-vulkan-arm64]) (push) Has been cancelled
Publish Docker image / Push Docker image to Docker Hub (map[dockerfile:.devops/main.Dockerfile platform:linux/amd64 runs_on:ubuntu-24.04 tag:main]) (push) Has been cancelled
Publish Docker image / Push Docker image to Docker Hub (map[dockerfile:.devops/main.Dockerfile platform:linux/arm64 runs_on:ubuntu-24.04-arm tag:main-arm64]) (push) Has been cancelled
Mark inactive issues stale / mark-issues (push) Failing after 1s
This commit is contained in:
5
scripts/apple/validate-apps.sh
Executable file
5
scripts/apple/validate-apps.sh
Executable file
@@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
./scripts/apple/validate-ios.sh
|
||||
./scripts/apple/validate-macos.sh
|
||||
./scripts/apple/validate-visionos.sh
|
||||
./scripts/apple/validate-tvos.sh
|
||||
817
scripts/apple/validate-ios.sh
Executable file
817
scripts/apple/validate-ios.sh
Executable file
@@ -0,0 +1,817 @@
|
||||
#!/bin/bash
|
||||
# validate-ios.sh - Validate iOS Application with embedded whisper.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="iOSWhisperTest"
|
||||
BUNDLE_ID="org.ggml.iOSWhisperTest"
|
||||
XCFRAMEWORK_PATH="${ROOT_DIR}/build-apple/whisper.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 whisper
|
||||
|
||||
@main
|
||||
struct WhisperTestApp: 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 whisper
|
||||
|
||||
struct ContentView: View {
|
||||
// Test that we can initialize a whisper context params struct
|
||||
let params = whisper_context_default_params()
|
||||
|
||||
var body: some View {
|
||||
VStack(spacing: 20) {
|
||||
Text("Whisper Framework Test")
|
||||
.font(.largeTitle)
|
||||
.padding()
|
||||
|
||||
Text("whisper_context_default_params() created successfully")
|
||||
.font(.headline)
|
||||
.multilineTextAlignment(.center)
|
||||
.padding()
|
||||
|
||||
// Display some param values to confirm the framework is working
|
||||
Text("dtw_n_top: \(params.dtw_n_top)")
|
||||
.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 /* whisper.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 66666666666666666666666; };
|
||||
77777777777777777777777 /* whisper.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 /* whisper.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 /* whisper.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = whisper.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 /* whisper.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 /* whisper.xcframework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
EEEEEEEEEEEEEEEEEEEEEEEE = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
FFFFFFFFFFFFFFFFFFFFFFFF /* iOSWhisperTest */,
|
||||
CCCCCCCCCCCCCCCCCCCCCCCC /* Products */,
|
||||
DDDDDDDDDDDDDDDDDDDDDDDD /* Frameworks */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
FFFFFFFFFFFFFFFFFFFFFFFF /* iOSWhisperTest */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
1111111111111111111111AA /* Sources */,
|
||||
AAAAAAAAAAAAAAAAAAAAAAA /* Info.plist */,
|
||||
);
|
||||
path = "iOSWhisperTest";
|
||||
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 = "iOSWhisperTest/Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.ggml.iOSWhisperTest";
|
||||
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 = "iOSWhisperTest/Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.ggml.iOSWhisperTest";
|
||||
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/whisper.framework" ]; then
|
||||
echo "✅ whisper.framework properly embedded"
|
||||
else
|
||||
echo "❌ whisper.framework not properly embedded"
|
||||
FINAL_VALIDATION_RESULT=1
|
||||
fi
|
||||
|
||||
# Check if framework binary exists
|
||||
if [ -f "${TEMP_DIR}/Payload/${APP_NAME}.app/Frameworks/whisper.framework/whisper" ]; then
|
||||
echo "✅ Framework binary exists"
|
||||
|
||||
# Further validate framework by checking architecture
|
||||
ARCHS=$(lipo -info "${TEMP_DIR}/Payload/${APP_NAME}.app/Frameworks/whisper.framework/whisper" 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
|
||||
778
scripts/apple/validate-macos.sh
Executable file
778
scripts/apple/validate-macos.sh
Executable file
@@ -0,0 +1,778 @@
|
||||
#!/bin/bash
|
||||
# validate-macos.sh - Validate macOS Application with embedded whisper.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="MacOSWhisperTest"
|
||||
BUNDLE_ID="org.ggml.MacOSWhisperTest"
|
||||
XCFRAMEWORK_PATH="${ROOT_DIR}/build-apple/whisper.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 whisper
|
||||
|
||||
@main
|
||||
struct WhisperTestApp: 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 whisper
|
||||
|
||||
struct ContentView: View {
|
||||
// Test that we can initialize a whisper context params struct
|
||||
let params = whisper_context_default_params()
|
||||
|
||||
var body: some View {
|
||||
VStack(spacing: 20) {
|
||||
Text("Whisper Framework Test on macOS")
|
||||
.font(.largeTitle)
|
||||
.padding()
|
||||
|
||||
Text("whisper_context_default_params() created successfully")
|
||||
.font(.headline)
|
||||
.multilineTextAlignment(.center)
|
||||
.padding()
|
||||
|
||||
// Display some param values to confirm the framework is working
|
||||
Text("dtw_n_top: \(params.dtw_n_top)")
|
||||
.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 /* whisper.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 66666666666666666666666; };
|
||||
77777777777777777777777 /* whisper.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 /* whisper.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 /* whisper.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = whisper.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 /* whisper.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 /* whisper.xcframework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
EEEEEEEEEEEEEEEEEEEEEEEE = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
FFFFFFFFFFFFFFFFFFFFFFFF /* MacOSWhisperTest */,
|
||||
CCCCCCCCCCCCCCCCCCCCCCCC /* Products */,
|
||||
DDDDDDDDDDDDDDDDDDDDDDDD /* Frameworks */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
FFFFFFFFFFFFFFFFFFFFFFFF /* MacOSWhisperTest */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
1111111111111111111111AA /* Sources */,
|
||||
AAAAAAAAAAAAAAAAAAAAAAA /* Info.plist */,
|
||||
);
|
||||
path = "MacOSWhisperTest";
|
||||
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 = "MacOSWhisperTest/Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.ggml.MacOSWhisperTest";
|
||||
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 = "MacOSWhisperTest/Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.ggml.MacOSWhisperTest";
|
||||
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/whisper.framework" ]; then
|
||||
echo "✅ whisper.framework properly embedded"
|
||||
else
|
||||
echo "❌ whisper.framework not properly embedded"
|
||||
FINAL_VALIDATION_RESULT=1
|
||||
fi
|
||||
|
||||
# Check if framework binary exists
|
||||
if [ -f "${APP_PATH}/Contents/Frameworks/whisper.framework/Versions/A/whisper" ]; then
|
||||
echo "✅ Framework binary exists"
|
||||
|
||||
# Further validate framework by checking architecture
|
||||
ARCHS=$(lipo -info "${APP_PATH}/Contents/Frameworks/whisper.framework/Versions/A/whisper" 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
|
||||
810
scripts/apple/validate-tvos.sh
Executable file
810
scripts/apple/validate-tvos.sh
Executable file
@@ -0,0 +1,810 @@
|
||||
#!/bin/bash
|
||||
# validate-tvos.sh - Validate tvOS Application with embedded whisper.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="TVOSWhisperTest"
|
||||
BUNDLE_ID="org.ggml.TVOSWhisperTest"
|
||||
XCFRAMEWORK_PATH="${ROOT_DIR}/build-apple/whisper.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 whisper
|
||||
|
||||
@main
|
||||
struct WhisperTestApp: 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 whisper
|
||||
|
||||
struct ContentView: View {
|
||||
// Test that we can initialize a whisper context params struct
|
||||
let params = whisper_context_default_params()
|
||||
|
||||
var body: some View {
|
||||
VStack(spacing: 40) {
|
||||
Text("Whisper Framework Test on tvOS")
|
||||
.font(.largeTitle)
|
||||
.padding()
|
||||
|
||||
Text("whisper_context_default_params() created successfully")
|
||||
.font(.headline)
|
||||
.multilineTextAlignment(.center)
|
||||
.padding()
|
||||
|
||||
// Display some param values to confirm the framework is working
|
||||
Text("dtw_n_top: \(params.dtw_n_top)")
|
||||
.font(.body)
|
||||
|
||||
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 /* whisper.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 66666666666666666666666; };
|
||||
77777777777777777777777 /* whisper.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 /* whisper.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 /* whisper.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = whisper.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 /* whisper.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 /* whisper.xcframework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
EEEEEEEEEEEEEEEEEEEEEEEE = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
FFFFFFFFFFFFFFFFFFFFFFFF /* TVOSWhisperTest */,
|
||||
CCCCCCCCCCCCCCCCCCCCCCCC /* Products */,
|
||||
DDDDDDDDDDDDDDDDDDDDDDDD /* Frameworks */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
FFFFFFFFFFFFFFFFFFFFFFFF /* TVOSWhisperTest */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
1111111111111111111111AA /* Sources */,
|
||||
AAAAAAAAAAAAAAAAAAAAAAA /* Info.plist */,
|
||||
);
|
||||
path = "TVOSWhisperTest";
|
||||
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 = "TVOSWhisperTest/Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.ggml.TVOSWhisperTest";
|
||||
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 = "TVOSWhisperTest/Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.ggml.TVOSWhisperTest";
|
||||
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/whisper.framework" ]; then
|
||||
echo "✅ whisper.framework properly embedded"
|
||||
else
|
||||
echo "❌ whisper.framework not properly embedded"
|
||||
FINAL_VALIDATION_RESULT=1
|
||||
fi
|
||||
|
||||
# Check if framework binary exists
|
||||
if [ -f "${TEMP_DIR}/Payload/${APP_NAME}.app/Frameworks/whisper.framework/whisper" ]; then
|
||||
echo "✅ Framework binary exists"
|
||||
|
||||
# Further validate framework by checking architecture
|
||||
ARCHS=$(lipo -info "${TEMP_DIR}/Payload/${APP_NAME}.app/Frameworks/whisper.framework/whisper" 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
|
||||
808
scripts/apple/validate-visionos.sh
Executable file
808
scripts/apple/validate-visionos.sh
Executable file
@@ -0,0 +1,808 @@
|
||||
#!/bin/bash
|
||||
# validate-visionos.sh - Validate visionOS Application with embedded whisper.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="VisionOSWhisperTest"
|
||||
BUNDLE_ID="org.ggml.VisionOSWhisperTest"
|
||||
XCFRAMEWORK_PATH="${ROOT_DIR}/build-apple/whisper.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 whisper
|
||||
|
||||
@main
|
||||
struct WhisperTestApp: 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 whisper
|
||||
|
||||
struct ContentView: View {
|
||||
// Test that we can initialize a whisper context params struct
|
||||
let params = whisper_context_default_params()
|
||||
|
||||
var body: some View {
|
||||
VStack(spacing: 20) {
|
||||
Text("Whisper Framework Test on visionOS")
|
||||
.font(.largeTitle)
|
||||
.padding()
|
||||
|
||||
Text("whisper_context_default_params() created successfully")
|
||||
.font(.headline)
|
||||
.multilineTextAlignment(.center)
|
||||
.padding()
|
||||
|
||||
// Display some param values to confirm the framework is working
|
||||
Text("dtw_n_top: \(params.dtw_n_top)")
|
||||
.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 /* whisper.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 66666666666666666666666; };
|
||||
77777777777777777777777 /* whisper.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 /* whisper.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 /* whisper.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = whisper.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 /* whisper.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 /* whisper.xcframework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
EEEEEEEEEEEEEEEEEEEEEEEE = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
FFFFFFFFFFFFFFFFFFFFFFFF /* VisionOSWhisperTest */,
|
||||
CCCCCCCCCCCCCCCCCCCCCCCC /* Products */,
|
||||
DDDDDDDDDDDDDDDDDDDDDDDD /* Frameworks */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
FFFFFFFFFFFFFFFFFFFFFFFF /* VisionOSWhisperTest */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
1111111111111111111111AA /* Sources */,
|
||||
AAAAAAAAAAAAAAAAAAAAAAA /* Info.plist */,
|
||||
);
|
||||
path = "VisionOSWhisperTest";
|
||||
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 = "VisionOSWhisperTest/Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.ggml.VisionOSWhisperTest";
|
||||
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 = "VisionOSWhisperTest/Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.ggml.VisionOSWhisperTest";
|
||||
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/whisper.framework" ]; then
|
||||
echo "✅ whisper.framework properly embedded"
|
||||
else
|
||||
echo "❌ whisper.framework not properly embedded"
|
||||
FINAL_VALIDATION_RESULT=1
|
||||
fi
|
||||
|
||||
# Check if framework binary exists
|
||||
if [ -f "${TEMP_DIR}/Payload/${APP_NAME}.app/Frameworks/whisper.framework/whisper" ]; then
|
||||
echo "✅ Framework binary exists"
|
||||
|
||||
# Further validate framework by checking architecture
|
||||
ARCHS=$(lipo -info "${TEMP_DIR}/Payload/${APP_NAME}.app/Frameworks/whisper.framework/whisper" 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
|
||||
411
scripts/bench-all-gg.txt
Normal file
411
scripts/bench-all-gg.txt
Normal file
@@ -0,0 +1,411 @@
|
||||
## M1 Pro (old 22c96b4)
|
||||
|
||||
make -j && ./scripts/bench-all.sh 8
|
||||
|
||||
Running memcpy benchmark
|
||||
|
||||
memcpy: 39.10 GB/s (heat-up)
|
||||
memcpy: 44.75 GB/s ( 1 thread)
|
||||
memcpy: 44.78 GB/s ( 1 thread)
|
||||
memcpy: 44.97 GB/s ( 2 thread)
|
||||
memcpy: 48.04 GB/s ( 3 thread)
|
||||
memcpy: 50.55 GB/s ( 4 thread)
|
||||
memcpy: 55.20 GB/s ( 5 thread)
|
||||
memcpy: 65.60 GB/s ( 6 thread)
|
||||
memcpy: 70.64 GB/s ( 7 thread)
|
||||
memcpy: 73.34 GB/s ( 8 thread)
|
||||
sum: -5120002535.000000
|
||||
|
||||
|
||||
make -j && ./scripts/bench-all.sh 1 0 0
|
||||
|
||||
Running ggml_mul_mat benchmark with 1 threads
|
||||
|
||||
64 x 64: Q4_0 237.1 GFLOPS (128 runs) | Q4_1 168.6 GFLOPS (128 runs)
|
||||
64 x 64: Q5_0 136.4 GFLOPS (128 runs) | Q5_1 135.6 GFLOPS (128 runs) | Q8_0 243.1 GFLOPS (128 runs)
|
||||
64 x 64: F16 140.4 GFLOPS (128 runs) | F32 316.6 GFLOPS (128 runs)
|
||||
128 x 128: Q4_0 496.6 GFLOPS (128 runs) | Q4_1 348.6 GFLOPS (128 runs)
|
||||
128 x 128: Q5_0 273.2 GFLOPS (128 runs) | Q5_1 274.1 GFLOPS (128 runs) | Q8_0 505.1 GFLOPS (128 runs)
|
||||
128 x 128: F16 300.4 GFLOPS (128 runs) | F32 653.9 GFLOPS (128 runs)
|
||||
256 x 256: Q4_0 791.7 GFLOPS (128 runs) | Q4_1 615.3 GFLOPS (128 runs)
|
||||
256 x 256: Q5_0 651.0 GFLOPS (128 runs) | Q5_1 674.7 GFLOPS (128 runs) | Q8_0 803.1 GFLOPS (128 runs)
|
||||
256 x 256: F16 869.6 GFLOPS (128 runs) | F32 957.2 GFLOPS (128 runs)
|
||||
512 x 512: Q4_0 973.3 GFLOPS (128 runs) | Q4_1 897.9 GFLOPS (128 runs)
|
||||
512 x 512: Q5_0 1078.8 GFLOPS (128 runs) | Q5_1 998.4 GFLOPS (128 runs) | Q8_0 752.4 GFLOPS (128 runs)
|
||||
512 x 512: F16 892.5 GFLOPS (128 runs) | F32 1399.6 GFLOPS (128 runs)
|
||||
1024 x 1024: Q4_0 1402.7 GFLOPS (128 runs) | Q4_1 1218.5 GFLOPS (128 runs)
|
||||
1024 x 1024: Q5_0 1444.8 GFLOPS (128 runs) | Q5_1 1444.7 GFLOPS (128 runs) | Q8_0 1395.7 GFLOPS (128 runs)
|
||||
1024 x 1024: F16 1524.1 GFLOPS (128 runs) | F32 1726.6 GFLOPS (128 runs)
|
||||
2048 x 2048: Q4_0 1479.4 GFLOPS ( 87 runs) | Q4_1 1378.5 GFLOPS ( 81 runs)
|
||||
2048 x 2048: Q5_0 1454.6 GFLOPS ( 85 runs) | Q5_1 1462.9 GFLOPS ( 86 runs) | Q8_0 1483.2 GFLOPS ( 87 runs)
|
||||
2048 x 2048: F16 1488.0 GFLOPS ( 87 runs) | F32 1538.2 GFLOPS ( 90 runs)
|
||||
4096 x 4096: Q4_0 1509.7 GFLOPS ( 11 runs) | Q4_1 1433.0 GFLOPS ( 11 runs)
|
||||
4096 x 4096: Q5_0 1422.4 GFLOPS ( 11 runs) | Q5_1 1437.0 GFLOPS ( 11 runs) | Q8_0 1523.0 GFLOPS ( 12 runs)
|
||||
4096 x 4096: F16 1551.3 GFLOPS ( 12 runs) | F32 1451.0 GFLOPS ( 11 runs)
|
||||
|
||||
| CPU | Config | Model | Th | FA | Enc. | Dec. | Bch5 | PP | Commit |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| M1 Pro | METAL | tiny | 1 | 0 | 32.44 | 1.71 | 0.43 | 0.04 | 8a67c55c |
|
||||
| M1 Pro | METAL | base | 1 | 0 | 63.54 | 2.62 | 0.71 | 0.06 | 8a67c55c |
|
||||
| M1 Pro | METAL | small | 1 | 0 | 200.30 | 5.34 | 1.72 | 0.17 | 8a67c55c |
|
||||
| M1 Pro | METAL | medium | 1 | 0 | 580.06 | 11.71 | 4.18 | 0.45 | 8a67c55c |
|
||||
|
||||
|
||||
make -j && ./scripts/bench-all.sh 1 1 1
|
||||
|
||||
| CPU | Config | Model | Th | FA | Enc. | Dec. | Bch5 | PP | Commit |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| M1 Pro | METAL | tiny | 1 | 1 | 22.09 | 1.84 | 0.43 | 0.03 | 8a67c55c |
|
||||
| M1 Pro | METAL | base | 1 | 1 | 40.57 | 2.22 | 0.44 | 0.04 | 8a67c55c |
|
||||
| M1 Pro | METAL | small | 1 | 1 | 135.15 | 4.23 | 0.95 | 0.12 | 8a67c55c |
|
||||
| M1 Pro | METAL | medium | 1 | 1 | 395.18 | 9.14 | 2.21 | 0.30 | 8a67c55c |
|
||||
|
||||
|
||||
## M2 Ultra
|
||||
|
||||
make -j && ./scripts/bench-all.sh 8
|
||||
|
||||
Running memcpy benchmark
|
||||
|
||||
memcpy: 48.01 GB/s (heat-up)
|
||||
memcpy: 56.00 GB/s ( 1 thread)
|
||||
memcpy: 56.20 GB/s ( 1 thread)
|
||||
memcpy: 102.69 GB/s ( 2 thread)
|
||||
memcpy: 140.32 GB/s ( 3 thread)
|
||||
memcpy: 179.04 GB/s ( 4 thread)
|
||||
memcpy: 159.61 GB/s ( 5 thread)
|
||||
memcpy: 159.02 GB/s ( 6 thread)
|
||||
memcpy: 180.29 GB/s ( 7 thread)
|
||||
memcpy: 198.10 GB/s ( 8 thread)
|
||||
sum: -5119999345.000000
|
||||
|
||||
|
||||
make -j && ./scripts/bench-all.sh 1
|
||||
|
||||
Running ggml_mul_mat benchmark with 1 threads
|
||||
|
||||
64 x 64: Q4_0 37.7 GFLOPS (128 runs) | Q4_1 36.0 GFLOPS (128 runs)
|
||||
64 x 64: Q5_0 20.1 GFLOPS (128 runs) | Q5_1 19.8 GFLOPS (128 runs) | Q8_0 39.5 GFLOPS (128 runs)
|
||||
64 x 64: F16 29.9 GFLOPS (128 runs) | F32 22.6 GFLOPS (128 runs)
|
||||
128 x 128: Q4_0 71.0 GFLOPS (128 runs) | Q4_1 62.2 GFLOPS (128 runs)
|
||||
128 x 128: Q5_0 33.4 GFLOPS (128 runs) | Q5_1 31.6 GFLOPS (128 runs) | Q8_0 79.8 GFLOPS (128 runs)
|
||||
128 x 128: F16 52.4 GFLOPS (128 runs) | F32 32.7 GFLOPS (128 runs)
|
||||
256 x 256: Q4_0 88.6 GFLOPS (128 runs) | Q4_1 77.2 GFLOPS (128 runs)
|
||||
256 x 256: Q5_0 40.3 GFLOPS (128 runs) | Q5_1 36.8 GFLOPS (128 runs) | Q8_0 102.5 GFLOPS (128 runs)
|
||||
256 x 256: F16 64.6 GFLOPS (128 runs) | F32 36.4 GFLOPS (128 runs)
|
||||
512 x 512: Q4_0 94.7 GFLOPS (128 runs) | Q4_1 83.6 GFLOPS (128 runs)
|
||||
512 x 512: Q5_0 45.9 GFLOPS (128 runs) | Q5_1 41.3 GFLOPS (128 runs) | Q8_0 112.8 GFLOPS (128 runs)
|
||||
512 x 512: F16 72.3 GFLOPS (128 runs) | F32 37.7 GFLOPS (128 runs)
|
||||
1024 x 1024: Q4_0 98.9 GFLOPS ( 47 runs) | Q4_1 88.2 GFLOPS ( 42 runs)
|
||||
1024 x 1024: Q5_0 49.0 GFLOPS ( 23 runs) | Q5_1 43.9 GFLOPS ( 21 runs) | Q8_0 121.0 GFLOPS ( 57 runs)
|
||||
1024 x 1024: F16 72.6 GFLOPS ( 34 runs) | F32 36.0 GFLOPS ( 17 runs)
|
||||
2048 x 2048: Q4_0 101.3 GFLOPS ( 6 runs) | Q4_1 90.0 GFLOPS ( 6 runs)
|
||||
2048 x 2048: Q5_0 50.8 GFLOPS ( 3 runs) | Q5_1 45.3 GFLOPS ( 3 runs) | Q8_0 124.1 GFLOPS ( 8 runs)
|
||||
2048 x 2048: F16 70.7 GFLOPS ( 5 runs) | F32 30.4 GFLOPS ( 3 runs)
|
||||
4096 x 4096: Q4_0 101.7 GFLOPS ( 3 runs) | Q4_1 90.3 GFLOPS ( 3 runs)
|
||||
4096 x 4096: Q5_0 52.2 GFLOPS ( 3 runs) | Q5_1 45.7 GFLOPS ( 3 runs) | Q8_0 123.0 GFLOPS ( 3 runs)
|
||||
4096 x 4096: F16 60.3 GFLOPS ( 3 runs) | F32 29.8 GFLOPS ( 3 runs)
|
||||
|
||||
|
||||
make -j && ./scripts/bench-all.sh 1 1 0
|
||||
|
||||
| CPU | Config | Model | Th | FA | Enc. | Dec. | Bch5 | PP | Commit |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| M2 ULTRA | METAL | tiny | 1 | 0 | 8.10 | 1.03 | 0.25 | 0.01 | f14ae77f |
|
||||
| M2 ULTRA | METAL | tiny-q5_0 | 1 | 0 | 8.53 | 1.02 | 0.26 | 0.01 | f14ae77f |
|
||||
| M2 ULTRA | METAL | tiny-q5_1 | 1 | 0 | 8.67 | 1.00 | 0.26 | 0.01 | f14ae77f |
|
||||
| M2 ULTRA | METAL | tiny-q8_0 | 1 | 0 | 9.32 | 1.02 | 0.26 | 0.01 | f14ae77f |
|
||||
| M2 ULTRA | METAL | base | 1 | 0 | 15.50 | 1.51 | 0.40 | 0.02 | f14ae77f |
|
||||
| M2 ULTRA | METAL | base-q5_0 | 1 | 0 | 16.63 | 1.45 | 0.40 | 0.02 | f14ae77f |
|
||||
| M2 ULTRA | METAL | base-q5_1 | 1 | 0 | 16.76 | 1.44 | 0.39 | 0.02 | f14ae77f |
|
||||
| M2 ULTRA | METAL | base-q8_0 | 1 | 0 | 15.73 | 1.43 | 0.38 | 0.02 | f14ae77f |
|
||||
| M2 ULTRA | METAL | small | 1 | 0 | 45.43 | 2.93 | 0.83 | 0.05 | f14ae77f |
|
||||
| M2 ULTRA | METAL | small-q5_0 | 1 | 0 | 49.78 | 2.85 | 0.84 | 0.06 | f14ae77f |
|
||||
| M2 ULTRA | METAL | small-q5_1 | 1 | 0 | 50.22 | 2.85 | 0.84 | 0.06 | f14ae77f |
|
||||
| M2 ULTRA | METAL | small-q8_0 | 1 | 0 | 47.08 | 2.78 | 0.83 | 0.05 | f14ae77f |
|
||||
| M2 ULTRA | METAL | medium | 1 | 0 | 125.19 | 6.10 | 1.88 | 0.12 | f14ae77f |
|
||||
| M2 ULTRA | METAL | medium-q5_0 | 1 | 0 | 142.49 | 5.59 | 1.90 | 0.14 | f14ae77f |
|
||||
| M2 ULTRA | METAL | medium-q5_1 | 1 | 0 | 142.63 | 5.68 | 1.92 | 0.14 | f14ae77f |
|
||||
| M2 ULTRA | METAL | medium-q8_0 | 1 | 0 | 130.98 | 5.83 | 1.87 | 0.13 | f14ae77f |
|
||||
| M2 ULTRA | METAL | medium-dis | 1 | 0 | 113.95 | 0.88 | 0.24 | 0.02 | f14ae77f |
|
||||
| M2 ULTRA | METAL | large-v2 | 1 | 0 | 239.27 | 8.97 | 2.92 | 0.21 | f14ae77f |
|
||||
| M2 ULTRA | METAL | large-v2-q5_0 | 1 | 0 | 275.07 | 8.56 | 2.92 | 0.24 | f14ae77f |
|
||||
| M2 ULTRA | METAL | large-v2-q5_1 | 1 | 0 | 274.28 | 8.62 | 2.93 | 0.24 | f14ae77f |
|
||||
| M2 ULTRA | METAL | large-v2-q8_0 | 1 | 0 | 248.90 | 8.32 | 2.81 | 0.22 | f14ae77f |
|
||||
| M2 ULTRA | METAL | large-v2-dis | 1 | 0 | 214.26 | 0.97 | 0.27 | 0.02 | f14ae77f |
|
||||
| M2 ULTRA | METAL | large-v3-turbo | 1 | 0 | 222.47 | 1.49 | 0.45 | 0.03 | f14ae77f |
|
||||
| M2 ULTRA | METAL | large-v3-turbo-q5_0 | 1 | 0 | 250.56 | 1.35 | 0.45 | 0.04 | f14ae77f |
|
||||
| M2 ULTRA | METAL | large-v3-turbo-q8_0 | 1 | 0 | 228.57 | 1.33 | 0.43 | 0.03 | f14ae77f |
|
||||
|
||||
make -j && ./scripts/bench-all.sh 1 1 1
|
||||
|
||||
| CPU | Config | Model | Th | FA | Enc. | Dec. | Bch5 | PP | Commit |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| M2 ULTRA | METAL | tiny | 1 | 1 | 6.03 | 0.86 | 0.20 | 0.01 | f14ae77f |
|
||||
| M2 ULTRA | METAL | tiny-q5_0 | 1 | 1 | 6.46 | 0.84 | 0.21 | 0.01 | f14ae77f |
|
||||
| M2 ULTRA | METAL | tiny-q5_1 | 1 | 1 | 6.46 | 0.85 | 0.21 | 0.01 | f14ae77f |
|
||||
| M2 ULTRA | METAL | tiny-q8_0 | 1 | 1 | 6.14 | 0.88 | 0.20 | 0.01 | f14ae77f |
|
||||
| M2 ULTRA | METAL | base | 1 | 1 | 10.87 | 1.24 | 0.31 | 0.01 | f14ae77f |
|
||||
| M2 ULTRA | METAL | base-q5_0 | 1 | 1 | 11.98 | 1.18 | 0.31 | 0.02 | f14ae77f |
|
||||
| M2 ULTRA | METAL | base-q5_1 | 1 | 1 | 12.07 | 1.18 | 0.31 | 0.02 | f14ae77f |
|
||||
| M2 ULTRA | METAL | base-q8_0 | 1 | 1 | 11.13 | 1.19 | 0.30 | 0.02 | f14ae77f |
|
||||
| M2 ULTRA | METAL | small | 1 | 1 | 31.46 | 2.37 | 0.63 | 0.04 | f14ae77f |
|
||||
| M2 ULTRA | METAL | small-q5_0 | 1 | 1 | 36.16 | 2.31 | 0.65 | 0.04 | f14ae77f |
|
||||
| M2 ULTRA | METAL | small-q5_1 | 1 | 1 | 36.57 | 2.31 | 0.65 | 0.04 | f14ae77f |
|
||||
| M2 ULTRA | METAL | small-q8_0 | 1 | 1 | 32.94 | 2.27 | 0.63 | 0.04 | f14ae77f |
|
||||
| M2 ULTRA | METAL | medium | 1 | 1 | 89.86 | 4.92 | 1.41 | 0.09 | f14ae77f |
|
||||
| M2 ULTRA | METAL | medium-q5_0 | 1 | 1 | 107.12 | 4.72 | 1.42 | 0.10 | f14ae77f |
|
||||
| M2 ULTRA | METAL | medium-q5_1 | 1 | 1 | 107.00 | 4.70 | 1.42 | 0.10 | f14ae77f |
|
||||
| M2 ULTRA | METAL | medium-q8_0 | 1 | 1 | 94.93 | 4.56 | 1.37 | 0.09 | f14ae77f |
|
||||
| M2 ULTRA | METAL | medium-dis | 1 | 1 | 79.66 | 0.78 | 0.20 | 0.01 | f14ae77f |
|
||||
| M2 ULTRA | METAL | large-v2 | 1 | 1 | 170.06 | 7.13 | 2.15 | 0.16 | f14ae77f |
|
||||
| M2 ULTRA | METAL | large-v2-q5_0 | 1 | 1 | 205.16 | 6.80 | 2.18 | 0.20 | f14ae77f |
|
||||
| M2 ULTRA | METAL | large-v2-q5_1 | 1 | 1 | 204.22 | 6.69 | 2.16 | 0.20 | f14ae77f |
|
||||
| M2 ULTRA | METAL | large-v2-q8_0 | 1 | 1 | 179.78 | 6.35 | 2.13 | 0.18 | f14ae77f |
|
||||
| M2 ULTRA | METAL | large-v2-dis | 1 | 1 | 148.11 | 0.89 | 0.22 | 0.02 | f14ae77f |
|
||||
| M2 ULTRA | METAL | large-v3-turbo | 1 | 1 | 149.23 | 1.29 | 0.34 | 0.03 | f14ae77f |
|
||||
| M2 ULTRA | METAL | large-v3-turbo-q5_0 | 1 | 1 | 180.77 | 1.13 | 0.35 | 0.03 | f14ae77f |
|
||||
| M2 ULTRA | METAL | large-v3-turbo-q8_0 | 1 | 1 | 158.66 | 1.10 | 0.33 | 0.03 | f14ae77f |
|
||||
|
||||
|
||||
## M4 Max
|
||||
|
||||
make -j && ./scripts/bench-all.sh 8
|
||||
|
||||
Running memcpy benchmark
|
||||
|
||||
memcpy: 57.23 GB/s (heat-up)
|
||||
memcpy: 68.85 GB/s ( 1 thread)
|
||||
memcpy: 70.00 GB/s ( 1 thread)
|
||||
memcpy: 104.83 GB/s ( 2 thread)
|
||||
memcpy: 124.54 GB/s ( 3 thread)
|
||||
memcpy: 144.30 GB/s ( 4 thread)
|
||||
memcpy: 141.24 GB/s ( 5 thread)
|
||||
memcpy: 147.03 GB/s ( 6 thread)
|
||||
memcpy: 147.18 GB/s ( 7 thread)
|
||||
memcpy: 149.83 GB/s ( 8 thread)
|
||||
sum: -5120001475.000000
|
||||
|
||||
|
||||
make -j && ./scripts/bench-all.sh 1
|
||||
|
||||
Running ggml_mul_mat benchmark with 1 threads
|
||||
|
||||
64 x 64: Q4_0 49.6 GFLOPS (128 runs) | Q4_1 46.8 GFLOPS (128 runs)
|
||||
64 x 64: Q5_0 28.1 GFLOPS (128 runs) | Q5_1 26.8 GFLOPS (128 runs) | Q8_0 52.3 GFLOPS (128 runs)
|
||||
64 x 64: F16 38.1 GFLOPS (128 runs) | F32 26.0 GFLOPS (128 runs)
|
||||
128 x 128: Q4_0 87.6 GFLOPS (128 runs) | Q4_1 79.9 GFLOPS (128 runs)
|
||||
128 x 128: Q5_0 44.7 GFLOPS (128 runs) | Q5_1 41.6 GFLOPS (128 runs) | Q8_0 98.9 GFLOPS (128 runs)
|
||||
128 x 128: F16 64.1 GFLOPS (128 runs) | F32 35.4 GFLOPS (128 runs)
|
||||
256 x 256: Q4_0 104.2 GFLOPS (128 runs) | Q4_1 92.3 GFLOPS (128 runs)
|
||||
256 x 256: Q5_0 57.3 GFLOPS (128 runs) | Q5_1 51.5 GFLOPS (128 runs) | Q8_0 127.7 GFLOPS (128 runs)
|
||||
256 x 256: F16 71.4 GFLOPS (128 runs) | F32 40.6 GFLOPS (128 runs)
|
||||
512 x 512: Q4_0 109.5 GFLOPS (128 runs) | Q4_1 98.0 GFLOPS (128 runs)
|
||||
512 x 512: Q5_0 62.4 GFLOPS (128 runs) | Q5_1 54.6 GFLOPS (128 runs) | Q8_0 135.0 GFLOPS (128 runs)
|
||||
512 x 512: F16 82.6 GFLOPS (128 runs) | F32 44.6 GFLOPS (128 runs)
|
||||
1024 x 1024: Q4_0 112.1 GFLOPS ( 53 runs) | Q4_1 100.9 GFLOPS ( 47 runs)
|
||||
1024 x 1024: Q5_0 65.4 GFLOPS ( 31 runs) | Q5_1 56.7 GFLOPS ( 27 runs) | Q8_0 140.9 GFLOPS ( 66 runs)
|
||||
1024 x 1024: F16 88.0 GFLOPS ( 41 runs) | F32 43.4 GFLOPS ( 21 runs)
|
||||
2048 x 2048: Q4_0 113.4 GFLOPS ( 7 runs) | Q4_1 102.0 GFLOPS ( 6 runs)
|
||||
2048 x 2048: Q5_0 67.1 GFLOPS ( 4 runs) | Q5_1 57.7 GFLOPS ( 4 runs) | Q8_0 142.7 GFLOPS ( 9 runs)
|
||||
2048 x 2048: F16 84.6 GFLOPS ( 5 runs) | F32 37.5 GFLOPS ( 3 runs)
|
||||
4096 x 4096: Q4_0 113.8 GFLOPS ( 3 runs) | Q4_1 102.0 GFLOPS ( 3 runs)
|
||||
4096 x 4096: Q5_0 67.7 GFLOPS ( 3 runs) | Q5_1 58.0 GFLOPS ( 3 runs) | Q8_0 142.9 GFLOPS ( 3 runs)
|
||||
4096 x 4096: F16 73.7 GFLOPS ( 3 runs) | F32 36.1 GFLOPS ( 3 runs)
|
||||
|
||||
|
||||
make -j && ./scripts/bench-all.sh 1 1 0
|
||||
|
||||
| CPU | Config | Model | Th | FA | Enc. | Dec. | Bch5 | PP | Commit |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| M4 Max | METAL | tiny | 1 | 0 | 10.75 | 0.87 | 0.24 | 0.01 | 47af2fb7 |
|
||||
| M4 Max | METAL | tiny-q8_0 | 1 | 0 | 11.15 | 0.85 | 0.24 | 0.01 | 47af2fb7 |
|
||||
| M4 Max | METAL | base | 1 | 0 | 20.12 | 1.34 | 0.36 | 0.02 | 47af2fb7 |
|
||||
| M4 Max | METAL | base-q8_0 | 1 | 0 | 20.40 | 1.25 | 0.37 | 0.02 | 47af2fb7 |
|
||||
| M4 Max | METAL | small | 1 | 0 | 63.80 | 2.75 | 0.77 | 0.06 | 47af2fb7 |
|
||||
| M4 Max | METAL | small-q8_0 | 1 | 0 | 65.46 | 2.43 | 0.77 | 0.06 | 47af2fb7 |
|
||||
| M4 Max | METAL | medium | 1 | 0 | 184.43 | 6.21 | 1.82 | 0.15 | 47af2fb7 |
|
||||
| M4 Max | METAL | medium-q8_0 | 1 | 0 | 190.19 | 5.76 | 1.86 | 0.15 | 47af2fb7 |
|
||||
| M4 Max | METAL | large-v2 | 1 | 0 | 344.05 | 10.64 | 3.07 | 0.26 | 47af2fb7 |
|
||||
| M4 Max | METAL | large-v2-q8_0 | 1 | 0 | 355.43 | 8.83 | 3.03 | 0.27 | 47af2fb7 |
|
||||
| M4 Max | METAL | large-v3-turbo | 1 | 0 | 306.64 | 1.82 | 0.49 | 0.04 | 47af2fb7 |
|
||||
|
||||
|
||||
make -j && ./scripts/bench-all.sh 1 1 1
|
||||
|
||||
| CPU | Config | Model | Th | FA | Enc. | Dec. | Bch5 | PP | Commit |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| M4 Max | METAL | tiny | 1 | 1 | 8.23 | 0.72 | 0.16 | 0.01 | 47af2fb7 |
|
||||
| M4 Max | METAL | tiny-q8_0 | 1 | 1 | 8.38 | 0.68 | 0.16 | 0.01 | 47af2fb7 |
|
||||
| M4 Max | METAL | base | 1 | 1 | 15.66 | 1.16 | 0.26 | 0.02 | 47af2fb7 |
|
||||
| M4 Max | METAL | base-q8_0 | 1 | 1 | 15.88 | 1.08 | 0.27 | 0.02 | 47af2fb7 |
|
||||
| M4 Max | METAL | small | 1 | 1 | 50.34 | 2.38 | 0.54 | 0.05 | 47af2fb7 |
|
||||
| M4 Max | METAL | small-q8_0 | 1 | 1 | 51.90 | 1.98 | 0.54 | 0.05 | 47af2fb7 |
|
||||
| M4 Max | METAL | medium | 1 | 1 | 149.55 | 5.59 | 1.30 | 0.12 | 47af2fb7 |
|
||||
| M4 Max | METAL | medium-q8_0 | 1 | 1 | 154.34 | 4.65 | 1.28 | 0.13 | 47af2fb7 |
|
||||
| M4 Max | METAL | large-v2 | 1 | 1 | 291.28 | 9.16 | 2.14 | 0.22 | 47af2fb7 |
|
||||
| M4 Max | METAL | large-v2-q8_0 | 1 | 1 | 301.06 | 7.21 | 2.08 | 0.23 | 47af2fb7 |
|
||||
| M4 Max | METAL | large-v3-turbo | 1 | 1 | 256.23 | 1.61 | 0.38 | 0.04 | 47af2fb7 |
|
||||
|
||||
|
||||
## M5 Max
|
||||
|
||||
make -j && ./scripts/bench-all.sh 1 1 0
|
||||
|
||||
| CPU | Config | Model | Th | FA | Enc. | Dec. | Bch5 | PP | Commit |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| M5 Max | METAL | tiny | 1 | 0 | 4.88 | 0.65 | 0.17 | 0.01 | f14ae77f |
|
||||
| M5 Max | METAL | tiny-q8_0 | 1 | 0 | 4.84 | 0.63 | 0.17 | 0.01 | f14ae77f |
|
||||
| M5 Max | METAL | base | 1 | 0 | 8.95 | 1.02 | 0.24 | 0.01 | f14ae77f |
|
||||
| M5 Max | METAL | base-q8_0 | 1 | 0 | 9.12 | 0.94 | 0.24 | 0.01 | f14ae77f |
|
||||
| M5 Max | METAL | small | 1 | 0 | 25.61 | 2.15 | 0.52 | 0.03 | f14ae77f |
|
||||
| M5 Max | METAL | small-q8_0 | 1 | 0 | 25.77 | 1.93 | 0.50 | 0.03 | f14ae77f |
|
||||
| M5 Max | METAL | medium | 1 | 0 | 73.96 | 4.61 | 1.16 | 0.08 | f14ae77f |
|
||||
| M5 Max | METAL | medium-q8_0 | 1 | 0 | 74.89 | 3.94 | 1.12 | 0.08 | f14ae77f |
|
||||
| M5 Max | METAL | large-v2 | 1 | 0 | 132.06 | 6.91 | 1.86 | 0.13 | f14ae77f |
|
||||
| M5 Max | METAL | large-v2-q8_0 | 1 | 0 | 132.56 | 6.00 | 1.76 | 0.13 | f14ae77f |
|
||||
| M5 Max | METAL | large-v3-turbo | 1 | 0 | 119.34 | 1.30 | 0.32 | 0.02 | f14ae77f |
|
||||
|
||||
|
||||
make -j && ./scripts/bench-all.sh 1 1 1
|
||||
|
||||
| CPU | Config | Model | Th | FA | Enc. | Dec. | Bch5 | PP | Commit |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| M5 Max | METAL | tiny | 1 | 1 | 4.31 | 0.59 | 0.13 | 0.01 | f14ae77f |
|
||||
| M5 Max | METAL | tiny-q8_0 | 1 | 1 | 4.51 | 0.55 | 0.12 | 0.01 | f14ae77f |
|
||||
| M5 Max | METAL | base | 1 | 1 | 7.77 | 0.91 | 0.20 | 0.01 | f14ae77f |
|
||||
| M5 Max | METAL | base-q8_0 | 1 | 1 | 7.67 | 0.78 | 0.19 | 0.01 | f14ae77f |
|
||||
| M5 Max | METAL | small | 1 | 1 | 20.90 | 1.76 | 0.40 | 0.03 | f14ae77f |
|
||||
| M5 Max | METAL | small-q8_0 | 1 | 1 | 21.32 | 1.62 | 0.38 | 0.03 | f14ae77f |
|
||||
| M5 Max | METAL | medium | 1 | 1 | 60.40 | 3.98 | 0.89 | 0.07 | f14ae77f |
|
||||
| M5 Max | METAL | medium-q8_0 | 1 | 1 | 60.72 | 3.35 | 0.86 | 0.07 | f14ae77f |
|
||||
| M5 Max | METAL | large-v2 | 1 | 1 | 110.57 | 6.06 | 1.41 | 0.12 | f14ae77f |
|
||||
| M5 Max | METAL | large-v2-q8_0 | 1 | 1 | 110.92 | 5.00 | 1.31 | 0.12 | f14ae77f |
|
||||
| M5 Max | METAL | large-v3-turbo | 1 | 1 | 98.36 | 1.19 | 0.27 | 0.02 | f14ae77f |
|
||||
|
||||
|
||||
# RTX 5090
|
||||
|
||||
make -j && ./scripts/bench-all.sh 1 1 0
|
||||
|
||||
| GPU | Config | Model | Th | FA | Enc. | Dec. | Bch5 | PP | Commit |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| RTX 5090 | CUDA | tiny | 1 | 0 | 2.17 | 0.38 | 0.10 | 0.00 | f14ae77f |
|
||||
| RTX 5090 | CUDA | tiny-q8_0 | 1 | 0 | 2.31 | 0.37 | 0.10 | 0.01 | f14ae77f |
|
||||
| RTX 5090 | CUDA | base | 1 | 0 | 3.94 | 0.56 | 0.17 | 0.01 | f14ae77f |
|
||||
| RTX 5090 | CUDA | base-q8_0 | 1 | 0 | 4.13 | 0.53 | 0.14 | 0.01 | f14ae77f |
|
||||
| RTX 5090 | CUDA | small | 1 | 0 | 12.06 | 1.09 | 0.34 | 0.02 | f14ae77f |
|
||||
| RTX 5090 | CUDA | small-q8_0 | 1 | 0 | 12.50 | 1.11 | 0.30 | 0.02 | f14ae77f |
|
||||
| RTX 5090 | CUDA | medium | 1 | 0 | 33.08 | 2.38 | 0.70 | 0.04 | f14ae77f |
|
||||
| RTX 5090 | CUDA | medium-q8_0 | 1 | 0 | 32.57 | 2.26 | 0.62 | 0.04 | f14ae77f |
|
||||
| RTX 5090 | CUDA | large-v2 | 1 | 0 | 54.27 | 3.68 | 1.03 | 0.06 | f14ae77f |
|
||||
| RTX 5090 | CUDA | large-v2-q8_0 | 1 | 0 | 53.11 | 3.22 | 0.89 | 0.06 | f14ae77f |
|
||||
| RTX 5090 | CUDA | large-v3-turbo | 1 | 0 | 50.56 | 0.58 | 0.15 | 0.01 | f14ae77f |
|
||||
| RTX 5090 | CUDA | large-v3-turbo-q8_0 | 1 | 0 | 49.39 | 0.49 | 0.13 | 0.01 | f14ae77f |
|
||||
|
||||
make -j && ./scripts/bench-all.sh 1 1 1
|
||||
|
||||
| GPU | Config | Model | Th | FA | Enc. | Dec. | Bch5 | PP | Commit |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| RTX 5090 | CUDA | tiny | 1 | 1 | 1.29 | 0.31 | 0.07 | 0.00 | f14ae77f |
|
||||
| RTX 5090 | CUDA | tiny-q8_0 | 1 | 1 | 1.45 | 0.31 | 0.07 | 0.00 | f14ae77f |
|
||||
| RTX 5090 | CUDA | base | 1 | 1 | 2.15 | 0.44 | 0.13 | 0.01 | f14ae77f |
|
||||
| RTX 5090 | CUDA | base-q8_0 | 1 | 1 | 2.27 | 0.43 | 0.10 | 0.01 | f14ae77f |
|
||||
| RTX 5090 | CUDA | small | 1 | 1 | 5.54 | 0.83 | 0.26 | 0.01 | f14ae77f |
|
||||
| RTX 5090 | CUDA | small-q8_0 | 1 | 1 | 5.95 | 0.84 | 0.22 | 0.01 | f14ae77f |
|
||||
| RTX 5090 | CUDA | medium | 1 | 1 | 15.43 | 1.81 | 0.53 | 0.02 | f14ae77f |
|
||||
| RTX 5090 | CUDA | medium-q8_0 | 1 | 1 | 14.71 | 1.66 | 0.46 | 0.03 | f14ae77f |
|
||||
| RTX 5090 | CUDA | large-v2 | 1 | 1 | 24.73 | 2.92 | 0.81 | 0.04 | f14ae77f |
|
||||
| RTX 5090 | CUDA | large-v2-q8_0 | 1 | 1 | 23.35 | 2.43 | 0.67 | 0.04 | f14ae77f |
|
||||
| RTX 5090 | CUDA | large-v3-turbo | 1 | 1 | 21.36 | 0.49 | 0.13 | 0.01 | f14ae77f |
|
||||
| RTX 5090 | CUDA | large-v3-turbo-q8_0 | 1 | 1 | 20.07 | 0.39 | 0.10 | 0.01 | f14ae77f |
|
||||
|
||||
|
||||
# DGX Spark
|
||||
|
||||
make -j && ./scripts/bench-all.sh 1 1 0
|
||||
|
||||
| GPU | Config | Model | Th | FA | Enc. | Dec. | Bch5 | PP | Commit |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| DGX Spk. | CUDA | tiny | 1 | 0 | 9.00 | 0.85 | 0.14 | 0.01 | f5b477ab |
|
||||
| DGX Spk. | CUDA | tiny-q8_0 | 1 | 0 | 8.86 | 0.83 | 0.12 | 0.01 | f5b477ab |
|
||||
| DGX Spk. | CUDA | base | 1 | 0 | 18.48 | 1.38 | 0.22 | 0.02 | f5b477ab |
|
||||
| DGX Spk. | CUDA | base-q8_0 | 1 | 0 | 17.28 | 1.22 | 0.19 | 0.02 | f5b477ab |
|
||||
| DGX Spk. | CUDA | small | 1 | 0 | 56.43 | 3.01 | 0.51 | 0.04 | f5b477ab |
|
||||
| DGX Spk. | CUDA | small-q8_0 | 1 | 0 | 55.70 | 2.68 | 0.44 | 0.04 | f5b477ab |
|
||||
| DGX Spk. | CUDA | medium | 1 | 0 | 160.20 | 7.52 | 1.25 | 0.11 | f5b477ab |
|
||||
| DGX Spk. | CUDA | medium-q8_0 | 1 | 0 | 150.84 | 6.01 | 1.01 | 0.12 | f5b477ab |
|
||||
| DGX Spk. | CUDA | large-v2 | 1 | 0 | 276.42 | 12.29 | 2.16 | 0.20 | f5b477ab |
|
||||
| DGX Spk. | CUDA | large-v2-q8_0 | 1 | 0 | 264.92 | 9.32 | 1.67 | 0.20 | f5b477ab |
|
||||
| DGX Spk. | CUDA | large-v3-turbo | 1 | 0 | 264.90 | 2.03 | 0.37 | 0.03 | f5b477ab |
|
||||
| DGX Spk. | CUDA | large-v3-turbo-q8_0 | 1 | 0 | 253.56 | 1.48 | 0.27 | 0.03 | f5b477ab |
|
||||
|
||||
| GPU | Config | Model | Th | FA | Enc. | Dec. | Bch5 | PP | Commit |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| DGX Spk. | CUDA | tiny | 1 | 0 | 9.79 | 0.65 | 0.14 | 0.01 | f14ae77f |
|
||||
| DGX Spk. | CUDA | tiny-q8_0 | 1 | 0 | 8.97 | 0.56 | 0.12 | 0.01 | f14ae77f |
|
||||
| DGX Spk. | CUDA | base | 1 | 0 | 18.58 | 1.04 | 0.22 | 0.01 | f14ae77f |
|
||||
| DGX Spk. | CUDA | base-q8_0 | 1 | 0 | 17.36 | 0.88 | 0.18 | 0.02 | f14ae77f |
|
||||
| DGX Spk. | CUDA | small | 1 | 0 | 56.78 | 2.33 | 0.51 | 0.04 | f14ae77f |
|
||||
| DGX Spk. | CUDA | small-q8_0 | 1 | 0 | 55.47 | 1.99 | 0.43 | 0.04 | f14ae77f |
|
||||
| DGX Spk. | CUDA | medium | 1 | 0 | 158.21 | 5.71 | 1.23 | 0.11 | f14ae77f |
|
||||
| DGX Spk. | CUDA | medium-q8_0 | 1 | 0 | 151.17 | 4.54 | 0.97 | 0.11 | f14ae77f |
|
||||
| DGX Spk. | CUDA | large-v2 | 1 | 0 | 269.59 | 10.48 | 2.13 | 0.20 | f14ae77f |
|
||||
| DGX Spk. | CUDA | large-v2-q8_0 | 1 | 0 | 262.82 | 7.43 | 1.61 | 0.20 | f14ae77f |
|
||||
| DGX Spk. | CUDA | large-v3-turbo | 1 | 0 | 263.91 | 1.80 | 0.37 | 0.03 | f14ae77f |
|
||||
| DGX Spk. | CUDA | large-v3-turbo-q8_0 | 1 | 0 | 252.89 | 1.23 | 0.26 | 0.03 | f14ae77f |
|
||||
|
||||
make -j && ./scripts/bench-all.sh 1 1 1
|
||||
|
||||
| GPU | Config | Model | Th | FA | Enc. | Dec. | Bch5 | PP | Commit |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| DGX Spk. | CUDA | tiny | 1 | 1 | 2.72 | 0.56 | 0.13 | 0.01 | f14ae77f |
|
||||
| DGX Spk. | CUDA | tiny-q8_0 | 1 | 1 | 2.55 | 0.47 | 0.11 | 0.01 | f14ae77f |
|
||||
| DGX Spk. | CUDA | base | 1 | 1 | 5.08 | 0.90 | 0.20 | 0.01 | f14ae77f |
|
||||
| DGX Spk. | CUDA | base-q8_0 | 1 | 1 | 4.38 | 0.72 | 0.16 | 0.01 | f14ae77f |
|
||||
| DGX Spk. | CUDA | small | 1 | 1 | 16.95 | 2.00 | 0.47 | 0.02 | f14ae77f |
|
||||
| DGX Spk. | CUDA | small-q8_0 | 1 | 1 | 15.67 | 1.67 | 0.39 | 0.02 | f14ae77f |
|
||||
| DGX Spk. | CUDA | medium | 1 | 1 | 53.12 | 5.10 | 1.24 | 0.06 | f14ae77f |
|
||||
| DGX Spk. | CUDA | medium-q8_0 | 1 | 1 | 43.64 | 3.87 | 0.91 | 0.05 | f14ae77f |
|
||||
| DGX Spk. | CUDA | large-v2 | 1 | 1 | 102.15 | 9.58 | 2.02 | 0.08 | f14ae77f |
|
||||
| DGX Spk. | CUDA | large-v2-q8_0 | 1 | 1 | 93.86 | 6.54 | 1.49 | 0.08 | f14ae77f |
|
||||
| DGX Spk. | CUDA | large-v3-turbo | 1 | 1 | 90.29 | 1.69 | 0.36 | 0.02 | f14ae77f |
|
||||
| DGX Spk. | CUDA | large-v3-turbo-q8_0 | 1 | 1 | 82.79 | 1.13 | 0.25 | 0.01 | f14ae77f |
|
||||
|
||||
|
||||
# V100
|
||||
|
||||
GGML_CUDA=1 make -j && ./scripts/bench-all.sh 8 1 0
|
||||
|
||||
| GPU | Config | Model | Th | FA | Enc. | Dec. | Bch5 | PP | Commit |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| V100 | AVX2 CUDA | tiny | 8 | 0 | 5.99 | 1.01 | 0.30 | 0.01 | dc8dda60 |
|
||||
| V100 | AVX2 CUDA | tiny-q5_1 | 8 | 0 | 6.07 | 1.00 | 0.26 | 0.01 | dc8dda60 |
|
||||
| V100 | AVX2 CUDA | base | 8 | 0 | 10.96 | 1.44 | 0.43 | 0.02 | dc8dda60 |
|
||||
| V100 | AVX2 CUDA | base-q5_1 | 8 | 0 | 11.11 | 1.41 | 0.37 | 0.02 | dc8dda60 |
|
||||
| V100 | AVX2 CUDA | small | 8 | 0 | 31.04 | 2.84 | 0.86 | 0.04 | dc8dda60 |
|
||||
| V100 | AVX2 CUDA | small-q5_1 | 8 | 0 | 31.69 | 2.82 | 0.71 | 0.04 | dc8dda60 |
|
||||
| V100 | AVX2 CUDA | medium | 8 | 0 | 83.95 | 6.05 | 1.82 | 0.09 | dc8dda60 |
|
||||
| V100 | AVX2 CUDA | medium-q5_0 | 8 | 0 | 85.86 | 5.58 | 1.45 | 0.10 | dc8dda60 |
|
||||
| V100 | AVX2 CUDA | large-v2 | 8 | 0 | 138.50 | 8.70 | 2.71 | 0.15 | dc8dda60 |
|
||||
| V100 | AVX2 CUDA | large-v2-q5_0 | 8 | 0 | 142.31 | 7.82 | 2.03 | 0.16 | dc8dda60 |
|
||||
| V100 | AVX2 CUDA | large-v3-turbo | 8 | 0 | 128.39 | 1.42 | 0.44 | 0.02 | dc8dda60 |
|
||||
| V100 | AVX2 CUDA | large-v3-turbo-q5_0 | 8 | 0 | 131.24 | 1.17 | 0.33 | 0.03 | dc8dda60 |
|
||||
|
||||
|
||||
GGML_CUDA=1 make -j && ./scripts/bench-all.sh 8 1 1
|
||||
|
||||
| GPU | Config | Model | Th | FA | Enc. | Dec. | Bch5 | PP | Commit |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| V100 | AVX2 CUDA | tiny | 8 | 1 | 4.85 | 0.97 | 0.26 | 0.01 | dc8dda60 |
|
||||
| V100 | AVX2 CUDA | tiny-q5_1 | 8 | 1 | 4.97 | 0.89 | 0.19 | 0.01 | dc8dda60 |
|
||||
| V100 | AVX2 CUDA | base | 8 | 1 | 7.23 | 1.28 | 0.35 | 0.02 | dc8dda60 |
|
||||
| V100 | AVX2 CUDA | base-q5_1 | 8 | 1 | 7.38 | 1.24 | 0.26 | 0.02 | dc8dda60 |
|
||||
| V100 | AVX2 CUDA | small | 8 | 1 | 20.87 | 2.44 | 0.71 | 0.03 | dc8dda60 |
|
||||
| V100 | AVX2 CUDA | small-q5_1 | 8 | 1 | 19.80 | 2.35 | 0.51 | 0.03 | dc8dda60 |
|
||||
| V100 | AVX2 CUDA | medium | 8 | 1 | 54.56 | 5.31 | 1.46 | 0.06 | dc8dda60 |
|
||||
| V100 | AVX2 CUDA | medium-q5_0 | 8 | 1 | 56.09 | 4.67 | 1.05 | 0.07 | dc8dda60 |
|
||||
| V100 | AVX2 CUDA | large-v2 | 8 | 1 | 87.05 | 7.65 | 2.16 | 0.10 | dc8dda60 |
|
||||
| V100 | AVX2 CUDA | large-v2-q5_0 | 8 | 1 | 94.65 | 6.60 | 1.47 | 0.11 | dc8dda60 |
|
||||
| V100 | AVX2 CUDA | large-v3-turbo | 8 | 1 | 76.46 | 1.29 | 0.37 | 0.02 | dc8dda60 |
|
||||
| V100 | AVX2 CUDA | large-v3-turbo-q5_0 | 8 | 1 | 79.62 | 1.03 | 0.23 | 0.02 | dc8dda60 |
|
||||
118
scripts/bench-all.sh
Executable file
118
scripts/bench-all.sh
Executable file
@@ -0,0 +1,118 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Helper script to run the bench tool on all models and print the results in share-able format
|
||||
|
||||
printf "Usage: ./scripts/bench-all.sh [n_threads] [encoder-only] [flash-attn]\n"
|
||||
|
||||
if [ -z "$1" ]; then
|
||||
n_threads=4
|
||||
else
|
||||
n_threads=$1
|
||||
fi
|
||||
|
||||
encoder_only=0
|
||||
if [ -z "$2" ] || [ "$2" -eq 0 ]; then
|
||||
encoder_only=0
|
||||
else
|
||||
encoder_only=$2
|
||||
fi
|
||||
|
||||
fattn=""
|
||||
if [ -z "$3" ] || [ "$3" -eq 0 ]; then
|
||||
fattn="-nfa"
|
||||
else
|
||||
fattn="-fa"
|
||||
fi
|
||||
|
||||
models=( \
|
||||
"tiny" "tiny-q4_0" "tiny-q4_1" "tiny-q5_0" "tiny-q5_1" "tiny-q8_0" \
|
||||
"base" "base-q4_0" "base-q4_1" "base-q5_0" "base-q5_1" "base-q8_0" \
|
||||
"small" "small-q4_0" "small-q4_1" "small-q5_0" "small-q5_1" "small-q8_0" \
|
||||
"medium" "medium-q4_0" "medium-q4_1" "medium-q5_0" "medium-q5_1" "medium-q8_0" "medium-dis" \
|
||||
"large-v2" "large-v2-q4_0" "large-v2-q4_1" "large-v2-q5_0" "large-v2-q5_1" "large-v2-q8_0" "large-v2-dis" \
|
||||
"large-v3-turbo" "large-v3-turbo-q5_0" "large-v3-turbo-q8_0" \
|
||||
)
|
||||
|
||||
if [ "$encoder_only" -eq 0 ]; then
|
||||
printf "\n"
|
||||
printf "Running memcpy benchmark\n"
|
||||
printf "\n"
|
||||
|
||||
./build/bin/whisper-bench -w 1 -t $n_threads 2>&1
|
||||
|
||||
printf "\n"
|
||||
printf "Running ggml_mul_mat benchmark with $n_threads threads\n"
|
||||
printf "\n"
|
||||
|
||||
./build/bin/whisper-bench -w 2 -t $n_threads 2>&1
|
||||
|
||||
printf "\n"
|
||||
printf "Running benchmark for all models\n"
|
||||
printf "This can take a while!\n"
|
||||
printf "\n"
|
||||
fi
|
||||
|
||||
if [ "$fattn" == "-fa" ]; then
|
||||
fattn_i=1
|
||||
else
|
||||
fattn_i=0
|
||||
fi
|
||||
|
||||
printf "| %6s | %6s | %16s | %13s | %3s | %3s | %7s | %7s | %7s | %7s | %7s |\n" "CPU" "OS" "Config" "Model" "Th" "FA" "Enc." "Dec." "Bch5" "PP" "Commit"
|
||||
printf "| %6s | %6s | %16s | %13s | %3s | %3s | %7s | %7s | %7s | %7s | %7s |\n" "---" "---" "---" "---" "---" "---" "---" "---" "---" "---" "---"
|
||||
|
||||
for model in "${models[@]}"; do
|
||||
# actual run
|
||||
# store stderr output in a variable in order to parse it later
|
||||
output=$(./build/bin/whisper-bench -m ./models/ggml-$model.bin -t $n_threads $fattn 2>&1)
|
||||
ret=$?
|
||||
|
||||
# parse the output:
|
||||
encode_time=$(echo "$output" | grep "encode time" | awk '{print $11}')
|
||||
decode_time=$(echo "$output" | grep "decode time" | awk '{print $11}')
|
||||
batchd_time=$(echo "$output" | grep "batchd time" | awk '{print $11}')
|
||||
prompt_time=$(echo "$output" | grep "prompt time" | awk '{print $11}')
|
||||
system_info=$(echo "$output" | grep "system_info")
|
||||
n_threads=$(echo "$output" | grep "system_info" | awk '{print $4}')
|
||||
|
||||
# floor to milliseconds
|
||||
#encode_time=${encode_time%.*}
|
||||
#decode_time=${decode_time%.*}
|
||||
#prompt_time=${prompt_time%.*}
|
||||
|
||||
config=""
|
||||
|
||||
if [[ $system_info == *"AVX2 = 1"* ]]; then
|
||||
config="$config AVX2"
|
||||
fi
|
||||
|
||||
if [[ $system_info == *"NEON = 1"* ]]; then
|
||||
config="$config NEON"
|
||||
fi
|
||||
|
||||
if [[ $system_info == *"BLAS = 1"* ]]; then
|
||||
config="$config BLAS"
|
||||
fi
|
||||
|
||||
if [[ $system_info == *"COREML = 1"* ]]; then
|
||||
config="$config COREML"
|
||||
fi
|
||||
|
||||
if [[ $system_info == *"CUDA = 1"* ]]; then
|
||||
config="$config CUDA"
|
||||
elif [[ $system_info == *"CUDA : ARCHS"* ]]; then
|
||||
config="$config CUDA"
|
||||
fi
|
||||
|
||||
if [[ $system_info == *"MTL = 1"* ]]; then
|
||||
config="$config MTL"
|
||||
elif [[ $system_info == *"MTL : EMBED_LIBRARY = 1"* ]]; then
|
||||
config="$config MTL"
|
||||
fi
|
||||
|
||||
commit=$(git rev-parse --short HEAD)
|
||||
|
||||
if [ $ret -eq 0 ]; then
|
||||
printf "| <todo> | <todo> | %16s | %13s | %3s | %3s | %7s | %7s | %7s | %7s | %7s |\n" "$config" "$model" "$n_threads" "$fattn_i" "$encode_time" "$decode_time" "$batchd_time" "$prompt_time" "$commit"
|
||||
fi
|
||||
done
|
||||
70
scripts/bench-wts.sh
Executable file
70
scripts/bench-wts.sh
Executable file
@@ -0,0 +1,70 @@
|
||||
# Benchmark word-level timestamps for different models
|
||||
#
|
||||
# This script takes two arguments
|
||||
# - an audio file
|
||||
# - [optional] path to a font file
|
||||
|
||||
# I'm using "/usr/share/fonts/truetype/freefont/FreeMono.ttf" on Ubuntu
|
||||
|
||||
if [ -z "$1" ]; then
|
||||
echo "Usage: $0 <audio file> [font file]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
#TODO: Make this a command line parameter
|
||||
#models="base small large"
|
||||
#models="tiny.en tiny base.en base small.en small medium.en medium large-v1 large"
|
||||
models="tiny.en base.en small.en medium.en large"
|
||||
|
||||
DURATION=$(ffprobe -i $1 -show_entries format=duration -v quiet -of csv="p=0")
|
||||
DURATION=$(printf "%.2f" $DURATION)
|
||||
echo "Input file duration: ${DURATION}s"
|
||||
|
||||
for model in $models; do
|
||||
echo "Running $model"
|
||||
COMMAND="./build/bin/whisper-cli -m models/ggml-$model.bin -owts -f $1 -of $1.$model"
|
||||
|
||||
if [ ! -z "$2" ]; then
|
||||
COMMAND="$COMMAND -fp $2"
|
||||
fi
|
||||
#TODO: Surface errors better
|
||||
# TIMEFMT is for zsh, TIMEFORMAT is for bash
|
||||
EXECTIME=$({ TIMEFMT="%E";TIMEFORMAT=%E; time $COMMAND >/dev/null 2>&1; } 2>&1)
|
||||
|
||||
# Slightly different formats between zsh and bash
|
||||
if [ "${EXECTIME: -1}" == "s" ]; then
|
||||
EXECTIME=${EXECTIME::-1}
|
||||
fi
|
||||
|
||||
RATIO=$(echo "$DURATION / $EXECTIME" | bc -l)
|
||||
RATIO=$(printf "%.2f" $RATIO)
|
||||
|
||||
echo "Execution time: ${EXECTIME}s (${RATIO}x realtime)"
|
||||
|
||||
# If the file already exists, delete it
|
||||
if [ -f $1.mp4 ]; then
|
||||
rm $1.mp4
|
||||
fi
|
||||
|
||||
bash $1.$model.wts >/dev/null 2>&1
|
||||
mv $1.mp4 $1.$model.mp4
|
||||
|
||||
ffmpeg -y -f lavfi -i color=c=black:s=1200x50:d=$DURATION -vf "drawtext=fontfile=$2:fontsize=36:x=10:y=(h-text_h)/2:text='ggml-$model - ${EXECTIME}s (${RATIO}x realtime)':fontcolor=lightgrey" $1.$model.info.mp4 >/dev/null 2>&1
|
||||
done
|
||||
|
||||
COMMAND="ffmpeg -y"
|
||||
for model in $models; do
|
||||
COMMAND="$COMMAND -i $1.$model.info.mp4 -i $1.$model.mp4"
|
||||
done
|
||||
COMMAND="$COMMAND -filter_complex \""
|
||||
COUNT=0
|
||||
for model in $models; do
|
||||
COMMAND="$COMMAND[${COUNT}:v][$(($COUNT+1)):v]"
|
||||
COUNT=$((COUNT+2))
|
||||
done
|
||||
COMMAND="$COMMAND vstack=inputs=${COUNT}[v]\" -map \"[v]\" -map 1:a $1.all.mp4 >/dev/null 2>&1"
|
||||
|
||||
echo $COMMAND
|
||||
|
||||
# Run the command
|
||||
eval $COMMAND
|
||||
225
scripts/bench.py
Normal file
225
scripts/bench.py
Normal file
@@ -0,0 +1,225 @@
|
||||
import os
|
||||
import subprocess
|
||||
import re
|
||||
import csv
|
||||
import wave
|
||||
import contextlib
|
||||
import argparse
|
||||
|
||||
|
||||
# Custom action to handle comma-separated list
|
||||
class ListAction(argparse.Action):
|
||||
def __call__(self, parser, namespace, values, option_string=None):
|
||||
setattr(namespace, self.dest, [int(val) for val in values.split(",")])
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser(description="Benchmark the speech recognition model")
|
||||
|
||||
# Define the argument to accept a list
|
||||
parser.add_argument(
|
||||
"-t",
|
||||
"--threads",
|
||||
dest="threads",
|
||||
action=ListAction,
|
||||
default=[4],
|
||||
help="List of thread counts to benchmark (comma-separated, default: 4)",
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"-p",
|
||||
"--processors",
|
||||
dest="processors",
|
||||
action=ListAction,
|
||||
default=[1],
|
||||
help="List of processor counts to benchmark (comma-separated, default: 1)",
|
||||
)
|
||||
|
||||
|
||||
parser.add_argument(
|
||||
"-f",
|
||||
"--filename",
|
||||
type=str,
|
||||
default="./samples/jfk.wav",
|
||||
help="Relative path of the file to transcribe (default: ./samples/jfk.wav)",
|
||||
)
|
||||
|
||||
# Parse the command line arguments
|
||||
args = parser.parse_args()
|
||||
|
||||
sample_file = args.filename
|
||||
|
||||
threads = args.threads
|
||||
processors = args.processors
|
||||
|
||||
# Define the models, threads, and processor counts to benchmark
|
||||
models = [
|
||||
"ggml-tiny.en.bin",
|
||||
"ggml-tiny.bin",
|
||||
"ggml-base.en.bin",
|
||||
"ggml-base.bin",
|
||||
"ggml-small.en.bin",
|
||||
"ggml-small.bin",
|
||||
"ggml-medium.en.bin",
|
||||
"ggml-medium.bin",
|
||||
"ggml-large-v1.bin",
|
||||
"ggml-large-v2.bin",
|
||||
"ggml-large-v3.bin",
|
||||
"ggml-large-v3-turbo.bin",
|
||||
]
|
||||
|
||||
|
||||
metal_device = ""
|
||||
|
||||
# Initialize a dictionary to hold the results
|
||||
results = {}
|
||||
|
||||
gitHashHeader = "Commit"
|
||||
modelHeader = "Model"
|
||||
hardwareHeader = "Hardware"
|
||||
recordingLengthHeader = "Recording Length (seconds)"
|
||||
threadHeader = "Thread"
|
||||
processorCountHeader = "Processor Count"
|
||||
loadTimeHeader = "Load Time (ms)"
|
||||
sampleTimeHeader = "Sample Time (ms)"
|
||||
encodeTimeHeader = "Encode Time (ms)"
|
||||
decodeTimeHeader = "Decode Time (ms)"
|
||||
sampleTimePerRunHeader = "Sample Time per Run (ms)"
|
||||
encodeTimePerRunHeader = "Encode Time per Run (ms)"
|
||||
decodeTimePerRunHeader = "Decode Time per Run (ms)"
|
||||
totalTimeHeader = "Total Time (ms)"
|
||||
|
||||
|
||||
def check_file_exists(file: str) -> bool:
|
||||
return os.path.isfile(file)
|
||||
|
||||
|
||||
def get_git_short_hash() -> str:
|
||||
try:
|
||||
return (
|
||||
subprocess.check_output(["git", "rev-parse", "--short", "HEAD"])
|
||||
.decode()
|
||||
.strip()
|
||||
)
|
||||
except subprocess.CalledProcessError as e:
|
||||
return ""
|
||||
|
||||
|
||||
def wav_file_length(file: str = sample_file) -> float:
|
||||
with contextlib.closing(wave.open(file, "r")) as f:
|
||||
frames = f.getnframes()
|
||||
rate = f.getframerate()
|
||||
duration = frames / float(rate)
|
||||
return duration
|
||||
|
||||
|
||||
def extract_metrics(output: str, label: str) -> tuple[float, float]:
|
||||
match = re.search(rf"{label} \s*=\s*(\d+\.\d+)\s*ms\s*/\s*(\d+)\s*runs", output)
|
||||
time = float(match.group(1)) if match else None
|
||||
runs = float(match.group(2)) if match else None
|
||||
return time, runs
|
||||
|
||||
|
||||
def extract_device(output: str) -> str:
|
||||
match = re.search(r"picking default device: (.*)", output)
|
||||
device = match.group(1) if match else "Not found"
|
||||
return device
|
||||
|
||||
|
||||
# Check if the sample file exists
|
||||
if not check_file_exists(sample_file):
|
||||
raise FileNotFoundError(f"Sample file {sample_file} not found")
|
||||
|
||||
recording_length = wav_file_length()
|
||||
|
||||
|
||||
# Check that all models exist
|
||||
# Filter out models from list that are not downloaded
|
||||
filtered_models = []
|
||||
for model in models:
|
||||
if check_file_exists(f"models/{model}"):
|
||||
filtered_models.append(model)
|
||||
else:
|
||||
print(f"Model {model} not found, removing from list")
|
||||
|
||||
models = filtered_models
|
||||
|
||||
# Loop over each combination of parameters
|
||||
for model in filtered_models:
|
||||
for thread in threads:
|
||||
for processor_count in processors:
|
||||
# Construct the command to run
|
||||
cmd = f"./build/bin/whisper-cli -m models/{model} -t {thread} -p {processor_count} -f {sample_file}"
|
||||
# Run the command and get the output
|
||||
process = subprocess.Popen(
|
||||
cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT
|
||||
)
|
||||
|
||||
output = ""
|
||||
while process.poll() is None:
|
||||
output += process.stdout.read().decode()
|
||||
|
||||
# Parse the output
|
||||
load_time_match = re.search(r"load time\s*=\s*(\d+\.\d+)\s*ms", output)
|
||||
load_time = float(load_time_match.group(1)) if load_time_match else None
|
||||
|
||||
metal_device = extract_device(output)
|
||||
sample_time, sample_runs = extract_metrics(output, "sample time")
|
||||
encode_time, encode_runs = extract_metrics(output, "encode time")
|
||||
decode_time, decode_runs = extract_metrics(output, "decode time")
|
||||
|
||||
total_time_match = re.search(r"total time\s*=\s*(\d+\.\d+)\s*ms", output)
|
||||
total_time = float(total_time_match.group(1)) if total_time_match else None
|
||||
|
||||
model_name = model.replace("ggml-", "").replace(".bin", "")
|
||||
|
||||
print(
|
||||
f"Ran model={model_name} threads={thread} processor_count={processor_count}, took {total_time}ms"
|
||||
)
|
||||
# Store the times in the results dictionary
|
||||
results[(model_name, thread, processor_count)] = {
|
||||
loadTimeHeader: load_time,
|
||||
sampleTimeHeader: sample_time,
|
||||
encodeTimeHeader: encode_time,
|
||||
decodeTimeHeader: decode_time,
|
||||
sampleTimePerRunHeader: round(sample_time / sample_runs, 2),
|
||||
encodeTimePerRunHeader: round(encode_time / encode_runs, 2),
|
||||
decodeTimePerRunHeader: round(decode_time / decode_runs, 2),
|
||||
totalTimeHeader: total_time,
|
||||
}
|
||||
|
||||
# Write the results to a CSV file
|
||||
with open("benchmark_results.csv", "w", newline="") as csvfile:
|
||||
fieldnames = [
|
||||
gitHashHeader,
|
||||
modelHeader,
|
||||
hardwareHeader,
|
||||
recordingLengthHeader,
|
||||
threadHeader,
|
||||
processorCountHeader,
|
||||
loadTimeHeader,
|
||||
sampleTimeHeader,
|
||||
encodeTimeHeader,
|
||||
decodeTimeHeader,
|
||||
sampleTimePerRunHeader,
|
||||
encodeTimePerRunHeader,
|
||||
decodeTimePerRunHeader,
|
||||
totalTimeHeader,
|
||||
]
|
||||
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
|
||||
|
||||
writer.writeheader()
|
||||
|
||||
shortHash = get_git_short_hash()
|
||||
# Sort the results by total time in ascending order
|
||||
sorted_results = sorted(results.items(), key=lambda x: x[1].get(totalTimeHeader, 0))
|
||||
for params, times in sorted_results:
|
||||
row = {
|
||||
gitHashHeader: shortHash,
|
||||
modelHeader: params[0],
|
||||
hardwareHeader: metal_device,
|
||||
recordingLengthHeader: recording_length,
|
||||
threadHeader: params[1],
|
||||
processorCountHeader: params[2],
|
||||
}
|
||||
row.update(times)
|
||||
writer.writerow(row)
|
||||
30
scripts/build-info.sh
Executable file
30
scripts/build-info.sh
Executable file
@@ -0,0 +1,30 @@
|
||||
#!/bin/sh
|
||||
|
||||
CC=$1
|
||||
|
||||
build_number="0"
|
||||
build_commit="unknown"
|
||||
build_compiler="unknown"
|
||||
build_target="unknown"
|
||||
|
||||
if out=$(git rev-list --count HEAD); then
|
||||
# git is broken on WSL so we need to strip extra newlines
|
||||
build_number=$(printf '%s' "$out" | tr -d '\n')
|
||||
fi
|
||||
|
||||
if out=$(git rev-parse --short HEAD); then
|
||||
build_commit=$(printf '%s' "$out" | tr -d '\n')
|
||||
fi
|
||||
|
||||
if out=$($CC --version | head -1); then
|
||||
build_compiler=$out
|
||||
fi
|
||||
|
||||
if out=$($CC -dumpmachine); then
|
||||
build_target=$out
|
||||
fi
|
||||
|
||||
echo "int WHISPER_BUILD_NUMBER = ${build_number};"
|
||||
echo "char const *WHISPER_COMMIT = \"${build_commit}\";"
|
||||
echo "char const *WHISPER_COMPILER = \"${build_compiler}\";"
|
||||
echo "char const *WHISPER_BUILD_TARGET = \"${build_target}\";"
|
||||
8
scripts/convert-all.sh
Executable file
8
scripts/convert-all.sh
Executable file
@@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
|
||||
models=( "tiny.en" "tiny" "base.en" "base" "small.en" "small" "medium.en" "medium" "large-v1" "large-v2" "large-v3" "large-v3-turbo" )
|
||||
|
||||
for model in "${models[@]}"; do
|
||||
python3 models/convert-pt-to-ggml.py ~/.cache/whisper/$model.pt ../whisper models/
|
||||
mv -v models/ggml-model.bin models/ggml-$model.bin
|
||||
done
|
||||
31
scripts/deploy-wasm.sh
Executable file
31
scripts/deploy-wasm.sh
Executable file
@@ -0,0 +1,31 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# This is a helper script to deploy all WebAssembly examples to my node
|
||||
# Run from the build directory:
|
||||
#
|
||||
# cd build-em
|
||||
# ../scripts/deploy-wasm.sh
|
||||
#
|
||||
|
||||
# check if emcmake is available
|
||||
if ! command -v emcmake &> /dev/null
|
||||
then
|
||||
echo "Error: emscripten environment is not set up"
|
||||
exit
|
||||
fi
|
||||
|
||||
emcmake cmake .. && make -j
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Error: build failed"
|
||||
exit
|
||||
fi
|
||||
|
||||
# copy all wasm files to the node
|
||||
scp bin/whisper.wasm/* root@linode0:/var/www/html/whisper/ && scp bin/libmain.worker.js root@linode0:/var/www/html/whisper/
|
||||
scp bin/stream.wasm/* root@linode0:/var/www/html/whisper/stream/ && scp bin/libstream.worker.js root@linode0:/var/www/html/whisper/stream/
|
||||
scp bin/command.wasm/* root@linode0:/var/www/html/whisper/command/ && scp bin/libcommand.worker.js root@linode0:/var/www/html/whisper/command/
|
||||
scp bin/talk.wasm/* root@linode0:/var/www/html/whisper/talk/ && scp bin/libtalk.worker.js root@linode0:/var/www/html/whisper/talk/
|
||||
scp bin/bench.wasm/* root@linode0:/var/www/html/whisper/bench/ && scp bin/libbench.worker.js root@linode0:/var/www/html/whisper/bench/
|
||||
|
||||
echo "Done"
|
||||
exit
|
||||
9
scripts/gen-authors.sh
Executable file
9
scripts/gen-authors.sh
Executable file
@@ -0,0 +1,9 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
printf "# date: $(date)\n" > AUTHORS
|
||||
printf "# this file is auto-generated by scripts/gen-authors.sh\n\n" >> AUTHORS
|
||||
|
||||
git log --format='%an <%ae>' --reverse --date=short master | awk '!seen[$0]++' | sort >> AUTHORS
|
||||
|
||||
# if necessary, update your name here. for example: jdoe -> John Doe
|
||||
sed -i '' 's/^jdoe/John Doe/g' AUTHORS
|
||||
38
scripts/get-flags.mk
Normal file
38
scripts/get-flags.mk
Normal file
@@ -0,0 +1,38 @@
|
||||
ifeq '' '$(findstring clang,$(shell $(GF_CC) --version))'
|
||||
GF_CC_IS_GCC = 1
|
||||
GF_CC_VER := $(shell { $(GF_CC) -dumpfullversion 2>/dev/null; echo; $(GF_CC) -dumpversion; } | awk -F. '/./ { printf("%02d%02d%02d", $$1, $$2, $$3); exit }')
|
||||
else
|
||||
GF_CC_IS_CLANG = 1
|
||||
ifeq '' '$(findstring Apple,$(shell $(GF_CC) --version))'
|
||||
GF_CC_IS_LLVM_CLANG = 1
|
||||
else
|
||||
GF_CC_IS_APPLE_CLANG = 1
|
||||
endif
|
||||
GF_CC_VER := \
|
||||
$(shell $(GF_CC) --version | sed -n 's/^.* version \([0-9.]*\).*$$/\1/p' \
|
||||
| awk -F. '{ printf("%02d%02d%02d", $$1, $$2, $$3) }')
|
||||
endif
|
||||
|
||||
ifeq ($(GF_CC_IS_CLANG), 1)
|
||||
# clang options
|
||||
GF_CFLAGS = -Wunreachable-code-break -Wunreachable-code-return
|
||||
GF_CXXFLAGS = -Wunreachable-code-break -Wunreachable-code-return -Wmissing-prototypes -Wextra-semi
|
||||
|
||||
ifneq '' '$(and $(GF_CC_IS_LLVM_CLANG),$(filter 1,$(shell expr $(GF_CC_VER) \>= 030800)))'
|
||||
GF_CFLAGS += -Wdouble-promotion
|
||||
endif
|
||||
ifneq '' '$(and $(GF_CC_IS_APPLE_CLANG),$(filter 1,$(shell expr $(GF_CC_VER) \>= 070300)))'
|
||||
GF_CFLAGS += -Wdouble-promotion
|
||||
endif
|
||||
else
|
||||
# gcc options
|
||||
GF_CFLAGS = -Wdouble-promotion
|
||||
GF_CXXFLAGS = -Wno-array-bounds
|
||||
|
||||
ifeq ($(shell expr $(GF_CC_VER) \>= 070100), 1)
|
||||
GF_CXXFLAGS += -Wno-format-truncation
|
||||
endif
|
||||
ifeq ($(shell expr $(GF_CC_VER) \>= 080100), 1)
|
||||
GF_CXXFLAGS += -Wextra-semi
|
||||
endif
|
||||
endif
|
||||
125
scripts/make-release-checks.sh
Executable file
125
scripts/make-release-checks.sh
Executable file
@@ -0,0 +1,125 @@
|
||||
#!/bin/bash
|
||||
# Run all pre-release checks and determine the release version.
|
||||
#
|
||||
# Usage: make-release-checks.sh [--dry-run]
|
||||
# --dry-run: warn on failures instead of aborting
|
||||
#
|
||||
# Env (when running in GitHub Actions):
|
||||
# GH_TOKEN, GITHUB_REPOSITORY, GITHUB_OUTPUT
|
||||
# RELEASE_BRANCH: when set, HEAD must belong to origin/RELEASE_BRANCH and must
|
||||
# not be older than 3 days from the branch HEAD (skipped when unset)
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
|
||||
DRY_RUN=false
|
||||
CHECKS_PASSED=true
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
--dry-run) DRY_RUN=true ;;
|
||||
*) echo "Unknown argument: $arg"; exit 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
MAJOR=$(grep "set(WHISPER_VERSION_MAJOR" "$REPO_ROOT/CMakeLists.txt" | sed 's/.*MAJOR \([0-9]*\).*/\1/')
|
||||
MINOR=$(grep "set(WHISPER_VERSION_MINOR" "$REPO_ROOT/CMakeLists.txt" | sed 's/.*MINOR \([0-9]*\).*/\1/')
|
||||
PATCH=$(grep "set(WHISPER_VERSION_PATCH" "$REPO_ROOT/CMakeLists.txt" | sed 's/.*PATCH \([0-9]*\).*/\1/')
|
||||
VERSION="v${MAJOR}.${MINOR}.${PATCH}"
|
||||
echo "Determined version: ${VERSION}"
|
||||
if [[ -n "${GITHUB_OUTPUT:-}" ]]; then
|
||||
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
SHA=$(git rev-parse HEAD)
|
||||
|
||||
echo "Checking that commit ${SHA} belongs to the release branch..."
|
||||
if [[ -z "${RELEASE_BRANCH:-}" ]]; then
|
||||
echo "Warning: RELEASE_BRANCH not set - skipping commit check (local run)"
|
||||
else
|
||||
TIP="origin/${RELEASE_BRANCH}"
|
||||
COMMIT_ERR=""
|
||||
if ! git rev-parse --verify "${TIP}" >/dev/null 2>&1; then
|
||||
COMMIT_ERR="branch ${RELEASE_BRANCH} not found on remote"
|
||||
elif ! git merge-base --is-ancestor "${SHA}" "${TIP}"; then
|
||||
COMMIT_ERR="commit ${SHA} is not part of branch ${RELEASE_BRANCH}"
|
||||
else
|
||||
COMMIT_TS=$(git show -s --format=%ct "${SHA}")
|
||||
TIP_TS=$(git show -s --format=%ct "${TIP}")
|
||||
AGE_DAYS=$(( (TIP_TS - COMMIT_TS) / 86400 ))
|
||||
if (( TIP_TS - COMMIT_TS > 3 * 86400 )); then
|
||||
COMMIT_ERR="commit ${SHA} is ${AGE_DAYS} day(s) older than the HEAD of ${RELEASE_BRANCH} (max: 3)"
|
||||
fi
|
||||
fi
|
||||
if [[ -n "${COMMIT_ERR}" ]]; then
|
||||
if [[ "$DRY_RUN" == "true" ]]; then
|
||||
echo "Warning: ${COMMIT_ERR} (dry run, continuing)."
|
||||
CHECKS_PASSED=false
|
||||
else
|
||||
echo "Error: ${COMMIT_ERR}"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "Commit ${SHA} is on branch ${RELEASE_BRANCH} and within 3 days of its HEAD - OK"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Checking that tag ${VERSION} does not already exist..."
|
||||
if git ls-remote --tags origin "${VERSION}" | grep -q "${VERSION}"; then
|
||||
echo "Error: tag ${VERSION} already exists on remote"
|
||||
exit 1
|
||||
fi
|
||||
echo "Tag ${VERSION} does not exist on remote - OK"
|
||||
|
||||
echo "Checking release.yml status for commit ${SHA}..."
|
||||
if [[ -z "${GITHUB_REPOSITORY:-}" ]]; then
|
||||
echo "Warning: GITHUB_REPOSITORY not set - skipping CI check (local run)"
|
||||
else
|
||||
RUNS=$(gh api "repos/${GITHUB_REPOSITORY}/actions/workflows/release.yml/runs?per_page=100" \
|
||||
--jq "[.workflow_runs[] | select(.head_sha == \"${SHA}\" and .conclusion == \"success\")] | length")
|
||||
if [[ "$RUNS" -eq 0 ]]; then
|
||||
if [[ "$DRY_RUN" == "true" ]]; then
|
||||
echo "Warning: no successful release.yml run found for HEAD (${SHA}) (dry run, continuing)."
|
||||
CHECKS_PASSED=false
|
||||
else
|
||||
echo "Error: no successful release.yml run found for HEAD (${SHA})"
|
||||
echo "The nightly build must complete successfully before making a release."
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "Found successful release.yml run for HEAD."
|
||||
fi
|
||||
fi
|
||||
|
||||
MAJOR=$(grep "set(GGML_VERSION_MAJOR" "$REPO_ROOT/ggml/CMakeLists.txt" | sed 's/.*MAJOR \([0-9]*\).*/\1/')
|
||||
MINOR=$(grep "set(GGML_VERSION_MINOR" "$REPO_ROOT/ggml/CMakeLists.txt" | sed 's/.*MINOR \([0-9]*\).*/\1/')
|
||||
PATCH=$(grep "set(GGML_VERSION_PATCH" "$REPO_ROOT/ggml/CMakeLists.txt" | sed 's/.*PATCH \([0-9]*\).*/\1/')
|
||||
GGML_VERSION="v${MAJOR}.${MINOR}.${PATCH}"
|
||||
echo "Local ggml version: ${GGML_VERSION}"
|
||||
|
||||
if ! git clone --depth 1 --branch "${GGML_VERSION}" https://github.com/ggml-org/ggml.git upstream-ggml 2>/dev/null; then
|
||||
echo "Warning: tag ${GGML_VERSION} not found in upstream ggml - skipping comparison"
|
||||
else
|
||||
echo "Comparing local ggml/ src and include with upstream ${GGML_VERSION}..."
|
||||
DIFF=$(diff -rq "$REPO_ROOT/ggml/src" upstream-ggml/src 2>&1 || true)
|
||||
DIFF+=$(diff -rq "$REPO_ROOT/ggml/include" upstream-ggml/include 2>&1 || true)
|
||||
DIFF+=$(diff "$REPO_ROOT/ggml/CMakeLists.txt" upstream-ggml/CMakeLists.txt 2>&1 || true)
|
||||
rm -rf upstream-ggml
|
||||
if [[ -n "$DIFF" ]]; then
|
||||
echo "local ggml/ differs from upstream ${GGML_VERSION}:"
|
||||
echo "$DIFF"
|
||||
if [[ "$DRY_RUN" == "true" ]]; then
|
||||
echo "Warning: would abort release due to ggml mismatch (dry run, continuing)."
|
||||
CHECKS_PASSED=false
|
||||
else
|
||||
echo "Error: ggml must match upstream before making a release."
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "local ggml/ matches upstream ${GGML_VERSION}"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -n "${GITHUB_OUTPUT:-}" ]]; then
|
||||
echo "checks_passed=${CHECKS_PASSED}" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
87
scripts/make-release-desc.sh
Executable file
87
scripts/make-release-desc.sh
Executable file
@@ -0,0 +1,87 @@
|
||||
#!/bin/bash
|
||||
# Generate the description of a release: the previous release version, the
|
||||
# change log and the link to the nightly release corresponding to the commit being released.
|
||||
#
|
||||
# Usage: make-release-desc.sh <version>
|
||||
# <version>: current release version (v<maj>.<min>.<pat>, the leading v is optional)
|
||||
#
|
||||
# The previous version is the highest plain semver tag (v<maj>.<min>.<pat>)
|
||||
# strictly below <version>. The change log lists all commits between the
|
||||
# previous version tag and the release commit, one line per commit.
|
||||
#
|
||||
# The release commit is the commit <version> points at when the tag exists,
|
||||
# HEAD otherwise. The nightly release is the b* tag pointing at that commit
|
||||
# (release.yml tags the same commit); the link is only generated when that
|
||||
# tag exists.
|
||||
#
|
||||
# Env (when running in GitHub Actions):
|
||||
# GITHUB_OUTPUT: previous_tag, changelog_title, changelog and nightly are written here
|
||||
# GITHUB_REPOSITORY: owner/repo, used to build the nightly release URL (skipped when unset)
|
||||
set -euo pipefail
|
||||
|
||||
if [[ $# -ne 1 ]]; then
|
||||
echo "Usage: $(basename "$0") <version>"
|
||||
exit 1
|
||||
fi
|
||||
VERSION="$1"
|
||||
|
||||
# Accept the version with or without the leading v, reject anything else
|
||||
if [[ "${VERSION}" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||
VERSION="v${VERSION}"
|
||||
elif [[ ! "${VERSION}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||
echo "Error: invalid version '${VERSION}' (expected v<maj>.<min>.<pat>)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Make sure all remote tags are available locally (skipped on local runs without origin)
|
||||
if ! git fetch --tags origin 2>/dev/null; then
|
||||
echo "Warning: could not fetch tags from origin (local run?)"
|
||||
fi
|
||||
|
||||
# Release commit: the commit <version> points at when the tag exists, HEAD otherwise.
|
||||
if ! RELEASE_COMMIT="$(git rev-parse -q --verify "refs/tags/${VERSION}^{commit}" 2>/dev/null)"; then
|
||||
RELEASE_COMMIT="$(git rev-parse HEAD)"
|
||||
fi
|
||||
|
||||
echo "Release commit: $(git rev-parse --short "${RELEASE_COMMIT}")"
|
||||
|
||||
PREV="$( { git tag --list; echo "${VERSION}"; } \
|
||||
| grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' \
|
||||
| sort -V \
|
||||
| awk -v cur="${VERSION}" '$0 == cur { exit } { prev = $0 } END { print prev }')"
|
||||
|
||||
if [[ -n "${PREV}" ]]; then
|
||||
CHANGELOG="$(git log --oneline "${PREV}..${RELEASE_COMMIT}")"
|
||||
CHANGELOG_TITLE="Changelog since ${PREV}"
|
||||
else
|
||||
CHANGELOG="(no previous release tag found)"
|
||||
CHANGELOG_TITLE="Changelog"
|
||||
fi
|
||||
|
||||
# Nightly release: the b* tag pointing at the release commit (|| true: no match is not an error)
|
||||
NIGHTLY_TAG="$(git tag --points-at "${RELEASE_COMMIT}" | grep -E '(^|-)b[0-9]+(-[0-9a-f]{7})?$' | head -n 1 || true)"
|
||||
|
||||
NIGHTLY=""
|
||||
if [[ -n "${NIGHTLY_TAG}" ]]; then
|
||||
if [[ -n "${GITHUB_REPOSITORY:-}" ]]; then
|
||||
NIGHTLY_URL="https://github.com/${GITHUB_REPOSITORY}/releases/tag/${NIGHTLY_TAG}"
|
||||
NIGHTLY="**Nightly build:** [${NIGHTLY_TAG}](${NIGHTLY_URL})"
|
||||
echo "Nightly release: ${NIGHTLY_URL}"
|
||||
fi
|
||||
else
|
||||
echo "No nightly release found for commit $(git rev-parse --short "${RELEASE_COMMIT}")"
|
||||
fi
|
||||
|
||||
echo "Previous version: ${PREV:-none}"
|
||||
echo "${CHANGELOG}"
|
||||
|
||||
if [[ -n "${GITHUB_OUTPUT:-}" ]]; then
|
||||
{
|
||||
echo "previous_tag=${PREV}"
|
||||
echo "changelog_title=${CHANGELOG_TITLE}"
|
||||
echo "nightly=${NIGHTLY}"
|
||||
echo "changelog<<CHANGELOG_EOF"
|
||||
echo "${CHANGELOG}"
|
||||
echo "CHANGELOG_EOF"
|
||||
} >> "${GITHUB_OUTPUT}"
|
||||
fi
|
||||
37
scripts/quantize-all.sh
Executable file
37
scripts/quantize-all.sh
Executable file
@@ -0,0 +1,37 @@
|
||||
#!/bin/bash
|
||||
|
||||
printf "Usage: $0 <upload>"
|
||||
|
||||
if [ $# -ne 1 ]; then
|
||||
printf "\nError: Invalid number of arguments\n"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
qtype0="q5_0"
|
||||
qtype1="q5_1"
|
||||
upload="$1"
|
||||
declare -a filedex
|
||||
|
||||
cd `dirname $0`
|
||||
cd ../
|
||||
|
||||
for i in `ls ./models | grep ^ggml-.*.bin | grep -v "\-q"`; do
|
||||
m="models/$i"
|
||||
if [ -f "$m" ]; then
|
||||
if [ "${m##*.}" == "bin" ]; then
|
||||
./build/bin/whisper-quantize "${m}" "${m::${#m}-4}-${qtype1}.bin" ${qtype1};
|
||||
./build/bin/whisper-quantize "${m}" "${m::${#m}-4}-${qtype0}.bin" ${qtype0};
|
||||
filedex+=( "${m::${#m}-4}-${qtype1}.bin" "${m::${#m}-4}-${qtype0}.bin" )
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
|
||||
if [ "$upload" == "1" ]; then
|
||||
for i in ${!filedex[@]}; do
|
||||
if [ "${filedex[$i]:9:8}" != "for-test" ]; then
|
||||
scp ${filedex[$i]} root@linode0:/mnt/Data/ggml/ggml-model-${filedex[$i]:9}
|
||||
fi
|
||||
done
|
||||
fi
|
||||
15
scripts/quantize-parakeet.sh
Executable file
15
scripts/quantize-parakeet.sh
Executable file
@@ -0,0 +1,15 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
build_dir=build
|
||||
modelname=ggml-parakeet-tdt-0.6b-v3
|
||||
model=models/${modelname}-f32.bin
|
||||
cmd=parakeet-quantize
|
||||
|
||||
cmake --build ${build_dir} --target $cmd -j 12
|
||||
|
||||
${build_dir}/bin/${cmd} $model models/${modelname}-q8_0.bin q8_0
|
||||
${build_dir}/bin/${cmd} $model models/${modelname}-q4_0.bin q4_0
|
||||
${build_dir}/bin/${cmd} $model models/${modelname}-q4_k.bin q4_k
|
||||
${build_dir}/bin/${cmd} $model models/${modelname}-q2_k.bin q2_k
|
||||
204
scripts/release.sh
Executable file
204
scripts/release.sh
Executable file
@@ -0,0 +1,204 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Release preparation script for whisper.cpp.
|
||||
#
|
||||
# Bumps the version in CMakeLists.txt on a release candidate branch.
|
||||
# The branch should then be pushed and a PR created, reviewed, and
|
||||
# merged. After the PR is merged and the build-cpu workflow has
|
||||
# completed successfully, the release is finalized by the make-release
|
||||
# workflow (.github/workflows/make-release.yml), which creates the tag.
|
||||
#
|
||||
# Usage:
|
||||
# ./scripts/release.sh [major|minor|patch] [--dry-run]
|
||||
#
|
||||
# Example:
|
||||
# $ ./scripts/release.sh minor
|
||||
#
|
||||
# The script:
|
||||
# 1. Creates a release candidate branch (whisper-rc-v<major>.<minor>.<patch>)
|
||||
# 2. Bumps the version in CMakeLists.txt
|
||||
# 3. Commits the version bump
|
||||
#
|
||||
|
||||
set -e
|
||||
|
||||
if [ ! -f "CMakeLists.txt" ] || [ ! -d "scripts" ]; then
|
||||
echo "Error: Must be run from whisper.cpp root directory"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Parse command line arguments
|
||||
VERSION_TYPE=""
|
||||
DRY_RUN=false
|
||||
|
||||
for arg in "$@"; do
|
||||
case $arg in
|
||||
--dry-run)
|
||||
DRY_RUN=true
|
||||
;;
|
||||
major|minor|patch)
|
||||
VERSION_TYPE="$arg"
|
||||
;;
|
||||
*)
|
||||
echo "Error: Unknown argument '$arg'"
|
||||
echo "Usage: $0 [major|minor|patch] [--dry-run]"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Default to patch if no version type specified
|
||||
VERSION_TYPE="${VERSION_TYPE:-patch}"
|
||||
|
||||
# Common validation functions
|
||||
check_git_status() {
|
||||
# Check for uncommitted changes (skip in dry-run)
|
||||
if [ "$DRY_RUN" = false ] && ! git diff-index --quiet HEAD --; then
|
||||
echo "Error: You have uncommitted changes. Please commit or stash them first."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
check_master_branch() {
|
||||
# Ensure we're on master branch
|
||||
CURRENT_BRANCH=$(git branch --show-current)
|
||||
if [ "$CURRENT_BRANCH" != "master" ]; then
|
||||
if [ "$DRY_RUN" = true ]; then
|
||||
echo "[dry run] Warning: Not on master branch (currently on: $CURRENT_BRANCH). Continuing with dry-run..."
|
||||
echo ""
|
||||
else
|
||||
echo "Error: Must be on master branch. Currently on: $CURRENT_BRANCH"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
check_master_up_to_date() {
|
||||
# Check if we have the latest from master (skip in dry-run)
|
||||
if [ "$DRY_RUN" = false ]; then
|
||||
echo "Checking if local master is up-to-date with remote..."
|
||||
git fetch origin master
|
||||
LOCAL=$(git rev-parse HEAD)
|
||||
REMOTE=$(git rev-parse origin/master)
|
||||
|
||||
if [ "$LOCAL" != "$REMOTE" ]; then
|
||||
echo "Error: Your local master branch is not up-to-date with origin/master."
|
||||
echo "Please run 'git pull origin master' first."
|
||||
exit 1
|
||||
fi
|
||||
echo "✓ Local master is up-to-date with remote"
|
||||
echo ""
|
||||
elif [ "$(git branch --show-current)" = "master" ]; then
|
||||
echo "[dry run] Warning: Dry-run mode - not checking if master is up-to-date with remote"
|
||||
echo ""
|
||||
fi
|
||||
}
|
||||
|
||||
# In-place sed that works on both GNU (Linux) and BSD (macOS) sed
|
||||
sed_inplace() {
|
||||
if sed --version >/dev/null 2>&1; then
|
||||
sed -i "$@"
|
||||
else
|
||||
sed -i '' "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
prepare_release() {
|
||||
if [ "$DRY_RUN" = true ]; then
|
||||
echo "[dry-run] Preparing release (no changes will be made)"
|
||||
else
|
||||
echo "Starting release preparation..."
|
||||
fi
|
||||
echo ""
|
||||
|
||||
check_git_status
|
||||
check_master_branch
|
||||
check_master_up_to_date
|
||||
|
||||
# Extract current version from CMakeLists.txt
|
||||
echo "Step 1: Reading current version..."
|
||||
MAJOR=$(grep "set(WHISPER_VERSION_MAJOR" CMakeLists.txt | sed 's/.*MAJOR \([0-9]*\).*/\1/')
|
||||
MINOR=$(grep "set(WHISPER_VERSION_MINOR" CMakeLists.txt | sed 's/.*MINOR \([0-9]*\).*/\1/')
|
||||
PATCH=$(grep "set(WHISPER_VERSION_PATCH" CMakeLists.txt | sed 's/.*PATCH \([0-9]*\).*/\1/')
|
||||
|
||||
echo "Current version: $MAJOR.$MINOR.$PATCH"
|
||||
|
||||
# Calculate new version
|
||||
case $VERSION_TYPE in
|
||||
major)
|
||||
NEW_MAJOR=$((MAJOR + 1))
|
||||
NEW_MINOR=0
|
||||
NEW_PATCH=0
|
||||
;;
|
||||
minor)
|
||||
NEW_MAJOR=$MAJOR
|
||||
NEW_MINOR=$((MINOR + 1))
|
||||
NEW_PATCH=0
|
||||
;;
|
||||
patch)
|
||||
NEW_MAJOR=$MAJOR
|
||||
NEW_MINOR=$MINOR
|
||||
NEW_PATCH=$((PATCH + 1))
|
||||
;;
|
||||
esac
|
||||
|
||||
NEW_VERSION="$NEW_MAJOR.$NEW_MINOR.$NEW_PATCH"
|
||||
RC_BRANCH="whisper-rc-v$NEW_VERSION"
|
||||
echo "New release version: $NEW_VERSION"
|
||||
echo "Release candidate branch: $RC_BRANCH"
|
||||
echo ""
|
||||
|
||||
# Create release candidate branch
|
||||
echo "Step 2: Creating release candidate branch..."
|
||||
if [ "$DRY_RUN" = true ]; then
|
||||
echo " [dry-run] Would create branch: $RC_BRANCH"
|
||||
else
|
||||
git checkout -b "$RC_BRANCH"
|
||||
echo "✓ Created and switched to branch: $RC_BRANCH"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Update CMakeLists.txt for release
|
||||
echo "Step 3: Updating version in CMakeLists.txt..."
|
||||
if [ "$DRY_RUN" = true ]; then
|
||||
echo " [dry-run] Would update WHISPER_VERSION_MAJOR to $NEW_MAJOR"
|
||||
echo " [dry-run] Would update WHISPER_VERSION_MINOR to $NEW_MINOR"
|
||||
echo " [dry-run] Would update WHISPER_VERSION_PATCH to $NEW_PATCH"
|
||||
else
|
||||
sed_inplace -e "s/set(WHISPER_VERSION_MAJOR [0-9]*)/set(WHISPER_VERSION_MAJOR $NEW_MAJOR)/" CMakeLists.txt
|
||||
sed_inplace -e "s/set(WHISPER_VERSION_MINOR [0-9]*)/set(WHISPER_VERSION_MINOR $NEW_MINOR)/" CMakeLists.txt
|
||||
sed_inplace -e "s/set(WHISPER_VERSION_PATCH [0-9]*)/set(WHISPER_VERSION_PATCH $NEW_PATCH)/" CMakeLists.txt
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Commit version bump
|
||||
echo "Step 4: Committing version bump..."
|
||||
if [ "$DRY_RUN" = true ]; then
|
||||
echo " [dry-run] Would commit: 'whisper : bump version to $NEW_VERSION'"
|
||||
else
|
||||
git add CMakeLists.txt
|
||||
git commit -m "whisper : bump version to $NEW_VERSION"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
echo ""
|
||||
if [ "$DRY_RUN" = true ]; then
|
||||
echo "[dry-run] Summary (no changes were made):"
|
||||
echo " • Would have created branch: $RC_BRANCH"
|
||||
echo " • Would have updated version to: $NEW_VERSION"
|
||||
else
|
||||
echo "Release preparation completed!"
|
||||
echo "Summary:"
|
||||
echo " • Created branch: $RC_BRANCH"
|
||||
echo " • Updated version to: $NEW_VERSION"
|
||||
echo ""
|
||||
echo "Next steps:"
|
||||
echo " • Push branch to remote: git push origin $RC_BRANCH"
|
||||
echo " • Create a Pull Request from $RC_BRANCH to master"
|
||||
echo " • After the PR is merged run the following workflows:"
|
||||
echo " • release workflow (.github/workflows/release.xml), creates a developer/nightly release"
|
||||
echo " • make-release workflow (.github/workflows/make-release.yml)"
|
||||
fi
|
||||
}
|
||||
|
||||
prepare_release
|
||||
7
scripts/sha-all.sh
Executable file
7
scripts/sha-all.sh
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Compute the SHA1 of all model files in ./models/ggml-*.bin
|
||||
|
||||
for f in ./models/ggml-*.bin; do
|
||||
shasum "$f" -a 1
|
||||
done
|
||||
160
scripts/sync-ggml-am.sh
Executable file
160
scripts/sync-ggml-am.sh
Executable file
@@ -0,0 +1,160 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Synchronize ggml changes to whisper.cpp
|
||||
#
|
||||
# Usage:
|
||||
#
|
||||
# $ cd /path/to/whisper.cpp
|
||||
# $ ./scripts/sync-ggml-am.sh -skip hash0,hash1,hash2...
|
||||
#
|
||||
|
||||
set -e
|
||||
|
||||
sd=$(dirname $0)
|
||||
cd $sd/../
|
||||
|
||||
SRC_WHISPER=$(pwd)
|
||||
SRC_GGML=$(cd ../ggml; pwd)
|
||||
|
||||
if [ ! -d $SRC_GGML ]; then
|
||||
echo "ggml not found at $SRC_GGML"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
lc=$(cat $SRC_WHISPER/scripts/sync-ggml.last)
|
||||
echo "Syncing ggml changes since commit $lc"
|
||||
|
||||
to_skip=""
|
||||
|
||||
# context for git patches in number of lines
|
||||
ctx="8"
|
||||
|
||||
while [ "$1" != "" ]; do
|
||||
case $1 in
|
||||
-skip )
|
||||
shift
|
||||
to_skip=$1
|
||||
;;
|
||||
-C )
|
||||
shift
|
||||
ctx=$1
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
cd $SRC_GGML
|
||||
|
||||
git log --oneline $lc..HEAD
|
||||
git log --oneline $lc..HEAD --reverse | grep -v "(whisper/[0-9]*)" | cut -d' ' -f1 > $SRC_WHISPER/ggml-commits
|
||||
|
||||
if [ ! -s $SRC_WHISPER/ggml-commits ]; then
|
||||
rm -v $SRC_WHISPER/ggml-commits
|
||||
echo "No new commits"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ -f $SRC_WHISPER/ggml-src.patch ]; then
|
||||
rm -v $SRC_WHISPER/ggml-src.patch
|
||||
fi
|
||||
|
||||
while read c; do
|
||||
if [ -n "$to_skip" ]; then
|
||||
if [[ $to_skip == *"$c"* ]]; then
|
||||
echo "Skipping $c"
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
|
||||
git format-patch -U${ctx} -k $c~1..$c --stdout -- \
|
||||
CMakeLists.txt \
|
||||
src/CMakeLists.txt \
|
||||
cmake/BuildTypes.cmake \
|
||||
cmake/GitVars.cmake \
|
||||
cmake/common.cmake \
|
||||
cmake/ggml-config.cmake.in \
|
||||
src/ggml-cpu/cmake/FindSIMD.cmake \
|
||||
src/ggml* \
|
||||
src/gguf* \
|
||||
include/ggml*.h \
|
||||
include/gguf*.h \
|
||||
examples/common.h \
|
||||
examples/common.cpp \
|
||||
examples/common-ggml.h \
|
||||
examples/common-ggml.cpp \
|
||||
LICENSE \
|
||||
scripts/gen-authors.sh \
|
||||
>> $SRC_WHISPER/ggml-src.patch
|
||||
done < $SRC_WHISPER/ggml-commits
|
||||
|
||||
rm -v $SRC_WHISPER/ggml-commits
|
||||
|
||||
# delete files if empty
|
||||
if [ ! -s $SRC_WHISPER/ggml-src.patch ]; then
|
||||
rm -v $SRC_WHISPER/ggml-src.patch
|
||||
fi
|
||||
|
||||
cd $SRC_WHISPER
|
||||
|
||||
if [ -f $SRC_WHISPER/ggml-src.patch ]; then
|
||||
# replace PR numbers
|
||||
#
|
||||
# Subject: some text (#1234)
|
||||
# Subject: some text (ggml/1234)
|
||||
cat ggml-src.patch | sed -e 's/^Subject: \(.*\) (#\([0-9]*\))/Subject: \1 (ggml\/\2)/' > ggml-src.patch.tmp
|
||||
mv ggml-src.patch.tmp ggml-src.patch
|
||||
|
||||
cat ggml-src.patch | sed -e 's/^\(.*\) (#\([0-9]*\))$/\1 (ggml\/\2)/' > ggml-src.patch.tmp
|
||||
mv ggml-src.patch.tmp ggml-src.patch
|
||||
|
||||
# replace filenames:
|
||||
#
|
||||
# CMakelists.txt -> ggml/CMakeLists.txt
|
||||
# src/CMakeLists.txt -> ggml/src/CMakeLists.txt
|
||||
|
||||
# cmake/BuildTypes.cmake -> ggml/cmake/BuildTypes.cmake
|
||||
# cmake/GitVars.cmake -> ggml/cmake/GitVars.cmake
|
||||
# cmake/common.cmake -> ggml/cmake/common.cmake
|
||||
# cmake/ggml-config.cmake.in -> ggml/cmake/ggml-config.cmake.in
|
||||
# src/ggml-cpu/cmake/FindSIMD.cmake -> ggml/src/ggml-cpu/cmake/FindSIMD.cmake
|
||||
#
|
||||
# src/ggml* -> ggml/src/ggml*
|
||||
#
|
||||
# include/ggml*.h -> ggml/include/ggml*.h
|
||||
# include/gguf*.h -> ggml/include/gguf*.h
|
||||
#
|
||||
# tests/test*.cpp -> tests/
|
||||
#
|
||||
# LICENSE -> LICENSE
|
||||
# scripts/gen-authors.sh -> scripts/gen-authors.sh
|
||||
|
||||
cat ggml-src.patch | sed -E \
|
||||
-e 's/([[:space:]]| [ab]\/)CMakeLists.txt/\1ggml\/CMakeLists.txt/g' \
|
||||
-e 's/([[:space:]]| [ab]\/)src\/CMakeLists.txt/\1ggml\/src\/CMakeLists.txt/g' \
|
||||
-e 's/([[:space:]]| [ab]\/)cmake\/BuildTypes.cmake/\1ggml\/cmake\/BuildTypes.cmake/g' \
|
||||
-e 's/([[:space:]]| [ab]\/)cmake\/GitVars.cmake/\1ggml\/cmake\/GitVars.cmake/g' \
|
||||
-e 's/([[:space:]]| [ab]\/)cmake\/common.cmake/\1ggml\/cmake\/common.cmake/g' \
|
||||
-e 's/([[:space:]]| [ab]\/)cmake\/ggml-config.cmake.in/\1ggml\/cmake\/ggml-config.cmake.in/g' \
|
||||
-e 's/([[:space:]]| [ab]\/)src\/ggml-cpu\/cmake\/FindSIMD.cmake/\1ggml\/src\/ggml-cpu\/cmake\/FindSIMD.cmake/g' \
|
||||
-e 's/([[:space:]]| [ab]\/)src\/ggml(.*)/\1ggml\/src\/ggml\2/g' \
|
||||
-e 's/([[:space:]]| [ab]\/)src\/gguf(.*)/\1ggml\/src\/gguf\2/g' \
|
||||
-e 's/([[:space:]]| [ab]\/)include\/ggml(.*)\.h/\1ggml\/include\/ggml\2.h/g' \
|
||||
-e 's/([[:space:]]| [ab]\/)include\/gguf(.*)\.h/\1ggml\/include\/gguf\2.h/g' \
|
||||
-e 's/([[:space:]]| [ab]\/)tests\/(.*)\.cpp/\1tests\/\2.cpp/g' \
|
||||
-e 's/([[:space:]]| [ab]\/)LICENSE/\1LICENSE/g' \
|
||||
-e 's/([[:space:]]| [ab]\/)scripts\/gen-authors\.sh/\1scripts\/gen-authors.sh/g' \
|
||||
> ggml-src.patch.tmp
|
||||
mv ggml-src.patch.tmp ggml-src.patch
|
||||
|
||||
git am ggml-src.patch
|
||||
|
||||
rm -v $SRC_WHISPER/ggml-src.patch
|
||||
fi
|
||||
|
||||
# update last commit
|
||||
cd $SRC_GGML
|
||||
git log -1 --format=%H > $SRC_WHISPER/scripts/sync-ggml.last
|
||||
|
||||
echo "Done"
|
||||
|
||||
exit 0
|
||||
1
scripts/sync-ggml.last
Normal file
1
scripts/sync-ggml.last
Normal file
@@ -0,0 +1 @@
|
||||
456172ec733a135778adcd32d00e576a58232e45
|
||||
21
scripts/sync-ggml.sh
Executable file
21
scripts/sync-ggml.sh
Executable file
@@ -0,0 +1,21 @@
|
||||
#!/bin/bash
|
||||
|
||||
cp -rpv ../ggml/CMakeLists.txt ./ggml/CMakeLists.txt
|
||||
cp -rpv ../ggml/src/CMakeLists.txt ./ggml/src/CMakeLists.txt
|
||||
|
||||
cp -rpv ../ggml/cmake/* ./ggml/cmake/
|
||||
cp -rpv ../ggml/src/ggml-cpu/cmake/* ./ggml/src/ggml-cpu/cmake/
|
||||
|
||||
cp -rpv ../ggml/src/ggml* ./ggml/src/
|
||||
cp -rpv ../ggml/src/gguf* ./ggml/src/
|
||||
|
||||
cp -rpv ../ggml/include/ggml*.h ./ggml/include/
|
||||
cp -rpv ../ggml/include/gguf*.h ./ggml/include/
|
||||
|
||||
cp -rpv ../ggml/examples/common.h ./examples/common.h
|
||||
cp -rpv ../ggml/examples/common.cpp ./examples/common.cpp
|
||||
cp -rpv ../ggml/examples/common-ggml.h ./examples/common-ggml.h
|
||||
cp -rpv ../ggml/examples/common-ggml.cpp ./examples/common-ggml.cpp
|
||||
|
||||
cp -rpv ../ggml/LICENSE ./LICENSE
|
||||
cp -rpv ../ggml/scripts/gen-authors.sh ./scripts/gen-authors.sh
|
||||
20
scripts/sync-llama.sh
Executable file
20
scripts/sync-llama.sh
Executable file
@@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
# note: run from the whisper.cpp root directory
|
||||
set -euo pipefail
|
||||
|
||||
# read the current llama.cpp version from the neighboring repo
|
||||
LLAMA_VERSION=$(sed -nE 's/^set\(LLAMA_VERSION_(MAJOR|MINOR|PATCH) ([0-9]+)\)$/\2/p' ../llama.cpp/CMakeLists.txt | paste -sd. -)
|
||||
|
||||
if [ -z "${LLAMA_VERSION}" ]; then
|
||||
echo "error: could not read llama.cpp version from ../llama.cpp/CMakeLists.txt" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# update the version number in examples/talk-llama/CMakeLists.txt
|
||||
sed -i.bak \
|
||||
-E -e "s/(find_package[(]llama )[0-9]+\.[0-9]+\.[0-9]+/\1${LLAMA_VERSION}/" \
|
||||
-e "s/(set[(]LLAMA_TAG \"v)[0-9]+\.[0-9]+\.[0-9]+/\1${LLAMA_VERSION}/" \
|
||||
examples/talk-llama/CMakeLists.txt
|
||||
rm examples/talk-llama/CMakeLists.txt.bak
|
||||
|
||||
echo "synced llama.cpp version: ${LLAMA_VERSION}"
|
||||
157
scripts/upload-parakeet.py
Normal file
157
scripts/upload-parakeet.py
Normal file
@@ -0,0 +1,157 @@
|
||||
import argparse
|
||||
import os
|
||||
from huggingface_hub import HfApi, create_repo
|
||||
|
||||
USER_NAME = "ggml-org"
|
||||
REPO_ID = f"{USER_NAME}/parakeet-GGUF"
|
||||
|
||||
MODELS = {
|
||||
"f32": {
|
||||
"local_path": "models/ggml-parakeet-tdt-0.6b-v3-f32.bin",
|
||||
"remote_name": "ggml-parakeet-tdt-0.6b-v3-f32.bin",
|
||||
"description": "Full precision (F32)",
|
||||
},
|
||||
"f16": {
|
||||
"local_path": "models/ggml-parakeet-tdt-0.6b-v3-f16.bin",
|
||||
"remote_name": "ggml-parakeet-tdt-0.6b-v3-f16.bin",
|
||||
"description": "Half precision (F16)",
|
||||
},
|
||||
"q8_0": {
|
||||
"local_path": "models/ggml-parakeet-tdt-0.6b-v3-q8_0.bin",
|
||||
"remote_name": "ggml-parakeet-tdt-0.6b-v3-q8_0.bin",
|
||||
"description": "8-bit quantized (Q8_0)",
|
||||
},
|
||||
"q4_0": {
|
||||
"local_path": "models/ggml-parakeet-tdt-0.6b-v3-q4_0.bin",
|
||||
"remote_name": "ggml-parakeet-tdt-0.6b-v3-q4_0.bin",
|
||||
"description": "4-bit quantized (Q4_0)",
|
||||
},
|
||||
"q4_k": {
|
||||
"local_path": "models/ggml-parakeet-tdt-0.6b-v3-q4_k.bin",
|
||||
"remote_name": "ggml-parakeet-tdt-0.6b-v3-q4_k.bin",
|
||||
"description": "4-bit K-quantized (Q4_k)",
|
||||
},
|
||||
}
|
||||
|
||||
def build_model_card(uploaded_variants):
|
||||
lines = [
|
||||
f"---",
|
||||
f"license: mit",
|
||||
f"base_model: nvidia/parakeet-tdt-0.6b-v3",
|
||||
f"tags:",
|
||||
f"- gguf",
|
||||
f"- asr",
|
||||
f"---",
|
||||
f"",
|
||||
f"# Parakeet TDT 0.6B v3 (GGUF)",
|
||||
f"",
|
||||
f"GGUF conversions of [nvidia/parakeet-tdt-0.6b-v3](https://huggingface.co/nvidia/parakeet-tdt-0.6b-v3) for use with [whisper.cpp](https://github.com/ggml-org/whisper.cpp).",
|
||||
f"",
|
||||
f"## Available files",
|
||||
f"",
|
||||
]
|
||||
|
||||
for key, m in MODELS.items():
|
||||
if key in uploaded_variants:
|
||||
lines.append(f"- `{m['remote_name']}` — {m['description']}")
|
||||
|
||||
lines += [
|
||||
f"",
|
||||
f"## Usage",
|
||||
f"",
|
||||
f"Build parakeet-cli:",
|
||||
f"```console",
|
||||
f"git clone https://github.com/ggml-org/whisper.cpp.git",
|
||||
f"cd whisper.cpp",
|
||||
f"cmake -B build -S .",
|
||||
f"cmake --build build --target parakeet-cli -j $(nproc)",
|
||||
f"```",
|
||||
f"",
|
||||
f"Download a model (e.g. Q8_0):",
|
||||
f"```console",
|
||||
f"hf download {REPO_ID} {MODELS['q8_0']['remote_name']} --local-dir models",
|
||||
f"```",
|
||||
f"",
|
||||
f"Run:",
|
||||
f"```console",
|
||||
f"./build/bin/parakeet-cli -m models/{MODELS['q8_0']['remote_name']} -f samples/jfk.wav",
|
||||
f"```",
|
||||
f"",
|
||||
]
|
||||
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def upload_variant(api, key):
|
||||
m = MODELS[key]
|
||||
local_path = m["local_path"]
|
||||
|
||||
if not os.path.exists(local_path):
|
||||
print(f" Skipping {key}: {local_path} not found")
|
||||
return False
|
||||
|
||||
print(f" Uploading {m['remote_name']} ({m['description']})...")
|
||||
api.upload_file(
|
||||
path_or_fileobj=local_path,
|
||||
path_in_repo=m["remote_name"],
|
||||
repo_id=REPO_ID,
|
||||
repo_type="model",
|
||||
commit_message=f"Upload {m['remote_name']}",
|
||||
)
|
||||
return True
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Upload parakeet GGUF models to Hugging Face")
|
||||
parser.add_argument(
|
||||
"variants",
|
||||
nargs="*",
|
||||
default=None,
|
||||
metavar="{" + ",".join(MODELS.keys()) + "}",
|
||||
help="Model variants to upload (default: all)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--no-model-card",
|
||||
action="store_true",
|
||||
help="Skip updating the model card README",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
api = HfApi()
|
||||
create_repo(repo_id=REPO_ID, repo_type="model", exist_ok=True)
|
||||
|
||||
variants = args.variants if args.variants else list(MODELS.keys())
|
||||
|
||||
unknown = [v for v in variants if v not in MODELS]
|
||||
if unknown:
|
||||
parser.error(f"unknown variant(s): {', '.join(unknown)} (choose from {', '.join(MODELS.keys())})")
|
||||
|
||||
uploaded = []
|
||||
for key in variants:
|
||||
if upload_variant(api, key):
|
||||
uploaded.append(key)
|
||||
|
||||
if not uploaded:
|
||||
print("No models were uploaded.")
|
||||
return
|
||||
|
||||
if not args.no_model_card:
|
||||
print("Updating model card...")
|
||||
existing = [k for k in MODELS if k in uploaded or
|
||||
any(f.rfilename == MODELS[k]["remote_name"]
|
||||
for f in api.list_repo_files(REPO_ID, repo_type="model")
|
||||
if hasattr(f, "rfilename"))]
|
||||
card = build_model_card(existing if existing else uploaded)
|
||||
api.upload_file(
|
||||
path_or_fileobj=card.encode(),
|
||||
path_in_repo="README.md",
|
||||
repo_id=REPO_ID,
|
||||
repo_type="model",
|
||||
commit_message="Update README.md",
|
||||
)
|
||||
|
||||
print(f"\nDone. Repository: https://huggingface.co/{REPO_ID}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user