在 C 中使用 pow 时,CMake 能否检测到我是否需要 link 到 libm?
Can CMake detect if I need to link to libm when using pow in C?
对于某些编译器,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 做什么的最佳方法是什么?这是我目前的解决方案,不太理想,因为 C 编译器比 GCC 和 MSVC 多得多:
if(NOT MSVC)
target_link_libraries(my-c-target PUBLIC m)
endif()
这适用于我的目的,但我很确定在某些情况下它会失败并需要用户手动干预,这对于不了解这种晦涩难懂的人来说并不有趣。理想情况下,我不希望用户必须通过命令行指定他们的编译器是否为 weird;我想在 CMake 中自动检测它,因为这是 CMake 的全部要点。
检查某些代码对编译器是否正确的常用方法是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
功能所需的库。
您应该使用 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()
如果我理解正确,链接 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
进行测试
对于某些编译器,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 做什么的最佳方法是什么?这是我目前的解决方案,不太理想,因为 C 编译器比 GCC 和 MSVC 多得多:
if(NOT MSVC)
target_link_libraries(my-c-target PUBLIC m)
endif()
这适用于我的目的,但我很确定在某些情况下它会失败并需要用户手动干预,这对于不了解这种晦涩难懂的人来说并不有趣。理想情况下,我不希望用户必须通过命令行指定他们的编译器是否为 weird;我想在 CMake 中自动检测它,因为这是 CMake 的全部要点。
检查某些代码对编译器是否正确的常用方法是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
功能所需的库。
您应该使用 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()
如果我理解正确,链接 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
进行测试