2012-02-21 61 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 ...