Примечание перед прочтением: Показанный здесь сценарий оболочки, безусловно, небезопасен для использования и хорошо протестирован. Используйте на свой страх и риск!
Я написал скрипт bash для выполнения этой задачи. Предположим, ваша библиотека - 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
где libwh независимо от того, откуда вы хотите включить символы. Тем не менее, я думаю, что безопаснее всего сначала скопировать все в отдельный каталог. Я бы не стал доверять своему сценарию (однако, он сработал для меня; я мог бы включить с этим libgsl.a в мою библиотеку чисел и пропустить этот переключатель компилятора -lgsl).