Linux ar-Befehl: Statische Bibliotheken (.a) erstellen & verwalten

Einleitung

In der systemnahen Softwareentwicklung unter Linux spielen statische Bibliotheken (.a) eine zentrale Rolle bei der Modularisierung von C- und C++-Projekten. Das Unix-Standardwerkzeug ar (kurz für archiver) schnürt kompilierte Objektdateien zu wiederverwendbaren Paketen zusammen. Dieser Praxisleitfaden demonstriert den kompletten Workflow: vom initialen Zusammenstellen über das Inspizieren und Modifizieren von Archiven bis hin zur Indexierung via ranlib sowie essenziellen Fallstricken beim Linken.

Entwicklungsumgebung einrichten und Objektdateien (.o) erzeugen

Für den Einstieg werden die GNU-Binärdienstprogramme sowie der C-Compiler benötigt. Die Bereitstellung erfolgt über den Paketmanager mittels apt-get update -qq && apt-get install -y binutils gcc:

Paketquellen aktualisieren und binutils sowie gcc installieren

Um das System sauber zu halten, richtet man einen temporären Arbeitsbereich ein und wechselt mit mkdir -p /tmp/ar_demo && cd /tmp/ar_demo direkt dorthin:

Temporäres Arbeitsverzeichnis ar_demo anlegen und betreten

Als Demonstrationsbasis dient eine simple Additionsfunktion in C, die per echo 'int add(int a, int b) { return a + b; }' > math_add.c als Quellcodedatei gespeichert wird:

Quellcodedatei math_add.c mit Additionsfunktion schreiben

Analog dazu wird eine Subtraktionsroutine implementiert und mit echo 'int sub(int a, int b) { return a - b; }' > math_sub.c im Dateisystem hinterlegt:

Quellcodedatei math_sub.c mit Subtraktionsfunktion anlegen

Aus diesen Quelltexten müssen vor dem Archivieren maschinenlesbare Zwischenmodule entstehen. Der Compiler erzeugt diese ohne anschließenden Linkvorgang durch gcc -c math_add.c math_sub.c:

C-Dateien zu Objektdateien kompilieren

Das Vorhandensein der frisch generierten Binärmodule math_add.o und math_sub.o lässt sich mit ls -l *.o verifizieren:

Erzeugte Objektdateien im Verzeichnis auflisten

Statische Archive (.a) schnüren und befüllen (ar rcs)

Vor der Archivierung stellen wir mit cd /tmp/ar_demo sicher, dass wir uns im richtigen Pfad befinden:

Sicherstellen des Verzeichniskontexts /tmp/ar_demo

Nun werden die einzelnen Objektdateien zu einer monolithischen statischen Bibliothek zusammengefügt; der Aufruf ar rcs libmath.a math_add.o math_sub.o bündelt die Module und generiert zeitgleich das Symbolverzeichnis:
Hierbei ersetzt oder fügt r Einträge hinzu, c unterdrückt Warnungen beim Neuanlegen der Datei, und s erzeugt zwingend erforderliche Querverweis-Indizes für den Linker.

Archiv libmath.a aus Objektdateien mit Optionen rcs erstellen

Ein kurzer Blick auf Dateigröße und Zugriffsrechte der erzeugten Bibliothek erfolgt über ls -lh libmath.a:

Details und Dateigröße von libmath.a abfragen

Archivinhalte analysieren und Symboltabellen auslesen (ar t, nm)

Für die Inspektion des Archivs bleibt /tmp/ar_demo unser Ausgangspunkt, angesteuert per cd /tmp/ar_demo:

Wechsel in das Arbeitsverzeichnis für Archivprüfungen

Welche Module sich im Detail im Archiv verbergen, verrät der Befehl ar tv libmath.a:
Der Parameter t listet alle enthaltenen Elemente tabellarisch auf, während v ausführliche Metadaten wie Zeitstempel, Dateigrößen und Besitzerinformationen ähnlich einem Langformat-Listing einblendet.

Ausführliche Dateiliste des Archivs mit ar tv anzeigen

Damit der Linker Funktionen beim Übersetzungsprozess auflösen kann, müssen exportierte Funktionsnamen katalogisiert sein. Dies überprüft nm -s libmath.a:
Das Tool nm dechiffriert Objektsymbole; die Option -s weist es an, speziell den internen Bibliotheksindex darzustellen, womit verifiziert wird, dass Symbole wie add und sub referenzierbar sind.

Symboltabelle und Indizes mit nm -s untersuchen

Extraktion und Bereinigung von Modulen (ar x, ar d)

Sollen einzelne Komponenten aus der Bibliothek isoliert werden, empfiehlt sich ein separater Ordner. Dieser entsteht über cd /tmp/ar_demo && mkdir -p extracted:

Zielordner für extrahierte Komponenten einrichten

Um gezielt nur die Additionsfunktion zu extrahieren und das Ergebnis zu kontrollieren, wird cd extracted && ar x ../libmath.a math_add.o && ls -l ausgeführt:
Der Parameter x entpackt die spezifizierten Archivelemente direkt in das gegenwärtige Arbeitsverzeichnis, ohne das Originalarchiv zu verändern.

Objektdatei math_add.o isolieren und überprüfen

Zurück auf der Hauptebene geht es mit cd /tmp/ar_demo weiter:

Rückkehr zum Basisverzeichnis

Soll ein veraltetes oder überflüssiges Modul dauerhaft aus der Bibliothek entfernt werden, nutzt man ar d libmath.a math_sub.o:
Die Operation d löscht das angegebene Mitglied rückstandslos aus dem Container.

Modul math_sub.o aus dem Bibliotheksarchiv entfernen

Ob die Löschung erfolgreich war und ausschließlich math_add.o verblieben ist, zeigt ein kompakter Inhaltsabgleich via ar t libmath.a:

Verbliebene Module im Archiv auflisten

Praxisfallen: Veraltete Symboltabellen und ranlib-Einsatz

Für Demonstration des Indexverhaltens wechseln wir erneut mit cd /tmp/ar_demo in das Testverzeichnis:

Vorbereitung für den Test veralteter Symbolindizes

Wird ein Modul ohne Erneuerung des Index zurück in das Archiv geschoben, geschieht dies über ar r libmath.a math_sub.o:
Unterlässt man hierbei das Flag s, gerät das interne Inhaltsverzeichnis des Archivs aus dem Tritt. Für moderne Build-Pipelines und Linker bedeutet ein desynchronisierter Index oft schwer nachvollziehbare Verknüpfungsfehler (undefined reference).

Objekt ohne Aktualisierungsflag in das Archiv einfügen

Zur manuellen Reparatur oder Rekonstruktion eines fehlenden Katalogs dient ranlib libmath.a:
Dieses Hilfsprogramm scannt sämtliche Objektdateien im Archiv neu ein und schreibt den globalen Symbolindex direkt in den Archiv-Header.

Symbolindex mit ranlib neu generieren

Dass alle Funktionen wieder lückenlos auffindbar sind, bestätigt die abschließende Validierung mittels nm -s libmath.a:
Der ausgegebene Archiv-Header belegt zweifelsfrei, dass sowohl add als auch sub vom Linker wieder problemlos aufgelöst werden können.

Wiederhergestellten Index mit nm -s überprüfen

Mit diesen Kernbefehlen und dem Wissen um die Bedeutung konsistenter Symboltabellen besitzen Sie das handwerkliche Rüstzeug, um statische C/C++-Bibliotheken unter Linux effizient zu kompilieren, zu paketieren und fehlerfrei in Ihre Build-Systeme einzubinden.