Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,12 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER
to add a path to the execution environment if it was discovered in
default_paths. Previously, the routine, called by many tool modules,
never altered the execution environment, leaving it to the tools.
- A new construction variable FORTRANCOMMONFLAGS is added which is
applied to all Fortran dialects, in case someone needs to set some
flags globally. FORTRANFLAGS looked like it was intended for that,
but was not applied to other dialects, and e2e tests explicitly checked
that FORTRANFLAGS did not propagate outside the FORTRAN dialect,
so the conclusion is that behavior is intentional (issue #2257)

From Zhichang Yu:
- Added MSVC_USE_SCRIPT_ARGS variable to pass arguments to MSVC_USE_SCRIPT.
Expand Down
2 changes: 2 additions & 0 deletions RELEASE.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ NEW FUNCTIONALITY
is taken and the constructed environment is likely incomplete. As implemented, the default
global policy is "warning". The ability to set the global policy via an SCons command-line
option may be added in a future enhancement.
- Fortran: a new construction variable FORTRANCOMMONFLAGS is added which is
applied to all Fortran dialects, to enable global (all-dialect) settings.


DEPRECATED FUNCTIONALITY
Expand Down
178 changes: 89 additions & 89 deletions SCons/Tool/FortranCommon.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,43 +21,48 @@
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

"""

Stuff for processing Fortran, common to all fortran dialects.

"""
"""Routines for setting up Fortran, common to all dialects."""

import re
import os.path
from typing import Tuple

import SCons.Action
import SCons.Scanner.Fortran
import SCons.Tool
import SCons.Util
from SCons.Action import Action


def isfortran(env, source) -> bool:
"""Returns True if source has any fortran files in it.

def isfortran(env, source):
"""Return 1 if any of code in source has fortran files in it, 0
otherwise."""
Only checks based on filename suffixes, does not examine code.
"""
try:
fsuffixes = env['FORTRANSUFFIXES']
except KeyError:
# If no FORTRANSUFFIXES, no fortran tool, so there is no need to look
# for fortran sources.
return 0
return False

if not source:
# Source might be None for unusual cases like SConf.
return 0
return False
for s in source:
if s.sources:
ext = os.path.splitext(str(s.sources[0]))[1]
if ext in fsuffixes:
return 1
return 0
return True
return False


def _fortranEmitter(target, source, env):
def _fortranEmitter(target, source, env) -> Tuple:
"""Common code for Fortran emitter.

Called by both the static and shared object emitters,
mainly to account for generated module files.
"""

node = source[0].rfile()
if not node.exists() and not node.is_derived():
print("Could not locate " + str(node.name))
Expand All @@ -78,21 +83,29 @@ def _fortranEmitter(target, source, env):
return (target, source)


def FortranEmitter(target, source, env):
def FortranEmitter(target, source, env) -> Tuple:
import SCons.Defaults
target, source = _fortranEmitter(target, source, env)
return SCons.Defaults.StaticObjectEmitter(target, source, env)


def ShFortranEmitter(target, source, env):
def ShFortranEmitter(target, source, env) -> Tuple:
import SCons.Defaults
target, source = _fortranEmitter(target, source, env)
return SCons.Defaults.SharedObjectEmitter(target, source, env)


def ComputeFortranSuffixes(suffixes, ppsuffixes):
"""suffixes are fortran source files, and ppsuffixes the ones to be
pre-processed. Both should be sequences, not strings."""
def ComputeFortranSuffixes(suffixes, ppsuffixes) -> None:
"""Update the suffix lists to reflect the platform requirements.

If upper-cased suffixes can be distinguished from lower, those are
added to *ppsuffixes*. If not, they are added to *suffixes*.

Args:
suffixes (list): indicate regular Fortran source files
ppsuffixes (list): indicate Fortran source files that should be
be run through the pre-processor
"""
assert len(suffixes) > 0
s = suffixes[0]
sup = s.upper()
Expand All @@ -102,31 +115,34 @@ def ComputeFortranSuffixes(suffixes, ppsuffixes):
else:
suffixes.extend(upper_suffixes)


def CreateDialectActions(dialect):
def CreateDialectActions(dialect) -> Tuple[Action, Action, Action, Action]:
"""Create dialect specific actions."""
CompAction = SCons.Action.Action('$%sCOM ' % dialect, '$%sCOMSTR' % dialect)
CompPPAction = SCons.Action.Action('$%sPPCOM ' % dialect, '$%sPPCOMSTR' % dialect)
ShCompAction = SCons.Action.Action('$SH%sCOM ' % dialect, '$SH%sCOMSTR' % dialect)
ShCompPPAction = SCons.Action.Action('$SH%sPPCOM ' % dialect, '$SH%sPPCOMSTR' % dialect)

CompAction = Action(f'${dialect}COM ', cmdstr=f'${dialect}COMSTR')
CompPPAction = Action(f'${dialect}PPCOM ', cmdstr=f'${dialect}PPCOMSTR')
ShCompAction = Action(f'$SH{dialect}COM ', cmdstr=f'$SH{dialect}COMSTR')
ShCompPPAction = Action(f'$SH{dialect}PPCOM ', cmdstr=f'$SH{dialect}PPCOMSTR')
return CompAction, CompPPAction, ShCompAction, ShCompPPAction


def DialectAddToEnv(env, dialect, suffixes, ppsuffixes, support_module=False):
"""Add dialect specific construction variables."""
ComputeFortranSuffixes(suffixes, ppsuffixes)
def DialectAddToEnv(env, dialect, suffixes, ppsuffixes, support_mods=False) -> None:
"""Add dialect specific construction variables.

fscan = SCons.Scanner.Fortran.FortranScan("%sPATH" % dialect)
Args:
dialect (str): dialect name
suffixes (list): suffixes associated with this dialect
ppsuffixes (list): suffixes using cpp associated with this dialect
support_mods (bool): whether this dialect supports modules
"""
ComputeFortranSuffixes(suffixes, ppsuffixes)

fscan = SCons.Scanner.Fortran.FortranScan(f"{dialect}PATH")
for suffix in suffixes + ppsuffixes:
SCons.Tool.SourceFileScanner.add_scanner(suffix, fscan)

env.AppendUnique(FORTRANSUFFIXES = suffixes + ppsuffixes)
env.AppendUnique(FORTRANSUFFIXES=suffixes + ppsuffixes)

compaction, compppaction, shcompaction, shcompppaction = \
CreateDialectActions(dialect)

static_obj, shared_obj = SCons.Tool.createObjBuilders(env)

for suffix in suffixes:
Expand All @@ -141,124 +157,111 @@ def DialectAddToEnv(env, dialect, suffixes, ppsuffixes, support_module=False):
static_obj.add_emitter(suffix, FortranEmitter)
shared_obj.add_emitter(suffix, ShFortranEmitter)

if '%sFLAGS' % dialect not in env:
env['%sFLAGS' % dialect] = SCons.Util.CLVar('')

if 'SH%sFLAGS' % dialect not in env:
env['SH%sFLAGS' % dialect] = SCons.Util.CLVar('$%sFLAGS' % dialect)
if f'{dialect}FLAGS' not in env:
env[f'{dialect}FLAGS'] = SCons.Util.CLVar('')
if f'SH{dialect}FLAGS' not in env:
env[f'SH{dialect}FLAGS'] = SCons.Util.CLVar(f'${dialect}FLAGS')

# If a tool does not define fortran prefix/suffix for include path, use C ones
if 'INC%sPREFIX' % dialect not in env:
env['INC%sPREFIX' % dialect] = '$INCPREFIX'

if 'INC%sSUFFIX' % dialect not in env:
env['INC%sSUFFIX' % dialect] = '$INCSUFFIX'

env['_%sINCFLAGS' % dialect] = '${_concat(INC%sPREFIX, %sPATH, INC%sSUFFIX, __env__, RDirs, TARGET, SOURCE, affect_signature=False)}' % (dialect, dialect, dialect)

if support_module:
env['%sCOM' % dialect] = '$%s -o $TARGET -c $%sFLAGS $_%sINCFLAGS $_FORTRANMODFLAG $SOURCES' % (dialect, dialect, dialect)
env['%sPPCOM' % dialect] = '$%s -o $TARGET -c $%sFLAGS $CPPFLAGS $_CPPDEFFLAGS $_%sINCFLAGS $_FORTRANMODFLAG $SOURCES' % (dialect, dialect, dialect)
env['SH%sCOM' % dialect] = '$SH%s -o $TARGET -c $SH%sFLAGS $_%sINCFLAGS $_FORTRANMODFLAG $SOURCES' % (dialect, dialect, dialect)
env['SH%sPPCOM' % dialect] = '$SH%s -o $TARGET -c $SH%sFLAGS $CPPFLAGS $_CPPDEFFLAGS $_%sINCFLAGS $_FORTRANMODFLAG $SOURCES' % (dialect, dialect, dialect)
if f'INC{dialect}PREFIX' not in env:
env[f'INC{dialect}PREFIX'] = '$INCPREFIX'
if f'INC{dialect}SUFFIX' not in env:
env[f'INC{dialect}SUFFIX'] = '$INCSUFFIX'

env[f'_{dialect}INCFLAGS'] = f'${{_concat(INC{dialect}PREFIX, {dialect}PATH, INC{dialect}SUFFIX, __env__, RDirs, TARGET, SOURCE, affect_signature=False)}}'

if support_mods:
env[f'{dialect}COM'] = f'${dialect} -o $TARGET -c $FORTRANCOMMONFLAGS ${dialect}FLAGS $_{dialect}INCFLAGS $_FORTRANMODFLAG $SOURCES'
env[f'{dialect}PPCOM'] = f'${dialect} -o $TARGET -c $FORTRANCOMMONFLAGS ${dialect}FLAGS $CPPFLAGS $_CPPDEFFLAGS $_{dialect}INCFLAGS $_FORTRANMODFLAG $SOURCES'
env[f'SH{dialect}COM'] = f'$SH{dialect} -o $TARGET -c $FORTRANCOMMONFLAGS $SH{dialect}FLAGS $_{dialect}INCFLAGS $_FORTRANMODFLAG $SOURCES'
env[f'SH{dialect}PPCOM'] = f'$SH{dialect} -o $TARGET -c $FORTRANCOMMONFLAGS $SH{dialect}FLAGS $CPPFLAGS $_CPPDEFFLAGS $_{dialect}INCFLAGS $_FORTRANMODFLAG $SOURCES'
else:
env['%sCOM' % dialect] = '$%s -o $TARGET -c $%sFLAGS $_%sINCFLAGS $SOURCES' % (dialect, dialect, dialect)
env['%sPPCOM' % dialect] = '$%s -o $TARGET -c $%sFLAGS $CPPFLAGS $_CPPDEFFLAGS $_%sINCFLAGS $SOURCES' % (dialect, dialect, dialect)
env['SH%sCOM' % dialect] = '$SH%s -o $TARGET -c $SH%sFLAGS $_%sINCFLAGS $SOURCES' % (dialect, dialect, dialect)
env['SH%sPPCOM' % dialect] = '$SH%s -o $TARGET -c $SH%sFLAGS $CPPFLAGS $_CPPDEFFLAGS $_%sINCFLAGS $SOURCES' % (dialect, dialect, dialect)
env[f'{dialect}COM'] = f'${dialect} -o $TARGET -c $FORTRANCOMMONFLAGS ${dialect}FLAGS $_{dialect}INCFLAGS $SOURCES'
env[f'{dialect}PPCOM'] = f'${dialect} -o $TARGET -c $FORTRANCOMMONFLAGS ${dialect}FLAGS $CPPFLAGS $_CPPDEFFLAGS $_{dialect}INCFLAGS $SOURCES'
env[f'SH{dialect}COM'] = f'$SH{dialect} -o $TARGET -c $FORTRANCOMMONFLAGS $SH{dialect}FLAGS $_{dialect}INCFLAGS $SOURCES'
env[f'SH{dialect}PPCOM'] = f'$SH{dialect} -o $TARGET -c $FORTRANCOMMONFLAGS $SH{dialect}FLAGS $CPPFLAGS $_CPPDEFFLAGS $_{dialect}INCFLAGS $SOURCES'


def add_fortran_to_env(env):
"""Add Builders and construction variables for Fortran to an Environment."""
def add_fortran_to_env(env) -> None:
"""Add Builders and construction variables for Fortran/generic."""
try:
FortranSuffixes = env['FORTRANFILESUFFIXES']
except KeyError:
FortranSuffixes = ['.f', '.for', '.ftn']

#print("Adding %s to fortran suffixes" % FortranSuffixes)
try:
FortranPPSuffixes = env['FORTRANPPFILESUFFIXES']
except KeyError:
FortranPPSuffixes = ['.fpp', '.FPP']

DialectAddToEnv(env, "FORTRAN", FortranSuffixes,
FortranPPSuffixes, support_module=True)
DialectAddToEnv(env, "FORTRAN", FortranSuffixes, FortranPPSuffixes, support_mods=True)

# Module support
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__, RDirs, TARGET, SOURCE)} $)'

