是否可能进行差分链接?

3
我有一个二进制文件,它链接了大量具有许多相互依赖关系的目标文件。每当我重新编译其中的一个文件时,我需要链接整个二进制文件。
链接器(特别是GCC或Clang)是否支持“差分链接”的某种方法?此方法足够保留所有其他链接部分之间的相互关系信息,因此当单个部分重新编译时,所需完成的工作仅涉及其与其他部分的关系+将它们放在二进制文件中?
注意:我主要关注C ++,但我想这个问题至少可以推广到C,并且可能适用于其他编译语言。
1个回答

2
在MSVC中,这被称为“增量链接”。有趣的是,我发现GCC可能在某种程度上支持它,尝试使用"-Wl,-i"或"-Wl,-r"参数来编译GCC(应该也由CLang支持,因为这些"-Wl"参数只是传递给ld)。

我以前从未使用过它,但是我用以下 makefile 完成了这项工作:

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

all:    test_app

test_app:   test_app.reloc
    g++ -o $@ $^

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

$(OBJS):    makefile

%.o:    %.cpp
    g++ -c -o $@ $<

这将构建应用程序,但我不完全确定它在内部执行的操作,是否像MSVC中执行的“增量链接”一样。
特别是,在使用“-Wl,-i”时,“-nostdlib”参数是必需的,以便默认库不会传递给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 $@ $^

%.o:    %.cpp
    g++ -c -o $@ $<

%.ro:   %.o
    g++ -Wl,-i -nostdlib -nostartfiles -o $@ $<

基本上,为每个对象创建可移植文件(这可能是将obj文件链接到可执行文件的重要部分),然后仅更新必要的可重定位文件。对于最终的链接步骤,使用可重定位文件将所有内容链接在一起(但已经完成了部分链接)。
还可以创建对象文件组的“组”,以便将它们分组为单个可重定位文件,这样最后就会少一些文件(不确定这是否会在最后带来任何好处)。

你能多写几句关于使用这些选项时的工作流程吗?例如,假设我的源文件是 a.cppb.cppc.cpp,分别单独编译,没有包含文件,并且我希望在重新编译 a.cpp 时能够减少链接工作量。最初应该运行什么,然后用新的 a.o 运行什么? - einpoklum
使用示例makefile进行更新 - EmDroid
关于第二个makefile:重点是gcc能够轻松地将.ro文件合并为一个可执行文件。好的,但是,我们为什么还需要.cpp -> .o这一步呢?为什么不直接进行.cpp -> .ro呢? - einpoklum
是的,我认为这样做应该也能起到同样的效果,通过直接创建可重定位的目标文件。 - EmDroid
@axalis:我只重新编译那些发生变化的文件。问题是,链接.ro文件是否比链接.r文件快得多(实际上我认为不会,除非在链接中重复使用二进制文件)。 - einpoklum
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接