С++ Статически связанная общая библиотека
У меня есть общая библиотека, используемая другим приложением вне моего контроля, которое требует *.so объектов. В моей библиотеке используется sqlite3, который должен быть статически связан с ним (мне абсолютно необходим автономный двоичный файл).
Когда я пытаюсь скомпилировать и связать свою библиотеку:
-fpic -flto -pthread -m64
-flto -static -shared
Я получаю следующую ошибку:
/usr/bin/ld: /usr/local/lib/gcc/x86_64-unknown-linux-gnu/4.6.1/crtbeginT.o: relocation R_X86_64_32 against `__DTOR_END__' can not be used when making a shared object; recompile with -fPIC
/usr/local/lib/gcc/x86_64-unknown-linux-gnu/4.6.1/crtbeginT.o: could not read symbols: Bad value
collect2: ld returned 1 exit status
Что такое перекомпиляция с -fPIC? Мой код или CRT?
Я уже пытался скомпилировать свой объект с -fPIC с тем же результатом.
Спасибо.
EDIT:
Проблема, похоже, не связана с SQLite3.
Я написал простую однострочную библиотеку, которая компилирует и ссылается следующим образом:
g++ -c -fPIC -o bar.o bar.cpp
g++ -shared -o bar.so bar.o
но не так:
g++ -c -fPIC -o bar.o bar.cpp
g++ -static -shared -o bar.so bar.o
Проблема, похоже, связана с CRT (crtbeginT.o). Я должен перекомпилировать GCC -with-pic или что-нибудь еще?
Ответы
Ответ 1
Нельзя использовать флаг -static
при создании общей библиотеки, для создания статически связанных исполняемых файлов.
Если у вас есть только статическая версия библиотеки, вы можете просто связать ее с помощью -lsqlite3
. Но если есть динамическая версия (.so) и статическая версия, компоновщик предпочтет динамический.
Чтобы дать ссылку компоновщику выбрать статический, дайте компоновщику флаг -Bstatic
и верните его к динамической компоновке для других вещей (например, libc и динамической поддержки) с помощью -Bdynamic
. То есть вы используете флаги:
-Wl,-Bstatic -lsqlite3 -Wl,-Bdynamic
Альтернативно, вы можете просто указать полный путь к .a файлу, например. /usr/lib/libsqlite3.a
вместо любых флагов компилятора/компоновщика.
С помощью GNU ld вы также можете использовать -l:libsqlite3.a
вместо -lsqlite3
. Это заставит использовать файл библиотеки libsqlite3.a
вместо libsqlite3.so
, который по умолчанию использует компоновщик.
Не забудьте убедиться, что файл .a был скомпилирован с флагом -fpic
, иначе вы обычно не можете вставлять его в общую библиотеку.
Ответ 2
Любой код, который каким-то образом пробивается в динамическую библиотеку, должен быть перемещен. Это означает, что все, что связано с вашим .so, независимо от статически или динамически, должно быть скомпилировано с помощью -fPIC
. В частности, статическая библиотека sqlite
также должна быть скомпилирована с помощью -fPIC
.
Подробности о том, какие средства PIC находятся здесь: http://en.wikipedia.org/wiki/Position-independent_code
Ответ 3
У меня была та же проблема. По-видимому-статический не то же самое, что -Bstatic. Я переключился на -Bstatic, и все сработало.