CMake 已经链接库并且符号存在,但出现"ld未定义引用错误"

4
我有一个如下的CMake文件:
cmake_minimum_required(VERSION 3.12)
project(cpp-service VERSION 0.1.0)

add_compile_definitions(OPENVDB_7_ABI_COMPATIBLE)
list(APPEND CMAKE_MODULE_PATH "/usr/local/lib64/cmake/OpenVDB/")
find_package(OpenVDB REQUIRED)

### https://dev59.com/lMLra4cB1Zd3GeqPDzCZ#69290761
list(APPEND CMAKE_MODULE_PATH "deps/tbb/cmake/")
find_package(TBB REQUIRED)

add_executable(${PROJECT_NAME}
    src/main.cpp
)

target_link_libraries(${PROJECT_NAME} PUBLIC
    OpenVDB::openvdb
    TBB::tbb
)


所有的库都已经通过CMake链接到了程序中,这些符号也全部可用。但是,在链接器执行过程中无法找到这些符号,导致出现许多类似于以下错误的问题:
...
[ 92%] Building CXX object ...
[ 96%] Building CXX object ...
[100%] Linking CXX executable cpp-service
/usr/lib64/gcc/x86_64-suse-linux/7/../../../../x86_64-suse-linux/bin/ld: CMakeFiles/cpp-service.dir/src/main.cpp.o: in function `hollowing::mesh_to_grid(hollowing::Contour const&, openvdb::v7_2::math::Transform const&, float, float, int)':
/home/m3/repos/cpp-service/src/hollowing.h:268: undefined reference to `openvdb::v7_2::initialize()'
/usr/lib64/gcc/x86_64-suse-linux/7/../../../../x86_64-suse-linux/bin/ld: CMakeFiles/cpp-service.dir/src/main.cpp.o: in function `tbb::task_group_context::task_group_context(tbb::task_group_context::kind_type, unsigned long)':
/home/m3/repos/cpp-service/deps/tbb/include/tbb/task.h:499: undefined reference to `tbb::task_group_context::init()'
...

猜测

有一个猜测是我正在遇到这个问题

......似乎gcc现在将连接器标志--as-needed发送给ld。 这会导致丢弃任何未具有链接所需符号的指定库。

尝试过

我尝试了这个,但没有效果。 相同的链接错误被抛出:

target_link_options(${PROJECT_NAME} PUBLIC
    "LINKER:-no-as-needed"
)

问题

我在调试这个问题时已经没有其他选择了。有人有什么建议可以尝试吗?


CMake命令

export CC=/usr/bin/gcc-11
export CXX=/usr/bin/g++-11
mkdir build
cd build
cmake ..
cmake --build . --verbose >> log.txt 2>&1     # Save log to file.

编译命令

CMake 显示的编译日志如下:

[  3%] Building CXX object CMakeFiles/cpp-service.dir/src/main.cpp.o
/usr/bin/g++-11 -I/home/m3/repos/cpp-service/deps/tbb/include -I/.../more/include/paths/.../... -g -std=c++17 -MD -MT CMakeFiles/cpp-service.dir/src/main.cpp.o -MF CMakeFiles/cpp-service.dir/src/main.cpp.o.d -o CMakeFiles/cpp-service.dir/src/main.cpp.o -c /home/m3/repos/cpp-service/src/main.cpp

链接命令

CMake记录显示链接命令为:

[100%] Linking CXX executable cpp-service
/usr/local/bin/cmake -E cmake_link_script CMakeFiles/cpp-service.dir/link.txt --verbose=1
/usr/bin/g++-11 -g CMakeFiles/cpp-service.dir/src/main.cpp.o CMakeFiles/cpp-service.dir/src/***.cpp.o CMakeFiles/cpp-service.dir/src/***more***object***files***.cpp.o -o cpp-service 

错误会在上述链接命令之后立即抛出。例如:

undefined reference to `openvdb::v7_2::initialize()'

符号

符号是在链接的库内定义的:

nm /usr/local/lib64/libopenvdb.so | less

以上命令显示 initialize 符号可用: Symbol

3
检查编译器命令行是第一步调试。 - Alan Birtles
1
所有的库都是由CMake链接的。- 你是否通过检查构建期间执行的确切命令行找到了它?请展示该命令行(将其添加到问题帖子中)。"所有符号都是可用的。" - 你是否通过检查nm的输出找到了它?请展示该输出。 - Tsyvarev
1
链接命令是否提到库? - fabian
@fabian 不,完全不是这样。这个错误发生在 Linux 机器上。我在另一台 Windows 上构建得很好,我检查了 Windows 上的 link 命令。我注意到即使在可构建的 Windows 上,也没有 link 命令提到任何库。 - user3405291
1
猜测是错误的。由于链接命令中未提及任何库,而它们明显应该被提及,问题在于cmake忽略了target_link_libraries中指定的库。 - n. m.
显示剩余2条评论
1个回答

2

修复

链接器错误的原因是以下语句:

if(LINUX)

解决方法是将其替换为以下内容:
if(UNIX AND NOT APPLE)

这个提交修复了问题: Commit 参考:https://dev59.com/Bmox5IYBdhLWcg3whUgV#40152725 奇怪的是,CMake没有抱怨任何问题,只是随机抛出链接器错误。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接