rust/kernel/lib.rs | 51 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+)
Add the `if_cfg!` macro to simplify conditional compilation using `cfg`
attributes. The macro expands to paired `#[cfg(cond)]` and
`#[cfg(not(cond))]` blocks, allowing compile-time selection between
code branches in both expression and statement contexts.
Note: Previous documentation incorrectly stated that both branches
must be valid Rust code. In reality, `if_cfg!()` compiles only the
active branch, allowing the inactive branch to reference items that
may not exist under certain configurations.
Suggested-by: Benno Lossin <lossin@kernel.org>
Link: https://github.com/Rust-for-Linux/linux/issues/1183
Signed-off-by: Areej Hamid <areejhamid8560@gmail.com>
---
rust/kernel/lib.rs | 51 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 51 insertions(+)
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index ed53169e795c..6bcce24600e3 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -294,6 +294,57 @@ macro_rules! asm {
};
}
+/// Conditionally compiles and executes code based on a `#[cfg]` condition.
+///
+/// Expands to `#[cfg(cond)] { ... }` and `#[cfg(not(cond))] { ... }`,
+/// allowing conditional compilation in both expression and statement positions.
+///
+/// # Key difference from `cfg!()`
+/// - `cfg!()` evaluates a configuration flag at compile time, but both branches must be valid Rust code
+/// - `if_cfg!()` compiles only the active branch, so the inactive branch can reference
+/// functions, types, or constants that may not exist under certain configurations
+///
+/// # Examples
+///
+/// Demonstrates the difference between `if_cfg!()` and `cfg!()`:
+/// ```ignore
+/// # use kernel::if_cfg;
+/// // FOR CONFIG_64BIT
+/// // Only the active branch is compiled - inactive branch can be invalid
+/// let x = if_cfg!(if CONFIG_64BIT {
+/// 42 // valid code
+/// } else {
+/// undefined_function() // invalid, but completely ignored by compiler
+/// });
+/// assert_eq!(x, 42);
+/// ```
+///
+/// Using `cfg!()` instead would fail compilation:
+/// ```ignore
+/// // This fails because Rust must validate both branches
+/// let x = if cfg!(CONFIG_64BIT) {
+/// 42
+/// } else {
+/// undefined_function() // compilation error - function doesn't exist
+/// };
+/// assert_eq!(x, 42);
+/// ```
+#[macro_export]
+macro_rules! if_cfg {
+ (if $cond:tt { $($then:tt)* } else { $($else:tt)* }) => {{
+ #[cfg($cond)]
+ { $($then)* }
+ #[cfg(not($cond))]
+ { $($else)* }
+ }};
+ (if $cond:tt { $($then:tt)* }) => {{
+ #[cfg($cond)]
+ { $($then)* }
+ #[cfg(not($cond))]
+ { () }
+ }};
+}
+
/// Gets the C string file name of a [`Location`].
///
/// If `file_with_nul()` is not available, returns a string that warns about it.
--
2.43.0
On Thu, Aug 14, 2025 at 6:25 PM Areej Hamid <areejhamid8560@gmail.com> wrote: > > +/// # Key difference from `cfg!()` Please add an empty docs line after headers. Also before opening examples below. > +/// - `cfg!()` evaluates a configuration flag at compile time, but both branches must be valid Rust code Please use intra-doc links wherever they may work. Also please end sentences with a period in docs and comments. > +/// - `if_cfg!()` compiles only the active branch, so the inactive branch can reference > +/// functions, types, or constants that may not exist under certain configurations Perhaps we could say "... branch can, for instance, reference ...", or that it is not type checked in general, i.e. more things than undefined items are allowed. > +/// // FOR CONFIG_64BIT I would skip this line. By the way, Tamir suggested in the linked Rust for Linux issue to match the name of the upstream one in case we want to migrate to the standard library one eventually. In the commit message, I would also mention this and link to the tracking issue that Trevor mentioned: https://github.com/rust-lang/rust/issues/115585. Finally, we may want to consider putting this into somewhere else, rather than the root file of the crate. Cheers, Miguel
On Thu Aug 14, 2025 at 8:49 PM CEST, Miguel Ojeda wrote: > By the way, Tamir suggested in the linked Rust for Linux issue to > match the name of the upstream one in case we want to migrate to the > standard library one eventually. In the commit message, I would also > mention this and link to the tracking issue that Trevor mentioned: > https://github.com/rust-lang/rust/issues/115585. Didn't we also want to vendor the `cfg-if` crate? Or am I missing something? > Finally, we may want to consider putting this into somewhere else, > rather than the root file of the crate. Yeah, let's have it in a `cfg_if.rs` or whatever the macro will be called. --- Cheers, Benno
On Thu, Aug 14, 2025 at 8:49 PM Miguel Ojeda <miguel.ojeda.sandonis@gmail.com> wrote: > > Finally, we may want to consider putting this into somewhere else, > rather than the root file of the crate. By the way, there are some strange addresses in Cc: Thomas at domain dot com, Andreas at Linaro, etc. Where are you fetching those from? Please use the ones from the `MAINTAINERS` file. Thanks! Cheers, Miguel
© 2016 - 2025 Red Hat, Inc.