CMake共享项目子目录避免重建

Ger*_*s R 5 c++ android cmake android-ndk android-gradle-plugin

对于一个项目,我使用的是带有CMake的Android gradle脚本,gradle插件是版本3:0:0,CMake版本3.6.gradle和CMake文件都非常简单且无趣(仅定义使用的文件 - 我仍然可以根据需要复制粘贴它们).

我有以下项目结构; 基本上是一个产生几十个.so文件的代码库(Android软件包的本机部分被打包成一个apk,因此被称为'Executables'),它们都依赖于相同的共享库代码(静态库,因此称为'库").库代码仍然(相对)易变,因此我希望可执行文件对它们具有项目级依赖性,这样无论何时构建可执行文件,每次更改代码时都会按需重建库.结构如下:

+ LibProjects/
---Bin/ (Originally empty)
---Lib1/CMakeLists.txt (+sources files, same level as the CMakeLists.txt)
...
---Lib10/CMakeLists.txt (same)
+ Executables/
---Executable1/CMakeLists.txt (source files here)
--------------/AndroidFiles/build.gradle (and other android project files)(points to the CMakeLists.txt)
...
---Executable40/CMakeLists.txt
Run Code Online (Sandbox Code Playgroud)

Libraries的CMakeLists使用输出将其输出重定向到Bin文件夹

set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY {CMAKE_CURRENT_SOURCE_DIR}/../Bin/${ANDROID_ABI}/${LibraryName})
Run Code Online (Sandbox Code Playgroud)

可执行文件的项目"正常"地添加库的依赖项

add_subdirectory(${PROJECTS_ROOT}/LibProjects/${LibraryName} ${PROJECTS_ROOT}/Framework/Bin/Android/${ANDROID_ABI}/${LibraryName})...
Run Code Online (Sandbox Code Playgroud)

一切都近乎工作,从某种意义上说,我可以得到合理的可执行文件,并且可执行文件触发了库的构建.

问题是,当按顺序构建可执行文件时,每个都不会重用其他库的项目输出:当我构建Executable1时,它将构建所有库(正常),然后它将构建自己.之后,当我构建Executable2时,它不会重用已经为Executable1构建的库,依此类推 - 这有效地将构建时间增加了~10倍.

我可以按预期在/ Bin文件夹中找到每个库的构建输出,但它们不会在可执行文件中重复使用 - bin文件夹中没有CMake"项目文件"(这是正确的术语),所有这些文件都是在可执行构建目录中生成.

我试图解决的问题是构建时间源于每个库为每个可执行文件重建的事实.

目前我正在考虑的解决方案是以某种方式指示CMake使用Bin文件夹(或其他文件夹)作为其自己文件夹中的每个库的工作文件夹而不是可执行文件,希望gradle android插件足够聪明然后发现cmakefiles和目标文件都不需要重新生成,并避免重建.

我的限制是我无法重构代码库本身,并且每个可执行文件必须可以与其他可执行文件分开构建 - 绝对没有顶级CMake的可能性 - 每个可执行文件都应该能够自己触发.

Oli*_*liv 2

CMake 可以通过读取当前构建目录中的信息来猜测构建是否是最新的。

当您在目录中手动运行 CMake 时Executables/<x>,cmake 从与目录关联的构建目录中检索信息Executable/<x>。然后,它检查构建文件的时间戳是否与此构建目录中执行的最后一次构建相对应。如果没有,则重建。发生的情况是:Lib1在 build 后构建了库文件Executable1,然后在 中运行 cmake Executalbe2,它比较目标文件的时间戳Lib1,发现该文件不是由 cmake 构建的此实例生成的,然后重建库。等等。

所以你有两个选择:

1-构建库并将其目标文件安装在目录中(例如bin使用installcmake 命令和bash 命令)。make install然后在Executalbe<x>/CMakeLists您使用find_library命令而不是add_subdirectory.

2-或者您创建一个具有以下结构的超级项目:

+  supper_project
---CMakeLists.txt #add_subdirectory(LibProjects/lib<x>)... add_subdirectory(Executables/Executalbe<x>)...
  + LibProjects/
  ---Bin/ (Originally empty)
  ---Lib1/CMakeLists.txt (+sources files, same level as the CMakeLists.txt)
  ...
  ---Lib10/CMakeLists.txt (same)
  + Executables/
  ---Executable1/CMakeLists.txt (source files here)
  --------------/AndroidFiles/build.gradle (and other android project files)
  (not any more:points to the CMakeLists.txt)
  ...
  ---Executable40/CMakeLists.txt
Run Code Online (Sandbox Code Playgroud)