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

Named custom cargo profiles #2678

Open
wants to merge 17 commits into
base: master
from

Conversation

Projects
None yet
8 participants
@da-x
Copy link
Member

commented Apr 4, 2019

Summary

The proposed change to Cargo is to add the ability to specify user-defined profiles in addition to the five predefined profiles, dev, release, test, bench, and the less talked-about doc. It is also desired in this scope to reduce confusion regarding where final outputs reside, and increase the flexbility to specify the user-defined profile attributes.

Related links

Show resolved Hide resolved text/0000-named-custom-cargo-profiles.md Outdated
Show resolved Hide resolved text/0000-named-custom-cargo-profiles.md Outdated
Show resolved Hide resolved text/0000-named-custom-cargo-profiles.md Outdated
Show resolved Hide resolved text/0000-named-custom-cargo-profiles.md Outdated

kennytm and others added some commits Apr 4, 2019

Update text/0000-named-custom-cargo-profiles.md
Co-Authored-By: da-x <alonid@gmail.com>
Update text/0000-named-custom-cargo-profiles.md
Co-Authored-By: da-x <alonid@gmail.com>
Update text/0000-named-custom-cargo-profiles.md
Co-Authored-By: da-x <alonid@gmail.com>
Update text/0000-named-custom-cargo-profiles.md
Co-Authored-By: da-x <alonid@gmail.com>
@kornelski

This comment has been minimized.

Copy link
Contributor

commented Apr 10, 2019

Is it worthwhile keeping test and bench outputs in target/debug and target/release?

It's very helpful to be able to run test binary under gdb, or the bench binary under a profiler. These have unpredictable paths already, so a different location would be fine, but they should be persisted in an accessible location.

@kornelski

This comment has been minimized.

Copy link
Contributor

commented Apr 10, 2019

The RFC doesn't mention cross-compilation. Cargo changes target/release to target/<platform triple>/release when cross-compiling. Presumably dir-name would be too?

@crlf0710

This comment has been minimized.

Copy link

commented Apr 10, 2019

Might be orthogonal, but many times i really wished that there's a profile that build the current crate in dev mode but all its dependencies in release mode.

@kornelski

This comment has been minimized.

Copy link
Contributor

commented Apr 10, 2019

Yes, a different profile for the workspace and dependencies outside of the workspace would be fantastic.

@ssokolow

This comment has been minimized.

Copy link

commented Apr 10, 2019

I definitely want something iike this. The "Direct cargo build flags alternative" option wouldn't really change the status quo for me.

The justfile in my project boilerplate already works around the lack of this functionality by using custom CARGO_TARGET_DIR values to simulate it in tasks like kcov.

The downside is that, due to that and my justfile forcing CARGO_BUILD_TARGET to always have a value for the sake of consistency, I treat invoking cargo subcommands directly as unsupported, purely because the odds are high that they'll act as if I'd just run cargo clean.

Another former downside that wasn't specifically due to the lack of custom profiles (rather, it was about opt-level = "z" only being valid in nightly builds, which could have been remedied by defining a release-nightly profile), but which shows how far I'm willing to go, was how hacky it was for my justfile to use sed to rewrite and then restore the [profile.release] section of my Cargo.toml as part of the build process under certain conditions.

