Skip to content

Commit e15260a

Browse files
committed
Fix cross-compiling Apple targets with cmake 3.14
1 parent 6a2ce3d commit e15260a

File tree

1 file changed

+167
-2
lines changed

1 file changed

+167
-2
lines changed

src/lib.rs

Lines changed: 167 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
}
@@ -480,6 +482,35 @@ impl Config {
480482
if !self.defined("CMAKE_SYSTEM_NAME") {
481483
cmd.arg("-DCMAKE_SYSTEM_NAME=SunOS");
482484
}
485+
} else if target.is_apple_target() {
486+
if !self.defined("CMAKE_OSX_ARCHITECTURES") {
487+
if let Some(cmake_target_arch) = target.cmake_target_arch() {
488+
cmd.arg(format!("-DCMAKE_OSX_ARCHITECTURES={}", cmake_target_arch));
489+
}
490+
}
491+
492+
if !self.defined("CMAKE_OSX_SYSROOT") {
493+
if let Some(sdk_name) = target.sdk_name() {
494+
cmd.arg(format!("-DCMAKE_OSX_SYSROOT={}", sdk_name));
495+
}
496+
}
497+
498+
if !self.defined("CMAKE_OSX_DEPLOYMENT_TARGET") {
499+
if let Some(deployment_target) = target.deployment_target() {
500+
cmd.arg(format!(
501+
"-DCMAKE_OSX_DEPLOYMENT_TARGET={}",
502+
deployment_target
503+
));
504+
}
505+
}
506+
507+
if target.is_cross_compiling() {
508+
if !self.defined("CMAKE_SYSTEM_NAME") {
509+
if let Some(cmake_system_name) = target.cmake_system_name() {
510+
cmd.arg(format!("-DCMAKE_SYSTEM_NAME={}", cmake_system_name));
511+
}
512+
}
513+
}
483514
}
484515
if let Some(ref generator) = self.generator {
485516
cmd.arg("-G").arg(generator);
@@ -593,6 +624,11 @@ impl Config {
593624
flagsflag.push(" ");
594625
flagsflag.push(arg);
595626
}
627+
if no_default_flags {
628+
if target.is_ios_target() {
629+
flagsflag.push(" -fPIC -fembed-bitcode");
630+
}
631+
}
596632
cmd.arg(flagsflag);
597633
}
598634

@@ -836,6 +872,135 @@ impl Config {
836872
}
837873
}
838874

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

0 commit comments

Comments
 (0)