-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathbuild.rs
74 lines (63 loc) · 3.53 KB
/
build.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
use std::env;
fn main() {
/// The name of the environment variable that can be set to enable the check for panics.
// If you change this, remember to also change the environment variable
// that is set in the CI job that checks for panics.
const ENV_KEY: &str = "LAMBERT_W_ENSURE_NO_PANICS";
/// The value we look for in the environment variable to enable the check for panics.
// If you change this, remember to also change the value that the variable is set to
// in the CI job that checks for panics.
const ENV_VAL: &str = "1";
/// The profile needed to ensure no false positives in the check for panics.
// If you change this, remember to also change the profile that is set in the CI job
// that checks for panics.
const NEEDED_PROFILE: &str = "release-lto";
// Changes to the above constants need to be mentioned in the CHANGELOG.md file.
// Re-run the build script if the environment variable changes.
println!("cargo:rerun-if-env-changed={ENV_KEY}");
// Make cargo aware of the `assert_no_panic` cfg option
println!("cargo:rustc-check-cfg=cfg(assert_no_panic)");
if let Ok(env_val) = env::var(ENV_KEY) {
// If the environment variable at `ENV_KEY` is set to `ENV_VAL` we use the `no-panic` crate to attempt to verify that the crate can not panic.
if env_val == ENV_VAL {
// Enable the `assert_no_panic` cfg option.
println!("cargo:rustc-cfg=assert_no_panic");
let suggestion = format!(
"The `{NEEDED_PROFILE}` profile must be enabled to ensure no false positives."
);
// In order for `no-panic` to not cause false positives a specific profile needs to be enabled.
// We emit a compilation warning if we can not determine that this profile is enabled.
match parse_build_profile_name_from_environment() {
Ok(Some(profile_name)) => {
if profile_name != NEEDED_PROFILE {
println!("cargo:warning=the `{ENV_KEY}` environment variable is set to {ENV_VAL}, but a profile that could result in false positives seems to be enabled. {suggestion}");
}
}
Ok(None) => {
println!("cargo:warning=the `{ENV_KEY}` environment variable is set to {ENV_VAL}, but the build profile name could not be determined. {suggestion}");
}
Err(e) => {
println!("cargo:warning=the `{ENV_KEY}` environment variable is set to {ENV_VAL}, but the `OUT_DIR` environment variable could not be read due to: {e}\nThe profile could therefore not be determined. {suggestion}");
}
}
}
}
}
/// Reads the build profile name from the `OUT_DIR` environment variable.
///
/// If everything works as expected it returns an `Ok(Some(String))`.
///
/// If the environment variable could not be read by the standard library
/// it returns an `Err(VarError)`, and if the profile name could not
/// be determined it returns an `Ok(None)`.
fn parse_build_profile_name_from_environment() -> Result<Option<String>, env::VarError> {
// Taken from <https://stackoverflow.com/a/73603419/3774277>.
// The profile name is always the 3rd last part of the path (with 1 based indexing).
// e.g. /code/core/target/cli/build/my-build-info-9f91ba6f99d7a061/out
env::var("OUT_DIR").map(|env_var_val| {
env_var_val
.split(std::path::MAIN_SEPARATOR)
.nth_back(3)
.map(|s| s.to_string())
})
}