automake-patches
[Top][All Lists]
Advanced

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

[PATCH] Support for interdependency tracking between Fortan 90 modules


From: Nicolai Stange
Subject: [PATCH] Support for interdependency tracking between Fortan 90 modules
Date: Fri, 19 Aug 2011 23:38:11 +0200

Just my final proposed patch (re-)created with 'git format-patch'.

A note on the status of the FSF assignment process: I've already received the 
necessary papers to sign.
We're currently checking who of my superiors is authorized to sign (the guys 
involved in checking this are quite busy at the moment). 
But it can be taken for granted that somebody will sign. This will happen next 
week, I hope.

---
 ChangeLog                          |   21 +++
 automake.in                        |  239 +++++++++++++++++++++++++++++++++-
 doc/automake.texi                  |   55 ++++++++-
 lib/Makefile.am                    |    2 +-
 lib/Makefile.in                    |    7 +-
 lib/fc-prepr                       |  254 ++++++++++++++++++++++++++++++++++++
 lib/fc-xtrctdefmods                |   81 ++++++++++++
 lib/fc-xtrctusedmods               |  223 +++++++++++++++++++++++++++++++
 m4/Makefile.am                     |    1 +
 m4/Makefile.in                     |    1 +
 m4/fortran.m4                      |  239 +++++++++++++++++++++++++++++++++
 tests/Makefile.am                  |    1 +
 tests/Makefile.in                  |    1 +
 tests/fort_obey_mod_interdeps.test |  163 +++++++++++++++++++++++
 14 files changed, 1279 insertions(+), 9 deletions(-)
 create mode 100755 lib/fc-prepr
 create mode 100755 lib/fc-xtrctdefmods
 create mode 100755 lib/fc-xtrctusedmods
 create mode 100644 m4/fortran.m4
 create mode 100755 tests/fort_obey_mod_interdeps.test

diff --git a/ChangeLog b/ChangeLog
index ea42a25..9713943 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,24 @@
+2011-08-19 Nicolai Stange <address@hidden>
+
+       automake: Add support for dependency tracking between Fortran 90
+       modules.
+       * automake.in (common_files): Added fc-prepr, fc-xtrctdefmods,
+       fc-xtrctusedmods.
+       (lang_fc_finish): New function.
+       * doc/automake.texi (Obeying Module Interdependencies): New
+       node/subsection.
+       * lib/Makefile.am (dist_script_DATA): Added fc-prepr,
+       fc-xtrctdefmods, fc-xtrctusedmods.
+       * lib/fc-prepr: New script.
+       * lib/fc-xtrctdefmods: New script.
+       * lib/fc-xtrctusedmods: New script.
+       * m4/Makefile.am (dist_m4data_DATA): Added fortran.m4.
+       * m4/fortran.m4 (AM_FC_MOD_OBEY_INTERDEPS, _AM_FC_FPP_DEPMODE)
+       (AM_OUTPUT_FC_MOD_DEP_COMMANDS, _AM_OUTPUT_FC_MOD_DEP_COMMANDS):
+       New autoconf macros.
+       * tests/Makefile.am (TESTS): Updated.
+       * tests/fort_obey_mod_interdeps.test: New test.
+
 2011-08-17  Stefano Lattarini  <address@hidden>
 
        * THANKS (Daniel Richard G.): Update e-mail address.
diff --git a/automake.in b/automake.in
index 517eea9..8e465fa 100644
--- a/automake.in
+++ b/automake.in
@@ -235,7 +235,8 @@ my @common_files =
        COPYING.LESSER ChangeLog INSTALL NEWS README THANKS TODO
        ansi2knr.1 ansi2knr.c ar-lib compile config.guess config.rpath
        config.sub depcomp elisp-comp install-sh libversion.in mdate-sh
-       missing mkinstalldirs py-compile texinfo.tex ylwrap),
+       missing mkinstalldirs py-compile texinfo.tex ylwrap
+        fc-prepr fc-xtrctdefmods fc-xtrctusedmods),
      @libtool_files, @libtool_sometimes);
 
 # Commonly used files we auto-include, but only sometimes.  This list
@@ -402,6 +403,10 @@ my $seen_init_automake = 0;
 # TRUE if we've seen AM_AUTOMAKE_VERSION.
 my $seen_automake_version = 0;
 
+# Which Fortran file extensions to include in Fortran dependency
+# tracking.
+my %fortran_obey_interdeps = ();
+
 # Hash table of discovered configure substitutions.  Keys are names,
 # values are `FILE:LINE' strings which are used by error message
 # generation.
@@ -951,7 +956,8 @@ register_language ('name' => 'fc',
                   'lder' => 'FCLD',
                   'ld' => '$(FC)',
                   'pure' => 1,
-                  'extensions' => ['.f90', '.f95', '.f03', '.f08']);
+                  'extensions' => ['.f90', '.f95', '.f03', '.f08'],
+                  '_finish' => \&lang_fc_finish);
 
 # Preprocessed Fortran
 register_language ('name' => 'ppfc',
@@ -969,7 +975,8 @@ register_language ('name' => 'ppfc',
                   'output_flag' => '-o',
                   'libtool_tag' => 'FC',
                   'pure' => 1,
-                  'extensions' => ['.F90','.F95', '.F03', '.F08']);
+                  'extensions' => ['.F90','.F95', '.F03', '.F08'],
+                  '_finish' => \&lang_fc_finish);
 
 # Preprocessed Fortran 77
 #
@@ -5311,6 +5318,7 @@ sub scan_autoconf_traces ($)
                m4_include => 1,
                m4_sinclude => 1,
                sinclude => 1,
+                AM_FC_MOD_OBEY_INTERDEPS => 1,
              );
 
   my $traces = ($ENV{AUTOCONF} || '@am_AUTOCONF@') . " ";
@@ -5560,6 +5568,10 @@ sub scan_autoconf_traces ($)
              %libtool_tags = (CC => 1, CXX => 1, GCJ => 1, F77 => 1);
            }
        }
+      elsif ($macro eq 'AM_FC_MOD_OBEY_INTERDEPS')
+       {
+         $fortran_obey_interdeps{'.' . $args[1]} = 1;
+       }
     }
 
   error ($where, "condition stack not properly closed")
@@ -6211,6 +6223,227 @@ sub lang_lex_finish
 }
 

