F2051:单位%s使用不同版本的%s编译

Ian*_*oyd 13 delphi delphi-xe6

我们一直在使用Delphi XE6修复VCL中的错误.到目前为止该文件夹包含:

| VCL Source Fixes
|----- Vcl.ComCtrls.pas
|----- Winapi.CommCtrl.pas
Run Code Online (Sandbox Code Playgroud)

我们将文件夹添加到我们的搜索路径:

在此输入图像描述

在此过程中,我们了解到我们必须将修复仅限于该implementation部分.否则,该部分中符号的散列签名会发生变化.这会导致链接器意识到DCU内的符号与它们期望的版本不同.interface

巴里凯利对这种行为有一个很好的解释:

符号版本的重要概念.保存DCU时,Delphi根据符号的接口声明计算散列并将其与符号关联.使用该符号的其他单位也存储符号版本.这样,与大多数C链接器不同,避免了由过时符号引起的链接时冲突.

这样做的结果是,您应该能够将Classes.pas添加到您的项目中并几乎根据您的内容修改其实现部分,并且仍然能够静态链接其余的RTL和VCL以及第三方库,甚至仅以对象格式提供的那些.

要小心的事情:

  • 内联例程; 内联例程的主体是符号版本的一部分
  • 泛型; 泛型类型和方法的实现方是各个符号版本的一部分

因此,我们努力将错误修正限制在实现部分(例如,引入新的cracker类,而不是覆盖面向公众的类中的方法).

然后

然后我去修理了Vcl.Themes.pas.我开始简单,复制文件并将其放在fixes文件夹中:

| VCL Source Fixes
|----- Vcl.ComCtrls.pas
|----- Winapi.CommCtrl.pas
|----- Vcl.Themes.pas
Run Code Online (Sandbox Code Playgroud)

即使我还没有(还)修改过Vcl.Themes.pas,编译器就会对它进行扼流:

[dcc32致命错误] Vcl.Themes.pas(2074):F2051单元Vcl.Forms是用不同版本的Vcl编译的.Themes.TMouseTrackControlStyleHook

为什么

重要的问题是:

为什么会这样?

是怎么回事,编译器无法意识到完全相同的文件是完全相同的文件?XE6附带的VCL源是否可能不合适,并且与DCU中的船舶不匹配?它与库搜索顺序有关吗?它是否与内联,泛型,迭代器,平台,调试dcus,64位编译器,ifdef,代码完成,协同作用有关?

还有其他隐含的问题,试图回答原因:

为什么它适用于其他两个文件,但不是这个?
当我甚至没有更改文件时为什么会失败?

你有什么尝试?

  • 试图VCL Source Fixes在搜索路径中越走越低
  • 尝试打开使用调试dcus
  • 尝试切换到64位平台
  • 尝试删除dcu项目文件夹中的所有文件(尽管没有删除D:\Programs\Embarcadero\Studio\14.0\lib\win32\release\Vcl.Themes.dcuDelphi XE6附带的文件)
  • 关闭XE6并重新运行它
  • 去Wendy吃午饭

当然我想解决它.但不仅仅是想解决这个问题,我想了解它失败的原因.编译器没有使用魔法,伏都教或类似Q的能力.它是一个确定性的机器,并且根据一组固定的(未记录的)规则进行操作.

为什么会这样?

也可以看看

Dav*_*nan 8

您需要编译器选项来匹配Embarcadero编译单元时使用的选项.这就是为什么你的实现部分只有在它看起来应该成功时才会失败的原因.

启动默认项目并使用CTRL+ O+ O生成这些选项.我明白了

{$A8,B-,C+,D+,E-,F-,G+,H+,I+,J-,K-,L+,M-,N-,O+,P+,Q-,R-,S-,T-,U-,V+,W-,X+,Y+,Z1}
Run Code Online (Sandbox Code Playgroud)

当我在XE6中这样做时.

把它放在你的单元副本的顶部,你应该很高兴.根据您的主机项目选项,您可以放弃这些的缩减子集.在我的代码中,我发现:

{$R-,T-,H+,X+}
Run Code Online (Sandbox Code Playgroud)

就足够了.