Проблема, как я понимаю, в следующем. У вас есть несколько библиотек, некоторые статические, некоторые динамические, а некоторые статические и динамические. По умолчанию gcc связывает "в основном динамические". То есть gcc по возможности ссылается на динамические библиотеки, но в остальном возвращается к статическим библиотекам. Когда вы используете параметр -static для gcc, поведение заключается в связывании только статических библиотек и выходе с ошибкой, если статическая библиотека не может быть найдена, даже если есть подходящая динамическая библиотека.
Другой вариант, который мне несколько раз хотелось, чтобы у gcc был, - это то, что я называю -в основном-статическим, и по сути он противоположен -динамическому. (по умолчанию). -mostly-static, если бы он существовал, предпочел бы связываться со статическими библиотеками, но вернулся бы к динамическим библиотекам.
Этой опции не существует, но ее можно эмулировать с помощью следующего алгоритма:
Создание командной строки ссылки без включения -static.
Перебирайте параметры динамической ссылки.
Накапливайте пути к библиотекам, то есть параметры формы -L ‹lib_dir› в переменной ‹lib_path›.
Для каждого параметра динамической ссылки, т.е. имеющего форму -l ‹lib_name›, выполните команду gcc ‹lib_path› -print-file-name = lib ‹lib_name› .a strong > и захватить выход.
Если команда выводит что-то отличное от того, что вы передали, это будет полный путь к статической библиотеке. Замените параметр динамической библиотеки полным путем к статической библиотеке.
Промойте и повторяйте, пока не обработаете всю командную строку ссылки. При желании сценарий также может принимать список имен библиотек для исключения из статической компоновки.
Следующий сценарий bash, похоже, помогает:
#!/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
Например:
mostlyStatic gcc -o test test.c -ldl -lpthread
в моей системе возвращается:
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"
или с исключением:
mostlyStatic --exclude dl gcc -o test test.c -ldl -lpthread
Тогда я получаю:
gcc -o test test.c -ldl "/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../x86_64-linux-gnu/libpthread.a"
person
jcoffland
schedule
06.12.2012