我有一个使用 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 构建。
为什么?我该怎么做才能获得所需的行为?
最佳答案
首先:CMake 的推荐用法是始终在命令行上明确指定 CMAKE_BUILD_TYPE
(当且仅当使用单一配置生成器时)。您的用例偏离了此最佳实践,因此请将此答案视为“您如何做”,而不一定是“您应该如何做”。
要解决第一个问题,您应该能够在 CMakeList 的早期执行此操作:
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif()
set(CMAKE_CXX_FLAGS "-Wall -Wextra")
set(CMAKE_CXX_FLAGS_DEBUG "-g")
set(CMAKE_CXX_FLAGS_RELEASE "-O3")
这将确保如果您根本不指定构建类型,它将默认为“发布”,因此将使用 CMAKE_CXX_FLAGS_RELEASE
。
第二个更难解决。从命令行传递的变量(例如 CMAKE_BUILD_TYPE=Debug
)由 CMake 缓存,因此在后续调用中重复使用(这是必要的,因为 CMake 可以重新触发如果您在构建之间修改其输入,则它本身)。
唯一的解决方案是让用户再次显式切换构建类型,使用 cmake .. -DCMAKE_BUILD_TYPE=Release
。
考虑为什么这是必要的:正如我所说,如果自上次 CMake 运行以来 CMake 的输入(CMakeLists.txt
文件或其依赖项)发生了变化,CMake 可以重新触发自身作为构建的一部分。在这种情况下,它也将在没有命令行参数(例如 -DCMAKE_BUILD_TYPE=whatever
)的情况下运行,并将依赖缓存提供与上次相同的值。这种情况与您手动运行 cmake ..
没有额外的参数没有区别。
如果没有在命令行上明确指定,我可以提供一个 hacky 解决方案来始终将 CMAKE_BUILD_TYPE
重置为 Release
。但是,这也意味着如果发生自动重新生成,生成为 Debug
的构建系统将重新生成为 Release
。我很确定这不是你想要的。
关于c++ - 默认在 CMake 中优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41361631/