Skip to content

CARGO_PRIMARY_PACKAGE is not included in the fingerprint, and can change for workspace members #14678

Open
@ehuss

Description

@ehuss

Problem

The is_primary_package status can change for workspace members, but it is not tracked in the fingerprint. This can cause the CARGO_PRIMARY_PACKAGE to change, but not be reflected in the build.

This can happen when you run a cargo command that selects all workspace members as roots, and then later run a separate cargo command that only selects one of them, but includes another workspace member as a dependency. That second command will act differently if you hadn't run the first command.

I don't know if this really matters, and maybe we decide to just ignore it. However, I'm uncomfortable with untracked state in the fingerprint.

Steps

Here's a test using cargo's testsuite:

#[cargo_test]
fn primary_package_changes_in_workspace() {
    // Tests for what happens to CARGO_PRIMARY_PACKAGE when a workspace member
    // toggles between being a "primary" package, and just a non-primary
    // dependency.
    let p = project()
        .file(
            "Cargo.toml",
            r#"
                [workspace]
                members = ["a", "b"]
            "#,
        )
        .file(
            "a/Cargo.toml",
            r#"
                [package]
                name = "a"
                edition = "2021"

                [dependencies]
                b = { path="../b" }
            "#,
        )
        .file(
            "a/src/main.rs",
            r#"
                fn main() {
                    println!("a={:?}", option_env!("CARGO_PRIMARY_PACKAGE"));
                    b::b();
                }
            "#,
        )
        .file("b/Cargo.toml", &basic_lib_manifest("b"))
        .file(
            "b/src/lib.rs",
            r#"
                pub fn b() {
                    println!("b={:?}", option_env!("CARGO_PRIMARY_PACKAGE"));
                }
            "#,
        )
        .build();

    // Try with "default"
    p.cargo("run")
        .with_stdout_data(str![[r#"
a=Some("1")
b=Some("1")

"#]])
        .run();

    p.build_dir().rm_rf();

    // Try with explicit
    p.cargo("run -p a")
        .with_stdout_data(str![[r#"
a=Some("1")
b=None

"#]])
        .run();

    p.build_dir().rm_rf();

    // Build selects all workspace members as "primary".
    p.cargo("build").run();

    // FIXME: This command emits a different output than the `run -p a` above
    p.cargo("run -p a")
        .with_stdout_data(str![[r#"
a=Some("1")
b=Some("1")

"#]])
        .run();
}

Possible Solution(s)

A possible solution is to include the primary state in the fingerprint.

Changing this will need very careful consideration of the impact on clippy (the primary reason this exists). Will it cause more cache thrashing for clippy users? If so, maybe we need to rethink how it is set for workspace dependencies.

Notes

No response

Version

cargo 1.83.0-nightly (ad074ab 2024-10-04)
release: 1.83.0-nightly
commit-hash: ad074ab
commit-date: 2024-10-04
host: aarch64-apple-darwin
libgit2: 1.8.1 (sys:0.19.0 vendored)
libcurl: 8.7.1 (sys:0.4.74+curl-8.9.0 system ssl:(SecureTransport) LibreSSL/3.3.6)
ssl: OpenSSL 1.1.1w 11 Sep 2023
os: Mac OS 14.6.1 [64-bit]

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-environment-variablesArea: environment variablesA-rebuild-detectionArea: rebuild detection and fingerprintingA-workspacesArea: workspacesC-bugCategory: bugS-triageStatus: This issue is waiting on initial triage.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions