使用 MinGW 的 C++ 可执行文件大小

ben*_*ben 6 c++ windows executable mingw

我通常用 C 编写 sizecoding 演示制作竞赛 (64kb),但考虑转向 C++。

MinGW g++ 下,我在 .exe 大小方面遇到了一些麻烦。(在使用可执行打包程序之前,我必须将其降低到 <100 kb。)。

我看过这个: 如何减少 MinGW g++ 编译器生成的可执行文件的大小? 但是我已经在使用 MinGW/g++ 4.8.1 和 -s -Os ......见下文(对于 4.8.1 也是: unrecognized option '-shared-libstdc++'cannot find -lstdc++_s)。

这个小小的 helloworld 只有10 kb(没关系):

#include "windows.h"
int main() {
    MessageBoxA(0, "test", "test", 0);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

但是,当我添加:

#include <string>
...
std::string asdf;
Run Code Online (Sandbox Code Playgroud)

它变成193 kb

当我添加:

#include <iostream>
Run Code Online (Sandbox Code Playgroud)

然后它变成了756 kb。

我正在使用这些标志:

-std=c++11
-Wall
-s       (or -Wl,-s)
-Os
-DNDEBUG
-fno-exceptions
-fno-rtti
(note: removed those with no effect)
Run Code Online (Sandbox Code Playgroud)

必须有某种方式只链接我使用的内容。我错过了什么?

选项 1:是否可以在 MinGW/g++ 4.8.1 中使用 -shared-libstdc++ 或 -lstdc++_s?

可选2:当我尝试-nostdlib替换mainWinMain

    #include "windows.h"
    int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 
        LPSTR lpCmdLine, int nCmdShow) {
        MessageBoxA(0, "test", "test", 0);
        return 0;
    }
Run Code Online (Sandbox Code Playgroud)

我没有收到编译器警告,但是运行时崩溃了,不过在编译为 C 时它工作正常。(可选,因为我不希望您/我花时间调试 crt-startup,用于修剪库的编译器链接器标志会更有帮助)

Mat*_*ice 6

这些额外的字节由标准库调用“拉入” - 高级库倾向于将它们下面的所有内容、内存分配、它们使用的异常等都带进来。最简单的开始就是尽量减少你使用的东西。基于 putchar() 的 hello world 可能会给你一个很好的比较点。我将专注于静态链接的程序,因为这就是我所知道的,无论如何,rubenvb 的答案似乎很好地涵盖了共享库。

新的、删除的、纯虚函数等特性也引入了库的一些部分和许多底层的依赖关系。关于如何替换它们的快速概述在这里:http : //ptspts.blogspot.com.au/2010/12/how-to-write-c-program-without-libstdc.html - 如果你变得非常极端,你可以找到以相同方式处理的 malloc 版本。

最近使用 C++11,如果你这样做,你会遇到 __cxa_guard_acquire 和 __cxa_guard_release:

int foo() {
    static int bar = 1; //thread safe in C++11, requires inbuilt functions
}
Run Code Online (Sandbox Code Playgroud)

为此,如果您的编译器支持,请使用 -fno-threadsafe-statics 标志。

如果这还不够,您可以在 ld 的 linux 版本上与标志 -Map=filename.map 链接以生成“地图”文件。输出文件的第一部分列出了被拉入的每个部分,以及需要它的部分。*

*映射文件还会显示函数节对标准库没有任何作用,因为它已经在没有该标志的情况下被编译,除此之外


Mic*_*iak 1

这是一个盲目的尝试,但在链接时尝试 -fwhole-program 选项。另外 -flto 在编译和链接时可能会有所帮助