Skip to content

Commit c9de51d

Browse files
committed
Apple: Rebuild when deployment target changes
Rebuild when the `*_DEPLOYMENT_TARGET` variables change when building Apple targets. This is done by: 1. Adding it as a tracked variable to `Options` to make sure it clears the incremental cache. 2. Emitting the variable in `--emit=dep-info` (`.d`) files, so that Cargo can pick up changes to it, and correctly trigger a rebuild.
1 parent 7b608a3 commit c9de51d

File tree

6 files changed

+55
-22
lines changed

6 files changed

+55
-22
lines changed

compiler/rustc_interface/src/passes.rs

+15-10
Original file line numberDiff line numberDiff line change
@@ -391,8 +391,7 @@ fn escape_dep_filename(filename: &str) -> String {
391391

392392
// Makefile comments only need escaping newlines and `\`.
393393
// The result can be unescaped by anything that can unescape `escape_default` and friends.
394-
fn escape_dep_env(symbol: Symbol) -> String {
395-
let s = symbol.as_str();
394+
fn escape_dep_env(s: &str) -> String {
396395
let mut escaped = String::with_capacity(s.len());
397396
for c in s.chars() {
398397
match c {
@@ -492,16 +491,22 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P
492491

493492
// Emit special comments with information about accessed environment variables.
494493
let env_depinfo = sess.psess.env_depinfo.borrow();
494+
495+
// We will soon sort, so the initial order does not matter.
496+
#[allow(rustc::potential_query_instability)]
497+
let mut env_depinfo: Vec<_> = env_depinfo
498+
.iter()
499+
.map(|(k, v)| (escape_dep_env(k.as_str()), v.map(|v| escape_dep_env(v.as_str()))))
500+
.chain(tcx.sess.target.is_like_osx.then(|| {
501+
// On Apple targets, we also depend on the deployment target environment variable.
502+
let name = rustc_target::spec::apple_deployment_target_env(&tcx.sess.target.os);
503+
(name.into(), std::env::var(name).ok().map(|var| escape_dep_env(&var)))
504+
}))
505+
.collect();
506+
env_depinfo.sort_unstable();
495507
if !env_depinfo.is_empty() {
496-
// We will soon sort, so the initial order does not matter.
497-
#[allow(rustc::potential_query_instability)]
498-
let mut envs: Vec<_> = env_depinfo
499-
.iter()
500-
.map(|(k, v)| (escape_dep_env(*k), v.map(escape_dep_env)))
501-
.collect();
502-
envs.sort_unstable();
503508
writeln!(file)?;
504-
for (k, v) in envs {
509+
for (k, v) in env_depinfo {
505510
write!(file, "# env-dep:{k}")?;
506511
if let Some(v) = v {
507512
write!(file, "={v}")?;

compiler/rustc_session/src/config.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1164,6 +1164,7 @@ impl Default for Options {
11641164
color: ColorConfig::Auto,
11651165
logical_env: FxIndexMap::default(),
11661166
verbose: false,
1167+
apple_deployment_target_env: None,
11671168
}
11681169
}
11691170
}
@@ -2710,6 +2711,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
27102711
color,
27112712
logical_env,
27122713
verbose,
2714+
apple_deployment_target_env: None,
27132715
}
27142716
}
27152717

compiler/rustc_session/src/options.rs

+9
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,15 @@ top_level_options!(
222222
color: ColorConfig [UNTRACKED],
223223

224224
verbose: bool [TRACKED_NO_CRATE_HASH],
225+
226+
/// The raw value of the `*_DEPLOYMENT_TARGET` environment variable
227+
/// for the selected target OS.
228+
///
229+
/// The exact environment variable to use depends on the target that
230+
/// the user has chosen, and we do not want to re-compile if an
231+
/// unrelated deployment target environment variable changed, so we
232+
/// defer the initialization of this to `build_session`.
233+
apple_deployment_target_env: Option<String> [TRACKED],
225234
}
226235
);
227236

compiler/rustc_session/src/session.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -1006,7 +1006,7 @@ fn default_emitter(
10061006
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
10071007
pub fn build_session(
10081008
early_dcx: EarlyDiagCtxt,
1009-
sopts: config::Options,
1009+
mut sopts: config::Options,
10101010
io: CompilerIO,
10111011
bundle: Option<Lrc<rustc_errors::FluentBundle>>,
10121012
registry: rustc_errors::registry::Registry,
@@ -1110,6 +1110,13 @@ pub fn build_session(
11101110

11111111
let asm_arch = if target.allow_asm { InlineAsmArch::from_str(&target.arch).ok() } else { None };
11121112

1113+
// Configure the deployment target for change-tracking, now that target
1114+
// details are available.
1115+
if target.is_like_osx {
1116+
let name = rustc_target::spec::apple_deployment_target_env(&target.os);
1117+
sopts.apple_deployment_target_env = std::env::var(name).ok();
1118+
}
1119+
11131120
let sess = Session {
11141121
target,
11151122
host,

compiler/rustc_target/src/spec/base/apple/mod.rs

+20-11
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,19 @@ pub fn platform(target: &Target) -> Option<u32> {
251251
})
252252
}
253253

254+
/// Name of the environment variable used to fetch the deployment target on
255+
/// the given OS.
256+
pub fn deployment_target_env(os: &str) -> &'static str {
257+
match os {
258+
"macos" => "MACOSX_DEPLOYMENT_TARGET",
259+
"ios" => "IPHONEOS_DEPLOYMENT_TARGET",
260+
"watchos" => "WATCHOS_DEPLOYMENT_TARGET",
261+
"tvos" => "TVOS_DEPLOYMENT_TARGET",
262+
"visionos" => "XROS_DEPLOYMENT_TARGET",
263+
_ => unreachable!("tried to get deployment target env var for non-Apple platform"),
264+
}
265+
}
266+
254267
/// Hack for calling `deployment_target` outside of this module.
255268
pub fn deployment_target_for_target(target: &Target) -> (u16, u8, u8) {
256269
let arch = if target.llvm_target.starts_with("arm64e") {
@@ -300,17 +313,13 @@ fn deployment_target(os: &str, arch: Arch, abi: TargetAbi) -> (u16, u8, u8) {
300313
_ => os_min,
301314
};
302315

303-
// The environment variable used to fetch the deployment target.
304-
let env_var = match os {
305-
"macos" => "MACOSX_DEPLOYMENT_TARGET",
306-
"ios" => "IPHONEOS_DEPLOYMENT_TARGET",
307-
"watchos" => "WATCHOS_DEPLOYMENT_TARGET",
308-
"tvos" => "TVOS_DEPLOYMENT_TARGET",
309-
"visionos" => "XROS_DEPLOYMENT_TARGET",
310-
_ => unreachable!("tried to get deployment target env var for non-Apple platform"),
311-
};
312-
313-
if let Ok(deployment_target) = env::var(env_var) {
316+
// NOTE: We access the deployment target environment variable here, which
317+
// makes the variable an **implicit** input which affects compilation.
318+
//
319+
// We make sure to rebuild when the variable changes, both by busting the
320+
// incremental cache, and by telling Cargo that it is a dependency.
321+
// Search for usages of `deployment_target_env` to see how.
322+
if let Ok(deployment_target) = env::var(deployment_target_env(os)) {
314323
match parse_version(&deployment_target) {
315324
// It is common that the deployment target is set too low, e.g. on
316325
// macOS Aarch64 to also target older x86_64, the user may set a

compiler/rustc_target/src/spec/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ pub mod crt_objects;
6060

6161
mod base;
6262
pub use base::apple::{
63+
deployment_target_env as apple_deployment_target_env,
6364
deployment_target_for_target as current_apple_deployment_target,
6465
platform as current_apple_platform, sdk_version as current_apple_sdk_version,
6566
};

0 commit comments

Comments
 (0)