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

cargo install --git builds workspace.default-members when it should not #11058

Closed
tedinski opened this issue Sep 6, 2022 · 2 comments · Fixed by #11067
Closed

cargo install --git builds workspace.default-members when it should not #11058

tedinski opened this issue Sep 6, 2022 · 2 comments · Fixed by #11067
Labels
A-workspaces Area: workspaces C-bug Category: bug Command-install

Comments

@tedinski
Copy link
Contributor

tedinski commented Sep 6, 2022

Problem

  • This affects --path as well.
  • It does not affect e.g. crates.io because the Cargo.toml there have workspace stripped from them.

When running a command like:

cargo install --locked --git /~https://github.com/model-checking/kani  kani-verifier

The "normal" behavior is to check out that repo, and only build the specified kani-verifier package from the workspace. Once we've added a workspace.default-members to Cargo.toml, however, cargo now seems to build those packages as well. (For Kani specifically, this fails, as other workspace members like kani-compiler should only be built against a specific Rust nightly...)

We did not expect cargo install behavior to change by changing workspace default members, and I believe this is a bug.

Steps

  1. Create a cargo workspace with multiple packages and workspace.default-members
  2. cargo install --path or --git one package from that workspace.
  3. Observe that all default-members get built as well.

Possible Solution(s)

No response

Notes

Suggested tags:

  • Command-install
  • A-workspaces

Version

cargo 1.65.0-nightly (4ed54cecc 2022-08-27)
release: 1.65.0-nightly
commit-hash: 4ed54cecce3ce9ab6ff058781f4c8a500ee6b8b5
commit-date: 2022-08-27
host: x86_64-unknown-linux-gnu
libgit2: 1.5.0 (sys:0.15.0 vendored)
libcurl: 7.83.1-DEV (sys:0.4.55+curl-7.83.1 vendored ssl:OpenSSL/1.1.1q)
os: Ubuntu 20.04 (focal) [64-bit]
@tedinski tedinski added the C-bug Category: bug label Sep 6, 2022
@tedinski
Copy link
Contributor Author

tedinski commented Sep 7, 2022

Some quick analysis of the cause: A cargo install invocation shares one "global" CompileOptions, which always has spec = Packages::Default. (This is just because cargo install doesn't take any of the arguments that affect the spec.)

The "global" nature means we can't just set spec = Packages::Packages(krates) because there might be multiple targets. (e.g. cargo install foo bar would complain it can't find package bar when it's building foo in foo's workspace. And vice versa. Because these were just two wholly different requested packages.)

Some possible approaches for fixing this:

  1. Eliminate this sharing, and clone CompileOptions for each InstallablePackage. This would allow us to change the spec for each build. I tried this and ran into CompileOptions having BuildOptions which has a RefCell however, and I haven't investigated this direction further...
  2. In make_ws_rustc_target (which creates the workspace for a cargo install) we could (introduce a new workspace method to) mutate the default-members to just include the target package. That way Packages::Default would resolve correctly. This is a bit weird but it is a small, minimally-impactful code change.
  3. Some deeper refactoring might be necessary?

@tedinski
Copy link
Contributor Author

tedinski commented Sep 8, 2022

After a bit more investigation, I think this issue is narrower than I originally thought.

cargo install effectively does a cargo build --release in the requested package. For most packages, this creates a workspace with current_manifest pointing to the requested package (and root_manifest pointing to the root of the discovered workspace).

This means that building in "default mode" will spot that it's not at the workspace root, but in a requested package. Thus, it would build that package.

However, when the requested package is the workspace root package (i.e. in a non-virtual workspace), a cargo build --release no longer sees current_manifest as different, so it... builds the workspace.default-members.

If default-members doesn't have the root package, this even means that it won't even build or install the requested package, but those packages instead, but will also install them as if they were the root package.

I think this even means there's no way to install the root package of a non-virtual workspace, where default-members does not contain the root package, with --path or --git.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-workspaces Area: workspaces C-bug Category: bug Command-install
Projects
None yet
2 participants