autoconf-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

New macro AC_FC_PP_SRCEXT for preprocessed file extensions.


From: Ralf Wildenhues
Subject: New macro AC_FC_PP_SRCEXT for preprocessed file extensions.
Date: Sat, 5 Mar 2011 19:59:27 +0100
User-agent: Mutt/1.5.20 (2010-08-04)

Fortran and preprocessing is another long story, not even starting with
COCO.

Of those Fortran 90+ compilers that I can get hold of, all provide some
way or another to enable preprocessing of source files with all kinds of
file name extensions.  It just isn't easy sometimes (esp. older gfortran
took some searching).  Just like in the AC_FC_SRCEXT case, the most
general case is that you need a different flag per file name extension
(thanks to IBM).

I'm guessing that it is possible to go with a minimal common denominator
of only using .F (not even .F90 is universal if I read the Sun manual
correctly), but relying on case-sensitive file systems is not cool and
telling other developers to mass-rename their files does not get you
high karma either.

So, here's what I came up with.  The macro is the sister of AC_FC_SRCEXT
and you can just replace its usage in projects where you want files to
be preprocessed.  In projects where it is *necessary* to disable the
preprocessor for some files with the same suffixes, I suppose you can
still play games with configure cache variables and manually written
makefile rules again; but other than that, I suppose Automake can
support all of this seamlessly eventually.  (Meanwhile, overriding the
respective inference rules is fairly straightforward, see below.)

I'm unsure about the macro name.  AC_FC_PP_SRCEXT or AC_FCPP_SRCEXT?
Or maybe AC_FC_CPP_SRCEXT?  Or preprocessing as additional optional
argument for AC_FC_SRCEXT?

Another thing I'm not totally sure of is: should AC_FC_SRCEXT semantics
be modified to try to explicitly turn off preprocessing?  Seems a bit
risky.  (Or yet another macro AC_FC_NO_PP_SRCEXT or tri-state option?)

Of course, good support for preprocessed Fortran should also have a
macro to select the preprocessor, only run that, etc.  Actually, that
turned out to be quite a mine field: while you can often pass some set
of options (a la -traditional-cpp -C -P) to cpp to make it behave with
Fortran code, it would be nicer to actually make use of whatever the
$FC compiler calls out to, if possible (if only to use the same spelling
of -D or -WF,-D arguments).  Now, several compilers provide a -P flag to
only preprocess, but then they save the output in a file, rather than
using stdout.  :-/

In projects so far, I've used either the proposed macro below, or
something like this as workaround:

# Treat all .f90 files as preprocessed Fortran.
.f90.o:
        $(FCCPP) $(FCDEFS) $(FCDEFAULT_INCLUDES) $(AM_FCCPPFLAGS) $(FCCPPFLAGS) 
$< > $*.pp.f90
        $(FCCOMPILE) -c -o $@ $(FCFLAGS_f90) $*.pp.f90

and set FCCPP to some combination of fpp or cpp and flags.  I'm not sure
whether portability would in the end require going this way for some
older compilers.

Further, I'm not sure how big semantic differences between preprocessors
are, or whether we need to expose preference fpp vs cpp to the user.
I've seen flags as to whether macros are also replaced outside of lines
starting with '#'.  Might be good to document a minimal common
denominator...

I haven't pushed this patch yet; I'd really appreciate some comments.

Thanks,
Ralf

    New macro AC_FC_PP_SRCEXT for preprocessed file extensions.
    
    * lib/autoconf/fortran.m4 (AC_FC_PP_SRCEXT): New macro.
    * lib/autom4te.in (Automake-preselections): Preselect it.
    * doc/autoconf.texi (Fortran Compiler): Document it, rewriting
    the documentation for AC_FC_SRCEXT along the way.
    * tests/fortran.at (AC_FC_PP_SRCEXT usage): New test.
    * tests/mktests.sh: Exclude the macro from default testing.
    * NEWS: Update.

diff --git a/NEWS b/NEWS
index 6a1771d..ccf6bf2 100644
--- a/NEWS
+++ b/NEWS
@@ -16,6 +16,7 @@ GNU Autoconf NEWS - User visible changes.
 
     AC_FC_CHECK_BOUNDS to enable array bounds checking
     AC_F77_IMPLICIT_NONE and AC_FC_IMPLICIT_NONE to disable implicit integer
