构建静态库时,是否可以解析跨.o文件的引用?

时间:2019-06-12 00:06:38

标签: c linker

例如,假设我构建了一个包含两个文件的库a.lib:foo.c和bar.c。 foo.c调用在bar.c中定义的函数void bar()

现在让我们说我要创建一个具有两个文件的可执行文件:main.c和bar.c。此bar.c还定义了void bar(),但实现方式不同。

当我将可执行文件与a.lib链接时,可执行文件将调用哪个void bar()

1 个答案:

答案 0 :(得分:1)

让我们假设:

  1. 该库为libfoobar.a(或libfoobar.lib),位于目录./lib中。
  2. 库文件foo.c定义了foo()foo()调用bar()
  3. 库文件bar.c定义了bar()
  4. 库源文件不在当前目录中。
  5. 程序文件bar.c还定义了bar()-一种不同的实现。
  6. 程序文件main.c调用foo()bar()
  7. 您的链接命令行如下:

    cc -o program main.o bar.o -L ./lib -lfoobar
    

然后:

  • 程序将包含程序文件bar()中的bar.c(因为该文件已明确包含在命令行中,位于库的前面)。
  • 该程序将包含库文件foo()中的foo.c,但是它调用的bar()将是程序文件bar.c中的那个foo.c从图书馆。

如果涉及更多符号,则库bar.c调用仅在库bar.c中可用的函数(程序bar.c并未实现所有这些函数),然后链接将失败,因为程序(无条件地)包含程序的bar.c,但是它也需要库的bar(),但这为函数bar.c提供了双重定义-这是一个错误。

曲折可能变得严重。简单的经验法则—不要这样做。也就是说,请勿使程序的bar.c提供库bar()中也可用的符号。如果必须并且还涉及其他切入点,那么您就必须加倍努力。

不要将库放在目标文件之前;那么您将无法通过双重定义aInstance = new A(); class B { anotherMethod = aInstance.someMethod; } 而失败。库位于链接列表中的目标文件之后。不过,您确实需要以正确的顺序获取多个(静态)库。或使用特殊选项使加载程序重新扫描库等。