You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CMake链接自定义库到可执行文件时出现未定义引用问题求助

问题:CMake链接共享库时出现未定义引用错误

我是CMake新手,感觉遗漏了某些配置,遇到如下问题:

1. 构建wrapper共享对象的CMake代码

add_library(wrapper SHARED
        dh-wrap.cpp)

target_link_options(wrapper PUBLIC -Wl,--no-as-needed)

target_include_directories(wrapper
        PUBLIC /usr/local/include/dahua)

target_link_directories(wrapper
        PUBLIC /usr/local/lib/dahua)

target_link_libraries(wrapper dhnetsdk)

2. 基于wrapper构建lib共享对象的CMake代码

add_library(lib SHARED
        library.c buffer.c)

target_link_options(lib PUBLIC -Wl,--no-as-needed)

target_include_directories(lib
        PUBLIC /usr/local/include/dahua)

target_link_directories(lib
        PUBLIC /usr/local/lib/dahua
        PUBLIC ../cmake-build-debug-gcc/wrapper)

target_link_libraries(lib wrapper)

3. 构建测试可执行文件test_x的CMake代码

# Test executable
add_executable(test_x main.c)

target_link_options(test_x PUBLIC -Wl,--no-as-needed)

target_include_directories(test_x
        PUBLIC /usr/local/include/dahua)

target_link_directories(test_x
        PUBLIC /usr/local/lib/dahua
        PUBLIC ../cmake-build-debug-gcc/wrapper
        PUBLIC ../cmake-build-debug-gcc/library)

target_link_libraries(test_x lib)

错误信息

构建时出现大量未定义引用错误,涉及wrapper及第三方库dhnetsdk的函数:

ld: ../wrapper/libwrapper.so: undefined reference to `CLIENT_SetDeviceMode(long, __EM_USEDEV_MODE, void*)'
ld: ../library/liblib.so: undefined reference to `DH_SDK_Init'
ld: ../library/liblib.so: undefined reference to `DH_DownloadByTime'
ld: ../library/liblib.so: undefined reference to `DH_SDK_Cleanup'
ld: ../library/liblib.so: undefined reference to `DH_Logout'
ld: ../library/liblib.so: undefined reference to `DH_SetDeviceMode'
ld: ../library/liblib.so: undefined reference to `DH_Login'
ld: ../wrapper/libwrapper.so: undefined reference to `CLIENT_StopDownload(long)'
...

最初用ldd检查发现wrapper和lib未链接dhnetsdk,添加-Wl,--no-as-needed后ldd显示依赖,但未定义引用问题仍存在。用readelf -s检查发现对应符号为未定义,按理解应在链接可执行文件时解析,但未生效,请问遗漏了什么配置?


解决方案

1. 修复依赖传递逻辑,移除手动路径指定

你手动添加target_link_directories指向构建目录的操作完全多余,CMake会自动管理同一项目内目标的依赖路径。移除这些手动路径,让CMake通过目标依赖链自动传递路径和库信息。

默认情况下target_link_libraries的依赖是PRIVATE,不会传递给上层依赖目标。需要用PUBLIC修饰,让依赖当前目标的上层目标自动继承该依赖:

  • wrapper链接dhnetsdk时用PUBLIC,确保lib和test_x能自动拿到dhnetsdk的依赖
  • lib链接wrapper时用PUBLIC,确保test_x继承wrapper的依赖

3. 处理C/C++混合编译的符号名问题

如果dhnetsdk是C语言库,而wrapper是C代码,必须用extern "C"包裹库的头文件,避免C名字修饰导致符号不匹配。

修改后的完整CMake代码

wrapper的CMake配置

add_library(wrapper SHARED
        dh-wrap.cpp)

# 明确开启位置无关代码(SHARED库默认已开启,可省略)
set_target_properties(wrapper PROPERTIES
        POSITION_INDEPENDENT_CODE ON)

# 传递链接选项给上层依赖
target_link_options(wrapper PUBLIC -Wl,--no-as-needed)

# 传递头文件路径给上层依赖
target_include_directories(wrapper
        PUBLIC /usr/local/include/dahua)

target_link_directories(wrapper
        PUBLIC /usr/local/lib/dahua)

# PUBLIC修饰,传递dhnetsdk依赖给所有依赖wrapper的目标
target_link_libraries(wrapper PUBLIC dhnetsdk)

dh-wrap.cpp中添加extern "C"包裹头文件

extern "C" {
#include <dhnetsdk.h> // 替换为实际的dahua库头文件名
}

// 你的wrapper代码...

lib的CMake配置

add_library(lib SHARED
        library.c buffer.c)

set_target_properties(lib PROPERTIES
        POSITION_INDEPENDENT_CODE ON)

target_link_options(lib PUBLIC -Wl,--no-as-needed)

# 无需重复设置dahua的头文件和库路径,通过wrapper自动继承
target_link_libraries(lib PUBLIC wrapper)

test_x的CMake配置

add_executable(test_x main.c)

# 直接链接lib,所有依赖会自动传递
target_link_libraries(test_x PUBLIC lib)

验证方法

修改后重新构建,用readelf -d libwrapper.so | grep NEEDED检查是否包含dhnetsdk,再用ldd test_x确认所有依赖库都被正确链接。

内容的提问来源于stack exchange,提问作者Danny

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 03:10:11