1 Standardverhalten von dub build

D-Pakete und D-Runtime: dub kompiliert alle D-Abhaengigkeiten direkt aus dem Quellcode mit in dein Binary ein. Auch die D-Runtime (druntime) und Standardbibliothek (Phobos) sind standardmaessig statisch enthalten (unter der unproblematischen Boost-Lizenz).

System-C-Bibliothek: Standardmaessig linkt dub jedoch weiterhin dynamisch gegen die System-glibc (libc.so.6). Ohne weitere Konfiguration haettest du also weiterhin das alte glibc-Versionsproblem auf fremden Linux-Systemen.

⚠️
Ein auf Ubuntu 24.04 kompiliertes Binary laeuft moeglicherweise nicht auf Debian 10 – wegen inkompatibler glibc-Symbol-Versionen.

2 Vollstaendig statische Builds mit dub + LDC

Du kannst dub anweisen, ein 100 % autarkes, statisches Binary zu erzeugen, das auf jeder Linux-Distribution laeuft – ohne glibc-Abhaengigkeit und ohne LGPL-Lizenzprobleme.

Der empfohlene Weg ist die Kombination aus dub + ldc2 + musl libc.

Option A – Kommandozeile

Wenn LDC installiert ist, reicht ein einzelner Befehl:

Option B – Projektdatei

Statisches Linken direkt in dub.json oder dub.sdl hinterlegen:

bashOption A – Kommandozeile
dub build --compiler=ldc2 --build=release --dflags="-static"
jsonOption B – dub.json
{
    "name": "mein-projekt",
    "dflags-ldc": ["-static"]
}
sdlOption B – dub.sdl
name "mein-projekt"
dflags "-static" platform="ldc"

3 Best Practice: Der 2-Zeilen-Docker-Build (Alpine Linux)

Da Alpine Linux von Haus aus auf musl (MIT-Lizenz) statt glibc basiert, ist dies der einfachste Weg, um mit dub ein portables Binary zu bauen:

dockerfileAlpine + LDC – statischer Build
FROM alpine:latest
RUN  apk add --no-cache ldc dub musl-dev gcc
WORKDIR /app
COPY . .
RUN  dub build --compiler=ldc2 --build=release --dflags="-static"
💡
Das fertige Binary kann anschliessend in ein leeres scratch-Image kopiert werden – das Ergebnis ist ein Image mit wenigen Megabytes und keinerlei Laufzeitabhaengigkeiten.

Das Ergebnis:

Vergleich: C

4 Die gleichen Probleme in C

Die zwei Kernprobleme – glibc-Versionsabhaengigkeit und LGPL-Lizenzkonflikt – existieren in C genauso, sind dort aber schwieriger zu loesen, weil keine uebergeordnete Build-Abstraktion wie dub vorhanden ist.

⚠️ Problem 1: glibc-Versionssymbole

Ein C-Binary, das auf Ubuntu 24.04 gebaut wurde, enthaelt Referenzen auf neue glibc-Symbole (z.B. GLIBC_2.38). Auf einem aelteren Debian 10 (glibc 2.28) schlaegt der Start fehl:

textFehlermeldung auf altem System
./mein_programm: /lib/x86_64-linux-gnu/libc.so.6:
  version 'GLIBC_2.38' not found (required by ./mein_programm)

Ursache: gcc linkt standardmaessig dynamisch gegen die System-glibc. Beim Start wird die Symbolversion geprueft – passt sie nicht, bricht der Loader ab.

⚠️ Problem 2: LGPL-Konflikt bei statischem Linken gegen glibc

glibc steht unter der GNU LGPL v2.1. Bei statischem Linken (gcc -static) entsteht ein Combined Work, das dem Nutzer technisch ermoeglichen muss, die glibc-Komponente auszutauschen (Relinking-Pflicht). Das ist fuer geschlossene Closed-Source-Binaeries problematisch und in der Praxis kaum umsetzbar.

Loesungsansaetze in C:

bashLoesung A – Statisch mit musl statt glibc (MIT-Lizenz)
# musl-gcc Wrapper installieren (Debian/Ubuntu)
apt install musl-tools

# Binary statisch gegen musl kompilieren – kein LGPL, kein Versionsproblem
musl-gcc -static -O2 mein_programm.c -o mein_programm

# Ergebnis pruefen
ldd mein_programm
# not a dynamic executable  ✔
bashLoesung B – Sysroot-Trick: auf altem glibc-Snapshot kompilieren
# Crosstool-NG oder ein Debian-Oldstable-Docker-Image als Buildumgebung nutzen
# Das Binary enthaelt dann nur Symbole bis zur alten glibc-Version
docker run --rm -v .:/src debian:buster-slim \
  bash -c "apt-get update -qq && apt-get install -y gcc && gcc -O2 /src/mein_programm.c -o /src/mein_programm"

# Laeuft dann auch auf neueren Systemen (abwaertskompatibel), aber nicht andersherum
dockerfileLoesung C – Alpine-Docker-Build (musl, analog zu D/dub)
FROM alpine:latest
RUN  apk add --no-cache gcc musl-dev
WORKDIR /app
COPY mein_programm.c .
RUN  gcc -static -O2 mein_programm.c -o mein_programm
# Ergebnis: echtes Standalone-Binary, MIT-lizenzierte C-Laufzeit
⚠️
Einschraenkung: Viele C-Projekte haben transitive Systemabhaengigkeiten (OpenSSL, libcurl, libpq, ...), die ebenfalls statisch gelinkt werden muessen. Das erfordert, alle diese Bibliotheken als statische Archive (.a) bereitzustellen – deutlich mehr Aufwand als in D, wo dub die gesamte Abhaengigkeitskette aus Quellcode baut.

Vergleich D/dub vs. C/gcc

Aspekt D / dub C / gcc
Standard-Linkage D-Code statisch, glibc dynamisch alles dynamisch
Vollstaendig statisch 1 Flag: --dflags="-static" musl-gcc -static oder Alpine
Lizenz C-Runtime Boost (problemlos) LGPL (glibc) → musl (MIT) als Ausweg
Transitive Deps statisch dub baut alles aus Quellcode Manuelle .a-Archive erforderlich
Gesamtaufwand ★★★★★ Sehr gering ★★★☆☆ Mittel bis hoch

📌 Zusammenfassung

Mit dub ist das D-Oekosystem ideal dafuer aufgestellt: Die Paket- und Runtime-Lizenzen stehen dir nicht im Weg, und ueber dub build --compiler=ldc2 --dflags="-static" (vorzugsweise in einer musl-Umgebung) erhaeltst du unkompliziert echte Standalone-Binaries. In C sind dieselben Ziele erreichbar – erfordern aber mehr manuelle Konfiguration, insbesondere sobald transitive Bibliotheksabhaengigkeiten ins Spiel kommen.