fishinabarrel / linux-kernel-module-rust

Framework for writing Linux kernel modules in safe Rust
GNU General Public License v2.0
1.33k stars 119 forks source link

Kbuild: Always rerun Cargo, trust Cargo to no-op if nothing changed #248

Closed geofft closed 4 years ago

geofft commented 4 years ago

This helps ensure a rebuild if build.rs, environment variables, Rust version, target, etc. changed, which weren't being picked up by the Make dependencies.

geofft commented 4 years ago

Short of getting things upstream? I don't have any great ideas, I think this largely boils down to the same problem as "how do I get a target.json out of linux-kernel-module-rust as a downstream user."

I could imagine a command that you cargo install that generates Kbuild. You'll still need a Makefile (and you always do for out-of-tree modules, but the minimal one is only slightly shorter than ours), but you could do something like

all: Kbuild
    ${MAKE} -C /lib/modules/...

Kbuild:
    linux-kernel-module-rust-kbuild-generator

but I don't really know how to make sure your version of that command matches the crate's dependency.

Maybe if it's a dev-dependency, you can run it on the host straight out of the crate's target?

Maybe we can do terrible things with build.rs?

all:
    GENERATE_KBUILD_FILE_ONLY=1 ${CARGO} build --no-default-features 2>&1 | grep -q "Kbuild generated successfully"
    ${make} -C /lib/modules/...
fn main() {
    if env::var("GENERATE_KBUILD_FILE_ONLY").is_some() {
        File::create("Kbuild").write_all(KBUILD_CONTENTS);
        eprintln!("Kbuild generated successfully");
        std::process::exit(1);
    }
    ...
}
geofft commented 4 years ago

Speaking of upstream, I'm not sure whether we want to do this upstream, but we might.

On a warm cache: make in helloworld with this change takes ~3 seconds on my machine before this patch and ~3.4 seconds with this patch (but the timings are very noisy). So it may be the case that this doesn't significantly add to build time.

geofft commented 4 years ago

OK, I think the terrible idea is likely to work.

If we go that route, you'll still want to write a Kbuild so you can set obj-m and mymodule-objs (just like if you were writing a C module), so maybe we tell users to

Kbuild.rust.mk:
    GENERATE_KBUILD_FILE_ONLY=1 ${CARGO} build etc.
.include Kbuild.rust.mk

We'll probably also want a configurable option to enable clippy in the generated file.