From 6147b82948a3f43f69ffc6e94e72b445a8dc0154 Mon Sep 17 00:00:00 2001 From: Miguel Ojeda Date: Mon, 2 Sep 2024 18:55:28 +0200 Subject: [PATCH 01/11] kbuild: rust: add `CONFIG_RUSTC_VERSION` Now that we support several Rust versions, introduce `CONFIG_RUSTC_VERSION` so that it can be used in Kconfig to enable and disable configuration options based on the `rustc` version. The approach taken resembles `pahole`'s -- see commit 613fe1692377 ("kbuild: Add CONFIG_PAHOLE_VERSION"), i.e. a simple version parsing without trying to identify several kinds of compilers, since so far there is only one (`rustc`). However, unlike `pahole`'s, we also print a zero if executing failed for any reason, rather than checking if the command is found and executable (which still leaves things like a file that exists and is executable, but e.g. is built for another platform [1]). An equivalent approach to the one here was also submitted for `pahole` [2]. Link: https://lore.kernel.org/rust-for-linux/CANiq72=4vX_tJMJLE6e+bg7ZECHkS-AQpm8GBzuK75G1EB7+Nw@mail.gmail.com/ [1] Link: https://lore.kernel.org/linux-kbuild/20240728125527.690726-1-ojeda@kernel.org/ [2] Reviewed-by: Nicolas Schier Tested-by: Alice Ryhl Link: https://lore.kernel.org/r/20240902165535.1101978-2-ojeda@kernel.org Signed-off-by: Miguel Ojeda --- init/Kconfig | 7 +++++++ scripts/rustc-version.sh | 26 ++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100755 scripts/rustc-version.sh diff --git a/init/Kconfig b/init/Kconfig index 839c8303400652..38c1cfcce821e4 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -60,6 +60,13 @@ config LLD_VERSION default $(ld-version) if LD_IS_LLD default 0 +config RUSTC_VERSION + int + default $(shell,$(srctree)/scripts/rustc-version.sh $(RUSTC)) + help + It does not depend on `RUST` since that one may need to use the version + in a `depends on`. + config RUST_IS_AVAILABLE def_bool $(success,$(srctree)/scripts/rust_is_available.sh) help diff --git a/scripts/rustc-version.sh b/scripts/rustc-version.sh new file mode 100755 index 00000000000000..62ea510be71b48 --- /dev/null +++ b/scripts/rustc-version.sh @@ -0,0 +1,26 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# +# Usage: $ ./rustc-version.sh rustc +# +# Print the Rust compiler name and its version in a 6 or 7-digit form. + +# Convert the version string x.y.z to a canonical up-to-7-digits form. +# +# Note that this function uses one more digit (compared to other +# instances in other version scripts) to give a bit more space to +# `rustc` since it will reach 1.100.0 in late 2026. +get_canonical_version() +{ + IFS=. + set -- $1 + echo $((100000 * $1 + 100 * $2 + $3)) +} + +if output=$("$@" --version 2>/dev/null); then + set -- $output + get_canonical_version $2 +else + echo 0 + exit 1 +fi From d44b0238c1a48b0f2e796efc88600bf806c589a4 Mon Sep 17 00:00:00 2001 From: Miguel Ojeda Date: Mon, 2 Sep 2024 18:55:29 +0200 Subject: [PATCH 02/11] kbuild: rust: re-run Kconfig if the version text changes Re-run Kconfig if we detect the Rust compiler has changed via the version text, like it is done for C. Unlike C, and unlike `RUSTC_VERSION`, the `RUSTC_VERSION_TEXT` is kept under `depends on RUST`, since it should not be needed unless `RUST` is enabled. Reviewed-by: Nicolas Schier Tested-by: Alice Ryhl Link: https://lore.kernel.org/r/20240902165535.1101978-3-ojeda@kernel.org Signed-off-by: Miguel Ojeda --- Makefile | 8 +++++--- init/Kconfig | 4 +++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 68ebd6d6b444df..1883aeb919a416 100644 --- a/Makefile +++ b/Makefile @@ -648,9 +648,11 @@ endif # The expansion should be delayed until arch/$(SRCARCH)/Makefile is included. # Some architectures define CROSS_COMPILE in arch/$(SRCARCH)/Makefile. -# CC_VERSION_TEXT is referenced from Kconfig (so it needs export), -# and from include/config/auto.conf.cmd to detect the compiler upgrade. +# CC_VERSION_TEXT and RUSTC_VERSION_TEXT are referenced from Kconfig (so they +# need export), and from include/config/auto.conf.cmd to detect the compiler +# upgrade. CC_VERSION_TEXT = $(subst $(pound),,$(shell LC_ALL=C $(CC) --version 2>/dev/null | head -n 1)) +RUSTC_VERSION_TEXT = $(subst $(pound),,$(shell $(RUSTC) --version 2>/dev/null)) ifneq ($(findstring clang,$(CC_VERSION_TEXT)),) include $(srctree)/scripts/Makefile.clang @@ -671,7 +673,7 @@ ifdef config-build # KBUILD_DEFCONFIG may point out an alternative default configuration # used for 'make defconfig' include $(srctree)/arch/$(SRCARCH)/Makefile -export KBUILD_DEFCONFIG KBUILD_KCONFIG CC_VERSION_TEXT +export KBUILD_DEFCONFIG KBUILD_KCONFIG CC_VERSION_TEXT RUSTC_VERSION_TEXT config: outputmakefile scripts_basic FORCE $(Q)$(MAKE) $(build)=scripts/kconfig $@ diff --git a/init/Kconfig b/init/Kconfig index 38c1cfcce821e4..c6b744a48dcca7 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -1927,7 +1927,9 @@ config RUST config RUSTC_VERSION_TEXT string depends on RUST - default "$(shell,$(RUSTC) --version 2>/dev/null)" + default "$(RUSTC_VERSION_TEXT)" + help + See `CC_VERSION_TEXT`. config BINDGEN_VERSION_TEXT string From e9600542b6e6ac36e1863e4eb3cb1141ccc0aa14 Mon Sep 17 00:00:00 2001 From: Miguel Ojeda Date: Mon, 2 Sep 2024 18:55:30 +0200 Subject: [PATCH 03/11] kbuild: rust: rebuild if the version text changes Now that `RUSTC_VERSION_TEXT` exists, use it to rebuild `core` when the version text changes (which in turn will trigger a rebuild of all the kernel Rust code). This also applies to proc macros (which only work with the `rustc` that compiled them), via the already existing dependency on `core.o`. That is cleaned up in the next commit. However, this does not cover host programs written in Rust, which is the same case in the C side. This is accomplished by referencing directly the generated file, instead of using the `fixdep` header trick, since we cannot change the Rust standard library sources. This is not too much of a burden, since it only needs to be done for `core`. Tested-by: Alice Ryhl Reviewed-by: Nicolas Schier Link: https://lore.kernel.org/r/20240902165535.1101978-4-ojeda@kernel.org Signed-off-by: Miguel Ojeda --- rust/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rust/Makefile b/rust/Makefile index e13d14ec5fe74c..bb57a7c30f1aa2 100644 --- a/rust/Makefile +++ b/rust/Makefile @@ -389,7 +389,8 @@ $(obj)/core.o: private skip_clippy = 1 $(obj)/core.o: private skip_flags = -Wunreachable_pub $(obj)/core.o: private rustc_objcopy = $(foreach sym,$(redirect-intrinsics),--redefine-sym $(sym)=__rust$(sym)) $(obj)/core.o: private rustc_target_flags = $(core-cfgs) -$(obj)/core.o: $(RUST_LIB_SRC)/core/src/lib.rs FORCE +$(obj)/core.o: $(RUST_LIB_SRC)/core/src/lib.rs \ + $(wildcard $(objtree)/include/config/RUSTC_VERSION_TEXT) FORCE +$(call if_changed_rule,rustc_library) ifneq ($(or $(CONFIG_X86_64),$(CONFIG_X86_32)),) $(obj)/core.o: scripts/target.json From 2e17c2dc00362fa1e14e59e2dda3307aa0f14d5e Mon Sep 17 00:00:00 2001 From: Miguel Ojeda Date: Mon, 2 Sep 2024 18:55:31 +0200 Subject: [PATCH 04/11] kbuild: rust: replace proc macros dependency on `core.o` with the version text With the `RUSTC_VERSION_TEXT` rebuild support in place, now proc macros can depend on that instead of `core.o`. This means that both the `core` and `macros` crates can be built in parallel, and that touching `core.o` does not trigger a rebuild of the proc macros. This could be accomplished using the same approach as for `core` (i.e. depending directly on `include/config/RUSTC_VERSION_TEXT`). However, that is considered an implementation detail [1], and thus it is best to avoid it. Instead, let fixdep find a string that we explicitly write down in the source code for this purpose (like it is done for `include/linux/compiler-version.h`), which we can easily do (unlike for `core`) since this is our own source code. Suggested-by: Masahiro Yamada Link: https://lore.kernel.org/rust-for-linux/CAK7LNAQBG0nDupXSgAAk-6nOqeqGVkr3H1RjYaqRJ1OxmLm6xA@mail.gmail.com/ [1] Reviewed-by: Nicolas Schier Tested-by: Alice Ryhl Link: https://lore.kernel.org/r/20240902165535.1101978-5-ojeda@kernel.org Signed-off-by: Miguel Ojeda --- rust/Makefile | 4 +--- rust/macros/lib.rs | 4 ++++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/rust/Makefile b/rust/Makefile index bb57a7c30f1aa2..4eae318f36ff74 100644 --- a/rust/Makefile +++ b/rust/Makefile @@ -342,9 +342,7 @@ quiet_cmd_rustc_procmacro = $(RUSTC_OR_CLIPPY_QUIET) P $@ --crate-name $(patsubst lib%.so,%,$(notdir $@)) $< # Procedural macros can only be used with the `rustc` that compiled it. -# Therefore, to get `libmacros.so` automatically recompiled when the compiler -# version changes, we add `core.o` as a dependency (even if it is not needed). -$(obj)/libmacros.so: $(src)/macros/lib.rs $(obj)/core.o FORCE +$(obj)/libmacros.so: $(src)/macros/lib.rs FORCE +$(call if_changed_dep,rustc_procmacro) quiet_cmd_rustc_library = $(if $(skip_clippy),RUSTC,$(RUSTC_OR_CLIPPY_QUIET)) L $@ diff --git a/rust/macros/lib.rs b/rust/macros/lib.rs index 5be0cb9db3ee49..a626b1145e5c4f 100644 --- a/rust/macros/lib.rs +++ b/rust/macros/lib.rs @@ -2,6 +2,10 @@ //! Crate for all kernel procedural macros. +// When fixdep scans this, it will find this string `CONFIG_RUSTC_VERSION_TEXT` +// and thus add a dependency on `include/config/RUSTC_VERSION_TEXT`, which is +// touched by Kconfig when the version string from the compiler changes. + #[macro_use] mod quote; mod concat_idents; From 77e1dd1d0f912f79d3c40b6bf35d45ba4953c066 Mon Sep 17 00:00:00 2001 From: Miguel Ojeda Date: Mon, 2 Sep 2024 18:55:33 +0200 Subject: [PATCH 05/11] docs: rust: include other expressions in conditional compilation section Expand the conditional compilation section to explain how to support other expressions, such as testing whether `RUSTC_VERSION` is at least a given version, which requires a numerical comparison that Rust's `cfg` predicates do not support (yet?). Reviewed-by: Nicolas Schier Tested-by: Alice Ryhl Link: https://lore.kernel.org/r/20240902165535.1101978-7-ojeda@kernel.org Signed-off-by: Miguel Ojeda --- Documentation/rust/general-information.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Documentation/rust/general-information.rst b/Documentation/rust/general-information.rst index 2d76e09da12162..6146b49b6a9881 100644 --- a/Documentation/rust/general-information.rst +++ b/Documentation/rust/general-information.rst @@ -151,3 +151,11 @@ configuration: #[cfg(CONFIG_X="y")] // Enabled as a built-in (`y`) #[cfg(CONFIG_X="m")] // Enabled as a module (`m`) #[cfg(not(CONFIG_X))] // Disabled + +For other predicates that Rust's ``cfg`` does not support, e.g. expressions with +numerical comparisons, one may define a new Kconfig symbol: + +.. code-block:: kconfig + + config RUSTC_VERSION_MIN_107900 + def_bool y if RUSTC_VERSION >= 107900 From 4beb37bdce5330be5c1219285d55e72eac1c6190 Mon Sep 17 00:00:00 2001 From: Patrick Miller Date: Thu, 5 Sep 2024 16:07:25 -0400 Subject: [PATCH 06/11] make section names plural --- rust/kernel/init.rs | 2 +- rust/kernel/list/arc.rs | 2 +- rust/kernel/sync/arc.rs | 2 +- rust/macros/lib.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/rust/kernel/init.rs b/rust/kernel/init.rs index a17ac8762d8f9f..98889ddf982825 100644 --- a/rust/kernel/init.rs +++ b/rust/kernel/init.rs @@ -746,7 +746,7 @@ macro_rules! try_init { /// Asserts that a field on a struct using `#[pin_data]` is marked with `#[pin]` ie. that it is /// structurally pinned. /// -/// # Example +/// # Examples /// /// This will succeed: /// ``` diff --git a/rust/kernel/list/arc.rs b/rust/kernel/list/arc.rs index d801b9dc6291db..611ce07cd29054 100644 --- a/rust/kernel/list/arc.rs +++ b/rust/kernel/list/arc.rs @@ -464,7 +464,7 @@ where /// A utility for tracking whether a [`ListArc`] exists using an atomic. /// -/// # Invariant +/// # Invariants /// /// If the boolean is `false`, then there is no [`ListArc`] for this value. #[repr(transparent)] diff --git a/rust/kernel/sync/arc.rs b/rust/kernel/sync/arc.rs index 3021f30fd822f6..3d3c100b0c0dfa 100644 --- a/rust/kernel/sync/arc.rs +++ b/rust/kernel/sync/arc.rs @@ -436,7 +436,7 @@ impl From>> for Arc { /// There are no mutable references to the underlying [`Arc`], and it remains valid for the /// lifetime of the [`ArcBorrow`] instance. /// -/// # Example +/// # Examples /// /// ``` /// use kernel::sync::{Arc, ArcBorrow}; diff --git a/rust/macros/lib.rs b/rust/macros/lib.rs index a626b1145e5c4f..3879e116286637 100644 --- a/rust/macros/lib.rs +++ b/rust/macros/lib.rs @@ -307,7 +307,7 @@ pub fn pinned_drop(args: TokenStream, input: TokenStream) -> TokenStream { /// literals (lifetimes and documentation strings are not supported). There is a difference in /// supported modifiers as well. /// -/// # Example +/// # Examples /// /// ```ignore /// use kernel::macro::paste; From 583a7b168dc0297d98e6e1b494a267349d464eb0 Mon Sep 17 00:00:00 2001 From: Patrick Miller Date: Fri, 6 Sep 2024 09:00:08 -0400 Subject: [PATCH 07/11] checkpatch: warn on known non-plural rust doc headers --- scripts/checkpatch.pl | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 39032224d504f1..0e99d11eeb0454 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -3900,6 +3900,14 @@ sub process { "Avoid using '.L' prefixed local symbol names for denoting a range of code via 'SYM_*_START/END' annotations; see Documentation/core-api/asm-annotations.rst\n" . $herecurr); } +# check that document section headers are plural in rust files + if ( $realfile =~ /\.rs$/ + && $rawline =~ /^\+\s*\/\/\/\s+#+\s+(Example|Invariant)\s*$/ ) + { + WARN( "RUST_DOC_HEADER", + "Rust doc headers should be plural\n" . $herecurr ); + } + # check we are in a valid source file C or perl if not then ignore this hunk next if ($realfile !~ /\.(h|c|pl|dtsi|dts)$/); From 37180546e8445815e7aa7dbc8cbd4cc0b4eb29b7 Mon Sep 17 00:00:00 2001 From: Patrick Miller Date: Fri, 6 Sep 2024 13:14:23 -0400 Subject: [PATCH 08/11] fix whitespace, add missed headers --- scripts/checkpatch.pl | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 0e99d11eeb0454..cb5ecdb6df9bdd 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -3901,12 +3901,11 @@ sub process { } # check that document section headers are plural in rust files - if ( $realfile =~ /\.rs$/ - && $rawline =~ /^\+\s*\/\/\/\s+#+\s+(Example|Invariant)\s*$/ ) - { - WARN( "RUST_DOC_HEADER", - "Rust doc headers should be plural\n" . $herecurr ); - } + if ($realfile =~ /\.rs$/ + && $rawline =~ /^\+\s*\/\/\/\s+#+\s+(Example|Invariant|Guarantee|Panic)\s*$/) { + WARN( "RUST_DOC_HEADER", + "Rust doc headers should be plural\n" . $herecurr ); + } # check we are in a valid source file C or perl if not then ignore this hunk next if ($realfile !~ /\.(h|c|pl|dtsi|dts)$/); From 836bb81fc2649edb59bb65b121bc10958b57306c Mon Sep 17 00:00:00 2001 From: Patrick Miller Date: Fri, 6 Sep 2024 13:22:01 -0400 Subject: [PATCH 09/11] Revert "fix whitespace, add missed headers" This reverts commit 37180546e8445815e7aa7dbc8cbd4cc0b4eb29b7. --- scripts/checkpatch.pl | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index cb5ecdb6df9bdd..0e99d11eeb0454 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -3901,11 +3901,12 @@ sub process { } # check that document section headers are plural in rust files - if ($realfile =~ /\.rs$/ - && $rawline =~ /^\+\s*\/\/\/\s+#+\s+(Example|Invariant|Guarantee|Panic)\s*$/) { - WARN( "RUST_DOC_HEADER", - "Rust doc headers should be plural\n" . $herecurr ); - } + if ( $realfile =~ /\.rs$/ + && $rawline =~ /^\+\s*\/\/\/\s+#+\s+(Example|Invariant)\s*$/ ) + { + WARN( "RUST_DOC_HEADER", + "Rust doc headers should be plural\n" . $herecurr ); + } # check we are in a valid source file C or perl if not then ignore this hunk next if ($realfile !~ /\.(h|c|pl|dtsi|dts)$/); From 161d428d34b5a0748d06b0fbd634e54f4b984883 Mon Sep 17 00:00:00 2001 From: Patrick Miller Date: Fri, 6 Sep 2024 13:22:19 -0400 Subject: [PATCH 10/11] Revert "checkpatch: warn on known non-plural rust doc headers" This reverts commit 583a7b168dc0297d98e6e1b494a267349d464eb0. --- scripts/checkpatch.pl | 8 -------- 1 file changed, 8 deletions(-) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 0e99d11eeb0454..39032224d504f1 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -3900,14 +3900,6 @@ sub process { "Avoid using '.L' prefixed local symbol names for denoting a range of code via 'SYM_*_START/END' annotations; see Documentation/core-api/asm-annotations.rst\n" . $herecurr); } -# check that document section headers are plural in rust files - if ( $realfile =~ /\.rs$/ - && $rawline =~ /^\+\s*\/\/\/\s+#+\s+(Example|Invariant)\s*$/ ) - { - WARN( "RUST_DOC_HEADER", - "Rust doc headers should be plural\n" . $herecurr ); - } - # check we are in a valid source file C or perl if not then ignore this hunk next if ($realfile !~ /\.(h|c|pl|dtsi|dts)$/); From 677bb2c2de58e2fec484474f0706c296e5b5e2eb Mon Sep 17 00:00:00 2001 From: Patrick Miller Date: Fri, 6 Sep 2024 13:34:33 -0400 Subject: [PATCH 11/11] checkpatch: warn on known non-plural rust doc headers --- scripts/checkpatch.pl | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 39032224d504f1..cb5ecdb6df9bdd 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -3900,6 +3900,13 @@ sub process { "Avoid using '.L' prefixed local symbol names for denoting a range of code via 'SYM_*_START/END' annotations; see Documentation/core-api/asm-annotations.rst\n" . $herecurr); } +# check that document section headers are plural in rust files + if ($realfile =~ /\.rs$/ + && $rawline =~ /^\+\s*\/\/\/\s+#+\s+(Example|Invariant|Guarantee|Panic)\s*$/) { + WARN( "RUST_DOC_HEADER", + "Rust doc headers should be plural\n" . $herecurr ); + } + # check we are in a valid source file C or perl if not then ignore this hunk next if ($realfile !~ /\.(h|c|pl|dtsi|dts)$/);