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

Commit a337e7f

Browse files
geofftalex
andcommitted
Remove kernel-cflags-finder (fixes #191)
The bulk of this is the changes from #185 that didn't make it into #188. We also upgrade Travis's Clang/LLVM version to 9 to pick up some sort of bugfix in relocation processing. With older versions, we get [ 1827.072410] module: x86/modules: Skipping invalid relocation target, existing value is nonzero for type 1, loc 00000000197e607d, val ffffffffc0703520 (where that "loc" seems to be random/garbage data, disconcertingly). Clang 9 is already required by kernels 5.0+ so this shouldn't be too much of a problem. Co-authored-by: Alex Gaynor <[email protected]>
1 parent 86a8004 commit a337e7f

File tree

10 files changed

+69
-110
lines changed

10 files changed

+69
-110
lines changed

.travis.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
matrix:
22
include:
3-
- dist: xenial
43
- dist: bionic
54

65
language: rust
@@ -13,10 +12,11 @@ branches:
1312

1413
install:
1514
- sudo apt-get install -y "linux-headers-$(uname -r)" coreutils
15+
- sudo apt-get install clang-9
1616
- rustup component add rust-src rustfmt clippy
1717

1818
script:
19-
- ./tests/run_tests.py
19+
- CLANG=clang-9 ./tests/run_tests.py
2020
- |
2121
for p in . hello-world tests/*; do
2222
if [ -d "$p" ]; then

README.md

+11-11
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,8 @@ various other examples in the tests/ directory.
1919
We run [bindgen](https://github.com/rust-lang/rust-bindgen) on the
2020
kernel headers to generate automatic Rust FFI bindings. bindgen is
2121
powered by [Clang](https://clang.llvm.org), so we use the kernel's
22-
own build system to determine the appropriate CFLAGS (see
23-
`kernel-cflags-finder`) and pass them to bindgen (see `build.rs`). Then we
24-
write safe bindings to these types (see the various files inside `src/`).
22+
own build system to determine the appropriate CFLAGS. Then we write safe
23+
bindings to these types (see the various files inside `src/`).
2524

2625
Each kernel module in Rust lives in a `staticlib` crate, which generates
2726
a `.a` file. We pass this object to the Linux kernel's own module build
@@ -46,14 +45,15 @@ for expected status.
4645
You'll need to have [Rust](https://www.rust-lang.org) - in particular
4746
Rust nightly, as we use [some unstable
4847
features](https://github.com/fishinabarrel/linux-kernel-module-rust/issues/41) -
49-
and [Clang](https://clang.llvm.org) installed. You need LLVM/Clang 3.9
50-
or higher [to bind constants
51-
properly](https://github.com/rust-lang/rust-bindgen/issues/1316). If
52-
you're running kernel 5.0 or newer, [you'll need Clang
53-
9](https://github.com/fishinabarrel/linux-kernel-module-rust/issues/123)
54-
(released September 2019), which adds support for `asm goto`.
55-
You may need to set the `CLANG` environment variable appropriately,
56-
e.g., `CLANG=clang-9`.
48+
and [Clang](https://clang.llvm.org) installed. You need LLVM/Clang 9
49+
(released September 2019) or higher for multiple reasons, primarily
50+
[support for `asm goto`]
51+
(https://github.com/fishinabarrel/linux-kernel-module-rust/issues/123).
52+
If you're on Debian, Ubuntu, or a derivative, https://apt.llvm.org is
53+
great.
54+
55+
If the binary named `clang` is too old, make sure to set the `CC` or
56+
`CLANG` environment variable appropriately, e.g., `CC=clang-9`.
5757

5858
## Building hello-world
5959

build.rs

+34-34
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use std::io::{BufRead, BufReader};
22
use std::path::PathBuf;
3-
use std::process::Command;
43
use std::{env, fs};
54

65
const INCLUDED_TYPES: &[&str] = &["file_system_type", "mode_t", "umode_t", "ctl_table"];
@@ -100,38 +99,39 @@ fn handle_kernel_symbols_cfg(symvers_path: &PathBuf) {
10099
}
101100
}
102101

103-
fn add_env_if_present(cmd: &mut Command, var: &str) {
104-
if let Ok(val) = env::var(var) {
105-
cmd.env(var, val);
102+
// Takes the CFLAGS from the kernel Makefile and changes all the include paths to be absolute
103+
// instead of relative.
104+
fn prepare_cflags(cflags: &str, kernel_dir: &str) -> Vec<String> {
105+
let cflag_parts = shlex::split(&cflags).unwrap();
106+
let mut cflag_iter = cflag_parts.iter();
107+
let mut kernel_args = vec![];
108+
while let Some(arg) = cflag_iter.next() {
109+
if arg.starts_with("-I") && !arg.starts_with("-I/") {
110+
kernel_args.push(format!("-I{}/{}", kernel_dir, &arg[2..]));
111+
} else if arg == "-include" {
112+
kernel_args.push(arg.to_string());
113+
let include_path = cflag_iter.next().unwrap();
114+
if include_path.starts_with("/") {
115+
kernel_args.push(include_path.to_string());
116+
} else {
117+
kernel_args.push(format!("{}/{}", kernel_dir, include_path));
118+
}
119+
} else {
120+
kernel_args.push(arg.to_string());
121+
}
106122
}
123+
kernel_args
107124
}
108125

109126
fn main() {
110-
println!("cargo:rerun-if-env-changed=KDIR");
111-
let kdir = env::var("KDIR").unwrap_or(format!(
112-
"/lib/modules/{}/build",
113-
std::str::from_utf8(&(Command::new("uname").arg("-r").output().unwrap().stdout))
114-
.unwrap()
115-
.trim()
116-
));
117-
118-
println!("cargo:rerun-if-env-changed=CLANG");
119-
println!("cargo:rerun-if-changed=kernel-cflags-finder/Makefile");
120-
let mut cmd = Command::new("make");
121-
cmd.arg("-C")
122-
.arg("kernel-cflags-finder")
123-
.arg("-s")
124-
.env_clear();
125-
add_env_if_present(&mut cmd, "KDIR");
126-
add_env_if_present(&mut cmd, "CLANG");
127-
add_env_if_present(&mut cmd, "PATH");
128-
let output = cmd.output().unwrap();
129-
if !output.status.success() {
130-
eprintln!("kernel-cflags-finder did not succeed");
131-
eprintln!("stdout: {}", std::str::from_utf8(&output.stdout).unwrap());
132-
eprintln!("stderr: {}", std::str::from_utf8(&output.stderr).unwrap());
133-
std::process::exit(1);
134-
}
127+
println!("cargo:rerun-if-env-changed=CC");
128+
println!("cargo:rerun-if-env-changed=abs_srctree");
129+
println!("cargo:rerun-if-env-changed=c_flags");
130+
131+
let kernel_dir = env::var("abs_srctree").expect("Must be invoked from kernel makefile");
132+
let kernel_cflags = env::var("c_flags").expect("Add 'export c_flags' to Kbuild");
133+
134+
let kernel_args = prepare_cflags(&kernel_cflags, &kernel_dir);
135135

136136
let target = env::var("TARGET").unwrap();
137137

@@ -143,8 +143,8 @@ fn main() {
143143
.rustfmt_bindings(true);
144144

145145
builder = builder.clang_arg(format!("--target={}", target));
146-
for arg in shlex::split(std::str::from_utf8(&output.stdout).unwrap()).unwrap() {
147-
builder = builder.clang_arg(arg.to_string());
146+
for arg in kernel_args.iter() {
147+
builder = builder.clang_arg(arg.clone());
148148
}
149149

150150
println!("cargo:rerun-if-changed=src/bindings_helper.h");
@@ -170,14 +170,14 @@ fn main() {
170170
.expect("Couldn't write bindings!");
171171

172172
handle_kernel_version_cfg(&out_path.join("bindings.rs"));
173-
handle_kernel_symbols_cfg(&PathBuf::from(&kdir).join("Module.symvers"));
173+
handle_kernel_symbols_cfg(&PathBuf::from(&kernel_dir).join("Module.symvers"));
174174

175175
let mut builder = cc::Build::new();
176-
builder.compiler(env::var("CLANG").unwrap_or_else(|_| "clang".to_string()));
176+
builder.compiler(env::var("CC").unwrap_or_else(|_| "clang".to_string()));
177177
builder.target(&target);
178178
builder.warnings(false);
179179
builder.file("src/helpers.c");
180-
for arg in shlex::split(std::str::from_utf8(&output.stdout).unwrap()).unwrap() {
180+
for arg in kernel_args.iter() {
181181
builder.flag(&arg);
182182
}
183183
builder.compile("helpers");

hello-world/Kbuild

+4-1
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@ helloworld-objs := hello_world.rust.o
33

44
CARGO ?= cargo
55

6+
export c_flags
7+
export abs_srctree ?= ${CURDIR}
8+
69
$(src)/target/x86_64-linux-kernel/debug/libhello_world.a: $(src)/Cargo.toml $(wildcard $(src)/src/*.rs)
7-
cd $(src); env -u MAKE -u MAKEFLAGS $(CARGO) build -Z build-std=core,alloc --target=x86_64-linux-kernel
10+
cd $(src); $(CARGO) build -Z build-std=core,alloc --target=x86_64-linux-kernel
811

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

hello-world/Makefile

+7-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
KDIR ?= /lib/modules/$(shell uname -r)/build
22

3+
CLANG ?= clang
4+
ifeq ($(origin CC),default)
5+
CC := ${CLANG}
6+
endif
7+
38
all:
4-
$(MAKE) -C $(KDIR) M=$(CURDIR)
9+
$(MAKE) -C $(KDIR) M=$(CURDIR) CC=$(CC) CONFIG_CC_IS_CLANG=y
510

611
clean:
7-
$(MAKE) -C $(KDIR) M=$(CURDIR) clean
12+
$(MAKE) -C $(KDIR) M=$(CURDIR) CC=$(CC) clean

kernel-cflags-finder/.gitignore

-12
This file was deleted.

kernel-cflags-finder/Makefile

-35
This file was deleted.

kernel-cflags-finder/README.md

-10
This file was deleted.

tests/Kbuild

+4-1
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@ testmodule-objs := $(TEST_NAME).rust.o
33

44
CARGO ?= cargo
55

6+
export c_flags
7+
export abs_srctree ?= ${CURDIR}
8+
69
$(src)/target/x86_64-linux-kernel/debug/lib%.a: $(src)/$(TEST_PATH)/Cargo.toml $(wildcard $(src)/$(TEST_PATH)/src/*.rs)
7-
cd $(src)/$(TEST_PATH); env -u MAKE -u MAKEFLAGS CARGO_TARGET_DIR=../target $(CARGO) build -Z build-std=core,alloc --target=x86_64-linux-kernel
10+
cd $(src)/$(TEST_PATH); CARGO_TARGET_DIR=../target $(CARGO) build -Z build-std=core,alloc --target=x86_64-linux-kernel
811

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

tests/Makefile

+7-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
KDIR ?= /lib/modules/$(shell uname -r)/build
22

3+
CLANG ?= clang
4+
ifeq ($(origin CC),default)
5+
CC := ${CLANG}
6+
endif
7+
38
all:
4-
$(MAKE) -C $(KDIR) M=$(CURDIR)
9+
$(MAKE) -C $(KDIR) M=$(CURDIR) CC=$(CC) CONFIG_CC_IS_CLANG=y
510

611
clean:
7-
$(MAKE) -C $(KDIR) M=$(CURDIR) clean
12+
$(MAKE) -C $(KDIR) M=$(CURDIR) CC=$(CC) clean

0 commit comments

Comments
 (0)