cmake 为release版本创建pdb文件

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


原理:https://www.wintellect.com/correctly-creating-native-c-release-build-pdbs/,摘录如下:


If you’ve read any of my books that discussed native debugging, I’ve been shouting that you must build PDB files for all builds. Of course, if you are paid by the hour don’t build PDB files so debugging is massively harder and you have guaranteed employment. There’s nothing like debugging yourself a new car. Just kidding!

One of the issues that you bump into with debugging release build native C++ applications are the compiler optimizations. For example, many local variables disappear because instead of putting them on the stack, as what happens in debug builds, the code generator puts them in registers instead. Additionally, release builds aggressively inline calls to functions so the code generator puts the body of the function directly in the calling method. Once you get used to the compiler’s patterns, and know a bit of assembly language, it’s not too hard to figure out what’s going on when debugging release build code. If you have never debugged release builds, I’d highly recommend the outstanding book, Advanced Windows Debugging, by Mario Hewardt and Daniel Pravat to get you started.

What I want to cover in this article are the exact switches necessary to properly create native C++ release build PDBs without screwing up your application so I can answer Sa’s question. The switches I will show you have nothing to do with optimizations and PDB file creation does not affect optimizations.

The first switch to set is on the compiler, CL.EXE and it’s /Zi. This switch will put the debug information in the .OBJ file so the linker can put it into the final PDB. You’ll set this switch in the project’s C/C++ property page as shown below.

The next three switches apply to the linker, LINK.EXE. The first, /DEBUG, tells the linker that you want to build create a PDB file for this build. Here’s the property page:

There’s a small problem with the /DEBUG switch. Turning it on tells the linker that you are doing a non-optimized build so /DEBUG implicitly turns on the /INCREMENTAL and essentially creates a debug build, though the compiler optimizations would apply (but not the link time code generation optimizations). What this means to you is that the linker links in “fast mode” so if you have an OBJ that has 300 functions in it, but you only reference (i.e., use) one of those functions, the linker puts all 300 functions into the output binary. Yes, that means 299 dead functions and a really bloated binary.

This “throw everything into the output binary” is one of the reasons your debug builds are so much bigger than your release builds. The Microsoft optimization technologies are extremely good, but not that good!

Because you only want those functions you actually reference in the output binary, you need to tell that to the linker with the /OPT:REF switch, which is set in the Optimization section of the linker as below:

The final linker switch you need to set is a an interesting little gem: /OPT:ICF. This turns on COMDAT folding. Wow! There’s a term you don’t hear every day. This is a nice little compiler optimization where the linker will look for functions that have identical assembly language code and only generate one of them. The first time most people here about COMDAT folding it throws them for a loop. However, when you consider how many functions, especially STL templates that are simple and identical, this COMDAT folding can help you slim down your binaries. For a more detailed discussion, see Raymond Chen’s examples and why on rare occasions optimized builds step into the “wrong” function with this switch turned on. If you looked closely at the Optimization section of the screen shot above, you’ll see the /OPT:ICF option is right below the /OPT:REF option.

In Sa’s case, I bet the reason their release build binaries are growing because they aren’t setting the /OPT:REF and /OPT:ICF switches. The only information added to a native C++ binary with these switches on is the debug directory in the output binary. As I mentioned in the first article in this series, you can peer into your Portable Executable files with the DUMPBIN program:

PS > dumpbin /headers foo.dll
// Output clipped for clarity.
Debug Directories
Time Type Size RVA Pointer
——– —— ——– ——– ——–
4A831A79 cv 4A 0000A5C0 97C0
Format: RSDS, {9FCACFCD-1503-4B25-A2EA-6009EAFC83BA}, 1, c:foofoo.pdb
// Output clipped for clarity.

I hope that clears things up for Sa and everyone else still working on native C++ applications. While .NET gets all the coverage these days, a huge amount of the Windows world still works because of those applications. Do you have any other questions about PDBs or debugging? Ask away by sending me an email (john @ this company’s domain) or through a question on the blog.


  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: CMake是一个跨平台的构建工具,可用于创建、测试和打包C++代码项目。在CMake中,release编译是指构建一个用于发布的版本,它会对代码进行优化以提高执行速度和减少二进制文件的大小。 与debug编译相比,release编译关注的是代码的运行和执行效率。为了使代码更快地运行,release编译对代码进行了优化,例如去除代码中没有使用的部分,减少代码中的重复计算等。这些优化可以大大提高代码的运行速度和执行效率。 另外,release编译还会生成可以直接发布的二进制文件,它们没有debug信息和其他调试工具,因此文件的大小也会减少。这些二进制文件通常比debug版本的快速执行,因为它们包含更少的调试代码和其他元数据。 总之,release编译的目标是创建一个性能更好、文件更小的产品版本,可供最终用户使用。因此,在编译代码时,开发人员应该仔细选择构建目标,以便最大化代码性能和效率。 ### 回答2: CMake是一种跨平台的开源构建自动化工具,它可以帮助程序员管理C++编译、依赖、链接、测试等方面的问题。Release编译是指在发布产品的时候进行的编译操作,目的是生成可执行的、优化过的、没有调试信息的程序,以提高产品的性能和安全性。 要进行CMake Release编译,需要在CMake中进行一些配置和设置。下面是具体的步骤: 1. 在CMakeLists.txt文件中添加编译选项:在CMakeLists.txt文件中添加set(CMAKE_BUILD_TYPE "Release"),这会告诉CMake编译器使用Release模式来进行编译,以优化程序性能。 2. 清空已有的编译文件:在编译Release版本之前应该先清空已有的编译文件。在命令行中进入项目目录后,输入rm -rf build/,即可清空build文件夹。 3. 建立编译目录:在命令行中输入mkdir build && cd build,新建一个名为build的文件夹,同时进入此文件夹。 4. 运行CMake:在build文件夹下,运行cmake .. ,这会自动生成Makefile。 5. 进行Release编译:在build文件夹下,运行make -j4,其中-j4表示使用4个线程进行编译。在编译完成之后,即可生成可执行的、没有调试信息的Release版本的程序。 需要注意的是,如果项目有依赖库,需要在CMakeLists.txt中添加链接库的选项,如target_link_libraries(),以确保在编译时能够正确链接这些依赖库。 总之,CMake Release编译可以生成优化过的、没有调试信息的程序,从而提高应用程序的性能和安全性,是开发人员必须掌握的基本技能之一。 ### 回答3: 在软件开发过程中,我们通常需要将代码编译为可执行文件,以供用户使用。不同的编译方式会影响最终的程序性能、文件大小等因素。 CMake是一款跨平台的编译工具,在编译过程中可以将源代码转化为目标代码或者可执行文件。在使用CMake进行编译时,我们通常会选择编译模式,包括Debug和Release两种。 Debug模式主要用于调试程序,开启了各种优化等设置,但同时也增加了程序的体积,降低了程序的性能。而Release模式则是为了获得最佳的程序性能和最小的程序体积,同时舍弃了调试信息和其他的优化设置。 在使用CMake进行Release编译时,我们需要对CMake进行一些设定。首先,我们需要在CMakeLists.txt中设置编译模式,标明我们要进行的是Release编译。其次,我们需要选择在Release模式下使用哪些编译器选项,以达到最佳的程序性能和最小的程序体积。在编译完成后,我们还可以使用各种工具对程序进行优化设置,以进一步提高程序的性能和减少程序的体积。 总的来说,CMake Release编译过程需要我们进行多次设定和优化设置,以达到最佳的程序性能和最小的程序体积。只有在熟练掌握这些技巧并加以实践之后,才能为我们的程序带来更好的表现和用户体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值