Skip to content

Commit

Permalink
Merge pull request torvalds#692 from ojeda/hostprogs
Browse files Browse the repository at this point in the history
kbuild: support host programs written in Rust
  • Loading branch information
ojeda authored Mar 3, 2022
2 parents 4fc14d4 + 046d82f commit 78e2b26
Show file tree
Hide file tree
Showing 26 changed files with 141 additions and 21 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -405,5 +405,8 @@ jobs:
grep -F '.text' ${{ env.BUILD_DIR }}samples/rust/rust_minimal.s
grep -F '; ModuleID' ${{ env.BUILD_DIR }}samples/rust/rust_minimal.ll
# Rust host programs
- run: ${{ env.BUILD_DIR }}samples/rust/hostprogs/single | grep -F 'The number is 42.'

# View changes to ccache
- run: ccache -s
1 change: 1 addition & 0 deletions .github/workflows/kernel-arm-debug.config
Original file line number Diff line number Diff line change
Expand Up @@ -1780,6 +1780,7 @@ CONFIG_SAMPLE_RUST_STACK_PROBING=m
CONFIG_SAMPLE_RUST_SEMAPHORE=m
CONFIG_SAMPLE_RUST_SEMAPHORE_C=m
CONFIG_SAMPLE_RUST_RANDOM=m
CONFIG_SAMPLE_RUST_HOSTPROGS=y
# CONFIG_STRICT_DEVMEM is not set

#
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/kernel-arm-release.config
Original file line number Diff line number Diff line change
Expand Up @@ -1704,6 +1704,7 @@ CONFIG_SAMPLE_RUST_STACK_PROBING=m
CONFIG_SAMPLE_RUST_SEMAPHORE=m
CONFIG_SAMPLE_RUST_SEMAPHORE_C=m
CONFIG_SAMPLE_RUST_RANDOM=m
CONFIG_SAMPLE_RUST_HOSTPROGS=y
# CONFIG_STRICT_DEVMEM is not set

#
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/kernel-arm64-debug-thinlto.config
Original file line number Diff line number Diff line change
Expand Up @@ -1437,6 +1437,7 @@ CONFIG_SAMPLE_RUST_STACK_PROBING=m
CONFIG_SAMPLE_RUST_SEMAPHORE=m
CONFIG_SAMPLE_RUST_SEMAPHORE_C=m
CONFIG_SAMPLE_RUST_RANDOM=m
CONFIG_SAMPLE_RUST_HOSTPROGS=y

#
# arm64 Debugging
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/kernel-arm64-debug.config
Original file line number Diff line number Diff line change
Expand Up @@ -1432,6 +1432,7 @@ CONFIG_SAMPLE_RUST_STACK_PROBING=m
CONFIG_SAMPLE_RUST_SEMAPHORE=m
CONFIG_SAMPLE_RUST_SEMAPHORE_C=m
CONFIG_SAMPLE_RUST_RANDOM=m
CONFIG_SAMPLE_RUST_HOSTPROGS=y

#
# arm64 Debugging
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/kernel-arm64-release-thinlto.config
Original file line number Diff line number Diff line change
Expand Up @@ -1355,6 +1355,7 @@ CONFIG_SAMPLE_RUST_STACK_PROBING=m
CONFIG_SAMPLE_RUST_SEMAPHORE=m
CONFIG_SAMPLE_RUST_SEMAPHORE_C=m
CONFIG_SAMPLE_RUST_RANDOM=m
CONFIG_SAMPLE_RUST_HOSTPROGS=y

#
# arm64 Debugging
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/kernel-arm64-release.config
Original file line number Diff line number Diff line change
Expand Up @@ -1350,6 +1350,7 @@ CONFIG_SAMPLE_RUST_STACK_PROBING=m
CONFIG_SAMPLE_RUST_SEMAPHORE=m
CONFIG_SAMPLE_RUST_SEMAPHORE_C=m
CONFIG_SAMPLE_RUST_RANDOM=m
CONFIG_SAMPLE_RUST_HOSTPROGS=y

#
# arm64 Debugging
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/kernel-ppc64le-debug.config
Original file line number Diff line number Diff line change
Expand Up @@ -1492,6 +1492,7 @@ CONFIG_SAMPLE_RUST_STACK_PROBING=m
CONFIG_SAMPLE_RUST_SEMAPHORE=m
CONFIG_SAMPLE_RUST_SEMAPHORE_C=m
CONFIG_SAMPLE_RUST_RANDOM=m
CONFIG_SAMPLE_RUST_HOSTPROGS=y
CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y
# CONFIG_STRICT_DEVMEM is not set

