将共享库与静态库链接:必须将静态库编译成不同于应用程序是否链接它?

至少在Linux和Solaris上,静态库实际上只是一堆编译的.o被抛入一个大文件中。当编译一个静态库时,通常会使用-fpic标志,所以生成的代码与位置有关。

现在说我的静态库是B.我已经构建了它,并且具有最终的.a文件,它真的只是所有位置依赖的.o文件的全局。现在我有一个我想要构建的共享库,A,我想让它静态地链接B.当我构建A时,我自然会使用-fpic标志使生成的代码位置独立。但是如果我链接到B,我不是混合位置依赖和位置无关对象文件?

我得到很多文本重定位错误,除非我也指定-imimpure-text,我认为这可能是原因。看来当我编译一个库时,我真的需要编译3次,一个共享版本,一个静态版本和一个静态可以被共享的libs版本。我对吗?我可以继续使用-imimpure-text,但是g man页面说,如果你这样做,对象实际上并不会最终被共享(不清楚它是全部是非共享的还是只是静态链接的部分,有没有人知道?) 。

最佳答案
您不必在共享对象中使用PIC代码(如您发现可以使用-mimpure-text选项来允许的)。

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

但是,如果您没有PIC代码,则运行时链接器加载共享对象时,必须将fixup应用于文本页面。这意味着使用共享对象的每个进程都将拥有自己的唯一版本的任何文本页面,它具有一个修正(即使共享对象加载在同一个地址上,只需要注意页面是修改而不是以相同的方式修改)。

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

但是如果不是这种情况,只有一个进程加载了共享对象,那么这几乎不是至关重要的。

转载注明原文:将共享库与静态库链接:必须将静态库编译成不同于应用程序是否链接它? - 代码日志