rust-playground
rust-playground copied to clipboard
Procedural macros in release mode rebuild all dependencies
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 --releasewhenproc-macro = trueto reuse artifacts that got built previously whencargo buildandcargo build --releasewere previously run with proc-macro set to false.The artifacts that got built previously are:
- everything in dev mode:
opt-level = 0anddebug = true- everything in release mode:
opt-level = 3anddebug = falseThis means
[profile.release.build-override] debug = trueis not the right thing because that's gonna make cargo look for artifacts withopt-level = 3anddebug = 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 --releaseinvocation; 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--releaseartifacts 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=playgroundtwice, changing the "inherits" value in between. And the Debug/Release dropdown will set the same "inherits" value instead of a--releaseargument.This speeds up your docker build compared to before, because the second
cargo build --profile=playgroundwill 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