La vinculación de las bibliotecas estáticas a otras bibliotecas estáticas
Pregunta
Tengo una pequeña pieza de código que depende de muchas bibliotecas estáticas (a_1-a_n). Me gustaría empaquetar ese código en una biblioteca estática y ponerlo a disposición de otras personas.
Mi biblioteca estática, permite llamarlo X, compila bien.
He creado un programa de ejemplo simple que utiliza una función de X, pero cuando intento de vincularlo a X, consigo muchos errores por perder símbolos de las bibliotecas a_1 -. A_n
¿Hay una manera que puedo crear una nueva biblioteca estática, Y que contiene X y toda la funcionalidad necesaria por X (seleccionado trozos de a_1 - a_n), de modo que pueda distribuir acaba Y para las personas a vincular sus programas de ?
ACTUALIZACIÓN:
He mirado simplemente vertido todo con ar y haciendo un mega-lib, sin embargo, que termina incluyendo una gran cantidad de símbolos que no son necesarios (todos los archivos .o son alrededor de 700 MB, sin embargo, un ejecutable enlazado estáticamente es 7 MB). ¿Hay una buena manera de incluir sólo lo que realmente se necesita?
Esto se ve muy relacionada con Cómo combinar varias bibliotecas de C / C ++ en una sola? .
Solución
Las librerías estáticas no se vinculan con otras bibliotecas estáticas. La única manera de hacer esto es usar su / bibliotecario archivador herramienta (por ejemplo, ar en Linux) para crear una sola biblioteca estática nueva mediante la concatenación de las múltiples bibliotecas.
Editar En respuesta a su actualización, la única forma que conozco para seleccionar sólo los símbolos que se requieren es crear manualmente la biblioteca del subconjunto de los archivos .o que los contienen. Esto es difícil, lento y propenso a errores. No estoy al tanto de ninguna herramienta para ayudar a hacer esto (por no decir que no existen), pero sería hacer un proyecto bastante interesante para un solo producto.
Otros consejos
Si está utilizando Visual Studio entonces sí, se puede hacer esto.
La herramienta de creación de la biblioteca que viene con Visual Studio le permite unirse a las bibliotecas juntos en la línea de comandos. No sé de ninguna manera de hacer esto en el editor visual sin embargo.
lib.exe /OUT:compositelib.lib lib1.lib lib2.lib
En Linux o MingW, con herramientas GNU:
ar -M <<EOM
CREATE libab.a
ADDLIB liba.a
ADDLIB libb.a
SAVE
END
EOM
ranlib libab.a
Por si lo hace liba.a
no borrar y libb.a
, se puede hacer un "archivo fina":
ar crsT libab.a liba.a libb.a
En Windows, la cadena de herramientas MSVC:
lib.exe /OUT:libab.lib liba.lib libb.lib
Una biblioteca estática es simplemente un archivo de los archivos objeto .o
. Extraerlos con ar
(suponiendo Unix) y el paquete de nuevo en una biblioteca grande.
Como alternativa a Link Library Dependencies
en las propiedades del proyecto hay otra forma de librerías de enlace en Visual Studio.
- Abra el proyecto de la biblioteca (X) que desea combinar con otras bibliotecas.
- Añadir el resto de bibliotecas que desea que se combina con X (clic derecho,
Add Existing Item...
). - Vaya a sus propiedades y asegúrese
Item Type
esLibrary
Esto incluirá las otras bibliotecas de X como si ejecutó
lib /out:X.lib X.lib other1.lib other2.lib
Nota Antes de leer el resto: El script se muestra aquí no es ciertamente seguro de usar y bien probado. Uso en su propio riesgo!
Me escribió un script bash para realizar esa tarea. Suponga que su biblioteca es LIB1 y el que usted necesita incluir algunos símbolos de LIB2 es. La secuencia de comandos ahora se ejecuta en un bucle, donde primero comprueba que undefined símbolos de lib1 se pueden encontrar en lib2. A continuación, extrae los archivos de objetos correspondientes a LIB2 con ar
, les cambia el nombre un poco, y los pone en LIB1. Ahora puede haber más símbolos que faltan, porque las cosas que abarcaba desde LIB2 necesita otras cosas de LIB2, que no hemos incluido, sin embargo, por lo que el bucle tiene que ejecutar de nuevo. Si después de algunas pasadas del bucle no hay cambios más, es decir, no hay archivos objeto desde lib2 añadido a lib1, el bucle puede parar.
Tenga en cuenta, que los símbolos incluidos todavía son reportados como no definidos por nm
, así que estoy un seguimiento de los archivos de objetos, que se agregaron a LIB1, ellos mismos, con el fin de determinar si el bucle 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
Me nombrado libcomp
que la escritura, por lo que se le puede llamar a continuación, por ejemplo, con
./libcomp libmylib.a libwhatever.a
donde libwhatever es la que desea incluir símbolos de. Sin embargo, creo que es más seguro para copiar todo en un directorio independiente en primer lugar. No confiaría en mi guión tanto (sin embargo, que trabajó para mí, pude incluir libgsl.a en mi biblioteca numéricos con eso y dejar de lado que el modificador de compilador -lgsl).