From 62498e01bdeb4478d2422edc16ad4eba2a9dc6a0 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Mon, 10 May 2021 21:27:43 +0100 Subject: [PATCH] rust: Rename libmodule to libmacros Renaming to libmacros allows us to potentially have more procedural macros in the future without introducing additional crates. Signed-off-by: Gary Guo --- rust/Makefile | 24 +++--- rust/kernel/module_param.rs | 4 +- rust/kernel/prelude.rs | 2 +- rust/macros/lib.rs | 126 ++++++++++++++++++++++++++++++ rust/{ => macros}/module.rs | 114 +-------------------------- scripts/generate_rust_analyzer.py | 8 +- 6 files changed, 146 insertions(+), 132 deletions(-) create mode 100644 rust/macros/lib.rs rename rust/{ => macros}/module.rs (86%) diff --git a/rust/Makefile b/rust/Makefile index 7621e92b3dc70f..9e94e687007217 100644 --- a/rust/Makefile +++ b/rust/Makefile @@ -3,7 +3,7 @@ obj-$(CONFIG_RUST) += core.o compiler_builtins.o helpers.o extra-$(CONFIG_RUST) += exports_core_generated.h -extra-$(CONFIG_RUST) += libmodule.so +extra-$(CONFIG_RUST) += libmacros.so extra-$(CONFIG_RUST) += bindings_generated.rs obj-$(CONFIG_RUST) += alloc.o kernel.o @@ -35,11 +35,11 @@ quiet_cmd_rustdoc = RUSTDOC $< --output $(objtree)/rust/doc --crate-name $(subst rustdoc-,,$@) \ -Fmissing-docs @$(objtree)/include/generated/rustc_cfg $< -rustdoc: rustdoc-module rustdoc-compiler_builtins rustdoc-kernel +rustdoc: rustdoc-macros rustdoc-compiler_builtins rustdoc-kernel -rustdoc-module: private rustdoc_target_flags = --crate-type proc-macro \ +rustdoc-macros: private rustdoc_target_flags = --crate-type proc-macro \ --extern proc_macro -rustdoc-module: $(srctree)/rust/module.rs FORCE +rustdoc-macros: $(srctree)/rust/macros/lib.rs FORCE $(call if_changed,rustdoc_host) rustdoc-compiler_builtins: $(srctree)/rust/compiler_builtins.rs FORCE @@ -47,9 +47,9 @@ rustdoc-compiler_builtins: $(srctree)/rust/compiler_builtins.rs FORCE rustdoc-kernel: private rustdoc_target_flags = --extern alloc \ --extern build_error \ - --extern module=$(objtree)/rust/libmodule.so -rustdoc-kernel: $(srctree)/rust/kernel/lib.rs rustdoc-module \ - $(objtree)/rust/libmodule.so $(objtree)/rust/bindings_generated.rs FORCE + --extern macros=$(objtree)/rust/libmacros.so +rustdoc-kernel: $(srctree)/rust/kernel/lib.rs rustdoc-macros \ + $(objtree)/rust/libmacros.so $(objtree)/rust/bindings_generated.rs FORCE $(call if_changed,rustdoc) ifdef CONFIG_CC_IS_CLANG @@ -126,9 +126,9 @@ quiet_cmd_rustc_procmacro = $(RUSTC_OR_CLIPPY_QUIET) P $@ sed -i '/^\#/d' $(depfile) # Procedural macros can only be used with the `rustc` that compiled it. -# Therefore, to get `libmodule.so` automatically recompiled when the compiler +# 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). -$(objtree)/rust/libmodule.so: $(srctree)/rust/module.rs \ +$(objtree)/rust/libmacros.so: $(srctree)/rust/macros/lib.rs \ $(objtree)/rust/core.o FORCE $(call if_changed_dep,rustc_procmacro) @@ -169,11 +169,11 @@ $(objtree)/rust/build_error.o: $(srctree)/rust/build_error.rs \ $(objtree)/rust/compiler_builtins.o FORCE $(call if_changed_dep,rustc_library) -# ICE on `--extern module`: https://github.com/rust-lang/rust/issues/56935 +# ICE on `--extern macros`: https://github.com/rust-lang/rust/issues/56935 $(objtree)/rust/kernel.o: private rustc_target_flags = --extern alloc \ --extern build_error \ - --extern module=$(objtree)/rust/libmodule.so + --extern macros=$(objtree)/rust/libmacros.so $(objtree)/rust/kernel.o: $(srctree)/rust/kernel/lib.rs $(objtree)/rust/alloc.o \ $(objtree)/rust/build_error.o \ - $(objtree)/rust/libmodule.so $(objtree)/rust/bindings_generated.rs FORCE + $(objtree)/rust/libmacros.so $(objtree)/rust/bindings_generated.rs FORCE $(call if_changed_dep,rustc_library) diff --git a/rust/kernel/module_param.rs b/rust/kernel/module_param.rs index c70f61367347f3..fc6a6b01c588db 100644 --- a/rust/kernel/module_param.rs +++ b/rust/kernel/module_param.rs @@ -52,7 +52,7 @@ pub trait ModuleParam: core::fmt::Display + core::marker::Sized { /// Get the current value of the parameter for use in the kernel module. /// /// This function should not be used directly. Instead use the wrapper - /// `read` which will be generated by [`module::module`]. + /// `read` which will be generated by [`macros::module`]. fn value(&self) -> &Self::Value; /// Set the module parameter from a string. @@ -428,7 +428,7 @@ impl ModuleParam /// A C-style string parameter. /// /// The Rust version of the [`charp`] parameter. This type is meant to be -/// used by the [`module::module`] macro, not handled directly. Instead use the +/// used by the [`macros::module`] macro, not handled directly. Instead use the /// `read` method generated by that macro. /// /// [`charp`]: ../../../include/linux/moduleparam.h diff --git a/rust/kernel/prelude.rs b/rust/kernel/prelude.rs index f0835fb19b2f7b..8a6161e2b0e262 100644 --- a/rust/kernel/prelude.rs +++ b/rust/kernel/prelude.rs @@ -15,7 +15,7 @@ pub use alloc::{borrow::ToOwned, string::String}; pub use super::build_assert; -pub use module::{module, module_misc_device}; +pub use macros::{module, module_misc_device}; pub use super::{pr_alert, pr_cont, pr_crit, pr_emerg, pr_err, pr_info, pr_notice, pr_warn}; diff --git a/rust/macros/lib.rs b/rust/macros/lib.rs new file mode 100644 index 00000000000000..a0c882dc8aa81d --- /dev/null +++ b/rust/macros/lib.rs @@ -0,0 +1,126 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Crate for all kernel procedural macros. +mod module; + +use proc_macro::TokenStream; + +/// Declares a kernel module. +/// +/// The `type` argument should be a type which implements the [`KernelModule`] +/// trait. Also accepts various forms of kernel metadata. +/// +/// C header: [`include/linux/moduleparam.h`](../../../include/linux/moduleparam.h) +/// +/// [`KernelModule`]: ../kernel/trait.KernelModule.html +/// +/// # Examples +/// +/// ```rust,no_run +/// use kernel::prelude::*; +/// +/// module!{ +/// type: MyKernelModule, +/// name: b"my_kernel_module", +/// author: b"Rust for Linux Contributors", +/// description: b"My very own kernel module!", +/// license: b"GPL v2", +/// params: { +/// my_i32: i32 { +/// default: 42, +/// permissions: 0o000, +/// description: b"Example of i32", +/// }, +/// writeable_i32: i32 { +/// default: 42, +/// permissions: 0o644, +/// description: b"Example of i32", +/// }, +/// }, +/// } +/// +/// struct MyKernelModule; +/// +/// impl KernelModule for MyKernelModule { +/// fn init() -> Result { +/// // If the parameter is writeable, then the kparam lock must be +/// // taken to read the parameter: +/// { +/// let lock = THIS_MODULE.kernel_param_lock(); +/// pr_info!("i32 param is: {}\n", writeable_i32.read(&lock)); +/// } +/// // If the parameter is read only, it can be read without locking +/// // the kernel parameters: +/// pr_info!("i32 param is: {}\n", my_i32.read()); +/// Ok(MyKernelModule) +/// } +/// } +/// ``` +/// +/// # Supported argument types +/// - `type`: type which implements the [`KernelModule`] trait (required). +/// - `name`: byte array of the name of the kernel module (required). +/// - `author`: byte array of the author of the kernel module. +/// - `description`: byte array of the description of the kernel module. +/// - `license`: byte array of the license of the kernel module (required). +/// - `alias`: byte array of alias name of the kernel module. +/// - `alias_rtnl_link`: byte array of the `rtnl_link_alias` of the kernel module (mutually exclusive with `alias`). +/// - `params`: parameters for the kernel module, as described below. +/// +/// # Supported parameter types +/// +/// - `bool`: Corresponds to C `bool` param type. +/// - `i8`: No equivalent C param type. +/// - `u8`: Corresponds to C `char` param type. +/// - `i16`: Corresponds to C `short` param type. +/// - `u16`: Corresponds to C `ushort` param type. +/// - `i32`: Corresponds to C `int` param type. +/// - `u32`: Corresponds to C `uint` param type. +/// - `i64`: No equivalent C param type. +/// - `u64`: Corresponds to C `ullong` param type. +/// - `isize`: No equivalent C param type. +/// - `usize`: No equivalent C param type. +/// - `str`: Corresponds to C `charp` param type. Reading returns a byte slice. +/// - `ArrayParam`: Corresponds to C parameters created using `module_param_array`. An array +/// of `T`'s of length at **most** `N`. +/// +/// `invbool` is unsupported: it was only ever used in a few modules. +/// Consider using a `bool` and inverting the logic instead. +#[proc_macro] +pub fn module(ts: TokenStream) -> TokenStream { + module::module(ts) +} + +/// Declares a kernel module that exposes a single misc device. +/// +/// The `type` argument should be a type which implements the [`FileOpener`] trait. Also accepts +/// various forms of kernel metadata. +/// +/// C header: [`include/linux/moduleparam.h`](../../../include/linux/moduleparam.h) +/// +/// [`FileOpener`]: ../kernel/file_operations/trait.FileOpener.html +/// +/// # Examples +/// +/// ```rust,no_run +/// use kernel::prelude::*; +/// +/// module_misc_device! { +/// type: MyFile, +/// name: b"my_miscdev_kernel_module", +/// author: b"Rust for Linux Contributors", +/// description: b"My very own misc device kernel module!", +/// license: b"GPL v2", +/// } +/// +/// #[derive(Default)] +/// struct MyFile; +/// +/// impl kernel::file_operations::FileOperations for MyFile { +/// kernel::declare_file_operations!(); +/// } +/// ``` +#[proc_macro] +pub fn module_misc_device(ts: TokenStream) -> TokenStream { + module::module_misc_device(ts) +} diff --git a/rust/module.rs b/rust/macros/module.rs similarity index 86% rename from rust/module.rs rename to rust/macros/module.rs index 9a7009644d3cd7..0a155b8d4c9f7f 100644 --- a/rust/module.rs +++ b/rust/macros/module.rs @@ -1,9 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -//! Proc macro crate implementing the [`module!`] magic. -//! -//! C header: [`include/linux/moduleparam.h`](../../../include/linux/moduleparam.h) - #![deny(clippy::complexity)] #![deny(clippy::correctness)] #![deny(clippy::perf)] @@ -399,86 +395,6 @@ impl ModuleInfo { } } -/// Declares a kernel module. -/// -/// The `type` argument should be a type which implements the [`KernelModule`] -/// trait. Also accepts various forms of kernel metadata. -/// -/// [`KernelModule`]: ../kernel/trait.KernelModule.html -/// -/// # Examples -/// -/// ```rust,no_run -/// use kernel::prelude::*; -/// -/// module!{ -/// type: MyKernelModule, -/// name: b"my_kernel_module", -/// author: b"Rust for Linux Contributors", -/// description: b"My very own kernel module!", -/// license: b"GPL v2", -/// params: { -/// my_i32: i32 { -/// default: 42, -/// permissions: 0o000, -/// description: b"Example of i32", -/// }, -/// writeable_i32: i32 { -/// default: 42, -/// permissions: 0o644, -/// description: b"Example of i32", -/// }, -/// }, -/// } -/// -/// struct MyKernelModule; -/// -/// impl KernelModule for MyKernelModule { -/// fn init() -> Result { -/// // If the parameter is writeable, then the kparam lock must be -/// // taken to read the parameter: -/// { -/// let lock = THIS_MODULE.kernel_param_lock(); -/// pr_info!("i32 param is: {}\n", writeable_i32.read(&lock)); -/// } -/// // If the parameter is read only, it can be read without locking -/// // the kernel parameters: -/// pr_info!("i32 param is: {}\n", my_i32.read()); -/// Ok(MyKernelModule) -/// } -/// } -/// ``` -/// -/// # Supported argument types -/// - `type`: type which implements the [`KernelModule`] trait (required). -/// - `name`: byte array of the name of the kernel module (required). -/// - `author`: byte array of the author of the kernel module. -/// - `description`: byte array of the description of the kernel module. -/// - `license`: byte array of the license of the kernel module (required). -/// - `alias`: byte array of alias name of the kernel module. -/// - `alias_rtnl_link`: byte array of the `rtnl_link_alias` of the kernel module (mutually exclusive with `alias`). -/// - `params`: parameters for the kernel module, as described below. -/// -/// # Supported parameter types -/// -/// - `bool`: Corresponds to C `bool` param type. -/// - `i8`: No equivalent C param type. -/// - `u8`: Corresponds to C `char` param type. -/// - `i16`: Corresponds to C `short` param type. -/// - `u16`: Corresponds to C `ushort` param type. -/// - `i32`: Corresponds to C `int` param type. -/// - `u32`: Corresponds to C `uint` param type. -/// - `i64`: No equivalent C param type. -/// - `u64`: Corresponds to C `ullong` param type. -/// - `isize`: No equivalent C param type. -/// - `usize`: No equivalent C param type. -/// - `str`: Corresponds to C `charp` param type. Reading returns a byte slice. -/// - `ArrayParam`: Corresponds to C parameters created using `module_param_array`. An array -/// of `T`'s of length at **most** `N`. -/// -/// `invbool` is unsupported: it was only ever used in a few modules. -/// Consider using a `bool` and inverting the logic instead. -#[proc_macro] pub fn module(ts: TokenStream) -> TokenStream { let mut it = ts.into_iter(); @@ -775,34 +691,6 @@ pub fn module(ts: TokenStream) -> TokenStream { ).parse().expect("Error parsing formatted string into token stream.") } -/// Declares a kernel module that exposes a single misc device. -/// -/// The `type` argument should be a type which implements the [`FileOpener`] trait. Also accepts -/// various forms of kernel metadata. -/// -/// [`FileOpener`]: ../kernel/file_operations/trait.FileOpener.html -/// -/// # Examples -/// -/// ```rust,no_run -/// use kernel::prelude::*; -/// -/// module_misc_device! { -/// type: MyFile, -/// name: b"my_miscdev_kernel_module", -/// author: b"Rust for Linux Contributors", -/// description: b"My very own misc device kernel module!", -/// license: b"GPL v2", -/// } -/// -/// #[derive(Default)] -/// struct MyFile; -/// -/// impl kernel::file_operations::FileOperations for MyFile { -/// kernel::declare_file_operations!(); -/// } -/// ``` -#[proc_macro] pub fn module_misc_device(ts: TokenStream) -> TokenStream { let mut it = ts.into_iter(); @@ -821,7 +709,7 @@ pub fn module_misc_device(ts: TokenStream) -> TokenStream { fn init() -> kernel::Result {{ Ok(Self {{ _dev: kernel::miscdev::Registration::new_pinned::<{type_}>( - kernel::c_str!(\"{name}\"), + kernel::c_str!({name}), None, (), )?, diff --git a/scripts/generate_rust_analyzer.py b/scripts/generate_rust_analyzer.py index e88d4fc9eb3000..2a7b22be642bbe 100755 --- a/scripts/generate_rust_analyzer.py +++ b/scripts/generate_rust_analyzer.py @@ -63,13 +63,13 @@ def append_crate(display_name, root_module, is_workspace_member, deps, cfg): ) append_crate( - "module", - srctree / "rust" / "module.rs", + "macros", + srctree / "rust" / "macros" / "lib.rs", True, [], [], ) - crates[-1]["proc_macro_dylib_path"] = "rust/libmodule.so" + crates[-1]["proc_macro_dylib_path"] = "rust/libmacros.so" append_crate( "build_error", @@ -83,7 +83,7 @@ def append_crate(display_name, root_module, is_workspace_member, deps, cfg): "kernel", srctree / "rust" / "kernel" / "lib.rs", True, - ["core", "alloc", "module", "build_error"], + ["core", "alloc", "macros", "build_error"], cfg, ) crates[-1]["env"]["RUST_BINDINGS_FILE"] = str(bindings_file.resolve(True))