def add_f77_to_env(env):
"""Add Builders and construction variables for f77 to an Environment."""
def add_f77_to_env(env) -> None:
"""Add Builders and construction variables for f77 dialect."""
try:
F77Suffixes = env['F77FILESUFFIXES']
except KeyError:
F77Suffixes = ['.f77']

#print("Adding %s to f77 suffixes" % F77Suffixes)
try:
F77PPSuffixes = env['F77PPFILESUFFIXES']
except KeyError:
F77PPSuffixes = []

DialectAddToEnv(env, "F77", F77Suffixes, F77PPSuffixes)

def add_f90_to_env(env):
"""Add Builders and construction variables for f90 to an Environment."""
def add_f90_to_env(env) -> None:
"""Add Builders and construction variables for f90 dialect."""
try:
F90Suffixes = env['F90FILESUFFIXES']
except KeyError:
F90Suffixes = ['.f90']

#print("Adding %s to f90 suffixes" % F90Suffixes)
try:
F90PPSuffixes = env['F90PPFILESUFFIXES']
except KeyError:
F90PPSuffixes = []

DialectAddToEnv(env, "F90", F90Suffixes, F90PPSuffixes,
support_module=True)

DialectAddToEnv(env, "F90", F90Suffixes, F90PPSuffixes, support_mods=True)

