【问题标题】:CMake append objects from different CMakeLists.txt into one libraryCMake 将来自不同 CMakeLists.txt 的对象附加到一个库中
【发布时间】:2018-08-22 06:52:07
【问题描述】:

我想从多个子目录中的对象创建一个库,每个子目录都包含自己的 CMakeLists.txt 和 OBJECT 库技巧,以使多个目标具有不同的编译选项。

这里是文件:

project_dir
|--- subdir1
|    |--- src1.c
|    |--- CMakeLists.txt
|--- subdir2
|    |--- src2.c
|    |--- CMakeLists.txt
|--- CMakeLists.txt

所有CMakeLists.txt的内容

// project_dir/CMakeLists.txt
// what to put here? to make one single library (mainLib)


// project_dir/subdir1/CMakeLists.txt
add_library(lib11 OBJECT src1.c)
set_target_properties(lib11 PROPERTIES COMPILE_FLAGS "some-flags11")

add_library(lib12 OBJECT src1.c)
set_target_properties(lib12 PROPERTIES COMPILE_FLAGS "some-flags12")
// here I would like to add lib11:objects and lib12:objects to mainLib
// how should it be done?

// project_dir/subdir2/CMakeLists.txt
// *** similar to subdir1 but with src2.c that creates lib21 and lib22
// here I would like to add lib21:objects and lib22:objects to mainLib
// how should it be done?

可以独立做平台吗?谢谢。

编辑: 基于CMake: how create a single shared library from all static libraries of subprojects?,我可以将cmake文件更改为以下,但仍然没有解决我的问题。

// project_dir/subdir1/CMakeLists.txt
add_library(lib11 OBJECT src1.c)
set_target_properties(lib11 PROPERTIES COMPILE_FLAGS "some-flags11")

add_library(lib12 OBJECT src1.c)
set_target_properties(lib12 PROPERTIES COMPILE_FLAGS "some-flags12")

add_library(lib1 STATIC $<TARGET_OBJECTS:lib11> $<TARGET_OBJECTS:lib12>)

// Above add_library cannot be OBJECT which would fix my problem.
// how to append the lib1 (lib11 and lib12) to mainLib?

编辑: 更新我的帖子,尝试按照答案中的建议链接接口库。

add_library(lib11 OBJECT test1/sub1/src1.c)
set_target_properties(lib11 PROPERTIES COMPILE_FLAGS "-DF1")

add_library(lib12 OBJECT test1/sub1/src1.c)
set_target_properties(lib12 PROPERTIES COMPILE_FLAGS "-DF2")

add_library(lib1 INTERFACE)
target_sources(lib1 INTERFACE $<TARGET_OBJECTS:lib11>)
target_sources(lib1 INTERFACE $<TARGET_OBJECTS:lib12>)

add_library(lib21 OBJECT test1/sub2/src2.c)
set_target_properties(lib21 PROPERTIES COMPILE_FLAGS "-DF1")

add_library(lib22 OBJECT test1/sub2/src2.c)
set_target_properties(lib22 PROPERTIES COMPILE_FLAGS "-DF2")

add_library(lib2 INTERFACE)
target_sources(lib2 INTERFACE $<TARGET_OBJECTS:lib21>)
target_sources(lib2 INTERFACE $<TARGET_OBJECTS:lib22>)

add_library(PARENT INTERFACE)

target_link_libraries(PARENT INTERFACE lib1)
target_link_libraries(PARENT INTERFACE lib2)

add_library(CORE OBJECT src.c)
add_library(GPARENT STATIC $<TARGET_OBJECTS:CORE>)

target_link_libraries(GPARENT INTERFACE PARENT)

【问题讨论】:

  • 感谢您的回复。我已经检查了那个链接。我可以使用相同的技术在子目录的 CMakeLists.txt 中组合不同的静态库(OBJECT),即使用 lib11 和 lib12 对象以及类似的 lib2 创建 lib1。您似乎无法链接此技术,这可以解决我的问题。我不想在我的主 CMakeLists.txt 中添加每个单独的对象库(例如 lib11、lib12、lib21、lib22)。请解释我是否遗漏了什么。
  • 嗯,所以你想用不同的标志编译 same OBJECT 库,不是吗?如果是,那么您不能 - 这将破坏 OBJECT 库作为一组预编译目标文件的核心目的。只需将源文件列表保存到某个变量中,并在创建具有适当编译器标志的主库时使用此列表。
  • 再次感谢您的回复。是的。我需要使用不同的标志多次编译子目录中的相同源文件。做到这一点并将所有目标文件放在同一个库中的最佳方法是什么?换句话说,如果我在顶层 CMakeLists.txt 中做 add_library(mainLib ),如何将更多的目标文件(从子目录 OBJECT 库)添加到这个 mainLib 中?

标签: build cmake linker unix-ar


【解决方案1】:

多个OBJECT库可以合并到一个INTERFACE库中:

# Create lib1 OBJECT library with some sources, compile flags and so.
add_library(lib1 OBJECT ...)

# Create lib2 OBJECT library with some sources, compile flags and so.
add_library(lib2 OBJECT ...)

# Create INTERFACE library..
add_library(libs INTERFACE)
# .. which combines OBJECT libraries
target_sources(libs INTERFACE $<TARGET_OBJECTS:lib1> $<TARGET_OBJECTS:lib2>)

生成的库可以与标准 target_link_libraries 一起使用:

add_library(mainLib <some-source>)
target_link_libraries(mainLib libs)

可以进一步结合INTERFACE库:

# Create libs_another INTERFACE library like 'libs' one
add_library(libs_another INTERFACE)
..

# Combine 'libs' and 'libs_another' together
add_library(upper_level_libs INTERFACE)
target_link_libraries(upper_level_libs INTERFACE libs libs_another)

生成的库的“链”可以是任意长度。


虽然这种组合 OBJECT 库的方式看起来很老套,但实际上CMake documentation 允许这样做:

虽然对象库可能不会在调用 target_link_libraries() 命令时直接命名,但可以通过使用 INTERFACE_SOURCES 目标属性的 Interface Library 间接“链接”它们设置为名称$&lt;TARGET_OBJECTS:objlib&gt;

【讨论】:

  • 完美。这就是我一直在寻找的。一个相关的问题:是否可以链接它?我的意思是如果我在目录树中有另一层。
  • 是的,可以进一步链接 INTERFACE 库。我已经更新了答案。
  • 再次感谢您的回复和更新的答案。我尝试按照您的建议组合接口库,然后使用组合接口库构建一个上层库。构建过程有效,但由于某种原因,上层库不包含组合接口库中的任何对象/符号。我还尝试向接口库添加显式依赖项,但仍然没有改变。我还需要做其他事情吗?
  • 奇怪!我也在 Linux 上并使用 CMake 3.10.2 。您使用的是较新的 CMake 吗?
  • 我用过 CMake 3.4 左右。你能显示不适合你的代码吗?
【解决方案2】:

我只是使用setPARENT_SCOPE 从所有地方收集对象。

根 CMakeLists.txt:

set(OBJECTS)

add_subdirectory(lib1)
add_subdirectory(lib2)

add_library(lib STATIC ${OBJECTS})

子目录中的 CMakeLists.txt:

add_subdirectory(lib11)

add_library(${PROJECT_NAME} OBJECT src1.c)
list(APPEND OBJECTS $<TARGET_OBJECTS:${PROJECT_NAME}>)
set(OBJECTS ${OBJECTS} PARENT_SCOPE)

【讨论】:

    猜你喜欢
    • 2023-02-04
    • 1970-01-01
    • 1970-01-01
    • 2011-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多