我有一个使用 CMake 作为其构建系统的 C++ 项目。我想要以下行为:
如果 cmake 被调用为 cmake ..
,那么 CMAKE_CXX_FLAGS
是 -O3 -Wall -Wextra
如果 cmake 被调用为 cmake .. -DCMAKE_BUILD_TYPE=Debug
,那么 CMAKE_CXX_FLAGS
是 -g -Wall -Wextra
我尝试了以下
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
set(CMAKE_CXX_FLAGS "-O3 -Wall -Wextra")
set(CMAKE_CXX_FLAGS_DEBUG "-g -Wall -Wextra")
但这有一个大问题。首先,如果使用第二次调用,那么 -O3
和 -g
标志都会传递给编译器。此外,如果我使用第二次调用和之后的第一次调用, CMAKE_BUILD_TYPE
保持 Debug
尽管没有明确订购 - 所以虽然我想要一个优化的构建,但我得到了一个 Debug 构建。
为什么?我该怎么做才能获得所需的行为?
原文由 marmistrz 发布,翻译遵循 CC BY-SA 4.0 许可协议
首先:CMake 的推荐用法是始终在命令行上明确指定
CMAKE_BUILD_TYPE
(当且仅当使用单一配置生成器时)。你的用例偏离了这个最佳实践,所以把这个答案当作“你怎么做”,而不一定是“你应该怎么做”。要解决第一个问题,您应该能够在 CMakeList 的早期执行此操作:
这将确保如果您根本不指定构建类型,它将默认为“发布”,因此将使用
CMAKE_CXX_FLAGS_RELEASE
。第二个更难对付。从命令行传递的变量(例如
CMAKE_BUILD_TYPE=Debug
)由 CMake _缓存_,因此在后续调用中重新使用(这是必要的,因为如果您在构建之间修改其输入,CMake 可以重新触发自身)。唯一的解决方案是让用户再次显式切换构建类型,使用
cmake .. -DCMAKE_BUILD_TYPE=Release
。考虑一下为什么这是必要的:正如我所说,如果 CMake 的输入(
CMakeLists.txt
文件或其依赖项)自上次 CMake 运行以来发生了变化,则 CMake 可以重新触发自身作为构建的一部分。在这种情况下,它也将在没有命令行参数的情况下运行,例如-DCMAKE_BUILD_TYPE=whatever
,并将依赖缓存提供与上次相同的值。这种情况与您手动运行cmake ..
没有其他参数没有区别。如果没有在命令行上明确指定,我可以提供一个 hacky 解决方案来始终将
CMAKE_BUILD_TYPE
重置为Release
。但是,这也意味着生成为Debug
的构建系统将重新生成为Release
如果发生自动重新生成。我很确定这不是你想要的。