use std::fmt::Write; use std::path::PathBuf; use std::process::Command; use std::str::FromStr; use std::{env, fs}; const BENCHMARKS: &[&str] = &[ "src/ud/libud.c", // "src/wikisort/libwikisort.c", Error: undefined reference to rand_beebs "src/nbody/nbody.c", "src/edn/libedn.c", "src/st/libst.c", "src/aha-mont64/mont64.c", "src/matmult-int/matmult-int.c", "src/slre/libslre.c", "src/tarfind/tarfind.c", "src/sglib-combined/combined.c", "src/huffbench/libhuffbench.c", "src/nsichneu/libnsichneu.c", "src/minver/libminver.c", "src/statemate/libstatemate.c", "src/crc32/crc_32.c", "src/picojpeg/libpicojpeg.c", "src/cubic/basicmath_small.c", "src/md5sum/md5.c", "src/qrduino/qrtest.c", "src/nettle-aes/nettle-aes.c", "src/primecount/primecount.c", "src/nettle-sha256/nettle-sha256.c", ]; fn main() { println!("cargo:rerun-if-changed=build.rs"); let out_dir = env::var("OUT_DIR").unwrap(); Command::new("git") .args(["clone", "https://github.com/embench/embench-iot"]) .current_dir(&out_dir) .spawn() .unwrap() .wait() .unwrap(); let embench_dir = PathBuf::from_str(&format!("{out_dir}/embench-iot")).unwrap(); let mut generated_code = String::new(); for &benchmark_file in BENCHMARKS { let path = embench_dir.join(benchmark_file); let dir = path.parent().unwrap(); let benchmark_name = dir.file_name().unwrap().to_string_lossy().replace("-", "_"); println!("cargo:warning={path:?}"); let mut build = cc::Build::new(); build .include(embench_dir.join("support")) .file(embench_dir.join("support/beebsc.c")) .file(&path) // Just use some roughly accurate value, it just influences how long each benchmark runs .define("CPU_MHZ", "2700"); // Rename all functions that are defined multiple times to avoid collisions let colliding_functions = [ "benchmark", "initialise_benchmark", "warm_caches", "verify_benchmark", ]; for name in colliding_functions { build.define(name, format!("{benchmark_name}_{name}").as_str()); } build.compile(&format!("libembench_{benchmark_name}.a")); write!( generated_code, r#" #[allow(non_camel_case_types)] pub struct {benchmark_name}; unsafe extern "C" {{ fn {benchmark_name}_benchmark(); fn {benchmark_name}_initialise_benchmark(); }} impl Benchmark for {benchmark_name} {{ unsafe fn init() {{ unsafe {{ {benchmark_name}_initialise_benchmark(); }} }} unsafe fn benchmark() {{ unsafe {{ {benchmark_name}_benchmark(); }} }} }} "# ) .unwrap(); } fs::write(format!("{out_dir}/libembench-sys.rs"), generated_code).unwrap(); }