CMake2.8链接共享库时静态库重复链接导致全局变量重复问题
问题根因
你遇到的符号重复问题由CMake 2.8的依赖透传逻辑导致:
- 若你使用的CMake 2.8小版本低于2.8.11,本身不支持
target_link_libraries的PUBLIC/PRIVATE/INTERFACE关键字,所有链接依赖默认都会透传给下游目标 - 你给共享库
AB链接了静态库A、B后,链接AB的测试程序Z会自动继承A、B的链接配置,最终链接命令中同时出现libAB.so(已经包含A、B的所有符号)和libA.a、libB.a,触发全局变量重复定义错误
可行解决方案
方案1:兼容所有CMake 2.8版本的配置修改
不要直接将静态库target作为参数传给target_link_libraries,改为传入静态库的实际文件路径,让CMake将其识别为普通链接参数而非target依赖,就不会触发透传逻辑:
# 放在root CMakeLists.txt中target_link_libraries之前 get_target_property(A_LIB_PATH A LOCATION) get_target_property(B_LIB_PATH B LOCATION) target_link_libraries( AB "-Wl,--whole-archive" ${A_LIB_PATH} ${B_LIB_PATH} "-Wl,--no-whole-archive" ${thirdPartyLibs} )
修改后Z的链接命令只会保留libAB.so,不会再额外引入libA.a、libB.a,即可解决重复定义问题。
方案2:适用于CMake >=2.8.11版本
如果你的CMake 2.8小版本大于等于2.8.11,正确使用PRIVATE关键字即可截断静态库依赖的透传:
target_link_libraries(AB # PRIVATE修饰的依赖仅AB自身使用,不会透传给下游 PRIVATE "-Wl,--whole-archive" A B "-Wl,--no-whole-archive" # PUBLIC修饰的依赖会透传给下游,仅保留AB对外接口必需的依赖即可 PUBLIC ${thirdPartyLibs} )
如果第三方库C/D/E不需要在AB的对外接口中使用,也可以改为PRIVATE修饰。
内容的提问来源于stack exchange,提问作者vkn
相关产品推荐
相关产品推荐