Expand Down
1 change: 1 addition & 0 deletions .github/workflows/kernel-ppc64le-release.config
Original file line number Diff line number Diff line change
Expand Up @@ -1454,6 +1454,7 @@ CONFIG_SAMPLE_RUST_STACK_PROBING=m
CONFIG_SAMPLE_RUST_SEMAPHORE=m
CONFIG_SAMPLE_RUST_SEMAPHORE_C=m
CONFIG_SAMPLE_RUST_RANDOM=m
CONFIG_SAMPLE_RUST_HOSTPROGS=y
CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y
# CONFIG_STRICT_DEVMEM is not set

Expand Down
1 change: 1 addition & 0 deletions .github/workflows/kernel-riscv64-debug.config
Original file line number Diff line number Diff line change
Expand Up @@ -1286,6 +1286,7 @@ CONFIG_SAMPLE_RUST_STACK_PROBING=m
CONFIG_SAMPLE_RUST_SEMAPHORE=m
CONFIG_SAMPLE_RUST_SEMAPHORE_C=m
CONFIG_SAMPLE_RUST_RANDOM=m
CONFIG_SAMPLE_RUST_HOSTPROGS=y
# CONFIG_STRICT_DEVMEM is not set

#
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/kernel-riscv64-release.config
Original file line number Diff line number Diff line change
Expand Up @@ -1202,6 +1202,7 @@ CONFIG_SAMPLE_RUST_STACK_PROBING=m
CONFIG_SAMPLE_RUST_SEMAPHORE=m
CONFIG_SAMPLE_RUST_SEMAPHORE_C=m
CONFIG_SAMPLE_RUST_RANDOM=m
CONFIG_SAMPLE_RUST_HOSTPROGS=y
# CONFIG_STRICT_DEVMEM is not set

#
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/kernel-x86_64-debug-thinlto.config
Original file line number Diff line number Diff line change
Expand Up @@ -1441,6 +1441,7 @@ CONFIG_SAMPLE_RUST_STACK_PROBING=m
CONFIG_SAMPLE_RUST_SEMAPHORE=m
CONFIG_SAMPLE_RUST_SEMAPHORE_C=m
CONFIG_SAMPLE_RUST_RANDOM=m
CONFIG_SAMPLE_RUST_HOSTPROGS=y
CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y
# CONFIG_STRICT_DEVMEM is not set

Expand Down
1 change: 1 addition & 0 deletions .github/workflows/kernel-x86_64-debug.config
Original file line number Diff line number Diff line change
Expand Up @@ -1444,6 +1444,7 @@ CONFIG_SAMPLE_RUST_STACK_PROBING=m
CONFIG_SAMPLE_RUST_SEMAPHORE=m
CONFIG_SAMPLE_RUST_SEMAPHORE_C=m
CONFIG_SAMPLE_RUST_RANDOM=m
CONFIG_SAMPLE_RUST_HOSTPROGS=y
CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y
# CONFIG_STRICT_DEVMEM is not set

Expand Down
1 change: 1 addition & 0 deletions .github/workflows/kernel-x86_64-release-thinlto.config
Original file line number Diff line number Diff line change
Expand Up @@ -1397,6 +1397,7 @@ CONFIG_SAMPLE_RUST_STACK_PROBING=m
CONFIG_SAMPLE_RUST_SEMAPHORE=m
CONFIG_SAMPLE_RUST_SEMAPHORE_C=m
CONFIG_SAMPLE_RUST_RANDOM=m
CONFIG_SAMPLE_RUST_HOSTPROGS=y
CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y
# CONFIG_STRICT_DEVMEM is not set

Expand Down
1 change: 1 addition & 0 deletions .github/workflows/kernel-x86_64-release.config
Original file line number Diff line number Diff line change
Expand Up @@ -1392,6 +1392,7 @@ CONFIG_SAMPLE_RUST_STACK_PROBING=m
CONFIG_SAMPLE_RUST_SEMAPHORE=m
CONFIG_SAMPLE_RUST_SEMAPHORE_C=m
CONFIG_SAMPLE_RUST_RANDOM=m
CONFIG_SAMPLE_RUST_HOSTPROGS=y
CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y
# CONFIG_STRICT_DEVMEM is not set

