2016-06-05
Building Static Wasp Lisp Binaries on Linux
Wasp Lisp builds binaries that are linked dynamically to glibc. This ties the binary to specific versions of Linux. It's usually not possible to run on an OS with older glibc versions than what it was compiled against. I wanted to be able to run a single binary of Wasp Lisp and MOSREF drones on new Ubuntu versions and some machines with an older version of Ubuntu. To do this I needed to have the libc linked statically.
Changing Wasp Lisp to statically link glibc doesn't work though. Some networking routines in glibc require dynamic linking. If glibc is statically linked then networking doesn't work.
The solution I opted for is to use musl libc instead of glibc. This is a libc that was designed to be statically linked. To buid Wasp Lisp binaries with musl it required:
- Building musl libc
- Building libevent using musl libc headers
- Building Wasp Lisp against musl and libevent
Building musl libc
Building musl libc requires using git
to clone the repository and following the standard configure
, make
, make install
invocations. The bin
directory for the musl tools is added to the PATH
:
$ git clone git://git.musl-libc.org/musl
$ cd musl
$ ./configure
$ make
$ sudo make install
$ export PATH=$PATH:/usr/local/musl/bin/
Building libevent
Building libevent with musl requires using the musl-gcc
command which was installed by the previous step. This invokes GCC with the required options to use musl. The following steps performs the build:
$ wget https://github.com/libevent/libevent/releases/download/release-2.0.22-stable/libevent-2.0.22-stable.tar.gz
$ tar xvf libevent-2.0.22-stable.tar.gz
$ cd libevent-2.0.22-stable/
$ ./configure --prefix=/tmp/musl/usr CC=musl-gcc --enable-static --disable-shared
$ make
$ make install
Building Wasp Lisp
The Wasp VM source requires a change to the Makefile.cf
to use static linking for all libraries. This changes:
EXEFLAGS += -Wl,-Bstatic $(STATICLIBS) -Wl,-Bdynamic $(DYNAMICLIBS)
to:
EXEFLAGS += -static $(STATICLIBS) $(DYNAMICLIBS)
I've made this change in the static
branch of my github fork . This branch also includes some other changes from the official repository for real number support. Building with musl and libevent is done with:
$ git clone https://github.com/doublec/WaspVM --branch static
$ cd WaspVM
$ CC=musl-gcc CFLAGS="-I /tmp/musl/usr/include -L /tmp/musl/usr/lib" make repl
This runs directly into the Lisp REPL. The following confirms a static binary:
$ ldd wasp
not a dynamic executable
Building MOSREF
The stub generated is also static and can be used to build static drones:
$ cd mod
$ ../waspc -exe ../mosref bin/mosref
$ chmod +x ../mosref
$ ../mosref
console> set addr=xx.xx.xx.xx
console> set port=8000
console> drone mydrone foo linux-x86_64
Drone executable created.
The generated drone should run on a wider range of Linux versions than the non-static build at the cost of a larger size. I rename the waspvm-linux-x86_64
stub to be waspvm-musl-x86-64
so I can generate static drones or dynamic linked drones as needed from the MOSREF console by using linux-x86_64
or musl-x86_64
respectively.