Jak rozumiem, problem jest następujący. Masz kilka bibliotek, niektóre statyczne, niektóre dynamiczne, a niektóre zarówno statyczne, jak i dynamiczne. Domyślnym zachowaniem gcc jest linkowanie „głównie dynamiczne”. Oznacza to, że gcc łączy się z bibliotekami dynamicznymi, jeśli jest to możliwe, ale w przeciwnym razie wraca do bibliotek statycznych. Kiedy używasz opcji -static do gcc zachowanie polega na połączeniu tylko bibliotek statycznych i zakończeniu z błędem, jeśli nie można znaleźć żadnej biblioteki statycznej, nawet jeśli istnieje odpowiednia biblioteka dynamiczna.
Inną opcją, którą przy kilku okazjach życzyłem sobie, by gcc był, jest to, co nazywam - głównie statyczne i zasadniczo jest przeciwieństwem opcji -dynamic (domyślna). -mostly-static wolałoby, gdyby istniało, łączyć się z bibliotekami statycznymi, ale wracałoby do bibliotek dynamicznych.
Ta opcja nie istnieje, ale można ją emulować za pomocą następującego algorytmu:
Konstruowanie wiersza poleceń łącza bez włączania -static .
Powtarzaj opcje łącza dynamicznego.
Gromadzenie ścieżek bibliotek, tj. Tych opcji postaci -L <katalog_lib> w zmiennej <ścieżka_lib>
Dla każdej opcji dowiązania dynamicznego, tj. Tych w postaci -l <nazwa_biblioteki> , uruchom komendę gcc <ścieżka_lib> -print-file-name = lib <nazwa_biblioteki> .a i przechwyć wynik.
Jeśli polecenie wydrukuje coś innego niż to, co przekazałeś, będzie to pełna ścieżka do biblioteki statycznej. Zastąp opcję biblioteki dynamicznej pełną ścieżką do biblioteki statycznej.
Płucz i powtarzaj, aż przetworzysz cały wiersz poleceń łącza. Opcjonalnie skrypt może również pobrać listę nazw bibliotek, które mają być wyłączone z łączenia statycznego.
Poniższy skrypt bash wydaje się działać:
#!/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
Na przykład:
mostlyStatic gcc -o test test.c -ldl -lpthread
w moim systemie zwraca:
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"
lub z wykluczeniem:
mostlyStatic --exclude dl gcc -o test test.c -ldl -lpthread
Otrzymuję wtedy:
gcc -o test test.c -ldl "/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../x86_64-linux-gnu/libpthread.a"