Skip to content
This repository was archived by the owner on Mar 7, 2021. It is now read-only.

Commit f50c385

Browse files
committed
Fixes #177 -- let the kernel build process drive cargo
1 parent 998c374 commit f50c385

File tree

8 files changed

+69
-105
lines changed

8 files changed

+69
-105
lines changed

README.md

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ environment variable appropriately, e.g., `CLANG=clang-9`.
5757

5858
## Building hello-world
5959

60-
1. Install clang, kernel headers, and the `rust-src` and `rustfmt` components from `rustup`:
60+
1. Install clang, kernel headers, and the `rust-src` and `rustfmt` components
61+
from `rustup`:
6162

6263
```
6364
apt-get install llvm clang linux-headers-"$(uname -r)" # or the equivalent for your OS
@@ -70,19 +71,14 @@ rustup component add --toolchain=nightly rust-src rustfmt
7071
cd hello-world
7172
```
7273

73-
3. Build the static object with cargo build, pointing it at our custom target
74-
75-
```
76-
cargo build -Z build-std=core,alloc --target x86_64-linux-kernel
77-
```
78-
79-
4. Build the kernel module using the Linux kernel build system (kbuild)
74+
3. Build the kernel module using the Linux kernel build system (kbuild), this
75+
will invoke `cargo` to build the Rust code
8076

8177
```
8278
make
8379
```
8480

85-
5. Load and unload the module!
81+
4. Load and unload the module!
8682

