代码之家  ›  专栏  ›  技术社区  ›  LB--

在C中使用pow时,CMake可以检测我是否需要链接到libm吗?

  •  12
  • LB--  · 技术社区  · 10 年前

    对于一些编译器, using pow and certain other functions in a C program requires linking to the m library 然而,一些编译器不需要这个,在链接到 男性 图书馆。C++也存在几乎相同的情况 std::thread pthread ,但是CMake模块 FindThreads 完全缓解了这种情况-libm有类似的模块吗?

    检测CMake的最佳方法是什么?这是我目前的解决方案,它不太理想,因为除了GCC和MSVC之外,还有更多的C编译器:

    if(NOT MSVC)
        target_link_libraries(my-c-target PUBLIC m)
    endif()
    

    这符合我的目的,但我很确定在某些情况下它会失败,需要手动用户干预,这对不了解这种模糊性的人来说并不有趣。理想情况下,我不希望用户必须指定他们的编译器是否 weird 或者不通过命令行;我想在CMake中自动检测它,因为这是CMake的全部要点。

    3 回复  |  直到 9 年前
        1
  •  11
  •   einpoklum    7 年前

    你应该使用 CHECK_FUNCTION_EXISTS 命令检查是否 pow 可以在没有额外标志的情况下使用。如果此检查失败,您可以添加 m 图书馆到 CMAKE_REQUIRED_LIBRARIES 变量,假设链接 libm 这就是缺失的。但你需要 检查功能存在 再次确保链接足够。

    示例代码:

    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()
    
        2
  •  4
  •   Tsyvarev    10 年前

    检查某些代码是否对编译器正确的常见方法是 try_compile .

    使用方式。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 功能。

        3
  •  4
  •   Андрей Тернити    2 年前

    如果我理解正确,链接 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(${PROJECT_NAME} PUBLIC ${POW_LIBS})
    

    使用Linux x86_64、glibc 2.23 cmake 3.13.2进行测试

    推荐文章