(On the plus side, cargo-make's @rust script runner should make it more robust to pull that trick, since I could use toml_edit for my crazy hacks.)

The dev profile receives the dir-name = "debug" attribute, so that its final outputs are emitted to target/debug, as existing Rust developers will expect this behavior. This should be added in the official documentation for the Cargo manifest, to make this fact clearer for users.

A debug profile name is not allowed, with a warning saying to use the already established dev name.

Why is it so important for the profile to be named dev that it justifies this special-casing, this hard-coded exception to letting projects define their own profile names, and this potential point of confusion?

I couldn't find a justification for that.

Do we really need pre-defined profiles for test, bench and/or doc, or can we make them obsolete?

Assuming we take it as a given that we're not going to accept the convenience regression of requiring users to do some setup before they can run cargo test and/or cargo doc, can you elaborate on what the alternative would look like?

@da-x

This comment has been minimized.

Copy link
Member Author

commented Apr 10, 2019

@ssokolow:

Why is it so important for the profile to be named dev that it justifies this special-casing, this hard-coded exception to letting projects define their own profile names, and this potential point of confusion?

I couldn't find a justification for that

The main issue is backward compatibility. If the alternative is to abolish the dev profile name in favor of the debug name, it would break existing projects' assumptions about the affects of the [profile.dev] clauses to the cargo build command (without any --profile parameter). Another alternative, is to emit to a target/dev directory instead of target/debug directory, but that would break current assumptions about the default cargo build output directories. Now, if we take neither of the aforementioned alternatives and we allow for a debug profile to be defined, then unwary people may expect the default cargo build command (i.e. without any --profile parameter) to be affected by it, and be surprised when it isn't. This is the problem I've had in mind. Perhaps someone can think of a better solution.

Assuming we take it as a given that we're not going to accept the convenience regression of requiring users to do some setup before they can run cargo test and/or cargo doc, can you elaborate on what the alternative would look like?

The alternative would be for bench to use the release profile (unless --profile is specified), and for doc and test to use dev (unless --profile is specified), and to remove these predefined profiles from code and documentation.

@da-x

This comment has been minimized.

Copy link
Member Author

commented Apr 10, 2019

The RFC doesn't mention cross-compilation. Cargo changes target/release to target/<platform triple>/release when cross-compiling. Presumably dir-name would be too?

Yes, that would be the expected behavior. Should update the RFC.

@da-x

This comment has been minimized.

Copy link
Member Author

commented Apr 10, 2019

Might be orthogonal, but many times i really wished that there's a profile that build the current crate in dev mode but all its dependencies in release mode.

@crlf0710 @kornelski I think this is achievable with profiles overrides (currently in nightly cargo).

Combined with this RFC's changes, it would be even better, because you could have these overrides under a custom profile, retaining the standard functionality with the dev profile.

For example:

[profile.dev-deps-release]
inherits = "release"
[profile.dev-deps-release.overrides."*"]
opt-level = 2

(See Unstable Features - The Cargo Book)

@ssokolow

This comment has been minimized.

Copy link

commented Apr 10, 2019

The main issue is backward compatibility. If the alternative is to abolish the dev profile name in favor of the debug name, it would break existing projects' assumptions about the affects of the [profile.dev] clauses to the cargo build command (without any --profile parameter). Another alternative, is to emit to a target/dev directory instead of target/debug directory, but that would break current assumptions about the default cargo build output directories.

Ahh, yes. I'd forgotten about that existing mismatch. Hazard of putting together a project template once and then not needing to modify it much, I guess.

@kornelski

This comment has been minimized.

Copy link
Contributor

commented Apr 11, 2019

Maybe dev profile name could be used only as a fallback? If there's profiles.debug in Cargo.toml, then use that. Otherwise try profiles.dev. That would keep backwards compatibility, and allow eventually deprecating and removing the dev name.

It's for development only, so it doesn't affect crate users, and the developer will see any deprecation notices.

@da-x

This comment has been minimized.

Copy link
Member Author

commented Apr 11, 2019

Maybe dev profile name could be used only as a fallback? If there's profiles.debug in Cargo.toml, then use that. Otherwise try profiles.dev. That would keep backwards compatibility, and allow eventually deprecating and removing the dev name.

It's for development only, so it doesn't affect crate users, and the developer will see any deprecation notices.

So the suggestion as I understand - having a debug profile defined will affect the default cargo build, cargo test, and cargo doc profile to be debug instead of dev. We can limit the emission of the warning to the case where there are customization on the dev profile.

However I am not sure it puts the dev profile on a full deprecation path, at least not during 1.x Rust, because the Cargo.toml of many old crates will probably still remain without a debug profile defined, and with dev customized.

This may be a good, but I'd feel better with more votes on the matter. Pinging @ehuss @matklad @Manishearth.

@Manishearth

This comment has been minimized.

Copy link
Member

commented Apr 13, 2019

(I'm not really a cargo person, and while I've written a profile RFC before I don't have strong opinions on this. I recall the cargo team having plans about profiles, though)

@ehuss
Copy link
Contributor

left a comment

Thank you for putting this together!

Some questions/comments:

  • What happens if the user specifies --release --profile=foo?
  • Is --release an alias for --profile=release?
  • Currently the profile is driven by the command, cargo target (--test uses test, --bench uses bench, --all-targets uses a mixture, etc.), and the --release flag. Does Cargo continue to behave that way if no profile is chosen? I'm concerned that is a little confusing, but the alternative (only using one profile) would also be problematic.
  • doc is currently unused, and I think has some issues that would prevent it from being reintroduced. I would prefer to leave out doc in the discussion here and leave it for future consideration.
  • There should be restrictions on valid profile names. I'm thinking the same as a package name (validate_package_name) would be a good start, though maybe it should be even more restrictive?
  • Can you add a link to the PR description to https://internals.rust-lang.org/t/strawman-pre-rfc-custom-profiles/6412 which had a very similar proposal?
  • Does cargo test --profile=foo build all crates with the foo profile? Currently cargo test is a little strange in that dependencies are built with dev/release. I'm thinking this might be a good opportunity to change that, so that test/bench are less special. The drawback is that it takes longer to compile if you change the test profile (since it can't share dependencies with dev), but it may be worthwhile.
Show resolved Hide resolved text/0000-named-custom-cargo-profiles.md Outdated
Show resolved Hide resolved text/0000-named-custom-cargo-profiles.md Outdated
Show resolved Hide resolved text/0000-named-custom-cargo-profiles.md Outdated
Show resolved Hide resolved text/0000-named-custom-cargo-profiles.md Outdated
Show resolved Hide resolved text/0000-named-custom-cargo-profiles.md Outdated

Finished release-lto [optimized + lto] target(s) in 3.83s

* As before, optimization mode is always printed, with `optimized` if

This comment has been minimized.

Copy link
@ehuss

ehuss Apr 13, 2019

Contributor

The problem with the Finished line is that multiple profiles may be used during a single command. For example, cargo build --all-targets can use both dev and test. I think this will need more consideration to figure out the best way to present a final summary.

FWIW, I don't mind that it is slightly incorrect now, so I don't think it is critical to fix this. But it should be fixed at some point, so it would be good to hear if anyone has any ideas on how to fix it.

This comment has been minimized.

Copy link
@da-x

da-x Apr 14, 2019

Author Member

Based on more feedback from more users, we may leave it out from the RFC or move it to the 'future possibilities' section (makes sense?). Maybe a good solution would come out of trying to implement a better Finished line while working to implement this RFC.

This comment has been minimized.

Copy link
@da-x

da-x Apr 14, 2019

Author Member

Also, do think it would be realistic to print a Finished line per target, with the profiles that used to build it?

This comment has been minimized.

Copy link
@ehuss

ehuss Apr 21, 2019

Contributor

I'm fine with deferring the details here. I'm not sure if printing multiple lines would be desirable. Perhaps after it's implemented we could experiment with a few different examples and come up with something people can look at.

* Similarly, `TomlProfiles` will be changed to hold profiles in a `BTreeMap`.
* We would need to compute the actual `build_override` for a profile based on
resolution through the `inherited` key.
* Custom build scripts: For compatibility, the `PROFILE` environment currently

This comment has been minimized.

Copy link
@ehuss

ehuss Apr 13, 2019

Contributor

I'm not sure about this change. Why the output directory and not the profile name? Some build scripts use it for accessing the output directory, but in general they shouldn't be.

Also, build scripts today only expect two values ("release" and "debug") and typically use that to determine how to compile other code. They will have no knowledge of any other profile name (especially within dependencies which are from other projects). I'm not sure we can change this behavior. No matter what is done here, I think it will break some projects.

I'm wondering if it might be best to deprecate "PROFILE", and build scripts should use "DEBUG" and "OPT_LEVEL" for determining build settings. I don't think they should be writing to the target directory. It could keep some sort of "best guess" to set it to "debug" or "release".

This comment has been minimized.

Copy link
@da-x

da-x Apr 14, 2019

Author Member

So it would be ok, to have it debug or release depending on the inherited-from profile being used?

This comment has been minimized.

Copy link
@ehuss

ehuss Apr 21, 2019

Contributor

I think so?

Show resolved Hide resolved text/0000-named-custom-cargo-profiles.md Outdated
Show resolved Hide resolved text/0000-named-custom-cargo-profiles.md
Show resolved Hide resolved text/0000-named-custom-cargo-profiles.md Outdated

ehuss and others added some commits Apr 14, 2019

Update text/0000-named-custom-cargo-profiles.md
Co-Authored-By: da-x <alonid@gmail.com>
Update text/0000-named-custom-cargo-profiles.md
Co-Authored-By: da-x <alonid@gmail.com>
Update text/0000-named-custom-cargo-profiles.md
Co-Authored-By: da-x <alonid@gmail.com>
Update text/0000-named-custom-cargo-profiles.md
Co-Authored-By: da-x <alonid@gmail.com>
Update text/0000-named-custom-cargo-profiles.md
Co-Authored-By: da-x <alonid@gmail.com>
Update text/0000-named-custom-cargo-profiles.md
Co-Authored-By: da-x <alonid@gmail.com>
@da-x

This comment has been minimized.

Copy link
Member Author

commented Apr 14, 2019

@ehuss, thanks for investing the time to review!

  • What happens if the user specifies --release --profile=foo?
  • Is --release an alias for --profile=release?

I'd suggest the following:

  • Using --profile and --release together will emit an error unless --profile=release.
  • Using --release on its own will be equivalent to specifying --profile=release
  • Currently the profile is driven by the command, cargo target (--test uses test, --bench uses bench, --all-targets uses a mixture, etc.), and the --release flag. Does Cargo continue to behave that way if no profile is chosen? I'm concerned that is a little confusing, but the alternative (only using one profile) would also be problematic.

Yes. I think it would be too late to deprecate this functionality.

  • doc is currently unused, and I think has some issues that would prevent it from being reintroduced. I would prefer to leave out doc in the discussion here and leave it for future consideration.

Agreed.

  • There should be restrictions on valid profile names. I'm thinking the same as a package name (validate_package_name) would be a good start, though maybe it should be even more restrictive?

Yes, let's take the restriction from package names: Name must not be empty, use only alphanumeric characters or - or _.

Was not aware of it. Sure.

  • Does cargo test --profile=foo build all crates with the foo profile? Currently cargo test is a little strange in that dependencies are built with dev/release. I'm thinking this might be a good opportunity to change that, so that test/bench are less special. The drawback is that it takes longer to compile if you change the test profile (since it can't share dependencies with dev), but it may be worthwhile.

