2017-02-15 119 views
2

我有一個二進制鏈接使用大量的對象文件與許多相互依賴性。每當我重新編譯其中一個,我需要鏈接整個二進制文件。是否可以執行差異鏈接?

鏈接器(特別是GCC或Clang的鏈接器)是否支持某種「差異鏈接」方法,其中有關於所有其他鏈接部分之間的內部關係的足夠信息,以便唯一需要的工作當單個部分重新編譯時是否與其他部分的關係+將它們放在二進制文件中?

注:我最感興趣的是C++,但我想這個問題至少推廣到C,可能還會推廣到其他編譯語言。

回答

1

在MSVC中,這被稱爲「增量鏈接」。有趣的是,我發現GCC可能會在某種程度上支持這一點,請嘗試對GCC使用「-Wl,-i」或「-Wl,-r」參數(實際上也應該由CLang支持,因爲這些「-Wl」參數僅傳遞給ld) 。


我從來沒有使用過它,但我做了下面的Makefile這項工作:

OBJS := a.o b.o c.o main.o 

all: test_app 

test_app: test_app.reloc 
    g++ -o [email protected] $^ 

# build a "relocatable" object for incremental linking (either -i or -r) 
test_app.reloc: $(OBJS) 
    g++ -Wl,-i -nostdlib -nostartfiles -o [email protected] $^ 

$(OBJS): makefile 

%.o: %.cpp 
    g++ -c -o [email protected] $< 

這將構建應用程序,但我不完全知道它在內部做,如果真的在MSVC中完成類似「增量鏈接」的操作。

特別是,當使用「-Wl,-i」時,參數「-nostdlib」是必須的,這樣默認的libs將不會被傳遞給ld(然後找不到它們 - 如果沒有它,錯誤「/usr/bin/ld: cannot find -lgcc_s」)。


另一個版本,它實際上可能會更好地工作(不知道,這將需要一個更大的應用程序進行測試,看是否有在鏈接時單對象更新一些增益):

OBJS := a.ro b.ro c.ro main.ro 

all: test_app 

test_app: $(OBJS) 
    g++ -o [email protected] $^ 

%.o: %.cpp 
    g++ -c -o [email protected] $< 

%.ro: %.o 
    g++ -Wl,-i -nostdlib -nostartfiles -o [email protected] $< 
  • 基本上爲每個對象創建可重定位的文件(這可能是將obj文件鏈接到可執行文件中的重要部分),然後只更新必要的可重定位文件。對於最後的鏈接步驟,使用可重定位將所有內容鏈接在一起(但之前已經完成了部分鏈接)。

也可以在一個可重新定位的對象文件中創建「組」,這樣在最後會有更少的對象文件(不知道是否會在結尾處帶來任何東西) 。

+0

當我使用這些選項時,您可以再寫一些關於工作流程的內容嗎?例如假設我的源文件是'a.cpp','b.cpp'和'c.cpp',分開編譯,沒有include,我希望在重新編譯'a.cpp'時能夠做更少的鏈接工作。我最初應該運行什麼,我應該用新的'a.o'運行? – einpoklum

+0

使用示例makefile更新 – axalis

+0

關於第二個makefile:關鍵是gcc能夠輕鬆地將.ro文件合併爲一個可執行文件。好的,但是 - 爲什麼我們甚至需要.cpp - > .o步驟呢?爲什麼不立即做.cpp - > .ro? – einpoklum