首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >CMake add_subdirectory与重新编译

CMake add_subdirectory与重新编译
EN

Stack Overflow用户
提问于 2011-12-12 19:45:24
回答 5查看 6.8K关注 0票数 3

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

代码语言:javascript
复制
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
  1. CMakeLists.txt文件配置编译标志、宏定义等,并使用CMake的add_subdirectory()包括由库和演示项目定义的目标。
  2. code子文件夹包含一个平面子文件夹列表,每个子文件夹都包含静态库的源代码(以及在CMakeLists.txt文件中定义的目标)。
  3. demo子文件夹包含一个扁平的子文件夹列表.每个文件都包含可执行文件和相关CMakeLists.txt文件的源代码。
  4. 每个库是一个独立的组件,构建独立于所有其他库和演示项目。
  5. 每个演示程序依赖于code子文件夹中的一个或多个不同的库。

这个设置真的很不错。如果我想改变构建选项,我只需要修改根CMakeLists.txt,所有的东西都会用新的设置重新编译。如果我在树中的任何地方修改任何源代码,适当的库(如果有的话)将被重新编译,并且所有依赖的演示程序也会被重新构建。

但是,如果我在树中的任何地方修改任何CMakeLists.txt文件,那么整个库和程序树就会在不考虑依赖关系的情况下重新编译。为了理解我的意思,这里是CMake构建脚本的几个部分。

project/demo/CMakeLists.txt

代码语言:javascript
复制
# 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

代码语言:javascript
复制
# 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以添加一个额外的库,如下所示:

代码语言:javascript
复制
set(${demo-project}_libraries
  library-1
  library-2
  library-5
  library-6
)

然后,重新编译项目中所有库和演示程序的全部源代码。为何会这样呢?是否有更好的方法来构造我的脚本以避免这种情况?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2011-12-21 18:42:56

碰巧我的问题是由一个完全无关的问题引起的。我应用了比尔·霍夫曼的建议,项目中任何"CMakeLists.txt“文件的修改最终都会修改所有生成的Makefile中的CXX_FLAGS (C++编译器标志)变量。

我将其追溯到根目录"CMakeLists.txt“文件,该文件有如下内容:

代码语言:javascript
复制
if(MSVC)
  # ...
  set(CMAKE_CXX_FLAGS_DEBUG
    "${CMAKE_CXX_FLAGS_DEBUG} /WX /wd4355" // depends on cached value.
    CACHE STRING "Debug compiler flags" FORCE)
  # ...
endif()

我把它改成了下面的。

代码语言:javascript
复制
if(MSVC)
  # ...
  set(CMAKE_CXX_FLAGS_DEBUG
    "/DWIN32 /D_WINDOWS /WX /wd4355" // no longer depends on cached value.
    CACHE STRING "Debug compiler flags" FORCE)
  # ...
endif()

CMake在更新构建脚本时不再重复/WX /wd4355标志,而且我的项目不再在每次修改时从头开始重新编译!

票数 2
EN

Stack Overflow用户

发布于 2011-12-21 17:05:29

你要做的第一件事就是找出什么改变。如果您安装了git,您可以使用git来帮助您做到这一点。

  1. 使用非源生成在项目上运行cmake
  2. 创建目录的cd
  3. 在构建树中创建一个git,git添加。git提交-m“添加构建树”
  4. 更改导致重新生成的cmakefile。
  5. 在构建树cmake上重新运行cmake。
  6. 运行git,看看有什么变化。
票数 4
EN

Stack Overflow用户

发布于 2011-12-21 16:51:13

确实,如果任何CMakeLists.txt文件更改(或任何对其的输入,例如configure_file调用的“源文件”),那么CMake将在构建树的顶层重新运行,并重新生成已更改的解决方案文件和项目文件。

但是,它只应该重新生成与上次运行时不同的文件.因此,基于你在问题中所展示的,我并没有一个很好的解释为什么一切都在重建。

另一方面,当触发“构建解决方案”时,CMake确实要由Visual来决定重新构建什么。除了将源和头放在正确的项目中、正确设置包含目录以及信任VS在头和源文件更改时正确分析包含和重新构建之外,我们不表示VS的任何依赖关系。

您不显示任何include_directories调用。您是否在顶级CMakeLists.txt文件中设置了这些值,以便使所有子目录都具有相同的包含值?如果是这样的话,也许这就是引发一切重建的原因。

我们当然会尽最大努力使CMake生产出最少重建时间的构建系统。

你的项目公开了吗?我能看到它的完整源代码并尝试在我自己的机器上重现这个问题吗?

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8479929

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档