我正在开发一个复杂的C生态系统,其中不同的人开发了不同的包/库。
我想创建一个名为foobar
的新项目。该项目使用两个库,即库foo
和库bar
。
不幸的是,bar
不需要foo
所需的相同版本。两者都使用say
因此存在冲突。
如果所有软件包都在带有子模块的Git上,则在递归克隆时无法构建foobar
项目,因为在不同的翻译单元中存在两个say
函数。因此submodule
策略不起作用。
我的问题是:如何管理使用两个不同版本的相同静态库的一个项目({{1 }})?
*.a
项目foobar需要库 foobar
|
.----'----. <---- (require)
v v
foo bar
(v1.0) | | (v2.0)
'-> say <-'
和库foo
,这两个库都使用bar
包:say
需要版本1和foo
需要版本2.
bar
// say.h
void say(char *);
// foo.c
#include "say.h"
void foo(void) {
say("I am foo");
}
// bar.c
#include "say.h"
void bar(void) {
say("I am bar");
}
答案 0 :(得分:2)
链接器通常具有一种模式,在该模式下,它们执行部分链接,该链接解析当前可以解析的引用,并生成准备好进一步链接的对象模块,而不是已完成的可执行文件。
例如,GCC链接器ld
有一个-r
开关允许这样做。使用此开关以及可能的其他人,您可以将foo.o
与一个库关联以生成foo.partial.o
,并将bar.o
与另一个库单独链接以生成bar.partial.o
。然后,您可以将foo.partial.o
和bar.partial.o
相互链接,主程序以及所需的任何其他库和对象模块。
这适用于静态库,其中每个库的代码都包含在生成的可执行文件或目标文件中,并且完全解析了对其符号的引用。对于共享动态库,可能存在问题,因为动态库需要在运行时解析引用,并且链接器和可执行文件格式可能支持也可能不支持在一个库的不同版本中区分同名符号的功能。