CMAKE_BUILD_TYPE在CMakeLists.txt中没有被使用。

111

我遇到了在 CMakeLists.txt 中将默认的构建配置设置为 Release 的问题。我在文件的顶部使用以下代码设置了 CMAKE_BUILD_TYPE:

#enable Release ALWAYS, configure vars
set(CMAKE_BUILD_TYPE Release)
set(EXECUTABLE_NAME "ParticleSimulator")
set(VERSION_MAJOR 0)
set(VERSION_MINOR 2)

但是,在构建我的项目并打开解决方案时,我总是看到Debug模式,这与我在CMakeLists文件中指定的相反。我做错了什么?

我看了一些其他的问题,但我没有看到任何与这个问题特别相关的东西。

CMakeLists.txt 的要点。


你清除了CMake缓存吗?http://www.cmake.org/pipermail/cmake/2008-September/023808.html - usr1234567
@usr1234567 是的,我也读过那个文件。我一定是做了什么愚蠢的事情阻止了 CMAKE_BUILD_TYPE 的工作... - Syntactic Fructose
@usr1234567 仍然没有运气...也尝试了 set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Configuration type" FORCE),但是没有起作用。 - Syntactic Fructose
4
set(CMAKE_BUILD_TYPE Release) 这并不是它的正确使用方式。这个命令虽然会在 Makefile 生成器中工作,但对于像 Xcode 和 Visual Studio 这样的 IDE,这行代码将被忽略,因为 Release/Debug 在内部切换。文档 已经很清楚地说明了这一点。如果你想限制你的编译变体,你需要设置 CMAKE_CONFIGURATION_TYPES - user2288008
@ruslo 请将您的评论发布为答案。 - usr1234567
1
附注:在此帖子中提供了设置CMAKE_BUILD_TYPE默认值的方法。一旦设置,使用make VERBOSE=1命令可以显示发送给编译器的完整命令,可用于验证是否有效。 - legends2k
3个回答

275

有两种类型的生成器:单配置和多配置。

单配置

类似于 Make 的生成器:Unix Makefiles, NMake Makefiles, MinGW Makefiles,...

您可以在生成步骤中设置配置类型:

cmake -H. -B_builds/Debug -DCMAKE_BUILD_TYPE=Debug "-GUnix Makefiles"

在这种情况下,构建步骤始终为调试
> cmake --build _builds/Debug
/usr/bin/c++ -g ...
> cmake --build _builds/Debug --config Debug # `--config` ignored
/usr/bin/c++ -g ...
> cmake --build _builds/Debug --config Release # yep, ignored
/usr/bin/c++ -g ...

多配置

IDE生成器:Visual Studio, Xcode

在生成步骤中忽略CMAKE_BUILD_TYPE,两者均适用:

> cmake -H. -B_builds -DCMAKE_BUILD_TYPE=Debug "-GVisual Studio 12 2013 Win64"

并且

> cmake -H. -B_builds -DCMAKE_BUILD_TYPE=Release "-GVisual Studio 12 2013 Win64"

将会产生相同的效果:

Enter image description here

这是因为所有的配置都是内部的(即,_builds/msvc-opaque/Release_builds/msvc-opaque/Debug或其他,无所谓)。您可以使用--config选项进行切换:
> cmake --build _builds --config Release
cl /O2 ...
> cmake --build _builds --config Debug
cl /Od ...

控制(?)

是的,你可以。只需定义CMAKE_CONFIGURATION_TYPES

# Somewhere in CMakeLists.txt
message("Generated with config types: ${CMAKE_CONFIGURATION_TYPES}")

默认输出:

-- Detecting CXX compiler ABI info - done
Generated with config types: Debug;Release;MinSizeRel;RelWithDebInfo
-- Configuring done

重写它:

> cmake -H. -B_builds -DCMAKE_CONFIGURATION_TYPES="Debug;Release" "-GVisual Studio 12 2013 Win64"
-- Detecting CXX compiler ABI info - done
Generated with config types: Debug;Release
-- Configuring done

Enter image description here

你甚至可以定义自己的配置类型:

> cmake -H. -B_builds -DCMAKE_CONFIGURATION_TYPES="Debug;MyRelease" -DCMAKE_CXX_FLAGS_MYRELEASE="/My-Rel-flag" -DCMAKE_EXE_LINKER_FLAGS_MYRELEASE="/My-Linker-flags" "-GVisual Studio 12 2013 Win64"

