Vấn đề như tôi hiểu nó là như sau. Bạn có một số thư viện, một số tĩnh, một số động và một số cả tĩnh và động. Hành vi mặc định của gcc là liên kết "chủ yếu là động". Có nghĩa là, gcc liên kết đến các thư viện động khi có thể nhưng nếu không sẽ trở lại thư viện tĩnh. Khi bạn sử dụng tùy chọn -static để gcc , hành vi là chỉ liên kết các thư viện tĩnh và thoát với lỗi nếu không tìm thấy thư viện tĩnh nào, ngay cả khi có thư viện động thích hợp.
Một tùy chọn khác, mà tôi có vài lần ước gcc có, là những gì tôi gọi là -mostly-static và về cơ bản là đối lập với -dynamic (mặc định). -mostly-static sẽ, nếu nó tồn tại, thích liên kết với các thư viện tĩnh nhưng sẽ trở lại thư viện động.
Tùy chọn này không tồn tại nhưng nó có thể được mô phỏng bằng thuật toán sau:
Xây dựng dòng lệnh liên kết với out bao gồm -static .
Lặp lại các tùy chọn liên kết động.
Tích lũy các đường dẫn thư viện, tức là các tùy chọn đó của biểu mẫu -L <lib_dir> trong một biến <lib_path>
Đối với mỗi tùy chọn liên kết động, tức là các tùy chọn có dạng -l <lib_name> , hãy chạy lệnh gcc <lib_path> -print-file-name = lib <lib_name> .a và chụp đầu ra.
Nếu lệnh in một cái gì đó khác với những gì bạn đã truyền, nó sẽ là đường dẫn đầy đủ đến thư viện tĩnh. Thay thế tùy chọn thư viện động bằng đường dẫn đầy đủ đến thư viện tĩnh.
Rửa sạch và lặp lại cho đến khi bạn đã xử lý toàn bộ dòng lệnh liên kết. Theo tùy chọn, tập lệnh cũng có thể lấy danh sách tên thư viện để loại trừ khỏi liên kết tĩnh.
Tập lệnh bash sau dường như thực hiện thủ thuật:
#!/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
Ví dụ:
mostlyStatic gcc -o test test.c -ldl -lpthread
trên hệ thống của tôi trả về:
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"
hoặc với một loại trừ:
mostlyStatic --exclude dl gcc -o test test.c -ldl -lpthread
Sau đó tôi nhận được:
gcc -o test test.c -ldl "/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../x86_64-linux-gnu/libpthread.a"