臃肿的 EXE 大小,以及与 Qt/MingW 的不需要的依赖关系

2022-01-23 00:00:00 compiler-optimization qt4 g++ mingw c++

我正在尝试弄清楚如何缩小在最新 QT SDK (4.8.2)(基于 mingw/g++)下编译的 EXE 文件的大小.我正在开发一个香草 c++ 控制台应用程序,它有一个简单的循环并且只有#includes iostream,当我注意到它生成的 exe 大约为 465kb 时;比他们应该的要大得多!注释掉所有流的东西会使它降低到预期的 5kb 范围(尽管剩余的代码大部分都是死的).这似乎根本不对,特别是因为我正在处理的另一个完整项目有一个 QGLwidget、窗口、十几个数据结构和约 3000 条语句,并且只有大约 126Kb 的时钟.我缺少一些设置或标志吗?这是 .pro,而 cpp 是微不足道的且无 Qt(基本上是 getline 和 cout 与半打字符交换):

I'm trying to figure out how to shrink the sizes of EXE files compiled under the newest QT SDK (4.8.2) (mingw/g++ based). I was working on a vanilla c++ console app that has a simple loop and only #includes iostream, when I noticed that the exe's it generated are about 465kb; way bigger than they should be! Commenting out all the stream stuff brings it down to the expected 5kb range (although the remaining code would be mostly dead). This doesn't seem right at all, especially since another, full project I'm working on has a QGLwidget, windowing, a dozen data structures and ~3000 statements and only clocks in at about 126Kb. Is there some setting or flag I'm missing? Here's the .pro, while the cpp is trivial and Qt-free (basically getline and cout with a half dozen char swaps):

TEMPLATE = app
CONFIG += console
CONFIG -= app_bundle
CONFIG -= qt
SOURCES += main.cpp
QMAKE_CXXFLAGS_RELEASE += -O2
QMAKE_CXXFLAGS_RELEASE += -Os

我尝试了一些其他配置,它肯定是在发布模式下编译(调试大于 3Mb),但我不知道为什么它这么臃肿.

I've tried a few other configurations, and it's definitely compiling in release mode (debug is >3Mb), but I can't figure out why it's so bloated.

我还查看了 PE 标头,我发现它正在从 libgcc_s_dw2-1.dll 和 mingwm10.dll 导入一些函数,如果我也能完全消除这些依赖关系,那就太好了,尤其是因为无论如何都不需要.我可以通过将 QMAKE_LFLAGS_RELEASE += -static 添加到 .pro 来使 libgcc 消失(以 17kb 的 exe 大小为代价),但 mingwm10.dll 保持不变,调用单个函数.

I've also looked at the PE header, and I see that it's importing some functions from libgcc_s_dw2-1.dll and mingwm10.dll, and it'd be nice if I could eliminate those dependencies altogether as well, especially since neither one should be required anyway. I can make the libgcc one go away(at the expense of 17kb of exe size) by adding QMAKE_LFLAGS_RELEASE += -static to the .pro, but the mingwm10.dll stays either way, calling a single function.

基于整体膨胀,以及编译器试图潜入的所有无用框架的东西(至少是网络).我猜这只是一些歪斜的设置的问题,尤其是一些默认编译器标志,如 -DQT_LARGEFILE_SUPPORT 或 -mthreads.以下是编译输出(为强调而添加的项目符号):

Based on the overall bloating, and all the useless framework stuff that the compiler is trying to sneak in (networking, at least). I'm guessing it's just a matter of a couple settings that are askew, particularly with some of the default compiler flags like -DQT_LARGEFILE_SUPPORT or -mthreads. Here is the compile output (bullets added for emphasis):

  • 14:04:00:项目竞赛的运行步骤...
  • 14:04:00:配置不变,跳过 qmake 步骤.
  • 14:04:01:开始:C:QtSDKmingwinmingw32-make.exe"
  • C:/QtSDK/mingw/bin/mingw32-make -f Makefile.Release
  • mingw32-make[1]:进入目录`C:/Documents and Settings/Administrator/My Documents/QT/conTest'
  • g++ -c -O2 -O2 -Os -frtti -fexceptions -mthreads -Wall -DUNICODE -DQT_LARGEFILE_SUPPORT -I"c:QtSDKDesktopQt4.8.1mingwmkspecswin32-g++" -oreleasemain.o main.cpp g++ -Wl,-s -Wl,-subsystem,console -mthreads -o releaseconTest.exe release/main.o
  • mingw32-make[1]: 离开目录`C:/Documents and Settings/Administrator/My Documents/QT/conTest'
  • 14:04:10:进程C:QtSDKmingwinmingw32-make.exe"正常退出.

推荐答案

使用 mingw 的一个问题是 w32 版本的 binutils 不支持死代码剥离(它会删除你不支持的部分库't 实际使用.)为了减小可执行文件的大小,我必须使用此处的补丁从源代码修补和构建 binutils:

One of the problems with using mingw is that the w32 version of binutils doesn't support dead code stripping (it removes the parts of the libraries that you don't actually use.) In order to bring down the sizes of my executables, I had to patch and build binutils from source using the patches here:

http://sourceware.org/bugzilla/show_bug.cgi?id=11539

它有帮助.但要使其正常工作,您需要使用以下方法重建所有内容:

It helped. But for it to work, you will need to rebuild everything using:

-fdata-sections -ffunction-sections

在所有东西的编译标志中(包括 GCC、Qt、其他库和你自己的应用程序)和:

in the compile flags of everything (including GCC, Qt, other libraries and your own application) and:

-Wl,--gc-sections

仅在您的应用程序的链接标志中.这对我来说是值得的,因为以前我的可执行文件的大小约为 20MB,而现在已经减半,大约为 10MB.这包括所有库(我静态链接),包括 Qt、SDL 和各种媒体库(如 Vorbis、mpg123、FLAC 等.)

in the link flags of your application only. It was worth it for me, as previously my executables would weigh in at about 20MB and now that's been halved and they're about 10MB. This includes all libraries (I link statically), including Qt, SDL, and various media libraries (like Vorbis, mpg123, FLAC and others.)

虽然我认为如果您在 Windows 上构建,那么要做到这一切并不容易.我使用 Linux 构建所有东西的 w32 交叉编译版本,这要容易得多.

Although I imagine that if you build on Windows, it's not gonna be easy to do all that. I used Linux to build w32 cross-compile versions of everything, which is way easier.

相关文章