+sub lang_fc_finish
+{
+  my ($lang) = @_;
+  
+  # Depending on whether we're doing Fortran interdependency tracking
+  # (the use of modules impose a particular order of compilation) and
+  # on whether we're doing it for preprocessed Fortran or
+  # non-preprocessed files only, several auxiliary scripts are
+  # required and several Makefile variables have to get defined for
+  # the rules that get generated in lang_fortran_finish_target.  Note
+  # that this code might get called twice, once for language 'fc'
+  # and once for language 'ppfc'. The common code to set up the
+  # environment for depencency tracking is invariant under being
+  # called twice though.
+
+  # START of setting up common environment
+  ## Whether we're supposed to do dependency tracking for at least one
+  ## Fortran file extension.
+  my $for_wedodeptracking = 0;
+  ## Whether we're supposed to do dependency tracking for at least
+  ## one Fortran file extension indicating preprocessed Fortran.  
+  my $forprepr_needed = 0;  
+  if(grep {$fortran_obey_interdeps{$_}} @{$languages{'fc'}->extensions})
+    {
+      $for_wedodeptracking = 1;
+    }
+
+  for (grep {$fortran_obey_interdeps{$_}} 
+                      @{$languages{'ppfc'}->extensions})
+    {
+      $for_wedodeptracking = 1;
+      $forprepr_needed = 1;
+      my $fppsrcext = $_;
+      $fppsrcext =~ s/^\.//; # Remove leading dot. 
+      define_configure_variable("am__cv_fc_fpp_$fppsrcext");
+    }
+  
+  if($for_wedodeptracking)
+    {
+      define_configure_variable("FDEPDIR");
+      define_variable ('forextractusedmods',
+                      "\$(SHELL) $am_config_aux_dir/fc-xtrctusedmods",
+                      INTERNAL);
+      require_conf_file ("$am_file.am", FOREIGN, 'fc-xtrctusedmods');
+      define_variable ('forextractdefmods',
+                      "\$(SHELL) $am_config_aux_dir/fc-xtrctdefmods",
+                      INTERNAL);
+      require_conf_file ("$am_file.am", FOREIGN, 'fc-xtrctdefmods');
+    }
+  else
+    {
+      return;
+    }
+  if($forprepr_needed)
+    {
+      define_variable ('forprepr',
+                      "\$(SHELL) $am_config_aux_dir/fc-prepr",
+                      INTERNAL);
+      require_conf_file ("$am_file.am", FOREIGN, 'fc-prepr');
+    }  
+
+  ## We need to maintain a list of all Fortran module caches in play
+  ## here. This list will serve as a fallback prerequisite to force a
+  ## rebuild of some module dependency files.
+  my @fortran_module_caches = ();
+  while(my ($obj, $src) = each %object_map)
+    {
+      $src =~ /.*(\.[^.]*)$/;
+      my $srcext = $1;
+      if($fortran_obey_interdeps{$srcext})
+       {
+         push @fortran_module_caches, ($obj);
+       }
+    }
+  ## And transform the object file extension to '.fmc'
+  map s/\.[^.]*$/.fmc/, @fortran_module_caches;
+  ## We still have to squeeze the $(FDEPDIR) in and define it as a variable.
+  map {$_ = dirname($_) . '/$(FDEPDIR)/' . basename($_) } 
+  @fortran_module_caches;
+  define_pretty_variable('FORTRAN_MODULE_CACHES', TRUE, INTERNAL, 
+                        @fortran_module_caches);
+  
+  # END of setting up common environment
+  
+  # We assert proper dependency tracking rules for the sources we're
+  # supposed to do so. This depends on whether the file is
+  # Preprocessed Fortran or not. Because there might exist per-target
+  # compilation flags and the fc-xtrctusedmods depends on those flags,
+  # this procedure is also target dependent.
+  # The general tactics is as follows:
+  # - Iterate through the targets
+  # - For each target iterate through the _OBJECTS variable
+  # - Look up the corresponding source in %object_map and
+  #   assert the corresponding rules for dependency tracking.
+  for my $target (keys(%known_programs), keys(%known_libraries))
+    {
+      my $derived = canonicalize ($target);
+      # remove the $EXEEXT that might have been added in the meanwhile.
+      $derived =~ s/\$\(EXEEXT\)$//; 
+      
+      # There might be special pre target compilation flags set.
+      # Rewrite each occurrence of `AM_$flag' in the compile
+      # rule into `${derived}_$flag' if it exists.
+      my $flags = $lang->compile;
+      ## Remove the first word, that is the compiler command itself
+      $flags =~ s/^[^ ]* +//;
+      for my $flag (@{$lang->flags})
+       {
+         my $val = "${derived}_${flag}";
+         $flags =~ s/\(AM_${flag}\)/\($val\)/ if set_seen ($val);
+       }
+      
+      # Now iterate on the objects for this target.
+      my $target_objects = var($derived . '_OBJECTS');
+      if(! $target_objects)
+       {
+         ## TODO: I would like to assert here, but I don't know how.
+         ;
+       }
+      
+      for my $obj ($target_objects->value_as_list_recursive)
+       {
+         my $src = $object_map{$obj};
+         if(!defined($src))
+           {
+             ## TODO: I would like to assert here, but I don't know how.
+             ;
+           }
+         
+         $src =~ /\.([^.]*)$/;
+         my $srcext = $1;
+         my $stem = $obj;
+         $stem =~ s/\.[^.]*$//;
+         my $fdep_stem = dirname($stem) . '/$(FDEPDIR)/' . basename($stem);
+         my $pofile = $obj;
+         $pofile =~ s/\.([^.]*)$/.P$1/;
+         $pofile =~ s/\$\(OBJEXT\)$/o/;
+         $pofile = dirname($pofile) . '/$(FDEPDIR)/' . basename($pofile);
+         $pofile =~ /\.([^.]*)$/;
+         my $poext = $1;
+         
+         # we need to get the source file, in VPATH builds this will be
+         # different from $file.
+         my $srctreefile='$(srcdir)/' . $src;
+         
+         ## skip this file if we're not supposed to do dependency tracking
+         ## for it or if it does not belong to the language this function
+          ## had been called with.
+         next if(! $fortran_obey_interdeps{'.' . $srcext}
+                 || ! grep { $_ eq '.' . $srcext } @{$lang->extensions});
+         
+         # The set of extra rules to emit depends heavily on whether
+         # this is Preprocessed Fortran or not.
+         if(grep /^\.$srcext$/, @{$languages{'fc'}->extensions})
+           {
+             # Non-preprocessed Fortran.
+             $output_rules .= "$obj : ${fdep_stem}.UMF ${fdep_stem}.fmc\n";
+             $output_rules .= "${fdep_stem}.UMF : $srctreefile\n"
+               . "\tobject=$obj"
+               . " FC_MODINC=\"\$(FC_MODINC)\""
+               . " all_mod_caches=\"\\\$\$(FORTRAN_MODULE_CACHES)\""
+               . " top_builddir=\"\$(top_builddir)\""
+               . " abs_top_builddir=\"\$(abs_top_builddir)\""
+               . " \$(forextractusedmods) $srctreefile $flags\n";
+             $output_rules .= "${fdep_stem}.fmc : $srctreefile\n"
+               . "\tobject=$obj"
+               . " \$(forextractdefmods) $srctreefile\n";
+             $output_rules .= (subst ('am__include')
+                               . ' '
+                               . subst ('am__quote')
+                               . "${fdep_stem}.UMF"
+                               . subst ('am__quote')
+                               . "\n");
+             $clean_files{dirname($fdep_stem) . '/*.fmc'} = MOSTLY_CLEAN;
+             $clean_files{dirname($fdep_stem) . '/*.UMF'} = DIST_CLEAN;
+           }
+         elsif(grep /^\.$srcext$/, @{$languages{'ppfc'}->extensions})
+           {
+             # preprocessed fortran          
+             $output_rules .= "$obj : ${fdep_stem}.UMF ${fdep_stem}.fmc\n";
+             $output_rules .= "${fdep_stem}.UMF : ${pofile}\n"
+               . "\tobject=$obj"
+               . " FC_MODINC=\"\$(FC_MODINC)\""
+               . " all_mod_caches=\"\\\$\$(FORTRAN_MODULE_CACHES)\""
+               . " top_builddir=\"\$(top_builddir)\""
+               . " abs_top_builddir=\"\$(abs_top_builddir)\""
+               . " \$(forextractusedmods) ${fdep_stem}.PF $flags\n";
+             $output_rules .= "${fdep_stem}.fmc : $pofile\n"
+               . "\tobject=$obj"
+               . " \$(forextractdefmods) ${fdep_stem}.PF\n";
+             $output_rules .= "$pofile : $srctreefile\n"
+               . "\tobject=$obj source=$srctreefile"
+               . " depfile=$pofile" 
+               . " depmode=" . subst("am__cv_fc_fpp_depmode_$srcext")
+               . " fpp=" . "\$(am__cv_fc_fpp_$srcext)"
+               . " \$(forprepr) $srctreefile" 
+               . " $flags " . subst("am__cv_fc_fpp_flags_$srcext") . "\n";
+             $output_rules .= (subst ('am__include')
+                               . ' '
+                               . subst ('am__quote')
+                               . "${fdep_stem}.UMF"
+                               . subst ('am__quote')
+                               . "\n");
+             $output_rules .= (subst ('am__include')
+                               . ' '
+                               . subst ('am__quote')
+                               . "$pofile"
+                               . subst ('am__quote')
+                               . "\n");
+             $clean_files{dirname($fdep_stem) . '/*.fmc'} = MOSTLY_CLEAN;
+             $clean_files{dirname($fdep_stem) . '/*.UMF'} = DIST_CLEAN;
+             $clean_files{dirname($fdep_stem) . '/*.'. $poext} = DIST_CLEAN;
+             $clean_files{dirname($fdep_stem) . '/*.' . $poext . '.bootstrap'} 
+                          = DIST_CLEAN;
+             $clean_files{dirname($fdep_stem) . '/*.PF'} = DIST_CLEAN;
+           }
+       }
+    }
+}
+
+
 # Given a hash table of linker names, pick the name that has the most
 # precedence.  This is lame, but something has to have global
 # knowledge in order to eliminate the conflict.  Add more linkers as