Expand Down
4 changes: 4 additions & 0 deletions Documentation/kbuild/kbuild.rst
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ HOSTCXXFLAGS
------------
Additional flags to be passed to $(HOSTCXX) when building host programs.

HOSTRUSTFLAGS
-------------
Additional flags to be passed to $(HOSTRUSTC) when building host programs.

HOSTLDFLAGS
-----------
Additional flags to be passed when linking host programs.
Expand Down
26 changes: 22 additions & 4 deletions Documentation/kbuild/makefiles.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@ This document describes the Linux kernel Makefiles.
--- 4.1 Simple Host Program
--- 4.2 Composite Host Programs
--- 4.3 Using C++ for host programs
--- 4.4 Controlling compiler options for host programs
--- 4.5 When host programs are actually built
--- 4.4 Using Rust for host programs
--- 4.5 Controlling compiler options for host programs
--- 4.6 When host programs are actually built
=== 5 Userspace Program support
--- 5.1 Simple Userspace Program
Expand Down Expand Up @@ -835,7 +836,24 @@ Both possibilities are described in the following.
qconf-cxxobjs := qconf.o
qconf-objs := check.o

4.4 Controlling compiler options for host programs
4.4 Using Rust for host programs
--------------------------------

Kbuild offers support for host programs written in Rust. However,
since a Rust toolchain is not mandatory for kernel compilation,
it may only be used in scenarios where Rust is required to be
available (e.g. when ``CONFIG_RUST`` is enabled).

Example::

hostprogs := target
target-rust := y

Kbuild will compile ``target`` using ``target.rs`` as the crate root,
located in the same directory as the ``Makefile``. The crate may
consist of several source files (see ``samples/rust/hostprogs``).

4.5 Controlling compiler options for host programs
--------------------------------------------------

When compiling host programs, it is possible to set specific flags.
Expand Down Expand Up @@ -867,7 +885,7 @@ Both possibilities are described in the following.
When linking qconf, it will be passed the extra option
"-L$(QTDIR)/lib".

4.5 When host programs are actually built
4.6 When host programs are actually built
-----------------------------------------

Kbuild will only build host-programs when they are referenced
Expand Down
40 changes: 26 additions & 14 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -437,13 +437,32 @@ else
HOSTCC = gcc
HOSTCXX = g++
endif
HOSTRUSTC = rustc

export KBUILD_USERCFLAGS := -Wall -Wmissing-prototypes -Wstrict-prototypes \
-O2 -fomit-frame-pointer -std=gnu89
export KBUILD_USERLDFLAGS :=

# These flags apply to all Rust code in the tree, including the kernel and
# host programs.
rust_common_flags := --edition=2021 \
-Zbinary_dep_depinfo=y \
-Dunsafe_op_in_unsafe_fn -Drust_2018_idioms \
-Dunreachable_pub -Dnon_ascii_idents \
-Wmissing_docs \
-Drustdoc::missing_crate_level_docs \
-Dclippy::correctness -Dclippy::style \
-Dclippy::suspicious -Dclippy::complexity \
-Dclippy::perf \
-Dclippy::let_unit_value -Dclippy::mut_mut \
-Dclippy::needless_bitwise_bool \
-Dclippy::needless_continue \
-Wclippy::dbg_macro

KBUILD_HOSTCFLAGS := $(KBUILD_USERCFLAGS) $(HOST_LFS_CFLAGS) $(HOSTCFLAGS)
KBUILD_HOSTCXXFLAGS := -Wall -O2 $(HOST_LFS_CFLAGS) $(HOSTCXXFLAGS)
KBUILD_HOSTRUSTFLAGS := $(rust_common_flags) -O -Zallow-features= \
$(HOSTRUSTFLAGS)
KBUILD_HOSTLDFLAGS := $(HOST_LFS_LDFLAGS) $(HOSTLDFLAGS)
KBUILD_HOSTLDLIBS := $(HOST_LFS_LIBS) $(HOSTLDLIBS)

