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

Remove kernel-cflags-finder (fixes #191) #236

Merged
merged 1 commit into from
Aug 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
matrix:
include:
- dist: xenial
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't have clang-9 in repo, and it uses the same kernel anyway (see #229). If we think it's valuable I can use apt.llvm.org

- dist: bionic

language: rust
Expand All @@ -13,10 +12,11 @@ branches:

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

script:
- ./tests/run_tests.py
- CLANG=clang-9 ./tests/run_tests.py
- |
for p in . hello-world tests/*; do
if [ -d "$p" ]; then
Expand Down
22 changes: 11 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,8 @@ various other examples in the tests/ directory.
We run [bindgen](https://github.com/rust-lang/rust-bindgen) on the
kernel headers to generate automatic Rust FFI bindings. bindgen is
powered by [Clang](https://clang.llvm.org), so we use the kernel's
own build system to determine the appropriate CFLAGS (see
`kernel-cflags-finder`) and pass them to bindgen (see `build.rs`). Then we
write safe bindings to these types (see the various files inside `src/`).
own build system to determine the appropriate CFLAGS. Then we write safe
bindings to these types (see the various files inside `src/`).

Each kernel module in Rust lives in a `staticlib` crate, which generates
a `.a` file. We pass this object to the Linux kernel's own module build
Expand Down Expand Up @@ -50,14 +49,15 @@ for expected status. They'll need src/c_types.rs ported, too.
You'll need to have [Rust](https://www.rust-lang.org) - in particular
Rust nightly, as we use [some unstable
features](https://github.com/fishinabarrel/linux-kernel-module-rust/issues/41) -
and [Clang](https://clang.llvm.org) installed. You need LLVM/Clang 3.9
or higher [to bind constants
properly](https://github.com/rust-lang/rust-bindgen/issues/1316). If
you're running kernel 5.0 or newer, [you'll need Clang
9](https://github.com/fishinabarrel/linux-kernel-module-rust/issues/123)
(released September 2019), which adds support for `asm goto`.
You may need to set the `CLANG` environment variable appropriately,
e.g., `CLANG=clang-9`.
and [Clang](https://clang.llvm.org) installed. You need LLVM/Clang 9
(released September 2019) or higher for multiple reasons, primarily
[support for `asm goto`]
(https://github.com/fishinabarrel/linux-kernel-module-rust/issues/123).
If you're on Debian, Ubuntu, or a derivative, https://apt.llvm.org is
great.

If the binary named `clang` is too old, make sure to set the `CC` or
`CLANG` environment variable appropriately, e.g., `CC=clang-9`.

Very recent kernels may require newer versions of Clang - try Clang 11
if older versions don't work for you.
Expand Down
68 changes: 34 additions & 34 deletions build.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use std::io::{BufRead, BufReader};
use std::path::PathBuf;
use std::process::Command;
use std::{env, fs};

const INCLUDED_TYPES: &[&str] = &["file_system_type", "mode_t", "umode_t", "ctl_table"];
Expand Down Expand Up @@ -112,38 +111,39 @@ fn handle_kernel_symbols_cfg(symvers_path: &PathBuf) {
}
}

fn add_env_if_present(cmd: &mut Command, var: &str) {
if let Ok(val) = env::var(var) {
cmd.env(var, val);
// 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() {
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=KDIR");
let kdir = env::var("KDIR").unwrap_or(format!(
"/lib/modules/{}/build",
std::str::from_utf8(&(Command::new("uname").arg("-r").output().unwrap().stdout))
.unwrap()
.trim()
));

println!("cargo:rerun-if-env-changed=CLANG");
println!("cargo:rerun-if-changed=kernel-cflags-finder/Makefile");
let mut cmd = Command::new("make");
cmd.arg("-C")
.arg("kernel-cflags-finder")
.arg("-s")
.env_clear();
add_env_if_present(&mut cmd, "KDIR");
add_env_if_present(&mut cmd, "CLANG");
add_env_if_present(&mut cmd, "PATH");
let output = cmd.output().unwrap();
if !output.status.success() {
eprintln!("kernel-cflags-finder did not succeed");
eprintln!("stdout: {}", std::str::from_utf8(&output.stdout).unwrap());
eprintln!("stderr: {}", std::str::from_utf8(&output.stderr).unwrap());
std::process::exit(1);
}
println!("cargo:rerun-if-env-changed=CC");
println!("cargo:rerun-if-env-changed=abs_srctree");
println!("cargo:rerun-if-env-changed=c_flags");

let kernel_dir = env::var("abs_srctree").expect("Must be invoked from kernel makefile");
let kernel_cflags = env::var("c_flags").expect("Add 'export c_flags' to Kbuild");

let kernel_args = prepare_cflags(&kernel_cflags, &kernel_dir);

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

Expand All @@ -155,8 +155,8 @@ fn main() {
.rustfmt_bindings(true);

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

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

handle_kernel_version_cfg(&out_path.join("bindings.rs"));
handle_kernel_symbols_cfg(&PathBuf::from(&kdir).join("Module.symvers"));
handle_kernel_symbols_cfg(&PathBuf::from(&kernel_dir).join("Module.symvers"));

let mut builder = cc::Build::new();
builder.compiler(env::var("CLANG").unwrap_or_else(|_| "clang".to_string()));
builder.compiler(env::var("CC").unwrap_or_else(|_| "clang".to_string()));
builder.target(&target);
builder.warnings(false);
builder.file("src/helpers.c");
for arg in shlex::split(std::str::from_utf8(&output.stdout).unwrap()).unwrap() {
for arg in kernel_args.iter() {
builder.flag(&arg);
}
builder.compile("helpers");
Expand Down
3 changes: 3 additions & 0 deletions hello-world/Kbuild
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ helloworld-objs := hello_world.rust.o

CARGO ?= cargo

export c_flags
export abs_srctree ?= ${CURDIR}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is exported by v5.2+ (torvalds/linux@25b146c) but it's pretty easy to keep compatibility with older ones.


$(src)/target/x86_64-linux-kernel/debug/libhello_world.a: $(src)/Cargo.toml $(wildcard $(src)/src/*.rs)
cd $(src); $(CARGO) build -Z build-std=core,alloc --target=x86_64-linux-kernel

Expand Down
9 changes: 7 additions & 2 deletions hello-world/Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
KDIR ?= /lib/modules/$(shell uname -r)/build

CLANG ?= clang
ifeq ($(origin CC),default)
CC := ${CLANG}
endif

all:
$(MAKE) -C $(KDIR) M=$(CURDIR)
$(MAKE) -C $(KDIR) M=$(CURDIR) CC=$(CC) CONFIG_CC_IS_CLANG=y

clean:
$(MAKE) -C $(KDIR) M=$(CURDIR) clean
$(MAKE) -C $(KDIR) M=$(CURDIR) CC=$(CC) clean
12 changes: 0 additions & 12 deletions kernel-cflags-finder/.gitignore

This file was deleted.

35 changes: 0 additions & 35 deletions kernel-cflags-finder/Makefile

This file was deleted.

10 changes: 0 additions & 10 deletions kernel-cflags-finder/README.md

This file was deleted.

3 changes: 3 additions & 0 deletions tests/Kbuild
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ testmodule-objs := $(TEST_NAME).rust.o

CARGO ?= cargo

export c_flags
export abs_srctree ?= ${CURDIR}

$(src)/target/x86_64-linux-kernel/debug/lib%.a: $(src)/$(TEST_PATH)/Cargo.toml $(wildcard $(src)/$(TEST_PATH)/src/*.rs)
cd $(src)/$(TEST_PATH); CARGO_TARGET_DIR=../target $(CARGO) build -Z build-std=core,alloc --target=x86_64-linux-kernel
cd $(src)/$(TEST_PATH); CARGO_TARGET_DIR=../target $(CARGO) clippy -Z build-std=core,alloc --target=x86_64-linux-kernel -- -Dwarnings
Expand Down
9 changes: 7 additions & 2 deletions tests/Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
KDIR ?= /lib/modules/$(shell uname -r)/build

CLANG ?= clang
ifeq ($(origin CC),default)
CC := ${CLANG}
endif

all:
$(MAKE) -C $(KDIR) M=$(CURDIR)
$(MAKE) -C $(KDIR) M=$(CURDIR) CC=$(CC) CONFIG_CC_IS_CLANG=y

clean:
$(MAKE) -C $(KDIR) M=$(CURDIR) clean
$(MAKE) -C $(KDIR) M=$(CURDIR) CC=$(CC) clean