diff --git a/doc/automake.texi b/doc/automake.texi
index c982b40..161a3f5 100644
--- a/doc/automake.texi
+++ b/doc/automake.texi
@@ -273,7 +273,9 @@ Mixing Fortran 77 With C and C++
 
 Fortran 9x Support
 
-* Compiling Fortran 9x Files::  Compiling Fortran 9x sources
+* Compiling Fortran 9x Files::          Compiling Fortran 9x sources
+* Obeying Module Interdependencies::    Enforcing a `correct' order of
+                                        compilation
 
 Other Derived Objects
 
@@ -6670,7 +6672,9 @@ library.
 @end vtable
 
 @menu
-* Compiling Fortran 9x Files::  Compiling Fortran 9x sources
+* Compiling Fortran 9x Files::          Compiling Fortran 9x sources
+* Obeying Module Interdependencies::    Enforcing a `correct' order of
+                                        compilation
 @end menu
 
 @node Compiling Fortran 9x Files
@@ -6698,6 +6702,53 @@ is as follows:
 
 @end table
 
address@hidden Obeying Module Interdependencies
address@hidden  node-name,  next,  previous,  up
address@hidden Obeying Module Interdependencies
+
+The introduction of modules with Fortran 9x puts additional
+constraints on the order of compilation. Usually, the compilation of a
+source file @address@hidden, wherein a @code{MODULE m1} is
+being defined, emits two files: @address@hidden and
address@hidden@var{m1}.mod}. The exact naming and format of the latter depends
+heavily on the compiler being used though. The important point is,
+that a @address@hidden containing @code{USE m1} must get
+compiled @emph{after} the creation of this @address@hidden, that
+is the compilation of @address@hidden If @address@hidden
+is not yet exisiting at the time of @address@hidden
+compilation, it will fail.  Furthermore there exists the possibility
+of employing an obsolete @address@hidden if the dependencies
+aren't resolved properly. You could of course list your source files
+in the correct order, but this technique has some drawbacks:
address@hidden
address@hidden You have to maintain the interdependencies by hand
address@hidden You can't employ parallel make anymore
address@hidden The problem with possibly obsolete module files still persists
address@hidden itemize
+
+Automake has got the capability to automatically resolve these
+dependencies for your Fortran sources now. You can include Fortran
+source files of a particular extension @address@hidden into this
+dependency tracking by calling
address@hidden(address@hidden@var{ext}}])},
address@hidden Keep in sync with fort_obey_mod_interdeps.test
+e.g. @code{AM_FC_MOD_OBEY_INTERDEPS([f90])}. This will introduce some
+dependency tracking mechanism very similiar to the one for C sources
+depending on some headers. There are differences though: For C, it
+suffices to generate the dependencies as side effects. For Fortran
+modules, these dependencies must be known @emph{before} the first
+compilation. This will add some overhead for each source file: It has
+to be scanned for modules it is defining and using. For preprocessed
+Fortran, this also implies that the source has to be preprocessed
+first.
+
address@hidden: The dependency tracking mechanism employs a feature
+currently only available with GNU make
+(@pxref{Automatic Prerequisites, , Generating Prerequisites
+Automatically, make, GNU Make}) and thus, if you make use of
+Automake's Fortran module interdependency tracking capabilities, you
+require your package's users to use GNU make for its compilation.
+
 @node Java Support
 @comment  node-name,  next,  previous,  up
 @section Java Support
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 5bdc02e..5dad076 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -29,7 +29,7 @@ dist_pkgvdata_DATA = COPYING INSTALL texinfo.tex ansi2knr.c 
ansi2knr.1 \
 scriptdir = $(pkgvdatadir)
 dist_script_DATA = config.guess config.sub install-sh mdate-sh missing \
   mkinstalldirs elisp-comp ylwrap acinstall depcomp compile py-compile \
-  symlink-tree ar-lib
+  symlink-tree ar-lib fc-xtrctdefmods fc-xtrctusedmods fc-prepr
 
 EXTRA_DIST = gnupload
 
diff --git a/lib/Makefile.in b/lib/Makefile.in
index 91e9bae..817083b 100644
--- a/lib/Makefile.in
+++ b/lib/Makefile.in
@@ -53,8 +53,9 @@ subdir = lib
 DIST_COMMON = $(dist_pkgvdata_DATA) $(dist_script_DATA) \
        $(srcdir)/Makefile.am $(srcdir)/Makefile.in COPYING INSTALL \
        ansi2knr.1 ansi2knr.c ar-lib compile config.guess config.sub \
-       depcomp elisp-comp install-sh mdate-sh missing mkinstalldirs \
-       py-compile texinfo.tex ylwrap
+       depcomp elisp-comp fc-prepr fc-xtrctdefmods fc-xtrctusedmods \
+       install-sh mdate-sh missing mkinstalldirs py-compile \
+       texinfo.tex ylwrap
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/m4/amversion.m4 \
        $(top_srcdir)/m4/auxdir.m4 $(top_srcdir)/m4/init.m4 \
