8d3204ff148d7f8c8d98f1e42c294cdced579f35
[senf.git] / scons / scons-1.2.0 / engine / SCons / Tool / FortranCommon.py
1 """SCons.Tool.FortranCommon
2
3 Stuff for processing Fortran, common to all fortran dialects.
4
5 """
6
7 #
8 # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
9 #
10 # Permission is hereby granted, free of charge, to any person obtaining
11 # a copy of this software and associated documentation files (the
12 # "Software"), to deal in the Software without restriction, including
13 # without limitation the rights to use, copy, modify, merge, publish,
14 # distribute, sublicense, and/or sell copies of the Software, and to
15 # permit persons to whom the Software is furnished to do so, subject to
16 # the following conditions:
17 #
18 # The above copyright notice and this permission notice shall be included
19 # in all copies or substantial portions of the Software.
20 #
21 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
22 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
23 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 #
29
30 __revision__ = "src/engine/SCons/Tool/FortranCommon.py 3842 2008/12/20 22:59:52 scons"
31
32 import re
33 import string
34 import os.path
35
36 import SCons.Action
37 import SCons.Defaults
38 import SCons.Scanner.Fortran
39 import SCons.Tool
40 import SCons.Util
41
42 def isfortran(env, source):
43     """Return 1 if any of code in source has fortran files in it, 0
44     otherwise."""
45     try:
46         fsuffixes = env['FORTRANSUFFIXES']
47     except KeyError:
48         # If no FORTRANSUFFIXES, no fortran tool, so there is no need to look
49         # for fortran sources.
50         return 0
51
52     if not source:
53         # Source might be None for unusual cases like SConf.
54         return 0
55     for s in source:
56         if s.sources:
57             ext = os.path.splitext(str(s.sources[0]))[1]
58             if ext in fsuffixes:
59                 return 1
60     return 0
61
62 def _fortranEmitter(target, source, env):
63     node = source[0].rfile()
64     if not node.exists() and not node.is_derived():
65        print "Could not locate " + str(node.name)
66        return ([], [])
67     mod_regex = """(?i)^\s*MODULE\s+(?!PROCEDURE)(\w+)"""
68     cre = re.compile(mod_regex,re.M)
69     # Retrieve all USE'd module names
70     modules = cre.findall(node.get_contents())
71     # Remove unique items from the list
72     modules = SCons.Util.unique(modules)
73     # Convert module name to a .mod filename
74     suffix = env.subst('$FORTRANMODSUFFIX', target=target, source=source)
75     moddir = env.subst('$FORTRANMODDIR', target=target, source=source)
76     modules = map(lambda x, s=suffix: string.lower(x) + s, modules)
77     for m in modules:
78        target.append(env.fs.File(m, moddir))
79     return (target, source)
80
81 def FortranEmitter(target, source, env):
82     target, source = _fortranEmitter(target, source, env)
83     return SCons.Defaults.StaticObjectEmitter(target, source, env)
84
85 def ShFortranEmitter(target, source, env):
86     target, source = _fortranEmitter(target, source, env)
87     return SCons.Defaults.SharedObjectEmitter(target, source, env)
88
89 def ComputeFortranSuffixes(suffixes, ppsuffixes):
90     """suffixes are fortran source files, and ppsuffixes the ones to be
91     pre-processed. Both should be sequences, not strings."""
92     assert len(suffixes) > 0
93     s = suffixes[0]
94     sup = string.upper(s)
95     upper_suffixes = map(string.upper, suffixes)
96     if SCons.Util.case_sensitive_suffixes(s, sup):
97         ppsuffixes.extend(upper_suffixes)
98     else:
99         suffixes.extend(upper_suffixes)
100
101 def CreateDialectActions(dialect):
102     """Create dialect specific actions."""
103     CompAction = SCons.Action.Action('$%sCOM ' % dialect, '$%sCOMSTR' % dialect)
104     CompPPAction = SCons.Action.Action('$%sPPCOM ' % dialect, '$%sPPCOMSTR' % dialect)
105     ShCompAction = SCons.Action.Action('$SH%sCOM ' % dialect, '$SH%sCOMSTR' % dialect)
106     ShCompPPAction = SCons.Action.Action('$SH%sPPCOM ' % dialect, '$SH%sPPCOMSTR' % dialect)
107
108     return CompAction, CompPPAction, ShCompAction, ShCompPPAction
109
110 def DialectAddToEnv(env, dialect, suffixes, ppsuffixes, support_module = 0):
111     """Add dialect specific construction variables."""
112     ComputeFortranSuffixes(suffixes, ppsuffixes)
113
114     fscan = SCons.Scanner.Fortran.FortranScan("%sPATH" % dialect)
115
116     for suffix in suffixes + ppsuffixes:
117         SCons.Tool.SourceFileScanner.add_scanner(suffix, fscan)
118
119     env.AppendUnique(FORTRANSUFFIXES = suffixes + ppsuffixes)
120
121     compaction, compppaction, shcompaction, shcompppaction = \
122             CreateDialectActions(dialect)
123
124     static_obj, shared_obj = SCons.Tool.createObjBuilders(env)
125
126     for suffix in suffixes:
127         static_obj.add_action(suffix, compaction)
128         shared_obj.add_action(suffix, shcompaction)
129         static_obj.add_emitter(suffix, FortranEmitter)
130         shared_obj.add_emitter(suffix, ShFortranEmitter)
131
132     for suffix in ppsuffixes:
133         static_obj.add_action(suffix, compppaction)
134         shared_obj.add_action(suffix, shcompppaction)
135         static_obj.add_emitter(suffix, FortranEmitter)
136         shared_obj.add_emitter(suffix, ShFortranEmitter)
137
138     if not env.has_key('%sFLAGS' % dialect):
139         env['%sFLAGS' % dialect] = SCons.Util.CLVar('')
140
141     if not env.has_key('SH%sFLAGS' % dialect):
142         env['SH%sFLAGS' % dialect] = SCons.Util.CLVar('$%sFLAGS' % dialect)
143
144     # If a tool does not define fortran prefix/suffix for include path, use C ones
145     if not env.has_key('INC%sPREFIX' % dialect):
146         env['INC%sPREFIX' % dialect] = '$INCPREFIX'
147
148     if not env.has_key('INC%sSUFFIX' % dialect):
149         env['INC%sSUFFIX' % dialect] = '$INCSUFFIX'
150
151     env['_%sINCFLAGS' % dialect] = '$( ${_concat(INC%sPREFIX, %sPATH, INC%sSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)' % (dialect, dialect, dialect)
152
153     if support_module == 1:
154         env['%sCOM' % dialect]     = '$%s -o $TARGET -c $%sFLAGS $_%sINCFLAGS $_FORTRANMODFLAG $SOURCES' % (dialect, dialect, dialect)
155         env['%sPPCOM' % dialect]   = '$%s -o $TARGET -c $%sFLAGS $CPPFLAGS $_CPPDEFFLAGS $_%sINCFLAGS $_FORTRANMODFLAG $SOURCES' % (dialect, dialect, dialect)
156         env['SH%sCOM' % dialect]    = '$SH%s -o $TARGET -c $SH%sFLAGS $_%sINCFLAGS $_FORTRANMODFLAG $SOURCES' % (dialect, dialect, dialect)
157         env['SH%sPPCOM' % dialect]  = '$SH%s -o $TARGET -c $SH%sFLAGS $CPPFLAGS $_CPPDEFFLAGS $_%sINCFLAGS $_FORTRANMODFLAG $SOURCES' % (dialect, dialect, dialect)
158     else:
159         env['%sCOM' % dialect]     = '$%s -o $TARGET -c $%sFLAGS $_%sINCFLAGS $SOURCES' % (dialect, dialect, dialect)
160         env['%sPPCOM' % dialect]   = '$%s -o $TARGET -c $%sFLAGS $CPPFLAGS $_CPPDEFFLAGS $_%sINCFLAGS $SOURCES' % (dialect, dialect, dialect)
161         env['SH%sCOM' % dialect]    = '$SH%s -o $TARGET -c $SH%sFLAGS $_%sINCFLAGS $SOURCES' % (dialect, dialect, dialect)
162         env['SH%sPPCOM' % dialect]  = '$SH%s -o $TARGET -c $SH%sFLAGS $CPPFLAGS $_CPPDEFFLAGS $_%sINCFLAGS $SOURCES' % (dialect, dialect, dialect)
163
164 def add_fortran_to_env(env):
165     """Add Builders and construction variables for Fortran to an Environment."""
166     try:
167         FortranSuffixes = env['FORTRANFILESUFFIXES']
168     except KeyError:
169         FortranSuffixes = ['.f', '.for', '.ftn']
170
171     #print "Adding %s to fortran suffixes" % FortranSuffixes
172     try:
173         FortranPPSuffixes = env['FORTRANPPFILESUFFIXES']
174     except KeyError:
175         FortranPPSuffixes = ['.fpp', '.FPP']
176
177     DialectAddToEnv(env, "FORTRAN", FortranSuffixes,
178                     FortranPPSuffixes, support_module = 1)
179
180     env['FORTRANMODPREFIX'] = ''     # like $LIBPREFIX
181     env['FORTRANMODSUFFIX'] = '.mod' # like $LIBSUFFIX
182
183     env['FORTRANMODDIR'] = ''          # where the compiler should place .mod files
184     env['FORTRANMODDIRPREFIX'] = ''    # some prefix to $FORTRANMODDIR - similar to $INCPREFIX
185     env['FORTRANMODDIRSUFFIX'] = ''    # some suffix to $FORTRANMODDIR - similar to $INCSUFFIX
186     env['_FORTRANMODFLAG'] = '$( ${_concat(FORTRANMODDIRPREFIX, FORTRANMODDIR, FORTRANMODDIRSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)'
187
188 def add_f77_to_env(env):
189     """Add Builders and construction variables for f77 to an Environment."""
190     try:
191         F77Suffixes = env['F77FILESUFFIXES']
192     except KeyError:
193         F77Suffixes = ['.f77']
194
195     #print "Adding %s to f77 suffixes" % F77Suffixes
196     try:
197         F77PPSuffixes = env['F77PPFILESUFFIXES']
198     except KeyError:
199         F77PPSuffixes = []
200
201     DialectAddToEnv(env, "F77", F77Suffixes, F77PPSuffixes)
202
203 def add_f90_to_env(env):
204     """Add Builders and construction variables for f90 to an Environment."""
205     try:
206         F90Suffixes = env['F90FILESUFFIXES']
207     except KeyError:
208         F90Suffixes = ['.f90']
209
210     #print "Adding %s to f90 suffixes" % F90Suffixes
211     try:
212         F90PPSuffixes = env['F90PPFILESUFFIXES']
213     except KeyError:
214         F90PPSuffixes = []
215
216     DialectAddToEnv(env, "F90", F90Suffixes, F90PPSuffixes,
217                     support_module = 1)
218
219 def add_f95_to_env(env):
220     """Add Builders and construction variables for f95 to an Environment."""
221     try:
222         F95Suffixes = env['F95FILESUFFIXES']
223     except KeyError:
224         F95Suffixes = ['.f95']
225
226     #print "Adding %s to f95 suffixes" % F95Suffixes
227     try:
228         F95PPSuffixes = env['F95PPFILESUFFIXES']
229     except KeyError:
230         F95PPSuffixes = []
231
232     DialectAddToEnv(env, "F95", F95Suffixes, F95PPSuffixes,
233                     support_module = 1)
234
235 def add_all_to_env(env):
236     """Add builders and construction variables for all supported fortran
237     dialects."""
238     add_fortran_to_env(env)
239     add_f77_to_env(env)
240     add_f90_to_env(env)
241     add_f95_to_env(env)