Может ли CMake определить, нужно ли мне ссылаться на libm при использовании pow в C?
С некоторыми компиляторами, используя pow
и некоторые другие функции в программе на C требуют ссылки на m
библиотека Тем не менее, некоторые компиляторы не требуют этого и выдают ошибку при соединении с m
библиотека. Практически идентичная ситуация существует для C++ с std::thread
а также pthread
, но модуль CMake FindThreads
полностью облегчает это - есть ли подобный модуль для libm?
Как лучше всего определить, что делать с CMake? Это мое текущее решение, которое далеко не идеально, потому что компиляторов Си гораздо больше, чем просто GCC и MSVC:
if(NOT MSVC)
target_link_libraries(my-c-target PUBLIC m)
endif()
Это работает для моих целей, но я почти уверен, что бывают случаи, когда он не срабатывает и требует ручного вмешательства пользователя, что неинтересно для тех, кто не знает об этой неизвестности. В идеале я не хочу, чтобы пользователь определял, является ли его компилятор странным или нет, через командную строку; Я хочу обнаружить это автоматически в CMake, так как это весь смысл CMake.
2 ответа
Вы должны использовать модуль CHECK_FUNCTION_EXISTS, чтобы проверить, pow
можно использовать без дополнительных флагов. Если эта проверка не пройдена, вы можете добавить m
библиотека для CMAKE_REQUIRED_LIBRARIES
переменная и запустить CHECK_FUNCTION_EXISTS
снова.
Образец кода:
include(CheckFunctionExists)
CHECK_FUNCTION_EXISTS(pow RESULT)
if(NOT RESULT)
unset(RESULT)
list(APPEND CMAKE_REQUIRED_LIBRARIES m)
CHECK_FUNCTION_EXISTS(pow RESULT)
if(RESULT)
target_link_libraries(yourtarget m)
else()
message(FATAL_ERROR "No pow() found")
endif()
endif()
Если я правильно понимаю, ссылка libm
всегда предпочтительнее, если он существует.
Итак, CheckLibraryExists работает.
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})
протестировано с Linux x86_64, glibc 2.23 cmake 3.13.2
Обычный способ проверки правильности кода для компилятора - 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})
Запись в кэш POW_LIBS
содержит библиотеки, необходимые для использования pow
функция.