Skip to content

Commit 55bc7db

Browse files
committed
Initial RFC for custom cargo profiles
1 parent b9b71bb commit 55bc7db

File tree

1 file changed

+143
-0
lines changed

1 file changed

+143
-0
lines changed

text/0000-custom-cargo-profiles.md

+143
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
- Feature Name: custom_cargo_profiles
2+
- Start Date: (fill me in with today's date, 2018-01-08)
3+
- RFC PR: (leave this empty)
4+
- Rust Issue: (leave this empty)
5+
6+
7+
# Summary
8+
[summary]: #summary
9+
10+
Add the ability to create custom profiles in Cargo.toml, to provide further control over how the project is built. Allow overriding profile keys for certain dependency trees.
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. There are
20+
currently two main profiles in Cargo ("dev" and "release"), and we're forced to fit everything we
21+
need into these two categories. This isn't really enough.
22+
23+
Furthermore, this doesn't allow for much customization. For example, when trying to optimize for
24+
compilation speed by building in debug mode, build scripts will get built in debug mode as well. In
25+
case of complex build-time dependencies like bindgen, this can end up significantly slowing down
26+
compilation. It would be nice to be able to say "build in debug mode, but build build dependencies
27+
in release". Also, your program may have large dependencies that it doesn't use in critical paths,
28+
being able to ask for just these dependencies to be run in debug mode would be nice.
29+
30+
# Guide-level explanation
31+
[guide-level-explanation]: #guide-level-explanation
32+
33+
34+
Currently, the [Cargo guide has a section on this](http://doc.crates.io/manifest.html#the-profile-sections).
35+
36+
We amend this to add that you can define custom profiles with the `profile.foo` key syntax. These can be invoked via
37+
`cargo build --profile foo`. The `dev`/`doc`/`bench`/etc profiles remain special. Each custom profile, aside from the
38+
"special" ones, gets a folder in `target/`, named after the profile. "dev" and "debug" are considered to be aliases
39+
40+
Profile keys can be "overridden":
41+
42+
```toml
43+
[profile.dev]
44+
opt-level = 0
45+
debug = true
46+
47+
# the `image` crate will be compiled with -Copt-level=3
48+
[profile.dev.overrides.image]
49+
opt-level = 3
50+
51+
# Dependencies semver-matching any entry in the space separated list
52+
# will be compiled without debuginfo
53+
[profile.dev.overrides."image=0.2 piston>5.0"]
54+
debug=false
55+
56+
# All dependencies (but not this crate itself) will be compiled
57+
# with -Copt-level=2 . This includes build dependencies.
58+
[profile.dev.overrides."*"]
59+
opt-level = 2
60+
61+
# Build scripts and their dependencies will be compiled with -Copt-level=3
62+
# By default, build scripts use the same rules as the rest of the profile
63+
[profile.dev.build_override]
64+
opt-level = 3
65+
```
66+
67+
Custom profiles _can_ be listed in a `.cargo/config`, however the user is responsible for
68+
clearing up build directories if the profile changes. That is, it is undefined behavior
69+
to run `cargo build --profile foo` if `foo` has been defined in `.cargo/config` and the
70+
profile has been edited since the last time you ran `cargo build --profile foo`.
71+
72+
# Reference-level explanation
73+
[reference-level-explanation]: #reference-level-explanation
74+
75+
In case of overlapping rules, the last mentioned rule will be applied. This applies to build scripts
76+
as well; if, for example, you have the following profile:
77+
78+
```toml
79+
[profile.dev]
80+
opt-level = 0
81+
[profile.dev.build_override]
82+
opt-level = 3
83+
```
84+
85+
and the `image` crate is _both_ a build dependency and a regular dependency; it will be compiled
86+
as per the `build_override` rule. If you wish it to be compiled as per the original rule,
87+
use a normal override rule:
88+
89+
```toml
90+
[profile.dev]
91+
opt-level = 0
92+
[profile.dev.build_override]
93+
opt-level = 3
94+
[profile.dev.overrides.image]
95+
opt-level = 0
96+
```
97+
98+
It is not possible to have the same crate compiled in different modes as a build dependency and a regular dependency within the same profile.
99+
100+
101+
`build_override` is itself
102+
103+
`cargo build --target foo` will fail to run if `foo` clashes with the name of a profile; so avoid
104+
giving profiles the same name as possible build targets.
105+
106+
107+
# Drawbacks
108+
[drawbacks]: #drawbacks
109+
110+
This complicates cargo.
111+
112+
# Rationale and alternatives
113+
[alternatives]: #alternatives
114+
115+
There are really two or three concerns here:
116+
117+
- 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)
118+
- 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)
119+
- The ability to use a different profile for specific dependencies
120+
121+
The first one can be resolved partially by stabilizing `cargo` arguments for overriding these. It
122+
doesn't fix the target directory issue, but that might not be a major concern. Allowing profiles to
123+
come from `.cargo/config` is another minimal solution to this for use cases like Firefox, which
124+
wraps Cargo in another build system.
125+
126+
The second one can be fixed with a specific `build-scripts = release` key for profiles.
127+
128+
The third can't be as easily fixed, however it's not clear if that's a major need.
129+
130+
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.
131+
132+
In general there are plans for Cargo to support other build systems by making it more modular (so
133+
that you can ask it for a build plan and then execute it yourself). Such build systems would be able to
134+
provide the ability to override profiles themselves instead. It's unclear if the general Rust
135+
community needs the ability to override profiles.
136+
137+
# Unresolved questions
138+
[unresolved]: #unresolved-questions
139+
140+
- Bikeshedding the naming of the keys
141+
- The priority order when doing resolution
142+
- Should `build_override` itself take an `overrides.foo` key?
143+
- The current proposal provides a way to say "special-case all build dependencies, even if they are regular dependencies as well", but not "special-case all build-only dependencies" (which can be solved with a `!build_override` thing, but that's weird and unweildy)

0 commit comments

Comments
 (0)