【转】gcc 编译链接库存在顺序问题…

来源:互联网 发布:网络主播灯光摆放图 编辑:程序博客网 时间:2024/06/05 08:52
使用gcc生成可执行文件时,大部分时候我们需要连接我们自己打包(AR)好的一些库文件,对于中大型(50万代码行以上)项目上,你将面对数个项目组,最好的情况是每个项目组发布自己的打包.ar文件,这些.ar文件之间没有任何依赖关系,然后由持续集成(ci)小组对这些包进行连接,不幸的是,这几乎是不可能的,我们在连接时还是遇到了liba.ar和libb.ar相互依赖的情况。

因为gcc的库是个有点怪怪的特性,在看-l帮助时可以看到:
      -l library
          Search the library named library when linking. (The second alter-
          native with the library as a separate argument is only forPOSIX
          compliance and is not recommended.)

          It makes a difference where in thecommand you write this option;
          the linker searches and processes libraries and object files inthe
          order they are specified.  Thus, foo.o -lz bar.osearches library z
          after file foo.o but before bar.o.  If bar.orefers to functions in
          z, those functions may not be loaded.

   出于知识产权保护的考虑,每一个项目组可能只允许看到自己的代码和别的项目组的头文件,这给CI小组带来了很头痛的事情,很多时候你不得不把库顺序来回调整。我也遇到了这样让人崩溃的情形,问题是对于liba.ar和libb.ar相互以来的情形,你可能最终采取丑陋的做法,将其中一个库在前后放两次:
gcc -o out.bin liba.ar libb.ar liba.ar -lrt
否则,您将不得不面对 "xx not referenced"之类的错误。

看看gcc的帮助,有下面的选项
-Xlinker option
          Pass option as an option to thelinker.  You can use this to supply
          system-specific linker options which GCC does not know how torec-
          ognize.

          If you want to pass an option that takes an argument, you mustuse
          -Xlinker twice, once for the option and once for theargument.  For
          example, to pass -assert definitions, you must write -Xlinker
          -assert -Xlinker definitions.  It does not work towrite -Xlinker
          "-assert definitions", because this passes the entire string asa
          single argument, which is not what the linker expects.

也就是说,-Xlinker是将连接选项传给连接器的,赶快看看ld的帮助有没有解决库顺序的选项吧:
 -( archives -)
      --start-group archives --end-group
          The archives should be a list of archive files. They may be either
          explicit file names, or -l options.

          The specified archives aresearched repeatedly until no new  unde-
          fined  references are created.   Normally, anarchive is searched
          only once in the order that it is specified on the  command  line.
          If  a symbol in that archive is needed to resolvean undefined sym-
          bol referred to by an object in an archive that appears  later  on
          the command line, the linker would not be able to resolve thatref-
          erence.  By grouping the archives, they all besearched  repeatedly
          until all possible references are resolved.

          Using  this  option has asignificant performance cost.  It is best
          to use it only  when there  are unavoidable  circular references
          between two or more archives.


不错,我们有个有点怪异的选项,-(和-),它能够强制"The specified archives are searchedrepeatedly"
god,这就是我们要找的啦。

最终的做法:
gcc -o output.bin -Xlinker "-(" liba.ar libb.ar -Xlinker "-)"-lrt

这样可以解决库顺序的问题了!问题是,如果你的库相互间的依赖如果错综复杂的话,可能会增加连接的时间,不过,做架构设计的都应该能考虑到这些问题吧。

原文出自:http://www.cppblog.com/findingworld/archive/2008/11/09/66408.html#Post

另一个文章:http://www.cppblog.com/wiisola/archive/2010/05/18/115637.html

GNU GCC手册2:http://www.shanghai.ws/gnu/gcc_2.htm
0 0