rust-lang / cargo

The Rust package manager
https://doc.rust-lang.org/cargo
Apache License 2.0
12.82k stars 2.43k forks source link

Workspace "profile ignored" warning discounts the possibility of publishing binary crates which use profile settings #8264

Open daboross opened 4 years ago

daboross commented 4 years ago

Problem

When a profile section is provided in the Cargo.toml for a crate in a workspace that isn't the workspace root, the following warning is generated:

warning: profiles for the non root package will be ignored, specify profiles at the workspace root:
package:   /home/daboross/workspace/subcrate/Cargo.toml
workspace: /home/daboross/workspace/Cargo.toml

However, if subcrate is a binary crate published to crates.io, then the profile section will be used when someone cargo installs that crate. Moving the profile section to the workspace root would remove the settings when cargo installing the crate downloaded from crates.io.

Steps

  1. Create a workspace & subcrate:
    cargo new workspace && cd workspace && cargo new subcrate
  2. Add workspace config:
    echo "subcrate = { path = 'subcrate' }" >> Cargo.toml
    echo "[workspace]" >> Cargo.toml

    or copy whole Cargo.toml:

    
    [package]
    name = "workspace"
    version = "0.1.0"
    authors = ["David Ross <daboross@daboross.net>"]
    edition = "2018"

See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies] subcrate = { path = 'subcrate' } [workspace]

3. Add profile to subcrate:

echo "[profile.release]" >> subcrate/Cargo.toml echo "opt-level = 3" >> subcrate/Cargo.toml

