diff options
Diffstat (limited to 'rust/kernel/build.rs')
-rw-r--r-- | rust/kernel/build.rs | 133 |
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!"); +} |