Skip to content

Conversation

@ranger-ross
Copy link
Member

@ranger-ross ranger-ross commented Dec 26, 2025

What does this PR try to resolve?

See #3544

Unresolved questions

How to test and review this PR?

See the e2e tests included in this PR.
As for the changes, they are not too bad.


meta: I picked this up to learn a bit more about the build script and unit graph code in Cargo.

r? @epage

@rustbot rustbot added A-build-scripts Area: build.rs scripts A-documenting-cargo-itself Area: Cargo's documentation A-unstable Area: nightly unstable support S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Dec 26, 2025
@ranger-ross ranger-ross force-pushed the build-script-artibtary-env-vars branch from 47d8a0f to c654a94 Compare December 26, 2025 17:31
Comment on lines +1440 to +1544
assert_eq!(env::var("CARGO_DEP_A_FOO").unwrap(), "bar");
assert_eq!(env::var("CARGO_DEP_A_BAR").unwrap(), "baz");
Copy link
Contributor

Choose a reason for hiding this comment

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

For me, one unresolved question is what to name this env variable

  • Technically, name_key is ambiguous. foo_bar_alice_bob could be foo_bar + alice_bob, foo + bar_alice_bob, etc and technically packages could conflict
  • Whether we should envify the package name and key or not. iirc we do it in some places but not others. Overall, I would prefer we would never do it so it matches the name people see in Cargo.toml

Copy link
Member Author

Choose a reason for hiding this comment

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

  • Technically, name_key is ambiguous. foo_bar_alice_bob could be foo_bar + alice_bob, foo + bar_alice_bob, etc and technically packages could conflict

I suppose one idea would be to using another delimiter between the name and key.
Maybe double underscore? foo_bar__alice_bob would now be different than foo__bar_alice_bob.
Not sure if there are any other delimiters that are compatible across enough platforms. I think POSIX is already pretty restrictive with what can be used an env var name.

  • Whether we should envify the package name and key or not. iirc we do it in some places but not others. Overall, I would prefer we would never do it so it matches the name people see in Cargo.toml

Given that env vars from cargo::metadata=KEY=VALUE are already envify'd in DEP_<links>_<key> I think it makes sense to keep that? I think it'd be more confusing if cargo::metadata=KEY=VALUE had multiple behaviors.

Copy link
Contributor

Choose a reason for hiding this comment

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

Note that I highlighted these for being called out in the stabilization conversations and do not block this PR. I don't have concrete ideas to say exactly what should be done but want to raise these for a wider conversation.

