Preprocessors
Octopus uses the C preprocessor for Fortran code, as controlled by the FCCPP
variable for the configure script. Linux systems generally have cpp
installed at /lib/cpp
, which is usually the one provided by GCC, and this is the default that will be used by configure
. This one will work for Octopus, as will using directly GNU’s cpp
, or through the C compiler with gcc -E
. (However, the default cpp
on Mac OS will not work; use clang -E -ansi
instead.) Generally -ansi
should be given as an argument, which will avoid deletion of //
“comments” but which are actually string concatenation in Fortran (do not use the -C
flag). C compilers in general will do C preprocessing only, if passed the -E
flag. The configure script will automatically decide whether the -P
flag is required, avoiding insertion of line numbers in the output: generally, only g95
objects to these lines and requires the flag. In some cases, files will be parsed differently according to the suffix; in this case, you may need to add the -x c
flag to cpp
to tell it to treat the file as C. Another problem to watch out for is some cpp versions might remove whitespace and thus illegally combine what were supposed to be separate Fortran lines.
A basic requirement for a cpp in Fortran is:
The file below, when named conftest.f90
, and preprocessed as $FCCPP conftest.f90
, will contain hi
and rout // ine
(no space between //
).
#define ADD_I(x) x -- i
ADD_I(h)
#define PUSH_SUB(x) x // ine
PUSH_SUB(rout)
For example, with cpp -ansi conftest.F90
, I get:
# 1 "conftest.F90"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "conftest.F90"
hi
rout // ine
We try to find an acceptable preprocessor in the configure script with the following m4 macro (from m4/fortran.m4
), which is licensed under GPL 2+, and also used in libxc and APE.
AC_DEFUN([ACX_FCCPP],[
# "gcc -E -x c" means treat the file as if it were C. For some reason, when gcc identifies the source
# as Fortran, it will not concatenate tokens in preprocessing, so we must trick it.
for FCCPP_base in "$FCCPP" "/lib/cpp" "$CPP" "$CPP -x c" "`which cpp`"; do
# cycle if blank
if test -z "$FCCPP_base"; then
continue
fi
for FCCPP in "$FCCPP_base" "$FCCPP_base -ansi"; do
AC_MSG_CHECKING([whether $FCCPP is usable for Fortran preprocessing])
acx_fpp_ok=yes
ACX_GREP_FCCPP([anything], AC_LANG_PROGRAM([],[anything]),
[], [acx_fpp_ok=no; AC_MSG_RESULT([preprocessor cannot be run]); break])
# very unlikely that adding -ansi will allow it to be run at all
ACX_GREP_FCCPP([hi], AC_LANG_PROGRAM([],[
#define ADD_I(x) x ## i
ADD_I(h)]),
[], [acx_fpp_ok=no; AC_MSG_RESULT([preprocessor does not concatenate tokens])])
# in Fortran this is string concatenation, must not be stripped
# some cpp's (e.g. icc -E -ansi) might actually insert a space between // too which is not acceptable
ACX_GREP_FCCPP([rout // ine], AC_LANG_PROGRAM([],[
#define PUSH_SUB(x) x // ine
PUSH_SUB(rout)]),
[], [acx_fpp_ok=no; AC_MSG_RESULT([preprocessor mangles C++ style comment])])
if test x"$acx_fpp_ok" = xyes; then
AC_MSG_RESULT([yes])
break
fi
done
if test x"$acx_fpp_ok" = xyes; then
break
fi
done
if test x"$acx_fpp_ok" = xno; then
AC_MSG_ERROR([Could not find preprocessor usable for Fortran.])
fi
AC_SUBST(FCCPP)
])