diff --git a/src/librustc_codegen_ssa/back/command.rs b/src/librustc_codegen_ssa/back/command.rs index 340cc772e5f07..596978f002b66 100644 --- a/src/librustc_codegen_ssa/back/command.rs +++ b/src/librustc_codegen_ssa/back/command.rs @@ -14,6 +14,7 @@ pub struct Command { program: Program, args: Vec, env: Vec<(OsString, OsString)>, + env_remove: Vec, } #[derive(Clone)] @@ -41,6 +42,7 @@ impl Command { program, args: Vec::new(), env: Vec::new(), + env_remove: Vec::new(), } } @@ -75,6 +77,17 @@ impl Command { self.env.push((key.to_owned(), value.to_owned())); } + pub fn env_remove(&mut self, key: K) -> &mut Command + where K: AsRef, + { + self._env_remove(key.as_ref()); + self + } + + fn _env_remove(&mut self, key: &OsStr) { + self.env_remove.push(key.to_owned()); + } + pub fn output(&mut self) -> io::Result { self.command().output() } @@ -100,6 +113,9 @@ impl Command { }; ret.args(&self.args); ret.envs(self.env.clone()); + for k in &self.env_remove { + ret.env_remove(k); + } return ret } diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index 8603d61fb5453..74cde92974c04 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -532,6 +532,9 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(sess: &'a Session, for &(ref k, ref v) in &sess.target.target.options.link_env { cmd.env(k, v); } + for k in &sess.target.target.options.link_env_remove { + cmd.env_remove(k); + } if sess.opts.debugging_opts.print_link_args { println!("{:?}", &cmd); diff --git a/src/librustc_target/spec/apple_base.rs b/src/librustc_target/spec/apple_base.rs index 53364e72bfe3a..f7551aa768dfc 100644 --- a/src/librustc_target/spec/apple_base.rs +++ b/src/librustc_target/spec/apple_base.rs @@ -51,3 +51,19 @@ pub fn macos_llvm_target(arch: &str) -> String { let (major, minor) = macos_deployment_target(); format!("{}-apple-macosx{}.{}.0", arch, major, minor) } + +pub fn macos_link_env_remove() -> Vec { + let mut env_remove = Vec::with_capacity(2); + // Remove the `SDKROOT` environment variable if it's clearly set for the wrong platform, which + // may occur when we're linking a custom build script while targeting iOS for example. + if let Some(sdkroot) = env::var("SDKROOT").ok() { + if sdkroot.contains("iPhoneOS.platform") || sdkroot.contains("iPhoneSimulator.platform") { + env_remove.push("SDKROOT".to_string()) + } + } + // Additionally, `IPHONEOS_DEPLOYMENT_TARGET` must not be set when using the Xcode linker at + // "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld", + // although this is apparently ignored when using the linker at "/usr/bin/ld". + env_remove.push("IPHONEOS_DEPLOYMENT_TARGET".to_string()); + env_remove +} diff --git a/src/librustc_target/spec/apple_ios_base.rs b/src/librustc_target/spec/apple_ios_base.rs index 6d3900c0b203f..fdbb1bd5db34b 100644 --- a/src/librustc_target/spec/apple_ios_base.rs +++ b/src/librustc_target/spec/apple_ios_base.rs @@ -38,9 +38,18 @@ pub fn get_sdk_root(sdk_name: &str) -> Result { // SDKROOT; for rustc, the user or build system can set it, or we // can fall back to checking for xcrun on PATH.) if let Some(sdkroot) = env::var("SDKROOT").ok() { - let sdkroot_path = Path::new(&sdkroot); - if sdkroot_path.is_absolute() && sdkroot_path != Path::new("/") && sdkroot_path.exists() { - return Ok(sdkroot); + let p = Path::new(&sdkroot); + match sdk_name { + // Ignore `SDKROOT` if it's clearly set for the wrong 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") => (), + // Ignore `SDKROOT` if it's not a valid path. + _ if !p.is_absolute() || p == Path::new("/") || !p.exists() => (), + _ => return Ok(sdkroot), } } let res = Command::new("xcrun") @@ -100,6 +109,13 @@ fn target_cpu(arch: Arch) -> String { }.to_string() } +fn link_env_remove(arch: Arch) -> Vec { + match arch { + Armv7 | Armv7s | Arm64 | I386 | X86_64 => vec!["MACOSX_DEPLOYMENT_TARGET".to_string()], + X86_64_macabi => vec!["IPHONEOS_DEPLOYMENT_TARGET".to_string()], + } +} + pub fn opts(arch: Arch) -> Result { let pre_link_args = build_pre_link_args(arch)?; Ok(TargetOptions { @@ -107,6 +123,7 @@ pub fn opts(arch: Arch) -> Result { dynamic_linking: false, executables: true, pre_link_args, + link_env_remove: link_env_remove(arch), has_elf_tls: false, eliminate_frame_pointer: false, .. super::apple_base::opts() diff --git a/src/librustc_target/spec/i686_apple_darwin.rs b/src/librustc_target/spec/i686_apple_darwin.rs index 7d804ea53fb31..27d05823bf21e 100644 --- a/src/librustc_target/spec/i686_apple_darwin.rs +++ b/src/librustc_target/spec/i686_apple_darwin.rs @@ -5,6 +5,7 @@ pub fn target() -> TargetResult { base.cpu = "yonah".to_string(); base.max_atomic_width = Some(64); base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m32".to_string()]); + base.link_env_remove.extend(super::apple_base::macos_link_env_remove()); base.stack_probes = true; base.eliminate_frame_pointer = false; diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index 503d8a08b6f4f..82e74f317de23 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -580,8 +580,10 @@ pub struct TargetOptions { /// user-defined libraries. pub post_link_args: LinkArgs, - /// Environment variables to be set before invoking the linker. + /// Environment variables to be set for the linker invocation. pub link_env: Vec<(String, String)>, + /// Environment variables to be removed for the linker invocation. + pub link_env_remove: Vec, /// Extra arguments to pass to the external assembler (when used) pub asm_args: Vec, @@ -843,6 +845,7 @@ impl Default for TargetOptions { post_link_objects_crt: Vec::new(), late_link_args: LinkArgs::new(), link_env: Vec::new(), + link_env_remove: Vec::new(), archive_format: "gnu".to_string(), custom_unwind_resume: false, allow_asm: true, @@ -1118,6 +1121,7 @@ impl Target { key!(post_link_objects_crt, list); key!(post_link_args, link_args); key!(link_env, env); + key!(link_env_remove, list); key!(asm_args, list); key!(cpu); key!(features); @@ -1334,6 +1338,7 @@ impl ToJson for Target { target_option_val!(post_link_objects_crt); target_option_val!(link_args - post_link_args); target_option_val!(env - link_env); + target_option_val!(link_env_remove); target_option_val!(asm_args); target_option_val!(cpu); target_option_val!(features); diff --git a/src/librustc_target/spec/x86_64_apple_darwin.rs b/src/librustc_target/spec/x86_64_apple_darwin.rs index 182103440f035..d059e44c5c82a 100644 --- a/src/librustc_target/spec/x86_64_apple_darwin.rs +++ b/src/librustc_target/spec/x86_64_apple_darwin.rs @@ -6,6 +6,7 @@ pub fn target() -> TargetResult { base.max_atomic_width = Some(128); // core2 support cmpxchg16b base.eliminate_frame_pointer = false; base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".to_string()]); + base.link_env_remove.extend(super::apple_base::macos_link_env_remove()); base.stack_probes = true; // Clang automatically chooses a more specific target based on