Skip to content

Commit

Permalink
build: Don't tie in tightly with riot-sys
Browse files Browse the repository at this point in the history
This removes all dependencies on `link=` exported DEP_RIOT_SYS_
variables infavor of parsing riotbuild.h.
  • Loading branch information
chrysn committed Jan 31, 2024
1 parent ac21e15 commit 858274f
Showing 1 changed file with 39 additions and 46 deletions.
85 changes: 39 additions & 46 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,63 +3,56 @@ extern crate shlex;
use std::env;

fn main() {
let cflags = env::var("DEP_RIOT_SYS_CFLAGS")
.expect("DEP_RIOT_SYS_CFLAGS is not set, check whether riot-sys exports it.");
let cflags = shlex::split(&cflags).expect("Odd shell escaping in CFLAGS");

println!("cargo:rerun-if-env-changed=DEP_RIOT_SYS_CFLAGS");

for flag in cflags.iter() {
if flag.starts_with("-DMODULE_") {
// Some modules like cmsis-dsp_StatisticsFunctions have funny characters
println!(
"cargo:rustc-cfg=riot_module_{}",
flag[9..].to_lowercase().replace("-", "_")
);
println!("cargo:rerun-if-env-changed=RIOTBUILD_CONFIG_HEADER_C");
let riotbuildh = env::var("RIOTBUILD_CONFIG_HEADER_C")
.expect("riotbuild.h is expected to be indicated in the RIOTBUILD_CONFIG_HEADER_C environment variable, or another source of enabled modules provided.");
println!("cargo:rerun-if-changed={riotbuildh}");

let mut defines = std::collections::HashMap::new();

use std::io::BufRead;
for line in std::io::BufReader::new(
std::fs::File::open(riotbuildh)
.expect("Failed to read riotbuild.h (RIOTBUILD_CONFIG_HEADER_C)"),
)
.lines()
{
let line = line.expect("Error reading line from riotbuild.h (RIOTBUILD_CONFIG_HEADER_C)");
if let Some(name) = line.strip_prefix("#undef ") {
defines.remove(name.trim());
}

if flag == "-DDEVELHELP" {
println!("cargo:rustc-cfg=riot_develhelp");
if let Some((name, val)) = line
.strip_prefix("#define ")
.and_then(|nv| nv.split_once(" "))
{
defines.insert(name.trim().to_owned(), val.trim().to_owned());
}
}

let bindgen_output_file = env::var("DEP_RIOT_SYS_BINDGEN_OUTPUT_FILE")
.expect("riot-sys did not provide BINDGEN_OUTPUT_FILE");

let bindgen_output =
std::fs::read_to_string(bindgen_output_file).expect("Failed to read BINDGEN_OUTPUT_FILE");

const BOOLEAN_FLAGS: &[&str] = &[
// This decides whether or not some fields are populated ... and unlike with other
// structs, the zeroed default is not a good solution here. (It'd kind of work, but
// it'd produce incorrect debug output).
"CONFIG_AUTO_INIT_ENABLE_DEBUG",
];

let parsed = syn::parse_file(&bindgen_output).expect("Failed to parse bindgen output");
for item in &parsed.items {
if let syn::Item::Const(const_) = item {
// It's the easiest way to get something we can `contains`...
let ident = const_.ident.to_string();
if BOOLEAN_FLAGS.contains(&ident.as_str()) {
if let syn::Expr::Lit(syn::ExprLit {
lit: syn::Lit::Int(litint),
..
}) = &*const_.expr
{
let value: usize = litint
.base10_parse()
.expect("Identifier is integer literal but not parsable");
if value != 0 {
println!("cargo:rustc-cfg=marker_{}", ident.to_lowercase());
}
continue;
}
panic!(
"Found {} but it's not the literal const it was expected to be",
ident
);
}
for (def, val) in defines {
if val != "1" {
// So far, only processing boolean flags
continue;
}
if let Some(module) = def.strip_prefix("MODULE_") {
// Some modules like cmsis-dsp_StatisticsFunctions have funny characters
println!(
"cargo:rustc-cfg=riot_module_{}",
module.to_lowercase().replace("-", "_")
);
}
if def == "DEVELHELP" {
println!("cargo:rustc-cfg=riot_develhelp");
}
if BOOLEAN_FLAGS.contains(&def.as_str()) {
println!("cargo:rustc-cfg=marker_{}", def.to_lowercase());
}
}
}

0 comments on commit 858274f

Please sign in to comment.