Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions crates/codspeed/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ fn main() {

collect_rustc_info();
collect_cargo_info();
collect_build_profile_info();

let mut build = cc::Build::new();
build
Expand Down Expand Up @@ -48,6 +49,41 @@ fn main() {
}
}

/// Collect build profile and performance-relevant compiler options at build time.
/// These env var names must be kept in sync with `src/instrument_hooks/mod.rs`.
///
/// Reference: <https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts>
fn collect_build_profile_info() {
// PROFILE is set by Cargo to the name of the profile being built (e.g. "release", "bench", "debug").
if let Ok(profile) = std::env::var("PROFILE") {
println!("cargo:rustc-env=CODSPEED_BUILD_PROFILE={profile}");
}

// OPT_LEVEL is set by Cargo to the optimization level (0, 1, 2, 3, s, z).
if let Ok(opt_level) = std::env::var("OPT_LEVEL") {
println!("cargo:rustc-env=CODSPEED_BUILD_OPT_LEVEL={opt_level}");
}

// Extract performance-relevant codegen flags from rustflags.
//
// Cargo uses two mutually exclusive sources for rustflags (see
// <https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-reads>):
// - RUSTFLAGS env var (space-separated, takes priority)
// - CARGO_ENCODED_RUSTFLAGS env var (0x1f-separated, used when RUSTFLAGS is not set)
// We check both in priority order to accurately represent the flags used to build.
let rustflags: Vec<String> = if let Ok(raw) = std::env::var("RUSTFLAGS") {
raw.split_whitespace().map(String::from).collect()
} else if let Ok(encoded) = std::env::var("CARGO_ENCODED_RUSTFLAGS") {
encoded.split('\x1f').map(String::from).collect()
} else {
Vec::new()
};

if let Some(target_cpu) = extract_codegen_flag(&rustflags, "target-cpu") {
println!("cargo:rustc-env=CODSPEED_BUILD_TARGET_CPU={target_cpu}");
}
}

/// Collect rustc toolchain info at build time and expose as env vars.
/// These env var names must be kept in sync with `src/instrument_hooks/mod.rs`.
fn collect_rustc_info() {
Expand Down Expand Up @@ -98,3 +134,35 @@ fn collect_cargo_info() {
println!("cargo:rustc-env=CODSPEED_CARGO_VERSION={rest}");
}
}

/// Extract a codegen option value from a list of rustc flags.
///
/// Handles all three forms that rustc accepts:
/// - `-Ckey=value` (no space)
/// - `-C` `key=value` (space between -C and the option, split into two entries)
/// - `-C` `key` `value` (space between key and value, split into three entries) — only for flags that accept it
///
/// Returns the value for the first match of `key`.
fn extract_codegen_flag(flags: &[String], key: &str) -> Option<String> {
let mut iter = flags.iter();
while let Some(flag) = iter.next() {
// Form: -Ckey=value
if let Some(rest) = flag.strip_prefix("-C") {
if let Some(value) = rest.strip_prefix(key).and_then(|s| s.strip_prefix('=')) {
return Some(value.to_string());
}
// rest is not our key, skip
continue;
}

// Form: -C key=value or -C key value
if flag == "-C" {
if let Some(next) = iter.next() {
if let Some(value) = next.strip_prefix(key).and_then(|s| s.strip_prefix('=')) {
return Some(value.to_string());
}
}
}
}
None
}
9 changes: 9 additions & 0 deletions crates/codspeed/src/instrument_hooks/bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,15 @@ extern "C" {
value: *const ::std::os::raw::c_char,
) -> u8;
}
extern "C" {
pub fn instrument_hooks_set_environment_list(
arg1: *mut InstrumentHooks,
section_name: *const ::std::os::raw::c_char,
key: *const ::std::os::raw::c_char,
values: *const *const ::std::os::raw::c_char,
count: u32,
) -> u8;
}
extern "C" {
pub fn instrument_hooks_write_environment(arg1: *mut InstrumentHooks, pid: u32) -> u8;
}
9 changes: 9 additions & 0 deletions crates/codspeed/src/instrument_hooks/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,15 @@ mod linux_impl {
if let Some(v) = option_env!("CODSPEED_CARGO_VERSION") {
let _ = self.set_environment(SECTION, "cargo", v);
}
if let Some(v) = option_env!("CODSPEED_BUILD_PROFILE") {
let _ = self.set_environment(SECTION, "profile", v);
}
if let Some(v) = option_env!("CODSPEED_BUILD_OPT_LEVEL") {
let _ = self.set_environment(SECTION, "opt-level", v);
}
if let Some(v) = option_env!("CODSPEED_BUILD_TARGET_CPU") {
let _ = self.set_environment(SECTION, "target-cpu", v);
}

if let Err(e) = self.write_environment() {
eprintln!("Warning: failed to write environment info: {e}");
Expand Down
6 changes: 4 additions & 2 deletions crates/codspeed/src/instrument_hooks/update-bindings.sh
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#!/usr/bin/env bash
set -euo pipefail

bindgen ../../instrument-hooks/includes/core.h \
-o bindings.rs \
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"

bindgen "$SCRIPT_DIR/../../instrument-hooks/includes/core.h" \
-o "$SCRIPT_DIR/bindings.rs" \
--rust-target 1.74 \
--allowlist-function "instrument_hooks_.*" \
--allowlist-var "MARKER_TYPE_.*"
Loading