New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Static binaries are too big #2

Closed
bkauler opened this Issue Sep 8, 2018 · 7 comments

Comments

Projects
None yet
2 participants
@bkauler

bkauler commented Sep 8, 2018

Hmmm, I just realised something. I reported in previous issue:

#1

that I successfully compiled 'i386-uclibc-gcc'. I tested with a simple hello world:

#include <stdio.h>
int main()
{
   // printf() displays the string inside quotation
   printf("Hello, World!");
   return 0;
}

Compile and strip:

# ./i386-uclibc-gcc -o hello hello.c -static
# strip hello

Before stripping, size is 276K, after stripping is 262K!!!

I have gcc 6.3.0, binutils 2.28.

@pts

This comment has been minimized.

Show comment
Hide comment
@pts

pts Sep 8, 2018

Owner

Before stripping, size is 276K, after stripping is 262K!!!

It should be about 17K stripped, that's the size which I get with xstatic gcc -s -O2 hello.c. Maybe the problem is that ./i386-uclibc-gcc is linking against glibc rather than uClibc, probably because the gcc -L flag it uses is wrong.

Owner

pts commented Sep 8, 2018

Before stripping, size is 276K, after stripping is 262K!!!

It should be about 17K stripped, that's the size which I get with xstatic gcc -s -O2 hello.c. Maybe the problem is that ./i386-uclibc-gcc is linking against glibc rather than uClibc, probably because the gcc -L flag it uses is wrong.

@bkauler

This comment has been minimized.

Show comment
Hide comment
@bkauler

bkauler Sep 8, 2018

I am far from expert at this, but compiled hello.c with gcc and uclibc directly:

export C_INCLUDE_PATH=/usr/i386-linux-uclibc/usr/include
export CPLUS_INCLUDE_PATH=/usr/i386-linux-uclibc/usr/include
export LIBRARY_PATH=/usr/i386-linux-uclibc/usr/lib

# gcc -nostdlib -static -L/usr/i386-linux-uclibc/usr/lib /usr/i386-linux-uclibc/usr/lib/crti.o /usr/i386-linux-uclibc/usr/lib/crt1.o /usr/i386-linux-uclibc/usr/lib/crtn.o  -nostdinc hello.c -o hello -isystem /usr/i386-linux-uclibc/usr/include -D__uclibc__   /usr/i386-linux-uclibc/usr/lib/libc.a -I/usr/i386-linux-uclibc/usr/include -I/usr/lib/gcc/i686-oe-linux/6.3.0/include

Still get 262KB after stripping. Tried sstrip also, got it down to 261KB!

I googled around, and found this post:

https://mailman.uclibc-ng.org/pipermail/devel/2016-December/001312.html

... 107K and growing! It is still better than 600K+ with glibc, however, if this is true, then uclibc-ng has gone to the dogs. The main usage, for me anyway, is to produce small executables.

Looks like I am going back to musl.

bkauler commented Sep 8, 2018

I am far from expert at this, but compiled hello.c with gcc and uclibc directly:

export C_INCLUDE_PATH=/usr/i386-linux-uclibc/usr/include
export CPLUS_INCLUDE_PATH=/usr/i386-linux-uclibc/usr/include
export LIBRARY_PATH=/usr/i386-linux-uclibc/usr/lib

# gcc -nostdlib -static -L/usr/i386-linux-uclibc/usr/lib /usr/i386-linux-uclibc/usr/lib/crti.o /usr/i386-linux-uclibc/usr/lib/crt1.o /usr/i386-linux-uclibc/usr/lib/crtn.o  -nostdinc hello.c -o hello -isystem /usr/i386-linux-uclibc/usr/include -D__uclibc__   /usr/i386-linux-uclibc/usr/lib/libc.a -I/usr/i386-linux-uclibc/usr/include -I/usr/lib/gcc/i686-oe-linux/6.3.0/include

Still get 262KB after stripping. Tried sstrip also, got it down to 261KB!

I googled around, and found this post:

https://mailman.uclibc-ng.org/pipermail/devel/2016-December/001312.html

... 107K and growing! It is still better than 600K+ with glibc, however, if this is true, then uclibc-ng has gone to the dogs. The main usage, for me anyway, is to produce small executables.

Looks like I am going back to musl.

@bkauler

This comment has been minimized.

Show comment
Hide comment
@bkauler

bkauler Sep 9, 2018

Had to find out what is going on here! I compiled the latest uclibc from git (NOT uclibc-ng), last commit was in 2015, added some patches from the T2-project, used it to compile 'hello.c' --- aargh, got 254K stripped.

So, looked into the .config file. Locale support is turned on, with support for all locales. I changed that to just support "en_US", this time 'hello' is 102K not stripped, 86K stripped.

Very interesting, that all the locale data is builtin to the binary.

86K is still high, so will experiment some more with the .config file. But it sure does beat 650K with glibc!

