A brief introduction to building Fortran Apps

While the Fortran programming language, developed by a team of computer scientists at IBM in the late 1950's, was the first high level language programming language, it has been largely superseded by C and C++ in fields of engineering, and Java and C# in commercial applications. The one place it retains significant use is in the research sciences where large amounts of legacy code is still in use and in computationally intensive tasks, such as weather and climate modeling, computational fluid dynamics, computational chemistry, computational economics, and computational physics.

So lets talk about Fortran.

The current language standard is up to 2003, although the majority of compilers only adhere to the 1990 or 1995 standards. The big break in the language occurred between the 1977 standard and what came after. The 1990+ standard was a significant modernization of the language which added vector operations, pointers, and derived types, among other changes, such as free-form source input and relaxed capitalization rules.

Fortran source files can have a variety of possible suffixes (.f, .F, .f77, .F77, .f95, .f90, .F90, or .F95). The files with a capital suffix (.F, F77, F95, or F90) indicate that the source code should be preprocessed by the C preprocessor (cpp) before being compiled, otherwise the only difference between the suffixes is the adherence to a specific standard.


The source code compilation occurs in two steps

  1. First the source code is compiled using the Fortran compiler $(FC) to create the object files (*.o). These files consist of binary code and data for a source file.
  2. Next, the object files are linked. Linkers combine multiple object files along with along with any external objects such as libraries. The linking stage, called transparently by the compiler, calls the linker ld command.
  3. Lastly, the loader , and loads everything into memory.
With modern compilers, all of these steps happen implicitly when the user runs the compiler.

The most basic build command looks like this:

$(FC) myprogram.f -o myprogram.exe

It builds the executable myprogram.exe from the source myprogram.f. The -o flag indicates the name of the executable. If omitted, the default name is a.out.

Next, suppose you have a c code and want to link to the math library libm.a. Because the math library is the library path variable you only need to indicate the name of the library with the lowercase -l flag such as

$(CC) -o myprogram.exe -lm myprogram.c

Note that the prefix lib and suffix .a are not included when the library is named. Also note that there are no spaces between the lowercase -l flag and the library name.

Suppose now that the library is not part of the system libraries, such as the netcdf IO libraries. In this case it is necessary to tell the compiler where to find this library. This is done with the uppercase -L library path flag.

$(FC) -o myprogram.exe myprogram.F -L/mylibrarypath/lib -lnetcdf

Because the name of the source code is followed by capital .F suffix, the source code was preprocessed using CPP processor before compiling.

This build looks for the library libnetcdf.a in the directory /mylibrarypath/lib. If the linker finds the library, the build succeeds. If the linker cannot find the library, or the indicated library does not contain the library element or symbol being called, the linker will give you a message roughly saying that you have unresolved or undefined symbols. (See the blog entry on linking and loading for more information on that).

To compile a source file without creating the executable, thus only creating the object file, use the -c flag. Suppose there is a second file called utility.f, to just produce its object file use

$(FC) -c utility.f

Now that we have the object file for utility.f, we can build the executable myprogram.exe by linking to utility.o with the command

$(FC) -o myprogram.exe myprogram.F utility.o -L/mylibrarypath/lib -lnetcdf

or if there are multiple files to link, use a wild card to represent the other object files.

$(FC) -o myprogram.exe myprogram.F *.o -L/mylibrarypath/lib -lnetcdf

No comments:

Post a Comment