Detecting the presence of a system function at build time

Hello,

I have some code that uses the nix crate and I need to use the nix::sys::stat::utimensat function provided by it. This function is just a wrapper over the libc crate's libc::utimensat function.

Now the problem is that not all systems implement the utimensat system call. In particular, macOS 10.13 does not, and I have to support this system (because that's what I get on Travis CI when I have to use OSXFUSE). When building on those systems, my code fails at link time with an undefined symbol error: https://travis-ci.org/jmmv/sandboxfs/jobs/647291509

So I'd like my code to conditionally use utimensat if I know is present or fall back to utimes if not.

My first instinct was to go for #[cfg] and check for the OS name... but then found out that there is no way to check the version (right?). Regardless, even if this were possible, it'd still be a suboptimal way of going about this because I'd rather not make assumptions about what features are present based on the OS name+version pair.

So in the C world, I'd just write an autoconf check to test for the presence of utimensat and then make my code conditional on that. How can I do something similar in Rust? I can imagine some build.rs magic? Is there a better way?

Thanks!

Perhaps autocfg could be extended to do this. Like autoconf, it attempts to compile a test program, then sets a config variable based on the result. However, I don't think there's currently a way to tell it to link its test programs to third-party crates, so it can't test for paths within nix or libc.

1 Like

Ah, I encountered autocfg a few minutes earlier than your reply but concluded it wouldn't be useful because I was looking at it from the point of view of building a C program, not a Rust program that calls into the functions I'm interested in. But that'd be nice.

I've also found cc, which almost lets me do what I need via try_compile... except I'd need linking (and then this feature wouldn't really fit with the spirit behind this crate).

It sounds like creating a dummy program that links to the function and enables a feature flag appropriately is the right solution here. Anything else (e.g. checking the OS) is just guessing.

Is there any pressing reason why this wouldn't fit with the spirit of the crate? If you're targeting *nix systems I think it's safe to assume there's a C compiler installed.

The cc crate seems focused on creating a static library for linking into the Rust binary. Hence adding something like try_link that creates a binary to later be discarded seems unrelated. But not my crate; I guess I should file a feature request or send a patch...