如何修改CMakeList.txt:找到库,但存在链接错误
How to modify CMakeList.txt: library found, but there are linking errors
我正在创建一个用 cmake 构建的 C 库,使用 Mac OS 进行开发。在CMakeList.txt中,我有以下
#htslib
find_package(htslib REQUIRED)
include_directories(${HTSLIB_INCLUDE_DIR})
target_link_libraries(projectname ${HTSlib_LIBRARIES})
在 cmake ..
上输出
Found hstlib
但是,在 make
之后,我遇到了链接器错误:
clang: error: linker command failed with exit code 1 (use -v to see invocation)
所以...它可以找到库,并且库肯定是用sudo make install
安装的,但是只有这个库有链接错误。
(1) 我猜 find_package(htslib REQUIRED)
正在寻找其他东西。我如何找出什么?
(2) 如何在 CMakeList.txt 中明确写入以找到我知道已正确安装的库?
- 使用
VERBOSE=1 make
查看链接器输出。搜索 -lhtslib
- 阅读特定
Find<LIB>.cmake
的文档。
您的具体问题:
- "How do I find what CMake found":使用
cmake-gui
或ccmake
。它们都显示相同的信息,但一个是 GUI,另一个是 Curses 界面。在高级模式中("t" on ccmake
),您将找到搜索包的所有变量。此外,您可以使用 MESSAGE(STATUS "Found htslib at: ${htslib_LIBRARIES}")
.
- "How to explicitly write in CMakeLists.txt where the library is?"请不要那样做! CMake 旨在准确地抽象出这种信息。您有两个选择,第一个是好的:在命令行(或在上述 GUI 中)配置 cmake 以获得
CMAKE_MODULES_PATH
或更具体的库提示 -D htslib_PATH=/usr/local/.../
(指向目录libhts.dylib
所在的位置)。更糟糕的解决方案是向 find_package
提供提示。 find_package(htslib REQUIRED PATH /usr/local/lib)
或 find_package(htslib REQUIRED HINT /usr/local/lib /some/second/path/where/it/may/be)
.
解决方案
您的链接项目有自定义 FindHTSlib.cmake
link。这个使用 pkg_config
配置库。为了重现您的问题,我使用了 brew 来安装 htslib
。 pkg-config 文件可以在 /usr/local/Cellar/htslib/1.8/lib/htslib.pc
下找到(对我来说,但 brew info htslib
告诉你)。所以,让我们给 CMake 所需的提示。
我无法测试这个,因为对我来说它直接找到了 htslib 包,没有进一步的提示。
git clone https://github.com/D-Lo/bamdb # I am using version f5f03d0
mkdir -p bamdb/build; cd bamdb/build
brew install ck htslib lmdb
cmake .. # -G Ninja recommended, but needs brew install ninja
make # lot's of missing symbols
我建议将 CMakeLists.txt
CMake 的最低要求版本从 2.8 更改为 3.10
(或至少 3.6)。
这是我得到的错误:
[ 62%] Linking C shared library libbamdb.dylib
/usr/local/Cellar/cmake/3.11.1/bin/cmake -E cmake_link_script CMakeFiles/libbamdb.dir/link.txt --verbose=1
/Library/Developer/CommandLineTools/usr/bin/cc -Wall -g -std=gnu99 -fPIC -dynamiclib -Wl,-headerpad_max_install_names -o libbamdb.dylib -install_name @rpath/libbamdb.dylib CMakeFiles/libbamdb.dir/src/bam_api.c.o CMakeFiles/libbamdb.dir/src/bam_lmdb.c.o CMakeFiles/libbamdb.dir/src/bamdb.c.o
Undefined symbols for architecture x86_64:
"_bam_destroy1", referenced from:
_get_bam_row in bam_api.c.o
_deserialize_func in bam_lmdb.c.o
这可以通过在 CMakeLists.txt
行 add_library(libbamdb ${SOURCES})
:
之后添加以下行来解决
target_link_libraries(libbamdb ${LIBS})
一些进一步的注意事项:您现在有一个带有 main
函数的库。这是因为 ${SOURCES}
用于构建可执行文件和库。这可能会产生意想不到的副作用。除非需要,否则不要这样做。
我正在创建一个用 cmake 构建的 C 库,使用 Mac OS 进行开发。在CMakeList.txt中,我有以下
#htslib
find_package(htslib REQUIRED)
include_directories(${HTSLIB_INCLUDE_DIR})
target_link_libraries(projectname ${HTSlib_LIBRARIES})
在 cmake ..
Found hstlib
但是,在 make
之后,我遇到了链接器错误:
clang: error: linker command failed with exit code 1 (use -v to see invocation)
所以...它可以找到库,并且库肯定是用sudo make install
安装的,但是只有这个库有链接错误。
(1) 我猜 find_package(htslib REQUIRED)
正在寻找其他东西。我如何找出什么?
(2) 如何在 CMakeList.txt 中明确写入以找到我知道已正确安装的库?
- 使用
VERBOSE=1 make
查看链接器输出。搜索-lhtslib
- 阅读特定
Find<LIB>.cmake
的文档。
您的具体问题:
- "How do I find what CMake found":使用
cmake-gui
或ccmake
。它们都显示相同的信息,但一个是 GUI,另一个是 Curses 界面。在高级模式中("t" onccmake
),您将找到搜索包的所有变量。此外,您可以使用MESSAGE(STATUS "Found htslib at: ${htslib_LIBRARIES}")
. - "How to explicitly write in CMakeLists.txt where the library is?"请不要那样做! CMake 旨在准确地抽象出这种信息。您有两个选择,第一个是好的:在命令行(或在上述 GUI 中)配置 cmake 以获得
CMAKE_MODULES_PATH
或更具体的库提示-D htslib_PATH=/usr/local/.../
(指向目录libhts.dylib
所在的位置)。更糟糕的解决方案是向find_package
提供提示。find_package(htslib REQUIRED PATH /usr/local/lib)
或find_package(htslib REQUIRED HINT /usr/local/lib /some/second/path/where/it/may/be)
.
解决方案
您的链接项目有自定义 FindHTSlib.cmake
link。这个使用 pkg_config
配置库。为了重现您的问题,我使用了 brew 来安装 htslib
。 pkg-config 文件可以在 /usr/local/Cellar/htslib/1.8/lib/htslib.pc
下找到(对我来说,但 brew info htslib
告诉你)。所以,让我们给 CMake 所需的提示。
我无法测试这个,因为对我来说它直接找到了 htslib 包,没有进一步的提示。
git clone https://github.com/D-Lo/bamdb # I am using version f5f03d0
mkdir -p bamdb/build; cd bamdb/build
brew install ck htslib lmdb
cmake .. # -G Ninja recommended, but needs brew install ninja
make # lot's of missing symbols
我建议将 CMakeLists.txt
CMake 的最低要求版本从 2.8 更改为 3.10
(或至少 3.6)。
这是我得到的错误:
[ 62%] Linking C shared library libbamdb.dylib
/usr/local/Cellar/cmake/3.11.1/bin/cmake -E cmake_link_script CMakeFiles/libbamdb.dir/link.txt --verbose=1
/Library/Developer/CommandLineTools/usr/bin/cc -Wall -g -std=gnu99 -fPIC -dynamiclib -Wl,-headerpad_max_install_names -o libbamdb.dylib -install_name @rpath/libbamdb.dylib CMakeFiles/libbamdb.dir/src/bam_api.c.o CMakeFiles/libbamdb.dir/src/bam_lmdb.c.o CMakeFiles/libbamdb.dir/src/bamdb.c.o
Undefined symbols for architecture x86_64:
"_bam_destroy1", referenced from:
_get_bam_row in bam_api.c.o
_deserialize_func in bam_lmdb.c.o
这可以通过在 CMakeLists.txt
行 add_library(libbamdb ${SOURCES})
:
target_link_libraries(libbamdb ${LIBS})
一些进一步的注意事项:您现在有一个带有 main
函数的库。这是因为 ${SOURCES}
用于构建可执行文件和库。这可能会产生意想不到的副作用。除非需要,否则不要这样做。