为什么 LINK.EXE 需要 .EXP 文件来适应 .DLL 文件之间的循环依赖关系?

问题描述 投票:0回答:1

注意:

.LIB
的所有情况均指的是
link.exe
导入库,而不是目标文件的存档。

我花了很长时间弄清楚如何适应 Windows 中

.DLL
文件之间的循环依赖关系。这是因为我正在使用一个
makefile
,它在循环依赖的共享库中具有未解析的外部。我认为我需要更多地了解链接器......

我要回顾一下,因为它很容易忘记。不仅如此,我对 Windows 中链接的理解很可能存在问题。任何更正都会有帮助。

为了这个问题,我有3个文件:exec.objone.objtwo.obj

场景:

  1. one.obj
    包含在
    two.obj
    中定义的符号,并通过
    link.exe
    链接到
    .DLL
  2. two.obj
    包含在 one.obj 中定义的符号,并通过
    link.exe
    链接到另一个
    .DLL
  3. exec.obj
    包含在
    one.obj
    two.obj
    中定义的符号,并通过
    link.exe
    链接到
    .EXE

常见的循环依赖问题:

one.obj
link.exe
处理时,会创建
one.dll
one.lib
(其导入库)。
one.lib
的目的是描述在
one.dll
中找到的导出符号。

在当前时间点,

one.dll
无法从
two.obj
导入符号,因为
two.obj
尚未被
link.exe
处理,因此
two.lib
(导入库)尚不存在。因此,
one.dll
包含对
two.obj
中定义的符号的未解析引用。

就像

one.obj
一样,当
two.obj
link.exe
处理时,它会创建一个导入库(
two.lib
)和
two.dll
。然而,
two.obj
实际上可以通过查看
one.lib
内部来找到它自己未解析的引用。此时,
one.dll
具有未解析的引用,而
two.dll
则没有。无论哪种方式,
exec.obj
在处理时都会有未解析的引用。

常见的循环依赖解决方案:

问题是,每当您尝试将

one.obj
链接到
.DLL
时,它都会搜索未解析的引用,将
one.obj
转换为 .DLL 并创建相应的
one.lib
(导入库),所有这些都在同一步骤中进行。该步骤完成后,再搜索任何其他未解析的引用就为时已晚,因为
one.obj
现在是
one.dll

解决方案是分解步骤。创建相应的导入库(

one.lib
),而不将
one.obj
变成
one.dll
。这将允许
one.obj
稍后由
link.exe
处理,从而在最终链接
two.lib
时不会禁用它使用
two.obj
的能力。

问题:

使用

one.lib
在其自己的单步中创建相应的导入库 (
link.exe
) 时,会创建另一个名为
one.exp
的文件。我不明白为什么有必要。如果
one.obj
仍然存在,则在处理
two.lib
时可以在
two.obj
中找到未解析的引用。但是,根据我的阅读,有必要在最后一步中包含
one.exp
不仅要处理
one.obj
并让它找到
two.lib
,还必须将
one.exp
添加到输入
link.exe
的文件列表中。为什么?
two.lib
已经描述了
one.obj
所需的符号,而
two.exp
从来不需要处理
two.obj

visual-studio dll linker shared-libraries
1个回答
1
投票

您必须将时钟倒回到 20 世纪 80 年代末,那时使用链接器的 /DEF 或 /EXPORT 选项指定导出。他们使生成 one.dll 的第二个链接步骤变得脆弱,当您不使用“完全相同”的相同选项时,您会被射断。通过链接 one.exp 并省略选项来避免,现在不再可能出错,并且链接器不会重写 one.lib 不再那么相关了,现在几乎每个人都使用

__declspec(dllexport)

属性来指定导出。在这种情况下,当您不链接 one.exp 时,除了 one.lib 文件日期比 Two.dll 更新并导致不必要的重建之外,我没有看到明显的失败情况。不太确定,我从来没有让自己陷入这样的困境。

    

© www.soinside.com 2019 - 2024. All rights reserved.