我正在处理两个不同模块 abc、xyz 的源代码编译
abc 和 xyz 共享共同的源文件,这些文件是单独编译的。在创建静态库 foo.a 时,我必须包含 abc、xys 模块中的所有目标文件。
假设我有 a.c 文件,该文件对于 abc、xyz 模块都是通用的,我正在创建名为 abc_a.o 、 xyz_a.o 的目标文件,请注意,底层源文件是相同的,即 a.c
创建 obj 文件后,我使用
ar
工具创建静态库 foo.a
ar rcs foo.a *_a.o
由于我正在处理一个巨大的项目,所以我有数千个这样的文件存在。我遵循在创建静态库之前查找目标文件的 md5sum 并过滤掉重复的目标文件的方法。但这会消耗大量的构建时间。
这是示例 make 文件片段:-
OBJECT_FILES := kvctmp1934.o kvctmp2160.o kvctmp1932.o kvctmp1931.o kvctmp1939.o .... <may more obj files>
DUPLICATES := $(shell md5sum $(OBJECT_FILES) | sort | uniq -d -w32 | cut -d' ' -f3)
$(info DUPLICATES are $(DUPLICATES))
是否有其他更好的方法来满足我的要求来查找从同一源文件构建的重复 obj 文件?
静态库(
.a
存档)中的模块即使重复,也永远不会被链接两次,因为链接器只会选择真正解决某些不满足引用的存档模块,而不会再次选择它们,如果它们看起来已经链接。为什么?因为目标模块解决的所有引用都已解决,如果遇到新的引用,则包含它们的原始模块将被选择解决,因此,不会再次选择新的引用。
如果您收到该错误,是因为:
恕我直言,您不需要使用正在使用的管道来避免重复的模块,只需将它们放入
.a
存档中,链接器只会选择它们一次。即使您在命令行中多次放置库(多次使用-la -la -la...
),每个模块也只会链接一次,并且将跳过下一次出现的情况,因为不满足的引用已经满足)
顺便说一下,将档案作为库链接(使用选项
-l
)非常重要,这与在链接命令行中指定 .a
文件不同。
ld ... -la
将搜索名为
liba.a
的库并将其视为库,仅当它们满足某些不满足的引用时才有条件地链接所包含的模块。但如果你这样做了,那就:
ld ... liba.a
然后链接器会将存档内的所有模块包含到二进制可执行文件中。发生这种情况就好像您已在命令行中将所有
.o
文件写入存档位置一样。这是旧链接器的遗产。你要小心。