Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use Linux-specific APIs and libraries only on Linux builds with CMake?

I have a project that I run on Linux (primarily), but sometimes on Darwin/Mac OS X. I use CMake to generate Makefiles on Linux and an Xcode project on Mac OS X. So far, this has worked well.

Now I want to use some Linux-specific functions (clock_gettime() and related functions). I get linker errors on Mac OS X when I try to use clock_gettime(), so I assume it is only available on Linux. I am prepared to introduce conditionally-compiled code in the .c files to use clock_gettime() on Linux and plain old clock() on Mac OS. (BTW I was planning to use #include <unistd.h> and #if _POSIX_TIMERS > 0 as the preprocessor expression, unless someone has a better alternative.)

Things get tricky when it comes to the CMakeLists.txt file. What is the preferred way of introducing linkage to Linux-specific APIs only under the Linux build in a cross-platform CMake project?

Note: An earlier revision of this question contained references to glibc, which was overly specific and confusing. The question is really about the right way to use Linux-specific APIs and libraries in a cross-platform CMake project.

like image 924
Randall Cook Avatar asked Dec 16 '22 05:12

Randall Cook


2 Answers

Abstracting away from your examples, and answering only this question:

How to use Linux-specific APIs and libraries only on Linux builds with CMake?

CMake provides numerous useful constants that you can check in order to determine which system you are running:

if (${UNIX})
  # *nix-specific includes or actions
elsif (${WIN32})
  # Windows-specific includes or actions
elsif (${APPLE})
  # ...
endif (${UNIX})
like image 131
Olha Puzhay Avatar answered Jan 13 '23 05:01

Olha Puzhay


(I know you're asking about glibc, but you really want to know whether clock_gettime is present, right? But nothing in your question is Linux-specific...)

If you want to check for clock_gettime, you can use the preprocessor. If clock_gettime is present, then _POSIX_TIMERS will be defined. The clock_gettime function is part of an optional POSIX extension (see spec), so it is not Linux-specific but not universal either. Mac OS X does not have clock_gettime: it is not declared in any header nor defined in any library.

#include <time.h>
#include <unistd.h> /* for _POSIX_TIMERS definition, if present */

#if _POSIX_TIMERS
...use clock_gettime()...
#else
...use something else...
#endif

This doesn't solve the problem that you still have to link with -lrt on Linux. This is typically solved with something like AC_CHECK_LIB in Autoconf, I'm sure there's an equivalent in CMake.

From man 2 clock_gettime:

On POSIX systems on which these functions are available, the symbol _POSIX_TIMERS is defined in <unistd.h> to a value greater than 0. The symbols _POSIX_MONOTONIC_CLOCK, _POSIX_CPUTIME, _POSIX_THREAD_CPUTIME indicate that CLOCK_MONOTONIC, CLOCK_PROCESS_CPUTIME_ID, CLOCK_THREAD_CPUTIME_ID are available. (See also sysconf(3).)

On Darwin you can use the mach_absolute_time function if you need a high-resolution monotonic clock. If you don't need the resolution or monotonicity, you should probably be using gettimeofday on both platforms.

like image 32
Dietrich Epp Avatar answered Jan 13 '23 05:01

Dietrich Epp