Проблема, как я понимаю, в следующем. У вас есть несколько библиотек, некоторые статические, некоторые динамические, а некоторые статические и динамические. По умолчанию gcc связывает "в основном динамические". То есть, когда это возможно , gcc ссылается на динамические библиотеки, но в остальном возвращается к статическим библиотекам. Когда вы используете параметр -static для gcc, поведение заключается в том, чтобы связывать только статические библиотеки и выходить с ошибкой, если статическая библиотека не может быть найдена, даже если есть соответствующая динамическая библиотека.
Другой вариант, о котором я несколько раз мечтал иметь gcc , - это то, что я называю -mostly-static и по сути является противоположностью -dynamic (по умолчанию). -mostly-static , если бы он существовал, предпочел бы связываться со статическими библиотеками, но вернулся бы к динамическим библиотекам.
Этого варианта не существует, но его можно эмулировать с помощью следующего алгоритма:
Создание командной строки ссылки без включения -static .
Перебирайте параметры динамической ссылки.
Накапливать пути к библиотекам, т.е. те параметры формы -L <lib_dir> в переменной <lib_path>
Для каждой опции динамической ссылки, то есть тех, которые имеют форму -l <lib_name> , запустите команду gcc <lib_path> -print-file-name = lib <lib_name> .a и запишите вывод.
Если команда выводит что-то иное, чем то, что вы передали, это будет полный путь к статической библиотеке. Замените параметр динамической библиотеки полным путем к статической библиотеке.
Промойте и повторяйте, пока не обработаете всю командную строку ссылки. При желании сценарий также может принимать список имен библиотек для исключения из статической компоновки.
Следующий сценарий 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"