Running tests and compiling examples only for specific compilation targets


#1

I have a crate that provides a cross-platform abstraction using a trait, but then also has specific structs for each platform that also publically exposes additional functionality. In this way consumers of my library can use either the cross-platform API or a platform-specific API depending on what functionality they need.

I’m having trouble with tests and examples that are platform-specific. I’ve broken up my library so the platform-specific code live in individual files with lib.rs providing the cross-platform abstractions. I was planning to write my tests and examples such that the platform-specific code are in entire files. But if I put a #![cfg(unix)] at the top of an example, running cargo test on Windows will result in an error: main function not found.

So it’s not clear to me what the current best practices are for examples or tests that are platform-specific when trying to cargo test on other platforms as I would’ve expected the above setup to be the “best”.

Has anyone solved this problem to their satisfaction?


#2

That sounds like an issue with how rustc is injecting the test harness. Basically I believe it’s adding a fn main to your test file, but then because the top level module is cfged out that is getting removed before it actually compiling your code.

As a workaround you should be able to put all your tests inside a module with #[cfg(unix)] on it, something like

#[cfg(unix)]
mod unix {
    extern crate bar;

    #[test]
    fn test_foo() { assert_eq!(bar::one(), 1) }
}

that way the top level test harness will still be compiled, but there will be zero tests that it will discover.

I wonder if there is some way the test harness injection could be changed that will allow this case, maybe do something like rustdoc where feature attributes are lifted up, then the rest of the code in the file is injected into an unnamed module so cfgs will not affect the test harness itself.


#3

This wasn’t a problem for test but for exmples, so they’re CLI executables, so I don’t think putting any of that code in a mod would do anything. I worked around this by putting the use statements inside a main(){} with an appropriate #cfg and another empty main in the file with the inverse of that cfg.

I do think this behavior shouldn’t require a work around, as you mentioned in your last paragraph. Should I bring this up as an issue on rust-lang/rust or post to developer.rust-lang.org to raise this issue?