Masalah yang saya pahami adalah sebagai berikut. Anda memiliki beberapa perpustakaan, beberapa statis, beberapa dinamis dan beberapa statis dan dinamis. Perilaku default gcc adalah menghubungkan "sebagian besar dinamis". Artinya, gcc menautkan ke pustaka dinamis jika memungkinkan, tetapi sebaliknya kembali ke pustaka statis. Saat Anda menggunakan opsi -static untuk meng - gcc , perilakunya adalah hanya menautkan pustaka statis dan keluar dengan kesalahan jika tidak ada pustaka statis yang dapat ditemukan, bahkan jika ada pustaka dinamis yang sesuai.
Pilihan lain, yang beberapa kali saya harapkan dari gcc , adalah apa yang saya sebut -mostly-static dan pada dasarnya kebalikan dari -dynamic (default). -mostly-static akan, jika ada, lebih memilih untuk menautkan ke pustaka statis tetapi akan kembali ke pustaka dinamis.
Opsi ini tidak ada tetapi dapat diemulasikan dengan algoritme berikut:
Membangun baris perintah tautan tanpa menyertakan -static .
Ulangi opsi tautan dinamis.
Akumulasi jalur perpustakaan, yaitu opsi-opsi dalam bentuk -L <lib_dir> dalam variabel <lib_path>
Untuk setiap opsi tautan dinamis, yaitu yang berformat -l <lib_name> , jalankan perintah gcc <lib_path> -print-file-name = lib <lib_name> .a dan tangkap hasilnya.
Jika perintah mencetak sesuatu selain yang Anda berikan, itu akan menjadi jalur lengkap ke pustaka statis. Ganti opsi perpustakaan dinamis dengan jalur lengkap ke perpustakaan statis.
Bilas dan ulangi sampai Anda memproses seluruh baris perintah tautan. Secara opsional, skrip juga dapat mengambil daftar nama pustaka untuk dikecualikan dari penautan statis.
Skrip bash berikut tampaknya melakukan triknya:
#!/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
Sebagai contoh:
mostlyStatic gcc -o test test.c -ldl -lpthread
saat sistem saya kembali:
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"
atau dengan pengecualian:
mostlyStatic --exclude dl gcc -o test test.c -ldl -lpthread
Saya kemudian mendapatkan:
gcc -o test test.c -ldl "/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../x86_64-linux-gnu/libpthread.a"