|
| 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