Зауважте, перш ніж прочитати решту: скрипт оболонки, показаний тут, звичайно, не є безпечним у використанні та добре перевірений. Використовуйте на свій страх і ризик!
Я написав баш сценарій для виконання цього завдання. Припустимо, у вашій бібліотеці lib1, і вам потрібно включити деякі символи - lib2. Тепер сценарій працює в циклі, де він спочатку перевіряє, які невизначені символи lib1 можуть бути знайдені в lib2. Потім він витягує відповідні об’єктні файли з lib2 ar
, перейменовує їх трохи і вводить їх у lib1. Тепер може бути більше відсутніх символів, тому що матеріал, який ви включили з lib2, потребує інших матеріалів від lib2, які ми ще не включили, тому цикл потрібно запустити знову. Якщо після деяких пропусків циклу більше не буде змін, тобто жодних об’єктних файлів з lib2, доданих до lib1, цикл може припинитися.
Зауважте, що включені символи все ще повідомляються як невизначені nm
, тому я відстежую файли об'єктів, які самі були додані до lib1, щоб визначити, чи можна зупинити цикл.
#! /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
Я назвав цей сценарій libcomp
, тож ви можете його назвати, наприклад, з
./libcomp libmylib.a libwhatever.a
де libw незалежно від того, звідки ви хочете включити символи. Однак я думаю, що найбезпечніше спочатку скопіювати все в окремий каталог. Я б не довіряв своєму сценарію так сильно (однак, він працював на мене; я міг би включити libgsl.a в свою бібліотеку чисел із цим і залишити цей перемикач компілятора -lgsl).