Expand Down Expand Up @@ -533,20 +552,12 @@ KBUILD_CFLAGS := -Wall -Wundef -Werror=strict-prototypes -Wno-trigraphs \
-std=gnu89
KBUILD_CPPFLAGS := -D__KERNEL__
KBUILD_RUST_TARGET := $(srctree)/arch/$(SRCARCH)/rust/target.json
KBUILD_RUSTFLAGS := --edition=2021 \
-Cpanic=abort -Cembed-bitcode=n -Clto=n -Crpath=n \
-Cforce-unwind-tables=n -Ccodegen-units=1 \
-Csymbol-mangling-version=v0 \
-Zbinary_dep_depinfo=y \
-Dunsafe_op_in_unsafe_fn -Drust_2018_idioms \
-Dunreachable_pub -Dnon_ascii_idents \
-Wmissing_docs \
-Drustdoc::missing_crate_level_docs \
-Dclippy::correctness -Dclippy::style -Dclippy::suspicious \
-Dclippy::complexity -Dclippy::perf -Dclippy::float_arithmetic \
-Dclippy::let_unit_value -Dclippy::mut_mut \
-Dclippy::needless_bitwise_bool -Dclippy::needless_continue \
-Wclippy::dbg_macro
KBUILD_RUSTFLAGS := $(rust_common_flags) \
-Cpanic=abort -Cembed-bitcode=n -Clto=n -Crpath=n \
-Cforce-unwind-tables=n -Ccodegen-units=1 \
-Csymbol-mangling-version=v0 \
-Dclippy::float_arithmetic

KBUILD_AFLAGS_KERNEL :=
KBUILD_CFLAGS_KERNEL :=
KBUILD_RUSTFLAGS_KERNEL :=
Expand All @@ -573,6 +584,7 @@ export RUSTC_BOOTSTRAP := 1

export ARCH SRCARCH CONFIG_SHELL BASH HOSTCC KBUILD_HOSTCFLAGS CROSS_COMPILE LD CC
export RUSTC RUSTDOC RUSTFMT RUSTC_OR_CLIPPY_QUIET RUSTC_OR_CLIPPY BINDGEN CARGO
export HOSTRUSTC KBUILD_HOSTRUSTFLAGS
export CPP AR NM STRIP OBJCOPY OBJDUMP READELF PAHOLE RESOLVE_BTFIDS LEX YACC AWK INSTALLKERNEL
export PERL PYTHON3 CHECK CHECKFLAGS MAKE UTS_MACHINE HOSTCXX
export KGZIP KBZIP2 KLZOP LZMA LZ4 XZ ZSTD
Expand Down
7 changes: 7 additions & 0 deletions samples/rust/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -120,4 +120,11 @@ config SAMPLE_RUST_PLATFORM

If unsure, say N.

config SAMPLE_RUST_HOSTPROGS
bool "Host programs"
help
This option builds the Rust host program samples.

If unsure, say N.

endif # SAMPLES_RUST
2 changes: 2 additions & 0 deletions samples/rust/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,5 @@ obj-$(CONFIG_SAMPLE_RUST_SEMAPHORE) += rust_semaphore.o
obj-$(CONFIG_SAMPLE_RUST_SEMAPHORE_C) += rust_semaphore_c.o
obj-$(CONFIG_SAMPLE_RUST_RANDOM) += rust_random.o
obj-$(CONFIG_SAMPLE_RUST_PLATFORM) += rust_platform.o

subdir-$(CONFIG_SAMPLE_RUST_HOSTPROGS) += hostprogs
3 changes: 3 additions & 0 deletions samples/rust/hostprogs/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# SPDX-License-Identifier: GPL-2.0

single
5 changes: 5 additions & 0 deletions samples/rust/hostprogs/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# SPDX-License-Identifier: GPL-2.0

hostprogs-always-y := single

single-rust := y
7 changes: 7 additions & 0 deletions samples/rust/hostprogs/a.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// SPDX-License-Identifier: GPL-2.0

//! Rust single host program sample: module `a`.
pub(crate) fn f(x: i32) {
println!("The number is {}.", x);
}
5 changes: 5 additions & 0 deletions samples/rust/hostprogs/b.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// SPDX-License-Identifier: GPL-2.0

//! Rust single host program sample: module `b`.
pub(crate) const CONSTANT: i32 = 42;
12 changes: 12 additions & 0 deletions samples/rust/hostprogs/single.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// SPDX-License-Identifier: GPL-2.0

//! Rust single host program sample.
mod a;
mod b;