+    AC_FC_PP_SRCEXT for preprocessed Fortran source files extensions
 
 * Noteworthy changes in release 2.68 (2010-09-22) [stable]
   Released by Eric Blake, based on git versions 2.67.*.
diff --git a/doc/autoconf.texi b/doc/autoconf.texi
index b552883..f980d29 100644
--- a/doc/autoconf.texi
+++ b/doc/autoconf.texi
@@ -8193,47 +8193,68 @@ Fortran Compiler
 
 @defmac AC_FC_SRCEXT (@var{ext}, @ovar{action-if-success}, @
   @dvar{action-if-failure, AC_MSG_FAILURE})
address@hidden AC_FC_PP_SRCEXT (@var{ext}, @ovar{action-if-success}, @
+  @dvar{action-if-failure, AC_MSG_FAILURE})
 @acindex{FC_SRCEXT}
address@hidden
address@hidden address@hidden
address@hidden address@hidden
 By default, the @code{FC} macros perform their tests using a @file{.f}
 extension for source-code files.  Some compilers, however, only enable
 newer language features for appropriately named files, e.g., Fortran 90
-features only for @file{.f90} files.  On the other hand, some other
-compilers expect all source files to end in @file{.f} and require
-special flags to support other file name extensions.  The
address@hidden macro deals with both of these issues.
-
-The @code{AC_FC_SRCEXT} tries to get the @code{FC} compiler to accept files
-ending with the extension address@hidden (i.e., @var{ext} does @emph{not}
-contain the dot).  If any special compiler flags are needed for this, it
-stores them in the output variable @address@hidden  This
-extension and these flags are then used for all subsequent @code{FC} tests
-(until @code{AC_FC_SRCEXT} is called again).
+features only for @file{.f90} files, or preprocessing only with
address@hidden files or maybe other upper-case extensions.  On the other
+hand, some other compilers expect all source files to end in @file{.f}
+and require special flags to support other file name extensions.  The
address@hidden and @code{AC_FC_PP_SRCEXT} macros deal with these
+issues.
+
+The @code{AC_FC_SRCEXT} macro tries to get the @code{FC} compiler to
+accept files ending with the extension @address@hidden (i.e.,
address@hidden does @emph{not} contain the dot).  If any special compiler
+flags are needed for this, it stores them in the output variable
address@hidden@var{ext}}.  This extension and these flags are then used
+for all subsequent @code{FC} tests (until @code{AC_FC_SRCEXT} or
address@hidden is called another time).
 
 For example, you would use @code{AC_FC_SRCEXT(f90)} to employ the
 @file{.f90} extension in future tests, and it would set the
 @code{FCFLAGS_f90} output variable with any extra flags that are needed
 to compile such files.
 
-The @address@hidden can @emph{not} be simply absorbed into
address@hidden, for two reasons based on the limitations of some
-compilers.  First, only one @address@hidden can be used at a
+Similarly, the @code{AC_FC_PP_SRCEXT} macro tries to get the @code{FC}
+compiler to preprocess and compile files with the extension
address@hidden@var{ext}}.  When both @command{fpp} and @command{cpp} style
+preprocessing are provided, the former is preferred, as the latter may
+treat continuation lines, @code{//} tokens, and white space differently
+from what some Fortran dialects expect.  Conversely, if you do not want
+files to be preprocessed, use only lower-case characters in the file
+name extension.  Like with @code{AC_FC_SRCEXT(f90)}, any needed flags
+are stored in the @address@hidden variable.
+
+The @address@hidden flags can @emph{not} be simply absorbed
+into @code{FCFLAGS}, for two reasons based on the limitations of some
+compilers.  First, only one @address@hidden can be used at a
 time, so files with different extensions must be compiled separately.
-Second, @address@hidden must appear @emph{immediately} before
+Second, @address@hidden must appear @emph{immediately} before
 the source-code file name when compiling.  So, continuing the example
 above, you might compile a @file{foo.f90} file in your makefile with the
 command:
 
 @example
 foo.o: foo.f90
-     $(FC) -c $(FCFLAGS) $(FCFLAGS_f90) '$(srcdir)/foo.f90'
+       $(FC) -c $(FCFLAGS) $(FCFLAGS_f90) '$(srcdir)/foo.f90'
 @end example
 
-If @code{AC_FC_SRCEXT} succeeds in compiling files with the @var{ext}
-extension, it calls @var{action-if-success} (defaults to nothing).  If
-it fails, and cannot find a way to make the @code{FC} compiler accept such
-files, it calls @var{action-if-failure} (defaults to exiting with an
-error message).
+If @code{AC_FC_SRCEXT} or @code{AC_FC_PP_SRCEXT} succeeds in compiling
+files with the @var{ext} extension, it calls @var{action-if-success}
+(defaults to nothing).  If it fails, and cannot find a way to make the
address@hidden compiler accept such files, it calls @var{action-if-failure}
+(defaults to exiting with an error message).
 
+The @code{AC_FC_SRCEXT} and @code{AC_FC_PP_SRCEXT} macros cache their
+results in @address@hidden and
address@hidden@var{ext}} variables, respectively.
 @end defmac
 
 @defmac AC_FC_FREEFORM (@ovar{action-if-success}, @dvar{action-if-failure, @
diff --git a/lib/autoconf/fortran.m4 b/lib/autoconf/fortran.m4
index 84f3162..13207eb 100644
--- a/lib/autoconf/fortran.m4
+++ b/lib/autoconf/fortran.m4
@@ -1176,6 +1176,105 @@ AC_LANG_POP(Fortran)dnl
 ])# AC_FC_SRCEXT
 
 
