Linker 链接到特定库

Linker 链接到特定库,linker,cmake,lapack,Linker,Cmake,Lapack,我正在编译一个简单的测试程序,它使用了lapack,但是我安装了3个版本的lapack库(一个来自/usr/lib中的苹果,一个来自/opt/local/lib中的macports,还有一个我自己安装在/usr/local/lib中) 我有以下CMakeLists.txt文件: cmake_minimum_required(VERSION 3.0) project(delme) include_directories(../../include /usr/local/include/boos

我正在编译一个简单的测试程序,它使用了
lapack
,但是我安装了3个版本的lapack库(一个来自
/usr/lib
中的苹果,一个来自
/opt/local/lib
中的macports,还有一个我自己安装在
/usr/local/lib
中)

我有以下CMakeLists.txt文件:

cmake_minimum_required(VERSION 3.0)

project(delme)

include_directories(../../include /usr/local/include/boost-numeric-bindings)

find_library(lapack_LIBRARY NAMES lapack liblapack HINTS /usr/local/lib )
find_library(atlas_LIBRARY NAMES atlas libatlas HINTS /usr/local/lib )
find_library(cblas_LIBRARY NAMES cblas libcblas HINTS /usr/local/lib )

add_executable(delme test.cpp main.cpp)

target_link_libraries(delme lapack atlas cblas)

install(TARGETS delme RUNTIME DESTINATION bin)
调用
cmake.&使VERBOSE=1
,我得到的输出以:

Linking CXX executable delme
/opt/local/bin/cmake -E cmake_link_script CMakeFiles/delme.dir/link.txt --verbose=1
/usr/bin/c++    -Wl,-search_paths_first -Wl,-headerpad_max_install_names   CMakeFiles/delme.dir/test.cpp.o CMakeFiles/delme.dir/main.cpp.o  -o delme  -llapack -latlas -lcblas
Undefined symbols for architecture x86_64:
  "_clapack_dgetrf", referenced from:
      boost::numeric::bindings::atlas::detail::getrf(CBLAS_ORDER, int, int, double*, int, int*) in main.cpp.o
  "_clapack_dgetri", referenced from:
      boost::numeric::bindings::atlas::detail::getri(CBLAS_ORDER, int, double*, int, int const*) in main.cpp.o
  "_clapack_dpotrf", referenced from:
      boost::numeric::bindings::atlas::detail::potrf(CBLAS_ORDER, CBLAS_UPLO, int, double*, int) in main.cpp.o
ld: symbol(s) not found for architecture x86_64
这些符号出现在
/usr/local/lib
和macports版本中,但不是苹果的版本,苹果的版本似乎就是它链接的对象。 如果我手动将
-L/usr/local/lib
添加到CMake生成的文件
CMakeFiles/delme.dir/link.txt
,则它可以正常编译


我的问题是,如何指示cmake在其链接命令(或其他替代命令)中包含
-L/usr/local/lib
,以便使用
/usr/local/lib
中的版本?

其他库路径之一可能位于cmake缓存变量中。CMake首先找到库版本。找到库后,除非清除缓存,否则“查找库”不会再次查询同一库

如中所述,命令
find_library
在搜索库时使用以下顺序:

  • 在cmake特定缓存变量中指定的搜索路径
  • 在cmake特定环境变量中指定的搜索路径
  • 搜索提示选项指定的路径
  • 搜索标准系统环境变量
  • 搜索当前系统的平台文件中定义的cmake变量
  • 搜索“路径”选项指定的路径或命令的简写版本
  • 基于这些步骤,CMake在步骤1或2中找到了不同版本的库。 存在允许跳过部分或所有这些步骤的参数

  • 使用
    无默认路径
    无默认路径
    跳过
  • 使用
    无默认路径
    无环境路径
    跳过
  • 使用
    无默认路径跳过
    
  • 使用
    无默认路径
    无系统环境路径
    跳过
  • 使用
    无默认路径
    无系统路径
    跳过
  • 使用
    无默认路径跳过
  • 所以一开始看起来你会跳过步骤1和2,但根据Kitware的说法,你不应该把绝对路径放在
    提示下。关于暗示,美国

    这些应该是由系统自省计算的路径,例如由已经找到的另一个项目的位置提供的提示。硬编码猜测应使用路径选项指定

    当然,今天使用提示可能会奏效,但如果您希望将来验证您的CMake文件,我建议您遵循他们的建议。因此,您的命令与此类似,以防止CMake执行步骤1、2、3和4:

    find_library(lapack_LIBRARY 
        NAMES lapack liblapack 
        PATHS /usr/local/lib 
        NO_CMAKE_PATH
        NO_CMAKE_ENVIRONMENT_PATH
        NO_SYSTEM_ENVIRONMENT_PATH
        NO_CMAKE_SYSTEM_PATH
    )
    
    另一种选择是设置在步骤1或2中搜索到的变量之一,但这更难做到正确,而且很容易被未来的更改破坏


    另外,请注意,避免使用
    cmake.
    创建源代码内构建。创建另一个文件夹,如
    build
    ,然后从那里运行cmake命令。这样可以更轻松地删除cmake生成的文件并重新开始。此外,它不会使源代码树混乱。

    其他库路径之一可能位于cmake缓存变量中。CMake首先找到库版本。找到库后,除非清除缓存,否则“查找库”不会再次查询同一库

    如中所述,命令
    find_library
    在搜索库时使用以下顺序:

  • 在cmake特定缓存变量中指定的搜索路径
  • 在cmake特定环境变量中指定的搜索路径
  • 搜索提示选项指定的路径
  • 搜索标准系统环境变量
  • 搜索当前系统的平台文件中定义的cmake变量
  • 搜索“路径”选项指定的路径或命令的简写版本
  • 基于这些步骤,CMake在步骤1或2中找到了不同版本的库。 存在允许跳过部分或所有这些步骤的参数

  • 使用
    无默认路径
    无默认路径
    跳过
  • 使用
    无默认路径
    无环境路径
    跳过
  • 使用
    无默认路径跳过
    
  • 使用
    无默认路径
    无系统环境路径
    跳过
  • 使用
    无默认路径
    无系统路径
    跳过
  • 使用
    无默认路径跳过
  • 所以一开始看起来你会跳过步骤1和2,但根据Kitware的说法,你不应该把绝对路径放在
    提示下。关于暗示,美国

    这些应该是由系统自省计算的路径,例如由已经找到的另一个项目的位置提供的提示。硬编码猜测应使用路径选项指定

    当然,今天使用提示可能会奏效,但如果您希望将来验证您的CMake文件,我建议您遵循他们的建议。因此,您的命令与此类似,以防止CMake执行步骤1、2、3和4:

    find_library(lapack_LIBRARY 
        NAMES lapack liblapack 
        PATHS /usr/local/lib 
        NO_CMAKE_PATH
        NO_CMAKE_ENVIRONMENT_PATH
        NO_SYSTEM_ENVIRONMENT_PATH
        NO_CMAKE_SYSTEM_PATH
    )
    
    另一种选择是设置在步骤1或2中搜索到的变量之一,但这更难做到正确,而且很容易被未来的更改破坏

    另外,请注意,避免使用
    cmake.
    创建源代码内构建。创建另一个文件夹,如
    build
    ,然后从那里运行cmake命令。这样可以更轻松地删除cmake生成的文件并重新开始。也是