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