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