I have a server application that had to be run on both Windows and Linux system. the problem starts with mdns/zeroconf modules that I use.
I use both:
zeroconf for Linux (https://docs.rs/zeroconf/latest/zeroconf/)astro_dnssd for Windows (https://github.com/astrohq/astro-dnssd)Why I had to use 2 modules to do the same thing?
I had to use 2 modules to do basically the same thing since zeroconf supports Linux but doesn't support Windows and astro_dnssd use bonjour-compatibility layer on top of Avahi for Linux which no longer supported, but astro_dnssd works fine on Windows
My main.rs:
// asto_dnssd can be compiled on both Windows and Linux, but doesn't work as intended on Linux
use astro_dnssd::DNSServiceBuilder;
// this modules doesn't even compile on Windows
// so I had to manually disable this line and everything that uses zeroconf to run my server app on Windows, including the "Cargo.toml" file
use zeroconf::prelude::*;
use zeroconf::{MdnsService, ServiceRegistration, ServiceType, TxtRecord};
The problem:
As of now, I had to manually disable zeroconf (by commenting the line) whenever I work on Windows and had to enable it again when I work on Linux. This is tedious work and unsustainable in the long run. Is is possible to use env variable or env::consts::OS to detect and make the "conditional import" in Rust? For example:
let current_os = env::consts::OS;
match current_os {
"windows" => {
use astro_dnssd::DNSServiceBuilder;
//... the rest of the code
}
"linux" => {
use zeroconf::prelude::*;
use zeroconf::{MdnsService, ServiceRegistration, ServiceType, TxtRecord};
// ... the rest of the code
}
_ => {
panic!("This operating system is not supported yet")
}
};
Conditional Imports
Conditional compilation can be done with cfg in Rust.
#[cfg(target_os = "linux")]
use zeroconf::prelude::*;
#[cfg(target_os = "linux")]
use zeroconf::{MdnsService, ServiceRegistration, ServiceType, TxtRecord};
#[cfg(target_os = "windows")]
use astro_dnssd::DNSServiceBuilder;
To improve readability, you may want to put the platform-specific parts within a module.
#[cfg(target_os = "linux")]
mod details {
use zeroconf::prelude::*;
use zeroconf::{MdnsService, ServiceRegistration, ServiceType, TxtRecord};
// Define structs, functions, ...
pub fn perform_platform_specific_operation() {}
}
#[cfg(target_os = "windows")]
mod details {
use astro_dnssd::DNSServiceBuilder;
// Define structs, functions, ...
pub fn perform_platform_specific_operation() {}
}
fn main() {
details::perform_platform_specific_operation();
}
Conditional Cargo Dependencies
See Platform specific dependncies from the Cargo Book. For example, the following lines in the Cargo.toml does what you want (adapt the version number to your own needs).
[target.'cfg(windows)'.dependencies]
astro_dnssd = "0.1.0"
[target.'cfg(unix)'.dependencies]
zeroconf = "0.1.0"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With