Compiling and Linking

FORTRAN 77 is a compiled language. This means that FORTRAN 77 source code must be converted into the host computer's native instruction set, a format known as machine code. This process is known as compilation. If a program uses functions or subroutines, these must also be compiled into machine code.

Then the machine code for the main program plus all functions and subroutines which it uses must be merged into a single file, called an executable. This process is known as linking.

What happens during compilation?

The FORTRAN 77 compiler processes each source file to convert the FORTRAN 77 statements into their equivalent in the low-level machine code for the target computer. This is normally the computer on which the FORTRAN 77 program is being compiled, but it could be a computer with a different type of CPU, in which case it is known as cross-compilation. In either case, the output is a binary file called an object file. Each source file is compiled into a separate object file.

The object file contains the machine code corresponding to the FORTRAN 77 source code, plus additional information which allows the linker to resolve references to functions and subroutines in other object files.

Most FORTRAN 77 compilers generate reasonably efficient machine code by default, but also provide options to apply higher levels of optimisation. This requires that the compiler analyse the source code in greater depth, so compilation is slower. However, the resulting machine code can often be much more efficient, leading to programs which run more quickly.

Many compilers can also take advantage of specific features of the target CPU, such as the streaming SIMD extension instruction set of Intel and AMD processors. These allow certain types of operation on arrays of numbers to be handled by the CPU's internal vector pipeline.

Creating subroutine libraries

Most operating systems provide a facility for combining a set of object files into a library of pre-compiled functions and subroutines, which can be shared by many programs. This is a very useful technique which avoids the need to attach copies of the source code for commonly-used functions and subroutines to every program.

Libraries are also the normal way to distribute collections of functions and subroutines that have been written by other programmers. One example is the very large and comprehensive collection of numerical algorithms which has been created by the Numerical Algorithms Group. This is a commercial product, and it is provided as a pre-compiled library.

What happens during linking?

The linker takes one or more object files, plus libraries, and combines them to create an executable file.

One of the most important tasks which the linker performs is to resolve references to functions and subroutines from different object files. To understand this, consider a FORTRAN 77 program which consists of two source code files. The first file contains the main program, which calls a subroutine named INVERT. That subroutine is defined in the second file.

When the compiler processes the first file, it finds a call to the INVERT subroutine, which it converts into the machine code instructions for a subroutine call. However, it does not know the location for the machine code of the INVERT subroutine, so it cannot put the location in the object file. Instead, it adds information to the object file to indicate that location of the INVERT is unknown and must be filled in by the linker.

When the compiler processes the second file, it adds information to that object file to indicate that it contains a subroutine named INVERT.

Finally, when the two object files are combined by the linker, the sections of machine code from each object file are copied into the executable file, and then the subroutine call instruction in the main program is updated with the location of the INVERT subroutine.

If the user forgets to include the second object file, then the linker has no information about a subroutine named INVERT, and it cannot create a valid executable file. It will display an error message to tell the user that there is a call to an undefined subroutine.