Delphi Compile和Build在同一个项目上生成不同的二进制文件

时间:2010-01-06 13:45:37

标签: delphi build compilation map-files

在新的VCL应用程序中,编译构建操作会产生相同的二进制文件和映射文件(即使“包含版本信息”,也会在.exe文件的末尾略有不同在项目“选项被关闭 - 已经讨论过”。映射文件的字节与字节相同。但是,我添加任何第三方组件,Build和Compile生成的二进制和map(!)文件明显不同!

测试了两个版本的Delphi:
  - 7.0版(Build 8.1)
  - CodeGear™RAD Studio 2007版本11。0。1902。0471(+ 2007年12月更新)

重现步骤:

  1. 创建新的VCL应用程序。可能添加任何本机Delphi组件(我尝试从Standart,Additional,Win32和System选项卡中的所有组件)。
  2. 启用“项目选项”的“链接”选项卡上的“详细地图”文件。
  3. 构建项目
  4. 重命名输出.exe和.map文件(例如:project1.exe到project1b.exe,project1.map到project1b.map)。
  5. 编译项目
  6. 重命名输出.exe和.map文件(例如:project1.exe到project1c.exe,project1.map到project1c.map)。
  7. 比较步骤4和6中的文件。(我使用WinMerge 2.12.4.0)。
  8. 我们有几乎不同的.exe文件和完全相同的.map文件。然后,如果我们再次重复所有步骤但在项目第三方组件中使用(我尝试ODAC,DOA,DevExpress和selfmade),我们会得到更多不同的.exe和不同的.map文件。

    为什么呢?有什么建议吗?

    更新
    关于我如何找到这个以及为什么它让我感兴趣的一些信息:
    Project是使用MSBuild从简单的脚本构建的。当在项目中添加了通过ITE(带有资源的dll)的翻译时,我发现当项目是Build(来自脚本或来自IDE)时 - 翻译版本工作错误 - 按钮,标签等上的某些文本来自错误的地方(字面意思来自另一个按钮,标签)。当项目从IDE编译时 - 一切正常。所以我开始比较Build和Compile输出......

3 个答案:

答案 0 :(得分:10)

您所看到的只是编译器内置make逻辑的工件。当您进行构建时,它会告诉编译器构建所有可用的源。因此,Delphi处理每个源文件以及它找到源的使用列表中的每个单元,然后它将构建该文件。它以递归方式执行此操作。编译时,只加载现有的.dcu文件,如果发现它们是最新的,则不执行任何操作。这实际上可以导致发现单元的不同顺序,因为每个.dcu将有效地“展平”使用列表。由于单元是以不同的顺序被发现和加载的,因此它们是相反的,以不同的顺序链接。这就是您的地图文件看起来如此不同的原因。给定相同的源,如果您连续执行两个构建或连续两个编译,则映射文件应该相同。

差异的其他原因更为平凡,包括PE标题时间戳以及其他填充和对齐位。

答案 1 :(得分:3)

我相信这个答案有两个部分。

您看到的部分问题IIRC是编译器在执行编译/构建之前不会将内存清零。因此,未初始化的存储器中的任何内容都会成为输出中的填充符,以便进行对齐。

我似乎还记得应用程序的pe头信息中包含日期时间戳。每次都会造成不同。

我不是确认这一点的最佳人选,但这是我从过去的讨论中回忆起来的。

像Allen Bauer或Barry Kelly这样的人可能会提供更好/更准确的信息。

答案 2 :(得分:0)

如果在项目中使用编译器定义并且只是更改了它们,那么如果进行编译,则不会看到对dcu和生成的模块(exe或dll)的任何更改。如果进行完全重建,则在新创建的dcu和模块中使用编译器定义。

我在一个大型项目组中看到过这种情况,我们在不同项目中使用具有不同定义的模块,并且所有dcu都存储在同一目录中。

Ergo:在这种情况下,编译器不会对定义强制执行依赖项。

也许你确实看到了同样的问题。