def add_f95_to_env(env):
"""Add Builders and construction variables for f95 to an Environment."""
def add_f95_to_env(env) -> None:
"""Add Builders and construction variables for f95 dialect."""
try:
F95Suffixes = env['F95FILESUFFIXES']
except KeyError:
F95Suffixes = ['.f95']

#print("Adding %s to f95 suffixes" % F95Suffixes)
try:
F95PPSuffixes = env['F95PPFILESUFFIXES']
except KeyError:
F95PPSuffixes = []

DialectAddToEnv(env, "F95", F95Suffixes, F95PPSuffixes,
support_module=True)

DialectAddToEnv(env, "F95", F95Suffixes, F95PPSuffixes, support_mods=True)

def add_f03_to_env(env):
"""Add Builders and construction variables for f03 to an Environment."""
def add_f03_to_env(env) -> None:
"""Add Builders and construction variables for f03 dialect."""
try:
F03Suffixes = env['F03FILESUFFIXES']
except KeyError:
F03Suffixes = ['.f03']

#print("Adding %s to f95 suffixes" % F95Suffixes)
try:
F03PPSuffixes = env['F03PPFILESUFFIXES']
except KeyError:
F03PPSuffixes = []

DialectAddToEnv(env, "F03", F03Suffixes, F03PPSuffixes,
support_module=True)
DialectAddToEnv(env, "F03", F03Suffixes, F03PPSuffixes, support_mods=True)


