Uwaga, zanim przeczytasz resztę: pokazany tutaj skrypt powłoki z pewnością nie jest bezpieczny w użyciu i dobrze przetestowany. Używaj na własne ryzyko!
Napisałem skrypt basha, aby wykonać to zadanie. Załóżmy, że twoja biblioteka to lib1, a ta, z której musisz dołączyć niektóre symbole, to lib2. Skrypt działa teraz w pętli, gdzie najpierw sprawdza, które niezdefiniowane symbole z lib1 można znaleźć w lib2. Następnie wyodrębnia odpowiednie pliki obiektowe z lib2 za pomocą ar
, zmienia nieco ich nazwy i umieszcza je w lib1. Teraz może być więcej brakujących symboli, ponieważ rzeczy, które dołączyłeś z lib2, wymagają innych rzeczy z lib2, których jeszcze nie uwzględniliśmy, więc pętla musi zostać uruchomiona ponownie. Jeśli po kilku przebiegach pętli nie ma już żadnych zmian, tj. Żadne pliki obiektowe z lib2 nie zostały dodane do lib1, pętla może się zatrzymać.
Zauważ, że dołączone symbole są nadal zgłaszane jako niezdefiniowane przez nm
, więc śledzę same pliki obiektowe, które zostały dodane do lib1, aby określić, czy pętla może zostać zatrzymana.
#! /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
Nazwałem ten skrypt libcomp
, więc możesz go wtedy nazwać np
./libcomp libmylib.a libwhatever.a
gdzie libcokolwiek jest skąd chcesz dołączyć symbole. Uważam jednak, że najbezpieczniej jest najpierw skopiować wszystko do oddzielnego katalogu. Nie ufałbym tak bardzo mojemu skryptowi (jednak zadziałał dla mnie; mógłbym dołączyć libgsl.a do mojej biblioteki numerycznej i pominąć ten przełącznik kompilatora -lgsl).