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

Regression: build-dependencies and dependencies should not have features unified #12676

Closed
Imisnew2 opened this issue Sep 15, 2023 · 4 comments
Closed
Labels
C-bug Category: bug S-triage Status: This issue is waiting on initial triage.

Comments

@Imisnew2
Copy link

Problem

It appears that cargo regressed on #4866 -- when a dependency exists as both a build-dependency and normal dependency, but they use different features, the features are unified. The documentation around features explicitly states otherwise:

The version "2" resolver avoids unifying features in a few situations where that unification can be unwanted. The exact situations are described in the resolver chapter, but in short, it avoids unifying in these situations:

Avoiding the unification is necessary for some situations. For example, if a build-dependency enables a std feature, and the same dependency is used as a normal dependency for a no_std environment, enabling std would break the build.

Steps

Reproducer 1

  1. Setup the following workspace:

<directory layout>

crates/
- foo/
  - src/
    - main.rs
  - Cargo.toml
- bar/
  - src/
    - lib.rs
  - Cargo.toml
Cargo.toml

crates/foo/src/main.rs

fn main() {
    println!("Hello from foo");
    bar::lib();
}

crates/foo/Cargo.toml

[package]
name = "foo"
version = "0.1.0"

[dependencies]
bar.path = "../bar"

[build-dependencies]
bar = { path = "../bar", features = ["build_feature"] }

crates/bar/src/lib.rs

pub fn lib() {
    println!("Hello from bar");
    #[cfg(feature = "build_feature")]
    println!("  bar build_feature on!");
}

crates/bar/Cargo.toml

[package]
name = "bar"
version = "0.1.0"

[features]
build_feature = []

Cargo.toml

[workspace]
members = ["crates/*"]
  1. Build the workspace: cargo build
  2. Run the foo binary: ./target/debug/foo

Expected Result:

Hello from foo
Hello from bar

Actual Result:

Hello from foo
Hello from bar
  bar build_feature on!

Reproducer 2

The above is a simplified version of what I found was happening in our code base. Just in case there's a difference I'm not aware of, the specific issue I noticed in our code base was structured as follows:

  • foo has a featured called "build_feature".
  • foo has a dev-dependency of bar.path = "../bar"
  • bar has a build-dependency of foo = { path = "../foo", features["build_feature"] }
  • Running cargo test -p foo builds foo's tests with "build_feature" enabled.

crates/foo/src/lib.rs

pub fn lib() {
    println!("Hello from foo");
    #[cfg(feature = "build_feature")]
    panic!("foo build_feature on!");
}

#[cfg(test)]
mod test {
    #[test]
    fn basic() {
        bar::lib();
        super::lib();
    }
}

crates/foo/Cargo.toml

[package]
name = "foo"
version = "0.1.0"

[features]
build_feature = []

[dev-dependencies]
bar.path = "../bar"

crates/bar/src/lib.rs

pub fn lib() {
    println!("Hello from bar");
}

crates/bar/Cargo.toml

[package]
name = "bar"
version = "0.1.0"

[build-dependencies]
foo = { path = "../foo", features = ["build_feature"] }

Cargo.toml

[workspace]
members = ["crates/*"]

Expected Result:

<test succeeds>

Actual Result:

---- test::basic stdout ----
Hello from bar
Hello from foo
thread 'test::basic' panicked at 'foo build_feature on!', crates/foo/src/lib.rs:4:5

Possible Solution(s)

No response

Notes

No response

Version

$ cargo version --verbose
cargo 1.71.1 (7f1d04c00 2023-07-29)
release: 1.71.1
commit-hash: 7f1d04c0053083b98fa50b69b6f56e339b0556a8
commit-date: 2023-07-29
host: aarch64-apple-darwin
libgit2: 1.6.4 (sys:0.17.1 vendored)
libcurl: 7.88.1 (sys:0.4.61+curl-8.0.1 system ssl:(SecureTransport) LibreSSL/3.3.6)
ssl: OpenSSL 1.1.1t  7 Feb 2023
os: Mac OS 13.4.1 [64-bit]
@Imisnew2 Imisnew2 added C-bug Category: bug S-triage Status: This issue is waiting on initial triage. labels Sep 15, 2023
@epage
Copy link
Contributor

epage commented Sep 15, 2023

So I haven't had the chance to run this to verify but don't you need workspace.resolver = "2"?

@Imisnew2
Copy link
Author

Imisnew2 commented Sep 15, 2023

So I haven't had the chance to run this to verify but don't you need workspace.resolver = "2"?

I think this solves the issue. Is this something specific to virtual workspaces? Just confirming before closing the issue.

I had reduced the example too much. The original code-base has package.edition = "2021" in each of the member crate's Cargo.toml files. But I guess this has no effect in virtual workspaces?

@weihanglo
Copy link
Member

I guess this has no effect in virtual workspaces?

Yes, and sorry for the inconvenience. We had some efforts around this, e.g. #10910 and #12388. Please read the doc here and here for more.

The resolver is a global option that affects the entire workspace. The resolver version in dependencies is ignored, only the value in the top-level package will be used. If using a virtual workspace, the version should be specified in the [workspace] table, for example:

@Imisnew2
Copy link
Author

I see. Thanks for the assistance! Using workspace.resolver = "2" in the root Cargo.toml solved my issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: bug S-triage Status: This issue is waiting on initial triage.
Projects
None yet
Development

No branches or pull requests

3 participants