C ++静态链接共享库

时间:2011-07-09 11:13:36

标签: c++ static-libraries crt dynamic-library

我有一个共享库,由我无法控制的另一个应用程序使用,需要* .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 - 用pic还是其他什么?

3 个答案:

答案 0 :(得分:38)

创建共享库时不应使用-static标志,而是用于创建静态链接的可执行文件。

如果您只拥有该库的静态版本,则只需使用-lsqlite3即可将其链接。但如果同时存在动态版本(.so)和静态版本,则链接器将更喜欢动态版本。

要指示链接器选择静态链接器,请为链接器提供-Bstatic标志,并使用-Bdynamic切换回动态链接以获取其他内容(如libc和动态运行时支持)。也就是说,你使用标志:

 -Wl,-Bstatic -lsqlite3 -Wl,-Bdynamic 

另外,您只需指定.a文件的完整路径,例如: /usr/lib/libsqlite3.a而不是任何编译器/链接器标志。

使用GNU ld,您还可以使用-l:libsqlite3.a代替-lsqlite3。这将强制使用库文件libsqlite3.a而不是libsqlite3.so,默认情况下链接器会更喜欢它。

请记住确保.a文件已使用-fpic标志进行编译,否则通常无法将其嵌入共享库中。

答案 1 :(得分:7)

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

PIC的含义详情如下:http://en.wikipedia.org/wiki/Position-independent_code

答案 2 :(得分:0)

I had the same problem. Apparently -static is not the same as -Bstatic. I switched to -Bstatic and everything worked.