Pass rustflags to artifacts built with implicit targets when using target-applies-to-host

This commit is contained in:
Greg Morenz 2024-05-10 17:25:17 -04:00
parent a547d19af7
commit 07c9f77ecd
11 changed files with 65 additions and 32 deletions

View File

@ -134,19 +134,6 @@ impl<'a, 'gctx> BuildContext<'a, 'gctx> {
self.build_config.jobs 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. /// Extra compiler flags to pass to `rustdoc` for a given unit.
/// ///
/// Although it depends on the caller, in the current Cargo implementation, /// Although it depends on the caller, in the current Cargo implementation,

View File

@ -23,6 +23,7 @@ use std::cell::RefCell;
use std::collections::hash_map::{Entry, HashMap}; use std::collections::hash_map::{Entry, HashMap};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::str::{self, FromStr}; use std::str::{self, FromStr};
use std::sync::Arc;
/// Information about the platform target gleaned from querying rustc. /// Information about the platform target gleaned from querying rustc.
/// ///
@ -52,7 +53,7 @@ pub struct TargetInfo {
/// target libraries. /// target libraries.
pub sysroot_target_libdir: PathBuf, pub sysroot_target_libdir: PathBuf,
/// Extra flags to pass to `rustc`, see [`extra_args`]. /// Extra flags to pass to `rustc`, see [`extra_args`].
pub rustflags: Vec<String>, pub rustflags: Arc<[String]>,
/// Extra flags to pass to `rustdoc`, see [`extra_args`]. /// Extra flags to pass to `rustdoc`, see [`extra_args`].
pub rustdocflags: Vec<String>, pub rustdocflags: Vec<String>,
/// Whether or not rustc (stably) supports the `--check-cfg` flag. /// Whether or not rustc (stably) supports the `--check-cfg` flag.
@ -312,7 +313,7 @@ impl TargetInfo {
crate_types: RefCell::new(map), crate_types: RefCell::new(map),
sysroot, sysroot,
sysroot_target_libdir, sysroot_target_libdir,
rustflags, rustflags: rustflags.into(),
rustdocflags: extra_args( rustdocflags: extra_args(
gctx, gctx,
requested_kinds, requested_kinds,
@ -867,7 +868,10 @@ pub struct RustcTargetData<'gctx> {
/// Build information for the "host", which is information about when /// Build information for the "host", which is information about when
/// `rustc` is invoked without a `--target` flag. This is used for /// `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, host_config: TargetConfig,
/// Information about the host platform. /// Information about the host platform.
host_info: TargetInfo, host_info: TargetInfo,
@ -889,7 +893,10 @@ impl<'gctx> RustcTargetData<'gctx> {
let mut target_config = HashMap::new(); let mut target_config = HashMap::new();
let mut target_info = HashMap::new(); let mut target_info = HashMap::new();
let target_applies_to_host = gctx.target_applies_to_host()?; 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)?; 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 { let host_config = if target_applies_to_host {
gctx.target_cfg_triple(&rustc.host)? gctx.target_cfg_triple(&rustc.host)?
} else { } else {
@ -902,9 +909,21 @@ impl<'gctx> RustcTargetData<'gctx> {
// needs access to the target config data, create a copy so that it // 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. // can be found. See `rebuild_unit_graph_shared` for why this is done.
if requested_kinds.iter().any(CompileKind::is_host) { if requested_kinds.iter().any(CompileKind::is_host) {
let ct = CompileTarget::new(&rustc.host)?; target_config.insert(host_target, gctx.target_cfg_triple(&rustc.host)?);
target_info.insert(ct, host_info.clone());
target_config.insert(ct, 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 { let mut res = RustcTargetData {

View File

@ -352,10 +352,7 @@ fn build_work(build_runner: &mut BuildRunner<'_, '_>, unit: &Unit) -> CargoResul
cmd.env("RUSTC_WORKSPACE_WRAPPER", wrapper); cmd.env("RUSTC_WORKSPACE_WRAPPER", wrapper);
} }
} }
cmd.env( cmd.env("CARGO_ENCODED_RUSTFLAGS", unit.rustflags.join("\x1f"));
"CARGO_ENCODED_RUSTFLAGS",
bcx.rustflags_args(unit).join("\x1f"),
);
cmd.env_remove("RUSTFLAGS"); cmd.env_remove("RUSTFLAGS");
if build_runner.bcx.ws.gctx().extra_verbose() { if build_runner.bcx.ws.gctx().extra_verbose() {

View File

@ -1417,7 +1417,7 @@ fn calculate_normal(
let extra_flags = if unit.mode.is_doc() || unit.mode.is_doc_scrape() { let extra_flags = if unit.mode.is_doc() || unit.mode.is_doc_scrape() {
build_runner.bcx.rustdocflags_args(unit) build_runner.bcx.rustdocflags_args(unit)
} else { } else {
build_runner.bcx.rustflags_args(unit) &unit.rustflags
} }
.to_vec(); .to_vec();
@ -1512,7 +1512,7 @@ fn calculate_run_custom_build(
An I/O error happened. Please make sure you can access the file. 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 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. 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."; 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| { 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::<CargoResult<Vec<_>>>()? .collect::<CargoResult<Vec<_>>>()?
}; };
let rustflags = build_runner.bcx.rustflags_args(unit).to_vec(); let rustflags = unit.rustflags.to_vec();
Ok(Fingerprint { Ok(Fingerprint {
local: Mutex::new(local), local: Mutex::new(local),

View File

@ -683,7 +683,7 @@ fn prepare_rustc(build_runner: &BuildRunner<'_, '_>, unit: &Unit) -> CargoResult
base.inherit_jobserver(&build_runner.jobserver); base.inherit_jobserver(&build_runner.jobserver);
build_deps_args(&mut base, build_runner, unit)?; build_deps_args(&mut base, build_runner, unit)?;
add_cap_lints(build_runner.bcx, unit, &mut base); 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 { if build_runner.bcx.gctx.cli_unstable().binary_dep_depinfo {
base.arg("-Z").arg("binary-dep-depinfo"); base.arg("-Z").arg("binary-dep-depinfo");
} }

View File

@ -178,6 +178,7 @@ pub fn generate_std_roots(
package_set: &PackageSet<'_>, package_set: &PackageSet<'_>,
interner: &UnitInterner, interner: &UnitInterner,
profiles: &Profiles, profiles: &Profiles,
target_data: &RustcTargetData<'_>,
) -> CargoResult<HashMap<CompileKind, Vec<Unit>>> { ) -> CargoResult<HashMap<CompileKind, Vec<Unit>>> {
// Generate the root Units for the standard library. // Generate the root Units for the standard library.
let std_ids = crates let std_ids = crates
@ -216,6 +217,7 @@ pub fn generate_std_roots(
*kind, *kind,
mode, mode,
features.clone(), features.clone(),
target_data.info(*kind).rustflags.clone(),
/*is_std*/ true, /*is_std*/ true,
/*dep_hash*/ 0, /*dep_hash*/ 0,
IsArtifact::No, IsArtifact::No,

View File

@ -14,6 +14,7 @@ use std::fmt;
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
use std::ops::Deref; use std::ops::Deref;
use std::rc::Rc; use std::rc::Rc;
use std::sync::Arc;
/// All information needed to define a unit. /// All information needed to define a unit.
/// ///
@ -59,6 +60,17 @@ pub struct UnitInner {
/// The `cfg` features to enable for this unit. /// The `cfg` features to enable for this unit.
/// This must be sorted. /// This must be sorted.
pub features: Vec<InternedString>, pub features: Vec<InternedString>,
/// 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 // if `true`, the dependency is an artifact dependency, requiring special handling when
// calculating output directories, linkage and environment variables provided to builds. // calculating output directories, linkage and environment variables provided to builds.
pub artifact: IsArtifact, pub artifact: IsArtifact,
@ -151,6 +163,7 @@ impl fmt::Debug for Unit {
.field("kind", &self.kind) .field("kind", &self.kind)
.field("mode", &self.mode) .field("mode", &self.mode)
.field("features", &self.features) .field("features", &self.features)
.field("rustflags", &self.rustflags)
.field("artifact", &self.artifact.is_true()) .field("artifact", &self.artifact.is_true())
.field( .field(
"artifact_target_for_features", "artifact_target_for_features",
@ -198,6 +211,7 @@ impl UnitInterner {
kind: CompileKind, kind: CompileKind,
mode: CompileMode, mode: CompileMode,
features: Vec<InternedString>, features: Vec<InternedString>,
rustflags: Arc<[String]>,
is_std: bool, is_std: bool,
dep_hash: u64, dep_hash: u64,
artifact: IsArtifact, artifact: IsArtifact,
@ -231,6 +245,7 @@ impl UnitInterner {
kind, kind,
mode, mode,
features, features,
rustflags,
is_std, is_std,
dep_hash, dep_hash,
artifact, artifact,

View File

@ -859,6 +859,7 @@ fn new_unit_dep_with_profile(
kind, kind,
mode, mode,
features, features,
state.target_data.info(kind).rustflags.clone(),
state.is_std, state.is_std,
/*dep_hash*/ 0, /*dep_hash*/ 0,
artifact.map_or(IsArtifact::No, |_| IsArtifact::Yes), artifact.map_or(IsArtifact::No, |_| IsArtifact::Yes),

View File

@ -360,6 +360,7 @@ pub fn create_bcx<'a, 'gctx>(
let generator = UnitGenerator { let generator = UnitGenerator {
ws, ws,
packages: &to_builds, packages: &to_builds,
target_data: &target_data,
filter, filter,
requested_kinds: &build_config.requested_kinds, requested_kinds: &build_config.requested_kinds,
explicit_host_kind, explicit_host_kind,
@ -399,6 +400,7 @@ pub fn create_bcx<'a, 'gctx>(
&pkg_set, &pkg_set,
interner, interner,
&profiles, &profiles,
&target_data,
)? )?
} else { } else {
Default::default() Default::default()
@ -694,6 +696,7 @@ fn traverse_and_share(
to_host.unwrap(), to_host.unwrap(),
unit.mode, unit.mode,
unit.features.clone(), unit.features.clone(),
unit.rustflags.clone(),
unit.is_std, unit.is_std,
unit.dep_hash, unit.dep_hash,
unit.artifact, unit.artifact,
@ -719,6 +722,7 @@ fn traverse_and_share(
canonical_kind, canonical_kind,
unit.mode, unit.mode,
unit.features.clone(), unit.features.clone(),
unit.rustflags.clone(),
unit.is_std, unit.is_std,
new_dep_hash, new_dep_hash,
unit.artifact, unit.artifact,
@ -880,6 +884,7 @@ fn override_rustc_crate_types(
unit.kind, unit.kind,
unit.mode, unit.mode,
unit.features.clone(), unit.features.clone(),
unit.rustflags.clone(),
unit.is_std, unit.is_std,
unit.dep_hash, unit.dep_hash,
unit.artifact, unit.artifact,

View File

@ -4,8 +4,8 @@ use std::fmt::Write;
use crate::core::compiler::rustdoc::RustdocScrapeExamples; use crate::core::compiler::rustdoc::RustdocScrapeExamples;
use crate::core::compiler::unit_dependencies::IsArtifact; use crate::core::compiler::unit_dependencies::IsArtifact;
use crate::core::compiler::UnitInterner;
use crate::core::compiler::{CompileKind, CompileMode, Unit}; use crate::core::compiler::{CompileKind, CompileMode, Unit};
use crate::core::compiler::{RustcTargetData, UnitInterner};
use crate::core::dependency::DepKind; use crate::core::dependency::DepKind;
use crate::core::profiles::{Profiles, UnitFor}; use crate::core::profiles::{Profiles, UnitFor};
use crate::core::resolver::features::{self, FeaturesFor}; use crate::core::resolver::features::{self, FeaturesFor};
@ -47,6 +47,7 @@ struct Proposal<'a> {
pub(super) struct UnitGenerator<'a, 'gctx> { pub(super) struct UnitGenerator<'a, 'gctx> {
pub ws: &'a Workspace<'gctx>, pub ws: &'a Workspace<'gctx>,
pub packages: &'a [&'a Package], pub packages: &'a [&'a Package],
pub target_data: &'a RustcTargetData<'gctx>,
pub filter: &'a CompileFilter, pub filter: &'a CompileFilter,
pub requested_kinds: &'a [CompileKind], pub requested_kinds: &'a [CompileKind],
pub explicit_host_kind: CompileKind, pub explicit_host_kind: CompileKind,
@ -162,13 +163,15 @@ impl<'a> UnitGenerator<'a, '_> {
unit_for, unit_for,
kind, kind,
); );
let kind = kind.for_target(target);
self.interner.intern( self.interner.intern(
pkg, pkg,
target, target,
profile, profile,
kind.for_target(target), kind,
target_mode, target_mode,
features.clone(), features.clone(),
self.target_data.info(kind).rustflags.clone(),
/*is_std*/ false, /*is_std*/ false,
/*dep_hash*/ 0, /*dep_hash*/ 0,
IsArtifact::No, IsArtifact::No,

View File

@ -1599,14 +1599,18 @@ fn target_applies_to_host_rustflags_works() {
) )
.build(); .build();
// Use RUSTFLAGS to pass an argument that would generate an error // Use RUSTFLAGS to pass an argument that will generate an error.
// but it is ignored.
p.cargo("check") p.cargo("check")
.masquerade_as_nightly_cargo(&["target-applies-to-host"]) .masquerade_as_nightly_cargo(&["target-applies-to-host"])
.arg("-Ztarget-applies-to-host") .arg("-Ztarget-applies-to-host")
.env("CARGO_TARGET_APPLIES_TO_HOST", "false") .env("CARGO_TARGET_APPLIES_TO_HOST", "false")
.env("RUSTFLAGS", r#"--cfg feature="flag""#) .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(); .run();
} }