@ranger-ross ranger-ross force-pushed the build-script-artibtary-env-vars branch 2 times, most recently from 00fac87 to 7253b99 Compare December 27, 2025 12:58
if dep.unit.mode.is_run_custom_build() {
let dep_metadata = build_runner.get_run_build_script_metadata(&dep.unit);

// FIXME: Do we need to handle dev-dependencies and/or build-dependencies?
Copy link
Contributor

Choose a reason for hiding this comment

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

Calling out for resolving

Copy link
Contributor

Choose a reason for hiding this comment

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

We should do whatever we do for links

Copy link
Member Author

Choose a reason for hiding this comment

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

I spent some time testing this and as far as I can tell links only propagates env vars set with cargo::metadata if its a regular dependency.

I can see we explicitly filter out dev-dependencies in:

// Skip dependencies induced via dev-dependencies since
// connections between `links` and build scripts only happens
// via normal dependencies. Otherwise since dev-dependencies can
// be cyclic we could have cyclic build-script executions.

and I believe that build-dependencies are implicitly not included when the unit graph is built.

I removed the FIXME comment, but lmk if you think there is something I missed

Copy link
Contributor

Choose a reason for hiding this comment

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

We should probably have tests showing the behavior for both ways of accessing metadata. Here is what I used for experimenting:

#[cargo_test]
fn metadata_from_dep_kinds() {
    let set_metadata = r#"
fn main() {
    println!("cargo::metadata=key=value");
}
"#;

    let get_metadata = r#"
fn main() {
    println!("cargo::warning={:?}", std::env::var("DEP_FOO_KEY"));
}
"#;

    let p = project()
        .file(
            "Cargo.toml",
            r#"
                [workspace]
                resolver = "3"
                members = ["links", "n", "b", "d"]
            "#,
        )
        .file(
            "links/Cargo.toml",
            r#"
[package]
name = "links"
edition = "2024"
links = "foo"
"#,
        )
        .file("links/src/lib.rs", "")
        .file("links/build.rs", set_metadata)
        .file(
            "n/Cargo.toml",
            r#"
[package]
name = "n"
edition = "2024"

[dependencies]
links.path = "../links"
"#,
        )
        .file("n/src/lib.rs", "")
        .file("n/build.rs", get_metadata)
        .file(
            "b/Cargo.toml",
            r#"
[package]
name = "b"
edition = "2024"

[build-dependencies]
links.path = "../links"
"#,
        )
        .file("b/src/lib.rs", "")
        .file("b/build.rs", get_metadata)
        .file(
            "d/Cargo.toml",
            r#"
[package]
name = "d"
edition = "2024"

[dev-dependencies]
links.path = "../links"
"#,
        )
        .file("d/src/lib.rs", "")
        .file("d/build.rs", get_metadata)
        .build();

    p.cargo("check --all-targets")
        .with_stderr_data(
            str![[r#"
[COMPILING] links v0.0.0 ([ROOT]/foo/links)
[COMPILING] n v0.0.0 ([ROOT]/foo/n)
[COMPILING] b v0.0.0 ([ROOT]/foo/b)
[COMPILING] d v0.0.0 ([ROOT]/foo/d)
[WARNING] [email protected]: Ok("value")
[WARNING] [email protected]: Err(NotPresent)
[WARNING] [email protected]: Err(NotPresent)
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s

"#]]
            .unordered(),
        )
        .run();
}

just needs the new CARGO_DEP env variables added to it

Copy link
Member Author

Choose a reason for hiding this comment

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

ahh thanks, using cargo::warning so we can leverage the snapbox testing infra is clever.

I added this test to the test commit and modified it to include CARGO_DEP_LINKS_KEY in the feat commit.

epage added a commit to epage/cargo that referenced this pull request Dec 29, 2025
Remaining `build`s:
- linker is potentially involved
- testing related to dev-dependencies
  (didn't look to see if `check --benches` could replace `bench`)

Similarly, some `run`s` were removed so long as compilation verified the
same details.

Inspired by rust-lang#16436 which is adding more tests which don't need `build`
but copied the existing ones.
github-merge-queue bot pushed a commit that referenced this pull request Dec 29, 2025
### What does this PR try to resolve?

Reduce test overhead by changing `build`s to `check`s.

Similarly, some `run`s` were removed so long as compilation verified the
same details.

Inspired by #16436 which is adding more tests which don't need `build`
but copied the existing ones.

### How to test and review this PR?

Remaining `build`s:
- linker is potentially involved
- testing related to dev-dependencies (didn't look to see if `check
--benches` could replace `bench`)
@ranger-ross ranger-ross force-pushed the build-script-artibtary-env-vars branch from 7253b99 to 180d3c5 Compare December 30, 2025 06:04
@rustbot

This comment has been minimized.

Comment on lines +468 to +470
d.package_name() == dep.unit.pkg.name()
&& d.source_id() == dep.unit.pkg.package_id().source_id()
&& d.version_req().matches(unit.pkg.version())
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

@rustbot

This comment has been minimized.

@ranger-ross ranger-ross force-pushed the build-script-artibtary-env-vars branch from 180d3c5 to a919c32 Compare December 31, 2025 01:39
@rustbot
Copy link
Collaborator

rustbot commented Dec 31, 2025

This PR was rebased onto a different master commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

@epage epage added this pull request to the merge queue Dec 31, 2025
Merged via the queue into rust-lang:master with commit 5d927cd Dec 31, 2025
29 checks passed
@rustbot rustbot removed the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Dec 31, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-build-scripts Area: build.rs scripts A-documenting-cargo-itself Area: Cargo's documentation A-unstable Area: nightly unstable support

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants