Nota prima di leggere il resto: lo script di shell mostrato qui non è certamente sicuro da usare e ben testato. Utilizzare a proprio rischio!
Ho scritto uno script bash per compiere quel compito. Supponiamo che la tua libreria sia lib1 e quella da cui devi includere alcuni simboli è lib2. Lo script ora viene eseguito in un ciclo, dove controlla innanzitutto quali simboli indefiniti di lib1 possono essere trovati in lib2. Quindi estrae i file oggetto corrispondenti da lib2 con ar
, li rinomina un po 'e li mette in lib1. Ora potrebbero esserci più simboli mancanti, perché le cose che hai incluso da lib2 hanno bisogno di altre cose da lib2, che non abbiamo ancora incluso, quindi il ciclo deve essere eseguito di nuovo. Se dopo alcuni passaggi del loop non ci sono più modifiche, ovvero nessun file oggetto da lib2 aggiunto a lib1, il loop può fermarsi.
Nota che i simboli inclusi sono ancora riportati come non definiti da nm
, quindi tengo traccia dei file oggetto, che sono stati aggiunti a lib1, stessi, per determinare se il loop può essere fermato.
#! /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
Ho chiamato questo script libcomp
, quindi puoi chiamarlo, ad esempio con
./libcomp libmylib.a libwhatever.a
dove libwhatever è dove vuoi includere simboli. Tuttavia, penso che sia più sicuro copiare prima tutto in una directory separata. Non mi fiderei tanto della mia sceneggiatura (tuttavia, ha funzionato per me; potrei includere libgsl.a nella mia libreria numerica con quella e tralasciare quel parametro del compilatore -lgsl).