mirror of
				https://github.com/rust-lang/cargo.git
				synced 2025-11-03 13:12:53 +00:00 
			
		
		
		
	Auto merge of #14205 - gmorenz:links_overrides_in_unit, r=weihanglo
Fix passing of links-overrides with target-applies-to-host and an implicit target ### What does this PR try to resolve? This fixes the link-overrides half of #14195, both the panic, and the fact that the field is being discarded, the latter of which caused the former as discussed in [the issue](https://github.com/rust-lang/cargo/issues/14195#issuecomment-2211481773). It does so following the blueprint laid out in #13900 - which is also in my opinion the current best summary of the broader context. ### How should we test and review this PR? For reviewing, comparing to the changes in #13900 might be useful. ### Additional information I'm pushing a PR for the other half of #14195 simultaneously. I thought it better to keep the PRs small since they're independent, though if merged simultaneously there will be a conflict over the ordering of fields in `Unit`.
This commit is contained in:
		
						commit
						61424d6040
					
				@ -8,9 +8,7 @@
 | 
				
			|||||||
//! * [`TargetInfo::rustc_outputs`] to get a list of supported file types.
 | 
					//! * [`TargetInfo::rustc_outputs`] to get a list of supported file types.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::core::compiler::apply_env_config;
 | 
					use crate::core::compiler::apply_env_config;
 | 
				
			||||||
