我刚刚将一个较大的项目从 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
CMakeLists.txt文件配置编译标志、宏定义等,并使用 CMakeadd_subdirectory()来包含库和演示项目定义的目标。code子文件夹包含子文件夹的平面列表,每个子文件夹都包含静态库的源代码(以及文件中定义的目标CMakeLists.txt)。demo文件夹包含子文件夹的平面列表。每个都包含可执行文件和关联CMakeLists.txt文件的源代码。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()
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()
如果我碰巧修改project/demo/demo-n/CMakeLists.txt以添加额外的库,如下所示:
set(${demo-project}_libraries
  library-1
  library-2
  library-5
  library-6
)
然后重新编译项目中所有库和演示程序的整个源代码。为什么会这样呢?有没有更好的方法来构建我的脚本以避免这种情况?
小智 5
您要做的第一件事就是弄清楚发生了什么变化。如果您安装了 git,则可以使用 git 来帮助您完成此操作。