将共享库链接到静态库:静态库的编译必须与应用程序链接的编译不同吗?

时间:2022-09-18 12:26:49

At least on Linux and Solaris, static libraries are really just a bunch of compiled .o's tossed into one big file. When compiling a static library, usually the -fpic flag is ommited, so the generated code is position dependent.

至少在Linux和Solaris上,静态库实际上只是一堆编译好的.o文件。在编译静态库时,通常省略-fpic标志,因此生成的代码与位置有关。

Now say my static library is B. I've built it and have the resulting .a file which is really just a glob of all of the position dependent .o files. Now I have a shared library I'd like to build, A, and I want it to statically link B. When I build A, naturally I'll use the -fpic flag to make the generated code position independent. But if I link against B, aren't I mixing position dependent and position independent object files?

现在假设我的静态库是b,我已经构建了它并得到了一个文件,它实际上是所有位置相关的。o文件的一个总体。现在我有了一个我想要构建的共享库a,我想让它静态地链接b。但是如果我链接到B,我不是混合了位置相关和位置无关的对象文件吗?

I'm getting a lot of text relocation errors unless I also specify -mimpure-text, and I think this maybe the cause. It seems when I compile a library, I really need to compile it 3 times, a shared version, a static version, and a static-that-can-be-used-by-shared-libs version. Am I right? I could just keep using -mimpure-text but the g++ man page says that if you do that the object doesn't actually end up being shared (it's unclear if it's all unshared or just the statically linked parts though, does anyone know?).

除非我指定-mimpure-text,否则我将收到大量的文本迁移错误,我认为这可能是原因。当我编译一个库时,我确实需要编译它3次,一个共享版本,一个静态版本,以及一个静态的- - - - - - -可以使用的- - - - - - -libs版本。我说的对吗?我可以继续使用-mimpure-text,但是g++ man页面说,如果这样做,对象实际上不会被共享(不清楚它是未共享的还是只是静态链接的部分,有人知道吗?)

3 个解决方案

#1


24  

You do not have to use PIC code in shared objects (as you have discovered you can use the -mimpure-text option to allow that).

您不必在共享对象中使用PIC代码(正如您所发现的,您可以使用-mimpure-text选项来实现这一点)。

That said, non-PIC code in shared objects are more heavyweight. With PIC code, the text pages in memory are just direct memory mappings of the text pages on disk. This means that if multiple processes are using the shared object, they can share the memory page.

也就是说,共享对象中的非pic代码更重量级。使用PIC代码,内存中的文本页只是磁盘上文本页的直接内存映射。这意味着如果多个进程正在使用共享对象,它们可以共享内存页。

But if you do not have PIC code, when the runtime linker loads the shared object, it will have to apply fixups to the text pages. This means that every processes that uses the shared object will have it's own unique version of any text page that has a fixup on it (even if the shared object is loaded at the same address as copy-on-write only notices that the page was modified and not that it was modified in the same way).

但是如果您没有PIC代码,那么当运行时链接器加载共享对象时,它必须对文本页面应用修复。这意味着每个过程都使用共享对象将有它自己的独特的版本的任何文本页面,有一个固定加载共享对象(即使在同一地址即写即拷只注意到页面被修改而不是以同样的方式,这是修改)。

To me, the important issue is whether you will simultaneously have multiple processes running that each load the shared object. If you do, it is definitely worth making sure all the code within the SO is PIC.

对我来说,重要的问题是,您是否同时拥有多个进程,每个进程都运行该共享对象。如果您这样做,那么确保SO中的所有代码都是PIC是绝对值得的。

But if that is not the case and only a single process has the shared object loaded, it's not nearly as critical.

但如果不是这样,而且只有一个进程装载了共享对象,那么它就不是那么重要了。

#2


3  

I do the following in the link stage for the shared object library version of a static library: g++ -shared -o libshared.so -Wl,--whole-archive -fPIC -lstatic -Wl,--no-whole-archive. Since --whole-archive links every object in a (list of) static libs (of the form libstatic.a) I believe preceding that (list) with -fPIC is all the OP need do.

我在一个静态库的共享对象库版本的链接阶段执行以下操作:g++ -共享-o libshared。所以-Wl -全存档-fPIC -lstatic -Wl -no-whole archive。因为——整个存档将每个对象(列表中的)静态libs(来自libstatic.a)中的每个对象链接起来,我相信在这之前(list)和-fPIC是所有OP需要做的事情。

#3


1  

As an alternative approach, ship two libraries: your shared one and the static you're linking against alongside. They should link into the final executable correctly.

作为另一种方法,ship两个库:共享的库和在旁边连接的静态。它们应该正确地链接到最终的可执行文件。

#1


24  

You do not have to use PIC code in shared objects (as you have discovered you can use the -mimpure-text option to allow that).

您不必在共享对象中使用PIC代码(正如您所发现的,您可以使用-mimpure-text选项来实现这一点)。

That said, non-PIC code in shared objects are more heavyweight. With PIC code, the text pages in memory are just direct memory mappings of the text pages on disk. This means that if multiple processes are using the shared object, they can share the memory page.

也就是说,共享对象中的非pic代码更重量级。使用PIC代码,内存中的文本页只是磁盘上文本页的直接内存映射。这意味着如果多个进程正在使用共享对象,它们可以共享内存页。

But if you do not have PIC code, when the runtime linker loads the shared object, it will have to apply fixups to the text pages. This means that every processes that uses the shared object will have it's own unique version of any text page that has a fixup on it (even if the shared object is loaded at the same address as copy-on-write only notices that the page was modified and not that it was modified in the same way).

但是如果您没有PIC代码,那么当运行时链接器加载共享对象时,它必须对文本页面应用修复。这意味着每个过程都使用共享对象将有它自己的独特的版本的任何文本页面,有一个固定加载共享对象(即使在同一地址即写即拷只注意到页面被修改而不是以同样的方式,这是修改)。

To me, the important issue is whether you will simultaneously have multiple processes running that each load the shared object. If you do, it is definitely worth making sure all the code within the SO is PIC.

对我来说,重要的问题是,您是否同时拥有多个进程,每个进程都运行该共享对象。如果您这样做,那么确保SO中的所有代码都是PIC是绝对值得的。

But if that is not the case and only a single process has the shared object loaded, it's not nearly as critical.

但如果不是这样,而且只有一个进程装载了共享对象,那么它就不是那么重要了。

#2


3  

I do the following in the link stage for the shared object library version of a static library: g++ -shared -o libshared.so -Wl,--whole-archive -fPIC -lstatic -Wl,--no-whole-archive. Since --whole-archive links every object in a (list of) static libs (of the form libstatic.a) I believe preceding that (list) with -fPIC is all the OP need do.

我在一个静态库的共享对象库版本的链接阶段执行以下操作:g++ -共享-o libshared。所以-Wl -全存档-fPIC -lstatic -Wl -no-whole archive。因为——整个存档将每个对象(列表中的)静态libs(来自libstatic.a)中的每个对象链接起来,我相信在这之前(list)和-fPIC是所有OP需要做的事情。

#3


1  

As an alternative approach, ship two libraries: your shared one and the static you're linking against alongside. They should link into the final executable correctly.

作为另一种方法,ship两个库:共享的库和在旁边连接的静态。它们应该正确地链接到最终的可执行文件。