Description
While taking to @dtolnay about #928, we realized that release mode procedural macros are rebuilding dependencies (and may always have been). They had this as a suggestion:
The goal is to get
cargo build --release
whenproc-macro = true
to reuse artifacts that got built previously whencargo build
andcargo build --release
were previously run with proc-macro set to false.The artifacts that got built previously are:
- everything in dev mode:
opt-level = 0
anddebug = true
- everything in release mode:
opt-level = 3
anddebug = false
This means
[profile.release.build-override] debug = true
is not the right thing because that's gonna make cargo look for artifacts withopt-level = 3
anddebug = true
, which is not something that got built previously.The simplest fix is to make release proc-macros reuse artifacts from the release non-macro build, by doing this:
[profile.release.build-override] codegen-units = 1 opt-level = 3I confirmed that fixes the issue. However that is not my preferred fix because that slows down your up-front
cargo build --release
invocation; it will spend more time compiling things like serde_derive than it used to, and there is no benefit to users from having the macros be optimized.Sadly you can't make release proc-macros reuse artifacts from the dev non-macro build. Naively you might try:
[profile.release.build-override] codegen-units = 1 debug = true debug-assertions = true opt-level = 0 overflow-checks = truewhich makes the entire profile line up correctly with what was previously built by
cargo build
. Yet Cargo will still not reuse the existing artifacts only because it wants--release
artifacts to go undertarget/release/
, and the existing ones were put undertarget/debug/
, and instead of saying "oh I have these already in the other directory, let me copy them" it will just rebuild the same artifacts in the new location.But here is my preferred fix:
[profile.playground] inherits = "dev" # mutates to "release" codegen-units = 1 incremental = false [profile.playground.build-override] codegen-units = 1 opt-level = 0 debug = true debug-assertions = true overflow-checks = trueNow instead of
cargo build
+cargo build --release
, your container will instead runcargo build --profile=playground
twice, changing the "inherits" value in between. And the Debug/Release dropdown will set the same "inherits" value instead of a--release
argument.This speeds up your docker build compared to before, because the second
cargo build --profile=playground
will be faster than the currentcargo build --release
. You'll be building a total of 1 copy of serde_derive etc, instead of 2 separate copies. Your image will also be smaller.On my machine, building your current Cargo.toml from the main branch produces a target directory that is 2.8 GB, whereas building my suggested fix produces 2.3 GB, which is 16.2% smaller