27

我有一个共享库,由我无法控制的另一个应用程序使用,它需要 *.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 编译我的对象,结果相同。

谢谢。

编辑:

该问题似乎与 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 还是什么?

4

3 回答 3

43

-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标志编译,否则您通常无法将其嵌入到共享库中。

于 2011-07-09T22:18:05.860 回答
8

任何以某种方式进入动态库的代码都应该是可重定位的。这意味着与您的 .so 链接的所有内容,无论是静态的还是动态的,都应该使用 .so 进行编译-fPIC。具体来说,静态sqlite库也应该用-fPIC.

PIC 含义的详细信息在这里:http ://en.wikipedia.org/wiki/Position-independent_code

于 2011-07-09T11:18:42.193 回答
0

我有同样的问题。显然 -static 与 -Bstatic 不同。我切换到 -Bstatic 并且一切正常。

于 2015-07-28T15:50:30.447 回答