Delphi编译和构建在同一项目上产生不同的二进制
-
19-09-2019 - |
题
在新的VCL应用程序中 编译 和 建造 操作产生相同的二进制文件和映射文件(即使“在项目中包含版本信息”选项已关闭 - 已经讨论过的“包含版本信息”选项,在.exe文件的末尾存在较小的差异)。地图文件是相同的字节到字节。但是WEN我添加了由构建和编译产生的二进制和地图(!)文件的任何第三方组件都显着不同!
在两个版本的Delphi上进行了测试:
- 版本7.0(构建8.1)
-Codegear™Rad Studio 2007版本11.0.2902.10471(+2007年12月更新)
繁殖的步骤:
- 创建新的VCL应用程序。可能会添加任何本机Delphi组件(我尝试从Standart,额外,Win32和System Tab中的所有组件)。
- 在项目选项的链接选项卡上打开详细的地图文件。
- 构建项目.
- 重命名输出.exe和.map文件(例如:project1.exe to project1b.exe和project1.map to project1b.map)。
- 编译项目.
- 重命名输出.exe和.map文件(例如:project1.exe to project1c.exe和project1.map to project1c.map)。
- 比较步骤4和6的文件(我使用Winmerge 2.12.4.0)。
我们几乎没有不同的.exe文件和完全相同的.map文件。然后,如果我们再次重复所有步骤,但是使用项目第三方组件(我尝试ODAC,DOA,DEVEXPRESS和自我制作),我们会获得更多不同的.exe和不同的.map文件。
为什么?有什么建议么?
更新
有关我如何找到这个以及为什么我感兴趣的一些信息:
项目是从使用MSBuild的简单脚本构建的。在项目中添加翻译(带有资源的DLL)时,我发现当项目构建(来自脚本或IDE)时 - 翻译版本的工作错误 - 某些文字在按钮,标签等。按钮,标签)。当项目从IDE编译时 - 一切都可以。因此,我开始比较构建和编译输出...
解决方案
您看到的只是编译器内置的制造逻辑的工件。当您进行构建时,它告诉编译器构建所有可用来源。因此,delphi处理每个源文件和使用源的使用列表中的每个单元,然后将构建该文件。它递归地做到这一点。当您进行编译时,仅加载了现有的.dcu文件,并且发现它们是最新的,则无需完成。这实际上可以导致发现单位的不同顺序,因为每个.dcu都会有效地“变平”使用列表。由于单位是以不同的顺序发现和加载的,因此它们是在弯曲的,以不同的顺序链接。这就是为什么您的地图文件看起来如此不同的原因。给定相同的来源,如果您在一排或两个编译中进行两个构建,则映射文件应相同。
差异的其他原因是更平凡的,包括PE标头时间戳记以及其他填充和对齐。
其他提示
我相信这个答案有两个部分。
您看到的部分问题是,IIRC是编译器在进行编译/构建之前并不为零。因此,出于对齐目的,在非初始化的内存中剩下的任何东西都变成了输出中的填充物。
我似乎还记得,PE标题信息中包含一个日期时间戳,用于应用程序。每次都会引起差异。
我不是确认这一点的最佳人选,但这似乎是我过去的讨论中回想起的。
像艾伦·鲍尔(Allen Bauer)或巴里·凯利(Barry Kelly)这样的人可能会为此提供更好/更准确的信息。
如果您使用编译器在项目中定义并将其更改,则如果进行编译,则将看到DCU和生成的模块(EXE或DLL)的任何更改。如果您进行了完整的重建,则编译器定义将在新创建的DCU和模块中使用。
我已经在一个大型项目组中看到了这一点,在一个大型项目组中,我们在具有不同定义的不同项目中使用模块,并且所有DCU都存储在同一目录中。
ERGO:编译器在这种情况下没有强制执行对定义的依赖关系。
也许您确实看到了同样的问题。