关于delphi:F2051:单元%s是用不同版本的%s编译的

F2051: Unit %s was compiled with a different version of %s

我们已经修复了Delphi XE6中VCL中的错误。到目前为止,该文件夹包含:

1
2
3
| VCL Source Fixes
|----- Vcl.ComCtrls.pas
|----- Winapi.CommCtrl.pas

然后将文件夹添加到我们的图书馆搜索路径:

enter image description here

在此过程中,我们了解到,我们只能将修补程序限制在implementation部分。否则,interface部分中符号的哈希签名会更改。这使链接器意识到DCU中的符号与期望的版本不同。

Barry Kelly对这种行为有很好的解释:

The important concept is that of symbol version. When saving a DCU, Delphi calculates a hash based on the interface declaration of the symbol and associates it with the symbol. Other units that use the symbol also store the symbol version. In this way, link-time conflicts caused by stale symbols are avoided, unlike most C linkers.

The upshot of this is that you should be able to add Classes.pas to your project and modify its implementation section almost to your heart's content, and still be able to statically link with the rest of the RTL and VCL and third-party libraries, even those provided in object format only.

Things to be careful of:

  • Inlined routines; the body of inlined routines are part of the symbol version
  • Generics; the implementation side of generic types and methods are part of the respective symbol versions

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

然后

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

1
2
3
4
| VCL Source Fixes
|----- Vcl.ComCtrls.pas
|----- Winapi.CommCtrl.pas
|----- Vcl.Themes.pas

即使我还没有修改Vcl.Themes.pas,编译器也对此感到窒息:

[dcc32 Fatal Error] Vcl.Themes.pas(2074): F2051 Unit Vcl.Forms was compiled with a different version of Vcl.Themes.TMouseTrackControlStyleHook

为什么

重要的问题是:

Why is this happening?

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

还有其他一些隐含的问题,以及试图回答其中的原因:

Why does it work for two other files, but not this one?
Why does it fail when I didn't even change the file?

你尝试了什么?

  • 尝试在搜索路径中将VCL Source Fixes上下移动
  • 尝试打开使用调试dcus
  • 尝试切换到64位平台
  • 尝试删除项目文件夹中的所有dcu文件(尽管不删除Delphi XE6随附的D:\Programs\Embarcadero\Studio\14.0\lib\win32
    elease\Vcl.Themes.dcu
    )
  • 关闭XE6并重新运行
  • 去温迪的午餐

我当然要修复它。但是除了想修复它之外,我还想了解它为什么会失败。编译器没有使用魔术,伏都教或类似Q的力量。这是一台确定性机器,并根据一组固定的(未记录的)规则进行操作。

为什么会这样呢?

也可以看看

  • Delphi-修复VCL错误时,使用x的其他版本编译了x单元
  • 我可以在RTL类System.Classes.TStream中修改常量并在运行时在Delphi XE6中重建它吗?


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

启动一个默认项目,并使用CTRL + O + O生成这些选项。 我懂了

1
{$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}

当我在XE6中执行此操作时。

将其放在单元副本的顶部,您应该可以使用。 根据宿主项目的选择,您可能可以摆脱其中的一部分。 在我的代码中,我发现:

1
{$R-,T-,H+,X+}

足够了。