diff --git a/src/cargo/core/compiler/build_context/mod.rs b/src/cargo/core/compiler/build_context/mod.rs index 78c1e90ae..472559ce3 100644 --- a/src/cargo/core/compiler/build_context/mod.rs +++ b/src/cargo/core/compiler/build_context/mod.rs @@ -134,19 +134,6 @@ impl<'a, 'gctx> BuildContext<'a, 'gctx> { self.build_config.jobs } - /// Extra compiler flags to pass to `rustc` for a given unit. - /// - /// Although it depends on the caller, in the current Cargo implementation, - /// these flags take precedence over those from [`BuildContext::extra_args_for`]. - /// - /// As of now, these flags come from environment variables and configurations. - /// See [`TargetInfo.rustflags`] for more on how Cargo collects them. - /// - /// [`TargetInfo.rustflags`]: TargetInfo::rustflags - pub fn rustflags_args(&self, unit: &Unit) -> &[String] { - &self.target_data.info(unit.kind).rustflags - } - /// Extra compiler flags to pass to `rustdoc` for a given unit. /// /// Although it depends on the caller, in the current Cargo implementation, diff --git a/src/cargo/core/compiler/build_context/target_info.rs b/src/cargo/core/compiler/build_context/target_info.rs index ed4b04dc2..da32c2f89 100644 --- a/src/cargo/core/compiler/build_context/target_info.rs +++ b/src/cargo/core/compiler/build_context/target_info.rs @@ -23,6 +23,7 @@ use std::cell::RefCell; use std::collections::hash_map::{Entry, HashMap}; use std::path::{Path, PathBuf}; use std::str::{self, FromStr}; +use std::sync::Arc; /// Information about the platform target gleaned from querying rustc. /// @@ -52,7 +53,7 @@ pub struct TargetInfo { /// target libraries. pub sysroot_target_libdir: PathBuf, /// Extra flags to pass to `rustc`, see [`extra_args`]. - pub rustflags: Vec, + pub rustflags: Arc<[String]>, /// Extra flags to pass to `rustdoc`, see [`extra_args`]. pub rustdocflags: Vec, /// Whether or not rustc (stably) supports the `--check-cfg` flag. @@ -312,7 +313,7 @@ impl TargetInfo { crate_types: RefCell::new(map), sysroot, sysroot_target_libdir, - rustflags, + rustflags: rustflags.into(), rustdocflags: extra_args( gctx, requested_kinds, @@ -867,7 +868,10 @@ pub struct RustcTargetData<'gctx> { /// Build information for the "host", which is information about when /// `rustc` is invoked without a `--target` flag. This is used for - /// procedural macros, build scripts, etc. + /// selecting a linker, and applying link overrides. + /// + /// The configuration read into this depends on whether or not + /// `target-applies-to-host=true`. host_config: TargetConfig, /// Information about the host platform. host_info: TargetInfo, @@ -889,7 +893,10 @@ impl<'gctx> RustcTargetData<'gctx> { let mut target_config = HashMap::new(); let mut target_info = HashMap::new(); let target_applies_to_host = gctx.target_applies_to_host()?; + let host_target = CompileTarget::new(&rustc.host)?; let host_info = TargetInfo::new(gctx, requested_kinds, &rustc, CompileKind::Host)?; + + // This config is used for link overrides and choosing a linker. let host_config = if target_applies_to_host { gctx.target_cfg_triple(&rustc.host)? } else { @@ -902,9 +909,21 @@ impl<'gctx> RustcTargetData<'gctx> { // needs access to the target config data, create a copy so that it // can be found. See `rebuild_unit_graph_shared` for why this is done. if requested_kinds.iter().any(CompileKind::is_host) { - let ct = CompileTarget::new(&rustc.host)?; - target_info.insert(ct, host_info.clone()); - target_config.insert(ct, gctx.target_cfg_triple(&rustc.host)?); + target_config.insert(host_target, gctx.target_cfg_triple(&rustc.host)?); + + // If target_applies_to_host is true, the host_info is the target info, + // otherwise we need to build target info for the target. + if target_applies_to_host { + target_info.insert(host_target, host_info.clone()); + } else { + let host_target_info = TargetInfo::new( + gctx, + requested_kinds, + &rustc, + CompileKind::Target(host_target), + )?; + target_info.insert(host_target, host_target_info); + } }; let mut res = RustcTargetData { diff --git a/src/cargo/core/compiler/custom_build.rs b/src/cargo/core/compiler/custom_build.rs index cdde79501..ec4ac68ad 100644 --- a/src/cargo/core/compiler/custom_build.rs +++ b/src/cargo/core/compiler/custom_build.rs @@ -352,10 +352,7 @@ fn build_work(build_runner: &mut BuildRunner<'_, '_>, unit: &Unit) -> CargoResul cmd.env("RUSTC_WORKSPACE_WRAPPER", wrapper); } } - cmd.env( - "CARGO_ENCODED_RUSTFLAGS", - bcx.rustflags_args(unit).join("\x1f"), - ); + cmd.env("CARGO_ENCODED_RUSTFLAGS", unit.rustflags.join("\x1f")); cmd.env_remove("RUSTFLAGS"); if build_runner.bcx.ws.gctx().extra_verbose() { diff --git a/src/cargo/core/compiler/fingerprint/mod.rs b/src/cargo/core/compiler/fingerprint/mod.rs index 9d9eb4e4d..ceee710d4 100644 --- a/src/cargo/core/compiler/fingerprint/mod.rs +++ b/src/cargo/core/compiler/fingerprint/mod.rs @@ -1417,7 +1417,7 @@ fn calculate_normal( let extra_flags = if unit.mode.is_doc() || unit.mode.is_doc_scrape() { build_runner.bcx.rustdocflags_args(unit) } else { - build_runner.bcx.rustflags_args(unit) + &unit.rustflags } .to_vec(); @@ -1512,7 +1512,7 @@ fn calculate_run_custom_build( An I/O error happened. Please make sure you can access the file. By default, if your project contains a build script, cargo scans all files in -it to determine whether a rebuild is needed. If you don't expect to access the +it to determine whether a rebuild is needed. If you don't expect to access the file, specify `rerun-if-changed` in your build script. See https://doc.rust-lang.org/cargo/reference/build-scripts.html#rerun-if-changed for more information."; pkg_fingerprint(build_runner.bcx, &unit.pkg).map_err(|err| { @@ -1542,7 +1542,7 @@ See https://doc.rust-lang.org/cargo/reference/build-scripts.html#rerun-if-change .collect::>>()? }; - let rustflags = build_runner.bcx.rustflags_args(unit).to_vec(); + let rustflags = unit.rustflags.to_vec(); Ok(Fingerprint { local: Mutex::new(local), diff --git a/src/cargo/core/compiler/mod.rs b/src/cargo/core/compiler/mod.rs index 706ff530a..52d70f971 100644 --- a/src/cargo/core/compiler/mod.rs +++ b/src/cargo/core/compiler/mod.rs @@ -683,7 +683,7 @@ fn prepare_rustc(build_runner: &BuildRunner<'_, '_>, unit: &Unit) -> CargoResult base.inherit_jobserver(&build_runner.jobserver); build_deps_args(&mut base, build_runner, unit)?; add_cap_lints(build_runner.bcx, unit, &mut base); - base.args(build_runner.bcx.rustflags_args(unit)); + base.args(&unit.rustflags); if build_runner.bcx.gctx.cli_unstable().binary_dep_depinfo { base.arg("-Z").arg("binary-dep-depinfo"); } diff --git a/src/cargo/core/compiler/standard_lib.rs b/src/cargo/core/compiler/standard_lib.rs index 3e387bddd..c3b0d3633 100644 --- a/src/cargo/core/compiler/standard_lib.rs +++ b/src/cargo/core/compiler/standard_lib.rs @@ -178,6 +178,7 @@ pub fn generate_std_roots( package_set: &PackageSet<'_>, interner: &UnitInterner, profiles: &Profiles, + target_data: &RustcTargetData<'_>, ) -> CargoResult>> { // Generate the root Units for the standard library. let std_ids = crates @@ -216,6 +217,7 @@ pub fn generate_std_roots( *kind, mode, features.clone(), + target_data.info(*kind).rustflags.clone(), /*is_std*/ true, /*dep_hash*/ 0, IsArtifact::No, diff --git a/src/cargo/core/compiler/unit.rs b/src/cargo/core/compiler/unit.rs index 4e96584c3..db779cd9c 100644 --- a/src/cargo/core/compiler/unit.rs +++ b/src/cargo/core/compiler/unit.rs @@ -14,6 +14,7 @@ use std::fmt; use std::hash::{Hash, Hasher}; use std::ops::Deref; use std::rc::Rc; +use std::sync::Arc; /// All information needed to define a unit. /// @@ -59,6 +60,17 @@ pub struct UnitInner { /// The `cfg` features to enable for this unit. /// This must be sorted. pub features: Vec, + /// Extra compiler flags to pass to `rustc` for a given unit. + /// + /// Although it depends on the caller, in the current Cargo implementation, + /// these flags take precedence over those from [`BuildContext::extra_args_for`]. + /// + /// As of now, these flags come from environment variables and configurations. + /// See [`TargetInfo.rustflags`] for more on how Cargo collects them. + /// + /// [`BuildContext::extra_args_for`]: crate::core::compiler::build_context::BuildContext::extra_args_for + /// [`TargetInfo.rustflags`]: crate::core::compiler::build_context::TargetInfo::rustflags + pub rustflags: Arc<[String]>, // if `true`, the dependency is an artifact dependency, requiring special handling when // calculating output directories, linkage and environment variables provided to builds. pub artifact: IsArtifact, @@ -151,6 +163,7 @@ impl fmt::Debug for Unit { .field("kind", &self.kind) .field("mode", &self.mode) .field("features", &self.features) + .field("rustflags", &self.rustflags) .field("artifact", &self.artifact.is_true()) .field( "artifact_target_for_features", @@ -198,6 +211,7 @@ impl UnitInterner { kind: CompileKind, mode: CompileMode, features: Vec, + rustflags: Arc<[String]>, is_std: bool, dep_hash: u64, artifact: IsArtifact, @@ -231,6 +245,7 @@ impl UnitInterner { kind, mode, features, + rustflags, is_std, dep_hash, artifact, diff --git a/src/cargo/core/compiler/unit_dependencies.rs b/src/cargo/core/compiler/unit_dependencies.rs index 169025974..96e3854f2 100644 --- a/src/cargo/core/compiler/unit_dependencies.rs +++ b/src/cargo/core/compiler/unit_dependencies.rs @@ -859,6 +859,7 @@ fn new_unit_dep_with_profile( kind, mode, features, + state.target_data.info(kind).rustflags.clone(), state.is_std, /*dep_hash*/ 0, artifact.map_or(IsArtifact::No, |_| IsArtifact::Yes), diff --git a/src/cargo/ops/cargo_compile/mod.rs b/src/cargo/ops/cargo_compile/mod.rs index a09a95c5a..860aab9cc 100644 --- a/src/cargo/ops/cargo_compile/mod.rs +++ b/src/cargo/ops/cargo_compile/mod.rs @@ -360,6 +360,7 @@ pub fn create_bcx<'a, 'gctx>( let generator = UnitGenerator { ws, packages: &to_builds, + target_data: &target_data, filter, requested_kinds: &build_config.requested_kinds, explicit_host_kind, @@ -399,6 +400,7 @@ pub fn create_bcx<'a, 'gctx>( &pkg_set, interner, &profiles, + &target_data, )? } else { Default::default() @@ -694,6 +696,7 @@ fn traverse_and_share( to_host.unwrap(), unit.mode, unit.features.clone(), + unit.rustflags.clone(), unit.is_std, unit.dep_hash, unit.artifact, @@ -719,6 +722,7 @@ fn traverse_and_share( canonical_kind, unit.mode, unit.features.clone(), + unit.rustflags.clone(), unit.is_std, new_dep_hash, unit.artifact, @@ -880,6 +884,7 @@ fn override_rustc_crate_types( unit.kind, unit.mode, unit.features.clone(), + unit.rustflags.clone(), unit.is_std, unit.dep_hash, unit.artifact, diff --git a/src/cargo/ops/cargo_compile/unit_generator.rs b/src/cargo/ops/cargo_compile/unit_generator.rs index b2d86b753..16a6a524d 100644 --- a/src/cargo/ops/cargo_compile/unit_generator.rs +++ b/src/cargo/ops/cargo_compile/unit_generator.rs @@ -4,8 +4,8 @@ use std::fmt::Write; use crate::core::compiler::rustdoc::RustdocScrapeExamples; use crate::core::compiler::unit_dependencies::IsArtifact; -use crate::core::compiler::UnitInterner; use crate::core::compiler::{CompileKind, CompileMode, Unit}; +use crate::core::compiler::{RustcTargetData, UnitInterner}; use crate::core::dependency::DepKind; use crate::core::profiles::{Profiles, UnitFor}; use crate::core::resolver::features::{self, FeaturesFor}; @@ -47,6 +47,7 @@ struct Proposal<'a> { pub(super) struct UnitGenerator<'a, 'gctx> { pub ws: &'a Workspace<'gctx>, pub packages: &'a [&'a Package], + pub target_data: &'a RustcTargetData<'gctx>, pub filter: &'a CompileFilter, pub requested_kinds: &'a [CompileKind], pub explicit_host_kind: CompileKind, @@ -162,13 +163,15 @@ impl<'a> UnitGenerator<'a, '_> { unit_for, kind, ); + let kind = kind.for_target(target); self.interner.intern( pkg, target, profile, - kind.for_target(target), + kind, target_mode, features.clone(), + self.target_data.info(kind).rustflags.clone(), /*is_std*/ false, /*dep_hash*/ 0, IsArtifact::No, diff --git a/tests/testsuite/rustflags.rs b/tests/testsuite/rustflags.rs index bd7bf6ef8..f2105564f 100644 --- a/tests/testsuite/rustflags.rs +++ b/tests/testsuite/rustflags.rs @@ -1599,14 +1599,18 @@ fn target_applies_to_host_rustflags_works() { ) .build(); - // Use RUSTFLAGS to pass an argument that would generate an error - // but it is ignored. + // Use RUSTFLAGS to pass an argument that will generate an error. p.cargo("check") .masquerade_as_nightly_cargo(&["target-applies-to-host"]) .arg("-Ztarget-applies-to-host") .env("CARGO_TARGET_APPLIES_TO_HOST", "false") .env("RUSTFLAGS", r#"--cfg feature="flag""#) - .with_status(0) + .with_status(101) + .with_stderr_data( + "[CHECKING] foo v0.0.1 ([ROOT]/foo) +[ERROR] flag passed +...", + ) .run(); }