2012-02-21 54 views
26

我们有一个代码库分解成静态库。不幸的是,这些库有循环依赖;例如,libfoo.a取决于libbar.a,反之亦然。通过链接两次相同的库来解决循环依赖性问题?

我知道“正确”的方式来处理,这是要使用的链接的--start-group--end-group选项,就像这样:

g++ -o myApp -Wl,--start-group -lfoo -lbar -Wl,--end-group 

但是,在我们现有的Makefile中,该问题通常是处理是这样的:

g++ -o myApp -lfoo -lbar -lfoo 

(想象一下扩展到约20个库具有复杂的相互依存关系。)

我一直在经历欧r Makefiles将第二种形式更改为第一种形式,但现在我的同事们问我为什么......除了“因为它更干净”以及其他形式存在风险的含义以外,我没有很好的答案。

那么,可以多次链接同一个库有没有创建一个问题?例如,如果相同的.o被拉两次,链接是否会失败并带有多重定义的符号?或者是否有任何风险,我们可以用相同静态对象的两个副本结束,从而创建微妙的错误?

基本上,我想知道是否有任何链接时间或运行时失败的可能性多次链接相同的库;如果是的话,如何触发它们。谢谢。

+0

我能想到的唯一问题是当您设法链接两个不同版本的同一个库。这很难做到,并且(IMO)在Linux上不太可能发生。另外,只有20家图书馆看起来不像。值得步入makefile吗?你可以花时间做别的事情。 – SigTerm 2012-02-21 15:43:08

+3

如果您修复库不具有循环依赖关系,则此问题就会消失。 – 2012-02-21 15:46:07

+3

我认为通过检查和分解库去除循环依赖是不可行的?因为这是最简洁的方式 – 2012-02-21 15:46:15

回答

5

我只能提供一个缺乏反例的例子。我从来没有见过第一种形式(尽管它明显更好),并且总是看到第二种形式得到解决,并且没有观察到问题。

即使如此,我仍然建议更改为第一种形式,因为它清楚地显示了库之间的关系,而不是依赖于链接器以特定方式运行。

这就是说,我建议至少考虑是否有重构代码的可能性,以将常见的部分抽出到其他库中。

+5

谢谢,马克。虽然我确实觉得有趣的是我的问题中有一半的评论说“修复你的代码库!”另一半说“你为什么要篡改一个有效的代码库?” :-) – Nemo 2012-02-21 16:36:09

+0

第一种形式会引入性能成本,因为链接器会尝试查找所有列出的库中重复的符号。请参阅:http://stackoverflow.com/a/409470/70198 – 2013-01-18 02:59:55

+0

第一种形式也仅适用于GNU ld,因此不是便携式解决方案。 – user1225999 2014-10-16 08:33:25

1

由于它是一个遗留应用程序,我敢打赌,库的结构是从一些可能无关紧要的安排中继承下来的,比如用来构建你不再使用的另一种产品。

即使继承的库结构仍然存在结构性原因,几乎可以肯定的是,从传统安排构建一个库仍然是可以接受的。只需将20个库中的所有模块放入新库即liballofthem.a即可。然后每个应用程序都是简单的g++ -o myApp -lallofthem ...