我有一个必须在Windows和Linux系统上运行的服务器应用程序. 这个问题始于我使用的mdns/zeroconf个模块.

我两个都用:

  1. Linuxzeroconf(https://docs.rs/zeroconf/latest/zeroconf/)
  2. Windowsastro_dnssd(https://github.com/astrohq/astro-dnssd)

Why I had to use 2 modules to do the same thing?

我不得不使用两个模块来做基本上相同的事情,因为zeroconf支持Linux但不支持Windows,astro_dnssd使用bonjour-compatibility layer on top of Avahi for Linux which no longer supported,但astro_dnssd在Windows上运行得很好

My 100:

// 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:

到目前为止,每当我在Windows上工作时,我都必须手动禁用zeroconf(通过注释该行),当我在Linux上工作时,我必须再次启用它.这是一项繁琐的工作,从长远来看是不可持续的.是否可以使用env变量或env::consts::OS来检测并在Rust中进行"有条件导入"?例如:

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

条件编译可以用Rust中的cfg来完成.

#[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;

为了提高可读性,您可能希望将特定于平台的部分放在一个模块中.

#[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

见《货册》中的Platform specific dependncies.例如,Cargo.toml中的以下几行可以满足您的需要(根据您的需要调整版本号).

[target.'cfg(windows)'.dependencies]
astro_dnssd = "0.1.0"

[target.'cfg(unix)'.dependencies]
zeroconf = "0.1.0"

Rust相关问答推荐

在rust中如何修改一个盒装函数并将其赋回?

如何从使用mockall模拟的方法中返回self?

如何访问Rust存储值的内存地址

在没有引用计数或互斥锁的情况下,可以从Rust回调函数内的封闭作用域访问变量吗?

支持TLS的模拟HTTP服务器

在铁 rust 中传递所有权

像这样的铁 rust 图案除了‘选项’之外,还有其他 Select 吗?

如何使用RefCell::JOYMOMTborrow 对 struct 不同字段的可变引用

Trait bound i8:来自u8的不满意

处理带有panic 的 Err 时,匹配臂具有不兼容的类型

将特征与具有生命周期的关联类型一起使用时的生命周期方差问题

Rust:为什么 &str 不使用 Into

为什么编译器看不到这个 `From` impl?

从Rust 的临时文件中创建引用是什么意思?

SDL2 没有在终端键上触发?

如何在 Rust 中创建最后一个元素是可变长度数组的 struct ?

Rust,使用枚举从 HashMap 获取值

深度嵌套枚举的清洁匹配臂

如何制作具有关联类型的特征的类型擦除版本?

为什么在使用 self 时会消耗 struct 而在解构时不会?