Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi编译和构建在同一项目上生成不同的二进制文件_Delphi_Build_Compilation_Map Files - Fatal编程技术网

Delphi编译和构建在同一项目上生成不同的二进制文件

Delphi编译和构建在同一项目上生成不同的二进制文件,delphi,build,compilation,map-files,Delphi,Build,Compilation,Map Files,在新的VCL应用程序中,编译和编译操作生成相同的二进制文件和映射文件(即使关闭了“在项目中包含版本信息”选项,在.exe文件末尾也会有细微差别-已讨论过)。映射文件是相同的字节到字节。但是,如果我添加任何第三方组件,构建和编译生成的二进制和map(!)文件会有很大的不同 在两个版本的Delphi上测试: -版本7.0(内部版本8.1) -代码齿轮™ RAD Studio 2007版本11.0.2902.10471(+2007年12月更新) 复制步骤: 创建新的VCL应用程序。可能添加任何本机De

在新的VCL应用程序中,编译和编译操作生成相同的二进制文件和映射文件(即使关闭了“在项目中包含版本信息”选项,在.exe文件末尾也会有细微差别-已讨论过)。映射文件是相同的字节到字节。但是,如果我添加任何第三方组件,构建和编译生成的二进制和map(!)文件会有很大的不同

在两个版本的Delphi上测试:
-版本7.0(内部版本8.1)
-代码齿轮™ RAD Studio 2007版本11.0.2902.10471(+2007年12月更新)

复制步骤:

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

    为什么??有什么建议吗

    更新
    一些关于我是如何发现这一点以及为什么我感兴趣的信息:

    项目是从带有MSBuild的简单脚本生成的。当在项目中添加translation thru ITE(带有资源的dll)时,我发现当项目构建时(从脚本或IDE)-翻译版本工作错误-按钮、标签等上的一些文本来自错误的位置(字面上是来自另一个按钮、标签)。当项目从IDE编译时,一切都正常。所以我开始比较构建和编译输出…

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

    您看到的问题IIRC的一部分是编译器在编译/构建之前没有清空内存。因此,出于对齐目的,未初始化内存中的任何内容都将成为输出中的填充内容

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

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


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

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


    造成差异的其他原因更为常见,包括PE头时间戳以及其他填充和对齐位。

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

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

    因此:在本例中,编译器不强制依赖于定义


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

    不知道,但是从更简单的第三方组件开始测试,然后再转到更复杂的组件。还要确保来源保持100%不变。不同的USES子句(包括order!)可能会改变单元初始化表的布局,因此二进制。源代码保持100%不变-我只生成和编译。您还会发现生成和生成不同的二进制文件。这与编译和编译之间的区别无关。@Rob:编译和编译产生不同的二进制文件是什么意思?你是说编译和构建吗?不,Ryan。Max说如果你构建然后编译,你会得到不同的结果。但是,如果你一次又一次地构建,你仍然会得到不同的结果。在这种情况下,编译和构建之间的区别无关紧要。@Allen:谢谢你提供的细节Allen,我不知道其中的DCU部分,但这是有意义的。谢谢你的解释。那么,是否有可能允许编译器使用编译器提示,指示编译器始终以一定的顺序以单元(DCU或PAS文件)链接?这会有点违背整个目的,不是吗?此外,典型的Delphi应用程序链接到您可能完全不知道甚至不存在的单元。链接顺序由编译器符号表本身的内部顺序决定。这是编译器如何工作的关键。为什么你不简单地为你的“官方”构建使用一个自动构建过程,这些构建总是从原始源构建的(即构建系统上不存在DCU)?@Allen:我使用自动构建过程。但是当我将翻译添加到我的项目中时(使用Delphi集成翻译)