为什么首先编译为目标文件?

时间:2011-03-12 16:40:34

标签: c++ c compilation fortran object-files

去年,我开始在Fortran的一所研究型大学工作。我以前的大部分经验都是使用PHP或旧ASP等网络语言,所以我是新手编译语句

我正在修改两个不同的代码。

在创建可执行文件之前,一个显式语句从模块创建.o文件(例如gfortran -c filea.f90)。

另一个 直接创建可执行文件(有时创建.mod文件,但没有.o文件,例如gfortran -o executable filea.f90 fileb.f90 mainfile。 F90)。

  • 是否有理由(除了,可能还有Makefiles)一种方法优先于另一种方法?

5 个答案:

答案 0 :(得分:29)

首先编译到目标文件称为单独编译。有许多优点和一些缺点。

优点:

  • 易于将目标文件(.o)转换为库并稍后链接到它们
  • 许多人可以同时处理不同的源文件
  • 编译速度更快(当源未更改时,您不会反复编译相同的文件)
  • 目标文件可以从不同的语言源创建,并在以后的某个时间链接在一起。为此,目标文件只需使用相同的格式和兼容的调用约定。
  • 单独编译可以分布系统范围的库(OS库,语言标准库或第三方库)静态或共享。

缺点:

  • 编译器无法执行某些优化(如优化函数),链接器不关心;但是,许多编译器现在都包含执行“链接时间优化”的选项,这在很大程度上抵消了这个缺点。但这仍然是系统库和第三方库的一个问题,特别是对于共享库(不可能优化掉每次运行时可能发生变化的组件部分,但是其他技术,如JIT编译可能会缓解这种情况)。
  • 在某些语言中,程序员必须提供某种标题,供其他与该对象链接的标题使用。例如,在C中,您必须提供.h个文件以与目标文件一起使用。但无论如何这都是好习惯。
  • 在基于文本的语言中包括C或C ++,如果更改函数原型,则必须在两个位置更改它。一旦进入头文件,一旦进入实现文件。

答案 1 :(得分:14)

如果项目包含几百个源文件,则每次更改时都不希望重新编译全部。通过将每个源文件编译为单独的目标文件并仅重新编译受更改影响的源文件,您可以花费从源代码更改到新可执行文件的最短时间。

make是用于跟踪此类依赖项并在某些内容发生更改时重新创建二进制文件的常用工具。通常,您可以设置每个源文件所依赖的内容(这些依赖项通常由编译器生成 - 以适合make的格式),并让make处理创建最新二进制文件的详细信息。

答案 2 :(得分:5)

.o文件是对象文件。它是最终节目的中间代表。

具体来说,通常,.o文件具有已编译的代码,但它没有的是所有不同例程或数据的最终地址。

程序运行之前需要的东西之一就像记忆图像一样。

例如。

如果你有你的主程序并且它调用例程A.(这是人造堡垒,我几十年没碰过,所以在这里和我一起工作。)

PROGRAM MAIN
INTEGER X,Y
X = 10
Y = SQUARE(X)
WRITE(*,*) Y
END

然后你有SQUARE功能。

FUNCTION SQUARE(N)
SQUARE = N * N
END

是单独编译的单位。你可以看到,当编译MAIN时,它不知道“SQUARE”在哪里,它的地址是什么。它需要知道,当它调用微处理器JUMP SUBROUTINE(JSR)指令时,该指令有一些地方可以去。

.o文件已经有JSR指令,但它没有实际值。这是在链接或加载阶段的后期(取决于您的应用程序)。

因此,MAINS .o文件包含main的所有代码,以及它想要解析的引用列表(特别是SQUARE)。 SQUARE基本上是独立的,它没有任何引用,但与此同时,它没有关于它在内存中的位置的地址。

链接器将从.o文件中取出所有内容并将它们合并到一个exe文件中。在过去,编译的代码实际上是一个内存映像。该程序将从某个地址开始,然后简单地加载到RAM批发中,然后执行。因此,在该场景中,您可以看到链接器获取两个.o文件,将它们连接在一起(以获取SQUARE的实际地址),然后它将返回并在MAIN中找到SQUARE引用,并填写地址。

现代链接器并没有那么远,并且将最终处理的大部分推迟到程序实际加载时。但这个概念是相似的。

通过编译.o文件,您最终得到可重复使用的逻辑单元,然后在执行之前由链接和加载进程组合。

另一个不错的方面是.o文件可以来自不同的语言。只要调用机制是兼容的(即参数如何传递到函数和过程以及从函数和过程传递),那么一旦编译成.o,源语言就变得不那么相关了。您可以使用FORTRAN代码链接,组合C代码,比如说。

在PHP等等中,该过程是不同的,因为所有代码都在运行时加载到单个图像中。你可以考虑类似于使用PHP的FORTRANs .o文件包括将文件组合成一个大而有凝聚力的整体的机制。

答案 3 :(得分:2)

除编译时间外,另一个原因是编译过程是multi-step process

The multi-part process.

目标文件只是该进程的一个中间输出。它们最终将被链接器用于生成可执行文件。

答案 4 :(得分:1)

我们编译到目标文件,以便能够将它们链接在一起以形成更大的可执行文件。这不是唯一的方法。

还有一些编译器没有这样做,而是编译到内存并立即执行结果。早些时候,当学生不得不使用大型机时,这是标准配置。 Turbo Pascal也是这样做的。