Skip to content

Commit f806a3f

Browse files
committed
rust: Create zephyr-sys for low-level bindings
With a lot of work done by Mario Jaun <[email protected]>. Use the rust-bindgen tool to extract bindings from the Zephyr header files. The tool is run with the exact configuration of the current build, and therefore the bindings will match the current target. The ifdefs and such are not translated into the Rust code, and this must be generated live for each build. Signed-off-by: David Brown <[email protected]>
1 parent 4dd43ca commit f806a3f

File tree

4 files changed

+130
-0
lines changed

4 files changed

+130
-0
lines changed

lib/rust/zephyr-sys/Cargo.toml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Copyright (c) 2024 Linaro LTD
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
[package]
5+
name = "zephyr-sys"
6+
version = "0.1.0"
7+
edition = "2021"
8+
description = """
9+
Zephyr low-level API bindings.
10+
"""
11+
12+
# These are needed at build time.
13+
# Whether these need to be vendored is an open question. They are not
14+
# used by the core Zephyr tree, but are needed by zephyr applications.
15+
[build-dependencies]
16+
anyhow = "1.0"
17+
bindgen = { version = "0.69.4", features = ["experimental"] }
18+
# zephyr-build = { version = "0.1.0", path = "../zephyr-build" }

lib/rust/zephyr-sys/build.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
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 anyhow::Result;
15+
16+
use bindgen::Builder;
17+
18+
use std::env;
19+
use std::path::PathBuf;
20+
21+
fn main() -> Result<()> {
22+
// Pass in the target used to build the native code.
23+
let target_arg = format!("--target={}", env::var("TARGET")?);
24+
25+
// println!("includes: {:?}", env::var("INCLUDE_DIRS"));
26+
// println!("defines: {:?}", env::var("INCLUDE_DEFINES"));
27+
28+
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
29+
let wrapper_path = PathBuf::from(env::var("WRAPPER_FILE").unwrap());
30+
31+
// Bindgen everything.
32+
let bindings = Builder::default()
33+
.header("wrapper.h")
34+
.use_core()
35+
.clang_arg(&target_arg);
36+
let bindings = define_args(bindings, "-I", "INCLUDE_DIRS");
37+
let bindings = define_args(bindings, "-D", "INCLUDE_DEFINES");
38+
let bindings = bindings
39+
.wrap_static_fns(true)
40+
.wrap_static_fns_path(wrapper_path)
41+
// <inttypes.h> seems to come from somewhere mysterious in Zephyr. For us, just pull in the
42+
// one from the minimal libc.
43+
.clang_arg("-DRUST_BINDGEN")
44+
.clang_arg("-I../../../lib/libc/minimal/include")
45+
.derive_copy(false)
46+
.allowlist_function("k_.*")
47+
.allowlist_function("gpio_.*")
48+
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
49+
.generate()
50+
.expect("Unable to generate bindings");
51+
52+
bindings
53+
.write_to_file(out_path.join("bindings.rs"))
54+
.expect("Couldn't write bindings!");
55+
56+
Ok(())
57+
}
58+
59+
fn define_args(bindings: Builder, prefix: &str, var_name: &str) -> Builder {
60+
let text = env::var(var_name).unwrap();
61+
let mut bindings = bindings;
62+
for entry in text.split(" ") {
63+
if entry.is_empty() {
64+
continue;
65+
}
66+
println!("Entry: {}{}", prefix, entry);
67+
let arg = format!("{}{}", prefix, entry);
68+
bindings = bindings.clang_arg(arg);
69+
}
70+
bindings
71+
}

lib/rust/zephyr-sys/src/lib.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright (c) 2024 Linaro LTD
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
//! Zephyr application support for Rust
5+
//!
6+
//! This crates provides the core functionality for applications written in Rust that run on top of
7+
//! Zephyr.
8+
9+
#![no_std]
10+
11+
// Allow rust naming convention violations.
12+
#![allow(non_snake_case)]
13+
#![allow(non_upper_case_globals)]
14+
#![allow(non_camel_case_types)]
15+
16+
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));

lib/rust/zephyr-sys/wrapper.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Copyright (c) 2024 Linaro LTD
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
/*
8+
* This file is the seed point for bindgen. This determines every header that will be visited for
9+
* binding generation. It should include any Zephyr headers we need bindings for. The driver in
10+
* build.rs will also select which functions need generation, which will determine the types that
11+
* are output.
12+
*/
13+
14+
#ifdef RUST_BINDGEN
15+
/* errno is coming from somewhere in Zephyr's build. Add the symbol when running bindgen so that it
16+
* is defined here.
17+
*/
18+
extern int errno;
19+
#endif
20+
21+
/* First, make sure we have all of our config settings. */
22+
#include <zephyr/autoconf.h>
23+
24+
#include <zephyr/kernel.h>
25+
#include <zephyr/drivers/gpio.h>

0 commit comments

Comments
 (0)