8783
```
8884
sudo insmod helloworld.ko

build.rs

Lines changed: 40 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -85,32 +85,56 @@ fn handle_kernel_version_cfg(bindings_path: &PathBuf) {
8585
}
8686
}
8787

88+
// Takes the CFLAGS from the kernel Makefile and changes all the include paths to be absolute
89+
// instead of relative.
90+
fn prepare_cflags(cflags: &str, kernel_dir: &str) -> Vec<String> {
91+
let cflag_parts = shlex::split(&cflags).unwrap();
92+
let mut cflag_iter = cflag_parts.iter();
93+
let mut kernel_args = vec![];
94+
while let Some(arg) = cflag_iter.next() {
95+
if arg.starts_with("-I") && !arg.starts_with("-I/") {
96+
kernel_args.push(format!("-I{}/{}", kernel_dir, &arg[2..]));
97+
} else if arg == "-include" {
98+
kernel_args.push(arg.to_string());
99+
let include_path = cflag_iter.next().unwrap();
100+
if include_path.starts_with("/") {
101+
kernel_args.push(include_path.to_string());
102+
} else {
103+
kernel_args.push(format!("{}/{}", kernel_dir, include_path));
104+
}
105+
} else {
106+
kernel_args.push(arg.to_string());
107+
}
108+
}
109+
return kernel_args;
110+
}
111+
88112
fn main() {
89113
println!("cargo:rerun-if-env-changed=KDIR");
90114
println!("cargo:rerun-if-env-changed=CLANG");
91-
println!("cargo:rerun-if-changed=kernel-cflags-finder/Makefile");
92-
let output = Command::new("make")
93-
.arg("-C")
94-
.arg("kernel-cflags-finder")
95-
.arg("-s")
96-
.output()
97-
.unwrap();
98-
if !output.status.success() {
99-
eprintln!("kernel-cflags-finder did not succeed");
100-
eprintln!("stdout: {}", std::str::from_utf8(&output.stdout).unwrap());
101-
eprintln!("stderr: {}", std::str::from_utf8(&output.stderr).unwrap());
102-
std::process::exit(1);
103-
}
115+
println!("cargo:rerun-if-env-changed=KERNEL_CLFAGS");
116+
117+
let kernel_cflags = env::var("KERNEL_CLFAGS").expect("Must be invoked from kernel makefile");
118+
let kernel_dir = env::var("KDIR").unwrap_or_else(|_| {
119+
format!(
120+
"/lib/modules/{}/build",
121+
std::str::from_utf8(&(Command::new("uname").arg("-r").output().unwrap().stdout))
122+
.unwrap()
123+
.trim()
124+
)
125+
});
126+
let kernel_args = prepare_cflags(&kernel_cflags, &kernel_dir);
104127

105128
let mut builder = bindgen::Builder::default()
106129
.use_core()
107130
.ctypes_prefix("c_types")
108131
.derive_default(true)
109132
.rustfmt_bindings(true);
110133

134+
// TODO: Support building for other kernel targets!
111135
builder = builder.clang_arg("--target=x86_64-linux-kernel");
112-
for arg in shlex::split(std::str::from_utf8(&output.stdout).unwrap()).unwrap() {
113-
builder = builder.clang_arg(arg.to_string());
136+
for arg in kernel_args.iter() {
137+
builder = builder.clang_arg(arg.clone());
114138
}
115139

116140
println!("cargo:rerun-if-changed=src/bindings_helper.h");
@@ -138,12 +162,11 @@ fn main() {
138162
handle_kernel_version_cfg(&out_path.join("bindings.rs"));
139163

140164
let mut builder = cc::Build::new();
141-
println!("cargo:rerun-if-env-changed=CLANG");
142165
builder.compiler(env::var("CLANG").unwrap_or("clang".to_string()));
143166
builder.target("x86_64-linux-kernel");
144167
builder.warnings(false);
145168
builder.file("src/helpers.c");
146-
for arg in shlex::split(std::str::from_utf8(&output.stdout).unwrap()).unwrap() {
169+
for arg in kernel_args.iter() {
147170
builder.flag(&arg);
148171
}
149172
builder.compile("helpers");

hello-world/Makefile

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,20 @@
1+
ifneq ($(KERNELRELEASE),)
12
obj-m := helloworld.o
23
helloworld-objs := hello_world.rust.o
3-
KDIR ?= /lib/modules/$(shell uname -r)/build
4+
5+
$(src)/target/x86_64-linux-kernel/debug/libhello_world.a: $(src)/Cargo.toml $(wildcard $(src)/src/*.c)
6+
cd $(src); env -u MAKE -u MAKEFLAGS KERNEL_CLFAGS="$(c_flags)" cargo build -Z build-std=core,alloc --target=x86_64-linux-kernel
47

58
%.rust.o: target/x86_64-linux-kernel/debug/lib%.a
69
$(LD) -r -o $@ --whole-archive $<
710

11+
else
12+
KDIR ?= /lib/modules/$(shell uname -r)/build
13+
CC ?= clang
14+
815
all:
9-
$(MAKE) -C $(KDIR) M=$(CURDIR)
16+
$(MAKE) -C $(KDIR) M=$(CURDIR) CC=$(CC)
1017

1118
clean:
12-
$(MAKE) -C $(KDIR) M=$(CURDIR) clean
19+
$(MAKE) -C $(KDIR) M=$(CURDIR) CC=$(CC) clean
20+
endif

kernel-cflags-finder/.gitignore

Lines changed: 0 additions & 13 deletions
This file was deleted.

kernel-cflags-finder/Makefile

Lines changed: 0 additions & 36 deletions
This file was deleted.

kernel-cflags-finder/README.md

Lines changed: 0 additions & 10 deletions
This file was deleted.

tests/Makefile

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,21 @@
1+
ifneq ($(KERNELRELEASE),)
12
obj-m := testmodule.o
23
testmodule-objs := $(TEST_NAME).rust.o
3-
KDIR ?= /lib/modules/$(shell uname -r)/build
4+
5+
$(src)/target/x86_64-linux-kernel/debug/lib%.a: $(src)/$(TEST_PATH)/Cargo.toml $(wildcard $(src)/$(TEST_PATH)/src/*.rs)
6+
cd $(src)/$(TEST_PATH); env -u MAKE -u MAKEFLAGS KERNEL_CLFAGS="$(c_flags)" RUSTFLAGS="-Dwarnings" CARGO_TARGET_DIR=../target cargo build -Z build-std=core,alloc --target=x86_64-linux-kernel
47

58
%.rust.o: target/x86_64-linux-kernel/debug/lib%.a
69
$(LD) -r -o $@ --whole-archive $<
710

11+
else
12+
KDIR ?= /lib/modules/$(shell uname -r)/build
13+
CC ?= clang
14+
815
all:
9-
$(MAKE) -C $(KDIR) M=$(CURDIR)
16+
@echo "CC=" $(CC)
17+
$(MAKE) -C $(KDIR) M=$(CURDIR) CC=$(CC)
1018

1119
clean:
12-
$(MAKE) -C $(KDIR) M=$(CURDIR) clean
20+
$(MAKE) -C $(KDIR) M=$(CURDIR) CC=$(CC) clean
21+
endif

tests/run_tests.py

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -25,24 +25,11 @@ def main():
2525
continue
2626

2727
print("+ [{}]".format(path))
28-
run(
29-
"cargo", "build", "-Zbuild-std=core,alloc",
30-
"--target", "x86_64-linux-kernel",
31-
cwd=os.path.join(BASE_DIR, path),
32-
environ=dict(
33-
os.environ,
34-
RUSTFLAGS="-Dwarnings",
35-
CARGO_TARGET_DIR=os.path.relpath(
36-
os.path.join(BASE_DIR, "target"),
37-
os.path.join(BASE_DIR, path)
38-
),
39-
XBUILD_SYSROOT_PATH=os.path.join(BASE_DIR, "target-sysroot"),
40-
)
41-
)
4228

4329
run(
4430
"make", "-C", BASE_DIR,
4531
"TEST_NAME={}_tests".format(path.replace("-", "_")),
32+
"TEST_PATH={}".format(path),
4633
)
4734
# TODO: qemu
4835
run(

0 commit comments

Comments
 (0)