This issue can be closed.

bkauler commented Sep 9, 2018

Had to find out what is going on here! I compiled the latest uclibc from git (NOT uclibc-ng), last commit was in 2015, added some patches from the T2-project, used it to compile 'hello.c' --- aargh, got 254K stripped.

So, looked into the .config file. Locale support is turned on, with support for all locales. I changed that to just support "en_US", this time 'hello' is 102K not stripped, 86K stripped.

Very interesting, that all the locale data is builtin to the binary.

86K is still high, so will experiment some more with the .config file. But it sure does beat 650K with glibc!

This issue can be closed.

@bkauler

This comment has been minimized.

Show comment
Hide comment
@bkauler

bkauler Sep 12, 2018

To round off this issue, a bit more info.

By disabling locale support, testing with uclibc-ng, got Hello World down to 56K. See comment here:

http://www.etalabs.net/compare_libcs.html

Quoting:

It should be noted that uClibc was tested with many optional features enabled, particularly locale. Due to a bug (design flaw) in uClibc's locale support, locale loading code and malloc get linked even in programs which never use setlocale.

There are other features, I think iconv support is one, if enabled, get into the static executable whether used or not. I reckon this rates as a bug.

bkauler commented Sep 12, 2018

To round off this issue, a bit more info.

By disabling locale support, testing with uclibc-ng, got Hello World down to 56K. See comment here:

http://www.etalabs.net/compare_libcs.html

Quoting:

It should be noted that uClibc was tested with many optional features enabled, particularly locale. Due to a bug (design flaw) in uClibc's locale support, locale loading code and malloc get linked even in programs which never use setlocale.

There are other features, I think iconv support is one, if enabled, get into the static executable whether used or not. I reckon this rates as a bug.

@pts pts added the question label Sep 12, 2018

@pts

This comment has been minimized.

Show comment
Hide comment
@pts

pts Sep 12, 2018

Owner

Thank you for investigating binary bloat when linking with newer versions of uClibc and uclibc-ng.

However, large binary sizes with uclibc-ng shouldn't be considered a bug of pts-tcc, thus I've labeled this issue as question. Feel free to report this as a bug to the uclibc-ng maintainers.

Please note that pts-tcc was designed to be used with uClibc 0.9.30.1 (from 2009). xstatic gcc can be used on modern Linux systems (as well as old ones) to link against uClibc 0.9.30.1. Download pts-xstatic from here. xstatic gcc -s -O2 hello.c produces a 17 kB hello-world binary for Linux i386.

It may be interesting to upgrade pts-tcc to use uClibc 0.9.33.2 (from 2012, the last uClibc release) and check file sizes. If you feel like doing so, please create a separate issue for that.

Owner

pts commented Sep 12, 2018

Thank you for investigating binary bloat when linking with newer versions of uClibc and uclibc-ng.

However, large binary sizes with uclibc-ng shouldn't be considered a bug of pts-tcc, thus I've labeled this issue as question. Feel free to report this as a bug to the uclibc-ng maintainers.

Please note that pts-tcc was designed to be used with uClibc 0.9.30.1 (from 2009). xstatic gcc can be used on modern Linux systems (as well as old ones) to link against uClibc 0.9.30.1. Download pts-xstatic from here. xstatic gcc -s -O2 hello.c produces a 17 kB hello-world binary for Linux i386.

It may be interesting to upgrade pts-tcc to use uClibc 0.9.33.2 (from 2012, the last uClibc release) and check file sizes. If you feel like doing so, please create a separate issue for that.

@bkauler

This comment has been minimized.

Show comment
Hide comment
@bkauler

bkauler Sep 13, 2018

Sorry, I meant that it could be perhaps considered to be a bug of uclibc-ng, not pts-tcc.

bkauler commented Sep 13, 2018

Sorry, I meant that it could be perhaps considered to be a bug of uclibc-ng, not pts-tcc.

@pts

This comment has been minimized.

Show comment
Hide comment
@pts

pts Sep 14, 2018

Owner

Thank you for reporting this!

Now https://github.com/pts/pts-tcc/blob/master/pts-tcc-0.9.26-compile.sh uses a specific, hardcoded version of precompiled uClibc which doesn't have the binary bloat you are experiencing with uclibc-ng.

I'm closing this issue now since I can't see how pts-tcc can be improved in this aspect. Feel free to open new issues if you encounter anything.

Owner

pts commented Sep 14, 2018

Thank you for reporting this!

Now https://github.com/pts/pts-tcc/blob/master/pts-tcc-0.9.26-compile.sh uses a specific, hardcoded version of precompiled uClibc which doesn't have the binary bloat you are experiencing with uclibc-ng.

I'm closing this issue now since I can't see how pts-tcc can be improved in this aspect. Feel free to open new issues if you encounter anything.

@pts pts closed this Sep 14, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment