Next Up Previous Contents
Next: 2.6 Using the Starlink CVS repository
Up: 2 Tools
Previous: 2.4 A few remarks on state
[ID index][Keyword index]

2.5 Preprocessable Fortran

The Starlink build system includes support for preprocessable Fortran, in both autoconf and automake.

As described in Appendix B, the installed version of autoconf is extended with support for preprocessable Fortran, by adding the two macros AC_PROG_FC and AC_PROG_FPP.

You should use AC_PROG_FC in preference to the macro AC_PROG_F77 described in the autoconf manual, since the `FC' support in autoconf is more flexible and more developed than the `F77' support, and the older macro is likely to be deprecated in coming autoconf releases. However a potential problem with the AC_PROG_FC macro is that it searches for Fortran 9x compilers before Fortran 77 ones. Fortran 9x incorporates all of strict Fortran 77 as a subset, but no more, so if you have used any of the common Fortran extensions (which is sometimes unavoidable), you might find the Fortran compiler objecting. In this case, you should use the second optional argument to AC_PROG_FC to specify Fortran 77 as the required dialect:


AC_PROG_FC([], 77)
See Appendix A.12 for full details.

Unlike C, there is no preprocessor defined as part of the Fortran standard, and this is inconvenient if you wish to use a Fortran extension if it is available, but not have the compilation fail if it is absent. This most commonly applies to the READONLY keyword on the Fortran OPEN statement. It is possible to use the C preprocessor, cpp, with Fortran, though not completely reliably, since the underlying syntaxes of C and Fortran are so different that cpp is capable of emitting invalid Fortran in some circumstances.

Both the Sun and GNU Fortran compilers can handle cpp-style preprocessor constructs in a Fortran file, avoiding any separate preprocessing stage. Sun have produced a Fortran preprocessor, fpp, which is available at <http://www.netlib.org/fortran/>: it's freely available, but not open-source. And more often than not we can in fact fall back on simple cpp, as long as we have confined ourselves to the #include, #define and #if... constructs. If it comes to that, such simple preprocessing could be mostly handled with a simple Perl script.

Starlink autoconf and automake between them add support for preprocessable Fortran. Autoconf supplies the AC_PROG_FPP macro described in Appendix A.13, to investigate what compiler and preprocessor are available, and automake works with the results of that test to add appropriate support to the generated Makefile.in.

For example, you might have in your configure.ac file the lines


AC_PROG_FC
AC_PROG_FPP
AC_FC_OPEN_SPECIFIERS(readonly,[access='sequential',recl=1])
and have in your my_io.F the lines

#include <config.h>
      SUBROUTINE MYIO(...)

* blah...

      OPEN ( UNIT = LUCON, FILE = IFCNAM, STATUS = 'OLD',
#ifdef HAVE_FC_OPEN_READONLY
     :       READONLY, 
#endif
#ifdef HAVE_FC_OPEN_ACCESSSEQUENTIALRECL1
     :       ACCESS='SEQUENTIAL',RECL=1,
#endif
     :       FORM = 'UNFORMATTED', IOSTAT = ISTAT )

The file my_io.F is listed in the Makefile.am as one of the _SOURCES of whatever library or application it contributes to, alongside the other Fortran files. If the compiler discovered by the ./configure script can support preprocessor statements itself, then the .F file is treated like any other; if not, and a separate preprocessing stage is required, then the Makefile handles this itself.

Note that we are using .F here as the file extension for preprocessable Fortran: see Appendix A.13 for discussion.

In those cases where you wish the preprocessing step alone, such as when you are generating an include file from a template, you should name the input file with a .F extension also. You will need to include a preprocessing rule in the makefile. The following idiom might be helpful:


# Run a .F file through the fpp preprocessor, to produce a file with
# no extension.
# The following deals with case-insensitive filesystems, on which
# foo.f and foo.F would be the same file.  FPP_OUTPUT is
# either "" (in which case the preprocessor writes to foo.f, and
# the filesystem is presumably case-sensitive) or ">$@".
foo: foo.F
        rm -f foo
        $(FPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
           $(FPPFLAGS) $(CPPFLAGS) foo.F $(FPP_OUTPUT)
        test -f foo || mv foo.f foo
or the following, for a suffix rule

SUFFIXES = .F
.F:
        rm -f $@
        $(FPP) $(DEFAULT_INCLUDES) $(FPPFLAGS) $(CPPFLAGS) $< $(FPP_OUTPUT)
        test -f $@ || mv $(<:.F=.f) $@
 
In this second example, in which we have elided the useful comment, we have declared the .F suffix (we wouldn't have to do this if there were `real' .F sources in this directory), and are using the $< and $@ magic variables.

In second example, we elided most of the flag variables we included in the first one, since we probably don't need them. In case of doubt, copy the .F.f: rule in one of the generated Makefile.in files.

There is a more elaborate example of this in the prm component.


Next Up Previous Contents
Next: 2.6 Using the Starlink CVS repository
Up: 2 Tools
Previous: 2.4 A few remarks on state
[ID index][Keyword index]
The Starlink Build System
Starlink System Note 78
Norman Gray, Peter W Draper, Mark B Taylor, Steven E Rankin
11 April 2005. Release snapshot: $Revision: 1.116 $. Last updated 28 May 2006