Delphi DCU文件是什么?

22

什么是Delphi DCU文件?

我相信它代表“Delphi编译单元”。我正确地假设它包含目标代码,因此对应于从C/C++源代码文件编译的“.o”文件吗?


1
它与“.o”或“.obj”文件类似,是的。它包含可链接的目标代码。 - Martin James
4
@Jerry:这是编译(二进制)代码,几乎就像 .c 目标文件一样。它不是任何类型的“缓存”;它可以复制到另一台计算机中,并在新项目中使用。它是一个目标文件。现在的孩子们可能不记得目标文件、库以及连接器的时代了。唉。 :-) - Ken White
1
@Ken 是的,我只是在指出 DCU 文件本质上的一个优点。如果你只修改了其中的一个模块而其他 9 个已经有了 DCU 文件,那么只有这个模块需要编译,从而加快了编译的速度。当然,除非你选择进行完整构建。 - Jerry Dodge
1
@Jerry:是的,这就是任何编译后的目标文件的确切行为。:-) 目标文件是编译器和链接器之间必要的中间步骤,以便将东西放在链接器可以处理并(与运行时和其他库一起)解析符号以“链接”在一起形成可执行文件的格式中。 - Ken White
1
称这些文件为“缓存”文件实在是有点牵强。构建过程内置了优化功能,旨在减少不必要的进程。因此,如果给定目标文件的任何依赖项都没有更新,并且目标文件仍然存在,则构建过程(例如,make)会简单地跳过重新构建它。就像说,如果你每晚不清空垃圾桶,那么它就像是一个你可能想回收的“缓存”。 - David Schwartz
显示剩余2条评论
3个回答

34
我认为 .dcu 通常意味着“Delphi编译单元”,而 .pas 文件仅是“Pascal源代码”。
.dcu 文件是 DCC 编译器在编译 .pas 文件后生成的文件(.dfm 文件被转换为二进制资源,然后直接由链接器处理)。
它类似于其他编译器生成的 .o.obj 文件,但包含有关符号的更多信息(因此您可以从中省略注释和编译器指令来反向工程单元的接口部分)。
.dc u文件在技术上不是“缓存”文件,尽管如果您不删除它们并且不需要重新编译它们时建议保留它们以使您的构建速度更快。 .dcu 文件与生成它的编译器版本绑定。在这个意义上,它比 .o 或 .obj 文件不太可移植(尽管它们也有兼容性问题)。

这里有一些历史,以防有所添加。

编译器传统上将源代码语言转换为某种中间形式。解释器不这样做--它们直接解释语言并立即运行应用程序。BASIC是解释语言的典型例子。DOS和Windows的"命令行"有一个称为"批处理文件"的文件可以写入,具有.bat扩展名。但在命令行上输入东西会直接执行它们。在*nix环境中,有许多不同的命令行解释器(CLIs),例如sh, csh, bash, ksh, 等等。您可以从所有这些解释器创建批处理文件--这通常被称为"脚本语言"。但现在有很多其他既解释又编译的语言。

无论是 Java 还是 .Net,例如,都会编译成一种称为中间 "byte-code" 表示的东西。

Pascal最初是作为一种单通编译器编写的,而Turbo Pascal(起源于PolyPascal)- 不同版本适用于CP/M, CP/M-86DOS - 直接生成可在这些操作系统下运行的二进制可执行文件(COM)。

Pascal最初被设计为一种小巧高效的语言,旨在通过结构化编程和数据结构来鼓励良好的编程实践;Turbo Pascal 1最初被设计为一个具有内置快速编译器的IDE,并且是DOS和CP/M市场上长时间编辑/编译/链接周期的可负担竞争对手。当时,Turbo Pascal和Pascal都有类似于任何编程环境的限制:内存和磁盘空间以kilobytes计算,处理器速度以Megahertz计算。

链接到可执行二进制文件会防止您链接到单独编译的单元和库。

在Turbo Pascal出现之前,有UCSD p-System操作系统(支持多种语言,包括Pascal)。当时的UCSD Pascal编译器已经使用单元将Pascal语言扩展了起来,并编译成一种伪机器字节码(称为p-code)格式,允许链接多个单元。尽管如此,它速度较慢。
同时,cVAXUnix环境中发展,编译成.o文件,这意味着“目标代码”,而不是“源代码”。注意:这与我们今天所谓的“objects”完全无关。
Turbo Pascal直到版本3可以直接生成.com二进制输出文件(虽然您可以使用修改那些覆盖文件),从版本4开始支持将代码分离为单位,这些单位首先编译为.tpu文件,然后链接到最终可执行二进制文件中。Turbo C编译器生成.obj(对象代码)文件而不是字节码,Delphi 2引入了.obj文件生成以便与C++ Builder协同工作。
对象文件在每个单元内部使用相对寻址,并且需要稍后进行所谓的“修正”(或relocation)才能使它们运行。修正指向符号标签,这些标签应该存在于其他对象文件或库中。
有两种“修正”:一种是由称为“linker”的工具静态完成的。链接器将一堆对象文件缝合在一起,形成类似拼布被子的东西。然后,它通过插入指向所有外部定义标签的指针来“修正”所有相对引用。
第二个修补程序是在程序加载运行时动态完成的。它们是由一个叫做“加载器”的东西完成的,但你从未见过它。当你在命令行上输入一个命令时,加载器会被调用来将一个EXE文件加载到内存中,根据文件加载的位置修正剩余的链接,然后控制转移到应用程序的入口点。
因此,.dcu文件最初是Borland在Turbo Pascal中引入单元时的.tpu文件,随着Delphi的引入而改变了扩展名。它们与.obj文件非常不同,尽管你可以从Turbo Pascal和Delphi链接到.obj文件。
Delphi还完全隐藏了链接器,所以你只需要编译和运行。然而,所有的链接器设置仍然存在于Delphi的一个选项面板中。

6
然而,虽然这段“历史”很有趣,但实际上回答这个问题的答案是:“是的,它们是Delphi编译单元,几乎与C/C++对象文件完全相同。” 这个答案应该首先给出,然后再讲历史(这样那些只想找到答案而不关心历史的人也可以清楚地找到答案)。 - Ken White
5
在Turbo Pascal 4.0中,"DCU"文件被称为"TPU"文件。Turbo Pascal从未生成或“链接”对象文件。直到Delphi 2推出新的32位编译器时才引入了对象文件创建功能。 - Allen Bauer
3
是的,@user1420752,它是一种模糊且专有的“目标文件”格式,类似于您熟悉的OMF和COFF。已经对其进行了一些逆向工程处理 http://hmelnov.icc.ru/DCU/FAQ.htm - Free Consulting
2
这是UCSD P-System,而不是USCS Pascal,并且原始的Turbo Pascal(版本3之前)生成COM文件,直到在Turbo Pascal 4中引入了units。 - Andy_D
3
“_Pascal最初是作为单程编译器编写的,它可以直接生成在DOS下运行的可执行文件(COM或EXE)。_”这句话有些错误。Pascal比DOS早大约10年。 - Disillusioned
显示剩余5条评论

8
除了David Schwartz的回答之外,还有一种情况,当在Delphi Unit中定义了通用类型定义时,dcu实际上与其他语言生成的typical obj文件是非常不同的。如果在Delphi Unit中定义了一个通用类型,则编译器将将此代码编译为语法树表示形式而不是机器代码。然后将此语法树表示形式存储在dcu文件中。当通用类型在另一个单位中被使用并实例化时,编译器将使用此表示形式并将其与使用通用类型的单位的语法树“合并”。您可以认为这与方法内联有些相似。顺便说一下,这也是为什么重度使用通用型号的单位需要更长时间进行编译的原因,尽管通用型号是从dcu文件中“链接”进来的。

1
COFF文件格式允许编译器和工具编写者向其中添加自定义字段,这些字段将被整个工具链忽略。因此,您可以轻松地将模板(C++)或通用(.NET/Delphi)类定义注入到标准对象文件中,而不会对其他工具产生不良影响。我想知道C++ Builder在这方面是否与Delphi做了同样的事情? - David Schwartz
2
@David,C++模板和Delphi泛型之间存在巨大的区别。前者实际上是真正的源代码替换,因此在另一个文件中使用时需要模板源代码可用,而Delphi泛型是预编译的,当它们被使用时不需要源代码。假设C++ Builder与C++标准兼容,我会认为C++ Builder处理模板的方式与Delphi泛型非常不同。 - iamjoosy

1

Delphi编译单元包含对象代码和预编译头文件,因此在某种程度上类似于obj文件和.pch/.gch文件。

Delphi源文件的“interface”部分对应于头文件,“implementation”部分创建对象代码。

预编译头文件可以显著减少编译和链接时间。DCU头部分提供了链接信息,指向其他引用单元,无需重新发现。

在Delphi/Turbo Pascal环境中,预编译头支持严格的类型检查,如果使用像.coff或.obj这样的Object文件格式,则需要源代码引用。(在C++中,名称重整提供了类似但不完整的功能)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接