Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Features dependency graph appears to be shared across distinct root crates #8144

Closed
rickvanprim opened this issue Apr 22, 2020 · 4 comments
Closed
Labels
C-bug Category: bug

Comments

@rickvanprim
Copy link

Problem
With the following minimal workspace, it's not possible to run cargo build at the workspace level, however it works as expected when run inside the individual binary crates.

Steps
Set up the following workspace:

root/
    Cargo.toml:
        [workspace]
        members = ["bin_a", "bin_b"]
    shared/
        Cargo.toml:
            [package]
            name = "shared"
            version = "0.1.0"
            edition = "2018"

            [dependencies]

            [features]
            a = []
            b = []
        src/
            lib.rs:
                #[cfg(feature = "a")]
                pub fn shared()
                {
                    println!("A");
                }

                #[cfg(feature = "b")]
                pub fn shared()
                {
                    println!("B");
                }
    bin_a/
        Cargo.toml:
            [package]
            name = "bin_a"
            version = "0.1.0"
            edition = "2018"

            [dependencies]
            shared = { path = "../shared", features = ["a"] }
        src/
            main.rs:
                fn main()
                {
                    println!("Hello, world!");
                    ::shared::shared();
                }
    bin_b/
        Cargo.toml:
            [package]
            name = "bin_b"
            version = "0.1.0"
            edition = "2018"

            [dependencies]
            shared = { path = "../shared", features = ["b"] }
        src/
            main.rs:
                fn main()
                {
                    println!("Hello, world!");
                    ::shared::shared();
                }

Run cargo build inside of root/.
Note that it fails on a duplicate symbol.
Navigate into bin_a and bin_b and execute cargo build in each.
Note that both succeed and output into the same target directory, but there are two copies of shared with different hashes as expected.

Possible Solution(s)
It seems like Cargo should have a distinct features dependency graph per root crate that is being built, so that being in a workspace doesn't cause unnecessary (or in this sample, contradictory) features to become enabled when they would not be enabled in a non-workspace build.

Notes

Output of cargo version: cargo 1.44.0-nightly (ebda506 2020-04-16)

Some relation to #4361 and #7754 .

@rickvanprim rickvanprim added the C-bug Category: bug label Apr 22, 2020
@alexcrichton
Copy link
Member

Thanks for the report! This is expected behavior because features are intended to be unioned. When building the workspace it builds all packages which unions the features of the shared create, leading to the same function being defined twice.

@hnj2
Copy link

hnj2 commented Aug 31, 2020

Thanks for the report! This is expected behavior because features are intended to be unioned. When building the workspace it builds all packages which unions the features of the shared create, leading to the same function being defined twice.

This very sad as it makes testing incompatible features of a crate rather hacky.

What would be the best practise way of testing incompatible features, just not using workspaces?

@rickvanprim
Copy link
Author

@hnj2 it's not ideal, but the workaround I've been using is to encode the features in the crates themselves.

Example:
crate foo_feature_a that defines feature_a and defaults it to on, and then its root lib.rs is as follows:

#[path = "../foo_common/lib.rs"]
mod foo_common;
pub use self::foo_common::*;

Then repeat with foo_feature_b, etc., as needed.

Alternatively you can avoid Cargo Workspaces and just build the explicit manifests in a larger build script, but this has issues with relative paths (see #8506).

@hnj2
Copy link

hnj2 commented Sep 1, 2020

@rickvanprim Thanks for the input.

After some more testing I've adopted your method 🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: bug
Projects
None yet
Development

No branches or pull requests

3 participants