1
0
forked from M-Labs/nac3
nac3/nac3core/build.rs

103 lines
3.2 KiB
Rust
Raw Normal View History

2024-06-01 15:10:43 +08:00
use std::ffi::OsStr;
use std::{
env,
2022-03-22 15:39:15 +08:00
fs::File,
io::Write,
2022-01-09 12:06:45 +08:00
path::Path,
process::{Command, Stdio},
};
2024-06-01 15:10:43 +08:00
use itertools::Itertools;
use regex::Regex;
2024-06-01 15:10:43 +08:00
/// Extracts the extension-less filename from a [`Path`].
fn path_to_extless_filename(path: &Path) -> &str {
path.file_name().map(Path::new).and_then(Path::file_stem).and_then(OsStr::to_str).unwrap()
}
/// Compiles a source C file into LLVM bitcode.
fn compile_file_to_ir(path: &Path, filename_without_ext: &str) {
/*
* HACK: Sadly, clang doesn't let us emit generic LLVM bitcode.
* Compiling for WASM32 and filtering the output with regex is the closest we can get.
*/
let flags: &[&str] = &[
"--target=wasm32",
2024-06-01 15:10:43 +08:00
path.to_str().unwrap(),
2024-07-09 13:31:29 +08:00
"-x",
"c++",
"-fno-discard-value-names",
2024-07-05 17:24:57 +08:00
"-fno-exceptions",
"-fno-rtti",
match env::var("PROFILE").as_deref() {
Ok("debug") => "-O0",
Ok("release") => "-O3",
2024-03-11 14:25:37 +08:00
flavor => panic!("Unknown or missing build flavor {flavor:?}"),
},
"-emit-llvm",
"-S",
"-Wall",
"-Wextra",
"-o",
"-",
];
2023-12-08 17:43:32 +08:00
2024-06-01 15:10:43 +08:00
println!("cargo:rerun-if-changed={}", path.to_str().unwrap());
2023-12-08 17:43:32 +08:00
let out_dir = env::var("OUT_DIR").unwrap();
let out_path = Path::new(&out_dir);
let output = Command::new("clang-irrt")
.args(flags)
.output()
.map(|o| {
assert!(o.status.success(), "{}", std::str::from_utf8(&o.stderr).unwrap());
o
})
.unwrap();
2024-06-01 15:10:43 +08:00
let output = std::str::from_utf8(&output.stdout).unwrap();
let mut filtered_output = String::with_capacity(output.len());
2023-10-26 13:52:40 +08:00
let regex_filter = Regex::new(r"(?ms:^define.*?\}$)|(?m:^declare.*?$)").unwrap();
2024-06-01 15:10:43 +08:00
for f in regex_filter.captures_iter(output) {
assert_eq!(f.len(), 1);
filtered_output.push_str(&f[0]);
filtered_output.push('\n');
}
let filtered_output = Regex::new("(#\\d+)|(, *![0-9A-Za-z.]+)|(![0-9A-Za-z.]+)|(!\".*?\")")
.unwrap()
.replace_all(&filtered_output, "");
2022-03-22 15:39:15 +08:00
println!("cargo:rerun-if-env-changed=DEBUG_DUMP_IRRT");
if env::var("DEBUG_DUMP_IRRT").is_ok() {
2024-06-01 15:10:43 +08:00
let mut file = File::create(out_path.join(format!("{filename_without_ext}.ll"))).unwrap();
2022-03-22 15:39:15 +08:00
file.write_all(output.as_bytes()).unwrap();
2024-06-01 15:10:43 +08:00
let mut file =
File::create(out_path.join(format!("{filename_without_ext}-filtered.ll"))).unwrap();
2022-03-22 15:39:15 +08:00
file.write_all(filtered_output.as_bytes()).unwrap();
}
2023-11-25 20:15:29 +08:00
let mut llvm_as = Command::new("llvm-as-irrt")
.stdin(Stdio::piped())
.arg("-o")
2024-06-01 15:10:43 +08:00
.arg(out_path.join(format!("{filename_without_ext}.bc")))
.spawn()
.unwrap();
llvm_as.stdin.as_mut().unwrap().write_all(filtered_output.as_bytes()).unwrap();
2023-12-08 17:43:32 +08:00
assert!(llvm_as.wait().unwrap().success());
}
2024-06-01 15:10:43 +08:00
fn main() {
const IRRT_SOURCE_PATHS: &[&str] =
&["src/codegen/irrt/irrt.cpp", "src/codegen/tracert/tracert.cpp"];
assert!(IRRT_SOURCE_PATHS.iter().map(Path::new).map(path_to_extless_filename).all_unique());
for path in IRRT_SOURCE_PATHS {
let path = Path::new(path);
compile_file_to_ir(path, path_to_extless_filename(path))
}
}