+# AC_FC_PP_SRCEXT(EXT, [ACTION-IF-SUCCESS], [ACTION-IF-FAILURE])
+# --------------------------------------------------------------
+# Like AC_FC_SRCEXT, set the source-code extension used in Fortran (FC) tests
+# to EXT (which defaults to f).  Also, look for any necessary additional
+# FCFLAGS needed to allow this extension for preprocessed Fortran, and store
+# them in the output variable FCFLAGS_<EXT> (e.g. FCFLAGS_f90 for EXT=f90).
+# If successful, call ACTION-IF-SUCCESS.  If unable to compile preprocessed
+# source code with EXT, call ACTION-IF-FAILURE, which defaults to failing with
+# an error message.
+#
+# Some compilers allow preprocessing with either a Fortran preprocessor or
+# with the C preprocessor (cpp).  Prefer the Fortran preprocessor, to deal
+# correctly with continuation lines, `//' (not a comment), and preserve white
+# space (for fixed form).
+#
+# (The flags for the current source-code extension, if any, are stored in
+# $ac_fcflags_srcext and used automatically in subsequent autoconf tests.)
+#
+# For ordinary extensions like f90, etcetera, the modified FCFLAGS
+# are needed for IBM's xlf*.  Also, for Intel's ifort compiler, the
+# $FCFLAGS_<EXT> variable *must* go immediately before the source file on the
+# command line, unlike other $FCFLAGS.  Ugh.
+#
+# Known extensions that enable preprocessing by default, and flags to force it:
+# GNU: .F .F90 .F95 .F03 .F08, -cpp for most others,
+#      -x f77-cpp-input for .f77 .F77; -x f95-cpp-input for gfortran < 4.4
+# SGI: .F .F90, -ftpp or -cpp for .f .f90, -E write preproc to stdout
+#      -macro_expand enable macro expansion everywhere (with -ftpp)
+#      -P preproc only, save in .i, no #line's
+# SUN: .F .F95, -fpp for others; -xpp={fpp,cpp} for preprocessor selection
+#      -F preprocess only (save in lowercase extension)
+# IBM: .F .F77 .F90 .F95 .F03, -qsuffix=cpp=EXT for extension .EXT to invoke 
cpp
+#      -WF,-qnofpp -WF,-qfpp=comment:linecont:nocomment:nolinecont
+#      -WF,-qlanglvl=classic or not -qnoescape (trigraph problems)
+#      -d no #line in output, -qnoobject for preprocessing only (output in .f)
+#      -q{no,}ppsuborigarg substitute original macro args before expansion
+# HP:  .F, +cpp={yes|no|default} use cpp, -cpp, +cpp_keep save in .i/.i90
+# PGI: -Mpreprocess
+# Absoft: .F .FOR .F90 .F95, -cpp for others
+# Cray: .F .F90 .FTN, -e Z for others; -F enable macro expansion everywhere
+# Intel: .F .F90, -fpp for others, but except for .f and .f90, -Tf may also be
+#        needed right before the source file name
+# PathScale: .F .F90 .F95, -ftpp or -cpp for .f .f90 .f95
+#         -macro_expand for expansion everywhere, -P for no #line in output
+# Lahey: .F .FOR .F90 .F95, -Cpp
+# NAGWare: .F .F90 .F95, .ff .ff90 .ff95 (new), -fpp for others
+# Compaq/Tru64: .F .F90, -cpp, -P keep .i file, -P keep .i file
+# f2c: .F, -cpp
+# g95: .F .FOR .F90 .F95 .F03, -cpp -no-cpp, -E for stdout
+AC_DEFUN([AC_FC_PP_SRCEXT],
+[AC_LANG_PUSH(Fortran)dnl
+AC_CACHE_CHECK([for Fortran flag to compile preprocessed .$1 files],
+               ac_cv_fc_pp_srcext_$1,
+[ac_ext=$1
+ac_fcflags_pp_srcext_save=$ac_fcflags_srcext
+ac_fcflags_srcext=
+ac_cv_fc_pp_srcext_$1=unknown
+case $ac_ext in #(
+  [[fF]]77) ac_try=f77-cpp-input;; #(
+  *) ac_try=f95-cpp-input;;
+esac
+for ac_flag in none -ftpp -fpp -Tf "-fpp -Tf" -xpp=fpp -Mpreprocess "-e Z" \
+               -cpp -xpp=cpp -qsuffix=cpp=$1 "-x $ac_try" +cpp -Cpp; do
+  test "x$ac_flag" != xnone && ac_fcflags_srcext="$ac_flag"
+  AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [[
+#if 0
+#include <ac_nonexistent.h>
+      choke me
+#endif]])],
+    [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [[
+#if 1
+#include <ac_nonexistent.h>
+      choke me
+#endif]])],
+       [],
+       [ac_cv_fc_pp_srcext_$1=$ac_flag; break])])
+done
+rm -f conftest.$ac_objext conftest.$1
+ac_fcflags_srcext=$ac_fcflags_pp_srcext_save
+])
+if test "x$ac_cv_fc_pp_srcext_$1" = xunknown; then
+  m4_default([$3],
+             [AC_MSG_ERROR([Fortran could not compile preprocessed .$1 
files])])
+else
+  ac_fc_srcext=$1
+  if test "x$ac_cv_fc_pp_srcext_$1" = xnone; then
+    ac_fcflags_srcext=""
+    FCFLAGS_[]$1[]=""
+  else
+    ac_fcflags_srcext=$ac_cv_fc_pp_srcext_$1
+    FCFLAGS_[]$1[]=$ac_cv_fc_pp_srcext_$1
+  fi
+  AC_SUBST(FCFLAGS_[]$1)
+  $2
+fi
+AC_LANG_POP(Fortran)dnl
+])# AC_FC_PP_SRCEXT
+
+
 # AC_FC_FREEFORM([ACTION-IF-SUCCESS], [ACTION-IF-FAILURE = FAILURE])
 # ------------------------------------------------------------------
 # Look for a compiler flag to make the Fortran (FC) compiler accept
