Fortran Programming Tools under Linux
Although demand for Linux support of punch card readers has been light, there are still quite a of number of us who learned to write computer code in the days when programming prowess was judged by the size of your card deck in the “360” queue. Of course, back then, Fortran was the high level language of choice for engineers and scientists, and it was the only programming language many of us (including myself) ever learned.
Many (well, maybe most) argue that Fortran is old-fashioned compared to modern computer languages; but Fortran-trained engineers, researchers, and scientists pay little heed to these arguments. We view programming as simply a tool to accomplish our goals, and we are most productive with familiar tools; therefore, we stick with Fortran. Fortunately for us, Linux offers a rich selection of Fortran programming tools.
This article surveys some of the basic tools available in Linux for Fortran users migrating to Linux from a non-Unix environment, such as VAX/VMS or DOS. My goal is to convince fellow “Fortran Fogeys” that they can take the Linux plunge without sacrificing their “native” programming capability. (It is worth noting that Linux users ranked Fortran fifth out of twenty-five programming languages in a recent Linux Journal survey.)
Several options exist for compiling FORTRAN 77 programs under Linux. The most established method is a public domain Fortran-to-C converter developed by AT&T Bell Laboratories and Bellcore. This Fortran converter, known as f2c, is normally included in all the popular Linux distributions. A second option is the newly released GNU Fortran compiler known as g77 (see sidebar). Because GNU g77 is still being beta-tested and is not as widely distributed as f2c, this article is restricted to the use of f2c. Finally, there are at least two commercial Fortran compilers available for Linux: NAG's F90 Fortran 90 compiler and Microway's NDP Fortran compiler.
The f2c converter reads the FORTRAN 77 source file and converts it into equivalent C language source code. This sounds like an impossible feat, but the f2c developers have done a remarkable implementation. The second step involves compiling the resulting C code using the GNU C compiler, gcc. Included in this step is the automatic creation of an executable file with proper links to the necessary static and shared libraries.
As usual with Unix, the new user is faced with a bewildering array of options associated with f2c and gcc. Fortunately, we have been protected from the “raw” power of Unix by a bash shell script called f77. This script has fewer options, and it makes compiling Fortran programs easy by serving as an interface to the f2c/gcc combination. In my Slackware distribution, the f77 script is located in the /usr/bin directory. I don't have a man page for f77, though it may exist. Fortunately, all the information you need to get started with f77 is listed in the first 18 lines of the f77 script itself.
The simple program listed below illustrates the basics of compiling Fortran programs under Linux. (I know the subroutine is not really necessary, but I have included it to illustrate some points later in the article.)
C============================== C Simple Program to Illustrate C Fortran Programming Tools C============================== PROGRAM F77DEMO DIMENSION X(100), Y(100) PI=2.*ACOS(0.) N=100 DO 10 I=1,N X(I)=I*(2*PI/N) 10 CONTINUE CALL TRIG(N,X,Y) DO 20 J=1,5 PRINT 15, X(J), Y(J) 15 FORMAT(2X,2F8.3) 20 CONTINUE STOP END C SUBROUTINE TRIG(N,X,Y) DIMENSION X(1), Y(1) DO 10 I=1,N Y(I) = SIN(X(I))*EXP(-X(I)) 10 CONTINUE RETURN END
Compiling and linking our example program, named f77demo.f, is easy (in this article, the commands that you type are preceded by the shell prompt $.):
$ f77 -o demoexe f77demo.f f2ctmp_f77demo.f: MAIN f77demo: trig:
No errors are listed, so we know the MAIN program and subroutine trig compiled successfully. The executable file, demoexe, is ready to run by simply typing demoexe on the command line. (If demoexe is not in your $PATH, you will have to indicate where it is—in this case, by typing ./demoexe.) In the compilation process, the f77 script also created an object module with the name f77demo.o.
The f77 script expects the Fortran source code to be in a file having the .f extension. If you are porting code having a different file extension, such as .FOR or .FTN, change it to .f. (When porting DOS files, use the fromdos program to strip line-ending Control-M and file-ending Control-Z characters. If you don't have the fromdos program, try using the shell script in Listing 1.) The -o switch tells the script to create an executable file having the name demoexe (in this example). Without this switch, the executable file name defaults to a.out.
More than one source file can be compiled into the executable module using f77. For example, if we break our example program into two files called maindemo.f and trig.f, our command line would be:
$ f77 -o demoexe maindemo.f trig.f
This usage might be typical for programs containing only a few subroutines. For large program development, the make utility can be used for more efficiency. [See Linux Journal Issue 6 or read the GNU make manual. —ED] The f77 script also allows you to compile Fortran, C, and assembly source files at the same time by including the source file names on the command line. This activity will be left as an exercise for the reader...
Among the several f77 command line options there are two that are particularly useful. The first is the -c option. This option tells f77 to create an object module, but not an executable. For example, the command
$ f77 -c trig.f
will result in the creation of the object file trig.o in your present working directory. Why would we want to do this? One reason is to create our own custom object libraries of Fortran-callable subroutines using the library manager available with Linux. Another reason is to create dynamic links between Fortran subroutines and other Linux programs (more later!).
The second important f77 switch is the -llib option. This option is used to tell the gcc compiler to search for subroutine calls in user-supplied libraries normally not examined by gcc. Static object libraries have the naming convention libmystuff.a where the name used in the -l option is the part wedged between lib and .a. Shared libraries also begin with lib, but have an extension similar to .so.#.##.#, where the #-sign is replaced by numbers corresponding to the library version.
Including libraries when compiling a Fortran program is illustrated by the command:
$ f77 -o foobar foobar.f -lmystuff -lmorestuff
During compilation the gcc compiler will search the libmystuff.a and libmorestuff.a libraries (in that order) for any unresolved subroutine and function calls. The order of the libraries is important. Suppose each library contained an object module named gag. Any calls to gag in the program foobar.f will be resolved by the gag object module in the first library, libmystuff.a.
It is important to remember that the -l option should always follow the list of source files. By default, f77 searches the f2c (libf2c.so.0) library and the math intrinsics library m (libm.so.4) before searching libraries specified on the command line. These libraries provide system calls, Fortran I/O functions, mathematical intrinsic functions, and run-time initialization.
A common gcc compiler error stems from the compiler being unable to locate a user-specified library. If this happens, you will need to determine which directories are searched for libraries. Then, either relocate your library to a valid library directory or create a symbolic link to your library from one of the library directories. You can also add directories to the library path on the f77 command line using the -L switch.
The above examples should be enough to get you started making use of Fortran in Linux using f77. Of course, more flexibility is offered using the f2c/gcc combination because more options are available. (f2c and gcc have good man pages, so I don't need to describe them here.) For example, the command:
$ f2c f77demo.f
creates the file f77demo.c, and:
$ gcc -o demoexe f77demo.c -lf2c -lm
creates the demoexe executable, and together they are equivalent to the f77 command shown earlier. Notice that we had to include the f2c and m libraries explicitly this time—and they must be listed in this order. Failure to include these two libraries would cause the compiler to complain. For example, leaving off the -lm option for our example program produces the errors:
Undefined symbol _exp referenced from text segment Undefined symbol _sin referenced from text segment
because the references to the sine and exponential functions in subroutine TRIG could not be resolved.
Finally, you may be interested in trying out a newer Perl driver script called fort77. It is billed as a replacement for f77, and it includes support for debugging, a feature missing from f77. I haven't tried fort77 yet, but it is definitely on my list of things to do.
- Resurrecting the Armadillo
- High-Availability Storage with HA-LVM
- Real-Time Rogue Wireless Access Point Detection with the Raspberry Pi
- Localhost DNS Cache
- March 2015 Issue of Linux Journal: System Administration
- DNSMasq, the Pint-Sized Super Dæmon!
- Days Between Dates: the Counting
- The Usability of GNOME
- You're the Boss with UBOS
- Linux for Astronomers