School of GeoSciences

School of GeoSciences


fmkmf: Makefiles for Fortran 9x

The perl program fmkmf constructs a make file for a Fortran 90 (or 95) program that uses modules. The shell script does the same thing, but more slowly. Why bother to do such a thing? The main reason is that the make utility really has C or FORTRAN 77 in mind. In these languages, you can compile your various source files in any order before you do the link step. A typical make file looks like this:

    foo:foo.o bar.o baz.o
    <-tab->cc -o foo foo.o bar.o baz.o

    <-tab->cc -c foo.c
    <-tab->cc -c bar.c
    <-tab->cc -c baz.c

In Fortran 90, however, you have to compile a sourcefile containing a module before you compile any source files which use that module. (Why? So that compile-time type checking can be done at subprogram calls, eliminating those horrid Bus Error crashes.) Soooo, if main.f90 contains the line use foomod and the file foo.f90 contains the line module foomod then you need a makefile like this:

      main:main.o foo.o
      <-tab->f90 -o main.o foo.o

      main.o:main.f90 foo.o #Note main.o depends on foo.o
      <-tab->f90 -c main.o

      <-tab->f90 -c foo.f90

The important difference is that main.o depends on foo.o, even though the command to generate main.o doesn't seem to use foo.o. This dependency forces foo.f90 to be compiled before main.f90.

If your Fortran 90 project has a messy dependency tree of modules and use statements, then writing a make file which compiles things in the right order is a royal pain in the neck. Now, however, fmkmf uses the magic of grep, sed and bash perl to do it all for you. In the above example you would just type

fmkmf main.f90 >makefile

...and your makefile would be ready to go!

You can get the shell script here and the perl script here; there are also some instructions . Meteorology dept folk: just add /home/hcp/bin to your PATH and fmkmf should become available.

I'm not doing version numbers, but I'll make a note here when I fix bugs.

  • ?? August 1999: First release
  • 16 Sept 1999: Fixed problems with module files in other directories
  • 30 Sept 1999:
    • Fixed problem when search path contains more than 2 directories
    • Fixed problem occurring if one module has a name that is a subset of another (e.g. foo and foo2). Thanks to Ed D'Azevedo for spotting it!
    • Fixed a bash-ism so it works in Sun's version of sh
    • Added environment variables which can be used instead of command line options
  • 22 Dec 1999: Added environment variable FMKMF_GREP: set this to a version of grep which works, instead of having to edit the script.
  • 20 Jan 2000: Added perl version. It is cleaner and MUCH faster. Any future embellishments will probably only be done to the perl version.
  • 24 Jan 2000: Fixed a small bug in the perl version. Fixed a larger bug in the shell version. (This calls itself recursively. It now uses sh to do this, so it always knows what it is called and does not rely on being called fmkmf)
  • 29 Feb 2000: Changed fmkmf so it adds a blank line to the end of the make file. Some versions of make need this or the last target (clean) doesn't work.
  • 15 May 2000: Changed the shell verson so it works if you have use foo, only:bar in your source code. Thanks to M. R. Schaferkotter for the fix. The perl version is unchanged -- it seems to do the Right Thing anyway. Did I mention that it is also a lot faster?
  • 30 Aug 2000: Changed the perl version so that
    • it accepts tabs on the line with the Use statement in. You should get rid of those tabs, though. I think they are not standard conforming. Thanks to Simon J. Rees for the suggestion.
    • The generated make file uses a makefile macro called F90 for the f90 command and its flags. This makes editing the makefile afterwards a much less tiresome job.
  • 22 Feb 2006. Changed perl version so that it accepts an arbitrary number of tabs and spaces between use or module and the following name. Thanks to Ron Crump for spotting it.

If fmkmf is not exactly what you are after, have a look at these alternatives: