Verknüpfen von statischen Bibliotheken zu anderen statischen Bibliotheken
Frage
Ich habe ein kleines Stück Code, das auf vielen statischen Bibliotheken abhängt (a 1-a_n). Ich mag, dass Code in einer statischen Bibliothek verpacken und zu anderen Menschen zur Verfügung zu stellen.
Meine statische Bibliothek, nennen wir es X kompiliert in Ordnung.
Ich habe ein einfaches Beispielprogramm erstellt, das eine Funktion von X verwendet, aber wenn ich versuche, es zu X zu verbinden, erhalte ich über viele Fehler Symbole aus Bibliotheken A_1 fehlt -. A_n
Gibt es eine Möglichkeit, dass ich eine neue statische Bibliothek erstellen kann, Y, die X und alle Funktionen von X (ausgewählten Bits von a 1 - a_n) benötigt enthält, so dass ich nur Y verteilen kann für Menschen, ihre Programme verlinken auf ?
UPDATE:
Ich habe bei nur Dumping alles sah mit ar und machen ein Mega-lib jedoch, dass endet eine Menge von Symbolen enthält, die nicht benötigt werden (alle die .o-Dateien sind über 700 MB jedoch ein statisch gelinkte ausführbar sind 7 MB). Gibt es eine schöne Möglichkeit, nur zu schließen, was notwendig ist eigentlich?
Das sieht eng verwandt mit Wie mehrere C / C ++ Bibliotheken in einem? kombinieren.
Lösung
Statische Bibliotheken verknüpfe nicht mit anderen statischen Bibliotheken. Der einzige Weg, dies zu tun ist Ihren Bibliothekar / Archivierungs-Tool verwenden (zum Beispiel ar auf Linux) eine einzige neue statische Bibliothek zu erstellen, indem die mehrere Bibliotheken verketten.
Edit: Als Reaktion auf das Update, der einzige Weg, ich kenne nur die Symbole auszuwählen, die erforderlich sind, um die Bibliothek manuell aus der Teilmenge der .o-Dateien zu erstellen, die sie enthalten. Dies ist schwierig, zeitaufwendig und fehleranfällig. Ich bin mir nicht bewusst, werkzeuglos zu helfen tut dies (nicht zu sagen, dass sie nicht existieren), aber es wäre durchaus ein interessantes Projekt zu produzieren machen.
Andere Tipps
Wenn Sie Visual Studio verwenden, dann ja, Sie können dies tun.
Die Bibliothek Builder-Tool, das kommt mit Visual Studio ermöglicht es Ihnen, Bibliotheken zusammen auf der Kommandozeile zu verbinden. Ich weiß nicht von irgendeiner Weise obwohl dies im visuellen Editor zu tun.
lib.exe /OUT:compositelib.lib lib1.lib lib2.lib
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 nicht löschen liba.a
und libb.a
, können Sie einen „thin-Archiv“ machen:
ar crsT libab.a liba.a libb.a
Unter Windows mit MSVC Toolchain:
lib.exe /OUT:libab.lib liba.lib libb.lib
Eine statische Bibliothek ist nur ein Archiv von .o
Objektdateien. Extrahieren Sie sie mit ar
(vorausgesetzt, Unix) und packen sie wieder in eine große Bibliothek.
Als Alternative zu Link Library Dependencies
in Projekteigenschaften gibt es eine andere Art und Weise zu Link Libraries in Visual Studio.
- Öffnen Sie das Projekt der Bibliothek (X), dass Sie mit anderen Bibliotheken kombiniert werden sollen.
- Fügen Sie die anderen Bibliotheken, die Sie mit X kombiniert werden sollen (Rechtsklick,
Add Existing Item...
). - Gehen Sie auf ihre Eigenschaften und stellen Sie sicher,
Item Type
istLibrary
Damit werden die anderen Bibliotheken in X enthalten, als ob Sie lief
lib /out:X.lib X.lib other1.lib other2.lib
Beachten Sie, bevor Sie lesen den Rest: Das Shell-Skript hier gezeigt ist sicherlich nicht sicher zu bedienen und gut getestet. Benutzung auf eigene Gefahr!
Ich schrieb einen Bash-Skript, diese Aufgabe zu erfüllen. Angenommen, Ihre Bibliothek ist lib1 und die, die Sie brauchen, um einige Symbole sind von lib2 ist. Das Skript läuft nun in einer Schleife, wo es zuerst überprüft, welche Symbole von lib1 undefined in lib2 finden. Es extrahiert dann die entsprechenden Objektdateien aus lib2 mit ar
, benennt sie ein wenig, und setzt sie in lib1. Nun kann es mehr Symbole fehlen, weil das Material, das Sie von lib2 enthalten andere Sachen aus lib2 braucht, die wir noch nicht aufgenommen haben, so dass die Schleife erneut ausgeführt werden muss. Wenn nach einigen Durchläufen der Schleife mehr da keine Änderungen sind, das heißt keine Objektdateien von lib2 zu lib1 hinzugefügt, kann die Schleife stoppen.
Beachten Sie, dass die darin enthaltenen Symbole weiterhin als nicht definiert durch nm
berichtet, so dass ich den Überblick über die Objektdateien zu halten bin, das zu lib1 hinzugefügt wurde, selbst, um zu bestimmen, 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 das Skript libcomp
benannt, so dass man es so nennen kann z.B. mit
./libcomp libmylib.a libwhatever.a
wo libwhatever ist, wo Sie aufnehmen möchten Symbole aus. Aber ich denke, es ist am sichersten zuerst alles in ein separates Verzeichnis zu kopieren. Ich würde meinem Skript nicht so viel Vertrauen (aber es funktionierte für mich, ich libgsl.a in meine Numerik-Bibliothek mit, dass beinhalten könnte und auslassen, dass -lgsl Compiler-Schalter).