Or copy whole `Cargo.toml`:
```toml
[package]
name = "subcrate"
version = "0.1.0"
authors = ["David Ross <daboross@daboross.net>"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
[profile.release]
opt-level = 3
  1. Build crates:
    $ cargo build
    warning: profiles for the non root package will be ignored, specify profiles at the workspace root:
    package:   /home/daboross/workspace/subcrate/Cargo.toml
    workspace: /home/daboross/workspace/Cargo.toml
    Compiling workspace v0.1.0 (/home/daboross/workspace)
    Finished dev [unoptimized + debuginfo] target(s) in 0.36s

Possible Solution(s)

Add a way to ignore this warning, and output a suggestion for that when outputting the error? Could be something like

[cargo-warnings]
ignored-profile = "ignore"

And when the error occurs, something like:

note: this profile will be used when publishing binary crates. To ignore warning, add the following to /home/dabross/workspace/subcrate/Cargo.toml:
  [cargo-warnings]
  ignored-profile = "ignore"

Another option could be to provide an option to copy configuration from workspace root when publishing the crate?

Notes

Output of cargo version: cargo 1.45.0-nightly (258c89644 2020-04-30)

I found this bug from this post on the users.rust-lang.org forum. The user in question decided to simply not have a workspace to avoid this error, but I don't think that's a good solution in general.

ehuss commented 4 years ago

The team discussed this a bit. We feel like it would probably be best if cargo publish would copy the profile from the workspace into the member package. Does that sound like it would resolve your use case?

I have definitely felt uneasy with that warning, since it cannot be silenced. However, I'm also a little uncomfortable with adding config and machinery for silencing it (just to avoid complexity).

kornelski commented 4 years ago

I get the same warning, but I'm not publishing anything. Copying of the profile would not be useful to me.

I combine a few standalone projects into a large workspace using git submodules. In my setup that is easier to work with than Cargo git dependencies and [patch].

The problem is that one of the subprojects pulled into the workspace is usable independently, and has its own profile. That one subproject supports WASM, so it has a profile with panic=abort; opt-level = 's', but I don't want that setting for the whole workspace. I would prefer that subproject to keep its profile when it's used outside of my workspace, but keep the workspace overriding that with its own profile.

So to me Cargo does the right thing. I'm aware the other profile is ignored, and that's exactly what I want. I just don't need to be reminded about this on every build.

ehuss commented 4 years ago

An alternate solution we discussed would be to have some kind of nested workspace support for the git submodule use case. Cargo and Rust have the same problem, since they use git submodules. But it sounds like @kornelski specifically wants to disable the profile. Hmm..

kornelski commented 4 years ago

To me it'd make sense if Cargo had a similar allow/deny mechanism that rustc has.

My problem is also related to lack of per-target profiles: #4897. I wouldn't need the other profile to be ignored in the workspace context if I could limit that profile to WASM targets.

jrvanwhy commented 4 years ago

The team discussed this a bit. We feel like it would probably be best if cargo publish would copy the profile from the workspace into the member package. Does that sound like it would resolve your use case?

Hi, I'm the poster from users.rust-lang.org. Yes, that would resolve my use case.

DzenanJupic commented 3 years ago

I just ran into the issue @kornelski described. I have a workspace, and one of the crates is a WASM application which should be compiled with panic = "abort" and opt-level = 's'. By creating a [profile.release.package.<PACKAGE>] section in the workspace Cargo.toml I can set opt-level = 's'.

For panic = "abort" there seems to be a bug, since when I place it in the [profile.release.package.<PACKAGE>], cargo says:

error: failed to parse manifest at `PATH\TO\WORKSPACE\Cargo.toml`

Caused by:
  `panic` may not be specified in a `package` profile

And when I place it in the crates Cargo.toml cargo says:

warning: profiles for the non root package will be ignored, specify profiles at the workspace root:
package:   PATH\TO\WORKSPACE\PACKAGE\Cargo.toml
workspace: PATH\TO\WORKSPACE\Cargo.toml

So there's no way of setting panic = "abort" while making cargo happy.

nickgerace commented 3 years ago

I ran into this as well. Same as @DzenanJupic with panic = "abort".

JesusGuzmanJr commented 3 years ago

I also ran into the same issue as @DzenanJupic. I was able to sidestep the issue by removing the cargo workspace from my project and instead use workspace emulation as provided by cargo-make.

Before So instead of using a cargo workspace with a virtual manifest like this:

# Cargo.toml
[workspace]
members = ["crate1", "crate2"]

After I now use Makefiles in all my crates. This is what the root Makefile looks like:

# Makefile.toml
[env]
# this tells cargo-make that this directory acts as a workspace root
CARGO_MAKE_WORKSPACE_EMULATION = true

# a list of crate members. since we do not have a Cargo.toml, we will need to specify this in here.
CARGO_MAKE_CRATE_WORKSPACE_MEMBERS = [
  "crate1",
  "crate2",
]

After setting up Makefiles in all my other crates I can now build my project like so:

Debug Build cargo make build

Release Build cargo make build --profile production

With cargo-make's workspace emulation, I no longer get the "profile ignored" warning and my WASM is optimized in release builds. 🎉

JoshMcguigan commented 2 years ago

I have the same issue with wanting to specify panic = "abort" for one package in a workspace.

I noticed the cargo docs mention this limitation:

[profile.<name>.package.<name>]  # Override profile for a package.
# Same keys for a normal profile (minus `panic`, `lto`, and `rpath`).

Is there a fundamental reason cargo can't support this? Or is it more a matter of requiring some additional work to implement?

EdmundsEcho commented 2 years ago

Use case

In my use case I have what I believe is called a "virtual" workspace. Virtual because it does not hold any dependencies. I have 4 project members.

What is surprising, is that I get the warning when I call to compile one of the projects. For instance,

cargo build \
        --release \
        --target x86_64-unknown-linux-musl \
        --bin oauth \
        --target-dir target

Why give me a warning that the Cargo.toml in the project-member I'm trying to compile will be ignored? (which by definition of compiling, cannot be the case).

Impact ability to create a "dependency-only" layer when working in docker?

This all said, I do wonder if it somehow prevents my ability to create a "dependency-only" layer in my builds?... perhaps depending on whether I specify a specific member-project?

WookashWackomy commented 1 year ago

Any updates on this issue? It pollutes cargo build's output so much that it makes it hardly readable. Right now I'm redirecting stdout/stderr to the file just to be able to read build log....I'm close to creating a custom filtering script just because I'm not able to follow/read build logs. Seems ridiculous :/

epage commented 1 year ago

What we do for the resolver field is we apply the workspace field to the individual packages when publishing so that the workspace's configuration is available for cargo install (#10911, #10961).

i would expect the same behavior for profile though it sounds like people are relying on this and it would be a breaking change. Maybe we could make this change on the next Edition.

wackazong commented 1 year ago

What about using the env var CARGO_PROFILE_<name>_PANIC as a workaround when building?