|
| 1 | +// Copyright (c) 2024 Linaro LTD |
| 2 | +// SPDX-License-Identifier: Apache-2.0 |
| 3 | + |
| 4 | +// Pre-build code for zephyr module. |
| 5 | + |
| 6 | +// This module makes the values from the generated .config available as conditional compilation. |
| 7 | +// Note that this only applies to the zephyr module, and the user's application will not be able to |
| 8 | +// see these definitions. To make that work, this will need to be moved into a support crate which |
| 9 | +// can be invoked by the user's build.rs. |
| 10 | + |
| 11 | +// This builds a program that is run on the compilation host before the code is compiled. It can |
| 12 | +// output configuration settings that affect the compilation. |
| 13 | + |
| 14 | +use std::io::{BufRead, BufReader, Write}; |
| 15 | +use std::env; |
| 16 | +use std::fs::File; |
| 17 | +use std::path::Path; |
| 18 | + |
| 19 | +use regex::Regex; |
| 20 | + |
| 21 | +/// Export boolean Kconfig entries. This must happen in any crate that wishes to access the |
| 22 | +/// configuration settings. |
| 23 | +pub fn export_bool_kconfig() { |
| 24 | + let dotconfig = env::var("DOTCONFIG").expect("DOTCONFIG must be set by wrapper"); |
| 25 | + |
| 26 | + // Ensure the build script is rerun when the dotconfig changes. |
| 27 | + println!("cargo:rerun-if-env-changed=DOTCONFIG"); |
| 28 | + println!("cargo-rerun-if-changed={}", dotconfig); |
| 29 | + |
| 30 | + let config_y = Regex::new(r"^(CONFIG_.*)=y$").unwrap(); |
| 31 | + |
| 32 | + let file = File::open(&dotconfig).expect("Unable to open dotconfig"); |
| 33 | + for line in BufReader::new(file).lines() { |
| 34 | + let line = line.expect("reading line from dotconfig"); |
| 35 | + if let Some(caps) = config_y.captures(&line) { |
| 36 | + println!("cargo:rustc-cfg={}", &caps[1]); |
| 37 | + } |
| 38 | + } |
| 39 | +} |
| 40 | + |
| 41 | +/// Capture bool, numeric and string kconfig values in a 'kconfig' module. |
| 42 | +/// This is a little simplistic, and will make the entries numeric if they look like numbers. |
| 43 | +/// Ideally, this would be built on the types of the values, but that will require more |
| 44 | +/// introspection. |
| 45 | +pub fn build_kconfig_mod() { |
| 46 | + let dotconfig = env::var("DOTCONFIG").expect("DOTCONFIG must be set by wrapper"); |
| 47 | + let outdir = env::var("OUT_DIR").expect("OUT_DIR must be set"); |
| 48 | + |
| 49 | + // The assumption is that hex values are unsigned, and decimal are signed. |
| 50 | + let config_hex = Regex::new(r"^(CONFIG_.*)=(0x[0-9a-fA-F]+)$").unwrap(); |
| 51 | + let config_int = Regex::new(r"^(CONFIG_.*)=(-?[1-9][0-9]*)$").unwrap(); |
| 52 | + // It is unclear what quoting might be used in the .config. |
| 53 | + let config_str = Regex::new(r#"^(CONFIG_.*)=(".*")$"#).unwrap(); |
| 54 | + let gen_path = Path::new(&outdir).join("kconfig.rs"); |
| 55 | + |
| 56 | + let mut f = File::create(&gen_path).unwrap(); |
| 57 | + writeln!(&mut f, "pub mod kconfig {{").unwrap(); |
| 58 | + |
| 59 | + let file = File::open(&dotconfig).expect("Unable to open dotconfig"); |
| 60 | + for line in BufReader::new(file).lines() { |
| 61 | + let line = line.expect("reading line from dotconfig"); |
| 62 | + if let Some(caps) = config_hex.captures(&line) { |
| 63 | + writeln!(&mut f, " #[allow(dead_code)]").unwrap(); |
| 64 | + writeln!(&mut f, " pub const {}: usize = {};", |
| 65 | + &caps[1], &caps[2]).unwrap(); |
| 66 | + } else if let Some(caps) = config_int.captures(&line) { |
| 67 | + writeln!(&mut f, " #[allow(dead_code)]").unwrap(); |
| 68 | + writeln!(&mut f, " pub const {}: isize = {};", |
| 69 | + &caps[1], &caps[2]).unwrap(); |
| 70 | + } else if let Some(caps) = config_str.captures(&line) { |
| 71 | + writeln!(&mut f, " #[allow(dead_code)]").unwrap(); |
| 72 | + writeln!(&mut f, " pub const {}: &'static str = {};", |
| 73 | + &caps[1], &caps[2]).unwrap(); |
| 74 | + } |
| 75 | + } |
| 76 | + writeln!(&mut f, "}}").unwrap(); |
| 77 | +} |
0 commit comments