Skip to content

Commit e7b8828

Browse files
committed
Fix cross-compiling Apple targets with cmake 3.14
1 parent c9df4fa commit e7b8828

File tree

1 file changed

+140
-2
lines changed

1 file changed

+140
-2
lines changed

src/lib.rs

Lines changed: 140 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -318,14 +318,16 @@ impl Config {
318318
let host = self.host.clone().unwrap_or_else(|| getenv_unwrap("HOST"));
319319
let msvc = target_triplet.contains("msvc");
320320
let ndk = self.uses_android_ndk();
321+
let target = Target::new(&target_triplet);
322+
let no_default_flags = ndk || target.is_ios_target();
321323
let mut c_cfg = cc::Build::new();
322324
c_cfg
323325
.cargo_metadata(false)
324326
.opt_level(0)
325327
.debug(false)
326328
.warnings(false)
327329
.host(&host)
328-
.no_default_flags(ndk);
330+
.no_default_flags(no_default_flags);
329331
if !ndk {
330332
c_cfg.target(&target_triplet);
331333
}
@@ -337,7 +339,7 @@ impl Config {
337339
.debug(false)
338340
.warnings(false)
339341
.host(&host)
340-
.no_default_flags(ndk);
342+
.no_default_flags(no_default_flags);
341343
if !ndk {
342344
cxx_cfg.target(&target_triplet);
343345
}
@@ -479,6 +481,32 @@ impl Config {
479481
if !self.defined("CMAKE_SYSTEM_NAME") {
480482
cmd.arg("-DCMAKE_SYSTEM_NAME=SunOS");
481483
}
484+
} else if target.is_apple_target() {
485+
if !self.defined("CMAKE_OSX_ARCHITECTURES") {
486+
if let Some(cmake_target_arch) = target.cmake_target_arch() {
487+
cmd.arg(format!("-DCMAKE_OSX_ARCHITECTURES={}", cmake_target_arch));
488+
}
489+
}
490+
491+
if !self.defined("CMAKE_OSX_SYSROOT") {
492+
if let Some(sdk_name) = target.sdk_name() {
493+
cmd.arg(format!("-DCMAKE_OSX_SYSROOT={}", sdk_name));
494+
}
495+
}
496+
497+
if !self.defined("CMAKE_OSX_DEPLOYMENT_TARGET") {
498+
if let Some(deployment_target) = target.deployment_target() {
499+
cmd.arg(format!("-DCMAKE_OSX_DEPLOYMENT_TARGET={}", deployment_target));
500+
}
501+
}
502+
503+
if target.is_cross_compiling() {
504+
if !self.defined("CMAKE_SYSTEM_NAME") {
505+
if let Some(cmake_system_name) = target.cmake_system_name() {
506+
cmd.arg(format!("-DCMAKE_SYSTEM_NAME={}", cmake_system_name));
507+
}
508+
}
509+
}
482510
}
483511
if let Some(ref generator) = self.generator {
484512
cmd.arg("-G").arg(generator);
@@ -592,6 +620,11 @@ impl Config {
592620
flagsflag.push(" ");
593621
flagsflag.push(arg);
594622
}
623+
if no_default_flags {
624+
if target.is_ios_target() {
625+
flagsflag.push(" -fPIC -fembed-bitcode");
626+
}
627+
}
595628
cmd.arg(flagsflag);
596629
}
597630

@@ -835,6 +868,111 @@ impl Config {
835868
}
836869
}
837870

871+
struct Target {
872+
rust_target: String,
873+
rust_target_arch: String,
874+
rust_target_vendor: String,
875+
rust_target_platform: String,
876+
}
877+
878+
impl Target {
879+
pub fn new(target_triplet: &str) -> Target {
880+
let parts: Vec<&str> = target_triplet.split('-').collect();
881+
if parts.len() < 3 {
882+
fail(&format!("target triplet not in the form arch-vendor-platform: {}", target_triplet));
883+
}
884+
885+
Target {
886+
rust_target: target_triplet.to_owned(),
887+
rust_target_arch: parts[0].to_owned(),
888+
rust_target_vendor: parts[1].to_owned(),
889+
rust_target_platform: parts[2].to_owned(),
890+
}
891+
}
892+
893+
fn is_apple_target(&self) -> bool {
894+
self.is_ios_target() || self.is_osx_target()
895+
}
896+
897+
fn is_ios_target(&self) -> bool {
898+
&self.rust_target_vendor == "apple" && &self.rust_target_platform == "ios"
899+
}
900+
901+
fn is_osx_target(&self) -> bool {
902+
&self.rust_target_vendor == "apple" && &self.rust_target_platform == "darwin"
903+
}
904+
905+
fn is_cross_compiling(&self) -> bool {
906+
self.is_ios_target()
907+
}
908+
909+
fn cmake_system_name(&self) -> Option<String> {
910+
if !self.is_cross_compiling() {
911+
eprintln!("Warning: cmake_system_name should only be used for cross-compiled targets. Target: {}", self.rust_target);
912+
None
913+
} else if self.is_ios_target() {
914+
Some("iOS".to_owned())
915+
} else {
916+
eprintln!("Warning: unknown system name for target: {}", self.rust_target);
917+
None
918+
}
919+
}
920+
921+
fn cmake_target_arch(&self) -> Option<String> {
922+
if !self.is_apple_target() {
923+
eprintln!("Warning: sdk_name only supported for Apple targets. Target: {}", self.rust_target);
924+
None
925+
} else {
926+
match self.rust_target_arch.as_str() {
927+
"aarch64" => Some("arm64".to_owned()),
928+
"armv7" => Some("armv7".to_owned()),
929+
"armv7s" => Some("armv7s".to_owned()),
930+
"i386" => Some("i386".to_owned()),
931+
"x86_64" => Some("x86_64".to_owned()),
932+
_ => {
933+
eprintln!("Warning: unknown architecture for target: {}", self.rust_target_arch);
934+
None
935+
}
936+
}
937+
}
938+
}
939+
940+
fn sdk_name(&self) -> Option<String> {
941+
if !self.is_apple_target() {
942+
eprintln!("Warning: sdk_name only supported for Apple targets. Target: {}", self.rust_target);
943+
None
944+
} else if self.is_ios_target() {
945+
match self.rust_target_arch.as_str() {
946+
"aarch64" | "armv7" | "armv7s" => Some("iphoneos".to_owned()),
947+
"i386" | "x86_64" => Some("iphonesimulator".to_owned()),
948+
_ => {
949+
eprintln!("Warning: unknown architecture for Apple target: {}", self.rust_target_arch);
950+
None
951+
},
952+
}
953+
} else if self.is_osx_target() {
954+
Some("macosx".to_owned())
955+
} else {
956+
eprintln!("Warning: unknown sdk name for target: {}", self.rust_target);
957+
None
958+
}
959+
}
960+
961+
fn deployment_target(&self) -> Option<String> {
962+
if !self.is_apple_target() {
963+
eprintln!("Warning: deployment_target only supported for Apple targets. Target: {}", self.rust_target);
964+
None
965+
} else if self.is_ios_target() {
966+
Some(std::env::var("IPHONEOS_DEPLOYMENT_TARGET").unwrap_or_else(|_| "7.0".into()))
967+
} else if self.is_osx_target() {
968+
Some(std::env::var("MACOSX_DEPLOYMENT_TARGET").unwrap_or_else(|_| "10.6".into()))
969+
} else {
970+
eprintln!("Warning: unknown deployment target for target: {}", self.rust_target);
971+
None
972+
}
973+
}
974+
}
975+
838976
fn run(cmd: &mut Command, program: &str) {
839977
println!("running: {:?}", cmd);
840978
let status = match cmd.status() {

0 commit comments

Comments
 (0)