【问题标题】:How to use nested OBJECT libraries and how to pass the object lib dependencies?如何使用嵌套的 OBJECT 库以及如何传递对象库依赖项?
【发布时间】:2022-01-22 15:17:25
【问题描述】:

我有三个库,每个库都在不同的文件夹中。

LibParent   add_library(${PROJECT_NAME} STATIC LibParent.cpp $<TARGET_OBJECTS:LibChild-obj>))
LibChild    add_library(${PROJECT_NAME}-obj OBJECT LibChild.cpp $<TARGET_OBJECTS:LibBase-obj>))
LibBase     add_library(${PROJECT_NAME}-obj OBJECT LibBase.cpp)

顶部CMakeLists.txt有:

add_subdirectory(LibBase)
add_subdirectory(LibChild)
add_subdirectory(LibParent)

问题是在应用程序中使用LibParent.a,我得到undefined reference to LibBase::...

如何使用LibChild-objLibBase 的依赖项传递给每个CMake 目标?

  • LibChild-obj 应该包括LibBaseLibChild 的对象

  • LibParent直接调用LibBase,只调用LibChild的函数

  • 我想避免在LibParent 中添加$&lt;TARGET_OBJECTS:LibBase-obj&gt;,因为它不会直接调用它。

当我不需要 STATIC 库时,我也想坚持使用 OBJECT 库

目标是只传递包含LibChildLibParent.a AND LibChild 的依赖项LibBase,以便LibChild 的函数可以调用LibBase 的函数。

我觉得有必要提一下 CMake 版本:>3.17

【问题讨论】:

  • 试试target_link_libraries(LibChild PUBLIC LibBase)等,而不是$&lt;TARGET_OBJECTS
  • 我试过了,它不会传播。
  • 这样做 LibParent 不包含 LibBase 和 LibChild 的符号。

标签: c++ cmake


【解决方案1】:

目标是只传递包含 LibChild 和 LibChild 的依赖项 LibBase 的 LibParent.a,以便 LibChild 的函数可以调用 LibBase 的函数。

你快到了...这里是构建文件:

# ./CMakeLists.txt
cmake_minimum_required(VERSION 3.22)
project(example)

add_subdirectory(LibBase)
add_subdirectory(LibChild)
add_subdirectory(LibParent)

add_executable(test main.cpp)
target_link_libraries(test PRIVATE LibParent)
# ./LibBase/CMakeLists.txt

add_library(LibBase OBJECT base.cpp)
target_include_directories(
  LibBase
  PUBLIC
  "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>"
)
# ./LibChild/CMakeLists.txt

add_library(LibChild OBJECT child.cpp)
target_include_directories(
  LibChild
  PUBLIC
  "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>"
)
target_link_libraries(LibChild PUBLIC LibBase)
# ./LibParent/CMakeLists.txt

add_library(LibParent parent.cpp)
target_include_directories(
  LibParent
  PUBLIC
  "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>"
)
target_link_libraries(LibParent PRIVATE LibChild LibBase)

这里有一些虚拟源文件:

// Lib{Base,Child,Parent}/{base,child,parent}.cpp
#include <cstdio>
#include "{base,child,parent}.h"  // only contains do_{..}  decl.

void do_{base,child,parent}() {
  do_{base,child}(); // parent calls child, child calls base
  puts("{base,child,parent}");
}
// main.cpp
#include <parent.h>

int main () {
  do_parent();
  return 0;
}

控制台交互:

$ cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
...
$ $ cmake --build build/ --verbose
[1/6] /usr/bin/c++  -I/home/alex/test/LibParent -I/home/alex/test/LibChild -I/home/alex/test/LibBase -O3 -DNDEBUG -MD -MT CMakeFiles/test.dir/main.cpp.o -MF CMakeFiles/test.dir/main.cpp.o.d -o CMakeFiles/test.dir/main.cpp.o -c /home/alex/test/main.cpp
[2/6] /usr/bin/c++  -I/home/alex/test/LibBase -O3 -DNDEBUG -MD -MT LibBase/CMakeFiles/LibBase.dir/base.cpp.o -MF LibBase/CMakeFiles/LibBase.dir/base.cpp.o.d -o LibBase/CMakeFiles/LibBase.dir/base.cpp.o -c /home/alex/test/LibBase/base.cpp
[3/6] /usr/bin/c++  -I/home/alex/test/LibChild -I/home/alex/test/LibBase -O3 -DNDEBUG -MD -MT LibChild/CMakeFiles/LibChild.dir/child.cpp.o -MF LibChild/CMakeFiles/LibChild.dir/child.cpp.o.d -o LibChild/CMakeFiles/LibChild.dir/child.cpp.o -c /home/alex/test/LibChild/child.cpp
[4/6] /usr/bin/c++  -I/home/alex/test/LibParent -I/home/alex/test/LibChild -I/home/alex/test/LibBase -O3 -DNDEBUG -MD -MT LibParent/CMakeFiles/LibParent.dir/parent.cpp.o -MF LibParent/CMakeFiles/LibParent.dir/parent.cpp.o.d -o LibParent/CMakeFiles/LibParent.dir/parent.cpp.o -c /home/alex/test/LibParent/parent.cpp
[5/6] : && /usr/bin/cmake -E rm -f LibParent/libLibParent.a && /usr/bin/ar qc LibParent/libLibParent.a  LibChild/CMakeFiles/LibChild.dir/child.cpp.o LibBase/CMakeFiles/LibBase.dir/base.cpp.o LibParent/CMakeFiles/LibParent.dir/parent.cpp.o && /usr/bin/ranlib LibParent/libLibParent.a && :
[6/6] : && /usr/bin/c++ -O3 -DNDEBUG  CMakeFiles/test.dir/main.cpp.o -o test  LibParent/libLibParent.a && :
$ ./build/test 
base
child
parent
$ nm build/LibParent/libLibParent.a

child.cpp.o:
                 U _GLOBAL_OFFSET_TABLE_
0000000000000000 r .LC0
                 U puts
                 U _Z7do_basev
0000000000000000 T _Z8do_childv

base.cpp.o:
                 U _GLOBAL_OFFSET_TABLE_
0000000000000000 r .LC0
                 U puts
0000000000000000 T _Z7do_basev

parent.cpp.o:
                 U _GLOBAL_OFFSET_TABLE_
0000000000000000 r .LC0
                 U puts
                 U _Z8do_childv
0000000000000000 T _Z9do_parentv

最终的库确实包含所有对象。

【讨论】:

  • 如果这里的结果不是您想要的,让我们通过这个 MRE 解决您的 true 问题(并酌情更新您的问题)。
  • 谢谢,不过,我想避免在LibParent 中提及LibBase,也许我错了,但我不需要添加我不需要的库的依赖项直接使用。值得一提的是LibParent从不使用/调用LibBase,它只使用/调用LibChild(它将在内部调用LibBase)。
猜你喜欢
  • 2020-03-30
  • 1970-01-01
  • 2011-08-30
  • 1970-01-01
  • 1970-01-01
  • 2014-07-26
  • 2017-03-06
  • 1970-01-01
  • 2018-08-19
相关资源
最近更新 更多