rt/rust/build.rs

106 lines
3.0 KiB
Rust

use std::{env, path::PathBuf};
static SOURCES: &[&str] = &[
"barrier.c",
"cond.c",
"list.c",
"mutex.c",
"notify.c",
"queue.c",
"rt.c",
"rwlock.c",
"sem.c",
"sleep.c",
];
struct Arch<'a> {
name: &'a str,
sources: &'a [&'a str],
flags: &'a [&'a str],
defs: &'a [(&'a str, &'a str)],
}
static PTHREAD_ARCH: Arch = Arch {
name: "pthread",
sources: &["pthread.c"],
flags: &["-pthread"],
defs: &[("_POSIX_C_SOURCE", "200809L")],
};
static ARM_ARCH: Arch = Arch {
name: "arm",
sources: &["arm.c", "syscall.S"],
flags: &["-fshort-enums"], // arm-none-eabi-gcc uses this by default, but clang/bindgen don't
defs: &[],
};
fn main() {
let root_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
let arch = match (target_arch.as_str(), target_os.as_str()) {
("arm", "none") => &ARM_ARCH,
(_, "linux") => &PTHREAD_ARCH,
(_, "macos") => &PTHREAD_ARCH,
_ => panic!("Unsupported (arch, os) combination: ({target_arch}, {target_os})"),
};
let src_dir = root_dir.join("src");
let include_dir = root_dir.join("include");
let arch_dir = root_dir.join("arch").join(arch.name);
let arch_include_dir = arch_dir.join("include");
let mut cc = cc::Build::new();
cc.files(SOURCES.iter().map(|s| src_dir.join(s)));
cc.files(arch.sources.iter().map(|s| arch_dir.join(s)));
cc.include(&include_dir);
cc.include(arch_dir.join("include"));
cc.flag("-std=c17");
for flag in arch.flags {
cc.flag(flag);
}
for &(name, val) in arch.defs {
cc.define(name, val);
}
// TODO: Enable LTO when rust options request it and the C compiler's LTO is compatible.
let target = env::var("TARGET").unwrap();
// TODO: Provide a better way to specify Cortex-R variants.
// For now armebv7r is always a Hercules.
if target.contains("armebv7r") {
cc.include(arch_dir.join("r/hercules"));
}
cc.compile("rt");
let wrapper = "rust/wrapper.h";
println!("cargo:rerun-if-changed={}", wrapper);
for d in [&src_dir, &include_dir, &arch_dir] {
println!("cargo:rerun-if-changed={}", d.display());
}
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
bindgen::builder()
.header(wrapper)
.clang_arg(format!("-I{}", include_dir.display()))
.clang_arg(format!("-I{}", arch_include_dir.display()))
.clang_args(arch.defs.iter().map(|&(m, v)| format!("-D{m}={v}")))
.clang_args(arch.flags)
.disable_nested_struct_naming()
.use_core()
.default_enum_style(bindgen::EnumVariation::NewType {
is_bitfield: false,
is_global: false,
})
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
.generate()
.expect("Failed to generate bindings.")
.write_to_file(out_dir.join("bindings.rs"))
.expect("Failed to write bindings.");
}