Skip to content

bindeps: wrong features in a build script for a shared dependency #10452

Closed
@ehuss

Description

@ehuss

With -Zbindeps, if there is a dependency that is used as a binary artifact, and also as a normal dependency, the build script for that shared dependency is receiving the wrong features.

In the following example, common gets built twice, once as the target bindep with feature f2, and once as a normal dependency with feature f1. However, the build script only has CARGO_FEATURE_F1 set in both cases.

#[cargo_test]
fn build_script_features_for_shared_dependency() {
    // When a build script is built and run, its features should match. Here:
    //
    // foo
    //   -> artifact on d1 with target
    //   -> common with features f1
    //
    // d1
    //   -> common with features f2
    //
    // common has features f1 and f2, with a build script.
    //
    // When common is built as a dependency of d1, it should have features
    // `f2` (for the library and the build script).
    //
    // When common is built as a dependency of foo, it should have features
    // `f1` (for the library and the build script).
    if cross_compile::disabled() {
        return;
    }
    let target = cross_compile::alternate();
    let p = project()
        .file(
            "Cargo.toml",
            &r#"
                [project]
                name = "foo"
                version = "0.0.1"
                resolver = "2"

                [dependencies]
                d1 = { path = "d1", artifact = "bin", target = "$TARGET" }
                common = { path = "common", features = ["f1"] }
            "#
            .replace("$TARGET", target),
        )
        .file(
            "src/main.rs",
            r#"
                fn main() {
                    let _b = include_bytes!(env!("CARGO_BIN_FILE_D1"));
                    common::f1();
                }
            "#,
        )
        .file(
            "d1/Cargo.toml",
            r#"
                [package]
                name = "d1"
                version = "0.0.1"

                [dependencies]
                common = { path = "../common", features = ["f2"] }
            "#,
        )
        .file(
            "d1/src/main.rs",
            r#"fn main() {
                common::f2();
            }"#,
        )
        .file(
            "common/Cargo.toml",
            r#"
                [package]
                name = "common"
                version = "0.0.1"

                [features]
                f1 = []
                f2 = []
            "#,
        )
        .file(
            "common/src/lib.rs",
            r#"
                #[cfg(feature = "f1")]
                pub fn f1() {}

                #[cfg(feature = "f2")]
                pub fn f2() {}
            "#,
        )
        .file(
            "common/build.rs",
            &r#"
                use std::env::var_os;
                fn main() {
                    if std::env::var("TARGET").unwrap() == "$TARGET" {
                        assert!(var_os("CARGO_FEATURE_F1").is_none());
                        assert!(var_os("CARGO_FEATURE_F2").is_some());
                    } else {
                        assert!(var_os("CARGO_FEATURE_F1").is_some());
                        assert!(var_os("CARGO_FEATURE_F2").is_none());
                    }
                    assert_eq!(var_os("CARGO_FEATURE_F1").is_some(), cfg!(feature="f1"));
                    assert_eq!(var_os("CARGO_FEATURE_F2").is_some(), cfg!(feature="f2"));
                }
            "#
            .replace("$TARGET", target),
        )
        .build();

    p.cargo("build -Z bindeps")
        .masquerade_as_nightly_cargo()
        .run();
}

cc @Byron

Metadata

Metadata

Assignees

No one assigned

    Labels

    Z-bindepsNightly: binary artifact dependencies

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions