Skip to content

Commit

Permalink
zephyr-build: Use parsed DT for both uses
Browse files Browse the repository at this point in the history
Instead of trying to hand off data through a file between the build of
different crates, which was causing build failures in applications that
need to use cfgs based on the presence of DT nodes, instead, just parse
the DT again, and recalculate the node tree from it.

This should fix build issues with the all nodes txt file missing.

Signed-off-by: David Brown <[email protected]>
  • Loading branch information
d3zd3z committed Nov 21, 2024
1 parent 669cae7 commit 7e8a847
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 30 deletions.
11 changes: 5 additions & 6 deletions zephyr-build/src/devicetree/output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,15 @@ impl DeviceTree {
self.node_walk(self.root.as_ref(), None, &augments)
}

/// Write to the given file a list of the path names of all of the nodes present in this
/// devicetree.
// Write, to the given writer, CFG lines so that Rust code can conditionalize based on the DT.
pub fn output_node_paths<W: Write>(&self, write: &mut W) -> Result<()> {
self.root.as_ref().output_path_walk(write, None)?;

// Also, output all of the labels. Technically, this depends on the labels augment being
// present.
writeln!(write, "labels")?;
writeln!(write, "cargo:rustc-cfg=dt=\"labels\"")?;
for label in self.labels.keys() {
writeln!(write, "labels::{}", fix_id(label))?;
writeln!(write, "cargo:rustc-cfg=dt=\"labels::{}\"", fix_id(label))?;
}
Ok(())
}
Expand Down Expand Up @@ -147,7 +146,7 @@ impl Node {
fixed_name
};

writeln!(write, "{}", child_name)?;
writeln!(write, "cargo:rustc-cfg=dt=\"{}\"", child_name)?;

for prop in &child.properties {
prop.output_path(write, &child_name)?;
Expand Down Expand Up @@ -175,7 +174,7 @@ impl Property {
fn output_path<W: Write>(&self, write: &mut W, name: &str) -> Result<()> {
if let Some(value) = self.get_single_value() {
if let Value::Phandle(_) = value {
writeln!(write, "{}::{}", name, self.name)?;
writeln!(write, "cargo:rustc-cfg=dt=\"{}::{}\"", name, fix_id(&self.name))?;
}
}
Ok(())
Expand Down
38 changes: 14 additions & 24 deletions zephyr-build/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,21 @@ pub fn build_kconfig_mod() {
}

/// Parse the finalized DTS file, generating the Rust devicetree file.
pub fn build_dts() {
fn import_dt() -> DeviceTree {
let zephyr_dts = env::var("ZEPHYR_DTS").expect("ZEPHYR_DTS must be set");
let outdir = env::var("OUT_DIR").expect("OUT_DIR must be set");
let gen_include = env::var("BINARY_DIR_INCLUDE_GENERATED")
.expect("BINARY_DIR_INCLUDE_GENERATED");
let builddir = env::var("BUILD_DIR").expect("BUILD_DIR");

let generated = format!("{}/devicetree_generated.h", gen_include);
DeviceTree::new(&zephyr_dts, generated)
}

pub fn build_dts() {
let dt = import_dt();

let outdir = env::var("OUT_DIR").expect("OUT_DIR must be set");
let out_path = Path::new(&outdir).join("devicetree.rs");
let mut out = File::create(&out_path).expect("Unable to create devicetree.rs");

let augments = env::var("DT_AUGMENTS").expect("DT_AUGMENTS must be set");
let augments: Vec<String> = augments.split_whitespace().map(String::from).collect();
Expand All @@ -110,40 +119,21 @@ pub fn build_dts() {
.map(|aug| Box::new(aug) as Box<dyn Augment>)
.collect();

let generated = format!("{}/devicetree_generated.h", gen_include);
let dt = DeviceTree::new(&zephyr_dts, generated);

let out_path = Path::new(&outdir).join("devicetree.rs");
let mut out = File::create(&out_path).expect("Unable to create devicetree.rs");

let tokens = dt.to_tokens(&augs);
if has_rustfmt() {
write_formatted(out, tokens);
} else {
writeln!(out, "{}", tokens).unwrap();
};

// Output all of the node names in the discovered tree.
let all_nodes_path = Path::new(&builddir)
.join("rust")
.join("all-dt-nodes.txt");
let mut out = File::create(&all_nodes_path).expect("Unable to create all-dt-nodex.txt");
dt.output_node_paths(&mut out).expect("Unable to write to all-dt-nodes.txt");
}

/// Generate cfg directives for each of the nodes in the generated device tree.
///
/// This assumes that build_dts was already run by the `zephyr` crate, which should happen if this
/// is called from a user application.
pub fn dt_cfgs() {
let builddir = env::var("BUILD_DIR").expect("BUILD_DIR");
let path = Path::new(&builddir)
.join("rust")
.join("all-dt-nodes.txt");
for line in BufReader::new(File::open(&path).expect("Unable to open all-dt-nodes")).lines() {
let line = line.expect("Error reading line from all-dt-nodes");
println!("cargo:rustc-cfg=dt=\"{}\"", line);
}
let dt = import_dt();
dt.output_node_paths(&mut std::io::stdout()).unwrap();
}

/// Determine if `rustfmt` is in the path, and can be excecuted. Returns false on any kind of error.
Expand Down

0 comments on commit 7e8a847

Please sign in to comment.