@@ -242,7 +243,7 @@ dist_pkgvdata_DATA = COPYING INSTALL texinfo.tex ansi2knr.c 
ansi2knr.1 \
 scriptdir = $(pkgvdatadir)
 dist_script_DATA = config.guess config.sub install-sh mdate-sh missing \
   mkinstalldirs elisp-comp ylwrap acinstall depcomp compile py-compile \
-  symlink-tree ar-lib
+  symlink-tree ar-lib fc-xtrctdefmods fc-xtrctusedmods fc-prepr
 
 EXTRA_DIST = gnupload
 all: all-recursive
diff --git a/lib/fc-prepr b/lib/fc-prepr
new file mode 100755
index 0000000..71f629e
--- /dev/null
+++ b/lib/fc-prepr
@@ -0,0 +1,254 @@
+#!/bin/sh 
+
+# Copyright (C) 2011 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Originally written by Nicolai Stange <address@hidden>.
+# Many parts have been copied verbatim from depcomp, originally 
+# written by Alexandre Oliva
+
+# fc-prepr Preprocess a Fortran source file, store the
+# result and generate make dependencies on #included files. It does
+# not do any compilation as depcomp would do.
+
+scriptversion="2011-07-24"
+
+# Possible values for depmode and meaning:
+# - gfortran4:
+#   * gfortran4 can generate dependencies as side effects while 
+#     preprocessing to stdout via -E.
+# - fppE:
+#   * Fortran compiler cannot create dependencies as side effects but is
+#     able to preprocess to stdout via -E
+# - fppF:
+#   * The Fortran compiler cannot send preprocessing output to stdout, but
+#     to a file with same name as the source with uncapitalized extension
+#     if -F is given.
+# - cpp:
+#   * The Fortran compiler cannot send preprocessing ouput with line 
+#     annotations anywhere we can use it. Use cpp as a fallback.
+
+# Generate make dependency file $depfile from the preprocessing
+# output in $tmppreprfile
+process_cpp_output () {
+  # Extract the files that have been included by the preprocessor
+  # from preprocessing output. 
+  # For GNU's cpp some special files like
+  # "<built-in>" and "<command-line>" are pulled in, remove them.
+  # There might also be files ending with two slashes indicating a
+  # directory. Remove it.
+  sed -n -e '/^# [0-9][0-9]* "<[^"]*>".*/ d' \
+      -e '/^# [0-9][0-9]* ".*\/\/"$/ d' \
+      -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s::\1:p' \
+      -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s::\1:p' \
+      "$tmppreprfile" |
+      sort | sort -u > "$tmpdepfile"
+  
+  cat > "$depfile" <<EOF
+$object $depfile : \\
+EOF
+
+  # Add the prerequisites with line continuation
+  sed 's:^.*$: & \\:' "$tmpdepfile" |
+  sed '$ s: \\$::' >> "$depfile"
+  echo '' >> "$depfile"
+
+  # Now add the dummy targets (equivalent of gcc -MP)
+  grep -v "$source" $tmpdepfile | sed '/^$/ d; s/$/ : /' >> "$depfile"
+  rm "$tmpdepfile"
+}
+
+case $1 in
+  '')
+     echo "$0: No source.  Try \`$0 --help' for more information." 1>&2
+     exit 1
+     ;;
+  -h | --h*)
+    cat <<EOF
+Usage: fc-prepr [--help] [--version] SOURCE [ARGS]
+
+Run ARGS to preprocess a file, generating dependencies.
+
+Environment variables:
+  depmode       Dependency tracking mode.
+  fpp           How to invoke the Fortran preprocessor
+  source        Source file read.
+  object        Object file output.
+  DEPDIR        directory where to store dependencies.
+  depfile       Dependency file to output.
+  tmpdepfile    Temporary file to use when outputing dependencies.
+  PREPRDIR      directory where to store preprocessing output.
+  preprfile     Where to write preprocessing output to.
+  tmppreprfile  Temporary file for preprocessing output.
+Report bugs to <address@hidden>.
+EOF
+    exit $?
+    ;;
+  -v | --v*)
+    echo "fc-prepr $scriptversion"
+    exit $?
+    ;;
+esac
+
+if test -z "$depmode" || test -z "$source" || test -z "$object" \
+    || test -z "$fpp" ; then
+  echo "$0: Variables source, object, depmode and fpp must be set" 1>&2
+  exit 1
+fi
+
+# This is thought as an assertion to check that only preprocessed
+# Fortran files (ones with a capitalized "F" in the source file
+# extension) get preprocessed here. $srcext and stem also used below.
+srcext=`echo "$source" | sed 's/.*\.\(.*\)$/\1/'`
+stem=`echo "$object" | sed 's/\(.*\)\..*$/\1/'`
+echo "$srcext" | grep '^f' > /dev/null 2>&1
+if [ $? = 0 ]; then
+    echo "$0: A non-Preprocessed Fortran input file has been given." 1>&2
+    exit 1
+fi
+
+# Preprocessing output for sub/bar.o or sub/bar.obj go into sub/.fdeps/bar.PF
+# "PF" stands for Preprocessed Fortran
+preprfile=${preprfile-`echo "$object" | 
+  sed 's|[^\\/]*$|'${PREPRDIR-.fdeps}'/&|;s|\.\([^.]*\)$|.PF|'`}
+tmppreprfile=${tmppreprfile-`echo "$preprfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
+rm -f "$tmppreprfile"
+
+# Dependencies for sub/bar.o or sub/bar.obj go into sub/.fdeps/bar.Po.
+depfile=${depfile-`echo "$object" |
+  sed 's|[^\\/]*$|'${DEPDIR-.fdeps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
+tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
+rm -f "$tmpdepfile"
+
+case "$depmode" in
+gfortran4)
+## gfortran implements dependency tracking that does exactly what we
+## want Yay!
+  $fpp -E -M -MT "$object" -MP -MF "$tmpdepfile" "$@" \
+      > "$tmppreprfile" 
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmppreprfile" "$tmpdepfile"
+    exit $stat
+  fi
+  mv "$tmppreprfile" "$preprfile"
+  # add the dependency file itself as a target of the prerequisites
+  sed "s:$object:$object $depfile:" "$tmpdepfile" > "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+fppE)
+## These preprocessors put the results to stdout.
+  $fpp -E "$@" > "$tmppreprfile"
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmppreprfile"
+    exit $stat
+  fi
+  
+  process_cpp_output
+  
+  mv "$tmppreprfile" "$preprfile"
+  rm -f "$tmppreprfile"
+  ;;
+
+fppF)
+## Unfortunately, these preprocessors don't output the result to
+## stdout, but to a filename with same name as the source file, but
+## uncapitalized extension
+  fppoutfile="$stem.`echo $srcext | tr F f`"
+  
+  # make sure $fppoutfile doesn't exist yet to avoid overwriting 
+  # it by accident
+  if test -f "$fppoutfile"; then
+    echo "$0: Can't preprocess $source because $fppoutfile already exists" \
+       1>&2
+    exit 1
+  fi
+  
+  $fpp -F "$@"
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+    rm -f "$fppoutfile"
+    exit $stat
+  fi
+  
+  mv "$fppoutfile" "$tmppreprfile"
+
+  process_cpp_output
+  
+  mv "$tmppreprfile" "$preprfile"
+  rm -f "$tmppreprfile"
+  ;;
+
+cpp)
+## This preprocessor puts the results to stdout.
+  # We have to strip off anything from "$@" that plain cpp might not
+  # understand, that is keep only -I* and -D*
+  cleared=no
+  addnext=no
+  for arg
+  do
+    case $cleared in
+      no)
+        set ""; shift
+        cleared=yes ;;
+    esac
+    case $addnext in 
+      yes)
+        set fnord "$@" "$arg" ; shift 
+        addnext=no; continue ;;
+    esac
+    case $arg in
+      -I|-D)
+        addnext=yes
+        set fnord "$@" "$arg" ; shift ;;
+      -I*|-D*)
+        set fnord "$@" "$arg" ; shift ;;
+      *)
+        continue ;;
+    esac
+  done
+  # add the source again:
+  set fnord "$@" "$source" ; shift
+
+  $fpp "$@" > "$tmppreprfile"
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmppreprfile"
+    exit $stat
+  fi
+  
+  process_cpp_output
+  
+  mv "$tmppreprfile" "$preprfile"
+  rm -f "$tmppreprfile"
+  ;;
+
+*)
+  echo "$0: depmode $depmode not supported" 1>&2
+  exit 1
+esac
+
+exit 0
diff --git a/lib/fc-xtrctdefmods b/lib/fc-xtrctdefmods
new file mode 100755
index 0000000..800460c
--- /dev/null
+++ b/lib/fc-xtrctdefmods
@@ -0,0 +1,81 @@
+#!/bin/sh
+
+# Copyright (C) 2011 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Originally written by Nicolai Stange <address@hidden>.
+
+# fc-xtrctdefmods extracts the Fortran MODULE statements from a
+# (optionally already preprocessed) Fortran file.
+
+scriptversion="2011-07-24"
+
+case $1 in
+  '')
+     echo "$0: No source.  Try \`$0 --help' for more information." 1>&2
+     exit 1
+     ;;
+  -h | --h*)
+    cat <<EOF
+Usage: fc-xtrctusedmods [--help] [--version] SOURCE
+
+Extract USE statements from SOURCE
+
+Environment variables:
+  object       Object file output.
+  DMDIR        directory where to store the list of defined modules
+  dmfile       File to write the list of defined modules to.
+  tmpdmfile    Temporary file to write the list of defined modules to.
+Report bugs to <address@hidden>.
+EOF
+    exit $?
+    ;;
+  -v | --v*)
+    echo "fc-xtrctdefmods $scriptversion"
+    exit $?
+    ;;
+esac
+
+# List of defined mods for sub/bar.o or sub/bar.obj go into sub/.fdeps/bar.fmc
+# "fmc" stands for fortran module cache
+dmfile=${dmfile-`echo "$object" | 
+  sed 's|[^\\/]*$|'${DMDIR-.fdeps}'/&|;s|\.\([^.]*\)$|.fmc|'`}
+tmpdmfile=${tmpdmfile-`echo "$dmfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
+rm -f "$tmpdmfile"
+
+## We write a comment containing ' # $object' to module list file
+## This will be used by fc-xtrctusedmods to get the $object it should
+## generate dependencies on. 
+cat > "$tmpdmfile" <<EOF
+# $object
+EOF
+
+## Now we actually extract the USE statements stripping the comments.
+## Note that USE statements spanning mupltiple lines won't get recognized
+## properly.
+## Ignore lines containing the following:
+## - "MODULE PROCEDURE"
+sed -n  -e '/[Mm][Oo][Dd][Uu][Ll][Ee]  *[Pp][Rr][Oo][Cc][Ee][Dd][Uu][Rr][Ee]/ 
d;' \
+        -e '/^ *[Mm][Oo][Dd][Uu][Ll][Ee]  *\([A-Za-z][_a-zA-Z0-9]*\).*/ 
s::\1:p' \
+           "$1" | tr '[:upper:]' '[:lower:]' >> "$tmpdmfile"
+
+mv "$tmpdmfile" "$dmfile"
+
+exit 0
\ No newline at end of file
diff --git a/lib/fc-xtrctusedmods b/lib/fc-xtrctusedmods
new file mode 100755
index 0000000..97a0f2e
--- /dev/null
+++ b/lib/fc-xtrctusedmods
@@ -0,0 +1,223 @@
+#!/bin/sh
+
+# Copyright (C) 2011 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Originally written by Nicolai Stange <address@hidden>.
+
+# fc-xtrctusedmods extracts the Fortran USE statements from a
+# (optionally already preprocessed) Fortran file, searches the paths 
+# given by "$FC_MODINC" as ARGS for those "defined modules" files generated by
+# fc-xtrctusedmods and generates a Makefile covering these dependencies
+# to be included into the main Makefile.
+
+scriptversion="2011-07-24"
+
+case $1 in
+  '')
+     echo "$0: No source.  Try \`$0 --help' for more information." 1>&2
+     exit 1
+     ;;
+  -h | --h*)
+    cat <<EOF
+Usage: fc-xtrctusedmods [--help] [--version] SOURCE [ARGS]
+
+Extract USE statements from SOURCE and generate dependency information.
+
+Environment variables:
+  object           Object file output.
+  FC_MODINC        The Fortran compiler's module search directory flag as
+                   determined by AC_FC_MODULE_FLAG.
+  UMDIR            directory where to store the generated dependency 
information
+  umfile           File to write the dependency information to.
+  tmpumfile        Temporary file to write the dependency information to.
+  DMDIR            Relative subdir where the files containing the list of 
modules
+                   (generated by fc-xtrctdefmods) are usually stored at.
+  all_mod_caches   All module caches (*.fmc) local to the current directory.
+  top_builddir     As defined by autoconf
+  abs_top_builddir As defined by autoconf
+Report bugs to <address@hidden>.
+EOF
+    exit $?
+    ;;
+  -v | --v*)
+    echo "fc-xtrctusedmods $scriptversion"
+    exit $?
+    ;;
+esac
+
+# Preprocessing output for sub/bar.o or sub/bar.obj go into sub/.fdeps/bar.UMF
+# "UMF" stands for "Used Modules Fortran"
+umfile=${umfile-`echo "$object" | 
+  sed 's|[^\\/]*$|'${UMDIR-.fdeps}'/&|;s|\.\([^.]*\)$|.UMF|'`}
+tmpumfile=${tmpumfile-`echo "$umfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
+rm -f "$tmpumfile"
+
+# We need this guy to know where to look for the module cache files
+# generated by fc-xtrctdefmods
+DMDIR="${DMDIR-.fdeps}"
+
+## Transform the "$FC_MODINC" arguments given on command line to a 
+## list of colon separated search directories.
+mod_search_dirs="."
+addnext=no
+for arg
+do
+  case $addnext in
+    yes)
+      mod_search_dirs="$mod_search_dirs:$arg"
+      addnext=no; continue ;;
+  esac
+  
+  case "$arg" in
+    "$FC_MODINC")
+      addnext=yes ;;
+    "$FC_MODINC"*)
+      arg="`echo $arg | sed 's/^$FC_MODINC//'`"
+      mod_search_dirs="$mod_search_dirs:$arg"
+      ;;
+  esac
+done
+
+
+## Now we actually extract the USE statements stripping the comments.
+## Note that USE statements spanning mupltiple lines won't get recognized
+## properly.
+usedmods="`sed -n '/^ *[Uu][Ss][Ee]  *\([A-Za-z][_a-zA-Z0-9]*\).*/ s::\1:p' 
$1`"
+all_found=yes # keep track of whether all modules being used have been found, 
see below
+obj_deps=""
+fmc_deps=""
+for um in $usedmods; do
+  um=`echo $um | tr '[:upper:]' '[:lower:]'`      
+  mod_found=no
+
+  # Try to find a module cache file under builddir corresponding to a
+  # Fortran source defining that module we're searching for.
+  saved_IFS="$IFS"
+  IFS=":"
+  for sd in $mod_search_dirs; do
+    if [ -z "$sd" ]; then
+      continue
+    fi
+
+    case "$sd" in
+      '.'  | "$top_builddir"* | "$abs_top_builddir"*)
+        # Searching under builddir. Watch out for module cache files
+        # containing that module.
+       IFS="$saved_IFS"
+       for mod_cache in "$sd/$DMDIR"/*.fmc; do
+         if [ "$mod_cache" = "$sd/$DMDIR/"/'*.fmc' ] ; then
+            # No matching files found
+              break
+         fi
+      
+          # Check that $mod_cache whether it lists the module being 
+         # searched for
+         if grep '^'"$um"'$' "$mod_cache" > /dev/null 2>&1; then
+            # It does, extract the corresponding object from the 
+           # '# $object' header line.
+              obj_deps="$obj_deps $sd/`sed -n '1 s/^# //p' $mod_cache`"
+             fmc_deps="$fmc_deps $mod_cache"
+             mod_found=yes
+             break 2
+         fi
+       done
+        ;;
+      *)
+        # Searching dir external to the package's builddir.
+        # Check for the existence of one of the known filenames a *.mod 
+        # might have.
+       IFS="$saved_IFS"
+       for poss_mod in $um `echo $um | tr '[:lower:]' '[:upper:]'`; do
+         if [ -f "$sd/${poss_mod}.mod" ]; then
+            mod_found=yes
+            break 2
+         fi
+       done
+       ;;
+    esac
+  done
+  IFS="$saved_IFS"
+  
+  # We've search in all possible locations for this module now.
+  if [ $mod_found = no ]; then
+    all_found=no
+  fi
+done
+
+if [ $all_found = no ]; then
+  # We haven't found all modules being referenced. This can only have
+  # the following reason:
+  #  The module had been moved to some other source within the same 
+  #  subdirectory and the *.fmc files have not been all update yet.
+  #  This is possible because the file we generate usually only depends
+  #  on the *.fmc files that contained sth. useful in the past.
+  # We deal with this by simply adding all *.fmc files as prerequisites of
+  # the UMF file we're just generating to force a rerun after all *.fmc files
+  # have been updated. To avoid infinite loops (due to case 1. or errorneously
+  # completely removed modules), we have to check whether we've done that 
+  # already in the previous run.
+    
+  ## Generate that depend-on-all "$umfile"
+  cat > "$tmpumfile" <<EOF
+$umfile : \\
+EOF
+  echo "$all_mod_caches" |
+  tr ' ' '\n' |
+  sed -e 's/^/ /; s/$/ \\/' -e '$ s/ \\$//' >> "$tmpumfile"
+  
+  if diff "$umfile" "$tmpumfile" > /dev/null 2>&1; then :
+  else
+    ## The "$umfile generated in the previous run differs from the one just 
+    ## generated
+    mv "$tmpumfile" "$umfile"
+    exit 0
+  fi
+fi
+
+# Now generate a "$umfile" containing the dependencies we've just found
+## dependencies of the object on other objects
+cat > "$tmpumfile" <<EOF
+$object : \\
+EOF
+echo "$obj_deps" |
+sed 's/^ //' | ## remeber: $obj_deps contains a leading space
+tr ' ' '\n' |
+sed -e 's/^/ /; s/$/ \\/' -e '$ s/ \\$//' >> "$tmpumfile"
+
+## dependencies of the file we generate on the *.fmc's being referred to
+cat >> "$tmpumfile" <<EOF
+
+$umfile : \\
+EOF
+echo "$fmc_deps" |
+sed 's/^ //' | ## remeber: $obj_deps conatins a leading space
+tr ' ' '\n' |
+sed -e 's/^/ /; s/$/ \\/' -e '$ s/ \\$//' >> "$tmpumfile"
+echo '' >> "$tmpumfile"
+
+# Add dummy rules for each fmc_dep (because they get removed by 'make clean')
+for fmc_dep in $fmc_deps; do
+    echo "$fmc_dep : " >> "$tmpumfile"
+    echo "" >> "$tmpumfile"
+done
+
+mv "$tmpumfile" "$umfile"
+exit 0
diff --git a/m4/Makefile.am b/m4/Makefile.am
index 0cf074b..9c5f17c 100644
--- a/m4/Makefile.am
+++ b/m4/Makefile.am
@@ -30,6 +30,7 @@ cond-if.m4 \
 depend.m4 \
 depout.m4 \
 dmalloc.m4 \
+fortran.m4 \
 gcj.m4 \
 header.m4 \
 init.m4 \
diff --git a/m4/Makefile.in b/m4/Makefile.in
index 679930b..da4d0dd 100644
--- a/m4/Makefile.in
+++ b/m4/Makefile.in
@@ -203,6 +203,7 @@ cond-if.m4 \
 depend.m4 \
 depout.m4 \
 dmalloc.m4 \
+fortran.m4 \
 gcj.m4 \
 header.m4 \
 init.m4 \
diff --git a/m4/fortran.m4 b/m4/fortran.m4
new file mode 100644
index 0000000..4dc4e19
--- /dev/null
+++ b/m4/fortran.m4
@@ -0,0 +1,239 @@
+# Copyright (C) 2011 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Originally written by Nicolai Stange <address@hidden>.
+
+# _AM_OUTPUT_FC_MOD_DEP_COMMANDS 
+# and AM_OUTPUT_FC_MOD_DEP_COMMANDS are taken almost verbatim
+# from depout.m4
+
+# _AM_OUTPUT_FC_MOD_DEP_COMMANDS
+# --------------------------------------
+AC_DEFUN([_AM_OUTPUT_FC_MOD_DEP_COMMANDS],
+[{
+  # Autoconf 2.62 quotes --file arguments for eval, but not when files
+  # are listed without --file.  Let's play safe and only enable the eval
+  # if we detect the quoting.
+  case $CONFIG_FILES in
+  *\'*) eval set x "$CONFIG_FILES" ;;
+  *)   set x $CONFIG_FILES ;;
+  esac
+  shift
+  for mf
+  do
+    # Strip MF so we end up with the name of the file.
+    mf=`echo "$mf" | sed -e 's/:.*$//'`
+    # Check whether this is an Automake generated Makefile or not.
+    # We used to match only the files named `Makefile.in', but
+    # some people rename them; so instead we look at the file content.
+    # Grep'ing the first line is not enough: some people post-process
+    # each Makefile.in and add a new line on top of each file to say so.
+    # Grep'ing the whole file is not good either: AIX grep has a line
+    # limit of 2048, but all sed's we know have understand at least 4000.
+    if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 
2>&1; then
+      dirpart=`AS_DIRNAME("$mf")`
+    else
+      continue
+    fi
+    # Extract the definition of FDEPDIR, am__include, and am__quote
+    # from the Makefile without running `make'.
+    FDEPDIR=`sed -n 's/^FDEPDIR = //p' < "$mf"`
+    test -z "$FDEPDIR" && continue
+    am__include=`sed -n 's/^am__include = //p' < "$mf"`
+    test -z "am__include" && continue
+    am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+    # Find all dependency output files, they are included files with
+    # $(FDEPDIR) in their names.  We invoke sed twice because it is the
+    # simplest approach to changing $(FDEPDIR) to its actual value in the
+    # expansion.
+    for file in `sed -n "
+      s/^$am__include $am__quote\(.*(FDEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+        sed -e 's/\$(FDEPDIR)/'"$FDEPDIR"'/g'`; do
+      # Make sure the directory exists.
+      test -f "$dirpart/$file" && continue
+      fdir=`AS_DIRNAME(["$file"])`
+      AS_MKDIR_P([$dirpart/$fdir])
+      stem=`echo "$file" | sed 's/\(.*\)\..*/\1/'`
+      # Depending on the file type included (dependencies on #included files
+      # vs. dependencies on used modules), we assert different rules
+      # that enforce proper regeneration before the first compilation.
+      case "$file" in
+       *.P*)
+         echo '# bootstrap dummy' > "$dirpart/$file"
+         echo "$file : ${file}.bootstrap" >> "$dirpart/$file"
+        echo "${file}.bootstrap : " >> "$dirpart/$file"
+        cat >> "$dirpart/$file" <<EOF
+        touch ${file}.bootstrap
+EOF
+        ;;
+       *.UMF)
+         echo '# bootstrap dummy' > "$dirpart/$file"
+         echo "$file : "'$(FORTRAN_MODULE_CACHES)' >> "$dirpart/$file"
+      esac 
+    done
+  done
+}
+])# _AM_OUTPUT_FC_MOD_DEP_COMMANDS
+
+
+# AM_OUTPUT_FC_MOD_DEP_COMMANDS
+# -------------------------------------
+# This macro should only be invoked once -- use via AC_REQUIRE.
+#
+# This code is only required when automatic dependency tracking
+# is enabled.  FIXME.  This creates each `.P' file that we will
+# need in order to bootstrap the dependency handling code.
+AC_DEFUN([AM_OUTPUT_FC_MOD_DEP_COMMANDS],
+[AC_CONFIG_COMMANDS([fdepfiles],
+     [_AM_OUTPUT_FC_MOD_DEP_COMMANDS])
+])
+
+
+# _AM_FC_FPP_DEPMODE([EXT])
+# ------------------------------
+# Determine how to preprocess a specific Fortran extension EXT and get the
+# dependencies on files being included.
+AC_DEFUN([_AM_FC_FPP_DEPMODE],
+[AC_CACHE_CHECK([for dependency style of Fortran preprocessor (for extension 
.$1)], 
+[am__cv_fc_fpp_depmode_$1],
+[am__cv_fc_fpp_depmode_$1=""
+ case $1 in
+   F90 | F95 | F03 | F08) ;;
+   *)
+     AC_MSG_ERROR([Filename extension .$1 is not valid for preprocessed 
Fortran]) ;;
+ esac
+
+ AC_REQUIRE([AC_PROG_FC])
+ saved_FC="$FC"
+ saved_FCFLAGS="$FCFLAGS"
+ FCFLAGS="$CPPFLAGS $FCFLAGS"
+ 
+ ## Little Fortran program to preprocess
+ cat > conftest.$1 <<EOF
+PROGRAM conftest
+END PROGRAM conftest
+EOF
+ ## At first try whether the gfortran 4 with dependency generation as side 
effects
+ ## is being supported
+ echo $FC -E -M -MT conftest.o -MP -MF conftest.Po \
+       $FCFLAGS $FCFLAGS_$1 conftest.$1 >&AS_MESSAGE_LOG_FD
+ if $FC -E -M -MT conftest.o -MP -MF conftest.Po \
+       $FCFLAGS $FCFLAGS_$1 conftest.$1 > /dev/null 2>&AS_MESSAGE_LOG_FD \
+    && test -e conftest.Po; then
+   am__cv_fc_fpp_depmode_$1=gfortran4
+   rm -f conftest.Po
+ fi
+
+ ## Otherwise check whether giving the Fortran compiler a -E will make it
+ ## outputting the preprocessed result to stdout.
+ ## Know examples: Older gfortran, Intels ifort, PGIs pgf*
+ if test -z "$am__cv_fc_fpp_depmode_$1"; then
+   echo $FC -E $FCFLAGS $FCFLAGS_$1 conftest.$1 >&AS_MESSAGE_LOG_FD
+   if $FC -E $FCFLAGS $FCFLAGS_$1 conftest.$1 2>&AS_MESSAGE_LOG_FD | 
+         grep conftest.$1 > /dev/null; then
+     am__cv_fc_fpp_depmode_$1=fppE
+   fi
+ fi
+ 
+ ## Another possibility is, that the Fortran compiler can preprocess only
+ ## with -F, but instead of writing the results to stdout, it will write
+ ## its output to a file with the same name as the source but uncapitalized
+ ## extension. 
+ ## Known examples are Oracle SolarisStudios (former SunStudio) comilers and
+ ## NAGs nagfor.
+ if test -z "$am__cv_fc_fpp_depmode_$1"; then
+   fpp_out_ext=`echo $1 | tr F f`
+   echo $FC -F $FCFLAGS $FCFLAGS_$1 conftest.$1 >&AS_MESSAGE_LOG_FD
+   if $FC -F $FCFLAGS $FCFLAGS_$1 conftest.$1 > /dev/null 2>&AS_MESSAGE_LOG_FD 
\
+      && test -e conftest.$fpp_out_ext; then
+     if grep conftest.$1 conftest.$fpp_out_ext > /dev/null 2>&1; then
+       am__cv_fc_fpp_depmode_$1=fppF
+     fi
+   fi
+   rm -f conftest.$fpp_out_ext
+ fi
+ 
+ ## The only possibility remaining is to use the C preprocessor
+ ## A known example are the IBM AIX xlf* compilers where one can force
+ ## them to behave similarly to fppF, but only with line information
+ ## stripped in the output which renders them useless here.
+ ## Note that we cant use AC_PROG_CPP here since this might 
+ ## (and is likely to) result in $CC -E. However, most C-compilers
+ ## wont accept Fortran input to -E.
+ if test -z "$am__cv_fc_fpp_depmode_$1"; then
+   am__cv_fc_fpp_depmode_$1=cpp
+ fi
+
+ FC="$saved_FC"        
+ FCFLAGS="$saved_FCFLAGS"
+ rm conftest.$1
+ ]) # AC_CACHE_CHECK
+ 
+ AC_SUBST([am__cv_fc_fpp_depmode_$1])
+
+ ## Give an error if no suitable Fortran preprocessor had been found.
+ if test -z "$am__cv_fc_fpp_depmode_$1"; then
+   AC_MSG_ERROR([No suitable Fortran preprocessor found (for extension .$1)])
+ fi
+ 
+ if test $am__cv_fc_fpp_depmode_$1 = cpp; then
+   AC_CHECK_PROG([am__cv_fc_fpp_depmode_$1], [cpp],[cpp])
+ fi
+
+ # Now, depending on $am__cv_fc_fpp_depmode_$1 and whether we're using
+ # Fortran 77 or >= 90, set am__cv_fc_fpp_$1 and am__cv_fc_fpp_flags_$1
+ # accordingly.
+ if test $am__cv_fc_fpp_depmode_$1 = cpp; then
+   am__cv_fc_fpp_$1=cpp
+ else
+   am__cv_fc_fpp_$1='$(FC)'
+ fi
+
+ am__cv_fc_fpp_flags_$1=''  # Nothing needed here yet
+ AC_SUBST([am__cv_fc_fpp_$1])
+ AC_SUBST([am__cv_fc_fpp_flags_$1])
+])
+
+
+# AM_FC_MOD_OBEY_INTERDEPS([EXT])
+# --------------------------------
+# Tells automake to include Fortran files of extension EXT into its 
interdepency
+# tracking.
+# This is necessary, because files that contain a MODULE statement must be
+# compiled before the files that USE the corresponding modules.
+AC_DEFUN([AM_FC_MOD_OBEY_INTERDEPS],
+[AC_REQUIRE([AM_MAKE_INCLUDE])
+ AC_REQUIRE([AC_FC_MODULE_FLAG])
+ AC_REQUIRE([AM_OUTPUT_FC_MOD_DEP_COMMANDS])
+ AC_SUBST([am_fc_mod_obey_interdeps_$1], [yes])
+ case $1 in
+  F90 | F95 | F03 | F08)
+    _AM_FC_FPP_DEPMODE([$1])
+    ;;
+  f90 | f95 | f03 | f08)
+    ;;
+  *)
+    AC_MSG_ERROR([Fortran files of extension .$1 not supported by automake 
interdependency tracking])
+    ;;   
+ esac
+ 
+ FDEPDIR=.fdeps
+ AC_SUBST([FDEPDIR])
+])
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 8502409..5b34d5f 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -470,6 +470,7 @@ fort4.test \
 fort5.test \
 fonly.test \
 fortdep.test \
