CMake add_subdirectory 并重新编译

And*_*ron 4 cmake

我刚刚将一个较大的项目从 Visual Studio 解决方案迁移到 CMake,我注意到一个奇怪的行为。我有类似以下结构:

project/CMakeLists.txt
project/code/CMakeLists.txt

project/code/library-1/CMakeLists.txt
project/code/library-1/*.hpp
project/code/library-1/*.cpp
project/code/library-2/CMakeLists.txt
project/code/library-2/*.hpp
project/code/library-2/*.cpp
...
project/code/library-n/CMakeLists.txt
project/code/library-n/*.hpp
project/code/library-n/*.cpp

project/demo/CMakeLists.txt
project/demo/demo-1/CMakeLists.txt
project/demo/demo-1/*.hpp
project/demo/demo-1/*.cpp
project/demo/demo-2/CMakeLists.txt
project/demo/demo-2/*.hpp
project/demo/demo-2/*.cpp
...
project/demo/demo-n/CMakeLists.txt
project/demo/demo-n/*.hpp
project/demo/demo-n/*.cpp
Run Code Online (Sandbox Code Playgroud)
  1. CMakeLists.txt文件配置编译标志、宏定义等,并使用 CMakeadd_subdirectory()来包含库和演示项目定义的目标。
  2. code子文件夹包含子文件夹的平面列表,每个子文件夹都包含静态库的源代码(以及文件中定义的目标CMakeLists.txt)。
  3. demo文件夹包含子文件夹的平面列表。每个都包含可执行文件和关联CMakeLists.txt文件的源代码。
  4. 每个库都是一个独立的组件,并且独立于所有其他库和演示项目而构建。
  5. 每个演示程序都依赖于子文件夹中的一个或多个不同的库code

这个设定实在是太好了。如果我想更改构建选项,我只需要修改根目录CMakeLists.txt,所有内容都会使用新设置重新编译。如果我修改树中任何位置的任何源代码,则会重新编译相应的库(如果有),并且也会重新构建所有依赖的演示程序。

但是,如果我修改树中任何位置的任何文件,则整个库和程序树都会重新编译,而不考虑依赖性。 CMakeLists.txt为了让您明白我的意思,这里有 CMake 构建脚本的几个部分。


project/demo/CMakeLists.txt

# Resolve libraries built in `code` sub-folder.
link_directories(${LIBRARY_OUTPUT_PATH})

set(demo-projects
  demo-1
  demo-2
  ...
  demo-n
)
foreach(demo-project ${demo-projects})
  add_subdirectory(${demo-project})
endforeach()
Run Code Online (Sandbox Code Playgroud)

project/demo/demo-n/CMakeLists.txt

# Find all source code in the same folder.
file(GLOB ${demo-project}_headers
  ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp
)
file(GLOB ${demo-project}_sources
  ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
)

# Select libraries to link with.
set(${demo-project}_libraries
  library-1
  library-2
  library-5
)

# Build the demo program.
add_executable(${demo-project}
  ${${demo-project}_headers}
  ${${demo-project}_sources}
)
if(${demo-project}_libraries)
  target_link_libraries(${demo-project} ${${demo-project}_libraries})
endif()

# Manually register some dependencies on other targets.
if(${demo-project}_dependencies)
  add_dependencies(${demo-project} ${${demo-project}_dependencies})
endif()
Run Code Online (Sandbox Code Playgroud)

如果我碰巧修改project/demo/demo-n/CMakeLists.txt以添加额外的库,如下所示:

set(${demo-project}_libraries
  library-1
  library-2
  library-5
  library-6
)
Run Code Online (Sandbox Code Playgroud)

然后重新编译项目中所有库和演示程序的整个源代码。为什么会这样呢?有没有更好的方法来构建我的脚本以避免这种情况?

小智 5

您要做的第一件事就是弄清楚发生了什么变化。如果您安装了 git,则可以使用 git 来帮助您完成此操作。

  1. 使用源代码构建在您的项目上运行 cmake
  2. cd 到构建目录
  3. 从构建树 git add 中创建一个 git 存储库。git commit -m“添加构建树”
  4. 更改导致重建的 cmakefile
  5. 在构建树 cmake 上重新运行 cmake 。
  6. 运行 git diff 看看发生了什么变化。