Observe antes de ler o restante: O script de shell mostrado aqui certamente não é seguro e bem testado. Use por sua conta e risco!
Eu escrevi um script bash para realizar essa tarefa. Suponha que sua biblioteca seja lib1 e que você precise incluir alguns símbolos é lib2. O script agora roda em um loop, onde primeiro verifica quais símbolos indefinidos da lib1 podem ser encontrados na lib2. Em seguida, extrai os arquivos de objeto correspondentes da lib2 com ar
, renomeia-os um pouco e os coloca na lib1. Agora pode haver mais símbolos ausentes, porque as coisas que você incluiu na lib2 precisam de outras coisas da lib2, que ainda não incluímos, portanto o loop precisa ser executado novamente. Se após algumas passagens do loop não houver mais alterações, ou seja, nenhum arquivo de objeto da lib2 adicionado à lib1, o loop poderá parar.
Observe que os símbolos incluídos ainda são relatados como indefinidos nm
, por isso estou acompanhando os arquivos de objetos que foram adicionados à lib1, eles mesmos, para determinar se o loop pode ser interrompido.
#! /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
Eu nomeei esse script libcomp
, para que você possa chamá-lo, por exemplo, com
./libcomp libmylib.a libwhatever.a
onde libwhatever é de onde você deseja incluir símbolos. No entanto, acho mais seguro copiar tudo para um diretório separado primeiro. Eu não confiava tanto no meu script (no entanto, funcionou para mim; eu poderia incluir a libgsl.a na minha biblioteca de números com isso e deixar de fora essa opção do compilador -lgsl).