def add_f08_to_env(env):
"""Add Builders and construction variables for f08 to an Environment."""
def add_f08_to_env(env) -> None:
"""Add Builders and construction variables for f08 dialect."""
try:
F08Suffixes = env['F08FILESUFFIXES']
except KeyError:
Expand All @@ -269,13 +272,10 @@ def add_f08_to_env(env):
except KeyError:
F08PPSuffixes = []

DialectAddToEnv(env, "F08", F08Suffixes, F08PPSuffixes,
support_module=True)

DialectAddToEnv(env, "F08", F08Suffixes, F08PPSuffixes, support_mods=True)

def add_all_to_env(env):
"""Add builders and construction variables for all supported fortran
dialects."""
def add_all_to_env(env) -> None:
"""Add builders and construction variables for all supported dialects."""
add_fortran_to_env(env)
add_f77_to_env(env)
add_f90_to_env(env)
Expand Down
5 changes: 3 additions & 2 deletions SCons/Tool/f03.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
<!--
__COPYRIGHT__
Copyright The SCons Foundation

This file is processed by the bin/SConsDoc.py module.
See its __doc__ string for a discussion of the format.
Expand Down Expand Up @@ -45,6 +45,7 @@ Set construction variables for generic POSIX Fortran 03 compilers.
<item>F03PPCOMSTR</item>
<item>SHF03COMSTR</item>
<item>SHF03PPCOMSTR</item>
<item>FORTRANCOMMONFLAGS</item>
</uses>
</tool>

Expand Down Expand Up @@ -271,7 +272,7 @@ Options that are passed to the Fortran 03 compiler
to generated shared-library objects.
You only need to set &cv-link-SHF03FLAGS; if you need to define specific
user options for Fortran 03 files.
You should normally set the &cv-link-SHFORTRANFLAGS; variable,
You should normally set the &cv-link-FORTRANCOMMONFLAGS; variable,
which specifies the user-specified options
passed to the default Fortran compiler
for all Fortran versions.
Expand Down
5 changes: 3 additions & 2 deletions SCons/Tool/f08.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
<!--
__COPYRIGHT__
Copyright The SCons Foundation

This file is processed by the bin/SConsDoc.py module.
See its __doc__ string for a discussion of the format.
Expand Down Expand Up @@ -45,6 +45,7 @@ Set construction variables for generic POSIX Fortran 08 compilers.
<item>F08PPCOMSTR</item>
<item>SHF08COMSTR</item>
<item>SHF08PPCOMSTR</item>
<item>FORTRANCOMMONFLAGS</item>
</uses>
</tool>

Expand Down Expand Up @@ -271,7 +272,7 @@ Options that are passed to the Fortran 08 compiler
to generated shared-library objects.
You only need to set &cv-link-SHF08FLAGS; if you need to define specific
user options for Fortran 08 files.
You should normally set the &cv-link-SHFORTRANFLAGS; variable,
You should normally set the &cv-link-FORTRANCOMMONFLAGS; variable,
which specifies the user-specified options
passed to the default Fortran compiler
for all Fortran versions.
Expand Down
Loading