假设我有一个带有两个独立子项目的项目。如果我正确地理解了cmake,这个想法是用一个根CMakeLists.txt
定义project(...)
,然后使用add_subdirectory(...)
包括子项目。每个子项目都有自己的CMakeLists.txt
来定义自己的项目。这样,项目既可以一起构建(使用根cmake文件),也可以单独构建(使用子项目的cmake文件)。
我现在想改变CMAKE_CONFIGURATION_TYPES
。我应该在根CMakeLists.txt
或在每个子项目中,或两者都这样做吗?
在根目录中更改它将意味着单独构建子项目将提供错误的配置类型;其他选项将复制cmake代码。我想我遗漏了一些东西。
分解出设置依赖于配置的设置的代码。创建一个文件,比如SetUpConfigurations.cmake
,内容如下:
if(NOT SET_UP_CONFIGURATIONS_DONE)
set(SET_UP_CONFIGURATIONS_DONE TRUE)
# No reason to set CMAKE_CONFIGURATION_TYPES if it's not a multiconfig generator
# Also no reason mess with CMAKE_BUILD_TYPE if it's a multiconfig generator.
get_property(isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if(isMultiConfig)
set(CMAKE_CONFIGURATION_TYPES "Debug;Release;Profile" CACHE STRING "" FORCE)
else()
if(NOT CMAKE_BUILD_TYPE)
message("Defaulting to release build.")
set(CMAKE_BUILD_TYPE Release CACHE STRING "" FORCE)
endif()
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY HELPSTRING "Choose the type of build")
# set the valid options for cmake-gui drop-down list
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug;Release;Profile")
endif()
# now set up the Profile configuration
set(CMAKE_C_FLAGS_PROFILE "...")
set(CMAKE_CXX_FLAGS_PROFILE "...")
set(CMAKE_EXE_LINKER_FLAGS_PROFILE "...")
endif()
然后include(..)
这个文件在CMakeLists.txt
的开头。
你有两个选择放在哪里SetUpConfigurations.cmake
,这取决于你如何组织你的项目,仓库:
最快捷的方法:复制并提交此脚本到每个需要它的项目中。相对于项目的
CMakeLists.txt
,它的位置将是固定的。所以你可以包括它,例如,include(${CMAKE_CURRENT_SOURCE_DIR}/<...>/SetUpConfigurations.cmake)
有纪律的方法:用你自定义的CMake脚本维护一个存储库,就像这样。每次使用
cmake
命令生成一个项目时,都要在CMAKE_MODULE_PATH
变量中传递到这个存储库的路径:cmake -DCMAKE_MODULE_PATH=<dir-of-cmake-script-repo> ...
在这种情况下,包含带有include(SetUpConfigurations)
(没有.cmake
扩展名)的脚本。
关于什么是multiconfig生成器的说明:
Xcode
和Visual Studio
是多配置生成器。它们尊重CMAKE_CONFIGURATION_TYPES
的值,但CMAKE_BUILD_TYPE
不起作用,因为在处理CMakeLists.txt
时没有定义具体的配置。它将在稍后的IDE用户界面上被选中。
另一方面,makefile样式的生成器对CMAKE_CONFIGURATION_TYPES
不感兴趣。CMAKE_BUILD_TYPE
定义配置。当处理CMakeLists.txt
文件时,它是一个具体的值,但仍然:永远不会根据CMAKE_BUILD_TYPE
:
if(CMAKE_BUILD_TYPE STREQUAL "Release") # WRONG!
....
endif()
你的项目在多配置生成器中不能正常工作。
当在子项目dir中使用add_subdirectory
时,您将几乎所有变量传播到该子项目中,这与"子项目独立性"相矛盾。
相反,最好在execute_process()
中使用嵌套的cmake
调用来构建和安装子项目。如果您想让一些子项目的定义可用于顶级项目,您需要在安装子项目时"导出"这些定义。这篇问答文章描述了如何做到这一点。