为啥在构建依赖库之前没有开始编译目标可执行文件?

Posted

技术标签:

【中文标题】为啥在构建依赖库之前没有开始编译目标可执行文件?【英文标题】:Why doesn't compilation of target executable already start before dependent library is built?为什么在构建依赖库之前没有开始编译目标可执行文件? 【发布时间】:2015-01-26 14:46:32 【问题描述】:

我已经建立了一个 CMake 项目 (3.1),其中包含一个可执行文件 E1 和两个静态库 L1 和 L2。

所有三个目标都需要编译几个 cpp 文件。 通过target_link_libraries(E1 L1 L2) E1 是针对这两个库链接的,当然,在链接 E1 之前,需要先构建 L1 和 L2。

但是使用 makefile-backend 和并行构建 (make -j),E1 的 cpp 文件的编译甚至不会在 L1 和 L2 静态链接之前开始 - 无论我使用 -j8 还是 -j256。

我可以通过 CMake 指定一些东西,以确保 E1 的单元已经编译,即使任何依赖库的(单线程)链接仍在进行中?

类似问题: CMake adds unnecessary dependencies between .o and .a files。 他们的解决方案是消除链接依赖或引入新的库层。 就我而言,这意味着将 E1 的 cpp 文件包装到单独的目标(静态或对象)L-E1 中,并在实际 E1 中链接到该目标。 但是就没有别的办法了吗?

【问题讨论】:

Hrm....我觉得这将是危险的水域。 CMake 没有说 E1 依赖于 L1.a,它说 E1 依赖于 L1。这允许您支持 L1 及其依赖项的其他内容(例如,E1 依赖于中间体(例如配置的头文件))。如果在 L1.a 完成之前,组件 E1 可能会因各种原因而失败... 这就是 add_dependencies(E1 L1) 的用途,不是吗?但是如果它 L1 只在 E1 的 target_link_libraries 中被提及,我不会期望不必要的依赖。 您能否向我们展示 CMake 生成的 Makefile,该文件描述了这里存在问题的先决条件关系? (我很好奇 CMake 到底在做什么。) 【参考方案1】:

我目前的解决方案是添加一个中间 object-library (CMake >= 2.8.8)。

所以下面的脚本,它不会开始编译 E1 的编译单元:

add_executable(E1 main.cpp logging.cpp ui.cpp)
target_link_libraries(E1 L1 L2)

替换为:

add_library(E1_OBJECTS OBJECT main.cpp logging.cpp ui.cpp)
add_executable(E1 $<TARGET_OBJECTS:E1_OBJECTS>)
target_link_libraries(E1 L1 L2)

这样 cpp 文件将尽可能早地编译,而无需等待链接到 E1 的库 L1 和 L2。

当然,任何编译时依赖项都需要转移到新目标 E1_OBJECTS。

【讨论】:

以上是关于为啥在构建依赖库之前没有开始编译目标可执行文件?的主要内容,如果未能解决你的问题,请参考以下文章

在Linux PC上查看arm交叉编译的可执行文件依赖的动态库

Linux - 为啥我的可执行文件将 libpthread 作为共享库?

为啥公共部分变量只显示在目标文件而不是可执行文件中?

Makefile:来自相同源的两个目标使用不同的标志编译两次

gcc 将共享库与依赖库链接

依赖项更改时重建 CMake 目标