The well-known implementation of the standard C library is glibc. musl libc is another implementation of the standard C library. It uses the MIT License, and it is known for its simple implementation and small binary size. It is also used in Alpine Linux.

A comparison with glibc can be found here.

This post is a note on how to build PostgreSQL using musl libc.

Preparing musl libc

The source code of musl libc can be downloaded here. It seems that there is also a place called musl.cc where you can download pre-built binaries, but this time I built it from source code:

$ wget https://musl.libc.org/releases/musl-1.2.5.tar.gz
$ tar zxf musl-1.2.5.tar.gz
$ cd musl-1.2.5
$ ./configure --prefix=/home/masahiko/musl --syslibdir=/home/masahiko/musl-lib/
$ make
$ make install

By specifying --prefix and --syslibdir options, you can specify the directories where musl libc and the dynamic linker will be installed, respectively. The build completed in about 20 seconds in my environment.

You can find a program called musl-gcc in the bin directory of the installation destination:

$ ls /home/masahiko/musl/bin
musl-gcc

musl-gcc is a wrapper program (it’s actually a shell script), and it seems that when you compile programs using this, they will be linked against musl libc.

Building PostgreSQL from source code

Preparation

As preparation, include the musl-gcc installed above in the PATH:

$ export PATH=/home/masahiko/musl/bin:$PATH

Then, copy the directories /usr/include/linux, /usr/include/asm, and /usr/include/asm-generic to the location where musl libc was installed:

$ cd /home/masahiko/musl/include
$ cp -rs /usr/include/linux linux/
$ cp -rs /usr/include/asm asm/
$ cp -rs /usr/include/asm-generic asm-generic/

The reason for doing this will be explained later.

Build

Download the PostgreSQL source code and built it:

$ git clone git://git.postgresql.org/git/postgresql.git
$ cd postgresql
$ ./configure --prefix=/home/masahiko/pgsql CC=musl-cc --without-readline --without-icu --witout-zlib
$ make
$ make install

About CC=musl-cc

You can specify the compiler to use with CC.

About specifying --without-XXX

By default, PostgreSQL builds with readline, zlib, and icu enabled (in the case of using configure script). While the readline header files are in usr/include/readline, /usr/include also contains the header files of glibc. Therefore, if it’s configured to search /usr/include directory when compiling programs, the build using musl-gcc wouldn’t work. So I disabled these libraries for the build.

The reason I copied /usr/include/linux etc. directories in the preparation step was to deal with this problem. This seems to be the recommended way, but I went with it for now. I think readline etc. could also be built in a similar way. Not sure.

While PostgreSQL can be built without readline etc. /usr/include/linux etc. are essential for building PostgreSQL as PostgreSQL’s built-in programs are using it. For instance, pg_combinebackup requires /usr/include/linux. Without these steps, I got the following error in my environment:

musl-gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wimplicit-fallthrough=3 -Wcast-function-type -Wshadow=compatible-
local -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -Wno-format-truncation -Wno-stringop-truncation -O2 -I../../../src/interfaces/libpq -I../../../src/include  -D_GNU_SOURCE
   -c -o pg_combinebackup.o pg_combinebackup.c
pg_combinebackup.c:24:10: fatal error: linux/fs.h: No such file or directory
   24 | #include <linux/fs.h>
      |          ^~~~~~~~~~~~

WARNINGs during build

In my environment, I got the following WARNING during the build, but the build itself succeeded, so no problem:

pg_get_line.c: In function _pg_get_line_append_:
pg_get_line.c:129:27: warning: _({anonymous})_ may be used uninitialized [-Wmaybe-uninitialized]
  129 |         if (prompt_ctx && sigsetjmp(*((sigjmp_buf *) prompt_ctx->jmpbuf), 1) != 0)
      |                           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Veficiation

After building PostgreSQL from source code, verify that it is indeed linked against musl libc:

$ ldd bin/postgres
        linux-vdso.so.1 (0x00007ffd0bdf6000)
        libc.so => /home/masahiko/musl/lib/libc.so (0x00007f21be639000)

musl libc is not completely compatible with glibc, and there are some behavioral differences, make check-world also passed.

While musl libc is smaller as a library than glibc, glibc is faster in terms of performance, so I’d also like to compare the performance as the next step.