Enter image description here

并构建:

cmake --build _builds --config MyRelease

混乱?

如果你知道诀窍,一点也不混乱 :) 以下是如何在脚本/CI服务器/文档的构建说明中构建/测试配置:

> CONFIG=Debug
> cmake -H. -B_builds "-DCMAKE_BUILD_TYPE=${CONFIG}" # Set Debug to Makefile, ignored by IDE
> cmake --build _builds --config "${CONFIG}" # Build Debug in IDE, ignored by Makefile
> (cd _builds && ctest -VV -C "${CONFIG}") # Test Debug in IDE, ignored by Makefile

不良模式

if(CMAKE_BUILD_TYPE STREQUAL Debug) # Burn it with fire!!!
set(CMAKE_BUILD_TYPE MySuperRelease) # Be ready to catch a bug from IDE user...

不错

set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} --my-debug-flags")

运行良好。

target_compile_definitions(MyTarget PUBLIC "$<$<CONFIG:Debug>:MYDEBUG_MACRO>")

谢谢!:) 你为一个程序员节省了一天的时间。

使用Makefile对我很有效,我很高兴...

来自一本不错的人的好书的一些引用,你可能知道(重点是我的):

为什么要费心呢?那些在各种系统上编程或使用各种编译器的人关心这个问题,因为如果他们不这样做,就会被迫花费时间查找和修复晦涩难懂的错误。那些声称他们不关心可移植性的人通常是因为他们只使用单一的系统,觉得可以采取“语言就是我的编译器实现”的态度。这是一个狭隘和短视的观点。如果你的程序成功了,很可能会被移植,所以别人就必须找到并修复与实现相关的问题。此外,程序经常需要使用其他编译器进行编译,即使是你最喜欢的编译器的未来版本也可能会与当前版本有所不同。在编写程序时了解和限制实现依赖性的影响要容易得多,而在事后试图解决混乱则要困难得多。

13
谢谢您的深入回答,这个回答值得在4小时后获得赏金。 - Syntactic Fructose
3
我找到了一个答案:“-H.”是CMake的未记录功能。原文链接:https://dev59.com/xl0Z5IYBdhLWcg3wwyne。 - wally
1
我看到你试图修复文档问题。谢谢你的尝试。 :) 仍然没有令人满意的答案说明为什么不能将其记录下来或删除(如果确实存在风险)。 - wally
2
@Muscampester,仅供参考,最有趣的链接和解释可以在此页面找到。 - user2288008
@ruslo,如果不使用字符串相等性检查,那么检查当前配置是否为“Debug”的替代方法是什么? :) - helmesjo
显示剩余11条评论

15

您也可以使用以下代码片段:

if(NOT CMAKE_BUILD_TYPE)
    set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING
            "Default build type: RelWithDebInfo" FORCE)
endif()

3
各位,如果您对提交的答案进行了负面评价,请用几个词说明原因。因为在所有建议的答案中,这个简单的答案是唯一有效的。在那之前,我在这里找到了类似的“已接受”解决方案: https://blog.kitware.com/cmake-and-the-default-build-type/。 - Alex D
2
不支持Visual Studio生成器。 - sz ppeter

6

可能的一个情况是,其中一个子模块在缓存中设置了CMAKE_BUILD_TYPE值,即:

SET(CMAKE_BUILD_TYPE Debug CACHE) 

这意味着该值将从那一点起永久更新到配置运行结束。

追踪该值发生更改的问题所在的好方法是使用CMake的variable_watch。在您的主CMakelists.txt文件中,添加以下行:

variable_watch(CMAKE_BUILD_TYPE)

每次访问此变量时,这将打印到标准错误。 要将其记录到日志文件中,请执行以下操作:

cmake <your options> 2>variable_watch.log

您可能会看到类似以下的内容:

在 <...>/CMakeLists.txt 的 CMake 调试日志中:第 184 行 (add_library) 访问了变量 "CMAKE_BUILD_TYPE",其值为 "Debug"。

然后,您很可能会看到首次更改 CMAKE_BUILD_TYPE 的位置。从这里开始,您将更接近追踪有问题的 CMake 行。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接