Skip to content

Commit 9cd6ae9

Browse files
authored
Merge pull request #2282 from Manishearth/custom-profiles
Cargo profile dependencies
2 parents 49eea1f + a52f15b commit 9cd6ae9

File tree

1 file changed

+146
-0
lines changed

1 file changed

+146
-0
lines changed

text/2282-profile-dependencies.md

+146
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
- Feature Name: profile_dependencies
2+
- Start Date: 2018-01-08
3+
- RFC PR: [rust-lang/rfcs#2282](https://github.com/rust-lang/rfcs/pull/2282)
4+
- Rust Issue: [rust-lang/rust#48683](https://github.com/rust-lang/rust/issues/48683)
5+
6+
7+
# Summary
8+
[summary]: #summary
9+
10+
Allow overriding profile keys for certain dependencies, as well as providing a way to set profiles in `.cargo/config`
11+
12+
# Motivation
13+
[motivation]: #motivation
14+
15+
Currently the "stable" way to tweak build parameters like "debug symbols", "debug assertions", and "optimization level" is to edit Cargo.toml.
16+
17+
This file is typically checked in tree, so for many projects overriding things involves making
18+
temporary changes to this, which feels hacky. On top of this, if Cargo is being called by an
19+
encompassing build system as what happens in Firefox, these changes can seem surprising.
20+
21+
This also doesn't allow for much customization. For example, when trying to optimize for
22+
compilation speed by building in debug mode, build scripts will get built in debug mode as well. In
23+
case of complex build-time dependencies like bindgen, this can end up significantly slowing down
24+
compilation. It would be nice to be able to say "build in debug mode, but build build dependencies
25+
in release". Also, your program may have large dependencies that it doesn't use in critical paths,
26+
being able to ask for just these dependencies to be run in debug mode would be nice.
27+
28+
29+
# Guide-level explanation
30+
[guide-level-explanation]: #guide-level-explanation
31+
32+
33+
Currently, the [Cargo guide has a section on this](http://doc.crates.io/manifest.html#the-profile-sections).
34+
35+
We amend this to add that you can override dependency configurations via `profile.foo.overrides`:
36+
37+
```toml
38+
[profile.dev]
39+
opt-level = 0
40+
debug = true
41+
42+
# the `image` crate will be compiled with -Copt-level=3
43+
[profile.dev.overrides.image]
44+
opt-level = 3
45+
46+
# All dependencies (but not this crate itself) will be compiled
47+
# with -Copt-level=2 . This includes build dependencies.
48+
[profile.dev.overrides."*"]
49+
opt-level = 2
50+
51+
# Build scripts and their dependencies will be compiled with -Copt-level=3
52+
# By default, build scripts use the same rules as the rest of the profile
53+
[profile.dev.build_override]
54+
opt-level = 3
55+
```
56+
57+
Additionally, profiles may be listed in `.cargo/config`. When building, cargo will calculate the
58+
current profile, and if it has changed, it will do a fresh/clean build.
59+
60+
# Reference-level explanation
61+
[reference-level-explanation]: #reference-level-explanation
62+
63+
In case of overlapping rules, the precedence order is that `overrides.foo`
64+
will win over `overrides."*"` and both will win over `build_override`.
65+
66+
So if you specify `build_override`
67+
it will not affect the compilation of any dependencies which are both
68+
build-dependencies and regular dependencies. If you have
69+
70+
```toml
71+
[profile.dev]
72+
opt-level = 0
73+
[profile.dev.build_override]
74+
opt-level = 3
75+
```
76+
77+
and the `image` crate is _both_ a build dependency and a regular dependency; it will be compiled
78+
as per the top level `opt-level=0` rule. If you wish it to be compiled as per the build_override rule,
79+
use a normal override rule:
80+
81+
```toml
82+
[profile.dev]
83+
opt-level = 0
84+
[profile.dev.build_override]
85+
opt-level = 3
86+
[profile.dev.overrides.image]
87+
opt-level = 3
88+
```
89+
90+
This clash may not occur whilst cross compiling since two separate versions of the crate will be compiled.
91+
(This RFC leaves the decision of whether or not to handle this up to the implementors)
92+
93+
It is not possible to have the same crate compiled in different modes as a build dependency and a
94+
regular dependency within the same profile when not cross compiling. (This is a current limitation
95+
in Cargo, but it would be nice if we could fix this)
96+
97+
Put succinctly, `build_override` is not able to affect anything compiled into the final binary.
98+
99+
`cargo build --target foo` will fail to run if `foo` clashes with the name of a profile; so avoid
100+
giving profiles the same name as possible build targets.
101+
102+
When in a workspace, `"*"` will apply to all dependencies that are _not_ workspace members, you can explicitly
103+
apply things to workspace members with `[profile.dev.overrides.membername]`.
104+
105+
The `panic` key cannot be specified in an override; only in the top level of a profile. Rust does not allow
106+
the linking together of crates with different `panic` settings.
107+
108+
# Drawbacks
109+
[drawbacks]: #drawbacks
110+
111+
This complicates cargo.
112+
113+
# Rationale and alternatives
114+
[alternatives]: #alternatives
115+
116+
There are really two or three concerns here:
117+
118+
- A stable interface for setting various profile keys (`cargo rustc -- -Clto` is not good, for example, and doesn't integrate into Cargo's target directories)
119+
- The ability to use a different profile for build scripts (usually, the ability to flip optimization modes; I don't think folks care as much about `-g` in build scripts)
120+
- The ability to use a different profile for specific dependencies
121+
122+
The first one can be resolved partially by stabilizing `cargo` arguments for overriding these. It
123+
doesn't fix the target directory issue, but that might not be a major concern. Allowing profiles to
124+
come from `.cargo/config` is another minimal solution to this for use cases like Firefox, which
125+
wraps Cargo in another build system.
126+
127+
The second one can be fixed with a specific `build-scripts = release` key for profiles.
128+
129+
The third can't be as easily fixed, however it's not clear if that's a major need.
130+
131+
The nice thing about this proposal is that it is able to handle all three of these concerns. However, separate RFCs for separate features could be introduced as well.
132+
133+
In general there are plans for Cargo to support other build systems by making it more modular (so
134+
that you can ask it for a build plan and then execute it yourself). Such build systems would be able to
135+
provide the ability to override profiles themselves instead. It's unclear if the general Rust
136+
community needs the ability to override profiles.
137+
138+
# Unresolved questions
139+
[unresolved]: #unresolved-questions
140+
141+
- Bikeshedding the naming of the keys
142+
- The current proposal provides a way to say "special-case all build dependencies, even if they are regular dependencies as well",
143+
but not "special-case all build-only dependencies" (which can be solved with a `!build_override` thing, but that's weird and unweildy)
144+
- It would be nice to have a way for crates to _declare_ that they use a particular
145+
panic mode (something like `allow-panic=all` vs `allow-panic=abort`/`allow_panic=unwind`, with `all` as default)
146+
so that they can assume a panic mode and cargo will refuse to compile them with anything else

0 commit comments

Comments
 (0)