简体   繁体   中英

C++ executable size using MinGW

I am normally writing in C for sizecoding demo-making competition (64kb) but considering moving to C++.

Under MinGW g++ i have some trouble with the .exe-size. (Before using executable-packers, i have to get it down to <100 kb.).

I have looked at this: How to reduce the size of executable produced by MinGW g++ compiler? however i am already using MinGW/g++ 4.8.1 and -s -Os ... see below (and for 4.8.1 too: unrecognized option '-shared-libstdc++' and cannot find -lstdc++_s ).

This little helloworld has only 10 kb (which is ok):

#include "windows.h"
int main() {
    MessageBoxA(0, "test", "test", 0);
    return 0;
}

However when i add:

#include <string>
...
std::string asdf;

it becomes 193 kb

And when i add:

#include <iostream>

then it becomes 756 kb.

I am using these flags:

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

There has to be some way to only link what i use. What am i missing?

Optional 1: Is it possible to get -shared-libstdc++ or -lstdc++_s working in MinGW/g++ 4.8.1?

Optional 2: When I try -nostdlib and replace main with WinMain :

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

I get no compiler warnings but a runtime crash, it works fine when compiling as C though. (optional because I don't want you/me to spend time debugging crt-startup, a compiler-linker-flag to trim libraries would be more helpful)

Those extra bytes are "pulled in" by standard library calls - the high level ones tend to bring everything below them along, memory allocation, the exceptions they use and so on. The easiest thing to start with is to minimize what you use. Basing a hello world on putchar() might give you a good point of comparison. I'll focus on statically linked programs as that's what I know, rubenvb's answer appears to cover shared libraries well anyway.

Features like new, delete, pure virtual functions etc. pull in bits of the library too and many dependencies underneath. A quick overview on how to replace those is here: http://ptspts.blogspot.com.au/2010/12/how-to-write-c-program-without-libstdc.html - if you get really extreme, you could find a version of malloc treated in the same way.

More recently with C++11 you'll run into __cxa_guard_acquire and __cxa_guard_release if you do this:

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

For that, use the -fno-threadsafe-statics flag if your compiler supports it.

If that doesn't quite get you far enough you can link with the flag -Map=filename.map on linux versions of ld to generate a "map" file. The first section of the file that outputs lists each section that was pulled in, along with the one that required it.*

*The map file would also reveal that function-sections does nothing to the standard library as it's already been compiled without that flag, apart from that

There is no way you can get rid of the extra code MinGW GCC compiled executables need to function. You might try a MinGW-w64 toolchain, which approaches the CRT differently, but it might be worse than plain MinGW in terms of "Hello world" size.

I strongly suggest using MSVC if binary size is that important, as it relies on its own CRT code built in to the OS. Which I may carefully call "cheating" in some way :-).

About the DLL libstdc++, of course it's possible, you just need a decent toolchain ;-). See here . Note that this is also "cheating", because I doubt the contest will ignore the size of the runtime libraries. This is why codesize contests are stupid. There is always another layer of the runtime you're ignoring. Until you hit bare metal kernel or assembly, which is not the point of said contest.

I tried to run your code under QT 5.1.0 MinGW 4.8 32 bit

#include "windows.h"
#include <string>
#include <iostream>
int main() {
    MessageBoxA(0, "test", "test", 0);


std::string asdf;

    return 0;
}

In release mode exe size is 34 kb, in debug mode exe size is 92 kb

It's a shot in the dark, but try -fwhole-program option when linking. Also -flto when compiling and linking may be helpful

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM