Tenga en cuenta antes de leer el resto: el script de shell que se muestra aquí ciertamente no es seguro de usar y está bien probado. ¡Úselo bajo su propio riesgo!
Escribí un script bash para lograr esa tarea. Suponga que su biblioteca es lib1 y de la que necesita incluir algunos símbolos es lib2. El script ahora se ejecuta en un bucle, donde primero verifica qué símbolos indefinidos de lib1 se pueden encontrar en lib2. Luego extrae los archivos de objetos correspondientes de lib2 con ar
, los renombra un poco y los coloca en lib1. Ahora puede haber más símbolos faltantes, porque las cosas que incluiste de lib2 necesitan otras cosas de lib2, que aún no hemos incluido, por lo que el ciclo debe ejecutarse nuevamente. Si después de algunas pasadas del bucle ya no hay cambios, es decir, no se agregaron archivos de objetos de lib2 a lib1, el bucle puede detenerse.
Tenga en cuenta que los símbolos incluidos todavía se informan como indefinidos nm
, por lo que estoy haciendo un seguimiento de los archivos de objetos, que se agregaron a lib1, ellos mismos, para determinar si el ciclo se puede detener.
#! /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
Llamé a ese script libcomp
, así que puedes llamarlo entonces, por ejemplo
./libcomp libmylib.a libwhatever.a
donde libwhatever es donde desea incluir símbolos. Sin embargo, creo que es más seguro copiar primero todo en un directorio separado. No confiaría tanto en mi script (sin embargo, funcionó para mí; podría incluir libgsl.a en mi biblioteca de números con eso y omitir ese cambio de compilador -lgsl).