From 8521a7fd90bfc58e66d76c0f38e817c751c7112f Mon Sep 17 00:00:00 2001 From: James Farrell <83229348+jfgoog@users.noreply.github.com> Date: Sun, 5 May 2024 21:50:26 -0500 Subject: [PATCH] Don't use the value of SDKROOT if it doesn't match the target. (#1047) * Don't use the value of SDKROOT if it doesn't match the target. The SDKROOT environment variable can be problematic on Mac. In cases where you are compiling for multiple targets, SDKROOT cannot be right for all of them. Furthermore, the system Python interpreter sets SDKROOT to the MacOSX SDK if not already set. So, if you are using a Python script to run a build, and you need to build for multiple targets, the logic in the cc crate doesn't work. This is precisely what is happening with rustc itself, and so we can't upgrade the version of the cc crate used by the bootstrap code. (Unsetting SDKROOT doesn't work either because the custom clang build that rustc uses for CI depends on it being set) * use env::var_os instead of env::var * Fix compilation * Fix compilation error * fix compilation --------- Co-authored-by: Jiahao XU --- src/lib.rs | 37 ++++++++++++++++++++++++++++++++++++- tests/test.rs | 26 ++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 2a47ac31..c6844efb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3651,8 +3651,43 @@ impl Build { } fn apple_sdk_root(&self, sdk: &str) -> Result { + // Code copied from rustc's compiler/rustc_codegen_ssa/src/back/link.rs. if let Some(sdkroot) = env::var_os("SDKROOT") { - return Ok(sdkroot); + let p = PathBuf::from(sdkroot); + let sdkroot = p.to_string_lossy(); + match sdk { + // Ignore `SDKROOT` if it's clearly set for the wrong platform. + "appletvos" + if sdkroot.contains("TVSimulator.platform") + || sdkroot.contains("MacOSX.platform") => {} + "appletvsimulator" + if sdkroot.contains("TVOS.platform") || sdkroot.contains("MacOSX.platform") => { + } + "iphoneos" + if sdkroot.contains("iPhoneSimulator.platform") + || sdkroot.contains("MacOSX.platform") => {} + "iphonesimulator" + if sdkroot.contains("iPhoneOS.platform") + || sdkroot.contains("MacOSX.platform") => {} + "macosx10.15" + if sdkroot.contains("iPhoneOS.platform") + || sdkroot.contains("iPhoneSimulator.platform") => {} + "watchos" + if sdkroot.contains("WatchSimulator.platform") + || sdkroot.contains("MacOSX.platform") => {} + "watchsimulator" + if sdkroot.contains("WatchOS.platform") + || sdkroot.contains("MacOSX.platform") => {} + "xros" + if sdkroot.contains("XRSimulator.platform") + || sdkroot.contains("MacOSX.platform") => {} + "xrsimulator" + if sdkroot.contains("XROS.platform") || sdkroot.contains("MacOSX.platform") => { + } + // Ignore `SDKROOT` if it's not a valid path. + _ if !p.is_absolute() || p == Path::new("/") || !p.exists() => {} + _ => return Ok(p.into()), + } } let mut cache = self diff --git a/tests/test.rs b/tests/test.rs index fac6a67b..e9bbc94a 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -626,6 +626,32 @@ fn clang_apple_visionos() { test.cmd(0).must_not_have("-mxrsimulator-version-min=1.0"); } +#[cfg(target_os = "macos")] +#[test] +fn apple_sdkroot_wrong() { + let output = std::process::Command::new("xcrun") + .args(["--show-sdk-path", "--sdk", "iphoneos"]) + .output() + .unwrap(); + if !output.status.success() { + return; + } + + let wrong_sdkroot = "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk"; + let test = Test::clang(); + test.gcc() + .__set_env("SDKROOT", wrong_sdkroot) + .target("aarch64-apple-ios") + .file("foo.c") + .compile("foo"); + + dbg!(test.cmd(0).args); + + test.cmd(0) + .must_have(std::str::from_utf8(&output.stdout).unwrap().trim()); + test.cmd(0).must_not_have(wrong_sdkroot); +} + #[test] fn compile_intermediates() { let test = Test::gnu();