note

This article was last updated on November 20, 2023, 8 months ago. The content may be out of date.

A static build is compiled version of a program which has been statically linked against libraries, according to Wikipedia. In practice, it means we can run a binary anywhere in compatible environments without installing dependencies. Although the binary is considerably larger, it greatly simplifies deployments.

Learning by Example - cURL

First, we take a look at how a static binary of cURL can be produced:

34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# dependencies to build curl
apk add build-base clang openssl-dev nghttp2-dev nghttp2-static libssh2-dev libssh2-static

# these are missing on at least armhf
apk add openssl-libs-static zlib-static || true

# gcc is apparantly incapable of building a static binary, even gcc -static helloworld.c ends up linked to libc, instead of solving, use clang
export CC=clang

# apply patches if needed
#patch -p1 < ../static.patch
#apk add autoconf automake libtool
#autoreconf -fi
# end apply patches

# set up any required curl options here
#LDFLAGS="-static" PKG_CONFIG="pkg-config --static" ./configure --disable-shared --enable-static --disable-libcurl-option --without-brotli --disable-manual --disable-unix-sockets --disable-dict --disable-file --disable-gopher --disable-imap --disable-smtp --disable-rtsp --disable-telnet --disable-tftp --disable-pop3 --without-zlib --disable-threaded-resolver --disable-ipv6 --disable-smb --disable-ntlm-wb --disable-tls-srp --disable-crypto-auth --without-ngtcp2 --without-nghttp2 --disable-ftp --disable-mqtt --disable-alt-svc --without-ssl

LDFLAGS="-static" PKG_CONFIG="pkg-config --static" ./configure --disable-shared --enable-static --disable-ldap --enable-ipv6 --enable-unix-sockets --with-ssl --with-libssh2

make -j4 V=1 LDFLAGS="-static -all-static"

This snippet is from Travis Burtrum’s static curl repository. There are several important points:

  1. Install dependencies and their corresponding static libraries
  2. Configure the static build process
  3. Build statically

info

This process is straight-forward, but environmental variables and configuration parameters vary between different programs.

However, several parameters are mostly likely to be used by programs, and we can refer to the manuals if it doesn’t work out.

Environmental variables:

export CC=clang
export LDFLAGS="-static"
export PKG_CONFIG="pkg-config --static"

Configuration parameters:

./configure --disable-shared --enable-shared=no --enable-static --enable-all-static

The detailed parameters for a program can be found by running ./configure --help. Unknown parameters usually result in warnings.

Examples

tmux

tmux is a terminal multiplexer. It only has two dependencies: libevent and ncurses, both of which have static libraries in the official repository.

After downloading and extracting the tmux source code, we can execute the following commands:

# install libevent and ncurses
apk add libevent-dev libevent-static ncurses-dev ncurses-static

# configure the build process
./configure --enable-static

# build
make

rsync

rsync is an open source utility that provides fast incremental file transfer. Its build dependencies can be found here.

info

xxHash doesn’t have a static library for install. lz4 library from the official repository lacks the LZ4_compress_default function that rsync requires. Both of these libraries need to be compiled manually.

# install ACL, xattr, zstd and OpenSSL
apk add acl-dev acl-static attr-dev zstd-dev zstd-static openssl-libs-static openssl-dev

# compile xxHash and lz4 from source. omitted for brevity

# no extra parameters required. rsync uses environmental variables
./configure --enable-ipv6

# build
make

aria2

aria2 is the ultra-fast download utility. It can use different libraries for one of its specific features. We’re using OpenSSL because it’s simpler this way.

info

We have to compile OpenSSL in aria2 version 1.37.0 because prebuilt OpenSSL doesn’t have the legacy provider. Its configuration parameter is no-shared no-module.

OpenSSL requires perl to be configured. It also requires linux-headers to be compiled.

# install dependency
apk add libssh2-dev libssh2-static libxml2-dev libxml2-static zlib-dev zlib-static c-ares-dev c-ares-static sqlite-dev sqlite-static

## install xz, or in the final stage linking will fail
apk add xz-dev xz-static

# compile OpenSSL from source. omitted for brevity

# configure the compilation process. note that aria2 uses environmental variables to determine whether it's statically built
ARIA2_STATIC=yes ./configure  --with-ca-bundle=/etc/ssl/certs/ca-certificates.crt

# build
make