153 lines
4.4 KiB
Rust
153 lines
4.4 KiB
Rust
use std::{env, path::PathBuf};
|
|
|
|
static SOURCES: &[&str] = &[
|
|
"assert.c",
|
|
"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, Option<&'a str>)],
|
|
}
|
|
|
|
static SIGNAL_ARCH: Arch = Arch {
|
|
name: "signal",
|
|
sources: &["signal.c", "syscall.S", "task_entry.S"],
|
|
flags: &["-pthread"],
|
|
defs: &[("_GNU_SOURCE", None)],
|
|
};
|
|
|
|
static ARM_ARCH: Arch = Arch {
|
|
name: "arm",
|
|
sources: &["arm.c", "syscall.S", "task_entry.S"],
|
|
flags: &["-fshort-enums"], // arm-none-eabi-gcc and rustc use this by default, but clang/bindgen don't
|
|
defs: &[],
|
|
};
|
|
|
|
struct ArmArFeature<'a> {
|
|
name: &'a str,
|
|
path: &'a str,
|
|
arch_patterns: &'a [&'a str],
|
|
}
|
|
|
|
static ARM_AR_FEATURES: &[ArmArFeature] = &[
|
|
ArmArFeature {
|
|
name: "HERCULES",
|
|
path: "hercules",
|
|
arch_patterns: &["armebv7r", "armv7r"],
|
|
},
|
|
ArmArFeature {
|
|
name: "SITARA_VIM",
|
|
path: "sitara/vim",
|
|
arch_patterns: &["armv7r"],
|
|
},
|
|
ArmArFeature {
|
|
name: "SITARA_INTC",
|
|
path: "sitara/intc",
|
|
arch_patterns: &["armv7a"],
|
|
},
|
|
];
|
|
|
|
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 target = env::var("TARGET").unwrap();
|
|
|
|
let arch = if target_arch == "arm" && target_os == "none" {
|
|
&ARM_ARCH
|
|
} else if ["linux", "macos"].contains(&target_os.as_str())
|
|
&& ["aarch64", "x86_64"].contains(&target_arch.as_str())
|
|
{
|
|
&SIGNAL_ARCH
|
|
} else {
|
|
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);
|
|
}
|
|
|
|
if arch.name == "arm" {
|
|
cc.flag("-flto");
|
|
cc.flag("-ffat-lto-objects");
|
|
if target.contains("armeb") {
|
|
cc.compiler("armeb-none-eabi-gcc");
|
|
cc.archiver("armeb-none-eabi-gcc-ar");
|
|
} else {
|
|
cc.compiler("arm-none-eabi-gcc");
|
|
cc.archiver("arm-none-eabi-gcc-ar");
|
|
}
|
|
let mut arm_ar_feature_already_set = false;
|
|
for feat in ARM_AR_FEATURES {
|
|
if env::var(format!("CARGO_FEATURE_{}", feat.name)).is_ok() {
|
|
// Prevent multiple arm/ar features from being enabled.
|
|
assert!(!arm_ar_feature_already_set);
|
|
// Check that the architecture matches what the feature expects.
|
|
assert!(feat.arch_patterns.iter().any(|pat| target.contains(pat)));
|
|
cc.include(arch_dir.join("ar").join(feat.path));
|
|
arm_ar_feature_already_set = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
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());
|
|
|
|
let arch_def_flags = arch.defs.iter().map(|(m, ov)| match ov {
|
|
Some(v) => format!("-D{m}={v}"),
|
|
None => format!("-D{m}"),
|
|
});
|
|
|
|
bindgen::builder()
|
|
.header(wrapper)
|
|
.clang_arg(format!("-I{}", include_dir.display()))
|
|
.clang_arg(format!("-I{}", arch_include_dir.display()))
|
|
.clang_args(arch_def_flags)
|
|
.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::new()))
|
|
.generate()
|
|
.expect("Failed to generate bindings.")
|
|
.write_to_file(out_dir.join("bindings.rs"))
|
|
.expect("Failed to write bindings.");
|
|
}
|