Skip to content

Commit cb7f25b

Browse files
committed
feat: add iOS support
1 parent 408345d commit cb7f25b

File tree

2 files changed

+78
-2
lines changed

2 files changed

+78
-2
lines changed

llama-cpp-2/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ system-ggml = ["llama-cpp-sys-2/system-ggml"]
4242
llguidance = ["dep:llguidance", "dep:toktrie"]
4343

4444

45-
[target.'cfg(all(target_os = "macos", any(target_arch = "aarch64", target_arch = "arm64")))'.dependencies]
45+
[target.'cfg(all(any(target_os = "macos", target_os = "ios"), any(target_arch = "aarch64", target_arch = "arm64")))'.dependencies]
4646
llama-cpp-sys-2 = { path = "../llama-cpp-sys-2", version = "0.1.138", features = [
4747
"metal",
4848
] }

llama-cpp-sys-2/build.rs

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ enum WindowsVariant {
1212

1313
enum AppleVariant {
1414
MacOS,
15+
IOSDevice,
16+
IOSSimulator,
1517
Other,
1618
}
1719

@@ -42,6 +44,10 @@ fn parse_target_os() -> Result<(TargetOs, String), String> {
4244
} else if target.contains("apple") {
4345
if target.ends_with("-apple-darwin") {
4446
Ok((TargetOs::Apple(AppleVariant::MacOS), target))
47+
} else if target == "aarch64-apple-ios" {
48+
Ok((TargetOs::Apple(AppleVariant::IOSDevice), target))
49+
} else if target == "aarch64-apple-ios-sim" {
50+
Ok((TargetOs::Apple(AppleVariant::IOSSimulator), target))
4551
} else {
4652
Ok((TargetOs::Apple(AppleVariant::Other), target))
4753
}
@@ -168,6 +174,41 @@ fn macos_link_search_path() -> Option<String> {
168174
None
169175
}
170176

177+
fn xcrun_sdk_path(sdk: &str) -> Result<String, String> {
178+
let output = Command::new("xcrun")
179+
.arg("--sdk")
180+
.arg(sdk)
181+
.arg("--show-sdk-path")
182+
.output()
183+
.map_err(|e| format!("Failed to run xcrun for SDK '{sdk}': {e}"))?;
184+
185+
if !output.status.success() {
186+
return Err(format!(
187+
"xcrun failed for SDK '{sdk}': {}",
188+
String::from_utf8_lossy(&output.stderr)
189+
));
190+
}
191+
192+
let sdk_path = String::from_utf8_lossy(&output.stdout).trim().to_string();
193+
if sdk_path.is_empty() {
194+
return Err(format!("xcrun returned an empty SDK path for '{sdk}'"));
195+
}
196+
197+
Ok(sdk_path)
198+
}
199+
200+
fn ios_deployment_target() -> String {
201+
env::var("IOS_DEPLOYMENT_TARGET").unwrap_or_else(|_| "16.4".to_string())
202+
}
203+
204+
fn clang_target_for(target_triple: &str) -> &str {
205+
match target_triple {
206+
"aarch64-apple-ios" => "arm64-apple-ios",
207+
"aarch64-apple-ios-sim" => "arm64-apple-ios-simulator",
208+
_ => target_triple,
209+
}
210+
}
211+
171212
fn validate_android_ndk(ndk_path: &str) -> Result<(), String> {
172213
let ndk_path = Path::new(ndk_path);
173214

@@ -220,6 +261,7 @@ fn main() {
220261
println!("cargo:rerun-if-env-changed=LLAMA_LIB_PROFILE");
221262
println!("cargo:rerun-if-env-changed=LLAMA_BUILD_SHARED_LIBS");
222263
println!("cargo:rerun-if-env-changed=LLAMA_STATIC_CRT");
264+
println!("cargo:rerun-if-env-changed=IOS_DEPLOYMENT_TARGET");
223265

224266
debug_log!("TARGET: {}", target_triple);
225267
debug_log!("CARGO_MANIFEST_DIR: {}", manifest_dir);
@@ -422,6 +464,23 @@ fn main() {
422464
}
423465
}
424466

467+
if matches!(
468+
target_os,
469+
TargetOs::Apple(AppleVariant::IOSDevice | AppleVariant::IOSSimulator)
470+
) {
471+
let sdk_name = match target_os {
472+
TargetOs::Apple(AppleVariant::IOSDevice) => "iphoneos",
473+
TargetOs::Apple(AppleVariant::IOSSimulator) => "iphonesimulator",
474+
_ => unreachable!(),
475+
};
476+
let sdk_path = xcrun_sdk_path(sdk_name).unwrap_or_else(|e| panic!("{e}"));
477+
478+
bindings_builder = bindings_builder
479+
.clang_arg(format!("--target={}", clang_target_for(&target_triple)))
480+
.clang_arg("-isysroot")
481+
.clang_arg(sdk_path);
482+
}
483+
425484
// Fix bindgen header discovery on Windows MSVC
426485
// Use cc crate to discover MSVC include paths by compiling a dummy file
427486
if matches!(target_os, TargetOs::Windows(WindowsVariant::Msvc)) {
@@ -623,6 +682,23 @@ fn main() {
623682
config.define("GGML_BLAS", "OFF");
624683
}
625684

685+
if matches!(
686+
target_os,
687+
TargetOs::Apple(AppleVariant::IOSDevice | AppleVariant::IOSSimulator)
688+
) {
689+
let ios_sysroot = match target_os {
690+
TargetOs::Apple(AppleVariant::IOSDevice) => "iphoneos",
691+
TargetOs::Apple(AppleVariant::IOSSimulator) => "iphonesimulator",
692+
_ => unreachable!(),
693+
};
694+
695+
config.define("CMAKE_SYSTEM_NAME", "iOS");
696+
config.define("CMAKE_OSX_SYSROOT", ios_sysroot);
697+
config.define("CMAKE_OSX_ARCHITECTURES", "arm64");
698+
config.define("CMAKE_OSX_DEPLOYMENT_TARGET", ios_deployment_target());
699+
config.define("LLAMA_OPENSSL", "OFF");
700+
}
701+
626702
if (matches!(target_os, TargetOs::Windows(WindowsVariant::Msvc))
627703
&& matches!(
628704
profile.as_str(),
@@ -1049,7 +1125,7 @@ fn main() {
10491125
println!("cargo:rustc-link-search={}", path);
10501126
}
10511127
}
1052-
AppleVariant::Other => (),
1128+
AppleVariant::IOSDevice | AppleVariant::IOSSimulator | AppleVariant::Other => {}
10531129
}
10541130
}
10551131
TargetOs::Android => {

0 commit comments

Comments
 (0)