cargo
cargo copied to clipboard
Tracking Issue for profile-rustflags
Summary
Original issue: #7878 Implementation: #10217 Documentation: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#profile-rustflags-option
The profile-rustflags
feature allows setting RUSTFLAGS per-profile.
Unresolved Issues
- [ ] How should things interact with rustdoc? If there is a flag that is required to correctly build a project, then
cargo test
may fail if they aren't passed to rustdoc. However, rustdoc doesn't accept all of rustc's flags. Adding arustdocflags
option seems to be adding more unwanted complexity, though. - [ ] This introduces potential backwards-compatibility hazards. For example, when Cargo adds new features or changes the way it invokes rustc, that can interfere with pre-existing flags. Is documenting this sufficient?
- [ ] What should the behavior be with build scripts and proc-macros? Those have historically been a pain point with rustflags. Perhaps there should be a default
build-override.rustflags = []
. - [ ] Profile rustflags are not considered as part of
TargetInfo
, which impacts feature resolution and other things.
Future Extensions
No response
About tracking issues
Tracking issues are used to record the overall progress of implementation. They are also used as hubs connecting to other relevant issues, e.g., bugs or open design questions. A tracking issue is however not meant for large scale discussion, questions, or bug reports about a feature. Instead, open a dedicated issue for the specific matter and add the relevant feature gate label.
I see something like this as necessary for the usability of RFC 3028 (artifact dependencies): https://github.com/rust-lang/cargo/issues/9096 . Historically Cargo has not supported passing arbitrary flags in profile overrides because many of them made no sense to pass to a dependency (e.g. -C linker
). However, with binary artifacts, now literally all rustc flags become something that users will have valid reasons to want to specify. Currently this leads to lots of pain and workarounds with trying to use binary dependencies, either by hacking things up with Cargo config files (which don't work in all cases) or build scripts (which don't support all flags) or environment variables (which are difficult to set in all circumstances).
That doesn't mean that this feature is the only way to satisfy this need, but I think anything that does satisfy this need would have to be functionally equivalent to profile-rustflags.
cargo-features = ["per-package-target", "profile-rustflags"] don't work together. By this I mean the target does not get applied when profile-rustflags get used.
cargo-features = ["per-package-target", "profile-rustflags"]
[package]
name = "perf_kernel"
version = "0.1.0"
authors = ["Luis Hebendanz <[email protected]>"]
edition = "2021"
forced-target = "x86_64-unknown-none"
[profile.dev]
rustflags = [ "-C", "link-args=--image-base=0x200000" ]
Will fail with gcc: error: unrecognized command-line option '--image-base=0x200000'
even though target defines ld.lld as linker
I can not get this to work with a no_std
crate on Windows with the current nightly. Steps to reproduce the linker issue:
- Create a new binary project.
-
Cargo.toml
:[... default content ...] [profile.release] panic = "abort"
-
src/main.rs
:#![no_main] #![no_std] #[panic_handler] fn rust_begin_unwind(_: &core::panic::PanicInfo) -> ! { loop {} } #[no_mangle] fn WinMainCRTStartup() -> u32 { 0 }
-
.cargo/config.toml
:[target.'cfg(target_env = "msvc")'] rustflags = [ "-C", "link-args=/Debug:None /SubSystem:Windows" ]
- Compile with
cargo build --release --target x86_64-pc-windows-msvc -Z build-std=core
-> it succeeds. - Delete
.cargo/config.toml
. -
Cargo.toml
:cargo-features = [ "profile-rustflags" ] [... previous content ...] rustflags = [ "-C", "link-args=/Debug:None /SubSystem:Windows" ]
- Compile with
cargo build --release --target x86_64-pc-windows-msvc -Z build-std=core
-> it succeeds. - Delete the
target
build artifact directory to enforce a complete recompilation. - Compile with
cargo build --release --target x86_64-pc-windows-msvc -Z build-std=core
-> it fails:Compiling compiler_builtins v0.1.85 Compiling rustc-std-workspace-core v1.99.0 error: linking with `link.exe` failed: exit code: 1120 [... linker command arguments ...] note: msvcrt.lib(exe_winmain.obj) : error LNK2019: unresolved external symbol WinMain referenced in function "int __cdecl __scrt_common_main_seh(void)" (?__scrt_common_main_seh@@YAHXZ) build_script_build-[RandomHash].exe : fatal error LNK1120: 1 unresolved externals
It seems like it tries to link the things that should be excluded via no_std
, like msvcrt
and WinMain
.
By the way, is it possible to use something like cfg(target_env = "msvc")
with profile-rustflags
?
As mentioned in the unresolved section, profile rustflags get applied to build scripts. You can override that with:
[profile.dev.build-override]
rustflags = []
Also, I might suggest using the #[windows_subsystem]
attribute instead of setting it manually.
Conditional settings are not supported in profiles, you'll need to use separate profiles.
In the future, please file a new issue if you have a question or problem. See the "About tracking issues" section above.
Sorry, I will read more carefully next time and create a separate issue instead. I did not realize that my example contained a build script, thanks for the hint! The #![windows_subsystem = "windows"]
seems to be ignored, if applied to the example - it will look for mainCRTStartup
, the console
subsystem main function, instead of WinMainCRTStartup
, the windows
subsystem main function.
I am getting an issue where workspace rustflags don't work for sub-crates.
For example, - in the workspace Cargo.toml:
# TODO: Remove when WebGPU is no longer an unstable
[target.'cfg(target_arch="wasm32")'.profile.dev]
rustflags = ["--cfg", "web_sys_unstable_apis"]
Subcrates won't compile that depend on this:
error[E0599]: no method named `gpu` found for struct `WorkerNavigator` in the current scope
--> /Users/simbleau/.cargo/registry/src/index.crates.io-6f17d22bba15001f/wgpu-0.17.2/src/backend/web.rs:950:18
|
947 | / global
948 | | .unchecked_into::<web_sys::WorkerGlobalScope>()
949 | | .navigator()
950 | | .gpu()
| | -^^^ method not found in `WorkerNavigator`
| |_________________|
cargo build --verbose
confirms the flags are not passed down correctly.
Related: https://github.com/rust-lang/cargo/issues/4897
# TODO: Remove when WebGPU is no longer an unstable [target.'cfg(target_arch="wasm32")'.profile.dev] rustflags = ["--cfg", "web_sys_unstable_apis"]
This is not a valid key in Cargo.toml
. You might get a warning like
warning: /path/to/pkg/Cargo.toml: unused manifest key: target.cfg(target_arch="wasm32").profile
# TODO: Remove when WebGPU is no longer an unstable [target.'cfg(target_arch="wasm32")'.profile.dev] rustflags = ["--cfg", "web_sys_unstable_apis"]
This is not a valid key in
Cargo.toml
. You might get a warning likewarning: /path/to/pkg/Cargo.toml: unused manifest key: target.cfg(target_arch="wasm32").profile
Confused what you mean by it's not a key.
It's documented here: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#profile-rustflags-option
Can we also have per-profile environment variables, for CFLAGS/CXXFLAGS? Before I make a corresponding issue, is this idea going to fly at all?
Rationale: RUSTFLAGS alone is not enough to have, for example, cross-language LTO on the release profile.
Depends on how you use profile. For now we can leverage --config <alternative-config.toml>
without waiting for such feature being implemented.
BTW I feel like this has been brought up, but couldn't find an issue of it.
Depends on how you use profile. For now we can leverage
--config <alternative-config.toml>
without waiting for such feature being implemented.BTW I feel like this has been brought up, but couldn't find an issue of it.
@weihanglo this sounds like a great solution, I just cant get it to work reasonably
let's say I have a default configuration that is used during development and in the dev profile. This should be a default and work without an extra command line which could be forgotten, because I want to put things like sanitizer support in there.
So this is my .cargo/config.toml
:
[build]
target = "x86_64-unknown-linux-gnu"
rustflags = ["-Z", "sanitizer=address"]
[env]
BUILD_PROFILE = "debug"
Now in my build system I want to build the release build with a different configuration and the stable compiler. I create a new .cargo/config-release.toml
with the following content:
[env]
BUILD_PROFILE = "release"
And use the command cargo +stable --config .cargo/config-release.toml
to build it. Now it will still fall back to the .cargo/config.toml
which will not work because there is no sanitizer in the stable compiler. Only once I delete the .cargo/config.toml
, it will start using the config-release.toml
.
How would you approach such a use case? I have a mixed C and Rust application, that needs different rustflags and environment variables for the debug and release builds.
I am really struggling with getting that right. Another really unfortunate thing with defining the rustflags
in the config.toml
, everytime I set the RUSTFLAGS
env variable all the entries in the config.toml
are silently thrown away. I just realized today, that I am setting RUSTFLAGS="${RUSTFLAGS} -D warnings"
in the CI and by doing this am disabling all the flags I set in the config.
@kamulos if config-include supports optional config.toml, that could be an approach to manage multiple config files. See https://github.com/rust-lang/cargo/issues/7723.