webentwicklung-frage-antwort-db.com.de

Verknüpfen von statischen Bibliotheken mit anderen statischen Bibliotheken

Ich habe ein kleines Stück Code, der von vielen statischen Bibliotheken abhängt (a_1-a_n). Ich möchte diesen Code in eine statische Bibliothek packen und anderen zur Verfügung stellen.

Meine statische Bibliothek, nennen wir sie X, lässt sich gut kompilieren.

Ich habe ein einfaches Beispielprogramm erstellt, das eine Funktion aus X verwendet, aber wenn ich versuche, sie mit X zu verknüpfen, erhalte ich viele Fehler bezüglich fehlender Symbole aus den Bibliotheken a_1 - a_n.

Gibt es eine Möglichkeit, eine neue statische Bibliothek Y zu erstellen, die X und alle von X benötigten Funktionen enthält (ausgewählte Bits von a_1 - a_n), sodass ich nur Y verteilen kann, damit Benutzer ihre Programme verknüpfen können?


AKTUALISIEREN:

Ich habe mir angesehen, wie man einfach alles mit ar ablädt und eine Mega-Lib erstellt, die jedoch eine Menge nicht benötigter Symbole enthält ( Alle .o-Dateien haben eine Größe von ca. 700 MB. Eine statisch verknüpfte ausführbare Datei hat jedoch eine Größe von 7 MB. Gibt es eine gute Möglichkeit, nur das einzubeziehen, was tatsächlich benötigt wird?


Dies ist eng verwandt mit Wie werden mehrere C/C++ - Bibliotheken zu einer kombiniert? .

121
Jason Sundram

Statische Bibliotheken sind nicht mit anderen statischen Bibliotheken verknüpft. Die einzige Möglichkeit, dies zu tun, besteht darin, Ihr Bibliothekar-/Archivierungstool (zum Beispiel ar unter Linux) zu verwenden, um eine einzelne neue statische Bibliothek durch Verketten der mehreren Bibliotheken zu erstellen.

Bearbeiten: Als Reaktion auf Ihr Update kann ich nur die erforderlichen Symbole auswählen, indem ich die Bibliothek manuell aus der Teilmenge der .o-Dateien erstelle, in denen sie enthalten sind. Dies ist schwierig, zeitaufwendig und fehleranfällig. Mir sind keine Tools bekannt, die mir dabei helfen (um nicht zu sagen, dass sie nicht existieren), aber es wäre ein ziemlich interessantes Projekt, eines zu produzieren.

63
anon

Wenn Sie Visual Studio verwenden, können Sie dies tun.

Mit dem in Visual Studio enthaltenen Tool zum Erstellen von Bibliotheken können Sie Bibliotheken in der Befehlszeile zusammenfügen. Ich kenne jedoch keine Möglichkeit, dies im visuellen Editor zu tun.

lib.exe /OUT:compositelib.lib  lib1.lib lib2.lib
42
John Knoeller

Unter Linux oder MingW mit GNU Toolchain:

ar -M <<EOM
    CREATE libab.a
    ADDLIB liba.a
    ADDLIB libb.a
    SAVE
    END
EOM
ranlib libab.a

Wenn Sie liba.a Und libb.a Nicht löschen, können Sie ein "dünnes Archiv" erstellen:

ar crsT libab.a liba.a libb.a

Unter Windows mit MSVC-Toolchain:

lib.exe /OUT:libab.lib liba.lib libb.lib
19
Star Brilliant

Eine statische Bibliothek ist nur ein Archiv von .o Objektdateien. Extrahieren Sie sie mit ar (Unix vorausgesetzt) ​​und packen Sie sie zurück in eine große Bibliothek.

8

Alternativ zu Link Library Dependencies In den Projekteigenschaften gibt es eine andere Möglichkeit, Bibliotheken in Visual Studio zu verknüpfen.

  1. Öffnen Sie das Projekt der Bibliothek (X), die Sie mit anderen Bibliotheken kombinieren möchten.
  2. Fügen Sie die anderen Bibliotheken hinzu, die Sie mit X kombinieren möchten (Rechtsklick, Add Existing Item...).
  3. Gehen Sie zu ihren Eigenschaften und stellen Sie sicher, dass Item Type ist Library

Dies schließt die anderen Bibliotheken in X ein, als ob Sie ausgeführt würden

lib /out:X.lib X.lib other1.lib other2.lib
6
evpo

Beachten Sie, bevor Sie den Rest lesen: Das hier gezeigte Shell-Skript ist mit Sicherheit nicht sicher und gut getestet. Benutzung auf eigene Gefahr!

Ich habe ein Bash-Skript geschrieben, um diese Aufgabe zu erfüllen. Angenommen, Ihre Bibliothek ist lib1 und die Bibliothek, aus der Sie einige Symbole einfügen müssen, ist lib2. Das Skript läuft nun in einer Schleife und prüft zunächst, welche undefinierten Symbole aus lib1 in lib2 zu finden sind. Anschließend werden die entsprechenden Objektdateien mit ar aus lib2 extrahiert, ein wenig umbenannt und in lib1 abgelegt. Jetzt fehlen möglicherweise mehr Symbole, da das von Ihnen in lib2 enthaltene Material andere Materialien von lib2 benötigt, die wir noch nicht enthalten haben, sodass die Schleife erneut ausgeführt werden muss. Wenn nach einigen Durchläufen der Schleife keine Änderungen mehr vorgenommen werden, d. H. Keine zu lib1 hinzugefügten Objektdateien aus lib2, kann die Schleife angehalten werden.

Beachten Sie, dass die eingeschlossenen Symbole von nm immer noch als undefiniert gemeldet werden. Daher verfolge ich die Objektdateien, die zu lib1 hinzugefügt wurden, selbst, um festzustellen, ob die Schleife gestoppt werden kann.

#! /bin/bash

lib1="$1"
lib2="$2"

if [ ! -e $lib1.backup ]; then
    echo backing up
    cp $lib1 $lib1.backup
fi

remove_later=""

new_tmp_file() {
    file=$(mktemp)
    remove_later="$remove_later $file"
    eval $1=$file
}
remove_tmp_files() {
    rm $remove_later
}
trap remove_tmp_files EXIT

find_symbols() {
    nm $1 $2 | cut -c20- | sort | uniq 
}

new_tmp_file lib2symbols
new_tmp_file currsymbols

nm $lib2 -s --defined-only > $lib2symbols

prefix="xyz_import_"
pass=0
while true; do
    ((pass++))
    echo "Starting pass #$pass"
    curr=$lib1
    find_symbols $curr "--undefined-only" > $currsymbols
    changed=0
    for sym in $(cat $currsymbols); do
        for obj in $(egrep "^$sym in .*\.o" $lib2symbols | cut -d" " -f3); do
            echo "  Found $sym in $obj."
            if [ -e "$prefix$obj" ]; then continue; fi
            echo "    -> Adding $obj to $lib1"
            ar x $lib2 $obj
            mv $obj "$prefix$obj"
            ar -r -s $lib1 "$prefix$obj"
            remove_later="$remove_later $prefix$obj"
            ((changed=changed+1))
        done
    done
    echo "Found $changed changes in pass #$pass"

    if [[ $changed == 0 ]]; then break; fi
done

Ich habe dieses Skript libcomp genannt, so dass Sie es dann aufrufen können, z. mit

./libcomp libmylib.a libwhatever.a

woher willst du auch immer Symbole einbinden? Ich denke jedoch, dass es am sichersten ist, zuerst alles in ein separates Verzeichnis zu kopieren. Ich würde meinem Skript nicht so sehr vertrauen (es funktionierte jedoch für mich; ich könnte libgsl.a damit in meine Zahlenbibliothek aufnehmen und diesen -lgsl-Compiler-Schalter weglassen).

3
Elmar Zander