use crate::core::compiler::{
 | 
					use crate::core::compiler::{BuildRunner, CompileKind, CompileMode, CompileTarget, CrateType};
 | 
				
			||||||
    BuildOutput, BuildRunner, CompileKind, CompileMode, CompileTarget, CrateType,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
use crate::core::{Dependency, Package, Target, TargetKind, Workspace};
 | 
					use crate::core::{Dependency, Package, Target, TargetKind, Workspace};
 | 
				
			||||||
use crate::util::context::{GlobalContext, StringList, TargetConfig};
 | 
					use crate::util::context::{GlobalContext, StringList, TargetConfig};
 | 
				
			||||||
use crate::util::interning::InternedString;
 | 
					use crate::util::interning::InternedString;
 | 
				
			||||||
@ -1038,14 +1036,6 @@ impl<'gctx> RustcTargetData<'gctx> {
 | 
				
			|||||||
            CompileKind::Target(s) => &self.target_config[&s],
 | 
					            CompileKind::Target(s) => &self.target_config[&s],
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// If a build script is overridden, this returns the `BuildOutput` to use.
 | 
					 | 
				
			||||||
    ///
 | 
					 | 
				
			||||||
    /// `lib_name` is the `links` library name and `kind` is whether it is for
 | 
					 | 
				
			||||||
    /// Host or Target.
 | 
					 | 
				
			||||||
    pub fn script_override(&self, lib_name: &str, kind: CompileKind) -> Option<&BuildOutput> {
 | 
					 | 
				
			||||||
        self.target_config(kind).links_overrides.get(lib_name)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Structure used to deal with Rustdoc fingerprinting
 | 
					/// Structure used to deal with Rustdoc fingerprinting
 | 
				
			||||||
 | 
				
			|||||||
@ -61,7 +61,7 @@ const OLD_CARGO_WARNING_SYNTAX: &str = "cargo:warning=";
 | 
				
			|||||||
/// [the doc]: https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#cargo-warning
 | 
					/// [the doc]: https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#cargo-warning
 | 
				
			||||||
const NEW_CARGO_WARNING_SYNTAX: &str = "cargo::warning=";
 | 
					const NEW_CARGO_WARNING_SYNTAX: &str = "cargo::warning=";
 | 
				
			||||||
/// Contains the parsed output of a custom build script.
 | 
					/// Contains the parsed output of a custom build script.
 | 
				
			||||||
#[derive(Clone, Debug, Hash, Default)]
 | 
					#[derive(Clone, Debug, Hash, Default, PartialEq, Eq, PartialOrd, Ord)]
 | 
				
			||||||
pub struct BuildOutput {
 | 
					pub struct BuildOutput {
 | 
				
			||||||
    /// Paths to pass to rustc with the `-L` flag.
 | 
					    /// Paths to pass to rustc with the `-L` flag.
 | 
				
			||||||
    pub library_paths: Vec<PathBuf>,
 | 
					    pub library_paths: Vec<PathBuf>,
 | 
				
			||||||
@ -160,7 +160,7 @@ pub struct BuildDeps {
 | 
				
			|||||||
/// See the [build script documentation][1] for more.
 | 
					/// See the [build script documentation][1] for more.
 | 
				
			||||||
///
 | 
					///
 | 
				
			||||||
/// [1]: https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#cargorustc-link-argflag
 | 
					/// [1]: https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#cargorustc-link-argflag
 | 
				
			||||||
#[derive(Clone, Hash, Debug, PartialEq, Eq)]
 | 
					#[derive(Clone, Hash, Debug, PartialEq, Eq, PartialOrd, Ord)]
 | 
				
			||||||
pub enum LinkArgTarget {
 | 
					pub enum LinkArgTarget {
 | 
				
			||||||
    /// Represents `cargo::rustc-link-arg=FLAG`.
 | 
					    /// Represents `cargo::rustc-link-arg=FLAG`.
 | 
				
			||||||
    All,
 | 
					    All,
 | 
				
			||||||
@ -1168,11 +1168,7 @@ pub fn build_map(build_runner: &mut BuildRunner<'_, '_>) -> CargoResult<()> {
 | 
				
			|||||||
        // If there is a build script override, pre-fill the build output.
 | 
					        // If there is a build script override, pre-fill the build output.
 | 
				
			||||||
        if unit.mode.is_run_custom_build() {
 | 
					        if unit.mode.is_run_custom_build() {
 | 
				
			||||||
            if let Some(links) = unit.pkg.manifest().links() {
 | 
					            if let Some(links) = unit.pkg.manifest().links() {
 | 
				
			||||||
                if let Some(output) = build_runner
 | 
					                if let Some(output) = unit.links_overrides.get(links) {
 | 
				
			||||||
                    .bcx
 | 
					 | 
				
			||||||
                    .target_data
 | 
					 | 
				
			||||||
                    .script_override(links, unit.kind)
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    let metadata = build_runner.get_run_build_script_metadata(unit);
 | 
					                    let metadata = build_runner.get_run_build_script_metadata(unit);
 | 
				
			||||||
                    build_runner.build_script_outputs.lock().unwrap().insert(
 | 
					                    build_runner.build_script_outputs.lock().unwrap().insert(
 | 
				
			||||||
                        unit.pkg.package_id(),
 | 
					                        unit.pkg.package_id(),
 | 
				
			||||||
 | 
				
			|||||||
@ -219,6 +219,7 @@ pub fn generate_std_roots(
 | 
				
			|||||||
                features.clone(),
 | 
					                features.clone(),
 | 
				
			||||||
                target_data.info(*kind).rustflags.clone(),
 | 
					                target_data.info(*kind).rustflags.clone(),
 | 
				
			||||||
                target_data.info(*kind).rustdocflags.clone(),
 | 
					                target_data.info(*kind).rustdocflags.clone(),
 | 
				
			||||||
 | 
					                target_data.target_config(*kind).links_overrides.clone(),
 | 
				
			||||||
                /*is_std*/ true,
 | 
					                /*is_std*/ true,
 | 
				
			||||||
                /*dep_hash*/ 0,
 | 
					                /*dep_hash*/ 0,
 | 
				
			||||||
                IsArtifact::No,
 | 
					                IsArtifact::No,
 | 
				
			||||||
 | 
				
			|||||||
@ -9,13 +9,15 @@ use crate::util::hex::short_hash;
 | 
				
			|||||||
use crate::util::interning::InternedString;
 | 
					use crate::util::interning::InternedString;
 | 
				
			||||||
use crate::util::GlobalContext;
 | 
					use crate::util::GlobalContext;
 | 
				
			||||||
use std::cell::RefCell;
 | 
					use std::cell::RefCell;
 | 
				
			||||||
use std::collections::HashSet;
 | 
					use std::collections::{BTreeMap, HashSet};
 | 
				
			||||||
use std::fmt;
 | 
					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;
 | 
					use std::sync::Arc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use super::BuildOutput;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// All information needed to define a unit.
 | 
					/// All information needed to define a unit.
 | 
				
			||||||
///
 | 
					///
 | 
				
			||||||
/// A unit is an object that has enough information so that cargo knows how to build it.
 | 
					/// A unit is an object that has enough information so that cargo knows how to build it.
 | 
				
			||||||
@ -82,6 +84,12 @@ pub struct UnitInner {
 | 
				
			|||||||
    /// [`BuildContext::extra_args_for`]: crate::core::compiler::build_context::BuildContext::extra_args_for
 | 
					    /// [`BuildContext::extra_args_for`]: crate::core::compiler::build_context::BuildContext::extra_args_for
 | 
				
			||||||
    /// [`TargetInfo.rustdocflags`]: crate::core::compiler::build_context::TargetInfo::rustdocflags
 | 
					    /// [`TargetInfo.rustdocflags`]: crate::core::compiler::build_context::TargetInfo::rustdocflags
 | 
				
			||||||
    pub rustdocflags: Arc<[String]>,
 | 
					    pub rustdocflags: Arc<[String]>,
 | 
				
			||||||
 | 
					    /// Build script override for the given library name.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// Any package with a `links` value for the given library name will skip
 | 
				
			||||||
 | 
					    /// running its build script and instead use the given output from the
 | 
				
			||||||
 | 
					    /// config file.
 | 
				
			||||||
 | 
					    pub links_overrides: Rc<BTreeMap<String, BuildOutput>>,
 | 
				
			||||||
    // 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,
 | 
				
			||||||
@ -176,6 +184,7 @@ impl fmt::Debug for Unit {
 | 
				
			|||||||
            .field("features", &self.features)
 | 
					            .field("features", &self.features)
 | 
				
			||||||
            .field("rustflags", &self.rustflags)
 | 
					            .field("rustflags", &self.rustflags)
 | 
				
			||||||
            .field("rustdocflags", &self.rustdocflags)
 | 
					            .field("rustdocflags", &self.rustdocflags)
 | 
				
			||||||
 | 
					            .field("links_overrides", &self.links_overrides)
 | 
				
			||||||
            .field("artifact", &self.artifact.is_true())
 | 
					            .field("artifact", &self.artifact.is_true())
 | 
				
			||||||
            .field(
 | 
					            .field(
 | 
				
			||||||
                "artifact_target_for_features",
 | 
					                "artifact_target_for_features",
 | 
				
			||||||
@ -225,6 +234,7 @@ impl UnitInterner {
 | 
				
			|||||||
        features: Vec<InternedString>,
 | 
					        features: Vec<InternedString>,
 | 
				
			||||||
        rustflags: Arc<[String]>,
 | 
					        rustflags: Arc<[String]>,
 | 
				
			||||||
        rustdocflags: Arc<[String]>,
 | 
					        rustdocflags: Arc<[String]>,
 | 
				
			||||||
 | 
					        links_overrides: Rc<BTreeMap<String, BuildOutput>>,
 | 
				
			||||||
        is_std: bool,
 | 
					        is_std: bool,
 | 
				
			||||||
        dep_hash: u64,
 | 
					        dep_hash: u64,
 | 
				
			||||||
        artifact: IsArtifact,
 | 
					        artifact: IsArtifact,
 | 
				
			||||||
@ -260,6 +270,7 @@ impl UnitInterner {
 | 
				
			|||||||
            features,
 | 
					            features,
 | 
				
			||||||
            rustflags,
 | 
					            rustflags,
 | 
				
			||||||
            rustdocflags,
 | 
					            rustdocflags,
 | 
				
			||||||
 | 
					            links_overrides,
 | 
				
			||||||
            is_std,
 | 
					            is_std,
 | 
				
			||||||
            dep_hash,
 | 
					            dep_hash,
 | 
				
			||||||
            artifact,
 | 
					            artifact,
 | 
				
			||||||
 | 
				
			|||||||
@ -457,11 +457,7 @@ fn compute_deps_custom_build(
 | 
				
			|||||||
    state: &State<'_, '_>,
 | 
					    state: &State<'_, '_>,
 | 
				
			||||||
) -> CargoResult<Vec<UnitDep>> {
 | 
					) -> CargoResult<Vec<UnitDep>> {
 | 
				
			||||||
    if let Some(links) = unit.pkg.manifest().links() {
 | 
					    if let Some(links) = unit.pkg.manifest().links() {
 | 
				
			||||||
        if state
 | 
					        if unit.links_overrides.get(links).is_some() {
 | 
				
			||||||
            .target_data
 | 
					 | 
				
			||||||
            .script_override(links, unit.kind)
 | 
					 | 
				
			||||||
            .is_some()
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            // Overridden build scripts don't have any dependencies.
 | 
					            // Overridden build scripts don't have any dependencies.
 | 
				
			||||||
            return Ok(Vec::new());
 | 
					            return Ok(Vec::new());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -861,6 +857,11 @@ fn new_unit_dep_with_profile(
 | 
				
			|||||||
        features,
 | 
					        features,
 | 
				
			||||||
        state.target_data.info(kind).rustflags.clone(),
 | 
					        state.target_data.info(kind).rustflags.clone(),
 | 
				
			||||||
        state.target_data.info(kind).rustdocflags.clone(),
 | 
					        state.target_data.info(kind).rustdocflags.clone(),
 | 
				
			||||||
 | 
					        state
 | 
				
			||||||
 | 
					            .target_data
 | 
				
			||||||
 | 
					            .target_config(kind)
 | 
				
			||||||
 | 
					            .links_overrides
 | 
				
			||||||
 | 
					            .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),
 | 
				
			||||||
 | 
				
			|||||||
@ -698,6 +698,7 @@ fn traverse_and_share(
 | 
				
			|||||||
            unit.features.clone(),
 | 
					            unit.features.clone(),
 | 
				
			||||||
            unit.rustflags.clone(),
 | 
					            unit.rustflags.clone(),
 | 
				
			||||||
            unit.rustdocflags.clone(),
 | 
					            unit.rustdocflags.clone(),
 | 
				
			||||||
 | 
					            unit.links_overrides.clone(),
 | 
				
			||||||
            unit.is_std,
 | 
					            unit.is_std,
 | 
				
			||||||
            unit.dep_hash,
 | 
					            unit.dep_hash,
 | 
				
			||||||
            unit.artifact,
 | 
					            unit.artifact,
 | 
				
			||||||
@ -725,6 +726,7 @@ fn traverse_and_share(
 | 
				
			|||||||
        unit.features.clone(),
 | 
					        unit.features.clone(),
 | 
				
			||||||
        unit.rustflags.clone(),
 | 
					        unit.rustflags.clone(),
 | 
				
			||||||
        unit.rustdocflags.clone(),
 | 
					        unit.rustdocflags.clone(),
 | 
				
			||||||
 | 
					        unit.links_overrides.clone(),
 | 
				
			||||||
        unit.is_std,
 | 
					        unit.is_std,
 | 
				
			||||||
        new_dep_hash,
 | 
					        new_dep_hash,
 | 
				
			||||||
        unit.artifact,
 | 
					        unit.artifact,
 | 
				
			||||||
@ -888,6 +890,7 @@ fn override_rustc_crate_types(
 | 
				
			|||||||
            unit.features.clone(),
 | 
					            unit.features.clone(),
 | 
				
			||||||
            unit.rustflags.clone(),
 | 
					            unit.rustflags.clone(),
 | 
				
			||||||
            unit.rustdocflags.clone(),
 | 
					            unit.rustdocflags.clone(),
 | 
				
			||||||
 | 
					            unit.links_overrides.clone(),
 | 
				
			||||||
            unit.is_std,
 | 
					            unit.is_std,
 | 
				
			||||||
            unit.dep_hash,
 | 
					            unit.dep_hash,
 | 
				
			||||||
            unit.artifact,
 | 
					            unit.artifact,
 | 
				
			||||||
 | 
				
			|||||||
@ -173,6 +173,7 @@ impl<'a> UnitGenerator<'a, '_> {
 | 
				
			|||||||
                    features.clone(),
 | 
					                    features.clone(),
 | 
				
			||||||
                    self.target_data.info(kind).rustflags.clone(),
 | 
					                    self.target_data.info(kind).rustflags.clone(),
 | 
				
			||||||
                    self.target_data.info(kind).rustdocflags.clone(),
 | 
					                    self.target_data.info(kind).rustdocflags.clone(),
 | 
				
			||||||
 | 
					                    self.target_data.target_config(kind).links_overrides.clone(),
 | 
				
			||||||
                    /*is_std*/ false,
 | 
					                    /*is_std*/ false,
 | 
				
			||||||
                    /*dep_hash*/ 0,
 | 
					                    /*dep_hash*/ 0,
 | 
				
			||||||
                    IsArtifact::No,
 | 
					                    IsArtifact::No,
 | 
				
			||||||
 | 
				
			|||||||
@ -4,6 +4,7 @@ use crate::util::CargoResult;
 | 
				
			|||||||
use serde::Deserialize;
 | 
					use serde::Deserialize;
 | 
				
			||||||
use std::collections::{BTreeMap, HashMap};
 | 
					use std::collections::{BTreeMap, HashMap};
 | 
				
			||||||
use std::path::PathBuf;
 | 
					use std::path::PathBuf;
 | 
				
			||||||
 | 
					use std::rc::Rc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Config definition of a `[target.'cfg(…)']` table.
 | 
					/// Config definition of a `[target.'cfg(…)']` table.
 | 
				
			||||||
///
 | 
					///
 | 
				
			||||||
@ -36,7 +37,7 @@ pub struct TargetConfig {
 | 
				
			|||||||
    /// Any package with a `links` value for the given library name will skip
 | 
					    /// Any package with a `links` value for the given library name will skip
 | 
				
			||||||
    /// running its build script and instead use the given output from the
 | 
					    /// running its build script and instead use the given output from the
 | 
				
			||||||
    /// config file.
 | 
					    /// config file.
 | 
				
			||||||
    pub links_overrides: BTreeMap<String, BuildOutput>,
 | 
					    pub links_overrides: Rc<BTreeMap<String, BuildOutput>>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Loads all of the `target.'cfg()'` tables.
 | 
					/// Loads all of the `target.'cfg()'` tables.
 | 
				
			||||||
@ -128,7 +129,7 @@ fn load_config_table(gctx: &GlobalContext, prefix: &str) -> CargoResult<TargetCo
 | 
				
			|||||||
        rustflags,
 | 
					        rustflags,
 | 
				
			||||||
        rustdocflags,
 | 
					        rustdocflags,
 | 
				
			||||||
        linker,
 | 
					        linker,
 | 
				
			||||||
        links_overrides,
 | 
					        links_overrides: Rc::new(links_overrides),
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -5777,3 +5777,41 @@ hello
 | 
				
			|||||||
"#]])
 | 
					"#]])
 | 
				
			||||||
        .run();
 | 
					        .run();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[cargo_test]
 | 
				
			||||||
 | 
					fn links_overrides_with_target_applies_to_host() {
 | 
				
			||||||
 | 
					    let p = project()
 | 
				
			||||||
 | 
					        .file(
 | 
				
			||||||
 | 
					            "Cargo.toml",
 | 
				
			||||||
 | 
					            r#"
 | 
				
			||||||
 | 
					                [package]
 | 
				
			||||||
 | 
					                name = "mylib-sys"
 | 
				
			||||||
 | 
					                edition = "2021"
 | 
				
			||||||
 | 
					                version = "0.0.1"
 | 
				
			||||||
 | 
					                authors = []
 | 
				
			||||||
 | 
					                links = "mylib"
 | 
				
			||||||
 | 
					            "#,
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        .file("src/lib.rs", "")
 | 
				
			||||||
 | 
					        .file("build.rs", "bad file")
 | 
				
			||||||
 | 
					        .build();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    p.cargo("build -v")
 | 
				
			||||||
 | 
					        .masquerade_as_nightly_cargo(&["target-applies-to-host"])
 | 
				
			||||||
 | 
					        .args(&[
 | 
				
			||||||
 | 
					            "-Ztarget-applies-to-host",
 | 
				
			||||||
 | 
					            "--config",
 | 
				
			||||||
 | 
					            "target-applies-to-host=false",
 | 
				
			||||||
 | 
					        ])
 | 
				
			||||||
 | 
					        .args(&[
 | 
				
			||||||
 | 
					            "--config",
 | 
				
			||||||
 | 
					            &format!(r#"target.{}.mylib.rustc-link-search=["foo"]"#, rustc_host()),
 | 
				
			||||||
 | 
					        ])
 | 
				
			||||||
 | 
					        .with_stderr_data(str![[r#"
 | 
				
			||||||
 | 
					[COMPILING] mylib-sys v0.0.1 ([ROOT]/foo)
 | 
				
			||||||
 | 
					[RUNNING] `rustc --crate-name mylib_sys [..] -L foo`
 | 
				
			||||||
 | 
					[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					"#]])
 | 
				
			||||||
 | 
					        .run();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user