@@ -7,6 +7,7 @@ fn main() {
77
88 collect_rustc_info ( ) ;
99 collect_cargo_info ( ) ;
10+ collect_build_profile_info ( ) ;
1011
1112 let mut build = cc:: Build :: new ( ) ;
1213 build
@@ -48,6 +49,41 @@ fn main() {
4849 }
4950}
5051
52+ /// Collect build profile and performance-relevant compiler options at build time.
53+ /// These env var names must be kept in sync with `src/instrument_hooks/mod.rs`.
54+ ///
55+ /// Reference: <https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts>
56+ fn collect_build_profile_info ( ) {
57+ // PROFILE is set by Cargo to the name of the profile being built (e.g. "release", "bench", "debug").
58+ if let Ok ( profile) = std:: env:: var ( "PROFILE" ) {
59+ println ! ( "cargo:rustc-env=CODSPEED_BUILD_PROFILE={profile}" ) ;
60+ }
61+
62+ // OPT_LEVEL is set by Cargo to the optimization level (0, 1, 2, 3, s, z).
63+ if let Ok ( opt_level) = std:: env:: var ( "OPT_LEVEL" ) {
64+ println ! ( "cargo:rustc-env=CODSPEED_BUILD_OPT_LEVEL={opt_level}" ) ;
65+ }
66+
67+ // Extract performance-relevant codegen flags from rustflags.
68+ //
69+ // Cargo uses two mutually exclusive sources for rustflags (see
70+ // <https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-reads>):
71+ // - RUSTFLAGS env var (space-separated, takes priority)
72+ // - CARGO_ENCODED_RUSTFLAGS env var (0x1f-separated, used when RUSTFLAGS is not set)
73+ // We check both in priority order to accurately represent the flags used to build.
74+ let rustflags: Vec < String > = if let Ok ( raw) = std:: env:: var ( "RUSTFLAGS" ) {
75+ raw. split_whitespace ( ) . map ( String :: from) . collect ( )
76+ } else if let Ok ( encoded) = std:: env:: var ( "CARGO_ENCODED_RUSTFLAGS" ) {
77+ encoded. split ( '\x1f' ) . map ( String :: from) . collect ( )
78+ } else {
79+ Vec :: new ( )
80+ } ;
81+
82+ if let Some ( target_cpu) = extract_codegen_flag ( & rustflags, "target-cpu" ) {
83+ println ! ( "cargo:rustc-env=CODSPEED_BUILD_TARGET_CPU={target_cpu}" ) ;
84+ }
85+ }
86+
5187/// Collect rustc toolchain info at build time and expose as env vars.
5288/// These env var names must be kept in sync with `src/instrument_hooks/mod.rs`.
5389fn collect_rustc_info ( ) {
@@ -98,3 +134,35 @@ fn collect_cargo_info() {
98134 println ! ( "cargo:rustc-env=CODSPEED_CARGO_VERSION={rest}" ) ;
99135 }
100136}
137+
138+ /// Extract a codegen option value from a list of rustc flags.
139+ ///
140+ /// Handles all three forms that rustc accepts:
141+ /// - `-Ckey=value` (no space)
142+ /// - `-C` `key=value` (space between -C and the option, split into two entries)
143+ /// - `-C` `key` `value` (space between key and value, split into three entries) — only for flags that accept it
144+ ///
145+ /// Returns the value for the first match of `key`.
146+ fn extract_codegen_flag ( flags : & [ String ] , key : & str ) -> Option < String > {
147+ let mut iter = flags. iter ( ) ;
148+ while let Some ( flag) = iter. next ( ) {
149+ // Form: -Ckey=value
150+ if let Some ( rest) = flag. strip_prefix ( "-C" ) {
151+ if let Some ( value) = rest. strip_prefix ( key) . and_then ( |s| s. strip_prefix ( '=' ) ) {
152+ return Some ( value. to_string ( ) ) ;
153+ }
154+ // rest is not our key, skip
155+ continue ;
156+ }
157+
158+ // Form: -C key=value or -C key value
159+ if flag == "-C" {
160+ if let Some ( next) = iter. next ( ) {
161+ if let Some ( value) = next. strip_prefix ( key) . and_then ( |s| s. strip_prefix ( '=' ) ) {
162+ return Some ( value. to_string ( ) ) ;
163+ }
164+ }
165+ }
166+ }
167+ None
168+ }
0 commit comments