summaryrefslogtreecommitdiffstats
path: root/rust/kernel/build.rs
diff options
context:
space:
mode:
Diffstat (limited to 'rust/kernel/build.rs')
-rw-r--r--rust/kernel/build.rs133
1 files changed, 133 insertions, 0 deletions
diff --git a/rust/kernel/build.rs b/rust/kernel/build.rs
new file mode 100644
index 000000000000..b9085a6367b4
--- /dev/null
+++ b/rust/kernel/build.rs
@@ -0,0 +1,133 @@
+// SPDX-License-Identifier: GPL-2.0
+
+use std::path::PathBuf;
+use std::env;
+
+const INCLUDED_TYPES: &[&str] = &["file_system_type", "mode_t", "umode_t", "ctl_table"];
+const INCLUDED_FUNCTIONS: &[&str] = &[
+ "cdev_add",
+ "cdev_init",
+ "cdev_del",
+ "register_filesystem",
+ "unregister_filesystem",
+ "krealloc",
+ "kfree",
+ "mount_nodev",
+ "kill_litter_super",
+ "register_sysctl",
+ "unregister_sysctl_table",
+ "access_ok",
+ "_copy_to_user",
+ "_copy_from_user",
+ "alloc_chrdev_region",
+ "unregister_chrdev_region",
+ "wait_for_random_bytes",
+ "get_random_bytes",
+ "rng_is_initialized",
+ "printk",
+ "add_device_randomness",
+];
+const INCLUDED_VARS: &[&str] = &[
+ "EINVAL",
+ "ENOMEM",
+ "ESPIPE",
+ "EFAULT",
+ "EAGAIN",
+ "__this_module",
+ "FS_REQUIRES_DEV",
+ "FS_BINARY_MOUNTDATA",
+ "FS_HAS_SUBTYPE",
+ "FS_USERNS_MOUNT",
+ "FS_RENAME_DOES_D_MOVE",
+ "BINDINGS_GFP_KERNEL",
+ "KERN_INFO",
+ "VERIFY_WRITE",
+ "LINUX_VERSION_CODE",
+ "SEEK_SET",
+ "SEEK_CUR",
+ "SEEK_END",
+ "O_NONBLOCK",
+];
+const OPAQUE_TYPES: &[&str] = &[
+ // These need to be opaque because they're both packed and aligned, which rustc
+ // doesn't support yet. See https://github.com/rust-lang/rust/issues/59154
+ // and https://github.com/rust-lang/rust-bindgen/issues/1538
+ "desc_struct",
+ "xregs_state",
+];
+
+// Takes the CFLAGS from the kernel Makefile and changes all the include paths to be absolute
+// instead of relative.
+fn prepare_cflags(cflags: &str, kernel_dir: &str) -> Vec<String> {
+ let cflag_parts = shlex::split(&cflags).unwrap();
+ let mut cflag_iter = cflag_parts.iter();
+ let mut kernel_args = vec![];
+ while let Some(arg) = cflag_iter.next() {
+ // TODO: bindgen complains
+ if arg.starts_with("-Wp,-MMD") {
+ continue;
+ }
+
+ if arg.starts_with("-I") && !arg.starts_with("-I/") {
+ kernel_args.push(format!("-I{}/{}", kernel_dir, &arg[2..]));
+ } else if arg == "-include" {
+ kernel_args.push(arg.to_string());
+ let include_path = cflag_iter.next().unwrap();
+ if include_path.starts_with('/') {
+ kernel_args.push(include_path.to_string());
+ } else {
+ kernel_args.push(format!("{}/{}", kernel_dir, include_path));
+ }
+ } else {
+ kernel_args.push(arg.to_string());
+ }
+ }
+ kernel_args
+}
+
+fn main() {
+ println!("cargo:rerun-if-env-changed=CC");
+ println!("cargo:rerun-if-env-changed=RUST_BINDGEN_CFLAGS");
+
+ let kernel_dir = "../../";
+ let cflags = env::var("RUST_BINDGEN_CFLAGS")
+ .expect("Must be invoked from kernel makefile");
+
+ let kernel_args = prepare_cflags(&cflags, &kernel_dir);
+
+ let target = env::var("TARGET").unwrap();
+
+ let mut builder = bindgen::Builder::default()
+ .use_core()
+ .ctypes_prefix("c_types")
+ .derive_default(true)
+ .size_t_is_usize(true)
+ .rustfmt_bindings(true);
+
+ builder = builder.clang_arg(format!("--target={}", target));
+ for arg in kernel_args.iter() {
+ builder = builder.clang_arg(arg.clone());
+ }
+
+ println!("cargo:rerun-if-changed=src/bindings_helper.h");
+ builder = builder.header("src/bindings_helper.h");
+
+ for t in INCLUDED_TYPES {
+ builder = builder.whitelist_type(t);
+ }
+ for f in INCLUDED_FUNCTIONS {
+ builder = builder.whitelist_function(f);
+ }
+ for v in INCLUDED_VARS {
+ builder = builder.whitelist_var(v);
+ }
+ for t in OPAQUE_TYPES {
+ builder = builder.opaque_type(t);
+ }
+ let bindings = builder.generate().expect("Unable to generate bindings");
+
+ let out_path = PathBuf::from("src/bindings_gen.rs");
+ bindings
+ .write_to_file(out_path)
+ .expect("Couldn't write bindings!");
+}