1. Reducing the size of a compiled executable
    1. Generating the smallest possible, self-contained executable
    2. OS X

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:

(import scheme) ;; required due to -explicit-use later on
(display "Hello, world!\n")

You need the files library.c, runtime.c, build-version.c, chicken.h from the CHICKEN source distribution. In addition, you need the generated chicken-config.h file for your target platform (which can be done with make chicken-config.h, optionally with a PLATFORM passed in).

First we generate hello.c from hello.scm:

$ chicken hello.scm -explicit-use

The option -explicit-use (note the single dash) tells the compiler not to link in the evaluator and other compilation units, since we just want the basic Scheme library (and the runtime system). The compiler is smart enough to know what compilation units to add based on any import statements being used.

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 -DHAVE_CHICKEN_CONFIG_H -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  -DHAVE_CHICKEN_CONFIG_H
 $ 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 -DHAVE_CHICKEN_CONFIG_H

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?

OS X

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.