我正在编译一个使用lapack
的简单测试程序,但我安装了3个版本的lapack库(一个来自Apple /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 . && make 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版本中,但不是Apple的版本,它似乎是它所链接的版本。
如果我手动将-L/usr/local/lib
添加到CMake生成的文件CMakeFiles/delme.dir/link.txt
,那么它编译得很好。
我的问题是,如何指示cmake在其链接命令(或其他替代方案)中包含-L/usr/local/lib
,以便它使用/usr/local/lib
中的版本?
答案 0 :(得分:3)
您的target_link_libraries
电话中看起来好像正在使用错误的库。正确的电话是:
target_link_libraries(delme ${lapack_LIBRARY} ${atlas_LIBRARY} ${cblas_LIBRARY})
这将使链接命令使用find_library
调用找到的库而不是默认库。
答案 1 :(得分:1)
其他库路径之一可能位于cmake缓存变量中。 CMake首先发现了库版本。找到库后,除非清除缓存,否则find_library不会再次查询同一个库。
如documentation中所述,命令find_library
在搜索库时使用以下顺序:
基于这些步骤,CMake在步骤1或2中找到了不同版本的库。 存在允许跳过部分或全部步骤的参数。
NO_DEFAULT_PATH
或NO_CMAKE_PATH
。 NO_DEFAULT_PATH
或NO_CMAKE_ENVIRONMENT_PATH
。 NO_DEFAULT_PATH
。 NO_DEFAULT_PATH
或NO_SYSTEM_ENVIRONMENT_PATH
。 NO_DEFAULT_PATH
或NO_CMAKE_SYSTEM_PATH
。 NO_DEFAULT_PATH
首先看起来你会跳过第1步和第2步,但根据Kitware,你不应该在HINTS
下放置绝对路径。关于提示,CMake documentation州
这些应该是系统内省计算的路径,例如由已找到的另一个项目的位置提供的提示。应使用PATHS选项指定硬编码猜测。
当然,今天可能会使用HINTS,但如果您希望将来证明您的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生成的文件并重新开始。它也不会使源树混乱。