#[path = "src/gen/build.rs"]
mod generated;
#[path = "version.rs"]
mod version;
use std::env;
use self::version::{Version, rustc_version};
fn main() {
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-changed=src/gen/build.rs");
let target_arch = &*env::var("CARGO_CFG_TARGET_ARCH").expect("CARGO_CFG_TARGET_ARCH not set");
let version = match rustc_version() {
Some(version) => version,
None => {
if env::var_os("SEMIHOSTING_DENY_WARNINGS").is_some() {
panic!("unable to determine rustc version")
}
println!(
"cargo:warning={}: unable to determine rustc version; assuming latest stable rustc (1.{})",
env!("CARGO_PKG_NAME"),
Version::LATEST.minor
);
Version::LATEST
}
};
if version.minor >= 80 {
println!(
"cargo:rustc-check-cfg=cfg(semihosting_no_asm,semihosting_no_duration_checked_float,semihosting_no_error_in_core,semihosting_no_strict_provenance,semihosting_target_feature)"
);
println!(
r#"cargo:rustc-check-cfg=cfg(semihosting_target_feature,values("mclass","thumb-mode"))"#
);
}
if !version.probe(66, 2022, 10, 24) {
println!("cargo:rustc-cfg=semihosting_no_duration_checked_float");
}
if !version.probe(81, 2024, 6, 8) {
println!("cargo:rustc-cfg=semihosting_no_error_in_core");
}
if !version.probe(84, 2024, 10, 21) {
println!("cargo:rustc-cfg=semihosting_no_strict_provenance");
}
match target_arch {
"arm" => {
let target = &*env::var("TARGET").expect("TARGET not set");
if !version.probe(79, 2024, 4, 10) {
println!("cargo:rerun-if-env-changed=CARGO_ENCODED_RUSTFLAGS");
println!("cargo:rerun-if-env-changed=RUSTFLAGS");
println!("cargo:rerun-if-env-changed=CARGO_BUILD_RUSTFLAGS");
let mut target_upper = target.replace(['-', '.'], "_");
target_upper.make_ascii_uppercase();
println!("cargo:rerun-if-env-changed=CARGO_TARGET_{target_upper}_RUSTFLAGS");
}
if needs_target_feature_fallback(&version) {
let mut subarch =
target.strip_prefix("arm").or_else(|| target.strip_prefix("thumb")).unwrap();
subarch = subarch.strip_prefix("eb").unwrap_or(subarch); subarch = subarch.split('-').next().unwrap(); subarch = subarch.split('.').next().unwrap(); let mut mclass = false;
match subarch {
"v6m" | "v7em" | "v7m" | "v8m" => mclass = true,
_ => {}
}
target_feature_fallback("mclass", mclass);
let thumb_mode =
target.starts_with("thumb") || generated::ARM_BUT_THUMB_MODE.contains(&target);
target_feature_fallback("thumb-mode", thumb_mode);
}
}
"loongarch32" => {
if !version.probe(91, 2025, 8, 10) {
println!("cargo:rustc-cfg=semihosting_no_asm");
}
}
_ => {}
}
}
fn needs_target_feature_fallback(version: &Version) -> bool {
if version.nightly {
false
} else {
true
}
}
fn target_feature_fallback(name: &str, mut has_target_feature: bool) {
if let Some(rustflags) = env::var_os("CARGO_ENCODED_RUSTFLAGS") {
for mut flag in rustflags.to_string_lossy().split('\x1f') {
flag = flag.strip_prefix("-C").unwrap_or(flag);
if let Some(flag) = flag.strip_prefix("target-feature=") {
for s in flag.split(',') {
match (s.as_bytes().first(), s.as_bytes().get(1..)) {
(Some(b'+'), Some(f)) if f == name.as_bytes() => has_target_feature = true,
(Some(b'-'), Some(f)) if f == name.as_bytes() => has_target_feature = false,
_ => {}
}
}
}
}
}
if has_target_feature {
println!("cargo:rustc-cfg=semihosting_target_feature=\"{name}\"");
}
}