使用一些编译器,using pow
and certain other functions in a C program requires linking to the m
library。但是,某些编译器不需要这样做,并且在链接到m
库时会出错。对于带有std::thread
和pthread
的C ++,情况几乎完全相同,但CMake模块FindThreads
完全缓解了这种情况 - 是否有类似的libm模块?
检测如何处理CMake的最佳方法是什么?这是我目前的解决方案,这不太理想,因为有比CCC和MSVC更多的C编译器:
if(NOT MSVC)
target_link_libraries(my-c-target PUBLIC m)
endif()
这适用于我的目的,但我很确定有些情况会失败并需要手动用户干预,这对于不了解这种默默无闻的人来说并不好玩。理想情况下,我不希望用户必须通过命令行指定其编译器是否为weird;我想在CMake中自动检测它,因为这是CMake的全部内容。
答案 0 :(得分:7)
您应该使用CHECK_FUNCTION_EXISTS
命令检查是否可以在没有其他标志的情况下使用pow
。如果此检查失败,您可以将m
库添加到CMAKE_REQUIRED_LIBRARIES
变量,假设与libm
的链接缺失。但是您需要再次CHECK_FUNCTION_EXISTS
以确保链接足够。
示例代码:
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()
答案 1 :(得分:3)
检查的常用方法是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
函数所需的库。
答案 2 :(得分:1)
如果我的理解正确,那么链接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中进行了测试