将CMake接口库与对象库链接

时间:2017-06-26 19:15:58

标签: cmake

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

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

Docs

  

虽然在调用target_link_libraries()命令时可能无法直接命名对象库,但可以使用其INTERFACE_SOURCES目标属性设置为名称{{1}的接口库间接地“链接”它们。 }。

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

$<TARGET_OBJECTS:objlib>

CMakeLists:

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

输出:

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)

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

编辑:

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

EDIT2:

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

3 个答案:

答案 0 :(得分: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版本可能是个好主意。

答案 1 :(得分:0)

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

因此问题的示例CMakeLists.txt应该在编译时获得正确的定义。

如果使用它,别忘了设置cmake_required(版本3.13)!

答案 2 :(得分:-1)

要使 OBJECT 本身使用特定的编译定义,您应该:

  • 将这些定义添加到库目标本身:

    target_compile_definitions(object_lib PUBLIC MY_DEF)
    
  • 或将库链接到另一个库,这需要这些定义:

    target_link_libraries(object_lib interface_lib)
    

在那里, OBJECT 库与CMake中的其他类型的库没有区别。

来自CMake文档的引文:

  

虽然在调用target_link_libraries()命令时可能无法直接命名对象库,但可以使用其INTERFACE_SOURCES目标属性设置为名称{{1}的接口库间接地“链接”它们。 }。

解释了传播如何将 OBJECT 库中的定义编译到另一个库中。关于如何将定义传播到 OBJECT 库本身