我正在从事一个由几十个共享库组成的项目,每个共享库都有许多相关的单元测试。许多库还依赖于其他库,因为用于某些特定功能的库将使用较常见的库之一中的代码。最后,当然还有依赖于lib的生产可执行文件。
毫无疑问,某个核心公共库的API(头文件)的更改将触发几乎整个系统的重大重新编译。但是通常实现上只有一个变化,编译的唯一文件是修改后的.cxx,理论上只需要链接修改后的lib-由于有了动态链接,因此不需要重新链接其他任何东西。但是CMake还是继续执行它:在重新链接lib之后,它将重新链接与该lib相关的所有单元测试。然后,它重新链接该库的依赖关系树中的所有库及其所有单元测试。最后,它重新链接生产可执行文件。由于项目的规模,这需要很多宝贵的时间。
我已基于此最小示例通过一个简单的项目重现了此行为(为简洁起见,注释已更改为共享,删除了注释)。我的系统是Intel PC上的Ubuntu 16,而我的CMake版本是3.5.1。
从一个空目录开始并创建以下文件:
CMakeLists.txt
cmake_minimum_required (VERSION 2.8.11)
project (HELLO)
add_subdirectory (Hello)
add_subdirectory (Demo)
Run Code Online (Sandbox Code Playgroud)
演示/CMakeLists.txt
add_executable (helloDemo demo.cxx)
target_link_libraries (helloDemo LINK_PUBLIC Hello)
Run Code Online (Sandbox Code Playgroud)
演示/demo.cxx
#include "hello.h"
int main() { hello(); }
Run Code Online (Sandbox Code Playgroud)
你好/CMakeLists.txt
add_library (Hello SHARED hello.cxx)
target_include_directories (Hello PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
Run Code Online (Sandbox Code Playgroud)
你好/hello.h
void hello();
Run Code Online (Sandbox Code Playgroud)
你好/hello.cxx
#include <stdio.h>
void hello() { printf("hello!\n"); }
Run Code Online (Sandbox Code Playgroud)
现在运行以下命令:
mkdir build
cd build
cmake ../
make
Run Code Online (Sandbox Code Playgroud)
您现在可以执行Demo/helloDemo并查看hello!。
现在,再次输入touchHello / hello.cxx make。您将看到helloDemo可执行文件已重新链接(“ Linking CXX executable helloDemo”)。即使将hello.cxx修改为打印不同的字符串,重新链接的可执行文件也保持二进制相同,因此实际上不需要重新链接。
有没有办法防止这些多余的构建动作?
事实证明,答案在于LINK_DEPENDS_NO_SHARED财产。在我的示例中,所需要做的就是将以下行添加到 Demo/CMakeLists.txt 文件中:
set_target_properties(helloDemo PROPERTIES LINK_DEPENDS_NO_SHARED true)
Run Code Online (Sandbox Code Playgroud)
这将防止 helloDemo 在其依赖项之一更新时重新链接 - 如果该依赖项是共享库。
在更复杂的系统上,其中一些库还依赖于其他库,将此设置添加到它们的配置中也很有用。
感谢 CMake 邮件列表的 Craig Scott 的帮助,存档在此链接。
| 归档时间: |
|
| 查看次数: |
412 次 |
| 最近记录: |