summaryrefslogtreecommitdiffstats
path: root/src/engine/SCons/Tool/fortran.py
diff options
context:
space:
mode:
authorSteven Knight <knight@baldmt.com>2004-07-29 13:22:43 (GMT)
committerSteven Knight <knight@baldmt.com>2004-07-29 13:22:43 (GMT)
commit39c71db4a22f03bf17a39fa84ff6abe84e4f0d51 (patch)
tree26e7f0319f29604b9c80df73009b768d1f0067a6 /src/engine/SCons/Tool/fortran.py
parent6a1ff461cdea7e26330ebcdce821ae5a95e415ce (diff)
downloadSCons-39c71db4a22f03bf17a39fa84ff6abe84e4f0d51.zip
SCons-39c71db4a22f03bf17a39fa84ff6abe84e4f0d51.tar.gz
SCons-39c71db4a22f03bf17a39fa84ff6abe84e4f0d51.tar.bz2
Add Fortran 90/95 support. (Chris Murray)
Diffstat (limited to 'src/engine/SCons/Tool/fortran.py')
-rw-r--r--src/engine/SCons/Tool/fortran.py165
1 files changed, 165 insertions, 0 deletions
diff --git a/src/engine/SCons/Tool/fortran.py b/src/engine/SCons/Tool/fortran.py
new file mode 100644
index 0000000..5e2b5eb
--- /dev/null
+++ b/src/engine/SCons/Tool/fortran.py
@@ -0,0 +1,165 @@
+"""SCons.Tool.fortran
+
+Tool-specific initialization for a generic Posix f77/f90 Fortran compiler.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import re
+import string
+
+import SCons.Action
+import SCons.Defaults
+import SCons.Scanner.Fortran
+import SCons.Tool
+import SCons.Util
+
+compilers = ['f95', 'f90', 'f77']
+
+FortranAction = SCons.Action.Action("$FORTRANCOM")
+ShFortranAction = SCons.Action.Action("$SHFORTRANCOM")
+FortranPPAction = SCons.Action.Action("$FORTRANPPCOM")
+ShFortranPPAction = SCons.Action.Action("$SHFORTRANPPCOM")
+
+#
+# Not yet sure how to deal with fortran pre-processor functions.
+# Different compilers do this differently in modern fortran. Some still
+# rely on the c pre-processor, some (like cvf, ivf) have their own
+# pre-processor technology and use intermediary suffixes (.i90)
+#
+FortranSuffixes = [".f", ".for", ".ftn", ]
+FortranPPSuffixes = ['.fpp', '.FPP']
+upper_case = [".F", ".FOR", ".FTN"]
+if SCons.Util.case_sensitive_suffixes('.f', '.F'):
+ FortranPPSuffixes.extend(upper_case)
+else:
+ FortranSuffixes.extend(upper_case)
+
+#
+FortranScan = SCons.Scanner.Fortran.FortranScan("FORTRANPATH")
+
+for suffix in FortranSuffixes + FortranPPSuffixes:
+ SCons.Defaults.ObjSourceScan.add_scanner(suffix, FortranScan)
+
+#
+def _fortranEmitter(target, source, env):
+ node = source[0].rfile()
+ if not node.exists() and not node.is_derived():
+ print "Could not locate " + str(node.name)
+ return ([], [])
+ mod_regex = """(?i)^\s*MODULE\s+(?!PROCEDURE)(\w+)"""
+ cre = re.compile(mod_regex,re.M)
+ # Retrieve all USE'd module names
+ modules = cre.findall(node.get_contents())
+ # Remove unique items from the list
+ modules = SCons.Util.unique(modules)
+ # Convert module name to a .mod filename
+ suffix = env.subst('$FORTRANMODSUFFIX')
+ modules = map(lambda x, s=suffix: string.lower(x) + s, modules)
+ for m in modules:
+ target.append(m)
+ return (target, source)
+
+def FortranEmitter(target, source, env):
+ target, source = _fortranEmitter(target, source, env)
+ return SCons.Defaults.StaticObjectEmitter(target, source, env)
+
+def ShFortranEmitter(target, source, env):
+ target, source = _fortranEmitter(target, source, env)
+ return SCons.Defaults.SharedObjectEmitter(target, source, env)
+
+class VariableListGenerator:
+ def __init__(self, *variablelist):
+ self.variablelist = variablelist
+ def __call__(self, env, target, source, for_signature):
+ for v in self.variablelist:
+ try: return env[v]
+ except KeyError: pass
+ return ''
+
+FortranGenerator = VariableListGenerator('FORTRAN', 'F77', '_FORTRAND')
+FortranFlagsGenerator = VariableListGenerator('FORTRANFLAGS', 'F77FLAGS')
+ShFortranGenerator = VariableListGenerator('SHFORTRAN', 'SHF77', 'FORTRAN', 'F77', '_FORTRAND')
+ShFortranFlagsGenerator = VariableListGenerator('SHFORTRANFLAGS', 'SHF77FLAGS')
+
+def add_to_env(env):
+ """Add Builders and construction variables for Fortran to an Environment."""
+
+ env['_FORTRANG'] = FortranGenerator
+ env['_FORTRANFLAGSG'] = FortranFlagsGenerator
+ env['FORTRANCOM'] = '$_FORTRANG $_FORTRANFLAGSG $_FORTRANINCFLAGS $_FORTRANMODFLAG -c -o $TARGET $SOURCES'
+ env['FORTRANPPCOM'] = '$_FORTRANG $_FORTRANFLAGSG $CPPFLAGS $_CPPDEFFLAGS $_FORTRANINCFLAGS $_FORTRANMODFLAG -c -o $TARGET $SOURCES'
+
+ env['_SHFORTRANG'] = ShFortranGenerator
+ env['_SHFORTRANFLAGSG'] = ShFortranFlagsGenerator
+ env['SHFORTRANCOM'] = '$_SHFORTRANG $_SHFORTRANFLAGSG $_FORTRANINCFLAGS $_FORTRANMODFLAG -c -o $TARGET $SOURCES'
+ env['SHFORTRANPPCOM'] = '$_SHFORTRANG $_SHFORTRANFLAGSG $CPPFLAGS $_CPPDEFFLAGS $_FORTRANINCFLAGS $_FORTRANMODFLAG -c -o $TARGET $SOURCES'
+
+ env['_FORTRANINCFLAGS'] = '$( ${_concat(INCPREFIX, FORTRANPATH, INCSUFFIX, __env__, RDirs)} $)'
+
+ env['FORTRANMODPREFIX'] = '' # like $LIBPREFIX
+ env['FORTRANMODSUFFIX'] = '.mod' # like $LIBSUFFIX
+
+ env['FORTRANMODDIR'] = '' # where the compiler should place .mod files
+ env['FORTRANMODDIRPREFIX'] = '' # some prefix to $FORTRANMODDIR - similar to $INCPREFIX
+ env['FORTRANMODDIRSUFFIX'] = '' # some suffix to $FORTRANMODDIR - similar to $INCSUFFIX
+ env['_FORTRANMODFLAG'] = '$( ${_concat(FORTRANMODDIRPREFIX, FORTRANMODDIR, FORTRANMODDIRSUFFIX, __env__)} $)'
+
+ env.AppendUnique(FORTRANSUFFIXES = FortranSuffixes + FortranPPSuffixes)
+
+ static_obj, shared_obj = SCons.Tool.createObjBuilders(env)
+
+ for suffix in FortranSuffixes:
+ static_obj.add_action(suffix, FortranAction)
+ shared_obj.add_action(suffix, ShFortranAction)
+ static_obj.add_emitter(suffix, FortranEmitter)
+ shared_obj.add_emitter(suffix, ShFortranEmitter)
+
+ for suffix in FortranPPSuffixes:
+ static_obj.add_action(suffix, FortranPPAction)
+ shared_obj.add_action(suffix, ShFortranPPAction)
+ static_obj.add_emitter(suffix, FortranEmitter)
+ shared_obj.add_emitter(suffix, ShFortranEmitter)
+
+def generate(env):
+ import f77
+ import f90
+ import f95
+ f77.add_to_env(env)
+ f90.add_to_env(env)
+ f95.add_to_env(env)
+
+ add_to_env(env)
+
+ env['_FORTRAND'] = env.Detect(compilers) or 'f77'
+
+def exists(env):
+ return env.Detect(compilers)