Repository navigation
fix(cargo-oxide): pin release-like codegen in Cargo profiles - #1510
Conversation
…rustflags
Release-like routes (`build`, `run`, `debug`, interop, passthrough `build`)
appended `-Copt-level=3 -Cdebug-assertions=off` (plus overflow-checks /
debuginfo variants) to CARGO_ENCODED_RUSTFLAGS, while `test` leaves the
profile alone. The values equal the release defaults, but different rustflags
change every crate's fingerprint: `cargo oxide test -- --release` followed by
`cargo oxide build` recompiled the whole dependency graph (~680 crates for one
application) and CI caches held two copies of everything.
`CodegenProfilePolicy::pinned_options` is now the single list of pins. They
are set as `CARGO_PROFILE_{RELEASE,DEV,<--profile>}_*`; Cargo fingerprints
resolved profile values, so build and test share every artifact. A pinned
`-C` flag is still appended after incoming rustflags that set the same option
(including `-O`, `-g` and `_` spellings), so the pin keeps winning. Every
release-like policy now pins `overflow-checks = off` explicitly: a passthrough
build without `--release` runs the dev profile, whose overflow-checks default
is on. `cargo oxide debug`'s manual CARGO_PROFILE_RELEASE_DEBUG moved into the
same list. `[profile.*.package.*]` overrides and `--config profile.*` outrank
the environment; the README says so.
Signed-off-by: Alex Khal <joss13@gmail.com>
Signed-off-by: ssoj13 <96214515+ssoj13@users.noreply.github.com>
A `--profile` other than `release` or `dev` received its pins through `CARGO_PROFILE_<NAME>_*`. For a dashed name such as `release-lto` Cargo reads that key as `profile.release.lto` and stops before compiling, so a build that worked through rustflags became a hard error. The environment now carries the pins for the two base profiles only, and a selected custom profile receives them as `--config profile.<name>.<key>=<value>` arguments placed right after the subcommand. Cargo compares the resolved values, so a build and a test under the same custom profile keep sharing artifacts, and a later user `--config` for the same key still wins. PinnedOption stores the manifest key and derives the environment key the way Cargo does. Unit tests cover both `--profile` forms, the base profiles, the test route, the debug-assertions policy and a name Cargo would reject. Signed-off-by: nihalpasham <nihalp@nvidia.com>
Extend the freshness probe to take the passthrough subcommand and extra Cargo arguments, and key a test harness apart from the library it is built from. Two probes drive real Cargo on a scratch workspace: a release build followed by `test --release` reuses the shared dependency, and a dashed custom profile that sets `opt-level = 1` and overflow checks builds in both `--profile` forms with the pins in force. Through rustflags the first probe recompiled the dependency. At the previous head the second stopped on the rejected environment key, and without the explicit overflow-checks pin the binary trapped. Signed-off-by: nihalpasham <nihalp@nvidia.com>
Name the environment carrier for `release` and `dev` and the `--config` carrier for a selected `--profile`. Scope the trailing `-C` re-pin to RUSTFLAGS, CARGO_ENCODED_RUSTFLAGS and `extra-rustflags`, and list manifest profile rustflags next to the package overrides and `--config` arguments that outrank the pins. The `cargo oxide pipeline` hint now lists `overflow-checks=off`, and the run hint mentions the `--config` carrier. Signed-off-by: nihalpasham <nihalp@nvidia.com>
|
Thanks for this, the fix is right and it is going in. One snag: your fork is a fork of ansidium/cuda-rust-windows, not of NVIDIA/cuda-rust, so "allow edits from maintainers" gives push rights to ansidium, not to us, and I could not push my follow-ups onto your branch. I reviewed and validated this on the 5090 and added the follow-ups on top of your commit, on branch |
|
Thanks @nihalpasham! Since GitHub only permits one fork per repository network ( |
|
/ok to test 90883b8 |
|
Good catch, this one annoyed me too, and thanks for carrying the branch over. Landed with a few follow-ups:
On the 5090 the switch from |
What this adds
Release-like
cargo oxideroutes used to forceopt-level=3,debug-assertions=offand (with--debug-assertions)overflow-checks=offthroughCARGO_ENCODED_RUSTFLAGS. Cargo hashes rustflags into every crate's fingerprint, whilecargo oxide test -- --releaseadded none, so the first switch between build and test in each direction rebuilt the whole dependency graph and left two copies of every artifact. The pins now travel in the Cargo profile (CARGO_PROFILE_RELEASE_*,CARGO_PROFILE_DEV_*, and--config profile.<name>.*for a selected custom profile), which Cargo compares by value, so both commands share every compiled crate.What we fixed
test -- --releasepassthrough commands hand rustc the sameCARGO_ENCODED_RUSTFLAGS; the pins move to Cargo profile settings at the single site every release-like route uses (example build/run/pipeline/debug, emit-ltoir, tilelib, interop device crates, sanitize host binary, passthrough build).overflow-checks=offis pinned explicitly in every release-like policy. On main only the--debug-assertionspolicy set it, so an incoming-C overflow-checks=onor[profile.release] overflow-checks = truereached device code, and a kernel with a reachable overflow trapped at runtime.-Cpin is still appended after incoming rustflags that set the same option (-C x,-Cx,--codegen,-O,-g, underscore forms), so those still lose to the pin.--profilesuch asrelease-ltono longer producesCARGO_PROFILE_RELEASE_LTO_*, which Cargo parsed asprofile.release.ltoand rejected before compiling; custom profiles receive the pins as--configarguments.cargo oxide debuggetsdebug = 2from the same pinned list instead of a hand-set environment variable; thecargo oxide pipelinehint lists all three pinned settings.Contract
[profile.*.package.*]overrides,--config profile.*and manifest[profile.*.rustflags]/[profile.*.package.*.rustflags]outrank them; the trailing-Cre-pin covers RUSTFLAGS,CARGO_ENCODED_RUSTFLAGSandextra-rustflagsonly.cargo oxide testleaves the selected Cargo profile alone, as before.build-overridesettings instead of the old-Copt-level=3.Implementation
CodegenProfilePolicy::pinned_optionsis the one list of pins; eachPinnedOptionpairs the rustc-Coption with its Cargo manifest key and value, and derives the environment key by Cargo's uppercase-and-underscore rule.apply_profile_pinssetsCARGO_PROFILE_RELEASE_*andCARGO_PROFILE_DEV_*;cargo_passthrough_commandadds--config profile.<name>.<key>=<value>right after the subcommand when--profilenames a profile other thanreleaseordev, before the user arguments, so a later user--configstill wins.passthrough.rscarries the--configpins for a selected custom profile;codegen_option_namesrecognises every rustc form of a codegen option;build_encoded_rustflags_with_existingappends a pin flag only for options the incoming flags set, after-Zcodegen-backendand before the-Zinvariants.Verification
Checked at
90883b87amerged with main5b606fddd(nightly-2026-10-11, RTX 5090, CUDA 13.4):cargo test -p cargo-oxide --all-targets: 268 passed, the two real-Cargo probes among them (build, test, build reuses the shared dependency; a dashed custom profile builds with the pins in force). Clippy and rustdoc with-D warnings,cargo oxide fmt --check, the lock check and the 18 guards pass. All 54 CI checks pass on the PR; they ran on90883b87amerged with main82f195bea, and the merge with5b606fdddis the local run above.cargo oxide run vecaddpasses and its PTX is byte-identical to main's, from the PR's pipeline and from main's own cargo-oxide; the passthrough build at sm_80 is byte-identical as well.cargo oxide test -- --releasefollowed bycargo oxide build -- --releaserecompiles only the application crate (1 of 72); on main the same sequence recompiles all 72.cargo oxide build -- --profile release-ltoon a copy of vecadd withopt-level = 1in that profile builds with-C opt-level=3in force; the author's head carried the pins asCARGO_PROFILE_RELEASE_LTO_*, which Cargo rejects before compiling (error in environment variable CARGO_PROFILE_RELEASE: could not load config key profile.release, exit 101, reproduced with plain Cargo on nightly-2026-10-11). compute-sanitizer memcheck on the release and release-lto binaries: 0 errors.cargo oxide pipeline vecaddprints the three pinned settings.Caveats
opt-level = 3through a package override,--config profile.*or manifest profile rustflags gets no diagnostic yet; a backend-side check is a follow-up.opt-level = 0instead of 3; device code is unaffected.-Copt-level=3in RUSTFLAGS still gets a trailing re-pin on build but not on test, so those two stop sharing; cache efficiency only.--configcarrier; it keeps only the base pins it inherits.just checkfigures come from the port PR on WSL2, not from this branch; here the examples-compile workflow and the stacked GPU smoketest cover it.Port of ansidium#12.
Closes #1508.