2

I'm just testing to see how small I can make this C++ code

#include <iostream>
using namespace std;

int main() {
    cout << "hi";
}

using this zsh command:

g++ test.cpp -Os -g -o main

but the smallest I can make it is 52 Kb, so is there any way to make it even smaller?

ks1322
  • 33,961
  • 14
  • 109
  • 164

2 Answers2

6

Using your code and compiler flags with g++ 11.2 I get a 35,8kB executable (different result could be explained by using a different compiler version or target system).

  1. Removing the -g flag (debugging symbols for GDB GNU Debugger or LLDB Clang/LLVM Debugger) brings the output file's size down to 16,3kB.
  2. You can modify your code without changing its functionality in the following way (16,0kB):
#include <stdio.h>

int main(){
    fputs("hi", stdout);
    return 0;  // doesn't change the output, only here for completeness sake
}
  1. Using clang to compile above code further reduces output executable's size to 15,9kB.

  2. Adding the -s flag (strip debug information): 14,5kB (same results using both clang and g++ 11.2)

Comparison table (best results in bold):

code compiler flags size step
original g++ 8.5.0 -Os -g 38 496 B
-Os 16 304 B
-Os -s 14 464 B
g++ 11.2.0 -Os -g 35 848 B 0
-Os 16 320 B 1
-Os -s 14 464 B
clang 11.0.1 -Os -g 30 736 B
-Os 16 304 B
-Os -g 14 552 B
clang 13.0.0 -Os -g 29 312 B
-Os 16 232 B
-Os -s 14 488 B
modified g++ 8.5.0 -Os -g 18 552 B
-Os 16 000 B
-Os -s 14 464 B
g++ 11.2.0 -Os -g 18 616 B
-Os 16 000 B 2
-Os -s 14 464 B
clang 11.0.1 -Os -g 16 720 B
-Os 15 960 B
-Os -s 14 528 B
clang 13.0.0 -Os -g 16 640 B
-Os 15 888 B 3
-Os -s 14 464 B 4
chubercik
  • 534
  • 1
  • 5
  • 13
  • 1
    Try adding `-flto`. – HolyBlackCat Jul 27 '22 at 22:36
  • 2
    You should also strip symbols if you haven't done so yet, i.e. `-s` or `-Wl,-s` or a call to `strip`. – user17732522 Jul 27 '22 at 23:15
  • @user17732522 I was about to post an answer just about the `-s`... – Zakk Jul 27 '22 at 23:17
  • @Zakk Go ahead. I only commented instead of writing an answer myself because I am too lazy to test the results. – user17732522 Jul 27 '22 at 23:17
  • @user17732522 I have just noticed that the OP's explicitly compiling with clang. I have tested for GCC, so I don't think the results are relevent. – Zakk Jul 27 '22 at 23:24
  • It would be nice if you organize all the results you obtained in a table: compiler, command, output size... – Zakk Jul 27 '22 at 23:26
  • I'll give it a try, gimme a minute – chubercik Jul 27 '22 at 23:32
  • 1
    Be aware that the process size (runtime memory usage) will be still much bigger because glibc is linked in dynamically. You can measure it with ```/usr/bin/time -v```. With a smaller libc, e.g. musl or dietlibc and ```-static```, you could get down to 0.2K, according to this bloat comparison: http://www.etalabs.net/compare_libcs.html – rudimeier Jul 27 '22 at 23:41
  • 1
    Another idea is to use ```-m32``` to build smaller 32bit binaries. x86_64 CPUs can still run this. BTW on my Ubuntu 18 system I get much smaller results (5612 B). What system do you have? – rudimeier Jul 28 '22 at 00:12
  • #2 defeats the C++ness of the exercise – Spencer Jul 28 '22 at 00:20
  • @Spencer fair enough, but given that C++ is, for the most part, a superset of C, I considered my changes to be allowed here – chubercik Jul 28 '22 at 00:26
  • @rudimeier I use Kubuntu 21.10 – chubercik Jul 28 '22 at 00:35
  • using all of the tips in this comment section I can only get it down to 50,808 bytes with `#include int main(){ fputs("hi", stdout); return 0; // doesn't change the output, only here for completeness sake }` and `clang++ test.cpp -Os -s -flto -o main` – I_like_python Jul 28 '22 at 01:10
  • sorry for the bad editing bty – I_like_python Jul 28 '22 at 01:11
  • Also I was looking at the hexidecimal of the executable and I found large chunks of empty space [example](https://drive.google.com/file/d/1QCWrvuYY21CPNy76cEWYg535rTUjYyIN/view?usp=drivesdk) – I_like_python Jul 31 '22 at 00:57
  • How can I specify the compiler version? `gcc 11.2` gives a error 11.2 no such file or directory – user16217248 Jan 27 '23 at 18:38
  • @user16217248 maybe try `gcc-11.2`? – chubercik Jan 28 '23 at 14:33
1

As mentioned, you should to strip symbols by "-s"

By using "-m32" you may define 32-bit code generation, which should be a bit more compact.

Finally, I suggest using the UPX compressor.

gcc -s -Os -m32 main.c

gcc 12.2.0 + upx = 6144 bytes win32 executable

With some additional effort you may go under 1k footprint range:

kimstik
  • 1,611
  • 2
  • 15
  • 14