+fort_obey_mod_interdeps.test \
 gcj.test \
 gcj2.test \
 gcj3.test \
diff --git a/tests/Makefile.in b/tests/Makefile.in
index 5b57141..9279013 100644
--- a/tests/Makefile.in
+++ b/tests/Makefile.in
@@ -743,6 +743,7 @@ fort4.test \
 fort5.test \
 fonly.test \
 fortdep.test \
+fort_obey_mod_interdeps.test \
 gcj.test \
 gcj2.test \
 gcj3.test \
diff --git a/tests/fort_obey_mod_interdeps.test 
b/tests/fort_obey_mod_interdeps.test
new file mode 100755
index 0000000..f001c8f
--- /dev/null
+++ b/tests/fort_obey_mod_interdeps.test
@@ -0,0 +1,163 @@
+#!/bin/sh
+# Copyright (C) 2011 Free Software Foundation, Inc.
+#
+# This file is part of GNU Automake.
+#
+# GNU Automake is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# GNU Automake is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Automake; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+
+# Test whether Automake's interdependency tracking for Fortran 90+ modules
+# works as expected.
+required='GNUmake gfortran libtoolize'
+. ./defs || exit 1
+
+
+# Build up some test Fortran project with both, libtool and
+# non-libtool targets and preprocessed/non-preprocessed Fortran files.
+mkdir src
+mkdir lib
+mkdir ltlib
+mkdir config
+
+cat >> configure.in <<EOF
+LT_INIT
+
+AC_PROG_FC
+AC_PROG_RANLIB
+
+AM_FC_MOD_OBEY_INTERDEPS([F90])
+AM_FC_MOD_OBEY_INTERDEPS([f90])
+
+AC_CONFIG_FILES([lib/Makefile ltlib/Makefile src/Makefile])
+AC_OUTPUT
+EOF
+
+cat > Makefile.am <<EOF
+SUBDIRS = lib ltlib src .
+EOF
+
+cat > lib/Makefile.am <<EOF
+AM_FCFLAGS=\$(FC_MODINC) .
+
+noinst_LIBRARIES = libnasty.a
+libnasty_a_SOURCES = nasty2.f90 \\
+       nasty1.F90 \\
+       nasty1.h
+EOF
+
+cat > lib/nasty1.F90 <<EOF
+#include "nasty1.h"
+EOF
+
+cat > lib/nasty1.h <<EOF
+MODULE lib1
+ CONTAINS
+ 
+ SUBROUTINE sub1
+      print *, 'lib1'
+ END SUBROUTINE sub1
+END MODULE lib1
+EOF
+
+cat > lib/nasty2.f90 <<EOF
+MODULE lib2
+ CONTAINS
+ 
+ SUBROUTINE sub2
+      USE lib1
+      print *, 'lib2'
+ END SUBROUTINE sub2
+END MODULE lib2
+EOF
+
+cat > ltlib/Makefile.am <<EOF
+AM_FCFLAGS=\$(FC_MODINC) .
+
+noinst_LTLIBRARIES = libnasty.la
+libnasty_la_SOURCES = nasty2.f90 nasty1.F90 nasty1.h
+EOF
+
+cat > ltlib/nasty1.F90 <<EOF
+#include "nasty1.h"
+EOF
+
+cat > ltlib/nasty1.h <<EOF
+MODULE ltlib1
+ CONTAINS
+ 
+ SUBROUTINE ltsub1
+      print *, 'ltlib1'
+ END SUBROUTINE ltsub1
+END MODULE ltlib1
+EOF
+
+cat > ltlib/nasty2.f90 <<EOF
+MODULE ltlib2
+ CONTAINS
+ 
+ SUBROUTINE ltsub2
+      USE ltlib1
+      print *, 'ltlib2'
+ END SUBROUTINE ltsub2
+END MODULE ltlib2
+EOF
+
+cat > src/Makefile.am <<EOF
+noinst_PROGRAMS = test \\
+       \\
+       lttest
+AM_FCFLAGS=\$(FC_MODINC) . \$(FC_MODINC) \$(top_builddir)/lib
+
+test_SOURCES = test.F90 test.h
+test_LDADD = \$(top_builddir)/lib/libnasty.a
+
+lttest_SOURCES = lttest.f90
+lttest_FCFLAGS = \$(FC_MODINC) . \$(FC_MODINC)../ltlib
+lttest_LDADD = \$(top_builddir)/ltlib/libnasty.la
+EOF
+
+cat > src/test.F90 <<EOF
+#include "test.h"
+       USE lib2
+       
+       call sub1
+       call sub2
+END PROGRAM test
+EOF
+
+cat > src/test.h <<EOF
+PROGRAM test
+      USE lib1
+EOF
+
+cat > src/lttest.f90 <<EOF
+PROGRAM lttest
+      USE ltlib1
+      USE ltlib2
+      call ltsub1
+      call ltsub2
+END PROGRAM lttest
+EOF
+
+# And try to build the test project
+libtoolize
+$ACLOCAL
+$AUTOMAKE -a
+$AUTOCONF
+
+./configure
+$MAKE
+
+Exit 0
-- 
1.7.4.1





reply via email to

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