如何link一个工程到同一个C静态库的两个不同版本?

How to link a project to two different versions of the same C static library?

我正在研究一个复杂的 C 生态系统,其中不同的 packages/libraries 由不同的人开发。

我想创建一个名为 foobar 的新项目。该项目使用 两个库,库foo 和库bar

遗憾的是,bar 不需要与 foo 相同的版本。两者都使用 say 所以有冲突。

如果所有包都在 Git 上且带有子模块,则递归克隆时无法构建 foobar 项目,因为两个 say 函数存在于不同的翻译单元中。所以 submodule 策略不起作用。

我的问题是:如何管理一个项目,该项目使用两个不同版本的相同静态库(*.a)?

结构

          foobar
            |
       .----'----.           <---- (require)
       v         v
      foo       bar
(v1.0) |         | (v2.0)
       '-> say <-' 

项目 foobar 需要库 foo 和库 bar,这两个库都使用 say 包:foo 需要版本 1 和 bar 需要版本 2。

// say.h
void say(char *);

foo

// foo.c
#include "say.h"

void foo(void) {
    say("I am foo");
}

// bar.c
#include "say.h"

void bar(void) {
    say("I am bar");
}

foobar

// main.c
#include <stdlib.h>
#include "foo"
#include "bar"

int main() {
    foo();
    bar();
    return EXIT_SUCCESS;
}

链接器通常有一种模式,在这种模式下,它们执行部分 link,解析当前可以解析的引用,并生成一个准备好进一步 linking 的目标模块,而不是完成的可执行文件.

例如,GCC linker ld 有一个允许这样做的 -r 开关。使用此开关,可能还有其他开关,您可以 link foo.o 使用一个库来制作 foo.partial.o 并单独 link bar.o 使用另一个库来制作 bar.partial.o.然后你可以 link foo.partial.obar.partial.o 彼此,主程序,以及任何其他所需的库和对象模块。

这适用于静态库,其中每个库的代码都包含在生成的可执行文件或目标文件中,并且对其符号的引用已完全解析。对于共享动态库,可能会有问题,因为动态库需要在 运行 时解析引用,并且 linker 和可执行文件格式可能支持也可能不支持区分符号的能力在一个库的不同版本中具有相同的名称。