cmake error: includes target which requires target that is not in the export set,解决静态库的PRIVATE依赖导出问题

59 篇文章 1 订阅
42 篇文章 28 订阅

问题描述

最近在使用 [interface libraries](file:///P:/cmake-3.1.0-rc3-win32-x86/doc/cmake-3.1/html/manual/cmake-buildsystem.7.html#interface-libraries)时出了个小问题。
示例如下,我希望target not_exported只是作为fse_cas_static 的private类的依赖库内部使用,不希望在config file中导出对它的依赖。

# 创建静态库
add_library(fse_cas_static STATIC ${_SOURCE_FILES})
# 创建interface libraries
add_library(not_exported INTERFACE)
target_link_libraries(fse_cas_static PRIVATE not_exported)

# 安装脚本,生成导出文件fse-targets.cmake
install(TARGETS fse_cas_static EXPORT fse-targets DESTINATION lib)
# 安装导出文件fse-targets.cmake
install(EXPORT fse-targets DESTINATION lib/cmake/Exp)

而且在cmake运行脚本时出错:

CMake Error: install(EXPORT “fse-targets” …) includes target “fse_cas_static” which requires target “not_exported” that is not in the export set.

意思就是not_exported这个我不希望export的target没有被export所以报错。

问题溯源

我明明把在target_link_libraries中指定了PRIVATE,就是不希望not_exportedtarget被export啊,怎么还会被要求export呢?

在google上找到了答案:

The private dependencies of a static library still need to be exported because they are needed to properly link the consumers of the static library. This applies even to interface libraries because their INTERFACE_LINK_LIBRARIES might specify something that provides symbols needed by the static library.
静态库的私有依赖仍然需要被导出,因为静态库的使用者需要它们才能正确链接静态库。这适用于接口库(interface libraries),因为它们的INTERFACE_LINK_LIBRARIES 属性可能会指定一些东西来提供静态库所需的符号。

摘自《Export of STATIC library with PRIVATE non-target dependencies broken》

解决方案

原因是知道了,上面的写法肯定是不对的,但是我确实不希望not_exported被导出啊。该怎么解决呢?

我想到cmake-generator-expressions
既然我只是希望在编译静态库fse_cas_static的时候让引入not_exported那么可以用cmake-generator-expressions中的$<BUILD_INTERFACE:...>来解决这个问题,$<BUILD_INTERFACE:...>表达的基本意义就是只在编译期返回...的内容,否则为空字符串。

所以我们可以用$<BUILD_INTERFACE:...>表达对上面脚本中的语句target_link_libraries(fse_cas_static PRIVATE not_exported) 中的not_exported加一个限定,改为

target_link_libraries(fse_cas_static PRIVATE $<BUILD_INTERFACE:not_exported>)

意思就是只在fse_cas_static编译的时候引入依赖not_exported,在 INSTALL 阶段这个值为空,不存在not_exported,就解决了问题,cmake不再报错,编译也正常进行。
最后生成的fse-targets.cmake中可以看到\$<LINK_ONLY:>这样的代码,应该是$<BUILD_INTERFACE:not_exported>这部分在生成export文件时转换生成的。

# Create imported target fse_cas_static
add_library(gdface::fse_cas_static STATIC IMPORTED)
set_target_properties(fse_cas_static PROPERTIES
  INTERFACE_COMPILE_DEFINITIONS "FSE_IS_A_DLL=0;CASSDK"
  INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include"
  INTERFACE_LINK_LIBRARIES "\$<LINK_ONLY:>;cassdk_THFeature"
  INTERFACE_POSITION_INDEPENDENT_CODE "ON"
)
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

10km

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值