Can CMake detect if I need to link to libm when using pow in C?

If I understand correctly, linking libm is always preferred if it is exists.

So, CheckLibraryExists works.

CMakeLists.txt

set(POW_LIBS "")
include(CheckLibraryExists)
check_library_exists(m pow "" LIBM)
if(LIBM)
    list(APPEND POW_LIBS "m")
endif()

...
target_link_libraries(my-c-target PUBLIC ${POW_LIBS})

tested with Linux x86_64, glibc 2.23 cmake 3.13.2


Common way for check, whether some code is correct for the compiler, is try_compile.

use_pow.c:

#include <math.h>
int main(void) {return pow(2, 2.5);}

CMakeLists.txt:

...
if(NOT DEFINED POW_LIBS)
    try_compile(pow_use_m # RESULT_VAR
                check_pow # bindir
                use_pow.c # srcfile
                LINK_LIBRARIES m)
    if(pow_use_m)
        set(POW_LIBS m CACHE INTERNAL "Libraries for use pow")
    else()
        set(POW_LIBS "" CACHE INTERNAL "Libraries for use pow")
    endif()
endif()

...
target_link_libraries(my-c-target PUBLIC ${POW_LIBS})

Cache entry POW_LIBS contains libraries needed for use pow function.


You should use the CHECK_FUNCTION_EXISTS command to check if pow can be used without additional flags. If this check fails, you can add m library to CMAKE_REQUIRED_LIBRARIES variable, assuming that linking against libm is what's missing. But you'll need to CHECK_FUNCTION_EXISTS again to make sure the linking is sufficient.

Sample code:

include(CheckFunctionExists)

if(NOT POW_FUNCTION_EXISTS AND NOT NEED_LINKING_AGAINST_LIBM)
  CHECK_FUNCTION_EXISTS(pow POW_FUNCTION_EXISTS)
  if(NOT POW_FUNCTION_EXISTS)
      unset(POW_FUNCTION_EXISTS CACHE)
      list(APPEND CMAKE_REQUIRED_LIBRARIES m)
      CHECK_FUNCTION_EXISTS(pow POW_FUNCTION_EXISTS)
      if(POW_FUNCTION_EXISTS)
          set(NEED_LINKING_AGAINST_LIBM True CACHE BOOL "" FORCE)
      else()
          message(FATAL_ERROR "Failed making the pow() function available")
      endif()
  endif()
endif()

if (NEED_LINKING_AGAINST_LIBM)
     target_link_libraries(your_target_here m)
endif()

Tags:

C

Gcc

Cmake

Libm