fn main() {
println!("Hello world!");

a::f(b::CONSTANT);
}
34 changes: 31 additions & 3 deletions scripts/Makefile.host
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ $(obj)/%.tab.c $(obj)/%.tab.h: $(src)/%.y FORCE
# to preprocess a data file.
#
# Both C and C++ are supported, but preferred language is C for such utilities.
# Rust is also supported, but it may only be used in scenarios where a Rust
# toolchain is required to be available (e.g. when `CONFIG_RUST` is enabled).
#
# Sample syntax (see Documentation/kbuild/makefiles.rst for reference)
# hostprogs := bin2hex
Expand All @@ -37,15 +39,20 @@ $(obj)/%.tab.c $(obj)/%.tab.h: $(src)/%.y FORCE
# qconf-objs := menu.o
# Will compile qconf as a C++ program, and menu as a C program.
# They are linked as C++ code to the executable qconf
#
# hostprogs := target
# target-rust := y
# Will compile `target` as a Rust program, using `target.rs` as the crate root.
# The crate may consist of several source files.

# C code
# Executables compiled from a single .c file
host-csingle := $(foreach m,$(hostprogs), \
$(if $($(m)-objs)$($(m)-cxxobjs),,$(m)))
$(if $($(m)-objs)$($(m)-cxxobjs)$($(m)-rust),,$(m)))

# C executables linked based on several .o files
host-cmulti := $(foreach m,$(hostprogs),\
$(if $($(m)-cxxobjs),,$(if $($(m)-objs),$(m))))
$(if $($(m)-cxxobjs)$($(m)-rust),,$(if $($(m)-objs),$(m))))

# Object (.o) files compiled from .c files
host-cobjs := $(sort $(foreach m,$(hostprogs),$($(m)-objs)))
Expand All @@ -58,11 +65,17 @@ host-cxxmulti := $(foreach m,$(hostprogs),$(if $($(m)-cxxobjs),$(m)))
# C++ Object (.o) files compiled from .cc files
host-cxxobjs := $(sort $(foreach m,$(host-cxxmulti),$($(m)-cxxobjs)))

# Rust code
# Executables compiled from a single Rust crate (which may consist of
# one or more .rs files)
host-rust := $(foreach m,$(hostprogs),$(if $($(m)-rust),$(m)))

host-csingle := $(addprefix $(obj)/,$(host-csingle))
host-cmulti := $(addprefix $(obj)/,$(host-cmulti))
host-cobjs := $(addprefix $(obj)/,$(host-cobjs))
host-cxxmulti := $(addprefix $(obj)/,$(host-cxxmulti))
host-cxxobjs := $(addprefix $(obj)/,$(host-cxxobjs))
host-rust := $(addprefix $(obj)/,$(host-rust))

#####
# Handle options to gcc. Support building with separate output directory
Expand All @@ -71,6 +84,8 @@ _hostc_flags = $(KBUILD_HOSTCFLAGS) $(HOST_EXTRACFLAGS) \
$(HOSTCFLAGS_$(target-stem).o)
_hostcxx_flags = $(KBUILD_HOSTCXXFLAGS) $(HOST_EXTRACXXFLAGS) \
$(HOSTCXXFLAGS_$(target-stem).o)
_hostrust_flags = $(KBUILD_HOSTRUSTFLAGS) $(HOST_EXTRARUSTFLAGS) \
$(HOSTRUSTFLAGS_$(target-stem))

# $(objtree)/$(obj) for including generated headers from checkin source files
ifeq ($(KBUILD_EXTMOD),)
Expand All @@ -82,6 +97,7 @@ endif

hostc_flags = -Wp,-MMD,$(depfile) $(_hostc_flags)
hostcxx_flags = -Wp,-MMD,$(depfile) $(_hostcxx_flags)
hostrust_flags = $(_hostrust_flags)

#####
# Compile programs on the host
Expand Down Expand Up @@ -128,5 +144,17 @@ quiet_cmd_host-cxxobjs = HOSTCXX $@
$(host-cxxobjs): $(obj)/%.o: $(src)/%.cc FORCE
$(call if_changed_dep,host-cxxobjs)

# Create executable from a single Rust crate (which may consist of
# one or more `.rs` files)
# host-rust -> Executable
quiet_cmd_host-rust = HOSTRUSTC $@
cmd_host-rust = \
$(HOSTRUSTC) $(hostrust_flags) --emit=dep-info,link \
--out-dir=$(obj)/ $<; \
mv $(obj)/$(target-stem).d $(depfile); \
sed -i '/^\#/d' $(depfile)
$(host-rust): $(obj)/%: $(src)/%.rs FORCE
$(call if_changed_dep,host-rust)

targets += $(host-csingle) $(host-cmulti) $(host-cobjs) \
$(host-cxxmulti) $(host-cxxobjs)
$(host-cxxmulti) $(host-cxxobjs) $(host-rust)

0 comments on commit 78e2b26

Please sign in to comment.