Reducing the size of a compiled executable
Generating the smallest possible, self-contained executable
Here is a small demonstration for creating the smallest possible (while still self-contained) executable. A UNIX-like environment is assumed.
A simple hello-world program:
(display "Hello, world!\n")
You need the files library.c, runtime.c, build-version.c, chicken.h and buildtag.h from the Chicken source distribution.
First we generate hello.c from hello.scm:
$ chicken hello.scm -explicit-use -uses library
The options -explicit-use -uses library (note the single dashes) tell the compiler not to link in the evaluator, we just want the basic Scheme library (and the runtime system).
Now we compile hello.c, the runtime system in runtime.c, the core library library.c and build version information build-version.c into a single executable:
$ gcc hello.c runtime.c library.c build-version.c -Os -fomit-frame-pointer -fno-strict-aliasing -o hello -lm $ strip hello $ ./hello Hello, world! $ size hello text data bss dec hex filename 287958 536 12876 301370 4993a hello
This program is now fully self-contained:
$ ldd hello linux-gate.so.1 => (0xffffe000) libm.so.6 => /lib/tls/libm.so.6 (0x4002e000) libc.so.6 => /lib/tls/libc.so.6 (0x40050000) /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
You can also try using the GNU Autotools with compiled code.
Not all functionality provided by library.scm may be required, though. It is possible to use a custom library:
;;;; lib.scm (define (##sys#interrupt-hook reason state) #f) (define (##sys#error-hook code loc . args) (##core#inline "C_halt" "error"))
$ csc -c hello.scm -x -uses library $ csc -c lib.scm -raw -x -O2 -d0 $ gcc -c runtime.c -Os -fomit-frame-pointer -fno-strict-aliasing $ gcc hello.o runtime.o lib.o -Lchicken -lm
Using this library will generate an even smaller executable. Since you will need some library functions it will be necessary to copy parts of the original library.scm into your custom library. Doing this will require some knowledge of the CHICKEN internals.
Performing the compile above takes about 30sec for me. It seems that this can be sped up by precompiling runtime.c and library.c
$ gcc -c runtime.c library.c build-version.c -Os -fomit-frame-pointer -fno-strict-aliasing
then compile hello like so:
$ gcc hello.c runtime.o library.o build-version.o -Os -fomit-frame-pointer -fno-strict-aliasing -o hello -lm
Question: why is this so much smaller than compiling statically with libchicken.a?
Because we also link in at least the extras unit (unless -explicit-use is given) with libchicken.a.
Question: How about any eggs I might be using?
On PowerPC OS X, adding -C -mdynamic-no-pic to csc's options (Or passing -mdynamic-no-pic directly to gcc) will reduce the size of executables and other compiled files that aren't going to be dynamically loaded.