Notice #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
I have to write it 4 times in such a short source....
C's precompiler has huge advantage here, and I think it is easy to add it ----- it can be added by using a shell script to call cc before running cargo build, ------- the only problems I guess are editor issues, syntax colors, line indent, rust-fmt things.
#![allow(dead_code)]
use std::net::*;
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
#[derive(Debug)]
pub struct RouteItem {
pfx: u8,
target: IpAddr,
ip: IpAddr,
mac: Vec<u8>,
}
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
#[cfg_attr(not(target_os = "windows"), path = "posix/posix.rs")]
mod platform;
#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
mod platform {}
pub use platform::*;
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
#[test]
fn test() {
let v = none_host_route_get().unwrap();
println!("{v:?}");
}
You might be looking for a crate like cfg_if - Rust
Rust's macro system is generally more powerful than the C preprocessor already.
5 Likes
Schard
December 19, 2024, 9:32am
3
What about organizing the code differently?
mod posix {}
mod windows {}
mod platform {
#[cfg(any(target_os = "linux", target_os = "macos"))]
pub use super::posix::*;
#[cfg(target_os = "windows")]
pub use super::windows::*;
}
mod common {
use std::net::IpAddr;
#[derive(Debug)]
pub struct RouteItem {
pfx: u8,
target: IpAddr,
ip: IpAddr,
mac: Vec<u8>,
}
#[test]
fn test() {
let v = none_host_route_get().unwrap();
println!("{v:?}");
}
}
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
pub use common::*;
pub use platform::*;
7 Likes
For what it's worth, I think a third-party attribute macro would be able to declare module-level "config variables" , something like
#[cfg_let(LMW = any(target_os = "linux", target_os = "macos", target_os = "windows"))]
mod foo {
#[cfg(LMW)] // this is expanded by the `cfg_let` macro
fn bar() {}
}
You can't just write these without cfg, for any environment, only either can be compiled
Schard
December 19, 2024, 12:27pm
6
Fair enough. Then you would have to add
#![cfg(any(target_os = "linux", target_os = "macos"))]
resp.
#![cfg(target_os = "windows")]
To the top of the respective modules.
I guess you cannot avoid some duplication of attributes in this case.
CAD97
December 20, 2024, 1:39am
7
A cute trick I've used a couple times:
macro_rules! m {( $($tt:tt)* ) => { $($tt)* }};
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
m! {
#[derive(Debug)]
pub struct RouteItem {
pfx: u8,
target: IpAddr,
ip: IpAddr,
mac: Vec<u8>,
}
#[cfg_attr(not(target_os = "windows"), path = "posix/posix.rs")]
mod platform;
pub use platform::*;
#[test]
fn test() {
let v = none_host_route_get().unwrap();
println!("{v:?}");
}
}
The macro which just takes any source and emits it unchanged enables a single #[cfg]
to apply to multiple items without putting them into a mod
.
6 Likes