Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 34 additions & 6 deletions src/cargo/core/compiler/custom_build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,8 @@ fn build_work(build_runner: &mut BuildRunner<'_, '_>, unit: &Unit) -> CargoResul
cmd.display_env_vars();
}

let any_build_script_metadata = bcx.gctx.cli_unstable().any_build_script_metadata;

// Gather the set of native dependencies that this package has along with
// some other variables to close over.
//
Expand All @@ -461,8 +463,26 @@ fn build_work(build_runner: &mut BuildRunner<'_, '_>, unit: &Unit) -> CargoResul
.filter_map(|dep| {
if dep.unit.mode.is_run_custom_build() {
let dep_metadata = build_runner.get_run_build_script_metadata(&dep.unit);

let Some(dependency) = unit.pkg.dependencies().iter().find(|d| {
d.package_name() == dep.unit.pkg.name()
&& d.source_id() == dep.unit.pkg.package_id().source_id()
&& d.version_req().matches(unit.pkg.version())
Comment on lines +468 to +470
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note that while investigating #16436 (comment) I noticed that only checking the package name could lead to inconsistent behavior if a package has 2 versions of a package imported under different names.

To mitigate this I added checks for source_id and version. This is close to comparing package_id (Dependency does not have package_id)

Note that Dependency only has a version requirement so we use .matches(). I think in practice we should only have 1 possible matching version as Cargo would error while building the unit graph if the same dependencies. (ref)
correct me if I am wrong

}) else {
panic!(
"Dependency `{}` not found in `{}`s dependencies",
dep.unit.pkg.name(),
unit.pkg.name()
)
};

Some((
dep.unit.pkg.manifest().links().unwrap().to_string(),
dependency.name_in_toml(),
dep.unit
.pkg
.manifest()
.links()
.map(|links| links.to_string()),
dep.unit.pkg.package_id(),
dep_metadata,
))
Expand Down Expand Up @@ -531,7 +551,7 @@ fn build_work(build_runner: &mut BuildRunner<'_, '_>, unit: &Unit) -> CargoResul
// native dynamic libraries.
{
let build_script_outputs = build_script_outputs.lock().unwrap();
for (name, dep_id, dep_metadata) in lib_deps {
for (name, links, dep_id, dep_metadata) in lib_deps {
let script_output = build_script_outputs.get(dep_metadata).ok_or_else(|| {
internal(format!(
"failed to locate build state for env vars: {}/{}",
Expand All @@ -540,10 +560,18 @@ fn build_work(build_runner: &mut BuildRunner<'_, '_>, unit: &Unit) -> CargoResul
})?;
let data = &script_output.metadata;
for (key, value) in data.iter() {
cmd.env(
&format!("DEP_{}_{}", super::envify(&name), super::envify(key)),
value,
);
if let Some(ref links) = links {
cmd.env(
&format!("DEP_{}_{}", super::envify(&links), super::envify(key)),
value,
);
}
if any_build_script_metadata {
cmd.env(
&format!("CARGO_DEP_{}_{}", super::envify(&name), super::envify(key)),
value,
);
}
}
}
if let Some(build_scripts) = build_scripts
Expand Down
8 changes: 5 additions & 3 deletions src/cargo/core/compiler/unit_dependencies.rs
Original file line number Diff line number Diff line change
Expand Up @@ -970,11 +970,13 @@ fn connect_run_custom_build_deps(state: &mut State<'_, '_>) {
.iter()
.map(move |a| (reverse_dep, a))
})
// Exclude ourself
.filter(|(_parent, other)| other.unit.pkg != unit.pkg)
// Only deps with `links`.
.filter(|(_parent, other)| {
other.unit.pkg != unit.pkg
&& other.unit.target.is_linkable()
&& other.unit.pkg.manifest().links().is_some()
state.gctx.cli_unstable().any_build_script_metadata
|| (other.unit.target.is_linkable()
&& other.unit.pkg.manifest().links().is_some())
})
// Avoid cycles when using the doc --scrape-examples feature:
// Say a workspace has crates A and B where A has a build-dependency on B.
Expand Down
2 changes: 2 additions & 0 deletions src/cargo/core/features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -844,6 +844,7 @@ unstable_cli_options!(
// All other unstable features.
// Please keep this list lexicographically ordered.
advanced_env: bool,
any_build_script_metadata: bool = ("Allow any build script to specify env vars via cargo::metadata=key=value"),
asymmetric_token: bool = ("Allows authenticating with asymmetric tokens"),
avoid_dev_deps: bool = ("Avoid installing dev-dependencies if possible"),
binary_dep_depinfo: bool = ("Track changes to dependency artifacts"),
Expand Down Expand Up @@ -1374,6 +1375,7 @@ impl CliUnstable {
// Unstable features
// Sorted alphabetically:
"advanced-env" => self.advanced_env = parse_empty(k, v)?,
"any-build-script-metadata" => self.any_build_script_metadata = parse_empty(k, v)?,
"asymmetric-token" => self.asymmetric_token = parse_empty(k, v)?,
"avoid-dev-deps" => self.avoid_dev_deps = parse_empty(k, v)?,
"binary-dep-depinfo" => self.binary_dep_depinfo = parse_empty(k, v)?,
Expand Down
11 changes: 11 additions & 0 deletions src/doc/src/reference/unstable.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ Each new feature described below should explain how to use it.
* Build scripts and linking
* [Metabuild](#metabuild) --- Provides declarative build scripts.
* [Multiple Build Scripts](#multiple-build-scripts) --- Allows use of multiple build scripts.
* [Any Build Script Metadata](#any-build-script-metadata) --- Allow any build script to specify env vars via `cargo::metadata=key=value`
* Resolver and features
* [no-index-update](#no-index-update) --- Prevents cargo from updating the index cache.
* [avoid-dev-deps](#avoid-dev-deps) --- Prevents the resolver from including dev-dependencies during resolution.
Expand Down Expand Up @@ -313,6 +314,16 @@ build = ["foo.rs", "bar.rs"]
where the `<script-name>` is the file-stem of the build script, exactly as-is.
For example, `bar_OUT_DIR` for script at `foo/bar.rs`. (Only set during compilation, can be accessed via `env!` macro)

## Any Build Script Metadata
* Tracking Issue: [#14903](https://github.com/rust-lang/cargo/issues/3544)

Allow any build script to specify env vars via `cargo::metadata=key=value`

Depedant build scripts can access these key/value pair by reading the `CARGO_DEP_<dep>_<key>` env variable at runtime.
For build scripts of crates with a `links`, both `DEP_<links>_<key>` and `CARGO_DEP_<dep>_<key>` will be set.

Note that `dep` and `key` in `CARGO_DEP_<dep>_<key>` are uppercased and hyphens (`-`) replaced with underscores (`_`).

## public-dependency
* Tracking Issue: [#44663](https://github.com/rust-lang/rust/issues/44663)

Expand Down
Loading