Le problème tel que je le comprends est le suivant. Vous avez plusieurs bibliothèques, certaines statiques, d'autres dynamiques et d'autres encore à la fois statiques et dynamiques. gcc Le comportement par défaut du site est d'établir des liens "principalement dynamiques". C'est-à-dire, gcc établit des liens avec les bibliothèques dynamiques lorsque cela est possible, mais se rabat sinon sur les bibliothèques statiques. Lorsque vous utilisez l'option -statique option pour gcc le comportement est de lier uniquement les bibliothèques statiques et de sortir avec une erreur si aucune bibliothèque statique ne peut être trouvée, même s'il existe une bibliothèque dynamique appropriée.
Une autre option, que j'ai souhaitée à plusieurs reprises. gcc avait, est ce que j'appelle -surtout statique et est essentiellement l'opposé de -dynamique (par défaut). -surtout statique préférerait, s'il existait, lier contre les bibliothèques statiques mais se rabattrait sur les bibliothèques dynamiques.
Cette option n'existe pas mais elle peut être émulée avec l'algorithme suivant :
-
Construire la ligne de commande link sans inclure -statique .
-
Itérer sur les options de liens dynamiques.
-
Accumuler les chemins de la bibliothèque, c'est-à-dire les options de la forme -L<lib_dir> dans une variable <chemin_lib>
-
Pour chaque option de lien dynamique, c'est-à-dire celles de la forme -l<nom_lib> exécutez la commande gcc <chemin_lib> -print-file-name=lib<nom_lib>.a et capturer la sortie.
-
Si la commande imprime quelque chose d'autre que ce que vous avez passé, ce sera le chemin complet de la bibliothèque statique. Remplacez l'option dynamic library par le chemin complet de la bibliothèque statique.
Rincez et répétez jusqu'à ce que vous ayez traité la totalité de la ligne de commande de liaison. Optionnellement, le script peut aussi prendre une liste de noms de bibliothèques à exclure de la liaison statique.
Le bash script suivant semble faire l'affaire :
#!/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
Par exemple :
mostlyStatic gcc -o test test.c -ldl -lpthread
sur les retours de mon système :
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"
ou avec une exclusion :
mostlyStatic --exclude dl gcc -o test test.c -ldl -lpthread
J'obtiens alors :
gcc -o test test.c -ldl "/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../x86_64-linux-gnu/libpthread.a"