use riscv_target_parser::RiscvTarget;
use std::{env, fs, io, path::PathBuf};
const RISCV_CFG: [&str; 4] = ["riscvi", "riscvm", "riscvf", "riscvd"];
fn add_linker_script(arch_width: u32) -> io::Result<()> {
let mut content = fs::read_to_string("link.x.in")?;
content = content.replace("${ARCH_WIDTH}", &arch_width.to_string());
let mut include_content = String::new();
if env::var_os("CARGO_FEATURE_NO_EXCEPTIONS").is_none() {
let exceptions_content = fs::read_to_string("exceptions.x")?;
include_content.push_str(&(exceptions_content + "\n"));
}
if env::var_os("CARGO_FEATURE_NO_INTERRUPTS").is_none() {
let interrupts_content = fs::read_to_string("interrupts.x")?;
include_content.push_str(&(interrupts_content + "\n"));
}
if env::var_os("CARGO_FEATURE_DEVICE").is_some() {
include_content.push_str("/* Device-specific exception and interrupt handlers */\n");
include_content.push_str("INCLUDE device.x\n");
}
if env::var_os("CARGO_FEATURE_MEMORY").is_some() {
include_content.push_str("/* Device-specific memory layout */\n");
include_content.push_str("INCLUDE memory.x\n");
}
content = content.replace("${INCLUDE_LINKER_FILES}", &include_content);
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
fs::write(out_dir.join("link.x"), content)?;
println!("cargo:rustc-link-search={}", out_dir.display());
println!("cargo:rerun-if-changed=link.x");
Ok(())
}
fn main() {
for ext in RISCV_CFG.iter() {
println!("cargo:rustc-check-cfg=cfg({ext})");
}
let target = env::var("TARGET").unwrap();
let cargo_flags = env::var("CARGO_ENCODED_RUSTFLAGS").unwrap();
if let Ok(target) = RiscvTarget::build(&target, &cargo_flags) {
let width_bytes = u32::from(target.width()) / 8;
println!(
"cargo:rustc-env=RISCV_RT_BASE_ISA={}",
target.llvm_base_isa()
);
println!(
"cargo:rustc-env=RISCV_RT_LLVM_ARCH_PATCH={}",
target.llvm_arch_patch()
);
println!("cargo:rerun-if-env-changed=RISCV_RT_BASE_ISA");
println!("cargo:rerun-if-env-changed=RISCV_RT_LLVM_ARCH_PATCH");
if env::var_os("CARGO_FEATURE_V_TRAP").is_some()
&& env::var_os("CARGO_FEATURE_NO_INTERRUPTS").is_none()
{
println!("cargo:rerun-if-env-changed=RISCV_MTVEC_ALIGN");
}
for flag in target.rustc_flags() {
if RISCV_CFG.contains(&flag.as_str()) {
println!("cargo:rustc-cfg={flag}");
}
}
add_linker_script(width_bytes).unwrap();
}
}