diff --git a/lib/autom4te.in b/lib/autom4te.in
index 05b325f..0f86842 100644
--- a/lib/autom4te.in
+++ b/lib/autom4te.in
@@ -44,6 +44,7 @@ args: --preselect AC_CONFIG_LIBOBJ_DIR
 args: --preselect AC_CONFIG_LINKS
 args: --preselect AC_FC_FREEFORM
 args: --preselect AC_FC_SRCEXT
+args: --preselect AC_FC_PP_SRCEXT
 args: --preselect AC_INIT
 args: --preselect AC_LIBSOURCE
 args: --preselect AC_REQUIRE_AUX_FILE
diff --git a/tests/fortran.at b/tests/fortran.at
index 4986ee4..33107ef 100644
--- a/tests/fortran.at
+++ b/tests/fortran.at
@@ -714,6 +714,106 @@ AT_CHECK([$MAKE], [], [ignore], [ignore])
 AT_CLEANUP
 
 
+## ---------------------- ##
+## AC_FC_PP_SRCEXT usage. ##
+## ---------------------- ##
+
+AT_SETUP([AC_FC_PP_SRCEXT usage])
+
+AT_DATA([configure.ac],
+[[AC_INIT
+AC_PROG_FC
+# Unconditionally require .f and .F to work.
+AC_FC_PP_SRCEXT([f])
+AC_FC_PP_SRCEXT([F])
+# For each other extension, fail gracefully if it does not work:
+# Not all compilers support all extensions/language versions.
+m4@&address@hidden([ext], [f77, f90, f95, f03, f08],
+  [AC_FC_PP_SRCEXT(ext, ext[_object='foo]ext[.$(OBJEXT)'], ext[_object=])
+   AC_SUBST(ext[_object])])
+m4@&address@hidden([ext], [F77, F90, F95, F03, F08],
+  [AC_FC_PP_SRCEXT(ext, ext[_object='bar]ext[.$(OBJEXT)'], ext[_object=])
+   AC_SUBST(ext[_object])])
+AC_CONFIG_FILES([Makefile])
+AC_OUTPUT
+]])
+
+AT_DATA([Makefile.in],
+[[OBJEXT = @OBJEXT@
+
+all: address@hidden@
address@hidden@: address@hidden@ @f77_object@ @f90_object@ \
+             @f95_object@ @f03_object@ @f08_object@ \
+             address@hidden@ @F77_object@ @F90_object@ \
+             @F95_object@ @F03_object@ @F08_object@
+       @FC@ @FCFLAGS@ -o $@ address@hidden@ @f77_object@ @f90_object@ \
+                            @f95_object@ @f03_object@ @f08_object@ \
+                            address@hidden@ @F77_object@ @F90_object@ \
+                            @F95_object@ @F03_object@ @F08_object@
+
+.SUFFIXES: .f .f77 .f90 .f95 .f03 .f08 .F .F77 .F90 .F95 .F03 .F08 
address@hidden@
address@hidden@:
+       @FC@ -c @FCFLAGS_f@ $<
address@hidden@:
+       @FC@ -c @FCFLAGS_f77@ $<
address@hidden@:
+       @FC@ -c @FCFLAGS@ @FCFLAGS_f90@ $<
address@hidden@:
+       @FC@ -c @FCFLAGS@ @FCFLAGS_f95@ $<
address@hidden@:
+       @FC@ -c @FCFLAGS@ @FCFLAGS_f03@ $<
address@hidden@:
+       @FC@ -c @FCFLAGS@ @FCFLAGS_f08@ $<
address@hidden@:
+       @FC@ -c @FCFLAGS_F@ $<
address@hidden@:
+       @FC@ -c @FCFLAGS_F77@ $<
address@hidden@:
+       @FC@ -c @FCFLAGS@ @FCFLAGS_F90@ $<
address@hidden@:
+       @FC@ -c @FCFLAGS@ @FCFLAGS_F95@ $<
address@hidden@:
+       @FC@ -c @FCFLAGS@ @FCFLAGS_F03@ $<
address@hidden@:
+       @FC@ -c @FCFLAGS@ @FCFLAGS_F08@ $<
+]])
+
+for ext in f77 f90 f95 f03 f08; do
+  cat > foo$ext.$ext <<EOF
+      subroutine foo$ext
+#if 0
+this is not correct fortran
+#endif
+      end
+EOF
+done
+
+for ext in F F77 F90 F95 F03 F08; do
+  cat > bar$ext.$ext <<EOF
+      subroutine bar$ext
+#if 0
+this is not correct fortran
+#endif
+      end
+EOF
+done
+
+AT_DATA([foof.f],
+[[      program main
+#if 0
+this is not correct fortran
+#endif
+      end
+]])
+
+AT_CHECK_AUTOCONF
+AT_CHECK_CONFIGURE
+: "${MAKE=make}"
+AT_CHECK([$MAKE], [], [ignore], [ignore])
+
+AT_CLEANUP
+
+
 ## --------------- ##
 ## AC_FC_FREEFORM. ##
 ## --------------- ##
diff --git a/tests/mktests.sh b/tests/mktests.sh
index 3559f0c..908092a 100755
--- a/tests/mktests.sh
+++ b/tests/mktests.sh
@@ -100,7 +100,7 @@ ac_exclude_list='
        # Produce "= val" because $1, the variable used to store the result,
        # is empty.
        /^AC_(F77|FC)_FUNC$/ {next}
-       /^AC_FC_SRCEXT$/ {next}
+       /^AC_FC_(PP_)?SRCEXT$/ {next}
        /^AC_PATH_((TARGET_)?TOOL|PROG)S?$/ {next}
 
        # Is a number.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]