El problema, según tengo entendido, es el siguiente. Tiene varias bibliotecas, algunas estáticas, otras dinámicas y otras tanto estáticas como dinámicas. El comportamiento predeterminado de gcc es vincular "principalmente dinámico". Es decir, gcc se vincula a bibliotecas dinámicas cuando es posible, pero por lo demás recurre a bibliotecas estáticas. Cuando usa la opción -static para gcc, el comportamiento es vincular solo bibliotecas estáticas y salir con un error si no se puede encontrar una biblioteca estática, incluso si hay una biblioteca dinámica adecuada.
Otra opción, que en varias ocasiones deseé que tuviera gcc , es lo que llamo -mostly-static y es esencialmente lo opuesto a -dynamic (el predeterminado). -mostly-static preferiría, si existiera, vincularse con bibliotecas estáticas, pero recurriría a bibliotecas dinámicas.
Esta opción no existe pero se puede emular con el siguiente algoritmo:
Construyendo la línea de comando del enlace sin incluir -static .
Repita las opciones de enlace dinámico.
Acumular rutas de biblioteca, es decir, aquellas opciones de la forma -L <lib_dir> en una variable <lib_path>
Para cada opción de enlace dinámico, es decir, aquellos de la forma -l <lib_name> , ejecute el comando gcc <lib_path> -print-file-name = lib <lib_name> .ay capture la salida.
Si el comando imprime algo diferente a lo que pasó, será la ruta completa a la biblioteca estática. Reemplace la opción de biblioteca dinámica con la ruta completa a la biblioteca estática.
Enjuague y repita hasta que haya procesado toda la línea de comando del enlace. Opcionalmente, el script también puede tomar una lista de nombres de bibliotecas para excluir de los enlaces estáticos.
El siguiente script bash parece funcionar:
#!/bin/bash
if [ $# -eq 0 ]; then
echo "Usage: $0 [--exclude <lib_name>]. . . <link_command>"
fi
exclude=()
lib_path=()
while [ $# -ne 0 ]; do
case "$1" in
-L*)
if [ "$1" == -L ]; then
shift
LPATH="-L$1"
else
LPATH="$1"
fi
lib_path+=("$LPATH")
echo -n "\"$LPATH\" "
;;
-l*)
NAME="$(echo $1 | sed 's/-l\(.*\)/\1/')"
if echo "${exclude[@]}" | grep " $NAME " >/dev/null; then
echo -n "$1 "
else
LIB="$(gcc $lib_path -print-file-name=lib"$NAME".a)"
if [ "$LIB" == lib"$NAME".a ]; then
echo -n "$1 "
else
echo -n "\"$LIB\" "
fi
fi
;;
--exclude)
shift
exclude+=(" $1 ")
;;
*) echo -n "$1 "
esac
shift
done
echo
Por ejemplo:
mostlyStatic gcc -o test test.c -ldl -lpthread
en mi sistema devuelve:
gcc -o test test.c "/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../x86_64-linux-gnu/libdl.a" "/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../x86_64-linux-gnu/libpthread.a"
o con una exclusión:
mostlyStatic --exclude dl gcc -o test test.c -ldl -lpthread
Entonces obtengo:
gcc -o test test.c -ldl "/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../x86_64-linux-gnu/libpthread.a"