It's very good that you brought this up. If I understood correctly, only the special test crate is built with the test profile all the dependencies including the current crate are built with either dev or release, depending on whether --release is provided (this includes both dependencies and dev-dependencies). This is what the Cargo docs say:

# The release profile, used for `cargo build --release` (and the dependencies
# for `cargo test --release`, including the local library or binary).

The existing functionality has the advantage that in cargo test --release the a test crate code which makes heavy use of dependencies for testing runs fast due to the optimized dependencies, while the test crate itself is still in debug mode, having more checks and emitting full backtraces for itself. Do we want to regress on this behavior? It may depends on how much logic people put inside their test crates, and we may need more data or user feedback for deciding.

Update text/0000-named-custom-cargo-profiles.md
Co-Authored-By: da-x <alonid@gmail.com>

ehuss and others added some commits Apr 14, 2019

Update text/0000-named-custom-cargo-profiles.md
Co-Authored-By: da-x <alonid@gmail.com>
Update text/0000-named-custom-cargo-profiles.md
Co-Authored-By: da-x <alonid@gmail.com>
Update text/0000-named-custom-cargo-profiles.md
Co-Authored-By: da-x <alonid@gmail.com>
Update text/0000-named-custom-cargo-profiles.md
Co-Authored-By: da-x <alonid@gmail.com>
@ehuss

This comment has been minimized.

Copy link
Contributor

commented Apr 21, 2019

Do we want to regress on this behavior? It may depends on how much logic people put inside their test crates, and we may need more data or user feedback for deciding.

I'm not sure. I'll ask the team if there's any opinion on this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.