Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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)

like image 668
ben Avatar asked Aug 24 '13 01:08

ben


3 Answers

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

like image 152
Matthew Elvey Price Avatar answered Sep 26 '22 06:09

Matthew Elvey Price


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.

like image 32
rubenvb Avatar answered Sep 22 '22 06:09

rubenvb


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

like image 36
Michał Walenciak Avatar answered Sep 24 '22 06:09

Michał Walenciak