@@ -5,6 +5,7 @@ use crate::{
5
5
prelude:: * ,
6
6
} ;
7
7
use cargo_metadata:: { camino:: Utf8PathBuf , Message , Metadata , TargetKind } ;
8
+ use semver:: Version ;
8
9
use std:: process:: { exit, Command , Stdio } ;
9
10
10
11
struct BuildOptions < ' a > {
@@ -105,15 +106,21 @@ impl BuildOptions<'_> {
105
106
Ok ( built_benches)
106
107
}
107
108
108
- /// Generates a subcommand to build the benchmarks by invoking cargo and forwarding the filters
109
- /// This command explicitly ignores the `self.benches`: all benches are built
110
- fn build_command ( & self , measurement_mode : MeasurementMode ) -> Command {
111
- let mut cargo = Command :: new ( "cargo" ) ;
112
- cargo. args ( [ "build" , "--benches" ] ) ;
113
-
114
- let mut rust_flags = std:: env:: var ( "RUSTFLAGS" ) . unwrap_or_else ( |_| "" . into ( ) ) ;
109
+ /// Adds debug flags and codspeed compilation
110
+ ///
111
+ /// If the user has set `RUSTFLAGS`, it will append the flags to it.
112
+ /// Else, and if the cargo version allows it, it will set the cargo config through
113
+ /// `--config 'build.rustflags=[ ... ]'`
114
+ ///
115
+ /// # Why we do this
116
+ /// As tracked in [https://github.com/rust-lang/cargo/issues/5376], setting `RUSTFLAGS`
117
+ /// completely overrides rustflags from rust config
118
+ /// We use the cargo built-in config mechanism to set the flags if the user has not set
119
+ /// `RUSTFLAGS`.
120
+ fn add_rust_flags ( & self , cargo : & mut Command , measurement_mode : MeasurementMode ) {
115
121
// Add debug info (equivalent to -g)
116
- rust_flags. push_str ( " -C debuginfo=2" ) ;
122
+ let mut flags = vec ! [ "-C" . to_string( ) ] ;
123
+ flags. push ( "debuginfo=2" . to_string ( ) ) ;
117
124
118
125
// Prevent debug info stripping
119
126
// https://doc.rust-lang.org/cargo/reference/profiles.html#release
@@ -122,13 +129,70 @@ impl BuildOptions<'_> {
122
129
// In practice, if we set debug info through RUSTFLAGS, cargo still strips them, most
123
130
// likely because debug = false in the release profile.
124
131
// We also need to disable stripping through rust flags.
125
- rust_flags. push_str ( " -C strip=none" ) ;
132
+ flags. push ( "-C" . to_string ( ) ) ;
133
+ flags. push ( "strip=none" . to_string ( ) ) ;
126
134
127
135
// Add the codspeed cfg flag if instrumentation mode is enabled
128
136
if measurement_mode == MeasurementMode :: Instrumentation {
129
- rust_flags. push_str ( " --cfg codspeed" ) ;
137
+ flags. push ( "--cfg" . to_string ( ) ) ;
138
+ flags. push ( "codspeed" . to_string ( ) ) ;
139
+ }
140
+
141
+ match std:: env:: var ( "RUSTFLAGS" ) {
142
+ std:: result:: Result :: Ok ( existing_rustflags) => {
143
+ // If RUSTFLAGS is set, append our flags to it
144
+ let mut combined_flags = existing_rustflags;
145
+ for flag in flags {
146
+ combined_flags. push ( ' ' ) ;
147
+ combined_flags. push_str ( & flag) ;
148
+ }
149
+ cargo. env ( "RUSTFLAGS" , combined_flags) ;
150
+ }
151
+ std:: result:: Result :: Err ( _) => {
152
+ // Check if cargo version supports --config (Cargo 1.63+, 2022-08-11)
153
+ if Self :: cargo_supports_config_from_cli ( ) {
154
+ // Use --config to set rustflags
155
+ let config_value = format ! (
156
+ "build.rustflags=[{}]" ,
157
+ flags. into_iter( ) . map( |f| format!( "\" {f}\" " ) ) . join( "," )
158
+ ) ;
159
+ cargo. arg ( "--config" ) . arg ( config_value) ;
160
+ } else {
161
+ // Fallback to RUSTFLAGS for older cargo versions
162
+ let rustflags = flags. join ( " " ) ;
163
+ cargo. env ( "RUSTFLAGS" , rustflags) ;
164
+ }
165
+ }
130
166
}
131
- cargo. env ( "RUSTFLAGS" , rust_flags) ;
167
+ }
168
+
169
+ /// Check if cargo version supports --config flag (Cargo 1.63+)
170
+ /// [https://doc.rust-lang.org/nightly/cargo/CHANGELOG.html#cargo-163-2022-08-11]
171
+ fn cargo_supports_config_from_cli ( ) -> bool {
172
+ let output = Command :: new ( "cargo" ) . arg ( "--version" ) . output ( ) ;
173
+
174
+ if let std:: result:: Result :: Ok ( output) = output {
175
+ if let std:: result:: Result :: Ok ( version_str) = String :: from_utf8 ( output. stdout ) {
176
+ // Parse version string like "cargo 1.70.0 (7fe40dc9c 2023-04-27)"
177
+ if let Some ( version_part) = version_str. split_whitespace ( ) . nth ( 1 ) {
178
+ if let std:: result:: Result :: Ok ( version) = Version :: parse ( version_part) {
179
+ // Cargo 1.63.0 introduced --config support
180
+ return version >= Version :: new ( 1 , 63 , 0 ) ;
181
+ }
182
+ }
183
+ }
184
+ }
185
+
186
+ false
187
+ }
188
+
189
+ /// Generates a subcommand to build the benchmarks by invoking cargo and forwarding the filters
190
+ /// This command explicitly ignores the `self.benches`: all benches are built
191
+ fn build_command ( & self , measurement_mode : MeasurementMode ) -> Command {
192
+ let mut cargo = Command :: new ( "cargo" ) ;
193
+ cargo. args ( [ "build" , "--benches" ] ) ;
194
+
195
+ self . add_rust_flags ( & mut cargo, measurement_mode) ;
132
196
133
197
if let Some ( features) = self . features {
134
198
cargo. arg ( "--features" ) . arg ( features. join ( "," ) ) ;
0 commit comments