【问题标题】:Linking CMake interface libraries with object libraries将 CMake 接口库与对象库链接
【发布时间】:2017-06-26 19:15:58
【问题描述】:

我正在尝试使用接口库来定义预处理器宏。然后将这些接口库链接到其他库以传播这些宏。这种方法适用于我正在创建的共享库,但不适用于 CMake 对象库。

我了解您不能直接将接口库链接到对象库,但您可以将TARGET_OBJECTS 间接链接到接口库。

Docs:

虽然对象库不能在调用target_link_libraries() 命令时直接命名,但可以通过使用将INTERFACE_SOURCES 目标属性设置为名称$<TARGET_OBJECTS:objlib> 的接口库间接“链接”它们。

我已尝试这样做,但目标文件仍未使用适当的定义进行编译。这是最小的工作示例:

// a.cpp    
int a() {
  return
#ifdef MY_DEF
  5;
#endif
    }

CMakeLists:

cmake_minimum_required(VERSION 3.0.1)
project(my_question)

add_library(object_lib OBJECT a.cpp)

add_library(interface_lib INTERFACE)
target_compile_definitions(interface_lib INTERFACE MY_DEF)

# This does not set the MY_DEF flag
target_sources(interface_lib INTERFACE $<TARGET_OBJECTS:object_lib>)

add_library(main_lib SHARED $<TARGET_OBJECTS:object_lib>)
target_link_libraries(main_lib)

输出:

/Library/Developer/CommandLineTools/usr/bin/make -f CMakeFiles/object_lib.dir/build.make CMakeFiles/object_lib.dir/build
[ 50%] Building CXX object CMakeFiles/object_lib.dir/a.cpp.o
/Library/Developer/CommandLineTools/usr/bin/c++     -o CMakeFiles/object_lib.dir/a.cpp.o -c /Users/umar/devel/so_question/a.cpp
/Users/umar/devel/so_question/a.cpp:7:5: error: expected expression
    }
    ^
1 error generated.
make[2]: *** [CMakeFiles/object_lib.dir/a.cpp.o] Error 1
make[1]: *** [CMakeFiles/object_lib.dir/all] Error 2
make: *** [all] Error 2

根据文档,这在 CMake 中应该是可能的。我不确定我是否做错了什么,或者这是否是 CMake 中的问题。我已经能够在 Debian 和 OSX 上的 CMake 版本 3.6 和 3.8 中重现这一点。

编辑:

我已经能够使用@utopia 的方法解决这个问题,但我很好奇为什么我在示例中使用的方法不起作用。我不知道我是否做错了,或者这是否是工具的问题。也许 StackOverflow 不是此类问题的正确平台,我应该针对该项目提交错误报告。

编辑2:

在 CMake(3.8) 的最新版本中,这在 CMake(see discussion) 中是不可能的。这可能在 3.9 中通过 this 合并请求得到支持。对于旧版本,乌托邦的答案是要走的路。

【问题讨论】:

  • target_link_libraries(main_lib) 应该是 target_link_libraries(main_lib interface_lib)。
  • 我认为只有在我想将定义应用于main_lib 目标的源时才有必要这样做。因为object_lib 源文件是单独编译的,所以定义不适用于它。尽管如此,我尝试了tll(main_lib interface_lib),但它没有将定义应用于 object_lib 源。
  • 在任何情况下,带有单个参数的target_link_libraries 无用。嗯,根据错误日志,您正在编译object_lib 中的目标文件。如果你想让这个文件有特定的定义,你需要链接object_lib目标,而不是main_lib一个:target_link_libraries(object_lib interface_lib)。将 OBJECT 库视为一组 预编译 目标文件:main_lib 为这些文件分配 compile 选项为时已晚。跨度>
  • @Tsyvarev 是的。这就是为什么我没有将它包含在target_link_libraries 电话中。我想将定义应用于目标文件,并且(至少根据我链接的文档)这应该可以通过将object_lib 的TARGET_OBJECTS 添加到接口库中,就像我在target_sources 命令中所做的那样

标签: cmake


【解决方案1】:

从 cmake 3.13 开始,对象库可以“链接”到其他库以继承其使用要求 (doc)。

所以问题中的示例 CMakeLists.txt 应该在编译时得到正确的定义。

如果你使用这个,别忘了设置 cmake_required(VERSION 3.13)!

【讨论】:

  • 像魅力一样工作!我已从 3.8.2 更新到 3.15.1,并将 target_compile_options 添加到对象库目标中。现在找到了接口库中的所有包含目录。
【解决方案2】:

只需通过属性直接从接口库中复制编译定义。信息就在那里,只是没有通过常用命令直接支持它:

cmake_minimum_required(VERSION 3.1)
project(my_question)

add_library(interface_lib INTERFACE)
target_compile_definitions(interface_lib INTERFACE MY_DEF)

add_library(object_lib OBJECT a.cpp)
target_compile_definitions(object_lib PUBLIC
  $<TARGET_PROPERTY:interface_lib,INTERFACE_COMPILE_DEFINITIONS>)

add_library(main_lib b.cpp)
target_sources(main_lib PRIVATE
  $<TARGET_OBJECTS:object_lib>)

注意target_sources() 似乎是在 3.1 版而不是 3.0.1 版中首次引入的。更新您的cmake_minimum_required 版本可能是个好主意。

【讨论】:

  • 我知道这种方法,并且我已经能够在我的项目中做到这一点,但似乎接口库应该根据我在问题中链接的文档应用于对象库。
  • @Umar Arshad 您是向 stackoverflow.com 而非 CMake 项目提交错误报告,还是您想要一个答案来解决您的问题?对于那些显然煞费苦心地为他们的问题创建一个最低限度的可行程序并把它说得足够好来回答的人来说,你现在对回应的反对是……奇怪的,特别是因为你根本没有在你的问题中提到这种方法。
  • 感谢您的回答,我并不是要贬低您的努力。我很好奇我做错了还是CMake有问题。我最近才开始以这种方式使用 CMake,我认为这是我无能的症状,而不是工具。我会更新问题,这样就不会再发生了
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-04
  • 2013-01-06
  • 2019-01-31
  • 2021-11-30
  • 1970-01-01
相关资源
最近更新 更多