Remarque avant de lire la suite: le script shell montré ici n'est certainement pas sûr à utiliser et bien testé. À utiliser à vos risques et périls!
J'ai écrit un script bash pour accomplir cette tâche. Supposons que votre bibliothèque soit lib1 et que celle dont vous ayez besoin pour inclure certains symboles soit lib2. Le script s'exécute maintenant dans une boucle, où il vérifie d'abord quels symboles non définis de lib1 peuvent être trouvés dans lib2. Il extrait ensuite les fichiers objets correspondants de la lib2 avec ar
, les renomme un peu et les met dans lib1. Maintenant, il peut y avoir plus de symboles manquants, parce que les éléments que vous avez inclus de lib2 ont besoin d'autres éléments de lib2, que nous n'avons pas encore inclus, donc la boucle doit être exécutée à nouveau. Si après quelques passages de la boucle il n'y a plus de changements, c'est-à-dire qu'aucun fichier objet de la lib2 n'a été ajouté à la lib1, la boucle peut s'arrêter.
Notez que les symboles inclus sont toujours signalés comme non définis par nm
, donc je garde une trace des fichiers objets, qui ont été ajoutés à lib1, eux-mêmes, afin de déterminer si la boucle peut être arrêtée.
#! /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
J'ai nommé ce script libcomp
, donc vous pouvez l'appeler alors par exemple avec
./libcomp libmylib.a libwhatever.a
où libwthing est d'où vous voulez inclure des symboles. Cependant, je pense qu'il est plus sûr de tout copier d'abord dans un répertoire séparé. Je ne ferais pas tellement confiance à mon script (cependant, cela a fonctionné pour moi; je pourrais inclure libgsl.a dans ma bibliothèque numérique avec cela et laisser de côté ce commutateur de compilateur -lgsl).