-
Notifications
You must be signed in to change notification settings - Fork 440
swift am2 compile wip #1877
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
swift am2 compile wip #1877
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1 @@ | ||
| swift-lib/.build | ||
| temp-resolver/ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,15 +1,101 @@ | ||
| fn main() { | ||
| // Build skipped - uncomment below to re-enable Swift linking | ||
|
|
||
| // #[cfg(target_os = "macos")] | ||
| // { | ||
| // swift_rs::SwiftLinker::new("13.0") | ||
| // .with_package("swift-lib", "./swift-lib/") | ||
| // .link(); | ||
| // } | ||
| // | ||
| // #[cfg(not(target_os = "macos"))] | ||
| // { | ||
| // println!("cargo:warning=Swift linking is only available on macOS"); | ||
| // } | ||
| #[cfg(target_os = "macos")] | ||
| { | ||
| use std::path::Path; | ||
| use std::process::Command; | ||
|
|
||
| let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR")); | ||
| let swift_lib_path = manifest_dir.join("swift-lib"); | ||
| let frameworks_dir = swift_lib_path.join("frameworks"); | ||
| let xcframework_dest = frameworks_dir.join("ArgmaxSDK.xcframework"); | ||
|
|
||
| if !xcframework_dest.exists() { | ||
| println!("cargo:warning=ArgmaxSDK.xcframework not found, extracting from registry..."); | ||
|
|
||
| let temp_dir = manifest_dir.join("temp-resolver"); | ||
| std::fs::create_dir_all(&temp_dir).expect("Failed to create temp directory"); | ||
|
|
||
| let resolver_package = r#"// swift-tools-version:5.10 | ||
| import PackageDescription | ||
| let package = Package( | ||
| name: "resolver", | ||
| platforms: [.macOS(.v13)], | ||
| dependencies: [ | ||
| .package(id: "argmaxinc.argmax-sdk-swift", exact: "1.9.3") | ||
| ], | ||
| targets: [] | ||
| ) | ||
| "#; | ||
| std::fs::write(temp_dir.join("Package.swift"), resolver_package) | ||
| .expect("Failed to write resolver Package.swift"); | ||
|
|
||
| let status = Command::new("swift") | ||
| .args(["package", "resolve"]) | ||
| .current_dir(&temp_dir) | ||
| .status() | ||
| .expect("Failed to run swift package resolve"); | ||
|
|
||
| if !status.success() { | ||
| panic!("swift package resolve failed"); | ||
| } | ||
|
|
||
| let artifacts_path = temp_dir.join( | ||
| ".build/artifacts/argmaxinc.argmax-sdk-swift/ArgmaxSDK/ArgmaxSDK.xcframework", | ||
| ); | ||
|
|
||
| if !artifacts_path.exists() { | ||
| panic!( | ||
| "ArgmaxSDK.xcframework not found in artifacts at: {:?}", | ||
| artifacts_path | ||
| ); | ||
| } | ||
|
|
||
| std::fs::create_dir_all(&frameworks_dir) | ||
| .expect("Failed to create frameworks directory"); | ||
|
|
||
| let status = Command::new("cp") | ||
| .args([ | ||
| "-R", | ||
| artifacts_path.to_str().unwrap(), | ||
| xcframework_dest.to_str().unwrap(), | ||
| ]) | ||
| .status() | ||
| .expect("Failed to copy xcframework"); | ||
|
|
||
| if !status.success() { | ||
| panic!("Failed to copy ArgmaxSDK.xcframework"); | ||
| } | ||
|
|
||
| std::fs::remove_dir_all(&temp_dir).ok(); | ||
|
|
||
| println!("cargo:warning=ArgmaxSDK.xcframework extracted successfully"); | ||
| } | ||
|
|
||
| let out_dir = std::env::var("OUT_DIR").unwrap(); | ||
| let swift_build_dir = Path::new(&out_dir).join("swift-rs/swift-lib"); | ||
| let workspace_state = swift_build_dir.join("workspace-state.json"); | ||
| if workspace_state.exists() { | ||
| std::fs::remove_file(&workspace_state).ok(); | ||
| } | ||
|
|
||
| swift_rs::SwiftLinker::new("13.0") | ||
| .with_package("swift-lib", "./swift-lib/") | ||
| .link(); | ||
|
|
||
| let framework_path = xcframework_dest.join("macos-arm64"); | ||
| println!( | ||
| "cargo:rustc-link-search=framework={}", | ||
| framework_path.display() | ||
| ); | ||
| println!("cargo:rustc-link-lib=framework=ArgmaxSDK"); | ||
| println!( | ||
| "cargo:rustc-link-arg=-Wl,-rpath,{}", | ||
| framework_path.display() | ||
| ); | ||
| } | ||
|
|
||
| #[cfg(not(target_os = "macos"))] | ||
| { | ||
| println!("cargo:warning=Swift linking is only available on macOS"); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,26 +1,53 @@ | ||
| use swift_rs::swift; | ||
| use swift_rs::{swift, SRString}; | ||
|
|
||
| swift!(fn initialize_am2_sdk()); | ||
| swift!(fn initialize_am2_sdk(api_key: &SRString)); | ||
|
|
||
| swift!(fn check_am2_ready() -> bool); | ||
|
|
||
| pub fn init() { | ||
| swift!(fn transcribe_audio_file(path: &SRString) -> SRString); | ||
|
|
||
| pub fn init(api_key: &str) { | ||
| let key = SRString::from(api_key); | ||
| unsafe { | ||
| initialize_am2_sdk(); | ||
| initialize_am2_sdk(&key); | ||
| } | ||
| } | ||
|
|
||
| pub fn is_ready() -> bool { | ||
| unsafe { check_am2_ready() } | ||
| } | ||
|
|
||
| pub fn transcribe(audio_path: &str) -> String { | ||
| let path = SRString::from(audio_path); | ||
| unsafe { transcribe_audio_file(&path).to_string() } | ||
| } | ||
|
|
||
| #[cfg(test)] | ||
| mod tests { | ||
| use super::*; | ||
|
|
||
| #[test] | ||
| fn test_am2_swift_compilation() { | ||
| init(); | ||
| let api_key = std::env::var("AM_API_KEY").expect("AM_API_KEY env var required"); | ||
| init(&api_key); | ||
| assert!(is_ready()); | ||
| } | ||
|
|
||
| #[test] | ||
| fn test_transcribe_audio() { | ||
| let api_key = std::env::var("AM_API_KEY").expect("AM_API_KEY env var required"); | ||
| init(&api_key); | ||
|
|
||
| let audio_path = concat!( | ||
| env!("CARGO_MANIFEST_DIR"), | ||
| "/../data/src/english_1/audio.wav" | ||
| ); | ||
| println!("Audio path: {}", audio_path); | ||
|
|
||
| let result = transcribe(audio_path); | ||
| println!("Transcription result: {}", result); | ||
|
|
||
| assert!(!result.is_empty()); | ||
| assert!(!result.starts_with("Error:")); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| .build/ | ||
| frameworks/ | ||
|
|
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,10 +1,10 @@ | ||
| // swift-tools-version:6.0 | ||
| // swift-tools-version:5.10 | ||
|
|
||
| import PackageDescription | ||
|
|
||
| let package = Package( | ||
| name: "swift-lib", | ||
| platforms: [.macOS("13.0")], | ||
| platforms: [.macOS(.v13)], | ||
| products: [ | ||
| .library( | ||
| name: "swift-lib", | ||
|
|
@@ -15,24 +15,21 @@ let package = Package( | |
| .package( | ||
| url: "https://github.com/Brendonovich/swift-rs", | ||
| revision: "01980f981bc642a6da382cc0788f18fdd4cde6df"), | ||
| .package( | ||
| id: "argmaxinc.argmax-sdk-swift", | ||
| exact: "1.9.3"), | ||
| .package( | ||
| url: "https://github.com/huggingface/swift-transformers.git", | ||
| exact: "0.1.24") | ||
| .package(url: "https://github.com/argmaxinc/WhisperKit.git", exact: "0.14.1") | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chainVerify WhisperKit version 0.14.1 is current and stable. Using 🌐 Web query: 💡 Result: WhisperKit v0.14.1 was released on Oct 17, 2025. The latest release is v0.15.0 (marked "Latest") published on Nov 7, 2025. [1] [1] argmaxinc/WhisperKit releases on GitHub. WhisperKit 0.14.1 is outdated; consider upgrading to 0.15.0. WhisperKit v0.14.1 was released on Oct 17, 2025, but the latest release is v0.15.0 (published Nov 7, 2025). Using exact version pinning on 0.14.1 locks the dependency to an older release. Unless there's a specific reason to avoid 0.15.0, consider updating to the latest stable version or switching to 🤖 Prompt for AI Agents |
||
| ], | ||
| targets: [ | ||
| .binaryTarget( | ||
| name: "ArgmaxSDK", | ||
| path: "frameworks/ArgmaxSDK.xcframework" | ||
| ), | ||
|
Comment on lines
+21
to
+24
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chainVerify ArgmaxSDK.xcframework exists at the specified path. Binary targets require the xcframework to be present at build time. Ensure 🏁 Script executed: #!/bin/bash
# Description: Verify ArgmaxSDK.xcframework exists at the expected location
# Check if the xcframework directory exists
fd -t d "ArgmaxSDK.xcframework" crates/am2/swift-lib
# Also check if there's a download script or documentation for obtaining the framework
fd -e sh -e md . crates/am2/swift-lib | xargs -I {} sh -c 'echo "=== {} ===" && head -30 {}'Length of output: 0 🏁 Script executed: #!/bin/bash
# Description: Comprehensive verification of ArgmaxSDK.xcframework and related files
echo "=== Checking directory structure ==="
ls -la crates/am2/swift-lib/ 2>/dev/null || echo "crates/am2/swift-lib does not exist"
echo -e "\n=== Searching for ArgmaxSDK.xcframework anywhere in repo ==="
find . -name "*ArgmaxSDK*" -o -name "*.xcframework" 2>/dev/null | head -20
echo -e "\n=== Checking .gitignore for binary/framework patterns ==="
cat .gitignore 2>/dev/null | grep -E "(\.xcframework|frameworks|binary|\.xcarchive)" || echo "No matching patterns in .gitignore"
echo -e "\n=== Checking Package.swift file context ==="
cat crates/am2/swift-lib/Package.swift 2>/dev/null || echo "Package.swift not found"
echo -e "\n=== Looking for build/download scripts in swift-lib ==="
find crates/am2/swift-lib -type f \( -name "*.sh" -o -name "Makefile" -o -name "*.yaml" -o -name "*.yml" \) 2>/dev/null
echo -e "\n=== Searching for ArgmaxSDK mentions in repo ==="
rg -i "ArgmaxSDK" --type swift --type text -B2 -A2 | head -40Length of output: 1548 🏁 Script executed: #!/bin/bash
# Description: Comprehensive verification of ArgmaxSDK.xcframework and related files
echo "=== Checking directory structure ==="
ls -la crates/am2/swift-lib/ 2>/dev/null || echo "crates/am2/swift-lib does not exist"
echo -e "\n=== Searching for ArgmaxSDK.xcframework anywhere in repo ==="
find . -name "*ArgmaxSDK*" -o -name "*.xcframework" 2>/dev/null | head -20
echo -e "\n=== Checking .gitignore for binary/framework patterns ==="
cat .gitignore 2>/dev/null | grep -E "(\.xcframework|frameworks|binary|\.xcarchive)" || echo "No matching patterns in .gitignore"
echo -e "\n=== Checking Package.swift file context ==="
cat crates/am2/swift-lib/Package.swift 2>/dev/null || echo "Package.swift not found"
echo -e "\n=== Looking for build/download scripts in swift-lib ==="
find crates/am2/swift-lib -type f \( -name "*.sh" -o -name "Makefile" -o -name "*.yaml" -o -name "*.yml" \) 2>/dev/null
echo -e "\n=== Searching for ArgmaxSDK mentions in repo ==="
rg -i "ArgmaxSDK" --type swift --type text -B2 -A2 | head -40Length of output: 1548 Add frameworks directory with ArgmaxSDK.xcframework or remove the binary target dependency. The
🤖 Prompt for AI Agents |
||
| .target( | ||
| name: "swift-lib", | ||
| dependencies: [ | ||
| .product(name: "SwiftRs", package: "swift-rs"), | ||
| .product(name: "Argmax", package: "argmaxinc.argmax-sdk-swift") | ||
| .product(name: "WhisperKit", package: "WhisperKit"), | ||
| "ArgmaxSDK" | ||
| ], | ||
| path: "src", | ||
| swiftSettings: [ | ||
| .swiftLanguageMode(.v5) | ||
| ] | ||
| path: "src" | ||
| ) | ||
| ] | ||
| ) | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -1,17 +1,58 @@ | ||||||
| import Argmax | ||||||
| import ArgmaxSDK | ||||||
| import Foundation | ||||||
| import SwiftRs | ||||||
|
|
||||||
| private var isAM2Ready = false | ||||||
| private var whisperKitPro: WhisperKitPro? | ||||||
|
|
||||||
| @_cdecl("initialize_am2_sdk") | ||||||
| public func initialize_am2_sdk() { | ||||||
| isAM2Ready = true | ||||||
| print("AM2 SDK initialized successfully") | ||||||
| public func initialize_am2_sdk(apiKey: SRString) { | ||||||
| let key = apiKey.toString() | ||||||
| let semaphore = DispatchSemaphore(value: 0) | ||||||
|
|
||||||
| Task { | ||||||
| await ArgmaxSDK.with(ArgmaxConfig(apiKey: key)) | ||||||
| isAM2Ready = true | ||||||
| print("AM2 SDK initialized successfully with API key: \(key.prefix(10))...") | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Avoid logging API key prefixes. Logging even the first 10 characters of an API key could expose sensitive information in logs. Consider removing or masking this entirely. - print("AM2 SDK initialized successfully with API key: \(key.prefix(10))...")
+ print("AM2 SDK initialized successfully")📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||
| semaphore.signal() | ||||||
| } | ||||||
|
|
||||||
| semaphore.wait() | ||||||
| } | ||||||
|
|
||||||
| @_cdecl("check_am2_ready") | ||||||
| public func check_am2_ready() -> Bool { | ||||||
| return isAM2Ready | ||||||
| } | ||||||
|
|
||||||
| @_cdecl("transcribe_audio_file") | ||||||
| public func transcribe_audio_file(path: SRString) -> SRString { | ||||||
| let audioPath = path.toString() | ||||||
| print("Transcribing: \(audioPath)") | ||||||
|
|
||||||
| var result = "" | ||||||
|
|
||||||
| let semaphore = DispatchSemaphore(value: 0) | ||||||
|
|
||||||
| Task { | ||||||
| do { | ||||||
| let config = WhisperKitProConfig(model: "large-v3-v20240930_626MB") | ||||||
| let kit = try await WhisperKitPro(config) | ||||||
| whisperKitPro = kit | ||||||
|
|
||||||
| print("WhisperKitPro initialized, starting transcription...") | ||||||
|
|
||||||
| let results = try await kit.transcribe(audioPath: audioPath) | ||||||
| let transcript = WhisperKitProUtils.mergeTranscriptionResults(results).text | ||||||
| result = transcript | ||||||
| print("Transcription complete: \(result)") | ||||||
| } catch { | ||||||
| result = "Error: \(error.localizedDescription)" | ||||||
| print("Transcription error: \(error)") | ||||||
| } | ||||||
| semaphore.signal() | ||||||
| } | ||||||
|
|
||||||
| semaphore.wait() | ||||||
| return SRString(result) | ||||||
| } | ||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hardcoded
macos-arm64breaks Intel Mac builds.The xcframework path hardcodes
macos-arm64, which will fail on Intel-based Macs. XCFrameworks contain architecture-specific slices that must be selected based on the build target.📝 Committable suggestion
🤖 Prompt for AI Agents