Background
I have two similar structs:
mod a {
struct MyStruct {
a: usize,
b: usize,
}
}
mod b {
struct MyStruct {
a: usize,
}
}
And I want to use declarative macro to generate those structs in modules, such as:
macro_rules! my_macro {
() => {
struct MyStruct {
a: usize,
// Not know how to handle conditional compilation
b: usize,
}
};
}
#[cfg]
approach, not work
I was thinking about #[cfg]
may help, just add #[cfg(my_struct_need_b)]
above the b: usize
part in the macro rules, like:
macro_rules! my_macro {
() => {
struct MyStruct {
a: usize,
#[cfg(my_struct_need_b)]
b: usize,
}
};
}
But how do I specify my_struct_need_b
feature in module a
without module b
? In C, we can use #define
to define a feature, and use #ifdef
and #ifndef
to control condition compilation, but Rust doesn't provide a functionality similar to #define
, and I found in Rust Reference:
It is not possible to set a configuration option from within the source code of the crate being compiled.
So I think #[cfg]
may not work.
Optional macro parameter, not work too
Another way is by optional macro parameter:
macro_rules! my_macro {
($($my_b_field: /* no type can work */)?) => {
struct MyStruct {
a: usize,
$($my_b_field)?
}
};
}
And use
mod a {
my_macro!(b: usize);
}
mod b {
my_macro!();
}
But it has two problems:
- The type of
$my_b_field
can't be determined. No type can work. - The struct without
b
field may need to be defined via this macro in multiple modules, it is unwise to write some duplicated long code (fieldb
is an example, may be a very long fragment) in multiple places.
Problem
How to achieve conditional compilation in macros, and control its behavior via code?