Lier les bibliothèques statiques vers d'autres bibliothèques statiques
Question
J'ai un petit morceau de code qui dépend de nombreuses bibliothèques statiques (A_1-a_n). Je voudrais empaqueter ce code dans une bibliothèque statique et la rendre accessible à d'autres personnes.
Ma bibliothèque statique, permet de l'appeler X, compile très bien.
J'ai créé un programme simple exemple qui utilise une fonction de X, mais lorsque je tente de le lier à X, je reçois beaucoup d'erreurs sur les symboles manquants dans les bibliothèques A_1 - a_n
.Est-il possible que je peux créer une nouvelle bibliothèque statique, Y qui contient X et toutes les fonctionnalités requises par X (bits sélectionnés de A_1 - a_n), afin que je puisse distribuer simplement Y pour les personnes de relier leurs programmes ?
Mise à jour:
J'ai regardé le dumping juste tout avec ar et faire cependant, un méga-lib, qui finit par y compris un grand nombre de symboles qui ne sont pas nécessaires (tous les fichiers .o sont environ 700 MB, cependant, un exécutable lié statiquement est de 7 Mo). Y at-il un bon moyen d'inclure uniquement ce qui est réellement nécessaire?
Cela semble étroitement lié à Comment combiner plusieurs C / C ++ bibliothèques en un? .
La solution
Les bibliothèques statiques ne lient pas avec d'autres bibliothèques statiques. La seule façon de le faire est d'utiliser votre bibliothécaire / outil d'archivage (par exemple ar sous Linux) pour créer une seule nouvelle bibliothèque statique par les concaténer plusieurs bibliothèques.
Modifier En réponse à votre mise à jour, la seule façon que je connaisse de ne sélectionner que les symboles qui sont nécessaires est de créer manuellement la bibliothèque à partir du sous-ensemble des fichiers .o qui les contiennent. Cela est difficile, beaucoup de temps et d'erreurs. Je ne suis pas au courant des outils pour aider à faire cela (ne veut pas dire qu'ils n'existent pas), mais il serait tout à fait un projet intéressant pour produire un.
Autres conseils
Si vous utilisez Visual Studio puis oui, vous pouvez le faire.
L'outil de création de bibliothèque qui est livré avec Visual Studio vous permet de joindre les bibliothèques ainsi que sur la ligne de commande. Je ne connais aucune façon de le faire dans l'éditeur visuel bien.
lib.exe /OUT:compositelib.lib lib1.lib lib2.lib
Sur Linux ou MinGW, avec GNU toolchain:
ar -M <<EOM
CREATE libab.a
ADDLIB liba.a
ADDLIB libb.a
SAVE
END
EOM
ranlib libab.a
Si vous ne supprimez pas liba.a
et libb.a
, vous pouvez faire une « mince archive »:
ar crsT libab.a liba.a libb.a
Sous Windows, avec MSVC toolchain:
lib.exe /OUT:libab.lib liba.lib libb.lib
Une bibliothèque statique est juste une archive de fichiers objet .o
. les extraire avec ar
(en supposant Unix) et les emballer de nouveau dans une grande bibliothèque.
Alternativement à Link Library Dependencies
dans les propriétés du projet, il est une autre façon de relier les bibliothèques dans Visual Studio.
- Ouvrez le projet de la bibliothèque (X) que vous voulez être combiné avec d'autres bibliothèques.
- Ajoutez les autres bibliothèques que vous voulez avec X (regroupé, clic droit,
Add Existing Item...
). - Accédez à leurs propriétés et faire
Item Type
vous estLibrary
Cela inclut les autres bibliothèques dans X comme si vous exécutiez
lib /out:X.lib X.lib other1.lib other2.lib
Note avant de lire le reste: Le script shell montré ici est certainement pas sûr à utiliser et bien testé. A utiliser à vos risques et périls!
J'ai écrit un script bash pour accomplir cette tâche. Supposons que votre bibliothèque est lib1 et celui que vous avez besoin d'inclure des symboles de lib2 est. Le script fonctionne maintenant dans une boucle, où il vérifie d'abord les symboles non définis de lib1 se trouvent dans lib2. Il extrait ensuite les fichiers objets correspondants de lib2 avec ar
, les renomme un peu, et les met en lib1. Maintenant, il peut y avoir des symboles plus manquants, parce que les choses que vous avez inclus de lib2 a besoin d'autres choses de lib2, que nous n'avons pas encore inclus, de sorte que la boucle doit fonctionner à nouveau. Si après quelques passages de la boucle, il n'y a pas de changements plus, à savoir aucun fichier objet de lib2 ajoutés à LIB1, la boucle peut arrêter.
Notez que les symboles inclus sont toujours déclarés comme non défini par nm
, donc je garder la trace des fichiers objets, qui ont été ajoutés à lib1, eux-mêmes, afin de déterminer si la boucle peut être arrêté.
#! /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
Je nommé que libcomp
script, vous pouvez donc l'appeler alors par exemple avec
./libcomp libmylib.a libwhatever.a
où libwhatever est l'endroit où vous voulez inclure des symboles de. Cependant, je pense qu'il est plus sûr de copier tout dans un répertoire distinct en premier. Je ne voudrais pas faire confiance à mon script tellement (cependant, il a travaillé pour moi, je pourrais inclure libgsl.a dans ma bibliothèque numerics avec cela et laisser que le commutateur de compilation -lgsl).