如何使用CMake标志为Release构建生成PDB文件?

20
我正在使用cmake生成Visual Studio解决方案。现在我想为Release版本生成pdb文件(为什么?因为我希望在用户发现某些错误时拥有符号)。
我尝试通过设置以下标志来生成,但并没有成功:
set(CMAKE_CONFIGURATION_TYPES ${CMAKE_BUILD_TYPE} CACHE STRING "Build Types" FORCE)

IF(WIN32)

set( CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/Release")
set( CMAKE_EXE_LINKER_FLAGS_RELEASE "/debug /INCREMENTAL")
set( CMAKE_SHARED_LINKER_FLAGS_RELEASE "/debug /INCREMENTAL")
set( CMAKE_MODULE_LINKER_FLAGS_RELEASE "/debug /INCREMENTAL")
set( CMAKE_CXX_FLAGS_RELEASE "/MD /Zi /O2 /Ob1 /D NDEBUG")
set( CMAKE_C_FLAGS_RELEASE "/MD /Zi /O2 /Ob1 /D NDEBUG")
ENDIF(WIN32)

看起来Cmake忽略了这些设置: 感谢您的帮助!


你能详细说明一下“without succeed”吗?你是否收到了错误提示,缺少结果或者只是无法正常工作? - Mr Mush
1
只是不起作用。我想知道这行代码 "set(CMAKE_CONFIGURATION_TYPES ${CMAKE_BUILD_TYPE} CACHE STRING "Build Types" FORCE)" 是否覆盖了标志。 - Eze Velez
我尝试了这个方法,除了add_executable(out a.cpp b.cpp)之外,当我构建Release配置时,还生成了一个.pdb文件。而且它是可调试的。你能提供更多细节吗?顺便说一下,在为MSVC生成时不要使用CMAKE_BUILD_TYPE - onqtam
3个回答

17

我使用了标志

set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zi")
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DEBUG /OPT:REF /OPT:ICF")

这个网站解释了详细内容


3
CMAKE_SHARED_LINKER_FLAGS_RELEASE是全局缓存变量,因此我必须添加CACHE STRING "" FORCE。还要确保根据需要使用CMAKE_STATIC_LINKER_FLAGS_RELEASECMAKE_EXE_LINKER_FLAGS_RELEASE变量。 - Nicolas Holthaus
变量 CMAKE_CXX_FLAGS_RELEASECMAKE_SHARED_LINKER_FLAGS_RELEASE 没有可用的 CMake 文档。你是在哪里找到它们的? - jaques-sam
哇,我不知道那个。谢谢! - jaques-sam
@DrumM,文档不是很多,但是有https://cmake.org/cmake/help/latest/variable/CMAKE_LANG_FLAGS_CONFIG.html和https://cmake.org/cmake/help/latest/variable/CMAKE_SHARED_LINKER_FLAGS_CONFIG.html。 - Andrey Starodubtsev
2
详细说明的相关文章已移至此处: https://www.wintellect.com/correctly-creating-native-c-release-build-pdbs/ - Frederik

10

另一种方法是使用cmake生成器表达式(https://cmake.org/cmake/help/latest/manual/cmake-generator-expressions.7.html),例如:

对于所有目标和配置:

add_compile_options("$<$<NOT:$<CONFIG:Debug>>:/Zi>")
add_link_options("$<$<NOT:$<CONFIG:Debug>>:/DEBUG>")
add_link_options("$<$<NOT:$<CONFIG:Debug>>:/OPT:REF>")
add_link_options("$<$<NOT:$<CONFIG:Debug>>:/OPT:ICF>")

仅针对特定目标和 Release 配置:

target_compile_options(my_exe PRIVATE "$<$<CONFIG:Release>:/Zi>")
target_link_options(my_exe PRIVATE "$<$<CONFIG:Release>:/DEBUG>")
target_link_options(my_exe PRIVATE "$<$<CONFIG:Release>:/OPT:REF>")
target_link_options(my_exe PRIVATE "$<$<CONFIG:Release>:/OPT:ICF>")

另外,对我而言 add_link_options 和 add_compile_options 运作得很好,但是扩展 CMAKE_* 变量(就像 2015 年的回复中所述)却对我没用。 - FourtyTwo
你不需要复制粘贴这些代码行,可以使用生成器表达式将多个选项传递给编译器。如果我没记错的话,用分号将它们分隔开,并在整个表达式外加上引号。 - Trass3r

1
在“现代 Cmake”中,您可以针对每个目标设置此项,这是正确的方法:
if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC" AND CMAKE_BUILD_TYPE MATCHES "Release")
   target_compile_options(${TARGET_NAME} PRIVATE /Zi)

   # Tell linker to include symbol data
    set_target_properties(${TARGET_NAME} PROPERTIES 
        LINK_FLAGS "/INCREMENTAL:NO /DEBUG /OPT:REF /OPT:ICF"
    )

    # Set file name & location
    set_target_properties(${TARGET_NAME} PROPERTIES 
        COMPILE_PDB_NAME ${TARGET_NAME} 
        COMPILE_PDB_OUTPUT_DIR ${CMAKE_BINARY_DIR}
    )
endif()

这些标志是MSVC特定的,而不是WIN32

2
在现代CMake中,您应该使用生成器表达式,因为MSVC在配置步骤期间未定义CMAKE_BUILD_TYPE的值。请参见https://dev59.com/EmAf5IYBdhLWcg3wnDwI中的已接受答案。 - R2RT
问题在于,你可以在配置时传递 -DCMAKE_BUILD_TYPE=Debug,然后在 Visual Studio(生成时)中将项目构建为 Release。因此,在多配置 IDE(包括 VS)中依赖于配置时的 CMAKE_BUILD_TYPE 不是可靠的。例如,在你的代码案例中,你可以相反地将 CMAKE_BUILD_TYPE 传递为 Release 然后通过 IDE 构建项目为 Debug,这样你很可能会得到重复的 "/INCREMENTAL:NO /DEBUG /OPT:REF /OPT:ICF" 标志。我同意,这在这种情况下可能不会有害,但可能会破坏其他构建。 - R2RT
1
经过重新阅读我的评论,我认为我可能没有表达出重点,即:您根本不应该为Visual Studio传递CMAKE_BUILD_TYPE,因为它不会使用它。引用文档:“此变量仅对单配置生成器有意义”。https://cmake.org/cmake/help/v3.15/variable/CMAKE_BUILD_TYPE.html 每当您在代码中使用它时,您应该将其视为任何其他用户定义的变量,例如MY_BUILD_TYPE变量。如果没有生成器表达式,您的方法只完成了“现代CMake”的一半。 - R2RT
没错!但是谁说我一定要用Visual Studio呢 :-) 唯一让我感到奇怪的是,你必须为其他调用执行相同的生成器表达式:set_target_propertiesset_target_properties。好像一个if就不够了。 - jaques-sam
1
-1 是关于 CMAKE_BUILD_TYPE 的问题。在没有明确检查活动生成器是否为单配置的情况下,读取该变量是无效的。 - Alex Reinking
显示剩余3条评论

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