diff --git a/SConstruct b/SConstruct index dc812d0094..ce88380549 100644 --- a/SConstruct +++ b/SConstruct @@ -33,38 +33,38 @@ else: # All of the following options may be modified at the command-line, for example: # `python scons/scons PREFIX=/opt` -opts = Options('config.py') +opts = Variables('config.py') opts.Add('CXX', 'The C++ compiler to use (defaults to g++).', 'g++') opts.Add('PREFIX', 'The install path "prefix"', '/usr/local') -opts.Add(PathOption('BOOST_INCLUDES', 'Search path for boost include files', '/usr/include')) -opts.Add(PathOption('BOOST_LIBS', 'Search path for boost library files', '/usr/' + LIBDIR_SCHEMA)) +opts.Add(PathVariable('BOOST_INCLUDES', 'Search path for boost include files', '/usr/include')) +opts.Add(PathVariable('BOOST_LIBS', 'Search path for boost library files', '/usr/' + LIBDIR_SCHEMA)) opts.Add('BOOST_TOOLKIT','Specify boost toolkit, e.g., gcc41.','',False) opts.Add('BOOST_ABI', 'Specify boost ABI, e.g., d.','',False) opts.Add('BOOST_VERSION','Specify boost version, e.g., 1_35.','',False) opts.Add(('FREETYPE_CONFIG', 'The path to the freetype-config executable.', 'freetype-config')) opts.Add(('XML2_CONFIG', 'The path to the xml2-config executable.', 'xml2-config')) -opts.Add(PathOption('ICU_INCLUDES', 'Search path for ICU include files', '/usr/include')) -opts.Add(PathOption('ICU_LIBS','Search path for ICU include files','/usr/' + LIBDIR_SCHEMA)) -opts.Add(PathOption('PNG_INCLUDES', 'Search path for libpng include files', '/usr/include')) -opts.Add(PathOption('PNG_LIBS','Search path for libpng include files','/usr/' + LIBDIR_SCHEMA)) -opts.Add(PathOption('JPEG_INCLUDES', 'Search path for libjpeg include files', '/usr/include')) -opts.Add(PathOption('JPEG_LIBS', 'Search path for libjpeg library files', '/usr/' + LIBDIR_SCHEMA)) -opts.Add(PathOption('TIFF_INCLUDES', 'Search path for libtiff include files', '/usr/include')) -opts.Add(PathOption('TIFF_LIBS', 'Search path for libtiff library files', '/usr/' + LIBDIR_SCHEMA)) -opts.Add(PathOption('PGSQL_INCLUDES', 'Search path for PostgreSQL include files', '/usr/include')) -opts.Add(PathOption('PGSQL_LIBS', 'Search path for PostgreSQL library files', '/usr/' + LIBDIR_SCHEMA)) -opts.Add(PathOption('PROJ_INCLUDES', 'Search path for PROJ.4 include files', '/usr/local/include')) -opts.Add(PathOption('PROJ_LIBS', 'Search path for PROJ.4 library files', '/usr/local/' + LIBDIR_SCHEMA)) -opts.Add(PathOption('GDAL_INCLUDES', 'Search path for GDAL include files', '/usr/include')) -opts.Add(PathOption('GDAL_LIBS', 'Search path for GDAL library files', '/usr/' + LIBDIR_SCHEMA)) -opts.Add(PathOption('PYTHON','Python executable', sys.executable)) -opts.Add(ListOption('INPUT_PLUGINS','Input drivers to include','all',['postgis','shape','raster','gdal'])) -opts.Add(ListOption('BINDINGS','Language bindings to build','all',['python'])) -opts.Add(BoolOption('DEBUG', 'Compile a debug version of mapnik', 'False')) +opts.Add(PathVariable('ICU_INCLUDES', 'Search path for ICU include files', '/usr/include')) +opts.Add(PathVariable('ICU_LIBS','Search path for ICU include files','/usr/' + LIBDIR_SCHEMA)) +opts.Add(PathVariable('PNG_INCLUDES', 'Search path for libpng include files', '/usr/include')) +opts.Add(PathVariable('PNG_LIBS','Search path for libpng include files','/usr/' + LIBDIR_SCHEMA)) +opts.Add(PathVariable('JPEG_INCLUDES', 'Search path for libjpeg include files', '/usr/include')) +opts.Add(PathVariable('JPEG_LIBS', 'Search path for libjpeg library files', '/usr/' + LIBDIR_SCHEMA)) +opts.Add(PathVariable('TIFF_INCLUDES', 'Search path for libtiff include files', '/usr/include')) +opts.Add(PathVariable('TIFF_LIBS', 'Search path for libtiff library files', '/usr/' + LIBDIR_SCHEMA)) +opts.Add(PathVariable('PGSQL_INCLUDES', 'Search path for PostgreSQL include files', '/usr/include')) +opts.Add(PathVariable('PGSQL_LIBS', 'Search path for PostgreSQL library files', '/usr/' + LIBDIR_SCHEMA)) +opts.Add(PathVariable('PROJ_INCLUDES', 'Search path for PROJ.4 include files', '/usr/local/include')) +opts.Add(PathVariable('PROJ_LIBS', 'Search path for PROJ.4 library files', '/usr/local/' + LIBDIR_SCHEMA)) +opts.Add(PathVariable('GDAL_INCLUDES', 'Search path for GDAL include files', '/usr/include')) +opts.Add(PathVariable('GDAL_LIBS', 'Search path for GDAL library files', '/usr/' + LIBDIR_SCHEMA)) +opts.Add(PathVariable('PYTHON','Python executable', sys.executable)) +opts.Add(ListVariable('INPUT_PLUGINS','Input drivers to include','all',['postgis','shape','raster','gdal'])) +opts.Add(ListVariable('BINDINGS','Language bindings to build','all',['python'])) +opts.Add(BoolVariable('DEBUG', 'Compile a debug version of mapnik', 'False')) opts.Add('DESTDIR', 'The root directory to install into. Useful mainly for binary package building', '/') -opts.Add(EnumOption('THREADING','Set threading support','multi', ['multi','single'])) -opts.Add(EnumOption('XMLPARSER','Set xml parser ','tinyxml', ['tinyxml','spirit','libxml2'])) -opts.Add(BoolOption('INTERNAL_LIBAGG', 'Use provided libagg', 'True')) +opts.Add(EnumVariable('THREADING','Set threading support','multi', ['multi','single'])) +opts.Add(EnumVariable('XMLPARSER','Set xml parser ','tinyxml', ['tinyxml','spirit','libxml2'])) +opts.Add(BoolVariable('INTERNAL_LIBAGG', 'Use provided libagg', 'True')) env = Environment(ENV=os.environ, options=opts) diff --git a/scons/scons-LICENSE b/scons/scons-LICENSE index 184b82e5de..804ed86821 100644 --- a/scons/scons-LICENSE +++ b/scons/scons-LICENSE @@ -3,7 +3,7 @@ This copyright and license do not apply to any other software with which this software may have been included. -Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/scons/scons-README b/scons/scons-README index 97fc5f4363..298a221682 100644 --- a/scons/scons-README +++ b/scons/scons-README @@ -1,4 +1,4 @@ -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation SCons - a software construction tool diff --git a/scons/scons-local-0.97.0d20071212/SCons/Errors.py b/scons/scons-local-0.97.0d20071212/SCons/Errors.py deleted file mode 100644 index 4282136634..0000000000 --- a/scons/scons-local-0.97.0d20071212/SCons/Errors.py +++ /dev/null @@ -1,71 +0,0 @@ -# -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation -# -# 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. -# - -"""SCons.Errors - -This file contains the exception classes used to handle internal -and user errors in SCons. - -""" - -__revision__ = "src/engine/SCons/Errors.py 2523 2007/12/12 09:37:41 knight" - - - -class BuildError(Exception): - def __init__(self, node=None, errstr="Unknown error", status=0, - filename=None, executor=None, action=None, command=None, - *args): - self.node = node - self.errstr = errstr - self.status = status - self.filename = filename - self.executor = executor - self.action = action - self.command = command - apply(Exception.__init__, (self,) + args) - -class InternalError(Exception): - pass - -class UserError(Exception): - pass - -class StopError(Exception): - pass - -class EnvironmentError(Exception): - pass - -class ExplicitExit(Exception): - def __init__(self, node=None, status=None, *args): - self.node = node - self.status = status - apply(Exception.__init__, (self,) + args) - -class TaskmasterException(Exception): - def __init__(self, node=None, exc_info=(None, None, None), *args): - self.node = node - self.errstr = "Exception" - self.exc_info = exc_info - apply(Exception.__init__, (self,) + args) diff --git a/scons/scons-local-0.97.0d20071212/SCons/Scanner/LaTeX.py b/scons/scons-local-0.97.0d20071212/SCons/Scanner/LaTeX.py deleted file mode 100644 index 59a88a27f6..0000000000 --- a/scons/scons-local-0.97.0d20071212/SCons/Scanner/LaTeX.py +++ /dev/null @@ -1,126 +0,0 @@ -"""SCons.Scanner.LaTeX - -This module implements the dependency scanner for LaTeX code. - -""" - -# -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation -# -# 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__ = "src/engine/SCons/Scanner/LaTeX.py 2523 2007/12/12 09:37:41 knight" - -import os.path -import string - -import SCons.Scanner - -def LaTeXScanner(): - """Return a prototype Scanner instance for scanning LaTeX source files""" - ds = LaTeX(name = "LaTeXScanner", - suffixes = '$LATEXSUFFIXES', - path_variable = 'TEXINPUTS', - regex = '\\\\(include|includegraphics(?:\[[^\]]+\])?|input|bibliography|usepackage){([^}]*)}', - recursive = 0) - return ds - -class LaTeX(SCons.Scanner.Classic): - """Class for scanning LaTeX files for included files. - - Unlike most scanners, which use regular expressions that just - return the included file name, this returns a tuple consisting - of the keyword for the inclusion ("include", "includegraphics", - "input", or "bibliography"), and then the file name itself. - Based on a quick look at LaTeX documentation, it seems that we - need a should append .tex suffix for the "include" keywords, - append .tex if there is no extension for the "input" keyword, - but leave the file name untouched for "includegraphics." For - the "bibliography" keyword we need to add .bib if there is - no extension. (This need to be revisited since if there - is no extension for an :includegraphics" keyword latex will - append .ps or .eps to find the file; while pdftex will use - other extensions.) - """ - def latex_name(self, include): - filename = include[1] - if include[0] == 'input': - base, ext = os.path.splitext( filename ) - if ext == "": - filename = filename + '.tex' - if (include[0] == 'include'): - filename = filename + '.tex' - if include[0] == 'bibliography': - base, ext = os.path.splitext( filename ) - if ext == "": - filename = filename + '.bib' - if include[0] == 'usepackage': - base, ext = os.path.splitext( filename ) - if ext == "": - filename = filename + '.sty' - return filename - def sort_key(self, include): - return SCons.Node.FS._my_normcase(self.latex_name(include)) - def find_include(self, include, source_dir, path): - i = SCons.Node.FS.find_file(self.latex_name(include), - (source_dir,) + path) - return i, include - - def scan(self, node, path=()): - # - # Modify the default scan function to allow for the regular - # expression to return a comma separated list of file names - # as can be the case with the bibliography keyword. - # - # cache the includes list in node so we only scan it once: - if node.includes != None: - includes = node.includes - else: - includes = self.cre.findall(node.get_contents()) - node.includes = includes - - # This is a hand-coded DSU (decorate-sort-undecorate, or - # Schwartzian transform) pattern. The sort key is the raw name - # of the file as specifed on the #include line (including the - # " or <, since that may affect what file is found), which lets - # us keep the sort order constant regardless of whether the file - # is actually found in a Repository or locally. - nodes = [] - source_dir = node.get_dir() - for include in includes: - # - # Handle multiple filenames in include[1] - # - inc_list = string.split(include[1],',') - for j in range(len(inc_list)): - include_local = [include[0],inc_list[j]] - n, i = self.find_include(include_local, source_dir, path) - - if n is None: - SCons.Warnings.warn(SCons.Warnings.DependencyWarning, - "No dependency generated for file: %s (included from: %s) -- file not found" % (i, node)) - else: - sortkey = self.sort_key(include) - nodes.append((sortkey, n)) - - nodes.sort() - nodes = map(lambda pair: pair[1], nodes) - return nodes diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/f77.py b/scons/scons-local-0.97.0d20071212/SCons/Tool/f77.py deleted file mode 100644 index aff2681ff1..0000000000 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/f77.py +++ /dev/null @@ -1,135 +0,0 @@ -"""engine.SCons.Tool.f77 - -Tool-specific initialization for the generic Posix f77 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 (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation -# -# 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__ = "src/engine/SCons/Tool/f77.py 2523 2007/12/12 09:37:41 knight" - -import SCons.Defaults -import SCons.Scanner.Fortran -import SCons.Tool -import SCons.Util -import fortran - -compilers = ['f77'] - -# -F77Suffixes = ['.f77'] -F77PPSuffixes = [] -if SCons.Util.case_sensitive_suffixes('.f77', '.F77'): - F77PPSuffixes.append('.F77') -else: - F77Suffixes.append('.F77') - -# -F77Scan = SCons.Scanner.Fortran.FortranScan("F77PATH") - -for suffix in F77Suffixes + F77PPSuffixes: - SCons.Tool.SourceFileScanner.add_scanner(suffix, F77Scan) -del suffix - -# -fVLG = fortran.VariableListGenerator - -F77Generator = fVLG('F77', 'FORTRAN', '_FORTRAND') -F77FlagsGenerator = fVLG('F77FLAGS', 'FORTRANFLAGS') -F77CommandGenerator = fVLG('F77COM', 'FORTRANCOM', '_F77COMD') -F77CommandStrGenerator = fVLG('F77COMSTR', 'FORTRANCOMSTR', '_F77COMSTRD') -F77PPCommandGenerator = fVLG('F77PPCOM', 'FORTRANPPCOM', '_F77PPCOMD') -F77PPCommandStrGenerator = fVLG('F77PPCOMSTR', 'FORTRANPPCOMSTR', '_F77PPCOMSTRD') -ShF77Generator = fVLG('SHF77', 'SHFORTRAN', 'F77', 'FORTRAN', '_FORTRAND') -ShF77FlagsGenerator = fVLG('SHF77FLAGS', 'SHFORTRANFLAGS') -ShF77CommandGenerator = fVLG('SHF77COM', 'SHFORTRANCOM', '_SHF77COMD') -ShF77CommandStrGenerator = fVLG('SHF77COMSTR', 'SHFORTRANCOMSTR', '_SHF77COMSTRD') -ShF77PPCommandGenerator = fVLG('SHF77PPCOM', 'SHFORTRANPPCOM', '_SHF77PPCOMD') -ShF77PPCommandStrGenerator = fVLG('SHF77PPCOMSTR', 'SHFORTRANPPCOMSTR', '_SHF77PPCOMSTRD') - -del fVLG - -# -F77Action = SCons.Action.Action('$_F77COMG ', '$_F77COMSTRG') -F77PPAction = SCons.Action.Action('$_F77PPCOMG ', '$_F77PPCOMSTRG') -ShF77Action = SCons.Action.Action('$_SHF77COMG ', '$_SHF77COMSTRG') -ShF77PPAction = SCons.Action.Action('$_SHF77PPCOMG ', '$_SHF77PPCOMSTRG') - -def add_to_env(env): - """Add Builders and construction variables for f77 to an Environment.""" - env.AppendUnique(FORTRANSUFFIXES = F77Suffixes + F77PPSuffixes) - - static_obj, shared_obj = SCons.Tool.createObjBuilders(env) - - for suffix in F77Suffixes: - static_obj.add_action(suffix, F77Action) - shared_obj.add_action(suffix, ShF77Action) - static_obj.add_emitter(suffix, fortran.FortranEmitter) - shared_obj.add_emitter(suffix, fortran.ShFortranEmitter) - - for suffix in F77PPSuffixes: - static_obj.add_action(suffix, F77PPAction) - shared_obj.add_action(suffix, ShF77PPAction) - static_obj.add_emitter(suffix, fortran.FortranEmitter) - shared_obj.add_emitter(suffix, fortran.ShFortranEmitter) - - env['_F77G'] = F77Generator - env['_F77FLAGSG'] = F77FlagsGenerator - env['_F77COMG'] = F77CommandGenerator - env['_F77PPCOMG'] = F77PPCommandGenerator - env['_F77COMSTRG'] = F77CommandStrGenerator - env['_F77PPCOMSTRG'] = F77PPCommandStrGenerator - - env['_SHF77G'] = ShF77Generator - env['_SHF77FLAGSG'] = ShF77FlagsGenerator - env['_SHF77COMG'] = ShF77CommandGenerator - env['_SHF77PPCOMG'] = ShF77PPCommandGenerator - env['_SHF77COMSTRG'] = ShF77CommandStrGenerator - env['_SHF77PPCOMSTRG'] = ShF77PPCommandStrGenerator - - env['_F77INCFLAGS'] = '$( ${_concat(INCPREFIX, F77PATH, INCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)' - - env['_F77COMD'] = '$_F77G -o $TARGET -c $_F77FLAGSG $_F77INCFLAGS $SOURCES' - env['_F77PPCOMD'] = '$_F77G -o $TARGET -c $_F77FLAGSG $CPPFLAGS $_CPPDEFFLAGS $_F77INCFLAGS $SOURCES' - env['_SHF77COMD'] = '$_SHF77G -o $TARGET -c $_SHF77FLAGSG $_F77INCFLAGS $SOURCES' - env['_SHF77PPCOMD'] = '$_SHF77G -o $TARGET -c $_SHF77FLAGSG $CPPFLAGS $_CPPDEFFLAGS $_F77INCFLAGS $SOURCES' - -def generate(env): - fortran.add_to_env(env) - - import f90 - import f95 - 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) diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/f90.py b/scons/scons-local-0.97.0d20071212/SCons/Tool/f90.py deleted file mode 100644 index d4a154c3d8..0000000000 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/f90.py +++ /dev/null @@ -1,132 +0,0 @@ -"""engine.SCons.Tool.f90 - -Tool-specific initialization for the generic Posix 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 (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation -# -# 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__ = "src/engine/SCons/Tool/f90.py 2523 2007/12/12 09:37:41 knight" - -import SCons.Defaults -import SCons.Scanner.Fortran -import SCons.Tool -import SCons.Util -import fortran - -compilers = ['f90'] - -# -F90Suffixes = ['.f90'] -F90PPSuffixes = [] -if SCons.Util.case_sensitive_suffixes('.f90', '.F90'): - F90PPSuffixes.append('.F90') -else: - F90Suffixes.append('.F90') - -# -F90Scan = SCons.Scanner.Fortran.FortranScan("F90PATH") - -for suffix in F90Suffixes + F90PPSuffixes: - SCons.Tool.SourceFileScanner.add_scanner(suffix, F90Scan) -del suffix - -# -fVLG = fortran.VariableListGenerator - -F90Generator = fVLG('F90', 'FORTRAN', '_FORTRAND') -F90FlagsGenerator = fVLG('F90FLAGS', 'FORTRANFLAGS') -F90CommandGenerator = fVLG('F90COM', 'FORTRANCOM', '_F90COMD') -F90CommandStrGenerator = fVLG('F90COMSTR', 'FORTRANCOMSTR', '_F90COMSTRD') -F90PPCommandGenerator = fVLG('F90PPCOM', 'FORTRANPPCOM', '_F90PPCOMD') -F90PPCommandStrGenerator = fVLG('F90PPCOMSTR', 'FORTRANPPCOMSTR', '_F90PPCOMSTRD') -ShF90Generator = fVLG('SHF90', 'SHFORTRAN', 'F90', 'FORTRAN', '_FORTRAND') -ShF90FlagsGenerator = fVLG('SHF90FLAGS', 'SHFORTRANFLAGS') -ShF90CommandGenerator = fVLG('SHF90COM', 'SHFORTRANCOM', '_SHF90COMD') -ShF90CommandStrGenerator = fVLG('SHF90COMSTR', 'SHFORTRANCOMSTR', '_SHF90COMSTRD') -ShF90PPCommandGenerator = fVLG('SHF90PPCOM', 'SHFORTRANPPCOM', '_SHF90PPCOMD') -ShF90PPCommandStrGenerator = fVLG('SHF90PPCOMSTR', 'SHFORTRANPPCOMSTR', '_SHF90PPCOMSTRD') - -del fVLG - -# -F90Action = SCons.Action.Action('$_F90COMG ', '$_F90COMSTRG') -F90PPAction = SCons.Action.Action('$_F90PPCOMG ', '$_F90PPCOMSTRG') -ShF90Action = SCons.Action.Action('$_SHF90COMG ', '$_SHF90COMSTRG') -ShF90PPAction = SCons.Action.Action('$_SHF90PPCOMG ', '$_SHF90PPCOMSTRG') - -def add_to_env(env): - """Add Builders and construction variables for f90 to an Environment.""" - env.AppendUnique(FORTRANSUFFIXES = F90Suffixes + F90PPSuffixes) - - static_obj, shared_obj = SCons.Tool.createObjBuilders(env) - - for suffix in F90Suffixes: - static_obj.add_action(suffix, F90Action) - shared_obj.add_action(suffix, ShF90Action) - static_obj.add_emitter(suffix, fortran.FortranEmitter) - shared_obj.add_emitter(suffix, fortran.ShFortranEmitter) - - for suffix in F90PPSuffixes: - static_obj.add_action(suffix, F90PPAction) - shared_obj.add_action(suffix, ShF90PPAction) - static_obj.add_emitter(suffix, fortran.FortranEmitter) - shared_obj.add_emitter(suffix, fortran.ShFortranEmitter) - - env['_F90G'] = F90Generator - env['_F90FLAGSG'] = F90FlagsGenerator - env['_F90COMG'] = F90CommandGenerator - env['_F90COMSTRG'] = F90CommandStrGenerator - env['_F90PPCOMG'] = F90PPCommandGenerator - env['_F90PPCOMSTRG'] = F90PPCommandStrGenerator - - env['_SHF90G'] = ShF90Generator - env['_SHF90FLAGSG'] = ShF90FlagsGenerator - env['_SHF90COMG'] = ShF90CommandGenerator - env['_SHF90COMSTRG'] = ShF90CommandStrGenerator - env['_SHF90PPCOMG'] = ShF90PPCommandGenerator - env['_SHF90PPCOMSTRG'] = ShF90PPCommandStrGenerator - - env['_F90INCFLAGS'] = '$( ${_concat(INCPREFIX, F90PATH, INCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)' - env['_F90COMD'] = '$_F90G -o $TARGET -c $_F90FLAGSG $_F90INCFLAGS $_FORTRANMODFLAG $SOURCES' - env['_F90PPCOMD'] = '$_F90G -o $TARGET -c $_F90FLAGSG $CPPFLAGS $_CPPDEFFLAGS $_F90INCFLAGS $_FORTRANMODFLAG $SOURCES' - env['_SHF90COMD'] = '$_SHF90G -o $TARGET -c $_SHF90FLAGSG $_F90INCFLAGS $_FORTRANMODFLAG $SOURCES' - env['_SHF90PPCOMD'] = '$_SHF90G -o $TARGET -c $_SHF90FLAGSG $CPPFLAGS $_CPPDEFFLAGS $_F90INCFLAGS $_FORTRANMODFLAG $SOURCES' - -def generate(env): - fortran.add_to_env(env) - - import f77 - f77.add_to_env(env) - - add_to_env(env) - - env['_FORTRAND'] = env.Detect(compilers) or 'f90' - -def exists(env): - return env.Detect(compilers) diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/f95.py b/scons/scons-local-0.97.0d20071212/SCons/Tool/f95.py deleted file mode 100644 index 3a3e3e4726..0000000000 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/f95.py +++ /dev/null @@ -1,135 +0,0 @@ -"""engine.SCons.Tool.f95 - -Tool-specific initialization for the generic Posix f95 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 (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation -# -# 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__ = "src/engine/SCons/Tool/f95.py 2523 2007/12/12 09:37:41 knight" - -import SCons.Defaults -import SCons.Tool -import SCons.Util -import fortran - -compilers = ['f95'] - -# -F95Suffixes = ['.f95'] -F95PPSuffixes = [] -if SCons.Util.case_sensitive_suffixes('.f95', '.F95'): - F95PPSuffixes.append('.F95') -else: - F95Suffixes.append('.F95') - -# -F95Scan = SCons.Scanner.Fortran.FortranScan("F95PATH") - -for suffix in F95Suffixes + F95PPSuffixes: - SCons.Tool.SourceFileScanner.add_scanner(suffix, F95Scan) -del suffix - -# -fVLG = fortran.VariableListGenerator - -F95Generator = fVLG('F95', 'FORTRAN', '_FORTRAND') -F95FlagsGenerator = fVLG('F95FLAGS', 'FORTRANFLAGS') -F95CommandGenerator = fVLG('F95COM', 'FORTRANCOM', '_F95COMD') -F95CommandStrGenerator = fVLG('F95COMSTR', 'FORTRANCOMSTR', '_F95COMSTRD') -F95PPCommandGenerator = fVLG('F95PPCOM', 'FORTRANPPCOM', '_F95PPCOMD') -F95PPCommandStrGenerator = fVLG('F95PPCOMSTR', 'FORTRANPPCOMSTR', '_F95PPCOMSTRD') -ShF95Generator = fVLG('SHF95', 'SHFORTRAN', 'F95', 'FORTRAN', '_FORTRAND') -ShF95FlagsGenerator = fVLG('SHF95FLAGS', 'SHFORTRANFLAGS') -ShF95CommandGenerator = fVLG('SHF95COM', 'SHFORTRANCOM', '_SHF95COMD') -ShF95CommandStrGenerator = fVLG('SHF95COMSTR', 'SHFORTRANCOMSTR', '_SHF95COMSTRD') -ShF95PPCommandGenerator = fVLG('SHF95PPCOM', 'SHFORTRANPPCOM', '_SHF95PPCOMD') -ShF95PPCommandStrGenerator = fVLG('SHF95PPCOMSTR', 'SHFORTRANPPCOMSTR', '_SHF95PPCOMSTRD') - -del fVLG - -# -F95Action = SCons.Action.Action('$_F95COMG ', '$_F95COMSTRG') -F95PPAction = SCons.Action.Action('$_F95PPCOMG ', '$_F95PPCOMSTRG') -ShF95Action = SCons.Action.Action('$_SHF95COMG ', '$_SHF95COMSTRG') -ShF95PPAction = SCons.Action.Action('$_SHF95PPCOMG ', '$_SHF95PPCOMSTRG') - -def add_to_env(env): - """Add Builders and construction variables for f95 to an Environment.""" - env.AppendUnique(FORTRANSUFFIXES = F95Suffixes + F95PPSuffixes) - - static_obj, shared_obj = SCons.Tool.createObjBuilders(env) - - for suffix in F95Suffixes: - static_obj.add_action(suffix, F95Action) - shared_obj.add_action(suffix, ShF95Action) - static_obj.add_emitter(suffix, fortran.FortranEmitter) - shared_obj.add_emitter(suffix, fortran.ShFortranEmitter) - - for suffix in F95PPSuffixes: - static_obj.add_action(suffix, F95PPAction) - shared_obj.add_action(suffix, ShF95PPAction) - static_obj.add_emitter(suffix, fortran.FortranEmitter) - shared_obj.add_emitter(suffix, fortran.ShFortranEmitter) - - env['_F95G'] = F95Generator - env['_F95FLAGSG'] = F95FlagsGenerator - env['_F95COMG'] = F95CommandGenerator - env['_F95COMSTRG'] = F95CommandStrGenerator - env['_F95PPCOMG'] = F95PPCommandGenerator - env['_F95PPCOMSTRG'] = F95PPCommandStrGenerator - - env['_SHF95G'] = ShF95Generator - env['_SHF95FLAGSG'] = ShF95FlagsGenerator - env['_SHF95COMG'] = ShF95CommandGenerator - env['_SHF95COMSTRG'] = ShF95CommandStrGenerator - env['_SHF95PPCOMG'] = ShF95PPCommandGenerator - env['_SHF95PPCOMSTRG'] = ShF95PPCommandStrGenerator - - env['_F95INCFLAGS'] = '$( ${_concat(INCPREFIX, F95PATH, INCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)' - - env['_F95COMD'] = '$_F95G -o $TARGET -c $_F95FLAGSG $_F95INCFLAGS $_FORTRANMODFLAG $SOURCES' - env['_F95PPCOMD'] = '$_F95G -o $TARGET -c $_F95FLAGSG $CPPFLAGS $_CPPDEFFLAGS $_F95INCFLAGS $_FORTRANMODFLAG $SOURCES' - env['_SHF95COMD'] = '$_SHF95G -o $TARGET -c $_SHF95FLAGSG $_F95INCFLAGS $_FORTRANMODFLAG $SOURCES' - env['_SHF95PPCOMD'] = '$_SHF95G -o $TARGET -c $_SHF95FLAGSG $CPPFLAGS $_CPPDEFFLAGS $_F95INCFLAGS $_FORTRANMODFLAG $SOURCES' - -def generate(env): - fortran.add_to_env(env) - - import f77 - f77.add_to_env(env) - - import f90 - f90.add_to_env(env) - - add_to_env(env) - - env['_FORTRAND'] = env.Detect(compilers) or 'f95' - -def exists(env): - return env.Detect(compilers) diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/fortran.py b/scons/scons-local-0.97.0d20071212/SCons/Tool/fortran.py deleted file mode 100644 index 33c135df25..0000000000 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/fortran.py +++ /dev/null @@ -1,186 +0,0 @@ -"""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 (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation -# -# 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__ = "src/engine/SCons/Tool/fortran.py 2523 2007/12/12 09:37:41 knight" - -import re -import string - -import SCons.Action -import SCons.Defaults -import SCons.Scanner.Fortran -import SCons.Tool -import SCons.Util - -compilers = ['f95', 'f90', 'f77'] - -# -# 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.Tool.SourceFileScanner.add_scanner(suffix, FortranScan) -del suffix - -# -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', target=target, source=source) - moddir = env.subst('$FORTRANMODDIR', target=target, source=source) - modules = map(lambda x, s=suffix: string.lower(x) + s, modules) - for m in modules: - target.append(env.fs.File(m, moddir)) - 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=0): - for v in self.variablelist: - try: return env[v] - except KeyError: pass - return '' - -# -FortranGenerator = VariableListGenerator('FORTRAN', 'F77', '_FORTRAND') -FortranFlagsGenerator = VariableListGenerator('FORTRANFLAGS', 'F77FLAGS') -FortranCommandGenerator = VariableListGenerator('FORTRANCOM', 'F77COM', '_FORTRANCOMD') -FortranCommandStrGenerator = VariableListGenerator('FORTRANCOMSTR', 'F77COMSTR', '_FORTRANCOMSTRD') -FortranPPCommandGenerator = VariableListGenerator('FORTRANPPCOM', 'F77PPCOM', '_FORTRANPPCOMD') -FortranPPCommandStrGenerator = VariableListGenerator('FORTRANPPCOMSTR', 'F77PPCOMSTR', '_FORTRANPPCOMSTRD') -ShFortranGenerator = VariableListGenerator('SHFORTRAN', 'SHF77', 'FORTRAN', 'F77', '_FORTRAND') -ShFortranFlagsGenerator = VariableListGenerator('SHFORTRANFLAGS', 'SHF77FLAGS') -ShFortranCommandGenerator = VariableListGenerator('SHFORTRANCOM', 'SHF77COM', '_SHFORTRANCOMD') -ShFortranCommandStrGenerator = VariableListGenerator('SHFORTRANCOMSTR', 'SHF77COMSTR', '_SHFORTRANCOMSTRD') -ShFortranPPCommandGenerator = VariableListGenerator('SHFORTRANPPCOM', 'SHF77PPCOM', '_SHFORTRANPPCOMD') -ShFortranPPCommandStrGenerator = VariableListGenerator('SHFORTRANPPCOMSTR', 'SHF77PPCOMSTR', '_SHFORTRANPPCOMSTRD') - -# -FortranAction = SCons.Action.Action('$_FORTRANCOMG ', '$_FORTRANCOMSTRG') -FortranPPAction = SCons.Action.Action('$_FORTRANPPCOMG ', '$_FORTRANPPCOMSTRG') -ShFortranAction = SCons.Action.Action('$_SHFORTRANCOMG ', '$_SHFORTRANCOMSTRG') -ShFortranPPAction = SCons.Action.Action('$_SHFORTRANPPCOMG ', '$_SHFORTRANPPCOMSTRG') - -def add_to_env(env): - """Add Builders and construction variables for Fortran to an Environment.""" - - env['_FORTRANG'] = FortranGenerator - env['_FORTRANFLAGSG'] = FortranFlagsGenerator - env['_FORTRANCOMG'] = FortranCommandGenerator - env['_FORTRANCOMSTRG'] = FortranCommandStrGenerator - env['_FORTRANPPCOMG'] = FortranPPCommandGenerator - env['_FORTRANPPCOMSTRG'] = FortranPPCommandStrGenerator - - env['_SHFORTRANG'] = ShFortranGenerator - env['_SHFORTRANFLAGSG'] = ShFortranFlagsGenerator - env['_SHFORTRANCOMG'] = ShFortranCommandGenerator - env['_SHFORTRANCOMSTRG'] = ShFortranCommandStrGenerator - env['_SHFORTRANPPCOMG'] = ShFortranPPCommandGenerator - env['_SHFORTRANPPCOMSTRG'] = ShFortranPPCommandStrGenerator - - env['_FORTRANINCFLAGS'] = '$( ${_concat(INCPREFIX, FORTRANPATH, INCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)' - - 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)} $)' - - 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) - - env['_FORTRANCOMD'] = '$_FORTRANG -o $TARGET -c $_FORTRANFLAGSG $_FORTRANINCFLAGS $_FORTRANMODFLAG $SOURCES' - env['_FORTRANPPCOMD'] = '$_FORTRANG -o $TARGET -c $_FORTRANFLAGSG $CPPFLAGS $_CPPDEFFLAGS $_FORTRANINCFLAGS $_FORTRANMODFLAG $SOURCES' - env['_SHFORTRANCOMD'] = '$_SHFORTRANG -o $TARGET -c $_SHFORTRANFLAGSG $_FORTRANINCFLAGS $_FORTRANMODFLAG $SOURCES' - env['_SHFORTRANPPCOMD'] = '$_SHFORTRANG -o $TARGET -c $_SHFORTRANFLAGSG $CPPFLAGS $_CPPDEFFLAGS $_FORTRANINCFLAGS $_FORTRANMODFLAG $SOURCES' - -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) diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/tex.py b/scons/scons-local-0.97.0d20071212/SCons/Tool/tex.py deleted file mode 100644 index 79e9750a6d..0000000000 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/tex.py +++ /dev/null @@ -1,268 +0,0 @@ -"""SCons.Tool.tex - -Tool-specific initialization for TeX. - -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 (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation -# -# 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__ = "src/engine/SCons/Tool/tex.py 2523 2007/12/12 09:37:41 knight" - -import os.path -import re -import string - -import SCons.Action -import SCons.Node -import SCons.Node.FS -import SCons.Util - -warning_rerun_re = re.compile("^LaTeX Warning:.*Rerun", re.MULTILINE) - -rerun_citations_str = "^LaTeX Warning:.*\n.*Rerun to get citations correct" -rerun_citations_re = re.compile(rerun_citations_str, re.MULTILINE) - -undefined_references_str = '(^LaTeX Warning:.*undefined references)|(^Package \w+ Warning:.*undefined citations)' -undefined_references_re = re.compile(undefined_references_str, re.MULTILINE) - -openout_aux_re = re.compile(r"\\openout.*`(.*\.aux)'") -openout_re = re.compile(r"\\openout.*`(.*)'") - -makeindex_re = re.compile(r"^[^%]*\\makeindex", re.MULTILINE) -tableofcontents_re = re.compile(r"^[^%]*\\tableofcontents", re.MULTILINE) -bibliography_re = re.compile(r"^[^%]*\\bibliography", re.MULTILINE) - -# An Action sufficient to build any generic tex file. -TeXAction = None - -# An action to build a latex file. This action might be needed more -# than once if we are dealing with labels and bibtex. -LaTeXAction = None - -# An action to run BibTeX on a file. -BibTeXAction = None - -# An action to run MakeIndex on a file. -MakeIndexAction = None - -def InternalLaTeXAuxAction(XXXLaTeXAction, target = None, source= None, env=None): - """A builder for LaTeX files that checks the output in the aux file - and decides how many times to use LaTeXAction, and BibTeXAction.""" - - basename = SCons.Util.splitext(str(source[0]))[0] - basedir = os.path.split(str(source[0]))[0] - - # Notice that all the filenames are not prefixed with the basedir. - # That's because the *COM variables have the cd command in the prolog. - - bblfilename = basename + '.bbl' - bblContents = "" - if os.path.exists(bblfilename): - bblContents = open(bblfilename, "rb").read() - - idxfilename = basename + '.idx' - idxContents = "" - if os.path.exists(idxfilename): - idxContents = open(idxfilename, "rb").read() - - tocfilename = basename + '.toc' - tocContents = "" - if os.path.exists(tocfilename): - tocContents = open(tocfilename, "rb").read() - - # Run LaTeX once to generate a new aux file. - XXXLaTeXAction(target, source, env) - - # Decide if various things need to be run, or run again. We check - # for the existence of files before opening them--even ones like the - # aux file that TeX always creates--to make it possible to write tests - # with stubs that don't necessarily generate all of the same files. - - # Read the log file to find all .aux files - logfilename = basename + '.log' - auxfiles = [] - if os.path.exists(logfilename): - content = open(logfilename, "rb").read() - auxfiles = openout_aux_re.findall(content) - - # Now decide if bibtex will need to be run. - for auxfilename in auxfiles: - if os.path.exists(os.path.join(basedir, auxfilename)): - content = open(os.path.join(basedir, auxfilename), "rb").read() - if string.find(content, "bibdata") != -1: - bibfile = env.fs.File(basename) - BibTeXAction(bibfile, bibfile, env) - break - - must_rerun_latex = 0 - # Now decide if latex will need to be run again due to table of contents. - if os.path.exists(tocfilename) and tocContents != open(tocfilename, "rb").read(): - must_rerun_latex = 1 - - # Now decide if latex will need to be run again due to bibliography. - if os.path.exists(bblfilename) and bblContents != open(bblfilename, "rb").read(): - must_rerun_latex = 1 - - # Now decide if latex will need to be run again due to index. - if os.path.exists(idxfilename) and idxContents != open(idxfilename, "rb").read(): - # We must run makeindex - idxfile = env.fs.File(basename) - MakeIndexAction(idxfile, idxfile, env) - must_rerun_latex = 1 - - if must_rerun_latex == 1: - XXXLaTeXAction(target, source, env) - - # Now decide if latex needs to be run yet again to resolve warnings. - logfilename = basename + '.log' - for _ in range(int(env.subst('$LATEXRETRIES'))): - if not os.path.exists(logfilename): - break - content = open(logfilename, "rb").read() - if not warning_rerun_re.search(content) and \ - not rerun_citations_re.search(content) and \ - not undefined_references_re.search(content): - break - XXXLaTeXAction(target, source, env) - return 0 - -def LaTeXAuxAction(target = None, source= None, env=None): - InternalLaTeXAuxAction( LaTeXAction, target, source, env ) - -LaTeX_re = re.compile("\\\\document(style|class)") - -def is_LaTeX(flist): - # Scan a file list to decide if it's TeX- or LaTeX-flavored. - for f in flist: - content = f.get_contents() - if LaTeX_re.search(content): - return 1 - return 0 - -def TeXLaTeXFunction(target = None, source= None, env=None): - """A builder for TeX and LaTeX that scans the source file to - decide the "flavor" of the source and then executes the appropriate - program.""" - if is_LaTeX(source): - LaTeXAuxAction(target,source,env) - else: - TeXAction(target,source,env) - return 0 - -def tex_emitter(target, source, env): - base = SCons.Util.splitext(str(source[0]))[0] - target.append(base + '.aux') - env.Precious(base + '.aux') - target.append(base + '.log') - for f in source: - content = f.get_contents() - if tableofcontents_re.search(content): - target.append(base + '.toc') - env.Precious(base + '.toc') - if makeindex_re.search(content): - target.append(base + '.ilg') - target.append(base + '.ind') - target.append(base + '.idx') - env.Precious(base + '.idx') - if bibliography_re.search(content): - target.append(base + '.bbl') - env.Precious(base + '.bbl') - target.append(base + '.blg') - - # read log file to get all output file (include .aux files) - logfilename = base + '.log' - dir, base_nodir = os.path.split(base) - if os.path.exists(logfilename): - content = open(logfilename, "rb").read() - out_files = openout_re.findall(content) - out_files = filter(lambda f, b=base_nodir+'.aux': f != b, out_files) - if dir != '': - out_files = map(lambda f, d=dir: d+os.sep+f, out_files) - target.extend(out_files) - for f in out_files: - env.Precious( f ) - - return (target, source) - -TeXLaTeXAction = None - -def generate(env): - """Add Builders and construction variables for TeX to an Environment.""" - - # A generic tex file Action, sufficient for all tex files. - global TeXAction - if TeXAction is None: - TeXAction = SCons.Action.Action("$TEXCOM", "$TEXCOMSTR") - - # An Action to build a latex file. This might be needed more - # than once if we are dealing with labels and bibtex. - global LaTeXAction - if LaTeXAction is None: - LaTeXAction = SCons.Action.Action("$LATEXCOM", "$LATEXCOMSTR") - - # Define an action to run BibTeX on a file. - global BibTeXAction - if BibTeXAction is None: - BibTeXAction = SCons.Action.Action("$BIBTEXCOM", "$BIBTEXCOMSTR") - - # Define an action to run MakeIndex on a file. - global MakeIndexAction - if MakeIndexAction is None: - MakeIndexAction = SCons.Action.Action("$MAKEINDEXCOM", "$MAKEINDEXCOMSTR") - - global TeXLaTeXAction - if TeXLaTeXAction is None: - TeXLaTeXAction = SCons.Action.Action(TeXLaTeXFunction, strfunction=None) - - import dvi - dvi.generate(env) - - bld = env['BUILDERS']['DVI'] - bld.add_action('.tex', TeXLaTeXAction) - bld.add_emitter('.tex', tex_emitter) - - env['TEX'] = 'tex' - env['TEXFLAGS'] = SCons.Util.CLVar('') - env['TEXCOM'] = 'cd ${TARGET.dir} && $TEX $TEXFLAGS ${SOURCE.file}' - - # Duplicate from latex.py. If latex.py goes away, then this is still OK. - env['LATEX'] = 'latex' - env['LATEXFLAGS'] = SCons.Util.CLVar('') - env['LATEXCOM'] = 'cd ${TARGET.dir} && $LATEX $LATEXFLAGS ${SOURCE.file}' - env['LATEXRETRIES'] = 3 - - env['BIBTEX'] = 'bibtex' - env['BIBTEXFLAGS'] = SCons.Util.CLVar('') - env['BIBTEXCOM'] = 'cd ${TARGET.dir} && $BIBTEX $BIBTEXFLAGS ${SOURCE.filebase}' - - env['MAKEINDEX'] = 'makeindex' - env['MAKEINDEXFLAGS'] = SCons.Util.CLVar('') - env['MAKEINDEXCOM'] = 'cd ${TARGET.dir} && $MAKEINDEX $MAKEINDEXFLAGS ${SOURCE.file}' - -def exists(env): - return env.Detect('tex') diff --git a/scons/scons-local-0.97.0d20071212/scons-0.97.0d20071212.egg-info b/scons/scons-local-0.97.0d20071212/scons-0.97.0d20071212.egg-info deleted file mode 100644 index 604062f4d2..0000000000 --- a/scons/scons-local-0.97.0d20071212/scons-0.97.0d20071212.egg-info +++ /dev/null @@ -1,13 +0,0 @@ -Metadata-Version: 1.0 -Name: scons -Version: 0.97.0d20071212 -Summary: Open Source next-generation build tool. -Improved, cross-platform substitute for the classic Make -utility. In short, SCons is an easier, more reliable -and faster way to build software. -Home-page: http://www.scons.org/ -Author: Steven Knight -Author-email: knight@baldmt.com -License: UNKNOWN -Description: UNKNOWN -Platform: UNKNOWN diff --git a/scons/scons-local-0.97.0d20071212/SCons/Action.py b/scons/scons-local-1.2.0/SCons/Action.py similarity index 61% rename from scons/scons-local-0.97.0d20071212/SCons/Action.py rename to scons/scons-local-1.2.0/SCons/Action.py index 5a7efccac4..d740de66d1 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Action.py +++ b/scons/scons-local-1.2.0/SCons/Action.py @@ -30,9 +30,9 @@ a pre-substitution command for debugging purposes. get_contents() - Fetches the "contents" of an Action for signature calculation. - This is what gets MD5 checksumm'ed to decide if a target needs - to be rebuilt because its action changed. + Fetches the "contents" of an Action for signature calculation + plus the varlist. This is what gets MD5 checksummed to decide + if a target needs to be rebuilt because its action changed. genstring() Returns a string representation of the Action *without* @@ -49,7 +49,7 @@ __str__() Returns a string approximation of the Action; no variable substitution is performed. - + execute() The internal method that really, truly, actually handles the execution of a command or Python function. This is used so @@ -57,6 +57,10 @@ pre-substitution representations, and *then* execute an action without worrying about the specific Actions involved. + get_presig() + Fetches the "contents" of a subclass for signature calculation. + The varlist is added to this to produce the Action's contents. + strfunction() Returns a substituted string representation of the Action. This is used by the _ActionAction.show() command to display the @@ -72,8 +76,7 @@ """ -# -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -93,32 +96,33 @@ # 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__ = "src/engine/SCons/Action.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Action.py 3842 2008/12/20 22:59:52 scons" +import cPickle import dis import os -import os.path import string import sys +import subprocess from SCons.Debug import logInstanceCreation import SCons.Errors import SCons.Executor import SCons.Util +import SCons.Subst -class _Null: - pass +# we use these a lot, so try to optimize them +is_String = SCons.Util.is_String +is_List = SCons.Util.is_List -_null = _Null +class _null: + pass print_actions = 1 execute_actions = 1 print_actions_presub = 0 -default_ENV = None - def rfile(n): try: return n.rfile() @@ -150,6 +154,141 @@ def remove_set_lineno_codes(code): i = i+1 return string.join(result, '') + +def _callable_contents(obj): + """Return the signature contents of a callable Python object. + """ + try: + # Test if obj is a method. + return _function_contents(obj.im_func) + + except AttributeError: + try: + # Test if obj is a callable object. + return _function_contents(obj.__call__.im_func) + + except AttributeError: + try: + # Test if obj is a code object. + return _code_contents(obj) + + except AttributeError: + # Test if obj is a function object. + return _function_contents(obj) + + +def _object_contents(obj): + """Return the signature contents of any Python object. + + We have to handle the case where object contains a code object + since it can be pickled directly. + """ + try: + # Test if obj is a method. + return _function_contents(obj.im_func) + + except AttributeError: + try: + # Test if obj is a callable object. + return _function_contents(obj.__call__.im_func) + + except AttributeError: + try: + # Test if obj is a code object. + return _code_contents(obj) + + except AttributeError: + try: + # Test if obj is a function object. + return _function_contents(obj) + + except AttributeError: + # Should be a pickable Python object. + try: + return cPickle.dumps(obj) + except (cPickle.PicklingError, TypeError): + # This is weird, but it seems that nested classes + # are unpickable. The Python docs say it should + # always be a PicklingError, but some Python + # versions seem to return TypeError. Just do + # the best we can. + return str(obj) + + +def _code_contents(code): + """Return the signature contents of a code object. + + By providing direct access to the code object of the + function, Python makes this extremely easy. Hooray! + + Unfortunately, older versions of Python include line + number indications in the compiled byte code. Boo! + So we remove the line number byte codes to prevent + recompilations from moving a Python function. + """ + + contents = [] + + # The code contents depends on the number of local variables + # but not their actual names. + contents.append("%s,%s" % (code.co_argcount, len(code.co_varnames))) + try: + contents.append(",%s,%s" % (len(code.co_cellvars), len(code.co_freevars))) + except AttributeError: + # Older versions of Python do not support closures. + contents.append(",0,0") + + # The code contents depends on any constants accessed by the + # function. Note that we have to call _object_contents on each + # constants because the code object of nested functions can + # show-up among the constants. + # + # Note that we also always ignore the first entry of co_consts + # which contains the function doc string. We assume that the + # function does not access its doc string. + contents.append(',(' + string.join(map(_object_contents,code.co_consts[1:]),',') + ')') + + # The code contents depends on the variable names used to + # accessed global variable, as changing the variable name changes + # the variable actually accessed and therefore changes the + # function result. + contents.append(',(' + string.join(map(_object_contents,code.co_names),',') + ')') + + + # The code contents depends on its actual code!!! + contents.append(',(' + str(remove_set_lineno_codes(code.co_code)) + ')') + + return string.join(contents, '') + + +def _function_contents(func): + """Return the signature contents of a function.""" + + contents = [_code_contents(func.func_code)] + + # The function contents depends on the value of defaults arguments + if func.func_defaults: + contents.append(',(' + string.join(map(_object_contents,func.func_defaults),',') + ')') + else: + contents.append(',()') + + # The function contents depends on the closure captured cell values. + try: + closure = func.func_closure or [] + except AttributeError: + # Older versions of Python do not support closures. + closure = [] + + #xxx = [_object_contents(x.cell_contents) for x in closure] + try: + xxx = map(lambda x: _object_contents(x.cell_contents), closure) + except AttributeError: + xxx = [] + contents.append(',(' + string.join(xxx, ',') + ')') + + return string.join(contents, '') + + def _actionAppend(act1, act2): # This function knows how to slap two actions together. # Mainly, it handles ListActions by concatenating into @@ -169,7 +308,34 @@ def _actionAppend(act1, act2): else: return ListAction([ a1, a2 ]) -def _do_create_action(act, *args, **kw): +def _do_create_keywords(args, kw): + """This converts any arguments after the action argument into + their equivalent keywords and adds them to the kw argument. + """ + v = kw.get('varlist', ()) + # prevent varlist="FOO" from being interpreted as ['F', 'O', 'O'] + if is_String(v): v = (v,) + kw['varlist'] = tuple(v) + if args: + # turn positional args into equivalent keywords + cmdstrfunc = args[0] + if cmdstrfunc is None or is_String(cmdstrfunc): + kw['cmdstr'] = cmdstrfunc + elif callable(cmdstrfunc): + kw['strfunction'] = cmdstrfunc + else: + raise SCons.Errors.UserError( + 'Invalid command display variable type. ' + 'You must either pass a string or a callback which ' + 'accepts (target, source, env) as parameters.') + if len(args) > 1: + kw['varlist'] = args[1:] + kw['varlist'] + if kw.get('strfunction', _null) is not _null \ + and kw.get('cmdstr', _null) is not _null: + raise SCons.Errors.UserError( + 'Cannot have both strfunction and cmdstr args to Action()') + +def _do_create_action(act, kw): """This is the actual "implementation" for the Action factory method, below. This handles the fact that passing lists to Action() itself has @@ -182,8 +348,11 @@ def _do_create_action(act, *args, **kw): if isinstance(act, ActionBase): return act - if SCons.Util.is_List(act): - return apply(CommandAction, (act,)+args, kw) + + if is_List(act): + #TODO(1.5) return CommandAction(act, **kw) + return apply(CommandAction, (act,), kw) + if callable(act): try: gen = kw['generator'] @@ -194,8 +363,9 @@ def _do_create_action(act, *args, **kw): action_type = CommandGeneratorAction else: action_type = FunctionAction - return apply(action_type, (act,)+args, kw) - if SCons.Util.is_String(act): + return action_type(act, kw) + + if is_String(act): var=SCons.Util.get_environment_var(act) if var: # This looks like a string that is purely an Environment @@ -204,30 +374,37 @@ def _do_create_action(act, *args, **kw): # of that Environment variable, so a user could put something # like a function or a CommandGenerator in that variable # instead of a string. - return apply(LazyAction, (var,)+args, kw) + return LazyAction(var, kw) commands = string.split(str(act), '\n') if len(commands) == 1: - return apply(CommandAction, (commands[0],)+args, kw) - else: - listCmdActions = map(lambda x, args=args, kw=kw: - apply(CommandAction, (x,)+args, kw), - commands) - return ListAction(listCmdActions) + #TODO(1.5) return CommandAction(commands[0], **kw) + return apply(CommandAction, (commands[0],), kw) + # The list of string commands may include a LazyAction, so we + # reprocess them via _do_create_list_action. + return _do_create_list_action(commands, kw) return None +def _do_create_list_action(act, kw): + """A factory for list actions. Convert the input list into Actions + and then wrap them in a ListAction.""" + acts = [] + for a in act: + aa = _do_create_action(a, kw) + if aa is not None: acts.append(aa) + if not acts: + return None + elif len(acts) == 1: + return acts[0] + else: + return ListAction(acts) + def Action(act, *args, **kw): """A factory for action objects.""" - if SCons.Util.is_List(act): - acts = map(lambda a, args=args, kw=kw: - apply(_do_create_action, (a,)+args, kw), - act) - acts = filter(None, acts) - if len(acts) == 1: - return acts[0] - else: - return ListAction(acts) - else: - return apply(_do_create_action, (act,)+args, kw) + # Really simple: the _do_create_* routines do the heavy lifting. + _do_create_keywords(args, kw) + if is_List(act): + return _do_create_list_action(act, kw) + return _do_create_action(act, kw) class ActionBase: """Base class for all types of action objects that can be held by @@ -240,6 +417,17 @@ def __cmp__(self, other): def genstring(self, target, source, env): return str(self) + def get_contents(self, target, source, env): + result = [ self.get_presig(target, source, env) ] + # This should never happen, as the Action() factory should wrap + # the varlist, but just in case an action is created directly, + # we duplicate this check here. + vl = self.varlist + if is_String(vl): vl = (vl,) + for v in vl: + result.append(env.subst('${'+v+'}')) + return string.join(result, '') + def __add__(self, other): return _actionAppend(self, other) @@ -265,9 +453,16 @@ def get_executor(self, env, overrides, tlist, slist, executor_kw): class _ActionAction(ActionBase): """Base class for actions that create output objects.""" - def __init__(self, strfunction=_null, presub=_null, chdir=None, exitstatfunc=None, **kw): - if not strfunction is _null: - self.strfunction = strfunction + def __init__(self, cmdstr=_null, strfunction=_null, varlist=(), + presub=_null, chdir=None, exitstatfunc=None, + **kw): + self.cmdstr = cmdstr + if strfunction is not _null: + if strfunction is None: + self.cmdstr = None + else: + self.strfunction = strfunction + self.varlist = varlist self.presub = presub self.chdir = chdir if not exitstatfunc: @@ -283,16 +478,16 @@ def __call__(self, target, source, env, show=_null, execute=_null, chdir=_null): - if not SCons.Util.is_List(target): + if not is_List(target): target = [target] - if not SCons.Util.is_List(source): + if not is_List(source): source = [source] - if exitstatfunc is _null: exitstatfunc = self.exitstatfunc if presub is _null: presub = self.presub - if presub is _null: - presub = print_actions_presub + if presub is _null: + presub = print_actions_presub + if exitstatfunc is _null: exitstatfunc = self.exitstatfunc if show is _null: show = print_actions if execute is _null: execute = execute_actions if chdir is _null: chdir = self.chdir @@ -302,19 +497,19 @@ def __call__(self, target, source, env, try: chdir = str(chdir.abspath) except AttributeError: - if not SCons.Util.is_String(chdir): + if not is_String(chdir): chdir = str(target[0].dir) if presub: t = string.join(map(str, target), ' and ') l = string.join(self.presub_lines(env), '\n ') out = "Building %s with action:\n %s\n" % (t, l) sys.stdout.write(out) - s = None + cmd = None if show and self.strfunction: - s = self.strfunction(target, source, env) - if s: + cmd = self.strfunction(target, source, env) + if cmd: if chdir: - s = ('os.chdir(%s)\n' % repr(chdir)) + s + cmd = ('os.chdir(%s)\n' % repr(chdir)) + cmd try: get = env.get except AttributeError: @@ -323,7 +518,7 @@ def __call__(self, target, source, env, print_func = get('PRINT_CMD_LINE_FUNC') if not print_func: print_func = self.print_cmd_line - print_func(s, target, source, env) + print_func(cmd, target, source, env) stat = 0 if execute: if chdir: @@ -341,7 +536,7 @@ def __call__(self, target, source, env, finally: if save_cwd: os.chdir(save_cwd) - if s and save_cwd: + if cmd and save_cwd: print_func('os.chdir(%s)' % repr(save_cwd), target, source, env) return stat @@ -357,9 +552,87 @@ def _string_from_cmd_list(cmd_list): cl.append(arg) return string.join(cl) +# A fiddlin' little function that has an 'import SCons.Environment' which +# can't be moved to the top level without creating an import loop. Since +# this import creates a local variable named 'SCons', it blocks access to +# the global variable, so we move it here to prevent complaints about local +# variables being used uninitialized. +default_ENV = None +def get_default_ENV(env): + global default_ENV + try: + return env['ENV'] + except KeyError: + if not default_ENV: + import SCons.Environment + # This is a hideously expensive way to get a default shell + # environment. What it really should do is run the platform + # setup to get the default ENV. Fortunately, it's incredibly + # rare for an Environment not to have a shell environment, so + # we're not going to worry about it overmuch. + default_ENV = SCons.Environment.Environment()['ENV'] + return default_ENV + +# This function is still in draft mode. We're going to need something like +# it in the long run as more and more places use subprocess, but I'm sure +# it'll have to be tweaked to get the full desired functionality. +# one special arg (so far?), 'error', to tell what to do with exceptions. +def _subproc(env, cmd, error = 'ignore', **kw): + """Do common setup for a subprocess.Popen() call""" + # allow std{in,out,err} to be "'devnull'" + io = kw.get('stdin') + if is_String(io) and io == 'devnull': + kw['stdin'] = open(os.devnull) + io = kw.get('stdout') + if is_String(io) and io == 'devnull': + kw['stdout'] = open(os.devnull, 'w') + io = kw.get('stderr') + if is_String(io) and io == 'devnull': + kw['stderr'] = open(os.devnull, 'w') + + # Figure out what shell environment to use + ENV = kw.get('env', None) + if ENV is None: ENV = get_default_ENV(env) + + # Ensure that the ENV values are all strings: + new_env = {} + for key, value in ENV.items(): + if is_List(value): + # If the value is a list, then we assume it is a path list, + # because that's a pretty common list-like value to stick + # in an environment variable: + value = SCons.Util.flatten_sequence(value) + new_env[key] = string.join(map(str, value), os.pathsep) + else: + # It's either a string or something else. If it's a string, + # we still want to call str() because it might be a *Unicode* + # string, which makes subprocess.Popen() gag. If it isn't a + # string or a list, then we just coerce it to a string, which + # is the proper way to handle Dir and File instances and will + # produce something reasonable for just about everything else: + new_env[key] = str(value) + kw['env'] = new_env + + try: + #FUTURE return subprocess.Popen(cmd, **kw) + return apply(subprocess.Popen, (cmd,), kw) + except EnvironmentError, e: + if error == 'raise': raise + # return a dummy Popen instance that only returns error + class dummyPopen: + def __init__(self, e): self.exception = e + def communicate(self): return ('','') + def wait(self): return -self.exception.errno + stdin = None + class f: + def read(self): return '' + def readline(self): return '' + stdout = stderr = f() + return dummyPopen(e) + class CommandAction(_ActionAction): """Class for command-execution actions.""" - def __init__(self, cmd, cmdstr=None, *args, **kw): + def __init__(self, cmd, **kw): # Cmd can actually be a list or a single item; if it's a # single item it should be the command string to execute; if a # list then it should be the words of the command string to @@ -371,25 +644,16 @@ def __init__(self, cmd, cmdstr=None, *args, **kw): # variables. if __debug__: logInstanceCreation(self, 'Action.CommandAction') - if not cmdstr is None: - if callable(cmdstr): - args = (cmdstr,)+args - elif not SCons.Util.is_String(cmdstr): - raise SCons.Errors.UserError(\ - 'Invalid command display variable type. ' \ - 'You must either pass a string or a callback which ' \ - 'accepts (target, source, env) as parameters.') - - apply(_ActionAction.__init__, (self,)+args, kw) - if SCons.Util.is_List(cmd): - if filter(SCons.Util.is_List, cmd): + #TODO(1.5) _ActionAction.__init__(self, **kw) + apply(_ActionAction.__init__, (self,), kw) + if is_List(cmd): + if filter(is_List, cmd): raise TypeError, "CommandAction should be given only " \ "a single command" self.cmd_list = cmd - self.cmdstr = cmdstr def __str__(self): - if SCons.Util.is_List(self.cmd_list): + if is_List(self.cmd_list): return string.join(map(str, self.cmd_list), ' ') return str(self.cmd_list) @@ -412,7 +676,9 @@ def process(self, target, source, env): return result, ignore, silent def strfunction(self, target, source, env): - if not self.cmdstr is None: + if self.cmdstr is None: + return None + if self.cmdstr is not _null: from SCons.Subst import SUBST_RAW c = env.subst(self.cmdstr, SUBST_RAW, target, source) if c: @@ -431,11 +697,8 @@ def execute(self, target, source, env): handle lists of commands, even though that's not how we use it externally. """ - from SCons.Subst import escape_list - import SCons.Util - flatten = SCons.Util.flatten - is_String = SCons.Util.is_String - is_List = SCons.Util.is_List + escape_list = SCons.Subst.escape_list + flatten_sequence = SCons.Util.flatten_sequence try: shell = env['SHELL'] @@ -452,14 +715,7 @@ def execute(self, target, source, env): escape = env.get('ESCAPE', lambda x: x) - try: - ENV = env['ENV'] - except KeyError: - global default_ENV - if not default_ENV: - import SCons.Environment - default_ENV = SCons.Environment.Environment()['ENV'] - ENV = default_ENV + ENV = get_default_ENV(env) # Ensure that the ENV values are all strings: for key, value in ENV.items(): @@ -468,7 +724,7 @@ def execute(self, target, source, env): # If the value is a list, then we assume it is a # path list, because that's a pretty common list-like # value to stick in an environment variable: - value = flatten(value) + value = flatten_sequence(value) ENV[key] = string.join(map(str, value), os.pathsep) else: # If it isn't a string or a list, then we just coerce @@ -492,7 +748,7 @@ def execute(self, target, source, env): command=cmd_line) return 0 - def get_contents(self, target, source, env): + def get_presig(self, target, source, env): """Return the signature contents of this action's command line. This strips $(-$) and everything in between the string, @@ -500,7 +756,7 @@ def get_contents(self, target, source, env): """ from SCons.Subst import SUBST_SIG cmd = self.cmd_list - if SCons.Util.is_List(cmd): + if is_List(cmd): cmd = string.join(map(str, cmd)) else: cmd = str(cmd) @@ -508,7 +764,7 @@ def get_contents(self, target, source, env): def get_implicit_deps(self, target, source, env): icd = env.get('IMPLICIT_COMMAND_DEPENDENCIES', True) - if SCons.Util.is_String(icd) and icd[:1] == '$': + if is_String(icd) and icd[:1] == '$': icd = env.subst(icd) if not icd or icd in ('0', 'None'): return [] @@ -524,20 +780,21 @@ def get_implicit_deps(self, target, source, env): class CommandGeneratorAction(ActionBase): """Class for command-generator actions.""" - def __init__(self, generator, *args, **kw): + def __init__(self, generator, kw): if __debug__: logInstanceCreation(self, 'Action.CommandGeneratorAction') self.generator = generator - self.gen_args = args self.gen_kw = kw + self.varlist = kw.get('varlist', ()) def _generate(self, target, source, env, for_signature): # ensure that target is a list, to make it easier to write # generator functions: - if not SCons.Util.is_List(target): + if not is_List(target): target = [target] ret = self.generator(target=target, source=source, env=env, for_signature=for_signature) - gen_cmd = apply(Action, (ret,)+self.gen_args, self.gen_kw) + #TODO(1.5) gen_cmd = Action(ret, **self.gen_kw) + gen_cmd = apply(Action, (ret,), self.gen_kw) if not gen_cmd: raise SCons.Errors.UserError("Object returned from command generator: %s cannot be used to create an Action." % repr(ret)) return gen_cmd @@ -561,13 +818,13 @@ def __call__(self, target, source, env, exitstatfunc=_null, presub=_null, return act(target, source, env, exitstatfunc, presub, show, execute, chdir) - def get_contents(self, target, source, env): + def get_presig(self, target, source, env): """Return the signature contents of this action's command line. This strips $(-$) and everything in between the string, since those parts don't affect signatures. """ - return self._generate(target, source, env, 1).get_contents(target, source, env) + return self._generate(target, source, env, 1).get_presig(target, source, env) def get_implicit_deps(self, target, source, env): return self._generate(target, source, env, 1).get_implicit_deps(target, source, env) @@ -593,22 +850,23 @@ def get_implicit_deps(self, target, source, env): class LazyAction(CommandGeneratorAction, CommandAction): - def __init__(self, var, *args, **kw): + def __init__(self, var, kw): if __debug__: logInstanceCreation(self, 'Action.LazyAction') - apply(CommandAction.__init__, (self, '$'+var)+args, kw) + #FUTURE CommandAction.__init__(self, '${'+var+'}', **kw) + apply(CommandAction.__init__, (self, '${'+var+'}'), kw) self.var = SCons.Util.to_String(var) - self.gen_args = args self.gen_kw = kw def get_parent_class(self, env): c = env.get(self.var) - if SCons.Util.is_String(c) and not '\n' in c: + if is_String(c) and not '\n' in c: return CommandAction return CommandGeneratorAction def _generate_cache(self, env): c = env.get(self.var, '') - gen_cmd = apply(Action, (c,)+self.gen_args, self.gen_kw) + #TODO(1.5) gen_cmd = Action(c, **self.gen_kw) + gen_cmd = apply(Action, (c,), self.gen_kw) if not gen_cmd: raise SCons.Errors.UserError("$%s value %s cannot be used to create an Action." % (self.var, repr(c))) return gen_cmd @@ -619,33 +877,34 @@ def _generate(self, target, source, env, for_signature): def __call__(self, target, source, env, *args, **kw): args = (self, target, source, env) + args c = self.get_parent_class(env) + #TODO(1.5) return c.__call__(*args, **kw) return apply(c.__call__, args, kw) - def get_contents(self, target, source, env): + def get_presig(self, target, source, env): c = self.get_parent_class(env) - return c.get_contents(self, target, source, env) + return c.get_presig(self, target, source, env) class FunctionAction(_ActionAction): """Class for Python function actions.""" - def __init__(self, execfunction, cmdstr=_null, *args, **kw): + def __init__(self, execfunction, kw): if __debug__: logInstanceCreation(self, 'Action.FunctionAction') - if not cmdstr is _null: - if callable(cmdstr): - args = (cmdstr,)+args - elif not (cmdstr is None or SCons.Util.is_String(cmdstr)): - raise SCons.Errors.UserError(\ - 'Invalid function display variable type. ' \ - 'You must either pass a string or a callback which ' \ - 'accepts (target, source, env) as parameters.') - self.execfunction = execfunction - apply(_ActionAction.__init__, (self,)+args, kw) - self.varlist = kw.get('varlist', []) - self.cmdstr = cmdstr + try: + self.funccontents = _callable_contents(execfunction) + except AttributeError: + try: + # See if execfunction will do the heavy lifting for us. + self.gc = execfunction.get_contents + except AttributeError: + # This is weird, just do the best we can. + self.funccontents = _object_contents(execfunction) + + #TODO(1.5) _ActionAction.__init__(self, **kw) + apply(_ActionAction.__init__, (self,), kw) def function_name(self): try: @@ -659,14 +918,20 @@ def function_name(self): def strfunction(self, target, source, env): if self.cmdstr is None: return None - if not self.cmdstr is _null: + if self.cmdstr is not _null: from SCons.Subst import SUBST_RAW c = env.subst(self.cmdstr, SUBST_RAW, target, source) if c: return c def array(a): def quote(s): - return '"' + str(s) + '"' + try: + str_for_display = s.str_for_display + except AttributeError: + s = repr(s) + else: + s = str_for_display() + return s return '[' + string.join(map(quote, a), ", ") + ']' try: strfunc = self.execfunction.strfunction @@ -689,73 +954,49 @@ def __str__(self): return "%s(target, source, env)" % name def execute(self, target, source, env): - rsources = map(rfile, source) + exc_info = (None,None,None) try: - result = self.execfunction(target=target, source=rsources, env=env) - except EnvironmentError, e: - # If an IOError/OSError happens, raise a BuildError. - # Report the name of the file or directory that caused the - # error, which might be different from the target being built - # (for example, failure to create the directory in which the - # target file will appear). - try: filename = e.filename - except AttributeError: filename = None - result = SCons.Errors.BuildError(node=target, - errstr=e.strerror, - status=1, - filename=filename, - action=self, - command=self.strfunction(target, source, env)) - else: - if result: - msg = "Error %s" % result - result = SCons.Errors.BuildError(errstr=msg, - status=result, - action=self, - command=self.strfunction(target, source, env)) - return result - - def get_contents(self, target, source, env): - """Return the signature contents of this callable action. - - By providing direct access to the code object of the - function, Python makes this extremely easy. Hooray! + rsources = map(rfile, source) + try: + result = self.execfunction(target=target, source=rsources, env=env) + except KeyboardInterrupt, e: + raise + except SystemExit, e: + raise + except Exception, e: + result = e + exc_info = sys.exc_info() - Unfortunately, older versions of Python include line - number indications in the compiled byte code. Boo! - So we remove the line number byte codes to prevent - recompilations from moving a Python function. - """ - execfunction = self.execfunction + if result: + result = SCons.Errors.convert_to_BuildError(result, exc_info) + result.node=target + result.action=self + result.command=self.strfunction(target, source, env) + + # FIXME: This maintains backward compatibility with respect to + # which type of exceptions were returned by raising an + # exception and which ones were returned by value. It would + # probably be best to always return them by value here, but + # some codes do not check the return value of Actions and I do + # not have the time to modify them at this point. + if (exc_info[1] and + not isinstance(exc_info[1],EnvironmentError)): + raise result + + return result + finally: + # Break the cycle between the traceback object and this + # function stack frame. See the sys.exc_info() doc info for + # more information about this issue. + del exc_info + + + def get_presig(self, target, source, env): + """Return the signature contents of this callable action.""" try: - # Test if execfunction is a function. - code = execfunction.func_code.co_code + return self.gc(target, source, env) except AttributeError: - try: - # Test if execfunction is a method. - code = execfunction.im_func.func_code.co_code - except AttributeError: - try: - # Test if execfunction is a callable object. - code = execfunction.__call__.im_func.func_code.co_code - except AttributeError: - try: - # See if execfunction will do the heavy lifting for us. - gc = self.execfunction.get_contents - except AttributeError: - # This is weird, just do the best we can. - contents = str(self.execfunction) - else: - contents = gc(target, source, env) - else: - contents = str(code) - else: - contents = str(code) - else: - contents = str(code) - contents = remove_set_lineno_codes(contents) - return contents + env.subst(string.join(map(lambda v: '${'+v+'}', - self.varlist))) + return self.funccontents def get_implicit_deps(self, target, source, env): return [] @@ -769,6 +1010,9 @@ def list_of_actions(x): return x return Action(x) self.list = map(list_of_actions, list) + # our children will have had any varlist + # applied; we don't need to do it again + self.varlist = () def genstring(self, target, source, env): return string.join(map(lambda a, t=target, s=source, e=env: @@ -778,13 +1022,12 @@ def genstring(self, target, source, env): def __str__(self): return string.join(map(str, self.list), '\n') - + def presub_lines(self, env): - return SCons.Util.flatten(map(lambda a, env=env: - a.presub_lines(env), - self.list)) + return SCons.Util.flatten_sequence( + map(lambda a, env=env: a.presub_lines(env), self.list)) - def get_contents(self, target, source, env): + def get_presig(self, target, source, env): """Return the signature contents of this action list. Simple concatenation of the signatures of the elements. @@ -822,6 +1065,7 @@ def __init__(self, parent, args, kw): self.parent = parent self.args = args self.kw = kw + def get_contents(self, target, source, env): actfunc = self.parent.actfunc try: @@ -837,33 +1081,50 @@ def get_contents(self, target, source, env): contents = str(actfunc) contents = remove_set_lineno_codes(contents) return contents + def subst(self, s, target, source, env): + # If s is a list, recursively apply subst() + # to every element in the list + if is_List(s): + result = [] + for elem in s: + result.append(self.subst(elem, target, source, env)) + return self.parent.convert(result) + # Special-case hack: Let a custom function wrapped in an # ActionCaller get at the environment through which the action # was called by using this hard-coded value as a special return. if s == '$__env__': return env - elif SCons.Util.is_String(s): - return env.subst(s, 0, target, source) + elif is_String(s): + return env.subst(s, 1, target, source) return self.parent.convert(s) + def subst_args(self, target, source, env): return map(lambda x, self=self, t=target, s=source, e=env: self.subst(x, t, s, e), self.args) + def subst_kw(self, target, source, env): kw = {} for key in self.kw.keys(): kw[key] = self.subst(self.kw[key], target, source, env) return kw + def __call__(self, target, source, env): args = self.subst_args(target, source, env) kw = self.subst_kw(target, source, env) + #TODO(1.5) return self.parent.actfunc(*args, **kw) return apply(self.parent.actfunc, args, kw) + def strfunction(self, target, source, env): args = self.subst_args(target, source, env) kw = self.subst_kw(target, source, env) + #TODO(1.5) return self.parent.strfunc(*args, **kw) return apply(self.parent.strfunc, args, kw) + def __str__(self): + #TODO(1.5) return self.parent.strfunc(*self.args, **self.kw) return apply(self.parent.strfunc, self.args, self.kw) class ActionFactory: @@ -879,6 +1140,7 @@ def __init__(self, actfunc, strfunc, convert=lambda x: x): self.actfunc = actfunc self.strfunc = strfunc self.convert = convert + def __call__(self, *args, **kw): ac = ActionCaller(self, args, kw) action = Action(ac, strfunction=ac.strfunction) diff --git a/scons/scons-local-0.97.0d20071212/SCons/Builder.py b/scons/scons-local-1.2.0/SCons/Builder.py similarity index 98% rename from scons/scons-local-0.97.0d20071212/SCons/Builder.py rename to scons/scons-local-1.2.0/SCons/Builder.py index 5bd2098acb..97aabb4837 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Builder.py +++ b/scons/scons-local-1.2.0/SCons/Builder.py @@ -76,7 +76,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -98,9 +98,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Builder.py 2523 2007/12/12 09:37:41 knight" - -import SCons.compat +__revision__ = "src/engine/SCons/Builder.py 3842 2008/12/20 22:59:52 scons" import UserDict import UserList @@ -234,7 +232,7 @@ def Builder(**kw): if kw.has_key('generator'): if kw.has_key('action'): raise UserError, "You must not specify both an action and a generator." - kw['action'] = SCons.Action.CommandGeneratorAction(kw['generator']) + kw['action'] = SCons.Action.CommandGeneratorAction(kw['generator'], {}) del kw['generator'] elif kw.has_key('action'): source_ext_match = kw.get('source_ext_match', 1) @@ -242,7 +240,7 @@ def Builder(**kw): del kw['source_ext_match'] if SCons.Util.is_Dict(kw['action']): composite = DictCmdGenerator(kw['action'], source_ext_match) - kw['action'] = SCons.Action.CommandGeneratorAction(composite) + kw['action'] = SCons.Action.CommandGeneratorAction(composite, {}) kw['src_suffix'] = composite.src_suffixes() else: kw['action'] = SCons.Action.Action(kw['action']) @@ -363,7 +361,7 @@ def __init__(self, action = None, name = None, chdir = _null, is_explicit = 1, - src_builder = [], + src_builder = None, ensure_suffix = False, **overrides): if __debug__: logInstanceCreation(self, 'Builder.BuilderBase') @@ -410,7 +408,9 @@ def __init__(self, action = None, self.executor_kw['chdir'] = chdir self.is_explicit = is_explicit - if not SCons.Util.is_List(src_builder): + if src_builder is None: + src_builder = [] + elif not SCons.Util.is_List(src_builder): src_builder = [ src_builder ] self.src_builder = src_builder @@ -505,7 +505,7 @@ def _create_nodes(self, env, target = None, source = None): tlist = [ t_from_s(pre, suf, splitext) ] else: target = self._adjustixes(target, pre, suf, self.ensure_suffix) - tlist = env.arg2nodes(target, target_factory) + tlist = env.arg2nodes(target, target_factory, target=target, source=source) if self.emitter: # The emitter is going to do str(node), but because we're @@ -712,14 +712,9 @@ def match_src_suffix(name, src_suffixes=src_suffixes, lengths=lengths): return None result = [] - - if SCons.Util.is_List(source): - source = SCons.Util.flatten(source) - else: - source = [source] - for s in source: + for s in SCons.Util.flatten(source): if SCons.Util.is_String(s): - match_suffix = match_src_suffix(s) + match_suffix = match_src_suffix(env.subst(s)) if not match_suffix and not '.' in s: src_suf = self.get_src_suffix(env) s = self._adjustixes(s, None, src_suf)[0] diff --git a/scons/scons-local-0.97.0d20071212/SCons/CacheDir.py b/scons/scons-local-1.2.0/SCons/CacheDir.py similarity index 89% rename from scons/scons-local-0.97.0d20071212/SCons/CacheDir.py rename to scons/scons-local-1.2.0/SCons/CacheDir.py index 871c62ec29..6eb6f173ba 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/CacheDir.py +++ b/scons/scons-local-1.2.0/SCons/CacheDir.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/CacheDir.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/CacheDir.py 3842 2008/12/20 22:59:52 scons" __doc__ = """ CacheDir support @@ -34,6 +34,7 @@ import SCons.Action +cache_enabled = True cache_debug = False cache_force = False cache_show = False @@ -129,31 +130,33 @@ def __init__(self, path): except ImportError: msg = "No hashlib or MD5 module available, CacheDir() not supported" SCons.Warnings.warn(SCons.Warnings.NoMD5ModuleWarning, msg) + self.path = None else: self.path = path + self.current_cache_debug = None + self.debugFP = None - def CacheDebugWrite(self, fmt, target, cachefile): - self.debugFP.write(fmt % (target, os.path.split(cachefile)[1])) - - def CacheDebugQuiet(self, fmt, target, cachefile): - pass - - def CacheDebugInit(self, fmt, target, cachefile): - if cache_debug: + def CacheDebug(self, fmt, target, cachefile): + if cache_debug != self.current_cache_debug: if cache_debug == '-': self.debugFP = sys.stdout - else: + elif cache_debug: self.debugFP = open(cache_debug, 'w') - self.CacheDebug = self.CacheDebugWrite - self.CacheDebug(fmt, target, cachefile) - else: - self.CacheDebug = self.CacheDebugQuiet + else: + self.debugFP = None + self.current_cache_debug = cache_debug + if self.debugFP: + self.debugFP.write(fmt % (target, os.path.split(cachefile)[1])) - CacheDebug = CacheDebugInit + def is_enabled(self): + return (cache_enabled and not self.path is None) def cachepath(self, node): """ """ + if not self.is_enabled(): + return None, None + sig = node.get_cachedir_bsig() subdir = string.upper(sig[0]) dir = os.path.join(self.path, subdir) @@ -184,6 +187,9 @@ def retrieve(self, node): execute the CacheRetrieveFunc and then have the latter explicitly check SCons.Action.execute_actions itself. """ + if not self.is_enabled(): + return False + retrieved = False if cache_show: @@ -202,16 +208,10 @@ def retrieve(self, node): return retrieved def push(self, node): + if not self.is_enabled(): + return return CachePush(node, [], node.get_build_env()) def push_if_forced(self, node): if cache_force: return self.push(node) - -class Null(SCons.Util.Null): - def repr(self): - return 'CacheDir.Null()' - def cachepath(self, node): - return None, None - def retrieve(self, node): - return False diff --git a/scons/scons-local-0.97.0d20071212/SCons/Conftest.py b/scons/scons-local-1.2.0/SCons/Conftest.py similarity index 78% rename from scons/scons-local-0.97.0d20071212/SCons/Conftest.py rename to scons/scons-local-1.2.0/SCons/Conftest.py index fcf8c5a75b..ba7dbf1361 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Conftest.py +++ b/scons/scons-local-1.2.0/SCons/Conftest.py @@ -142,6 +142,101 @@ def CheckBuilder(context, text = None, language = None): _YesNoResult(context, ret, None, text) return ret +def CheckCC(context): + """ + Configure check for a working C compiler. + + This checks whether the C compiler, as defined in the $CC construction + variable, can compile a C source file. It uses the current $CCCOM value + too, so that it can test against non working flags. + + """ + context.Display("Checking whether the C compiler works") + text = """ +int main() +{ + return 0; +} +""" + ret = _check_empty_program(context, 'CC', text, 'C') + _YesNoResult(context, ret, None, text) + return ret + +def CheckSHCC(context): + """ + Configure check for a working shared C compiler. + + This checks whether the C compiler, as defined in the $SHCC construction + variable, can compile a C source file. It uses the current $SHCCCOM value + too, so that it can test against non working flags. + + """ + context.Display("Checking whether the (shared) C compiler works") + text = """ +int foo() +{ + return 0; +} +""" + ret = _check_empty_program(context, 'SHCC', text, 'C', use_shared = True) + _YesNoResult(context, ret, None, text) + return ret + +def CheckCXX(context): + """ + Configure check for a working CXX compiler. + + This checks whether the CXX compiler, as defined in the $CXX construction + variable, can compile a CXX source file. It uses the current $CXXCOM value + too, so that it can test against non working flags. + + """ + context.Display("Checking whether the C++ compiler works") + text = """ +int main() +{ + return 0; +} +""" + ret = _check_empty_program(context, 'CXX', text, 'C++') + _YesNoResult(context, ret, None, text) + return ret + +def CheckSHCXX(context): + """ + Configure check for a working shared CXX compiler. + + This checks whether the CXX compiler, as defined in the $SHCXX construction + variable, can compile a CXX source file. It uses the current $SHCXXCOM value + too, so that it can test against non working flags. + + """ + context.Display("Checking whether the (shared) C++ compiler works") + text = """ +int main() +{ + return 0; +} +""" + ret = _check_empty_program(context, 'SHCXX', text, 'C++', use_shared = True) + _YesNoResult(context, ret, None, text) + return ret + +def _check_empty_program(context, comp, text, language, use_shared = False): + """Return 0 on success, 1 otherwise.""" + if not context.env.has_key(comp) or not context.env[comp]: + # The compiler construction variable is not set or empty + return 1 + + lang, suffix, msg = _lang2suffix(language) + if msg: + return 1 + + if use_shared: + return context.CompileSharedObject(text, suffix) + else: + return context.CompileProg(text, suffix) + def CheckFunc(context, function_name, header = None, language = None): """ @@ -206,7 +301,9 @@ def CheckFunc(context, function_name, header = None, language = None): context.Display("Checking for %s function %s()... " % (lang, function_name)) ret = context.BuildProg(text, suffix) - _YesNoResult(context, ret, "HAVE_" + function_name, text) + _YesNoResult(context, ret, "HAVE_" + function_name, text, + "Define to 1 if the system has the function `%s'." %\ + function_name) return ret @@ -253,7 +350,8 @@ def CheckHeader(context, header_name, header = None, language = None, context.Display("Checking for %s header file %s... " % (lang, header_name)) ret = context.CompileProg(text, suffix) - _YesNoResult(context, ret, "HAVE_" + header_name, text) + _YesNoResult(context, ret, "HAVE_" + header_name, text, + "Define to 1 if you have the <%s> header file." % header_name) return ret @@ -310,7 +408,8 @@ def CheckType(context, type_name, fallback = None, context.Display("Checking for %s type %s... " % (lang, type_name)) ret = context.BuildProg(text, suffix) - _YesNoResult(context, ret, "HAVE_" + type_name, text) + _YesNoResult(context, ret, "HAVE_" + type_name, text, + "Define to 1 if the system has the type `%s'." % type_name) if ret and fallback and context.headerfilename: f = open(context.headerfilename, "a") f.write("typedef %s %s;\n" % (fallback, type_name)) @@ -371,11 +470,11 @@ def CheckTypeSize(context, type_name, header = None, language = None, expect = N } """ - # XXX: Try* vs CompileProg ? - st = context.TryCompile(src % (type_name, expect), suffix) - if st: - _Have(context, "SIZEOF_" + type_name, str(expect)) + st = context.CompileProg(src % (type_name, expect), suffix) + if not st: context.Display("yes\n") + _Have(context, "SIZEOF_%s" % type_name, expect, + "The size of `%s', as computed by sizeof." % type_name) return expect else: context.Display("no\n") @@ -400,21 +499,78 @@ def CheckTypeSize(context, type_name, header = None, language = None, expect = N return 0; } """ - ret = context.TryRun(src, suffix) - st = ret[0] + st, out = context.RunProg(src, suffix) try: - size = int(ret[1]) - _Have(context, "SIZEOF_" + type_name, str(size)) - context.Display("%d\n" % size) + size = int(out) except ValueError: + # If cannot convert output of test prog to an integer (the size), + # something went wront, so just fail + st = 1 size = 0 - _LogFailed(context, src, st) - context.Display(" Failed !\n") - if st: + + if not st: + context.Display("yes\n") + _Have(context, "SIZEOF_%s" % type_name, size, + "The size of `%s', as computed by sizeof." % type_name) return size else: + context.Display("no\n") + _LogFailed(context, src, st) return 0 + return 0 + +def CheckDeclaration(context, symbol, includes = None, language = None): + """Checks whether symbol is declared. + + Use the same test as autoconf, that is test whether the symbol is defined + as a macro or can be used as an r-value. + + Arguments: + symbol : str + the symbol to check + includes : str + Optional "header" can be defined to include a header file. + language : str + only C and C++ supported. + + Returns: + status : bool + True if the check failed, False if succeeded.""" + + # Include "confdefs.h" first, so that the header can use HAVE_HEADER_H. + if context.headerfilename: + includetext = '#include "%s"' % context.headerfilename + else: + includetext = '' + + if not includes: + includes = "" + + lang, suffix, msg = _lang2suffix(language) + if msg: + context.Display("Cannot check for declaration %s: %s\n" % (type_name, msg)) + return msg + + src = includetext + includes + context.Display('Checking whether %s is declared... ' % symbol) + + src = src + r""" +int main() +{ +#ifndef %s + (void) %s; +#endif + ; + return 0; +} +""" % (symbol, symbol) + + st = context.CompileProg(src, suffix) + _YesNoResult(context, st, "HAVE_DECL_" + symbol, src, + "Set to 1 if %s is defined." % symbol) + return st + def CheckLib(context, libs, func_name = None, header = None, extra_libs = None, call = None, language = None, autoadd = 1): """ @@ -509,7 +665,8 @@ def CheckLib(context, libs, func_name = None, header = None, ret = context.BuildProg(text, suffix) - _YesNoResult(context, ret, sym, text) + _YesNoResult(context, ret, sym, text, + "Define to 1 if you have the `%s' library." % lib_name) if oldLIBS != -1 and (ret or not autoadd): context.SetLIBS(oldLIBS) @@ -522,15 +679,17 @@ def CheckLib(context, libs, func_name = None, header = None, # END OF PUBLIC FUNCTIONS # -def _YesNoResult(context, ret, key, text): +def _YesNoResult(context, ret, key, text, comment = None): """ Handle the result of a test with a "yes" or "no" result. "ret" is the return value: empty if OK, error message when not. "key" is the name of the symbol to be defined (HAVE_foo). "text" is the source code of the program used for testing. + "comment" is the C comment to add above the line defining the symbol (the + comment is automatically put inside a /* */). If None, no comment is added. """ if key: - _Have(context, key, not ret) + _Have(context, key, not ret, comment) if ret: context.Display("no\n") _LogFailed(context, text, ret) @@ -538,7 +697,7 @@ def _YesNoResult(context, ret, key, text): context.Display("yes\n") -def _Have(context, key, have): +def _Have(context, key, have, comment = None): """ Store result of a test in context.havedict and context.headerfilename. "key" is a "HAVE_abc" name. It is turned into all CAPITALS and non- @@ -566,12 +725,17 @@ def _Have(context, key, have): else: line = "#define %s %s\n" % (key_up, str(have)) + if comment is not None: + lines = "\n/* %s */\n" % comment + line + else: + lines = "\n" + line + if context.headerfilename: f = open(context.headerfilename, "a") - f.write(line) + f.write(lines) f.close() elif hasattr(context,'config_h'): - context.config_h = context.config_h + line + context.config_h = context.config_h + lines def _LogFailed(context, text, msg): diff --git a/scons/scons-local-0.97.0d20071212/SCons/Debug.py b/scons/scons-local-1.2.0/SCons/Debug.py similarity index 79% rename from scons/scons-local-0.97.0d20071212/SCons/Debug.py rename to scons/scons-local-1.2.0/SCons/Debug.py index c2e552d711..c6485b6fa3 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Debug.py +++ b/scons/scons-local-1.2.0/SCons/Debug.py @@ -7,7 +7,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -29,7 +29,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Debug.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Debug.py 3842 2008/12/20 22:59:52 scons" import os import string @@ -115,39 +115,57 @@ def memory(): res = resource.getrusage(resource.RUSAGE_SELF) return res[4] - - -caller_dicts = {} - -def caller(*backlist): +# returns caller's stack +def caller_stack(*backlist): import traceback if not backlist: backlist = [0] result = [] for back in backlist: tb = traceback.extract_stack(limit=3+back) - key = tb[1][:3] - try: - entry = caller_dicts[key] - except KeyError: - entry = caller_dicts[key] = {} key = tb[0][:3] - entry[key] = entry.get(key, 0) + 1 result.append('%s:%d(%s)' % func_shorten(key)) return result +caller_bases = {} +caller_dicts = {} + +# trace a caller's stack +def caller_trace(back=0): + import traceback + tb = traceback.extract_stack(limit=3+back) + tb.reverse() + callee = tb[1][:3] + caller_bases[callee] = caller_bases.get(callee, 0) + 1 + for caller in tb[2:]: + caller = callee + caller[:3] + try: + entry = caller_dicts[callee] + except KeyError: + caller_dicts[callee] = entry = {} + entry[caller] = entry.get(caller, 0) + 1 + callee = caller + +# print a single caller and its callers, if any +def _dump_one_caller(key, file, level=0): + l = [] + for c,v in caller_dicts[key].items(): + l.append((-v,c)) + l.sort() + leader = ' '*level + for v,c in l: + file.write("%s %6d %s:%d(%s)\n" % ((leader,-v) + func_shorten(c[-3:]))) + if caller_dicts.has_key(c): + _dump_one_caller(c, file, level+1) + +# print each call tree def dump_caller_counts(file=sys.stdout): - keys = caller_dicts.keys() + keys = caller_bases.keys() keys.sort() for k in keys: - file.write("Callers of %s:%d(%s):\n" % func_shorten(k)) - counts = caller_dicts[k] - callers = counts.keys() - callers.sort() - for c in callers: - #file.write(" counts[%s] = %s\n" % (c, counts[c])) - t = ((counts[c],) + func_shorten(c)) - file.write(" %6d %s:%d(%s)\n" % t) + file.write("Callers of %s:%d(%s), %d calls:\n" + % (func_shorten(k) + (caller_bases[k],))) + _dump_one_caller(k, file) shorten_list = [ ( '/scons/SCons/', 1), @@ -168,10 +186,8 @@ def func_shorten(func_tuple): if i >= 0: if t[1]: i = i + len(t[0]) - f = f[i:] - break - return (f,)+func_tuple[1:] - + return (f[i:],)+func_tuple[1:] + return func_tuple TraceFP = {} diff --git a/scons/scons-local-0.97.0d20071212/SCons/Defaults.py b/scons/scons-local-1.2.0/SCons/Defaults.py similarity index 79% rename from scons/scons-local-0.97.0d20071212/SCons/Defaults.py rename to scons/scons-local-1.2.0/SCons/Defaults.py index e4b0391c1d..fc0ab26ba3 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Defaults.py +++ b/scons/scons-local-1.2.0/SCons/Defaults.py @@ -10,7 +10,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -32,7 +32,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Defaults.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Defaults.py 3842 2008/12/20 22:59:52 scons" @@ -40,6 +40,7 @@ import os.path import shutil import stat +import string import time import types import sys @@ -93,7 +94,7 @@ def DefaultEnvironment(*args, **kw): _default_env.Decider('timestamp-match') global DefaultEnvironment DefaultEnvironment = _fetch_DefaultEnvironment - _default_env._CacheDir = SCons.CacheDir.Null() + _default_env._CacheDir_path = None return _default_env # Emitters for setting the shared attribute on object files, @@ -157,19 +158,36 @@ def SharedFlagChecker(source, target, env): # ways by creating ActionFactory instances. ActionFactory = SCons.Action.ActionFactory -def chmod_func(path, mode): - return os.chmod(str(path), mode) +def get_paths_str(dest): + # If dest is a list, we need to manually call str() on each element + if SCons.Util.is_List(dest): + elem_strs = [] + for element in dest: + elem_strs.append('"' + str(element) + '"') + return '[' + string.join(elem_strs, ', ') + ']' + else: + return '"' + str(dest) + '"' + +def chmod_func(dest, mode): + SCons.Node.FS.invalidate_node_memos(dest) + if not SCons.Util.is_List(dest): + dest = [dest] + for element in dest: + os.chmod(str(element), mode) + +def chmod_strfunc(dest, mode): + return 'Chmod(%s, 0%o)' % (get_paths_str(dest), mode) -Chmod = ActionFactory(chmod_func, - lambda dest, mode: 'Chmod("%s", 0%o)' % (dest, mode)) +Chmod = ActionFactory(chmod_func, chmod_strfunc) def copy_func(dest, src): + SCons.Node.FS.invalidate_node_memos(dest) if SCons.Util.is_List(src) and os.path.isdir(dest): for file in src: - shutil.copy(file, dest) + shutil.copy2(file, dest) return 0 elif os.path.isfile(src): - return shutil.copy(src, dest) + return shutil.copy2(src, dest) else: return shutil.copytree(src, dest, 1) @@ -177,40 +195,61 @@ def copy_func(dest, src): lambda dest, src: 'Copy("%s", "%s")' % (dest, src), convert=str) -def delete_func(entry, must_exist=0): - entry = str(entry) - if not must_exist and not os.path.exists(entry): - return None - if not os.path.exists(entry) or os.path.isfile(entry): - return os.unlink(entry) - else: - return shutil.rmtree(entry, 1) +def delete_func(dest, must_exist=0): + SCons.Node.FS.invalidate_node_memos(dest) + if not SCons.Util.is_List(dest): + dest = [dest] + for entry in dest: + entry = str(entry) + if not must_exist and not os.path.exists(entry): + continue + if not os.path.exists(entry) or os.path.isfile(entry): + os.unlink(entry) + continue + else: + shutil.rmtree(entry, 1) + continue -def delete_strfunc(entry, must_exist=0): - return 'Delete("%s")' % entry +def delete_strfunc(dest, must_exist=0): + return 'Delete(%s)' % get_paths_str(dest) Delete = ActionFactory(delete_func, delete_strfunc) -Mkdir = ActionFactory(os.makedirs, - lambda dir: 'Mkdir("%s")' % dir, - convert=str) +def mkdir_func(dest): + SCons.Node.FS.invalidate_node_memos(dest) + if not SCons.Util.is_List(dest): + dest = [dest] + for entry in dest: + os.makedirs(str(entry)) -Move = ActionFactory(lambda dest, src: os.rename(src, dest), +Mkdir = ActionFactory(mkdir_func, + lambda dir: 'Mkdir(%s)' % get_paths_str(dir)) + +def move_func(dest, src): + SCons.Node.FS.invalidate_node_memos(dest) + SCons.Node.FS.invalidate_node_memos(src) + os.rename(src, dest) + +Move = ActionFactory(move_func, lambda dest, src: 'Move("%s", "%s")' % (dest, src), convert=str) -def touch_func(file): - file = str(file) - mtime = int(time.time()) - if os.path.exists(file): - atime = os.path.getatime(file) - else: - open(file, 'w') - atime = mtime - return os.utime(file, (atime, mtime)) +def touch_func(dest): + SCons.Node.FS.invalidate_node_memos(dest) + if not SCons.Util.is_List(dest): + dest = [dest] + for file in dest: + file = str(file) + mtime = int(time.time()) + if os.path.exists(file): + atime = os.path.getatime(file) + else: + open(file, 'w') + atime = mtime + os.utime(file, (atime, mtime)) Touch = ActionFactory(touch_func, - lambda file: 'Touch("%s")' % file) + lambda file: 'Touch(%s)' % get_paths_str(file)) # Internal utility functions @@ -224,9 +263,6 @@ def _concat(prefix, list, suffix, env, f=lambda x: x, target=None, source=None): if not list: return list - if SCons.Util.is_List(list): - list = SCons.Util.flatten(list) - l = f(SCons.PathList.PathList(list).subst_path(env, target, source)) if not l is None: list = l @@ -270,7 +306,7 @@ def _concat_ixes(prefix, list, suffix, env): return result -def _stripixes(prefix, list, suffix, stripprefix, stripsuffix, env, c=None): +def _stripixes(prefix, list, suffix, stripprefixes, stripsuffixes, env, c=None): """ This is a wrapper around _concat()/_concat_ixes() that checks for the existence of prefixes or suffixes on list elements and strips them @@ -292,22 +328,32 @@ def _stripixes(prefix, list, suffix, stripprefix, stripsuffix, env, c=None): else: c = _concat_ixes - if SCons.Util.is_List(list): - list = SCons.Util.flatten(list) + stripprefixes = map(env.subst, SCons.Util.flatten(stripprefixes)) + stripsuffixes = map(env.subst, SCons.Util.flatten(stripsuffixes)) - lsp = len(stripprefix) - lss = len(stripsuffix) stripped = [] for l in SCons.PathList.PathList(list).subst_path(env, None, None): if isinstance(l, SCons.Node.FS.File): stripped.append(l) continue + if not SCons.Util.is_String(l): l = str(l) - if l[:lsp] == stripprefix: - l = l[lsp:] - if l[-lss:] == stripsuffix: - l = l[:-lss] + + for stripprefix in stripprefixes: + lsp = len(stripprefix) + if l[:lsp] == stripprefix: + l = l[lsp:] + # Do not strip more than one prefix + break + + for stripsuffix in stripsuffixes: + lss = len(stripsuffix) + if l[-lss:] == stripsuffix: + l = l[:-lss] + # Do not strip more than one suffix + break + stripped.append(l) return c(prefix, stripped, suffix, env) @@ -378,7 +424,10 @@ def __init__(self, variable, method): self.method = method def __call__(self, *args, **kw): try: 1/0 - except ZeroDivisionError: frame = sys.exc_info()[2].tb_frame + except ZeroDivisionError: + # Don't start iterating with the current stack-frame to + # prevent creating reference cycles (f_back is safe). + frame = sys.exc_info()[2].tb_frame.f_back variable = self.variable while frame: if frame.f_locals.has_key(variable): diff --git a/scons/scons-local-0.97.0d20071212/SCons/Environment.py b/scons/scons-local-1.2.0/SCons/Environment.py similarity index 86% rename from scons/scons-local-0.97.0d20071212/SCons/Environment.py rename to scons/scons-local-1.2.0/SCons/Environment.py index c3244795f8..e1a8ec2c66 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Environment.py +++ b/scons/scons-local-1.2.0/SCons/Environment.py @@ -10,7 +10,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -32,12 +32,13 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Environment.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Environment.py 3842 2008/12/20 22:59:52 scons" import copy import os -import os.path +import sys +import re import shlex import string from UserDict import UserDict @@ -64,6 +65,10 @@ class _Null: _null = _Null +_warn_copy_deprecated = True +_warn_source_signatures_deprecated = True +_warn_target_signatures_deprecated = True + CleanTargets = {} CalculatorArgs = {} @@ -100,24 +105,40 @@ def apply_tools(env, tools, toolpath): else: env.Tool(tool) -# These names are controlled by SCons; users should never set or override -# them. This warning can optionally be turned off, but scons will still -# ignore the illegal variable names even if it's off. -reserved_construction_var_names = \ - ['TARGET', 'TARGETS', 'SOURCE', 'SOURCES'] +# These names are (or will be) controlled by SCons; users should never +# set or override them. This warning can optionally be turned off, +# but scons will still ignore the illegal variable names even if it's off. +reserved_construction_var_names = [ + 'SOURCE', + 'SOURCES', + 'TARGET', + 'TARGETS', +] + +future_reserved_construction_var_names = [ + 'CHANGED_SOURCES', + 'CHANGED_TARGETS', + 'UNCHANGED_SOURCES', + 'UNCHANGED_TARGETS', +] def copy_non_reserved_keywords(dict): result = semi_deepcopy(dict) for k in result.keys(): if k in reserved_construction_var_names: - SCons.Warnings.warn(SCons.Warnings.ReservedVariableWarning, - "Ignoring attempt to set reserved variable `%s'" % k) + msg = "Ignoring attempt to set reserved variable `$%s'" + SCons.Warnings.warn(SCons.Warnings.ReservedVariableWarning, msg % k) del result[k] return result def _set_reserved(env, key, value): - msg = "Ignoring attempt to set reserved variable `%s'" % key - SCons.Warnings.warn(SCons.Warnings.ReservedVariableWarning, msg) + msg = "Ignoring attempt to set reserved variable `$%s'" + SCons.Warnings.warn(SCons.Warnings.ReservedVariableWarning, msg % key) + +def _set_future_reserved(env, key, value): + env._dict[key] = value + msg = "`$%s' will be reserved in a future release and setting it will become ignored" + SCons.Warnings.warn(SCons.Warnings.FutureReservedVariableWarning, msg % key) def _set_BUILDERS(env, key, value): try: @@ -137,6 +158,24 @@ def _set_SCANNERS(env, key, value): env._dict[key] = value env.scanner_map_delete() +def _delete_duplicates(l, keep_last): + """Delete duplicates from a sequence, keeping the first or last.""" + seen={} + result=[] + if keep_last: # reverse in & out, then keep first + l.reverse() + for i in l: + try: + if not seen.has_key(i): + result.append(i) + seen[i]=1 + except TypeError: + # probably unhashable. Just keep it. + result.append(i) + if keep_last: + result.reverse() + return result + # The following is partly based on code in a comment added by Peter @@ -225,7 +264,7 @@ def __getattr__(self, name): elif name == 'builder': return self.method else: - return self.__dict__[name] + raise AttributeError, name def __setattr__(self, name, value): if name == 'env': @@ -279,6 +318,18 @@ def update(self, dict): for i, v in dict.items(): self.__setitem__(i, v) + + +_is_valid_var = re.compile(r'[_a-zA-Z]\w*$') + +def is_valid_construction_var(varstr): + """Return if the specified string is a legitimate construction + variable. + """ + return _is_valid_var.match(varstr) + + + class SubstitutionEnvironment: """Base class for different flavors of construction environments. @@ -329,9 +380,16 @@ def _init_special(self): self._special_set = {} for key in reserved_construction_var_names: self._special_set[key] = _set_reserved + for key in future_reserved_construction_var_names: + self._special_set[key] = _set_future_reserved self._special_set['BUILDERS'] = _set_BUILDERS self._special_set['SCANNERS'] = _set_SCANNERS + # Freeze the keys of self._special_set in a list for use by + # methods that need to check. (Empirically, list scanning has + # gotten better than dict.has_key() in Python 2.5.) + self._special_set_keys = self._special_set.keys() + def __cmp__(self, other): return cmp(self._dict, other._dict) @@ -346,12 +404,28 @@ def __getitem__(self, key): return self._dict[key] def __setitem__(self, key, value): - special = self._special_set.get(key) - if special: - special(self, key, value) + # This is heavily used. This implementation is the best we have + # according to the timings in bench/env.__setitem__.py. + # + # The "key in self._special_set_keys" test here seems to perform + # pretty well for the number of keys we have. A hard-coded + # list works a little better in Python 2.5, but that has the + # disadvantage of maybe getting out of sync if we ever add more + # variable names. Using self._special_set.has_key() works a + # little better in Python 2.4, but is worse then this test. + # So right now it seems like a good trade-off, but feel free to + # revisit this with bench/env.__setitem__.py as needed (and + # as newer versions of Python come out). + if key in self._special_set_keys: + self._special_set[key](self, key, value) else: - if not SCons.Util.is_valid_construction_var(key): - raise SCons.Errors.UserError, "Illegal construction variable `%s'" % key + # If we already have the entry, then it's obviously a valid + # key and we don't need to check. If we do check, using a + # global, pre-compiled regular expression directly is more + # efficient than calling another function or a method. + if not self._dict.has_key(key) \ + and not _is_valid_var.match(key): + raise SCons.Errors.UserError, "Illegal construction variable `%s'" % key self._dict[key] = value def get(self, key, default=None): @@ -361,6 +435,9 @@ def get(self, key, default=None): def has_key(self, key): return self._dict.has_key(key) + def __contains__(self, key): + return self._dict.__contains__(key) + def items(self): return self._dict.items() @@ -373,10 +450,7 @@ def arg2nodes(self, args, node_factory=_null, lookup_list=_null, **kw): if not args: return [] - if SCons.Util.is_List(args): - args = SCons.Util.flatten(args) - else: - args = [args] + args = SCons.Util.flatten(args) nodes = [] for v in args: @@ -465,7 +539,7 @@ def s(obj): try: get = obj.get except AttributeError: - pass + obj = SCons.Util.to_String_for_subst(obj) else: obj = get() return obj @@ -481,7 +555,7 @@ def s(obj): # We have an object plus a string, or multiple # objects that we need to smush together. No choice # but to make them into a string. - p = string.join(map(SCons.Util.to_String, p), '') + p = string.join(map(SCons.Util.to_String_for_subst, p), '') else: p = s(p) r.append(p) @@ -491,24 +565,21 @@ def s(obj): def backtick(self, command): import subprocess - if SCons.Util.is_List(command): - p = subprocess.Popen(command, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - universal_newlines=True) - else: - p = subprocess.Popen(command, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - universal_newlines=True, - shell=True) - out = p.stdout.read() - p.stdout.close() - err = p.stderr.read() - p.stderr.close() + # common arguments + kw = { 'stdin' : 'devnull', + 'stdout' : subprocess.PIPE, + 'stderr' : subprocess.PIPE, + 'universal_newlines' : True, + } + # if the command is a list, assume it's been quoted + # othewise force a shell + if not SCons.Util.is_List(command): kw['shell'] = True + # run constructed command + #TODO(1.5) p = SCons.Action._subproc(self, command, **kw) + p = apply(SCons.Action._subproc, (self, command), kw) + out,err = p.communicate() status = p.wait() if err: - import sys sys.stderr.write(err) if status: raise OSError("'%s' exited %d" % (command, status)) @@ -543,16 +614,19 @@ def Override(self, overrides): environment, and doesn't even create a wrapper object if there are no overrides. """ - if overrides: - o = copy_non_reserved_keywords(overrides) - overrides = {} - for key, value in o.items(): + if not overrides: return self + o = copy_non_reserved_keywords(overrides) + if not o: return self + overrides = {} + merges = None + for key, value in o.items(): + if key == 'parse_flags': + merges = value + else: overrides[key] = SCons.Subst.scons_subst_once(value, self, key) - if overrides: - env = OverrideEnvironment(self, overrides) - return env - else: - return self + env = OverrideEnvironment(self, overrides) + if merges: env.MergeFlags(merges) + return env def ParseFlags(self, *flags): """ @@ -709,13 +783,16 @@ def append_define(name, dict = dict): do_parse(arg, do_parse) return dict - def MergeFlags(self, args, unique=1): + def MergeFlags(self, args, unique=1, dict=None): """ - Merge the dict in args into the construction variables. If args - is not a dict, it is converted into a dict using ParseFlags. - If unique is not set, the flags are appended rather than merged. + Merge the dict in args into the construction variables of this + env, or the passed-in dict. If args is not a dict, it is + converted into a dict using ParseFlags. If unique is not set, + the flags are appended rather than merged. """ + if dict is None: + dict = self if not SCons.Util.is_Dict(args): args = self.ParseFlags(args) if not unique: @@ -763,6 +840,26 @@ def MergeFlags(self, args, unique=1): self[key] = t return self +# def MergeShellPaths(self, args, prepend=1): +# """ +# Merge the dict in args into the shell environment in env['ENV']. +# Shell path elements are appended or prepended according to prepend. + +# Uses Pre/AppendENVPath, so it always appends or prepends uniquely. + +# Example: env.MergeShellPaths({'LIBPATH': '/usr/local/lib'}) +# prepends /usr/local/lib to env['ENV']['LIBPATH']. +# """ + +# for pathname, pathval in args.items(): +# if not pathval: +# continue +# if prepend: +# apply(self.PrependENVPath, (pathname, pathval)) +# else: +# apply(self.AppendENVPath, (pathname, pathval)) + + # Used by the FindSourceFiles() method, below. # Stuck here for support of pre-2.2 Python versions. def build_source(ss, result): @@ -819,7 +916,8 @@ def __init__(self, platform=None, tools=None, toolpath=None, - options=None, + variables=None, + parse_flags = None, **kw): """ Initialization of a basic SCons construction environment, @@ -862,14 +960,19 @@ def __init__(self, self._dict['PLATFORM'] = str(platform) platform(self) - # Apply the passed-in variables and customizable options to the + # Apply the passed-in and customizable variables to the # environment before calling the tools, because they may use # some of them during initialization. + if kw.has_key('options'): + # Backwards compatibility: they may stll be using the + # old "options" keyword. + variables = kw['options'] + del kw['options'] apply(self.Replace, (), kw) keys = kw.keys() - if options: - keys = keys + options.keys() - options.Update(self) + if variables: + keys = keys + variables.keys() + variables.Update(self) save = {} for k in keys: @@ -888,12 +991,15 @@ def __init__(self, tools = ['default'] apply_tools(self, tools, toolpath) - # Now restore the passed-in variables and customized options + # Now restore the passed-in and customized variables # to the environment, since the values the user set explicitly # should override any values set by the tools. for key, val in save.items(): self._dict[key] = val + # Finally, apply any flags to be merged in + if parse_flags: self.MergeFlags(parse_flags) + ####################################################################### # Utility methods that are primarily for internal use by SCons. # These begin with lower-case letters. @@ -909,11 +1015,18 @@ def get_builder(self, name): def get_CacheDir(self): try: - return self._CacheDir + path = self._CacheDir_path except AttributeError: - cd = SCons.Defaults.DefaultEnvironment()._CacheDir - self._CacheDir = cd - return cd + path = SCons.Defaults.DefaultEnvironment()._CacheDir_path + try: + if path == self._last_CacheDir_path: + return self._last_CacheDir + except AttributeError: + pass + cd = SCons.CacheDir.CacheDir(path) + self._last_CacheDir_path = path + self._last_CacheDir = cd + return cd def get_factory(self, factory, default='File'): """Return a factory function for creating Nodes for this @@ -1085,31 +1198,39 @@ def Append(self, **kw): orig[val] = None self.scanner_map_delete(kw) - def AppendENVPath(self, name, newpath, envname = 'ENV', sep = os.pathsep): + def AppendENVPath(self, name, newpath, envname = 'ENV', + sep = os.pathsep, delete_existing=1): """Append path elements to the path 'name' in the 'ENV' dictionary for this environment. Will only add any particular path once, and will normpath and normcase all paths to help assure this. This can also handle the case where the env variable is a list instead of a string. + + If delete_existing is 0, a newpath which is already in the path + will not be moved to the end (it will be left where it is). """ orig = '' if self._dict.has_key(envname) and self._dict[envname].has_key(name): orig = self._dict[envname][name] - nv = SCons.Util.AppendPath(orig, newpath, sep) + nv = SCons.Util.AppendPath(orig, newpath, sep, delete_existing) if not self._dict.has_key(envname): self._dict[envname] = {} self._dict[envname][name] = nv - def AppendUnique(self, **kw): + def AppendUnique(self, delete_existing=0, **kw): """Append values to existing construction variables in an Environment, if they're not already there. + If delete_existing is 1, removes existing values first, so + values move to end. """ kw = copy_non_reserved_keywords(kw) for key, val in kw.items(): + if SCons.Util.is_List(val): + val = _delete_duplicates(val, delete_existing) if not self._dict.has_key(key) or self._dict[key] in ('', None): self._dict[key] = val elif SCons.Util.is_Dict(self._dict[key]) and \ @@ -1119,20 +1240,29 @@ def AppendUnique(self, **kw): dk = self._dict[key] if not SCons.Util.is_List(dk): dk = [dk] - val = filter(lambda x, dk=dk: x not in dk, val) + if delete_existing: + dk = filter(lambda x, val=val: x not in val, dk) + else: + val = filter(lambda x, dk=dk: x not in dk, val) self._dict[key] = dk + val else: dk = self._dict[key] if SCons.Util.is_List(dk): # By elimination, val is not a list. Since dk is a # list, wrap val in a list first. - if not val in dk: + if delete_existing: + dk = filter(lambda x, val=val: x not in val, dk) self._dict[key] = dk + [val] + else: + if not val in dk: + self._dict[key] = dk + [val] else: - self._dict[key] = self._dict[key] + val + if delete_existing: + dk = filter(lambda x, val=val: x not in val, dk) + self._dict[key] = dk + val self.scanner_map_delete(kw) - def Clone(self, tools=[], toolpath=None, **kw): + def Clone(self, tools=[], toolpath=None, parse_flags = None, **kw): """Return a copy of a construction Environment. The copy is like a Python "deep copy"--that is, independent copies are made recursively of each objects--except that @@ -1150,9 +1280,14 @@ def Clone(self, tools=[], toolpath=None, **kw): else: clone._dict['BUILDERS'] = BuilderDict(cbd, clone) + # Check the methods added via AddMethod() and re-bind them to + # the cloned environment. Only do this if the attribute hasn't + # been overwritten by the user explicitly and still points to + # the added method. clone.added_methods = [] for mw in self.added_methods: - clone.added_methods.append(mw.clone(clone)) + if mw == getattr(self, mw.name): + clone.added_methods.append(mw.clone(clone)) clone._memo = {} @@ -1169,10 +1304,18 @@ def Clone(self, tools=[], toolpath=None, **kw): # apply them again in case the tools overwrote them apply(clone.Replace, (), new) + # Finally, apply any flags to be merged in + if parse_flags: clone.MergeFlags(parse_flags) + if __debug__: logInstanceCreation(self, 'Environment.EnvironmentClone') return clone def Copy(self, *args, **kw): + global _warn_copy_deprecated + if _warn_copy_deprecated: + msg = "The env.Copy() method is deprecated; use the env.Clone() method instead." + SCons.Warnings.warn(SCons.Warnings.DeprecatedCopyWarning, msg) + _warn_copy_deprecated = False return apply(self.Clone, args, kw) def _changed_build(self, dependency, target, prev_ni): @@ -1410,31 +1553,39 @@ def Prepend(self, **kw): orig[val] = None self.scanner_map_delete(kw) - def PrependENVPath(self, name, newpath, envname = 'ENV', sep = os.pathsep): + def PrependENVPath(self, name, newpath, envname = 'ENV', sep = os.pathsep, + delete_existing=1): """Prepend path elements to the path 'name' in the 'ENV' dictionary for this environment. Will only add any particular path once, and will normpath and normcase all paths to help assure this. This can also handle the case where the env variable is a list instead of a string. + + If delete_existing is 0, a newpath which is already in the path + will not be moved to the front (it will be left where it is). """ orig = '' if self._dict.has_key(envname) and self._dict[envname].has_key(name): orig = self._dict[envname][name] - nv = SCons.Util.PrependPath(orig, newpath, sep) + nv = SCons.Util.PrependPath(orig, newpath, sep, delete_existing) if not self._dict.has_key(envname): self._dict[envname] = {} self._dict[envname][name] = nv - def PrependUnique(self, **kw): - """Append values to existing construction variables + def PrependUnique(self, delete_existing=0, **kw): + """Prepend values to existing construction variables in an Environment, if they're not already there. + If delete_existing is 1, removes existing values first, so + values move to front. """ kw = copy_non_reserved_keywords(kw) for key, val in kw.items(): + if SCons.Util.is_List(val): + val = _delete_duplicates(val, not delete_existing) if not self._dict.has_key(key) or self._dict[key] in ('', None): self._dict[key] = val elif SCons.Util.is_Dict(self._dict[key]) and \ @@ -1444,16 +1595,25 @@ def PrependUnique(self, **kw): dk = self._dict[key] if not SCons.Util.is_List(dk): dk = [dk] - val = filter(lambda x, dk=dk: x not in dk, val) + if delete_existing: + dk = filter(lambda x, val=val: x not in val, dk) + else: + val = filter(lambda x, dk=dk: x not in dk, val) self._dict[key] = val + dk else: dk = self._dict[key] if SCons.Util.is_List(dk): # By elimination, val is not a list. Since dk is a # list, wrap val in a list first. - if not val in dk: + if delete_existing: + dk = filter(lambda x, val=val: x not in val, dk) self._dict[key] = [val] + dk + else: + if not val in dk: + self._dict[key] = [val] + dk else: + if delete_existing: + dk = filter(lambda x, val=val: x not in val, dk) self._dict[key] = val + dk self.scanner_map_delete(kw) @@ -1532,6 +1692,7 @@ def WhereIs(self, prog, path=None, pathext=None, reject=[]): pass elif SCons.Util.is_String(pathext): pathext = self.subst(pathext) + prog = self.subst(prog) path = SCons.Util.WhereIs(prog, path, pathext, reject) if path: return path return None @@ -1634,10 +1795,11 @@ def AlwaysBuild(self, *targets): t.set_always_build() return tlist - def BuildDir(self, build_dir, src_dir, duplicate=1): - build_dir = self.arg2nodes(build_dir, self.fs.Dir)[0] - src_dir = self.arg2nodes(src_dir, self.fs.Dir)[0] - self.fs.BuildDir(build_dir, src_dir, duplicate) + def BuildDir(self, *args, **kw): + if kw.has_key('build_dir'): + kw['variant_dir'] = kw['build_dir'] + del kw['build_dir'] + return apply(self.VariantDir, args, kw) def Builder(self, **kw): nkw = self.subst_kw(kw) @@ -1645,10 +1807,9 @@ def Builder(self, **kw): def CacheDir(self, path): import SCons.CacheDir - if path is None: - self._CacheDir = SCons.CacheDir.Null() - else: - self._CacheDir = SCons.CacheDir.CacheDir(self.subst(path)) + if not path is None: + path = self.subst(path) + self._CacheDir_path = path def Clean(self, targets, files): global CleanTargets @@ -1699,7 +1860,13 @@ def Depends(self, target, dependency): def Dir(self, name, *args, **kw): """ """ - return apply(self.fs.Dir, (self.subst(name),) + args, kw) + s = self.subst(name) + if SCons.Util.is_Sequence(s): + result=[] + for e in s: + result.append(apply(self.fs.Dir, (e,) + args, kw)) + return result + return apply(self.fs.Dir, (s,) + args, kw) def NoClean(self, *targets): """Tags a target so that it will not be cleaned by -c""" @@ -1722,7 +1889,13 @@ def NoCache(self, *targets): def Entry(self, name, *args, **kw): """ """ - return apply(self.fs.Entry, (self.subst(name),) + args, kw) + s = self.subst(name) + if SCons.Util.is_Sequence(s): + result=[] + for e in s: + result.append(apply(self.fs.Entry, (e,) + args, kw)) + return result + return apply(self.fs.Entry, (s,) + args, kw) def Environment(self, **kw): return apply(SCons.Environment.Environment, [], self.subst_kw(kw)) @@ -1733,6 +1906,10 @@ def Execute(self, action, *args, **kw): action = apply(self.Action, (action,) + args, kw) result = action([], [], self) if isinstance(result, SCons.Errors.BuildError): + errstr = result.errstr + if result.filename: + errstr = result.filename + ': ' + errstr + sys.stderr.write("scons: *** %s\n" % errstr) return result.status else: return result @@ -1740,7 +1917,13 @@ def Execute(self, action, *args, **kw): def File(self, name, *args, **kw): """ """ - return apply(self.fs.File, (self.subst(name),) + args, kw) + s = self.subst(name) + if SCons.Util.is_Sequence(s): + result=[] + for e in s: + result.append(apply(self.fs.File, (e,) + args, kw)) + return result + return apply(self.fs.File, (s,) + args, kw) def FindFile(self, file, dirs): file = self.subst(file) @@ -1819,6 +2002,11 @@ def SConsignFile(self, name=".sconsign", dbm_module=None): name = self.subst(name) if not os.path.isabs(name): name = os.path.join(str(self.fs.SConstruct_dir), name) + if name: + name = os.path.normpath(name) + sconsign_dir = os.path.dirname(name) + if sconsign_dir and not os.path.exists(sconsign_dir): + self.Execute(SCons.Defaults.Mkdir(sconsign_dir)) SCons.SConsign.File(name, dbm_module) def SideEffect(self, side_effect, target): @@ -1845,6 +2033,12 @@ def SourceCode(self, entry, builder): return entries def SourceSignatures(self, type): + global _warn_source_signatures_deprecated + if _warn_source_signatures_deprecated: + msg = "The env.SourceSignatures() method is deprecated;\n" + \ + "\tconvert your build to use the env.Decider() method instead." + SCons.Warnings.warn(SCons.Warnings.DeprecatedSourceSignaturesWarning, msg) + _warn_source_signatures_deprecated = False type = self.subst(type) self.src_sig_type = type if type == 'MD5': @@ -1875,6 +2069,12 @@ def Split(self, arg): return [self.subst(arg)] def TargetSignatures(self, type): + global _warn_target_signatures_deprecated + if _warn_target_signatures_deprecated: + msg = "The env.TargetSignatures() method is deprecated;\n" + \ + "\tconvert your build to use the env.Decider() method instead." + SCons.Warnings.warn(SCons.Warnings.DeprecatedTargetSignaturesWarning, msg) + _warn_target_signatures_deprecated = False type = self.subst(type) self.tgt_sig_type = type if type in ('MD5', 'content'): @@ -1895,6 +2095,11 @@ def Value(self, value, built_value=None): """ return SCons.Node.Python.Value(value, built_value) + def VariantDir(self, variant_dir, src_dir, duplicate=1): + variant_dir = self.arg2nodes(variant_dir, self.fs.Dir)[0] + src_dir = self.arg2nodes(src_dir, self.fs.Dir)[0] + self.fs.VariantDir(variant_dir, src_dir, duplicate) + def FindSourceFiles(self, node='.'): """ returns a list of all source files. """ @@ -1978,7 +2183,7 @@ def __getitem__(self, key): except KeyError: return self.__dict__['__subject'].__getitem__(key) def __setitem__(self, key, value): - if not SCons.Util.is_valid_construction_var(key): + if not is_valid_construction_var(key): raise SCons.Errors.UserError, "Illegal construction variable `%s'" % key self.__dict__['overrides'][key] = value def __delitem__(self, key): @@ -2007,6 +2212,10 @@ def has_key(self, key): return 1 except KeyError: return self.__dict__['__subject'].has_key(key) + def __contains__(self, key): + if self.__dict__['overrides'].__contains__(key): + return 1 + return self.__dict__['__subject'].__contains__(key) def Dictionary(self): """Emulates the items() method of dictionaries.""" d = self.__dict__['__subject'].Dictionary().copy() diff --git a/scons/scons-local-1.2.0/SCons/Errors.py b/scons/scons-local-1.2.0/SCons/Errors.py new file mode 100644 index 0000000000..8369873c7e --- /dev/null +++ b/scons/scons-local-1.2.0/SCons/Errors.py @@ -0,0 +1,198 @@ +# +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation +# +# 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. +# + +"""SCons.Errors + +This file contains the exception classes used to handle internal +and user errors in SCons. + +""" + +__revision__ = "src/engine/SCons/Errors.py 3842 2008/12/20 22:59:52 scons" + +import SCons.Util + +import exceptions + +class BuildError(Exception): + """ Errors occuring while building. + + BuildError have the following attributes: + + Information about the cause of the build error: + ----------------------------------------------- + + errstr : a description of the error message + + status : the return code of the action that caused the build + error. Must be set to a non-zero value even if the + build error is not due to an action returning a + non-zero returned code. + + exitstatus : SCons exit status due to this build error. + Must be nonzero unless due to an explicit Exit() + call. Not always the same as status, since + actions return a status code that should be + respected, but SCons typically exits with 2 + irrespective of the return value of the failed + action. + + filename : The name of the file or directory that caused the + build error. Set to None if no files are associated with + this error. This might be different from the target + being built. For example, failure to create the + directory in which the target file will appear. It + can be None if the error is not due to a particular + filename. + + exc_info : Info about exception that caused the build + error. Set to (None, None, None) if this build + error is not due to an exception. + + + Information about the cause of the location of the error: + --------------------------------------------------------- + + node : the error occured while building this target node(s) + + executor : the executor that caused the build to fail (might + be None if the build failures is not due to the + executor failing) + + action : the action that caused the build to fail (might be + None if the build failures is not due to the an + action failure) + + command : the command line for the action that caused the + build to fail (might be None if the build failures + is not due to the an action failure) + """ + + def __init__(self, + node=None, errstr="Unknown error", status=2, exitstatus=2, + filename=None, executor=None, action=None, command=None, + exc_info=(None, None, None)): + + self.errstr = errstr + self.status = status + self.exitstatus = exitstatus + self.filename = filename + self.exc_info = exc_info + + self.node = node + self.executor = executor + self.action = action + self.command = command + + Exception.__init__(self, node, errstr, status, exitstatus, filename, + executor, action, command, exc_info) + + def __str__(self): + if self.filename: + return self.filename + ': ' + self.errstr + else: + return self.errstr + +class InternalError(Exception): + pass + +class UserError(Exception): + pass + +class StopError(Exception): + pass + +class EnvironmentError(Exception): + pass + +class ExplicitExit(Exception): + def __init__(self, node=None, status=None, *args): + self.node = node + self.status = status + self.exitstatus = status + apply(Exception.__init__, (self,) + args) + +def convert_to_BuildError(status, exc_info=None): + """ + Convert any return code a BuildError Exception. + + `status' can either be a return code or an Exception. + The buildError.status we set here will normally be + used as the exit status of the "scons" process. + """ + if not exc_info and isinstance(status, Exception): + exc_info = (status.__class__, status, None) + + if isinstance(status, BuildError): + buildError = status + buildError.exitstatus = 2 # always exit with 2 on build errors + elif isinstance(status, ExplicitExit): + status = status.status + errstr = 'Explicit exit, status %s' % status + buildError = BuildError( + errstr=errstr, + status=status, # might be 0, OK here + exitstatus=status, # might be 0, OK here + exc_info=exc_info) + # TODO(1.5): + #elif isinstance(status, (StopError, UserError)): + elif isinstance(status, StopError) or isinstance(status, UserError): + buildError = BuildError( + errstr=str(status), + status=2, + exitstatus=2, + exc_info=exc_info) + elif isinstance(status, exceptions.EnvironmentError): + # If an IOError/OSError happens, raise a BuildError. + # Report the name of the file or directory that caused the + # error, which might be different from the target being built + # (for example, failure to create the directory in which the + # target file will appear). + try: filename = status.filename + except AttributeError: filename = None + buildError = BuildError( + errstr=status.strerror, + status=status.errno, + exitstatus=2, + filename=filename, + exc_info=exc_info) + elif isinstance(status, Exception): + buildError = BuildError( + errstr='%s : %s' % (status.__class__.__name__, status), + status=2, + exitstatus=2, + exc_info=exc_info) + elif SCons.Util.is_String(status): + buildError = BuildError( + errstr=status, + status=2, + exitstatus=2) + else: + buildError = BuildError( + errstr="Error %s" % status, + status=status, + exitstatus=2) + + #import sys + #sys.stderr.write("convert_to_BuildError: status %s => (errstr %s, status %s)"%(status,buildError.errstr, buildError.status)) + return buildError diff --git a/scons/scons-local-0.97.0d20071212/SCons/Executor.py b/scons/scons-local-1.2.0/SCons/Executor.py similarity index 78% rename from scons/scons-local-0.97.0d20071212/SCons/Executor.py rename to scons/scons-local-1.2.0/SCons/Executor.py index f7179768ce..a37da0719e 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Executor.py +++ b/scons/scons-local-1.2.0/SCons/Executor.py @@ -6,7 +6,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -28,7 +28,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Executor.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Executor.py 3842 2008/12/20 22:59:52 scons" import string @@ -134,7 +134,11 @@ def do_execute(self, target, kw): raise status elif status: msg = "Error %s" % status - raise SCons.Errors.BuildError(errstr=msg, executor=self, action=act) + raise SCons.Errors.BuildError( + errstr=msg, + node=self.targets, + executor=self, + action=act) return status # use extra indirection because with new-style objects (Python 2.2 @@ -160,6 +164,16 @@ def get_sources(self): self.sources_need_sorting = False return self.sources + def prepare(self): + """ + Preparatory checks for whether this Executor can go ahead + and (try to) build its targets. + """ + for s in self.get_sources(): + if s.missing(): + msg = "Source `%s' not found, needed by target `%s'." + raise SCons.Errors.StopError, msg % (s, self.targets[0]) + def add_pre_action(self, action): self.pre_actions.append(action) @@ -221,40 +235,35 @@ def scan(self, scanner, node_list): This essentially short-circuits an N*M scan of the sources for each individual target, which is a hell of a lot more efficient. """ - map(lambda N: N.disambiguate(), node_list) - env = self.get_build_env() - select_specific_scanner = lambda t: (t[0], t[1].select(t[0])) - remove_null_scanners = lambda t: not t[1] is None - add_scanner_path = lambda t, s=self: \ - (t[0], t[1], s.get_build_scanner_path(t[1])) + + deps = [] if scanner: - scanner_list = map(lambda n, s=scanner: (n, s), node_list) + for node in node_list: + node.disambiguate() + s = scanner.select(node) + if not s: + continue + path = self.get_build_scanner_path(s) + deps.extend(node.get_implicit_deps(env, s, path)) else: kw = self.get_kw() - get_initial_scanners = lambda n, e=env, kw=kw: \ - (n, n.get_env_scanner(e, kw)) - scanner_list = map(get_initial_scanners, node_list) - scanner_list = filter(remove_null_scanners, scanner_list) - - scanner_list = map(select_specific_scanner, scanner_list) - scanner_list = filter(remove_null_scanners, scanner_list) - scanner_path_list = map(add_scanner_path, scanner_list) - - deps = [] - for node, scanner, path in scanner_path_list: - deps.extend(node.get_implicit_deps(env, scanner, path)) + for node in node_list: + node.disambiguate() + scanner = node.get_env_scanner(env, kw) + if not scanner: + continue + scanner = scanner.select(node) + if not scanner: + continue + path = self.get_build_scanner_path(scanner) + deps.extend(node.get_implicit_deps(env, scanner, path)) deps.extend(self.get_implicit_deps()) for tgt in self.targets: tgt.add_to_implicit(deps) - def get_missing_sources(self): - """ - """ - return filter(lambda s: s.missing(), self.get_sources()) - def _get_unignored_sources_key(self, ignore=()): return tuple(ignore) @@ -317,10 +326,25 @@ def get_implicit_deps(self): result.extend(act.get_implicit_deps(self.targets, self.get_sources(), build_env)) return result +nullenv = None + +def get_NullEnvironment(): + """Use singleton pattern for Null Environments.""" + global nullenv + + import SCons.Util + class NullEnvironment(SCons.Util.Null): + import SCons.CacheDir + _CacheDir_path = None + _CacheDir = SCons.CacheDir.CacheDir(None) + def get_CacheDir(self): + return self._CacheDir -_Executor = Executor + if not nullenv: + nullenv = NullEnvironment() + return nullenv -class Null(_Executor): +class Null: """A null Executor, with a null build Environment, that does nothing when the rest of the methods call it. @@ -330,20 +354,40 @@ class Null(_Executor): """ def __init__(self, *args, **kw): if __debug__: logInstanceCreation(self, 'Executor.Null') - kw['action'] = [] - apply(_Executor.__init__, (self,), kw) + self.targets = kw['targets'] def get_build_env(self): - import SCons.Util - class NullEnvironment(SCons.Util.Null): - #def get_scanner(self, key): - # return None - #def changed_since_last_build(self, dependency, target, prev_ni): - # return dependency.changed_since_last_buld(target, prev_ni) - def get_CacheDir(self): - import SCons.CacheDir - return SCons.CacheDir.Null() - return NullEnvironment() + return get_NullEnvironment() def get_build_scanner_path(self): return None def cleanup(self): pass + def prepare(self): + pass + def get_unignored_sources(self, *args, **kw): + return tuple(()) + def get_action_list(self): + return [] + def __call__(self, *args, **kw): + return 0 + def get_contents(self): + return '' + + def _morph(self): + """Morph this Null executor to a real Executor object.""" + self.__class__ = Executor + self.__init__([], targets=self.targets) + + # The following methods require morphing this Null Executor to a + # real Executor object. + + def add_pre_action(self, action): + self._morph() + self.add_pre_action(action) + def add_post_action(self, action): + self._morph() + self.add_post_action(action) + def set_action_list(self, action): + self._morph() + self.set_action_list(action) + + diff --git a/scons/scons-local-0.97.0d20071212/SCons/Job.py b/scons/scons-local-1.2.0/SCons/Job.py similarity index 58% rename from scons/scons-local-0.97.0d20071212/SCons/Job.py rename to scons/scons-local-1.2.0/SCons/Job.py index b0252c9599..bcd39819a1 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Job.py +++ b/scons/scons-local-1.2.0/SCons/Job.py @@ -7,7 +7,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -29,9 +29,37 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Job.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Job.py 3842 2008/12/20 22:59:52 scons" + +import os +import signal + +import SCons.Errors + +# The default stack size (in kilobytes) of the threads used to execute +# jobs in parallel. +# +# We use a stack size of 256 kilobytes. The default on some platforms +# is too large and prevents us from creating enough threads to fully +# parallelized the build. For example, the default stack size on linux +# is 8 MBytes. + +explicit_stack_size = None +default_stack_size = 256 + +interrupt_msg = 'Build interrupted.' + + +class InterruptState: + def __init__(self): + self.interrupted = False + + def set(self): + self.interrupted = True + + def __call__(self): + return self.interrupted -import SCons.compat class Jobs: """An instance of this class initializes N jobs, and provides @@ -54,8 +82,12 @@ class can't do it, it gets reset to 1. Wrapping interfaces that self.job = None if num > 1: + stack_size = explicit_stack_size + if stack_size is None: + stack_size = default_stack_size + try: - self.job = Parallel(taskmaster, num) + self.job = Parallel(taskmaster, num, stack_size) self.num_jobs = num except NameError: pass @@ -63,21 +95,71 @@ class can't do it, it gets reset to 1. Wrapping interfaces that self.job = Serial(taskmaster) self.num_jobs = 1 - def run(self): - """run the job""" + def run(self, postfunc=lambda: None): + """Run the jobs. + + postfunc() will be invoked after the jobs has run. It will be + invoked even if the jobs are interrupted by a keyboard + interrupt (well, in fact by a signal such as either SIGINT, + SIGTERM or SIGHUP). The execution of postfunc() is protected + against keyboard interrupts and is guaranteed to run to + completion.""" + self._setup_sig_handler() try: self.job.start() - except KeyboardInterrupt: - # mask any further keyboard interrupts so that scons - # can shutdown cleanly: - # (this only masks the keyboard interrupt for Python, - # child processes can still get the keyboard interrupt) - import signal - signal.signal(signal.SIGINT, signal.SIG_IGN) - raise - - def cleanup(self): - self.job.cleanup() + finally: + postfunc() + self._reset_sig_handler() + + def were_interrupted(self): + """Returns whether the jobs were interrupted by a signal.""" + return self.job.interrupted() + + def _setup_sig_handler(self): + """Setup an interrupt handler so that SCons can shutdown cleanly in + various conditions: + + a) SIGINT: Keyboard interrupt + b) SIGTERM: kill or system shutdown + c) SIGHUP: Controlling shell exiting + + We handle all of these cases by stopping the taskmaster. It + turns out that it very difficult to stop the build process + by throwing asynchronously an exception such as + KeyboardInterrupt. For example, the python Condition + variables (threading.Condition) and Queue's do not seem to + asynchronous-exception-safe. It would require adding a whole + bunch of try/finally block and except KeyboardInterrupt all + over the place. + + Note also that we have to be careful to handle the case when + SCons forks before executing another process. In that case, we + want the child to exit immediately. + """ + def handler(signum, stack, self=self, parentpid=os.getpid()): + if os.getpid() == parentpid: + self.job.taskmaster.stop() + self.job.interrupted.set() + else: + os._exit(2) + + self.old_sigint = signal.signal(signal.SIGINT, handler) + self.old_sigterm = signal.signal(signal.SIGTERM, handler) + try: + self.old_sighup = signal.signal(signal.SIGHUP, handler) + except AttributeError: + pass + + def _reset_sig_handler(self): + """Restore the signal handlers to their previous state (before the + call to _setup_sig_handler().""" + + signal.signal(signal.SIGINT, self.old_sigint) + signal.signal(signal.SIGTERM, self.old_sigterm) + try: + signal.signal(signal.SIGHUP, self.old_sighup) + except AttributeError: + pass class Serial: """This class is used to execute tasks in series, and is more efficient @@ -97,6 +179,7 @@ def __init__(self, taskmaster): execute (e.g. execute() raised an exception).""" self.taskmaster = taskmaster + self.interrupted = InterruptState() def start(self): """Start the job. This will begin pulling tasks from the taskmaster @@ -112,11 +195,18 @@ def start(self): try: task.prepare() - task.execute() - except KeyboardInterrupt: - raise + if task.needs_execute(): + task.execute() except: - task.exception_set() + if self.interrupted(): + try: + raise SCons.Errors.BuildError( + task.targets[0], errstr=interrupt_msg) + except: + task.exception_set() + else: + task.exception_set() + # Let the failed() callback function arrange for the # build to stop if that's appropriate. task.failed() @@ -124,9 +214,8 @@ def start(self): task.executed() task.postprocess() + self.taskmaster.cleanup() - def cleanup(self): - pass # Trap import failure so that everything in the Job module but the # Parallel class (and its dependent classes) will work if the interpreter @@ -142,28 +231,29 @@ class Worker(threading.Thread): dequeues the task, executes it, and posts a tuple including the task and a boolean indicating whether the task executed successfully. """ - def __init__(self, requestQueue, resultsQueue): + def __init__(self, requestQueue, resultsQueue, interrupted): threading.Thread.__init__(self) self.setDaemon(1) self.requestQueue = requestQueue self.resultsQueue = resultsQueue + self.interrupted = interrupted self.start() def run(self): while 1: task = self.requestQueue.get() - if not task: + if task is None: # The "None" value is used as a sentinel by # ThreadPool.cleanup(). This indicates that there # are no more tasks, so we should quit. break try: + if self.interrupted(): + raise SCons.Errors.BuildError( + task.targets[0], errstr=interrupt_msg) task.execute() - except KeyboardInterrupt: - # be explicit here for test/interrupts.py - ok = False except: task.exception_set() ok = False @@ -175,27 +265,49 @@ def run(self): class ThreadPool: """This class is responsible for spawning and managing worker threads.""" - def __init__(self, num): - """Create the request and reply queues, and 'num' worker threads.""" + def __init__(self, num, stack_size, interrupted): + """Create the request and reply queues, and 'num' worker threads. + + One must specify the stack size of the worker threads. The + stack size is specified in kilobytes. + """ self.requestQueue = Queue.Queue(0) self.resultsQueue = Queue.Queue(0) + try: + prev_size = threading.stack_size(stack_size*1024) + except AttributeError, e: + # Only print a warning if the stack size has been + # explicitly set. + if not explicit_stack_size is None: + msg = "Setting stack size is unsupported by this version of Python:\n " + \ + e.args[0] + SCons.Warnings.warn(SCons.Warnings.StackSizeWarning, msg) + except ValueError, e: + msg = "Setting stack size failed:\n " + str(e) + SCons.Warnings.warn(SCons.Warnings.StackSizeWarning, msg) + # Create worker threads self.workers = [] for _ in range(num): - worker = Worker(self.requestQueue, self.resultsQueue) + worker = Worker(self.requestQueue, self.resultsQueue, interrupted) self.workers.append(worker) - def put(self, obj): + # Once we drop Python 1.5 we can change the following to: + #if 'prev_size' in locals(): + if 'prev_size' in locals().keys(): + threading.stack_size(prev_size) + + def put(self, task): """Put task into request queue.""" - self.requestQueue.put(obj) + self.requestQueue.put(task) - def get(self, block = True): + def get(self): """Remove and return a result tuple from the results queue.""" - return self.resultsQueue.get(block) + return self.resultsQueue.get() - def preparation_failed(self, obj): - self.resultsQueue.put((obj, False)) + def preparation_failed(self, task): + self.resultsQueue.put((task, False)) def cleanup(self): """ @@ -233,7 +345,7 @@ class Parallel: This class is thread safe. """ - def __init__(self, taskmaster, num): + def __init__(self, taskmaster, num, stack_size): """Create a new parallel job given a taskmaster. The taskmaster's next_task() method should return the next @@ -249,7 +361,8 @@ def __init__(self, taskmaster, num): multiple tasks simultaneously. """ self.taskmaster = taskmaster - self.tp = ThreadPool(num) + self.interrupted = InterruptState() + self.tp = ThreadPool(num, stack_size, self.interrupted) self.maxjobs = num @@ -269,22 +382,21 @@ def start(self): if task is None: break - # prepare task for execution try: + # prepare task for execution task.prepare() - except KeyboardInterrupt: - raise except: - # Let the failed() callback function arrange - # for the build to stop if that's appropriate. task.exception_set() - self.tp.preparation_failed(task) - jobs = jobs + 1 - continue - - # dispatch task - self.tp.put(task) - jobs = jobs + 1 + task.failed() + task.postprocess() + else: + if task.needs_execute(): + # dispatch task + self.tp.put(task) + jobs = jobs + 1 + else: + task.executed() + task.postprocess() if not task and not jobs: break @@ -292,11 +404,20 @@ def start(self): # back and put the next batch of tasks on the queue. while 1: task, ok = self.tp.get() - jobs = jobs - 1 + if ok: task.executed() else: + if self.interrupted(): + try: + raise SCons.Errors.BuildError( + task.targets[0], errstr=interrupt_msg) + except: + task.exception_set() + + # Let the failed() callback function arrange + # for the build to stop if that's appropriate. task.failed() task.postprocess() @@ -304,5 +425,5 @@ def start(self): if self.tp.resultsQueue.empty(): break - def cleanup(self): self.tp.cleanup() + self.taskmaster.cleanup() diff --git a/scons/scons-local-0.97.0d20071212/SCons/Memoize.py b/scons/scons-local-1.2.0/SCons/Memoize.py similarity index 90% rename from scons/scons-local-0.97.0d20071212/SCons/Memoize.py rename to scons/scons-local-1.2.0/SCons/Memoize.py index ad3d99b5a8..f79dd6b930 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Memoize.py +++ b/scons/scons-local-1.2.0/SCons/Memoize.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Memoize.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Memoize.py 3842 2008/12/20 22:59:52 scons" __doc__ = """Memoizer @@ -217,33 +217,47 @@ def __init__(self): class M: def __init__(cls, name, bases, cls_dict): - cls.has_metaclass = 1 - -class A: - __metaclass__ = M + cls.use_metaclass = 1 + def fake_method(self): + pass + new.instancemethod(fake_method, None, cls) try: - has_metaclass = A.has_metaclass + class A: + __metaclass__ = M + + use_metaclass = A.use_metaclass except AttributeError: - has_metaclass = None + use_metaclass = None + reason = 'no metaclasses' +except TypeError: + use_metaclass = None + reason = 'new.instancemethod() bug' +else: + del A del M -del A -if not has_metaclass: +if not use_metaclass: def Dump(title): pass - class Memoized_Metaclass: - # Just a place-holder so pre-metaclass Python versions don't - # have to have special code for the Memoized classes. - pass + try: + class Memoized_Metaclass(type): + # Just a place-holder so pre-metaclass Python versions don't + # have to have special code for the Memoized classes. + pass + except TypeError: + class Memoized_Metaclass: + # A place-holder so pre-metaclass Python versions don't + # have to have special code for the Memoized classes. + pass def EnableMemoization(): import SCons.Warnings - msg = 'memoization is not supported in this version of Python (no metaclasses)' - raise SCons.Warnings.NoMetaclassSupportWarning, msg + msg = 'memoization is not supported in this version of Python (%s)' + raise SCons.Warnings.NoMetaclassSupportWarning, msg % reason else: diff --git a/scons/scons-local-0.97.0d20071212/SCons/Node/Alias.py b/scons/scons-local-1.2.0/SCons/Node/Alias.py similarity index 94% rename from scons/scons-local-0.97.0d20071212/SCons/Node/Alias.py rename to scons/scons-local-1.2.0/SCons/Node/Alias.py index ae2398f99f..4ce9fff7d1 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Node/Alias.py +++ b/scons/scons-local-1.2.0/SCons/Node/Alias.py @@ -8,7 +8,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Node/Alias.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Node/Alias.py 3842 2008/12/20 22:59:52 scons" import string import UserDict @@ -74,6 +74,9 @@ def __init__(self, name): SCons.Node.Node.__init__(self) self.name = name + def str_for_display(self): + return '"' + self.__str__() + '"' + def __str__(self): return self.name diff --git a/scons/scons-local-0.97.0d20071212/SCons/Node/FS.py b/scons/scons-local-1.2.0/SCons/Node/FS.py similarity index 87% rename from scons/scons-local-0.97.0d20071212/SCons/Node/FS.py rename to scons/scons-local-1.2.0/SCons/Node/FS.py index 43ff0da9aa..15368f029f 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Node/FS.py +++ b/scons/scons-local-1.2.0/SCons/Node/FS.py @@ -11,7 +11,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -33,9 +33,10 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Node/FS.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Node/FS.py 3842 2008/12/20 22:59:52 scons" import fnmatch +from itertools import izip import os import os.path import re @@ -58,6 +59,25 @@ from SCons.Debug import Trace +do_store_info = True + + +class EntryProxyAttributeError(AttributeError): + """ + An AttributeError subclass for recording and displaying the name + of the underlying Entry involved in an AttributeError exception. + """ + def __init__(self, entry_proxy, attribute): + AttributeError.__init__(self) + self.entry_proxy = entry_proxy + self.attribute = attribute + def __str__(self): + entry = self.entry_proxy.get() + fmt = "%s instance %s has no attribute %s" + return fmt % (entry.__class__.__name__, + repr(entry.name), + repr(self.attribute)) + # The max_drift value: by default, use a cached signature value for # any file that's been untouched for more than two days. default_max_drift = 2*24*60*60 @@ -73,10 +93,10 @@ # # A number of the above factors, however, can be set after we've already # been asked to return a string for a Node, because a Repository() or -# BuildDir() call or the like may not occur until later in SConscript +# VariantDir() call or the like may not occur until later in SConscript # files. So this variable controls whether we bother trying to save # string values for Nodes. The wrapper interface can set this whenever -# they're done mucking with Repository and BuildDir and the other stuff, +# they're done mucking with Repository and VariantDir and the other stuff, # to let this module know it can start returning saved string values # for Nodes. # @@ -222,8 +242,6 @@ def LinkFunc(target, source, env): if func == Link_Funcs[-1]: # exception of the last link method (copy) are fatal raise - else: - pass return 0 Link = SCons.Action.Action(LinkFunc, None) @@ -445,7 +463,7 @@ def __get_srcnode(self): def __get_srcdir(self): """Returns the directory containing the source node linked to this - node via BuildDir(), or the directory of this node if not linked.""" + node via VariantDir(), or the directory of this node if not linked.""" return EntryProxy(self.get().srcnode().dir) def __get_rsrcnode(self): @@ -453,7 +471,7 @@ def __get_rsrcnode(self): def __get_rsrcdir(self): """Returns the directory containing the source node linked to this - node via BuildDir(), or the directory of this node if not linked.""" + node via VariantDir(), or the directory of this node if not linked.""" return EntryProxy(self.get().srcnode().rfile().dir) def __get_dir(self): @@ -482,16 +500,11 @@ def __getattr__(self, name): except KeyError: try: attr = SCons.Util.Proxy.__getattr__(self, name) - except AttributeError: - entry = self.get() - classname = string.split(str(entry.__class__), '.')[-1] - if classname[-2:] == "'>": - # new-style classes report their name as: - # "" - # instead of the classic classes: - # "something" - classname = classname[:-2] - raise AttributeError, "%s instance '%s' has no attribute '%s'" % (classname, entry.name, name) + except AttributeError, e: + # Raise our own AttributeError subclass with an + # overridden __str__() method that identifies the + # name of the entry that caused the exception. + raise EntryProxyAttributeError(self, name) return attr else: return attr_function(self) @@ -543,6 +556,9 @@ def __init__(self, name, directory, fs): self.cwd = None # will hold the SConscript directory for target nodes self.duplicate = directory.duplicate + def str_for_display(self): + return '"' + self.__str__() + '"' + def must_be_same(self, klass): """ This node, which already existed, is being looked up as the @@ -586,7 +602,7 @@ def _get_str(self): if self.duplicate or self.is_derived(): return self.get_path() srcnode = self.srcnode() - if srcnode.stat() is None and not self.stat() is None: + if srcnode.stat() is None and self.stat() is not None: result = self.get_path() else: result = srcnode.get_path() @@ -601,7 +617,7 @@ def _get_str(self): # values that the underlying stat() method saved. try: del self._memo['stat'] except KeyError: pass - if not self is srcnode: + if self is not srcnode: try: del srcnode._memo['stat'] except KeyError: pass return result @@ -619,7 +635,7 @@ def stat(self): return result def exists(self): - return not self.stat() is None + return self.stat() is not None def rexists(self): return self.rfile().exists() @@ -636,11 +652,11 @@ def getsize(self): def isdir(self): st = self.stat() - return not st is None and stat.S_ISDIR(st[stat.ST_MODE]) + return st is not None and stat.S_ISDIR(st[stat.ST_MODE]) def isfile(self): st = self.stat() - return not st is None and stat.S_ISREG(st[stat.ST_MODE]) + return st is not None and stat.S_ISREG(st[stat.ST_MODE]) if hasattr(os, 'symlink'): def islink(self): @@ -880,10 +896,10 @@ def get_contents(self): def must_be_same(self, klass): """Called to make sure a Node is a Dir. Since we're an Entry, we can morph into one.""" - if not self.__class__ is klass: + if self.__class__ is not klass: self.__class__ = klass self._morph() - self.clear + self.clear() # The following methods can get called before the Taskmaster has # had a chance to call disambiguate() directly to see if this Entry @@ -904,7 +920,7 @@ def exists(self): def rel_path(self, other): d = self.disambiguate() - if d.__class__ == Entry: + if d.__class__ is Entry: raise "rel_path() could not disambiguate File/Dir" return d.rel_path(other) @@ -1059,7 +1075,7 @@ def chdir(self, dir, change_os_dir=0): """ curr=self._cwd try: - if not dir is None: + if dir is not None: self._cwd = dir if change_os_dir: os.chdir(dir.abspath) @@ -1165,7 +1181,7 @@ def _lookup(self, p, directory, fsclass, create=1): return root._lookup_abs(p, fsclass, create) def Entry(self, name, directory = None, create = 1): - """Lookup or create a generic Entry node with the specified name. + """Look up or create a generic Entry node with the specified name. If the name is a relative path (begins with ./, ../, or a file name), then it is looked up relative to the supplied directory node, or to the top level directory of the FS (supplied at @@ -1174,7 +1190,7 @@ def Entry(self, name, directory = None, create = 1): return self._lookup(name, directory, Entry, create) def File(self, name, directory = None, create = 1): - """Lookup or create a File node with the specified name. If + """Look up or create a File node with the specified name. If the name is a relative path (begins with ./, ../, or a file name), then it is looked up relative to the supplied directory node, or to the top level directory of the FS (supplied at construction @@ -1186,7 +1202,7 @@ def File(self, name, directory = None, create = 1): return self._lookup(name, directory, File, create) def Dir(self, name, directory = None, create = True): - """Lookup or create a Dir node with the specified name. If + """Look up or create a Dir node with the specified name. If the name is a relative path (begins with ./, ../, or a file name), then it is looked up relative to the supplied directory node, or to the top level directory of the FS (supplied at construction @@ -1197,21 +1213,21 @@ def Dir(self, name, directory = None, create = True): """ return self._lookup(name, directory, Dir, create) - def BuildDir(self, build_dir, src_dir, duplicate=1): - """Link the supplied build directory to the source directory + def VariantDir(self, variant_dir, src_dir, duplicate=1): + """Link the supplied variant directory to the source directory for purposes of building files.""" if not isinstance(src_dir, SCons.Node.Node): src_dir = self.Dir(src_dir) - if not isinstance(build_dir, SCons.Node.Node): - build_dir = self.Dir(build_dir) - if src_dir.is_under(build_dir): - raise SCons.Errors.UserError, "Source directory cannot be under build directory." - if build_dir.srcdir: - if build_dir.srcdir == src_dir: + if not isinstance(variant_dir, SCons.Node.Node): + variant_dir = self.Dir(variant_dir) + if src_dir.is_under(variant_dir): + raise SCons.Errors.UserError, "Source directory cannot be under variant directory." + if variant_dir.srcdir: + if variant_dir.srcdir == src_dir: return # We already did this. - raise SCons.Errors.UserError, "'%s' already has a source directory: '%s'."%(build_dir, build_dir.srcdir) - build_dir.link(src_dir, duplicate) + raise SCons.Errors.UserError, "'%s' already has a source directory: '%s'."%(variant_dir, variant_dir.srcdir) + variant_dir.link(src_dir, duplicate) def Repository(self, *dirs): """Specify Repository directories to search.""" @@ -1220,11 +1236,11 @@ def Repository(self, *dirs): d = self.Dir(d) self.Top.addRepository(d) - def build_dir_target_climb(self, orig, dir, tail): - """Create targets in corresponding build directories + def variant_dir_target_climb(self, orig, dir, tail): + """Create targets in corresponding variant directories Climb the directory tree, and look up path names - relative to any linked build directories we find. + relative to any linked variant directories we find. Even though this loops and walks up the tree, we don't memoize the return value because this is really only used to process @@ -1232,10 +1248,10 @@ def build_dir_target_climb(self, orig, dir, tail): """ targets = [] message = None - fmt = "building associated BuildDir targets: %s" + fmt = "building associated VariantDir targets: %s" start_dir = dir while dir: - for bd in dir.build_dirs: + for bd in dir.variant_dirs: if start_dir.is_under(bd): # If already in the build-dir location, don't reflect return [orig], fmt % str(orig) @@ -1314,7 +1330,7 @@ def _morph(self): self.cwd = self self.searched = 0 self._sconsign = None - self.build_dirs = [] + self.variant_dirs = [] self.root = self.dir.root # Don't just reset the executor, replace its action list, @@ -1342,7 +1358,7 @@ def __clearRepositoryCache(self, duplicate=None): del node._srcreps except AttributeError: pass - if duplicate != None: + if duplicate is not None: node.duplicate=duplicate def __resetDuplicate(self, node): @@ -1361,8 +1377,7 @@ def Dir(self, name, create=True): Looks up or creates a directory node named 'name' relative to this directory. """ - dir = self.fs.Dir(name, self, create) - return dir + return self.fs.Dir(name, self, create) def File(self, name): """ @@ -1385,16 +1400,16 @@ def _lookup_rel(self, name, klass, create=1): a path containing '..'), an absolute path name, a top-relative ('#foo') path name, or any kind of object. """ - name = self.labspath + '/' + name + name = self.entry_labspath(name) return self.root._lookup_abs(name, klass, create) def link(self, srcdir, duplicate): - """Set this directory as the build directory for the + """Set this directory as the variant directory for the supplied source directory.""" self.srcdir = srcdir self.duplicate = duplicate self.__clearRepositoryCache(duplicate) - srcdir.build_dirs.append(self) + srcdir.variant_dirs.append(self) def getRepositories(self): """Returns a list of repositories for this directory. @@ -1407,7 +1422,7 @@ def getRepositories(self): def get_all_rdirs(self): try: - return self._memo['get_all_rdirs'] + return list(self._memo['get_all_rdirs']) except KeyError: pass @@ -1423,7 +1438,7 @@ def get_all_rdirs(self): fname = dir.name + os.sep + fname dir = dir.up() - self._memo['get_all_rdirs'] = result + self._memo['get_all_rdirs'] = list(result) return result @@ -1445,15 +1460,15 @@ def rel_path(self, other): """Return a path to "other" relative to this directory. """ - # This complicated and expensive method, which constructs relative - # paths between arbitrary Node.FS objects, is no longer used - # by SCons itself. It was introduced to store dependency paths - # in .sconsign files relative to the target, but that ended up - # being significantly inefficient. + # This complicated and expensive method, which constructs relative + # paths between arbitrary Node.FS objects, is no longer used + # by SCons itself. It was introduced to store dependency paths + # in .sconsign files relative to the target, but that ended up + # being significantly inefficient. # - # We're continuing to support the method because some SConstruct - # files out there started using it when it was available, and - # we're all about backwards compatibility.. + # We're continuing to support the method because some SConstruct + # files out there started using it when it was available, and + # we're all about backwards compatibility.. try: memo_dict = self._memo['rel_path'] @@ -1467,11 +1482,9 @@ def rel_path(self, other): pass if self is other: - result = '.' elif not other in self.path_elements: - try: other_dir = other.get_dir() except AttributeError: @@ -1485,9 +1498,7 @@ def rel_path(self, other): result = other.name else: result = dir_rel_path + os.sep + other.name - else: - i = self.path_elements.index(other) + 1 path_elems = ['..'] * (len(self.path_elements) - i) \ @@ -1538,7 +1549,7 @@ def prepare(self): def build(self, **kw): """A null "builder" for directories.""" global MkdirBuilder - if not self.builder is MkdirBuilder: + if self.builder is not MkdirBuilder: apply(SCons.Node.Node.build, [self,], kw) # @@ -1554,10 +1565,9 @@ def _create(self): if parent.exists(): break listDirs.append(parent) - p = parent.up() - if p is None: - raise SCons.Errors.StopError, parent.path - parent = p + parent = parent.up() + else: + raise SCons.Errors.StopError, parent.path listDirs.reverse() for dirnode in listDirs: try: @@ -1577,21 +1587,36 @@ def _create(self): def multiple_side_effect_has_builder(self): global MkdirBuilder - return not self.builder is MkdirBuilder and self.has_builder() + return self.builder is not MkdirBuilder and self.has_builder() def alter_targets(self): - """Return any corresponding targets in a build directory. + """Return any corresponding targets in a variant directory. """ - return self.fs.build_dir_target_climb(self, self, []) + return self.fs.variant_dir_target_climb(self, self, []) def scanner_key(self): """A directory does not get scanned.""" return None def get_contents(self): - """Return aggregate contents of all our children.""" - contents = map(lambda n: n.get_contents(), self.children()) - return string.join(contents, '') + """Return content signatures and names of all our children + separated by new-lines. Ensure that the nodes are sorted.""" + contents = [] + name_cmp = lambda a, b: cmp(a.name, b.name) + sorted_children = self.children()[:] + sorted_children.sort(name_cmp) + for node in sorted_children: + contents.append('%s %s\n' % (node.get_csig(), node.name)) + return string.join(contents, '') + + def get_csig(self): + """Compute the content signature for Directory nodes. In + general, this is not needed and the content signature is not + stored in the DirNodeInfo. However, if get_contents on a Dir + node is called which has a child directory, the child + directory should return the hash of its contents.""" + contents = self.get_contents() + return SCons.Util.MD5signature(contents) def do_duplicate(self, src): pass @@ -1601,7 +1626,7 @@ def do_duplicate(self, src): def is_up_to_date(self): """If any child is not up-to-date, then this directory isn't, either.""" - if not self.builder is MkdirBuilder and not self.exists(): + if self.builder is not MkdirBuilder and not self.exists(): return 0 up_to_date = SCons.Node.up_to_date for kid in self.children(): @@ -1696,7 +1721,7 @@ def srcdir_duplicate(self, name): for dir in self.srcdir_list(): if self.is_under(dir): # We shouldn't source from something in the build path; - # build_dir is probably under src_dir, in which case + # variant_dir is probably under src_dir, in which case # we are reflecting. break if dir.entry_exists_on_disk(name): @@ -1761,7 +1786,10 @@ def dir_on_disk(self, name): if self.entry_exists_on_disk(name): try: return self.Dir(name) except TypeError: pass - return None + node = self.srcdir_duplicate(name) + if isinstance(node, File): + return None + return node def file_on_disk(self, name): if self.entry_exists_on_disk(name) or \ @@ -1771,7 +1799,7 @@ def file_on_disk(self, name): except TypeError: pass node = self.srcdir_duplicate(name) if isinstance(node, Dir): - node = None + return None return node def walk(self, func, arg): @@ -1823,8 +1851,8 @@ def glob(self, pathname, ondisk=True, source=False, strings=False): The "source" argument, when true, specifies that corresponding source Nodes must be returned if you're globbing in a build - directory (initialized with BuildDir()). The default behavior - is to return Nodes local to the BuildDir(). + directory (initialized with VariantDir()). The default behavior + is to return Nodes local to the VariantDir(). The "strings" argument, when true, returns the matches as strings, not Nodes. The strings are path names relative to this directory. @@ -1846,6 +1874,7 @@ def glob(self, pathname, ondisk=True, source=False, strings=False): if strings: r = map(lambda x, d=str(dir): os.path.join(d, x), r) result.extend(r) + result.sort(lambda a, b: cmp(str(a), str(b))) return result def _glob1(self, pattern, ondisk=True, source=False, strings=False): @@ -1863,6 +1892,7 @@ def _glob1(self, pattern, ondisk=True, source=False, strings=False): for srcdir in self.srcdir_list(): search_dir_list.extend(srcdir.get_all_rdirs()) + selfEntry = self.Entry names = [] for dir in search_dir_list: # We use the .name attribute from the Node because the keys of @@ -1872,34 +1902,39 @@ def _glob1(self, pattern, ondisk=True, source=False, strings=False): entry_names = filter(lambda n: n not in ('.', '..'), dir.entries.keys()) node_names = map(lambda n, e=dir.entries: e[n].name, entry_names) names.extend(node_names) + if not strings: + # Make sure the working directory (self) actually has + # entries for all Nodes in repositories or variant dirs. + map(selfEntry, node_names) if ondisk: try: disk_names = os.listdir(dir.abspath) except os.error: - pass - else: - names.extend(disk_names) - if not strings: - # We're going to return corresponding Nodes in - # the local directory, so we need to make sure - # those Nodes exist. We only want to create - # Nodes for the entries that will match the - # specified pattern, though, which means we - # need to filter the list here, even though - # the overall list will also be filtered later, - # after we exit this loop. - if pattern[0] != '.': - #disk_names = [ d for d in disk_names if d[0] != '.' ] - disk_names = filter(lambda x: x[0] != '.', disk_names) - disk_names = fnmatch.filter(disk_names, pattern) - rep_nodes = map(dir.Entry, disk_names) - #rep_nodes = [ n.disambiguate() for n in rep_nodes ] - rep_nodes = map(lambda n: n.disambiguate(), rep_nodes) - for node, name in zip(rep_nodes, disk_names): - n = self.Entry(name) - if n.__class__ != node.__class__: - n.__class__ = node.__class__ - n._morph() + continue + names.extend(disk_names) + if not strings: + # We're going to return corresponding Nodes in + # the local directory, so we need to make sure + # those Nodes exist. We only want to create + # Nodes for the entries that will match the + # specified pattern, though, which means we + # need to filter the list here, even though + # the overall list will also be filtered later, + # after we exit this loop. + if pattern[0] != '.': + #disk_names = [ d for d in disk_names if d[0] != '.' ] + disk_names = filter(lambda x: x[0] != '.', disk_names) + disk_names = fnmatch.filter(disk_names, pattern) + dirEntry = dir.Entry + for name in disk_names: + # Add './' before disk filename so that '#' at + # beginning of filename isn't interpreted. + name = './' + name + node = dirEntry(name).disambiguate() + n = selfEntry(name) + if n.__class__ != node.__class__: + n.__class__ = node.__class__ + n._morph() names = set(names) if pattern[0] != '.': @@ -1940,7 +1975,7 @@ def __init__(self, name, fs): # except for the "lookup abspath," which does not have the # drive letter. self.abspath = name + os.sep - self.labspath = '/' + self.labspath = '' self.path = name + os.sep self.tpath = name + os.sep self._morph() @@ -1951,6 +1986,7 @@ def __init__(self, name, fs): # os.path.normpath() seems to preserve double slashes at the # beginning of a path (presumably for UNC path names), but # collapses triple slashes to a single slash. + self._lookupDict[''] = self self._lookupDict['/'] = self self._lookupDict['//'] = self self._lookupDict[os.sep] = self @@ -1988,13 +2024,14 @@ def _lookup_abs(self, p, klass, create=1): dir_name, file_name = os.path.split(p) dir_node = self._lookup_abs(dir_name, Dir) result = klass(file_name, dir_node, self.fs) - self._lookupDict[k] = result - dir_node.entries[_my_normcase(file_name)] = result - dir_node.implicit = None # Double-check on disk (as configured) that the Node we # created matches whatever is out there in the real world. result.diskcheck_match() + + self._lookupDict[k] = result + dir_node.entries[_my_normcase(file_name)] = result + dir_node.implicit = None else: # There is already a Node for this path name. Allow it to # complain if we were looking for an inappropriate type. @@ -2008,7 +2045,7 @@ def entry_abspath(self, name): return self.abspath + name def entry_labspath(self, name): - return self.labspath + name + return '/' + name def entry_path(self, name): return self.path + name @@ -2106,19 +2143,18 @@ def prepare_dependencies(self): strings = getattr(self, nattr) nodeinfos = getattr(self, sattr) except AttributeError: - pass - else: - nodes = [] - for s, ni in zip(strings, nodeinfos): - if not isinstance(s, SCons.Node.Node): - s = ni.str_to_node(s) - nodes.append(s) - setattr(self, nattr, nodes) + continue + nodes = [] + for s, ni in izip(strings, nodeinfos): + if not isinstance(s, SCons.Node.Node): + s = ni.str_to_node(s) + nodes.append(s) + setattr(self, nattr, nodes) def format(self, names=0): result = [] bkids = self.bsources + self.bdepends + self.bimplicit bkidsigs = self.bsourcesigs + self.bdependsigs + self.bimplicitsigs - for bkid, bkidsig in zip(bkids, bkidsigs): + for bkid, bkidsig in izip(bkids, bkidsigs): result.append(str(bkid) + ': ' + string.join(bkidsig.format(names=names), ' ')) result.append('%s [%s]' % (self.bactsig, self.bact)) @@ -2133,6 +2169,8 @@ class File(Base): NodeInfo = FileNodeInfo BuildInfo = FileBuildInfo + md5_chunksize = 64 + def diskcheck_match(self): diskcheck_match(self, self.isdir, "Directory %s found where file expected.") @@ -2144,23 +2182,25 @@ def __init__(self, name, directory, fs): def Entry(self, name): """Create an entry node named 'name' relative to - the SConscript directory of this file.""" - return self.cwd.Entry(name) + the directory of this file.""" + return self.dir.Entry(name) def Dir(self, name, create=True): """Create a directory node named 'name' relative to - the SConscript directory of this file.""" - return self.cwd.Dir(name, create) + the directory of this file.""" + return self.dir.Dir(name, create=create) def Dirs(self, pathlist): """Create a list of directories relative to the SConscript directory of this file.""" + # TODO(1.5) + # return [self.Dir(p) for p in pathlist] return map(lambda p, s=self: s.Dir(p), pathlist) def File(self, name): """Create a file node named 'name' relative to - the SConscript directory of this file.""" - return self.cwd.File(name) + the directory of this file.""" + return self.dir.File(name) #def generate_build_dict(self): # """Return an appropriate dictionary of values for building @@ -2203,6 +2243,23 @@ def get_contents(self): raise return r + def get_content_hash(self): + """ + Compute and return the MD5 hash for this file. + """ + if not self.rexists(): + return SCons.Util.MD5signature('') + fname = self.rfile().abspath + try: + cs = SCons.Util.MD5filesignature(fname, + chunksize=SCons.Node.FS.File.md5_chunksize*1024) + except EnvironmentError, e: + if not e.filename: + e.filename = fname + raise + return cs + + memoizer_counters.append(SCons.Memoize.CountValue('get_size')) def get_size(self): @@ -2242,7 +2299,8 @@ def store_info(self): # This accomodates "chained builds" where a file that's a target # in one build (SConstruct file) is a source in a different build. # See test/chained-build.py for the use case. - self.dir.sconsign().store_info(self.name, self) + if do_store_info: + self.dir.sconsign().store_info(self.name, self) convert_copy_attrs = [ 'bsources', @@ -2336,26 +2394,24 @@ def convert_old_entry(self, old_entry): try: value = getattr(old_entry, attr) except AttributeError: - pass - else: - setattr(binfo, attr, value) - delattr(old_entry, attr) + continue + setattr(binfo, attr, value) + delattr(old_entry, attr) for attr in self.convert_sig_attrs: try: sig_list = getattr(old_entry, attr) except AttributeError: - pass - else: - value = [] - for sig in sig_list: - ninfo = self.new_ninfo() - if len(sig) == 32: - ninfo.csig = sig - else: - ninfo.timestamp = sig - value.append(ninfo) - setattr(binfo, attr, value) - delattr(old_entry, attr) + continue + value = [] + for sig in sig_list: + ninfo = self.new_ninfo() + if len(sig) == 32: + ninfo.csig = sig + else: + ninfo.timestamp = sig + value.append(ninfo) + setattr(binfo, attr, value) + delattr(old_entry, attr) return new_entry memoizer_counters.append(SCons.Memoize.CountValue('get_stored_info')) @@ -2368,7 +2424,7 @@ def get_stored_info(self): try: sconsign_entry = self.dir.sconsign().get_entry(self.name) - except (KeyError, OSError): + except (KeyError, EnvironmentError): import SCons.SConsign sconsign_entry = SCons.SConsign.SConsignEntry() sconsign_entry.binfo = self.new_binfo() @@ -2419,6 +2475,7 @@ def get_found_includes(self, env, scanner, path): pass if scanner: + # result = [n.disambiguate() for n in scanner(self, env, path)] result = scanner(self, env, path) result = map(lambda N: N.disambiguate(), result) else: @@ -2469,38 +2526,20 @@ def visited(self): self.get_build_env().get_CacheDir().push_if_forced(self) ninfo = self.get_ninfo() - old = self.get_stored_info() - - csig = None - mtime = self.get_timestamp() - size = self.get_size() - - max_drift = self.fs.max_drift - if max_drift > 0: - if (time.time() - mtime) > max_drift: - try: - n = old.ninfo - if n.timestamp and n.csig and n.timestamp == mtime: - csig = n.csig - except AttributeError: - pass - elif max_drift == 0: - try: - csig = old.ninfo.csig - except AttributeError: - pass + csig = self.get_max_drift_csig() if csig: ninfo.csig = csig - ninfo.timestamp = mtime - ninfo.size = size + ninfo.timestamp = self.get_timestamp() + ninfo.size = self.get_size() if not self.has_builder(): # This is a source file, but it might have been a target file # in another build that included more of the DAG. Copy # any build information that's stored in the .sconsign file # into our binfo object so it doesn't get lost. + old = self.get_stored_info() self.get_binfo().__dict__.update(old.binfo.__dict__) self.store_info() @@ -2540,14 +2579,14 @@ def has_src_builder(self): scb = self.sbuilder except AttributeError: scb = self.sbuilder = self.find_src_builder() - return not scb is None + return scb is not None def alter_targets(self): - """Return any corresponding targets in a build directory. + """Return any corresponding targets in a variant directory. """ if self.is_derived(): return [], None - return self.fs.build_dir_target_climb(self, self.dir, [self.name]) + return self.fs.variant_dir_target_climb(self, self.dir, [self.name]) def _rmv_existing(self): self.clear_memoized_values() @@ -2613,8 +2652,8 @@ def exists(self): # Duplicate from source path if we are set up to do this. if self.duplicate and not self.is_derived() and not self.linked: src = self.srcnode() - if not src is self: - # At this point, src is meant to be copied in a build directory. + if src is not self: + # At this point, src is meant to be copied in a variant directory. src = src.rfile() if src.abspath != self.abspath: if src.exists(): @@ -2623,7 +2662,7 @@ def exists(self): # not actually occur if the -n option is being used. else: # The source file does not exist. Make sure no old - # copy remains in the build directory. + # copy remains in the variant directory. if Base.exists(self) or self.islink(): self.fs.unlink(self.path) # Return None explicitly because the Base.exists() call @@ -2638,6 +2677,32 @@ def exists(self): # SIGNATURE SUBSYSTEM # + def get_max_drift_csig(self): + """ + Returns the content signature currently stored for this node + if it's been unmodified longer than the max_drift value, or the + max_drift value is 0. Returns None otherwise. + """ + old = self.get_stored_info() + mtime = self.get_timestamp() + + max_drift = self.fs.max_drift + if max_drift > 0: + if (time.time() - mtime) > max_drift: + try: + n = old.ninfo + if n.timestamp and n.csig and n.timestamp == mtime: + return n.csig + except AttributeError: + pass + elif max_drift == 0: + try: + return old.ninfo.csig + except AttributeError: + pass + + return None + def get_csig(self): """ Generate a node's content signature, the digested signature @@ -2653,16 +2718,23 @@ def get_csig(self): except AttributeError: pass - try: - contents = self.get_contents() - except IOError: - # This can happen if there's actually a directory on-disk, - # which can be the case if they've disabled disk checks, - # or if an action with a File target actually happens to - # create a same-named directory by mistake. - csig = '' - else: - csig = SCons.Util.MD5signature(contents) + csig = self.get_max_drift_csig() + if csig is None: + + try: + if self.get_size() < SCons.Node.FS.File.md5_chunksize: + contents = self.get_contents() + else: + csig = self.get_content_hash() + except IOError: + # This can happen if there's actually a directory on-disk, + # which can be the case if they've disabled disk checks, + # or if an action with a File target actually happens to + # create a same-named directory by mistake. + csig = '' + else: + if not csig: + csig = SCons.Util.MD5signature(contents) ninfo.csig = csig @@ -2684,7 +2756,7 @@ def changed_content(self, target, prev_ni): return 1 def changed_state(self, target, prev_ni): - return (self.state != SCons.Node.up_to_date) + return self.state != SCons.Node.up_to_date def changed_timestamp_then_content(self, target, prev_ni): if not self.changed_timestamp_match(target, prev_ni): @@ -2790,8 +2862,8 @@ def get_cachedir_csig(self): cachedir, cachefile = self.get_build_env().get_CacheDir().cachepath(self) if not self.exists() and cachefile and os.path.exists(cachefile): - contents = open(cachefile, 'rb').read() - self.cachedir_csig = SCons.Util.MD5signature(contents) + self.cachedir_csig = SCons.Util.MD5filesignature(cachefile, \ + SCons.Node.FS.File.md5_chunksize * 1024) else: self.cachedir_csig = self.get_csig() return self.cachedir_csig @@ -2805,13 +2877,15 @@ def get_cachedir_bsig(self): # Add the path to the cache signature, because multiple # targets built by the same action will all have the same # build signature, and we have to differentiate them somehow. - children = self.children() - sigs = map(lambda n: n.get_cachedir_csig(), children) + children = self.children() executor = self.get_executor() + # sigs = [n.get_cachedir_csig() for n in children] + sigs = map(lambda n: n.get_cachedir_csig(), children) sigs.append(SCons.Util.MD5signature(executor.get_contents())) sigs.append(self.path) - self.cachesig = SCons.Util.MD5collect(sigs) - return self.cachesig + result = self.cachesig = SCons.Util.MD5collect(sigs) + return result + default_fs = None @@ -2842,14 +2916,14 @@ def filedir_lookup(self, p, fd=None): It would be more compact to just use this as a nested function with a default keyword argument (see the commented-out version below), but that doesn't work unless you have nested scopes, - so we define it here just this works work under Python 1.5.2. + so we define it here just so this work under Python 1.5.2. """ if fd is None: fd = self.default_filedir dir, name = os.path.split(fd) drive, d = os.path.splitdrive(dir) if d in ('/', os.sep): - return p + return p.fs.get_root(drive).dir_on_disk(name) if dir: p = self.filedir_lookup(p, dir) if not p: @@ -2859,9 +2933,10 @@ def filedir_lookup(self, p, fd=None): node = p.entries[norm_name] except KeyError: return p.dir_on_disk(name) - # Once we move to Python 2.2 we can do: - #if isinstance(node, (Dir, Entry)): - if isinstance(node, Dir) or isinstance(node, Entry): + if isinstance(node, Dir): + return node + if isinstance(node, Entry): + node.must_be_same(Dir) return node return None @@ -2899,14 +2974,11 @@ def find_file(self, filename, paths, verbose=None): except KeyError: pass - if verbose: + if verbose and not callable(verbose): if not SCons.Util.is_String(verbose): verbose = "find_file" - if not callable(verbose): - verbose = ' %s: ' % verbose - verbose = lambda s, v=verbose: sys.stdout.write(v + s) - else: - verbose = lambda x: x + verbose = ' %s: ' % verbose + verbose = lambda s, v=verbose: sys.stdout.write(v + s) filedir, filename = os.path.split(filename) if filedir: @@ -2930,8 +3002,11 @@ def find_file(self, filename, paths, verbose=None): # node = p.entries[norm_name] # except KeyError: # return p.dir_on_disk(name) - # # Once we move to Python 2.2 we can do: - # #if isinstance(node, (Dir, Entry)): + # if isinstance(node, Dir): + # return node + # if isinstance(node, Entry): + # node.must_be_same(Dir) + # return node # if isinstance(node, Dir) or isinstance(node, Entry): # return node # return None @@ -2942,10 +3017,12 @@ def find_file(self, filename, paths, verbose=None): result = None for dir in paths: - verbose("looking for '%s' in '%s' ...\n" % (filename, dir)) + if verbose: + verbose("looking for '%s' in '%s' ...\n" % (filename, dir)) node, d = dir.srcdir_find_file(filename) if node: - verbose("... FOUND '%s' in '%s'\n" % (filename, d)) + if verbose: + verbose("... FOUND '%s' in '%s'\n" % (filename, d)) result = node break @@ -2954,3 +3031,45 @@ def find_file(self, filename, paths, verbose=None): return result find_file = FileFinder().find_file + + +def invalidate_node_memos(targets): + """ + Invalidate the memoized values of all Nodes (files or directories) + that are associated with the given entries. Has been added to + clear the cache of nodes affected by a direct execution of an + action (e.g. Delete/Copy/Chmod). Existing Node caches become + inconsistent if the action is run through Execute(). The argument + `targets` can be a single Node object or filename, or a sequence + of Nodes/filenames. + """ + from traceback import extract_stack + + # First check if the cache really needs to be flushed. Only + # actions run in the SConscript with Execute() seem to be + # affected. XXX The way to check if Execute() is in the stacktrace + # is a very dirty hack and should be replaced by a more sensible + # solution. + for f in extract_stack(): + if f[2] == 'Execute' and f[0][-14:] == 'Environment.py': + break + else: + # Dont have to invalidate, so return + return + + if not SCons.Util.is_List(targets): + targets = [targets] + + for entry in targets: + # If the target is a Node object, clear the cache. If it is a + # filename, look up potentially existing Node object first. + try: + entry.clear_memoized_values() + except AttributeError: + # Not a Node object, try to look up Node by filename. XXX + # This creates Node objects even for those filenames which + # do not correspond to an existing Node object. + node = get_default_fs().Entry(entry) + if node: + node.clear_memoized_values() + diff --git a/scons/scons-local-0.97.0d20071212/SCons/Node/Python.py b/scons/scons-local-1.2.0/SCons/Node/Python.py similarity index 94% rename from scons/scons-local-0.97.0d20071212/SCons/Node/Python.py rename to scons/scons-local-1.2.0/SCons/Node/Python.py index 8b5774a914..21fbb157c3 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Node/Python.py +++ b/scons/scons-local-1.2.0/SCons/Node/Python.py @@ -5,7 +5,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,7 +27,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Node/Python.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Node/Python.py 3842 2008/12/20 22:59:52 scons" import SCons.Node @@ -56,9 +56,12 @@ def __init__(self, value, built_value=None): if not built_value is None: self.built_value = built_value - def __str__(self): + def str_for_display(self): return repr(self.value) + def __str__(self): + return str(self.value) + def make_ready(self): self.get_csig() diff --git a/scons/scons-local-0.97.0d20071212/SCons/Node/__init__.py b/scons/scons-local-1.2.0/SCons/Node/__init__.py similarity index 88% rename from scons/scons-local-0.97.0d20071212/SCons/Node/__init__.py rename to scons/scons-local-1.2.0/SCons/Node/__init__.py index 769cbe333b..8ea6719e01 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Node/__init__.py +++ b/scons/scons-local-1.2.0/SCons/Node/__init__.py @@ -20,7 +20,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -42,11 +42,10 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Node/__init__.py 2523 2007/12/12 09:37:41 knight" - -import SCons.compat +__revision__ = "src/engine/SCons/Node/__init__.py 3842 2008/12/20 22:59:52 scons" import copy +from itertools import chain, izip import string import UserList @@ -75,7 +74,7 @@ def classname(obj): failed = 5 StateString = { - 0 : "0", + 0 : "no_state", 1 : "pending", 2 : "executing", 3 : "up_to_date", @@ -202,15 +201,16 @@ def __init__(self): # a class. (Of course, we could always still do that in the # future if we had a good reason to...). self.sources = [] # source files used to build node - self.sources_dict = {} + self.sources_set = set() + self._specific_sources = False self.depends = [] # explicit dependencies (from Depends) - self.depends_dict = {} + self.depends_set = set() self.ignore = [] # dependencies to ignore - self.ignore_dict = {} + self.ignore_set = set() self.prerequisites = SCons.Util.UniqueList() self.implicit = None # implicit (scanned) dependencies (None means not scanned yet) - self.waiting_parents = {} - self.waiting_s_e = {} + self.waiting_parents = set() + self.waiting_s_e = set() self.ref_count = 0 self.wkids = None # Kids yet to walk, when it's an array @@ -220,12 +220,11 @@ def __init__(self): self.noclean = 0 self.nocache = 0 self.always_build = None - self.found_includes = {} self.includes = None self.attributes = self.Attrs() # Generic place to stick information about the Node. self.side_effect = 0 # true iff this node is a side effect self.side_effects = [] # the side effects of building this target - self.linked = 0 # is this node linked to the build directory? + self.linked = 0 # is this node linked to the variant directory? self.clear_memoized_values() @@ -330,24 +329,29 @@ def prepare(self): is out-of-date and must be rebuilt, but before actually calling the method to build the Node. - This default implemenation checks that all children either exist - or are derived, and initializes the BuildInfo structure that - will hold the information about how this node is, uh, built. + This default implementation checks that explicit or implicit + dependencies either exist or are derived, and initializes the + BuildInfo structure that will hold the information about how + this node is, uh, built. + + (The existence of source files is checked separately by the + Executor, which aggregates checks for all of the targets built + by a specific action.) Overriding this method allows for for a Node subclass to remove the underlying file from the file system. Note that subclass methods should call this base class method to get the child check and the BuildInfo structure. """ - l = self.depends + for d in self.depends: + if d.missing(): + msg = "Explicit dependency `%s' not found, needed by target `%s'." + raise SCons.Errors.StopError, msg % (d, self) if not self.implicit is None: - l = l + self.implicit - missing_sources = self.get_executor().get_missing_sources() \ - + filter(lambda c: c.missing(), l) - if missing_sources: - desc = "Source `%s' not found, needed by target `%s'." % (missing_sources[0], self) - raise SCons.Errors.StopError, desc - + for i in self.implicit: + if i.missing(): + msg = "Implicit dependency `%s' not found, needed by target `%s'." + raise SCons.Errors.StopError, msg % (i, self) self.binfo = self.get_binfo() def build(self, **kw): @@ -373,9 +377,8 @@ def built(self): # Clear the implicit dependency caches of any Nodes # waiting for this Node to be built. - for parent in self.waiting_parents.keys(): + for parent in self.waiting_parents: parent.implicit = None - parent.del_binfo() self.clear() @@ -399,7 +402,7 @@ def visited(self): # def add_to_waiting_s_e(self, node): - self.waiting_s_e[node] = 1 + self.waiting_s_e.add(node) def add_to_waiting_parents(self, node): """ @@ -410,37 +413,26 @@ def add_to_waiting_parents(self, node): True and False instead...) """ wp = self.waiting_parents - if wp.has_key(node): - result = 0 - else: - result = 1 - wp[node] = 1 - return result - - def call_for_all_waiting_parents(self, func): - func(self) - for parent in self.waiting_parents.keys(): - parent.call_for_all_waiting_parents(func) + if node in wp: + return 0 + wp.add(node) + return 1 def postprocess(self): """Clean up anything we don't need to hang onto after we've been built.""" self.executor_cleanup() - self.waiting_parents = {} + self.waiting_parents = set() def clear(self): """Completely clear a Node of all its cached state (so that it can be re-evaluated by interfaces that do continuous integration builds). """ - # Note in case it's important in the future: We also used to clear - # the build information (the lists of dependencies) here like this: - # - # self.del_binfo() - # - # But we now rely on the fact that we're going to look at that - # once before the build, and then store the results in the - # .sconsign file after the build. + # The del_binfo() call here isn't necessary for normal execution, + # but is for interactive mode, where we might rebuild the same + # target and need to start from scratch. + self.del_binfo() self.clear_memoized_values() self.ninfo = self.new_ninfo() self.executor_cleanup() @@ -449,7 +441,6 @@ def clear(self): except AttributeError: pass self.includes = None - self.found_includes = {} def clear_memoized_values(self): self._memo = {} @@ -510,7 +501,7 @@ def is_derived(self): Returns true iff this node is derived (i.e. built). This should return true only for nodes whose path should be in - the build directory when duplicate=0 and should contribute their build + the variant directory when duplicate=0 and should contribute their build signatures when they are used as source files to other derived files. For example: source with source builders are not derived in this sense, and hence should not return true. @@ -597,9 +588,9 @@ def get_source_scanner(self, node): def add_to_implicit(self, deps): if not hasattr(self, 'implicit') or self.implicit is None: self.implicit = [] - self.implicit_dict = {} + self.implicit_set = set() self._children_reset() - self._add_child(self.implicit, self.implicit_dict, deps) + self._add_child(self.implicit, self.implicit_set, deps) def scan(self): """Scan this node's dependents for implicit dependencies.""" @@ -609,7 +600,7 @@ def scan(self): if not self.implicit is None: return self.implicit = [] - self.implicit_dict = {} + self.implicit_set = set() self._children_reset() if not self.has_builder(): return @@ -638,9 +629,7 @@ def scan(self): # one of this node's sources has changed, # so we must recalculate the implicit deps: self.implicit = [] - self.implicit_dict = {} - self._children_reset() - self.del_binfo() + self.implicit_set = set() # Have the executor scan the sources. executor.scan_sources(self.builder.source_scanner) @@ -713,33 +702,44 @@ def get_binfo(self): self.binfo = binfo executor = self.get_executor() - - sources = executor.get_unignored_sources(self.ignore) - - depends = self.depends - implicit = self.implicit or [] - - if self.ignore: - depends = filter(self.do_not_ignore, depends) - implicit = filter(self.do_not_ignore, implicit) - - def get_ninfo(node): - return node.get_ninfo() - - sourcesigs = map(get_ninfo, sources) - dependsigs = map(get_ninfo, depends) - implicitsigs = map(get_ninfo, implicit) + ignore_set = self.ignore_set if self.has_builder(): binfo.bact = str(executor) binfo.bactsig = SCons.Util.MD5signature(executor.get_contents()) - binfo.bsources = sources - binfo.bdepends = depends - binfo.bimplicit = implicit + if self._specific_sources: + sources = [] + for s in self.sources: + if s not in ignore_set: + sources.append(s) + else: + sources = executor.get_unignored_sources(self.ignore) + seen = set() + bsources = [] + bsourcesigs = [] + for s in sources: + if not s in seen: + seen.add(s) + bsources.append(s) + bsourcesigs.append(s.get_ninfo()) + binfo.bsources = bsources + binfo.bsourcesigs = bsourcesigs - binfo.bsourcesigs = sourcesigs + depends = self.depends + dependsigs = [] + for d in depends: + if d not in ignore_set: + dependsigs.append(d.get_ninfo()) + binfo.bdepends = depends binfo.bdependsigs = dependsigs + + implicit = self.implicit or [] + implicitsigs = [] + for i in implicit: + if i not in ignore_set: + implicitsigs.append(i.get_ninfo()) + binfo.bimplicit = implicit binfo.bimplicitsigs = implicitsigs return binfo @@ -823,7 +823,7 @@ def remove(self): def add_dependency(self, depend): """Adds dependencies.""" try: - self._add_child(self.depends, self.depends_dict, depend) + self._add_child(self.depends, self.depends_set, depend) except TypeError, e: e = e.args[0] if SCons.Util.is_List(e): @@ -840,7 +840,7 @@ def add_prerequisite(self, prerequisite): def add_ignore(self, depend): """Adds dependencies to ignore.""" try: - self._add_child(self.ignore, self.ignore_dict, depend) + self._add_child(self.ignore, self.ignore_set, depend) except TypeError, e: e = e.args[0] if SCons.Util.is_List(e): @@ -851,8 +851,10 @@ def add_ignore(self, depend): def add_source(self, source): """Adds sources.""" + if self._specific_sources: + return try: - self._add_child(self.sources, self.sources_dict, source) + self._add_child(self.sources, self.sources_set, source) except TypeError, e: e = e.args[0] if SCons.Util.is_List(e): @@ -861,9 +863,9 @@ def add_source(self, source): s = str(e) raise SCons.Errors.UserError("attempted to add a non-Node as source of %s:\n\t%s is a %s, not a Node" % (str(self), s, type(e))) - def _add_child(self, collection, dict, child): - """Adds 'child' to 'collection', first checking 'dict' to see - if it's already present.""" + def _add_child(self, collection, set, child): + """Adds 'child' to 'collection', first checking 'set' to see if it's + already present.""" #if type(child) is not type([]): # child = [child] #for c in child: @@ -871,13 +873,17 @@ def _add_child(self, collection, dict, child): # raise TypeError, c added = None for c in child: - if not dict.has_key(c): + if c not in set: + set.add(c) collection.append(c) - dict[c] = 1 added = 1 if added: self._children_reset() + def set_specific_source(self, source): + self.add_source(source) + self._specific_sources = True + def add_wkid(self, wkid): """Add a node to the list of kids waiting to be evaluated""" if self.wkids != None: @@ -889,10 +895,14 @@ def _children_reset(self): # build info that it's cached so we can re-calculate it. self.executor_cleanup() - def do_not_ignore(self, node): - return node not in self.ignore + memoizer_counters.append(SCons.Memoize.CountValue('_children_get')) + + def _children_get(self): + try: + return self._memo['children_get'] + except KeyError: + pass - def _all_children_get(self): # The return list may contain duplicate Nodes, especially in # source trees where there are a lot of repeated #includes # of a tangle of .h files. Profiling shows, however, that @@ -910,21 +920,22 @@ def _all_children_get(self): # using dictionary keys, lose the order, and the only ordered # dictionary patterns I found all ended up using "not in" # internally anyway...) - if self.implicit is None: - return self.sources + self.depends - else: - return self.sources + self.depends + self.implicit + if self.ignore_set: + if self.implicit is None: + iter = chain(self.sources,self.depends) + else: + iter = chain(self.sources, self.depends, self.implicit) - memoizer_counters.append(SCons.Memoize.CountValue('_children_get')) + children = [] + for i in iter: + if i not in self.ignore_set: + children.append(i) + else: + if self.implicit is None: + children = self.sources + self.depends + else: + children = self.sources + self.depends + self.implicit - def _children_get(self): - try: - return self._memo['children_get'] - except KeyError: - pass - children = self._all_children_get() - if self.ignore: - children = filter(self.do_not_ignore, children) self._memo['children_get'] = children return children @@ -932,7 +943,28 @@ def all_children(self, scan=1): """Return a list of all the node's direct children.""" if scan: self.scan() - return self._all_children_get() + + # The return list may contain duplicate Nodes, especially in + # source trees where there are a lot of repeated #includes + # of a tangle of .h files. Profiling shows, however, that + # eliminating the duplicates with a brute-force approach that + # preserves the order (that is, something like: + # + # u = [] + # for n in list: + # if n not in u: + # u.append(n)" + # + # takes more cycles than just letting the underlying methods + # hand back cached values if a Node's information is requested + # multiple times. (Other methods of removing duplicates, like + # using dictionary keys, lose the order, and the only ordered + # dictionary patterns I found all ended up using "not in" + # internally anyway...) + if self.implicit is None: + return self.sources + self.depends + else: + return self.sources + self.depends + self.implicit def children(self, scan=1): """Return a list of the node's direct children, minus those @@ -1013,9 +1045,10 @@ def changed(self, node=None): # entries to equal the new dependency list, for the benefit # of the loop below that updates node information. then.extend([None] * diff) + if t: Trace(': old %s new %s' % (len(then), len(children))) result = True - for child, prev_ni in zip(children, then): + for child, prev_ni in izip(children, then): if child.changed_since_last_build(self, prev_ni): if t: Trace(': %s changed' % child) result = True @@ -1071,7 +1104,10 @@ def render_include_tree(self): env = self.get_build_env() for s in self.sources: scanner = self.get_source_scanner(s) - path = self.get_build_scanner_path(scanner) + if scanner: + path = self.get_build_scanner_path(scanner) + else: + path = None def f(node, env=env, scanner=scanner, path=path): return node.get_found_includes(env, scanner, path) return SCons.Util.render_tree(s, f, 1) @@ -1158,8 +1194,8 @@ def explain(self): new_bkids = new.bsources + new.bdepends + new.bimplicit new_bkidsigs = new.bsourcesigs + new.bdependsigs + new.bimplicitsigs - osig = dict(zip(old_bkids, old_bkidsigs)) - nsig = dict(zip(new_bkids, new_bkidsigs)) + osig = dict(izip(old_bkids, old_bkidsigs)) + nsig = dict(izip(new_bkids, new_bkidsigs)) # The sources and dependencies we'll want to report are all stored # as relative paths to this target's directory, but we want to @@ -1167,7 +1203,10 @@ def explain(self): # so we only print them after running them through this lambda # to turn them into the right relative Node and then return # its string. - stringify = lambda s, E=self.dir.Entry: str(E(s)) + def stringify( s, E=self.dir.Entry ) : + if hasattr( s, 'dir' ) : + return str(E(s)) + return str(s) lines = [] diff --git a/scons/scons-local-1.2.0/SCons/Options/BoolOption.py b/scons/scons-local-1.2.0/SCons/Options/BoolOption.py new file mode 100644 index 0000000000..c5fed0a142 --- /dev/null +++ b/scons/scons-local-1.2.0/SCons/Options/BoolOption.py @@ -0,0 +1,44 @@ +# +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation +# +# 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__ = "src/engine/SCons/Options/BoolOption.py 3842 2008/12/20 22:59:52 scons" + +__doc__ = """Place-holder for the old SCons.Options module hierarchy + +This is for backwards compatibility. The new equivalent is the Variables/ +class hierarchy. These will have deprecation warnings added (some day), +and will then be removed entirely (some day). +""" + +import SCons.Variables +import SCons.Warnings + +warned = False + +def BoolOption(*args, **kw): + global warned + if not warned: + msg = "The BoolOption() function is deprecated; use the BoolVariable() function instead." + SCons.Warnings.warn(SCons.Warnings.DeprecatedOptionsWarning, msg) + warned = True + return apply(SCons.Variables.BoolVariable, args, kw) diff --git a/scons/scons-local-1.2.0/SCons/Options/EnumOption.py b/scons/scons-local-1.2.0/SCons/Options/EnumOption.py new file mode 100644 index 0000000000..4f50d01b88 --- /dev/null +++ b/scons/scons-local-1.2.0/SCons/Options/EnumOption.py @@ -0,0 +1,44 @@ +# +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation +# +# 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__ = "src/engine/SCons/Options/EnumOption.py 3842 2008/12/20 22:59:52 scons" + +__doc__ = """Place-holder for the old SCons.Options module hierarchy + +This is for backwards compatibility. The new equivalent is the Variables/ +class hierarchy. These will have deprecation warnings added (some day), +and will then be removed entirely (some day). +""" + +import SCons.Variables +import SCons.Warnings + +warned = False + +def EnumOption(*args, **kw): + global warned + if not warned: + msg = "The EnumOption() function is deprecated; use the EnumVariable() function instead." + SCons.Warnings.warn(SCons.Warnings.DeprecatedOptionsWarning, msg) + warned = True + return apply(SCons.Variables.EnumVariable, args, kw) diff --git a/scons/scons-local-1.2.0/SCons/Options/ListOption.py b/scons/scons-local-1.2.0/SCons/Options/ListOption.py new file mode 100644 index 0000000000..b4cd923add --- /dev/null +++ b/scons/scons-local-1.2.0/SCons/Options/ListOption.py @@ -0,0 +1,44 @@ +# +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation +# +# 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__ = "src/engine/SCons/Options/ListOption.py 3842 2008/12/20 22:59:52 scons" + +__doc__ = """Place-holder for the old SCons.Options module hierarchy + +This is for backwards compatibility. The new equivalent is the Variables/ +class hierarchy. These will have deprecation warnings added (some day), +and will then be removed entirely (some day). +""" + +import SCons.Variables +import SCons.Warnings + +warned = False + +def ListOption(*args, **kw): + global warned + if not warned: + msg = "The ListOption() function is deprecated; use the ListVariable() function instead." + SCons.Warnings.warn(SCons.Warnings.DeprecatedOptionsWarning, msg) + warned = True + return apply(SCons.Variables.ListVariable, args, kw) diff --git a/scons/scons-local-1.2.0/SCons/Options/PackageOption.py b/scons/scons-local-1.2.0/SCons/Options/PackageOption.py new file mode 100644 index 0000000000..7fcbe5f1dd --- /dev/null +++ b/scons/scons-local-1.2.0/SCons/Options/PackageOption.py @@ -0,0 +1,44 @@ +# +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation +# +# 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__ = "src/engine/SCons/Options/PackageOption.py 3842 2008/12/20 22:59:52 scons" + +__doc__ = """Place-holder for the old SCons.Options module hierarchy + +This is for backwards compatibility. The new equivalent is the Variables/ +class hierarchy. These will have deprecation warnings added (some day), +and will then be removed entirely (some day). +""" + +import SCons.Variables +import SCons.Warnings + +warned = False + +def PackageOption(*args, **kw): + global warned + if not warned: + msg = "The PackageOption() function is deprecated; use the PackageVariable() function instead." + SCons.Warnings.warn(SCons.Warnings.DeprecatedOptionsWarning, msg) + warned = True + return apply(SCons.Variables.PackageVariable, args, kw) diff --git a/scons/scons-local-1.2.0/SCons/Options/PathOption.py b/scons/scons-local-1.2.0/SCons/Options/PathOption.py new file mode 100644 index 0000000000..649fc45eab --- /dev/null +++ b/scons/scons-local-1.2.0/SCons/Options/PathOption.py @@ -0,0 +1,70 @@ +# +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation +# +# 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__ = "src/engine/SCons/Options/PathOption.py 3842 2008/12/20 22:59:52 scons" + +__doc__ = """Place-holder for the old SCons.Options module hierarchy + +This is for backwards compatibility. The new equivalent is the Variables/ +class hierarchy. These will have deprecation warnings added (some day), +and will then be removed entirely (some day). +""" + +import SCons.Variables +import SCons.Warnings + +warned = False + +class _PathOptionClass: + def warn(self): + global warned + if not warned: + msg = "The PathOption() function is deprecated; use the PathVariable() function instead." + SCons.Warnings.warn(SCons.Warnings.DeprecatedOptionsWarning, msg) + warned = True + + def __call__(self, *args, **kw): + self.warn() + return apply(SCons.Variables.PathVariable, args, kw) + + def PathAccept(self, *args, **kw): + self.warn() + return apply(SCons.Variables.PathVariable.PathAccept, args, kw) + + def PathIsDir(self, *args, **kw): + self.warn() + return apply(SCons.Variables.PathVariable.PathIsDir, args, kw) + + def PathIsDirCreate(self, *args, **kw): + self.warn() + return apply(SCons.Variables.PathVariable.PathIsDirCreate, args, kw) + + def PathIsFile(self, *args, **kw): + self.warn() + return apply(SCons.Variables.PathVariable.PathIsFile, args, kw) + + def PathExists(self, *args, **kw): + self.warn() + return apply(SCons.Variables.PathVariable.PathExists, args, kw) + +PathOption = _PathOptionClass() diff --git a/scons/scons-local-1.2.0/SCons/Options/__init__.py b/scons/scons-local-1.2.0/SCons/Options/__init__.py new file mode 100644 index 0000000000..3e41b8d634 --- /dev/null +++ b/scons/scons-local-1.2.0/SCons/Options/__init__.py @@ -0,0 +1,68 @@ +# +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation +# +# 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__ = "src/engine/SCons/Options/__init__.py 3842 2008/12/20 22:59:52 scons" + +__doc__ = """Place-holder for the old SCons.Options module hierarchy + +This is for backwards compatibility. The new equivalent is the Variables/ +class hierarchy. These will have deprecation warnings added (some day), +and will then be removed entirely (some day). +""" + +import SCons.Variables +import SCons.Warnings + +from BoolOption import BoolOption # okay +from EnumOption import EnumOption # okay +from ListOption import ListOption # naja +from PackageOption import PackageOption # naja +from PathOption import PathOption # okay + +warned = False + +class Options(SCons.Variables.Variables): + def __init__(self, *args, **kw): + global warned + if not warned: + msg = "The Options class is deprecated; use the Variables class instead." + SCons.Warnings.warn(SCons.Warnings.DeprecatedOptionsWarning, msg) + warned = True + apply(SCons.Variables.Variables.__init__, + (self,) + args, + kw) + + def AddOptions(self, *args, **kw): + return apply(SCons.Variables.Variables.AddVariables, + (self,) + args, + kw) + + def UnknownOptions(self, *args, **kw): + return apply(SCons.Variables.Variables.UnknownVariables, + (self,) + args, + kw) + + def FormatOptionHelpText(self, *args, **kw): + return apply(SCons.Variables.Variables.FormatVariableHelpText, + (self,) + args, + kw) diff --git a/scons/scons-local-0.97.0d20071212/SCons/PathList.py b/scons/scons-local-1.2.0/SCons/PathList.py similarity index 94% rename from scons/scons-local-0.97.0d20071212/SCons/PathList.py rename to scons/scons-local-1.2.0/SCons/PathList.py index 355d06c94b..8b877fa4f1 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/PathList.py +++ b/scons/scons-local-1.2.0/SCons/PathList.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/PathList.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/PathList.py 3842 2008/12/20 22:59:52 scons" __doc__ = """SCons.PathList @@ -59,7 +59,7 @@ def node_conv(obj): try: get = obj.get except AttributeError: - if isinstance(obj, SCons.Node.Node): + if isinstance(obj, SCons.Node.Node) or SCons.Util.is_Sequence( obj ): result = obj else: result = str(obj) @@ -132,10 +132,9 @@ def subst_path(self, env, target, source): value = env.subst(value, target=target, source=source, conv=node_conv) if SCons.Util.is_Sequence(value): - # It came back as a string or tuple, which in this - # case usually means some variable expanded to an - # actually Dir node. Concatenate the values. - value = string.join(map(str, value), '') + result.extend(value) + continue + elif type == TYPE_OBJECT: value = node_conv(value) if value: diff --git a/scons/scons-local-0.97.0d20071212/SCons/Platform/__init__.py b/scons/scons-local-1.2.0/SCons/Platform/__init__.py similarity index 98% rename from scons/scons-local-0.97.0d20071212/SCons/Platform/__init__.py rename to scons/scons-local-1.2.0/SCons/Platform/__init__.py index 61e529931e..12158650bc 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Platform/__init__.py +++ b/scons/scons-local-1.2.0/SCons/Platform/__init__.py @@ -20,7 +20,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -42,7 +42,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Platform/__init__.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Platform/__init__.py 3842 2008/12/20 22:59:52 scons" import imp import os diff --git a/scons/scons-local-0.97.0d20071212/SCons/Platform/aix.py b/scons/scons-local-1.2.0/SCons/Platform/aix.py similarity index 93% rename from scons/scons-local-0.97.0d20071212/SCons/Platform/aix.py rename to scons/scons-local-1.2.0/SCons/Platform/aix.py index e054abee22..c8cb7e89f0 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Platform/aix.py +++ b/scons/scons-local-1.2.0/SCons/Platform/aix.py @@ -8,7 +8,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Platform/aix.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Platform/aix.py 3842 2008/12/20 22:59:52 scons" import os import string diff --git a/scons/scons-local-0.97.0d20071212/SCons/Platform/cygwin.py b/scons/scons-local-1.2.0/SCons/Platform/cygwin.py similarity index 91% rename from scons/scons-local-0.97.0d20071212/SCons/Platform/cygwin.py rename to scons/scons-local-1.2.0/SCons/Platform/cygwin.py index 0e32e7a5af..f51eeb16ee 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Platform/cygwin.py +++ b/scons/scons-local-1.2.0/SCons/Platform/cygwin.py @@ -8,7 +8,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Platform/cygwin.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Platform/cygwin.py 3842 2008/12/20 22:59:52 scons" import posix from SCons.Platform import TempFileMunge diff --git a/scons/scons-local-0.97.0d20071212/SCons/Platform/darwin.py b/scons/scons-local-1.2.0/SCons/Platform/darwin.py similarity index 89% rename from scons/scons-local-0.97.0d20071212/SCons/Platform/darwin.py rename to scons/scons-local-1.2.0/SCons/Platform/darwin.py index bcd57b2231..94365465cf 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Platform/darwin.py +++ b/scons/scons-local-1.2.0/SCons/Platform/darwin.py @@ -8,7 +8,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Platform/darwin.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Platform/darwin.py 3842 2008/12/20 22:59:52 scons" import posix diff --git a/scons/scons-local-0.97.0d20071212/SCons/Platform/hpux.py b/scons/scons-local-1.2.0/SCons/Platform/hpux.py similarity index 89% rename from scons/scons-local-0.97.0d20071212/SCons/Platform/hpux.py rename to scons/scons-local-1.2.0/SCons/Platform/hpux.py index e69403fe42..2bd468b71d 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Platform/hpux.py +++ b/scons/scons-local-1.2.0/SCons/Platform/hpux.py @@ -8,7 +8,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Platform/hpux.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Platform/hpux.py 3842 2008/12/20 22:59:52 scons" import posix diff --git a/scons/scons-local-0.97.0d20071212/SCons/Platform/irix.py b/scons/scons-local-1.2.0/SCons/Platform/irix.py similarity index 89% rename from scons/scons-local-0.97.0d20071212/SCons/Platform/irix.py rename to scons/scons-local-1.2.0/SCons/Platform/irix.py index ca09b62a39..b70481db29 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Platform/irix.py +++ b/scons/scons-local-1.2.0/SCons/Platform/irix.py @@ -8,7 +8,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Platform/irix.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Platform/irix.py 3842 2008/12/20 22:59:52 scons" import posix diff --git a/scons/scons-local-0.97.0d20071212/SCons/Platform/os2.py b/scons/scons-local-1.2.0/SCons/Platform/os2.py similarity index 91% rename from scons/scons-local-0.97.0d20071212/SCons/Platform/os2.py rename to scons/scons-local-1.2.0/SCons/Platform/os2.py index 0e9597c244..803d890d9d 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Platform/os2.py +++ b/scons/scons-local-1.2.0/SCons/Platform/os2.py @@ -8,7 +8,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Platform/os2.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Platform/os2.py 3842 2008/12/20 22:59:52 scons" def generate(env): if not env.has_key('ENV'): diff --git a/scons/scons-local-0.97.0d20071212/SCons/Platform/posix.py b/scons/scons-local-1.2.0/SCons/Platform/posix.py similarity index 85% rename from scons/scons-local-0.97.0d20071212/SCons/Platform/posix.py rename to scons/scons-local-1.2.0/SCons/Platform/posix.py index ab6c7d9bc8..6d0b0747e2 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Platform/posix.py +++ b/scons/scons-local-1.2.0/SCons/Platform/posix.py @@ -8,7 +8,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,12 +30,13 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Platform/posix.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Platform/posix.py 3842 2008/12/20 22:59:52 scons" +import errno import os import os.path -import popen2 import string +import subprocess import sys import select @@ -50,7 +51,7 @@ def escape(arg): "escape shell special characters" slash = '\\' - special = '"$' + special = '"$()' arg = string.replace(arg, slash, slash+slash) for c in special: @@ -92,7 +93,7 @@ def _get_env_command(sh, escape, cmd, args, env): s = string.join(args) if env: l = ['env', '-'] + \ - map(lambda t, e=escape: t[0]+'='+e(t[1]), env.items()) + \ + map(lambda t, e=escape: e(t[0])+'='+e(t[1]), env.items()) + \ [sh, '-c', escape(s)] s = string.join(l) return s @@ -109,25 +110,31 @@ def fork_spawn(sh, escape, cmd, args, env): def process_cmd_output(cmd_stdout, cmd_stderr, stdout, stderr): stdout_eof = stderr_eof = 0 while not (stdout_eof and stderr_eof): - (i,o,e) = select.select([cmd_stdout, cmd_stderr], [], []) - if cmd_stdout in i: - str = cmd_stdout.read() - if len(str) == 0: - stdout_eof = 1 - elif stdout != None: - stdout.write(str) - if cmd_stderr in i: - str = cmd_stderr.read() - if len(str) == 0: - #sys.__stderr__.write( "stderr_eof=1\n" ) - stderr_eof = 1 - else: - #sys.__stderr__.write( "str(stderr) = %s\n" % str ) - stderr.write(str) + try: + (i,o,e) = select.select([cmd_stdout, cmd_stderr], [], []) + if cmd_stdout in i: + str = cmd_stdout.read() + if len(str) == 0: + stdout_eof = 1 + elif stdout != None: + stdout.write(str) + if cmd_stderr in i: + str = cmd_stderr.read() + if len(str) == 0: + #sys.__stderr__.write( "stderr_eof=1\n" ) + stderr_eof = 1 + else: + #sys.__stderr__.write( "str(stderr) = %s\n" % str ) + stderr.write(str) + except select.error, (_errno, _strerror): + if _errno != errno.EINTR: + raise def exec_popen3(l, env, stdout, stderr): - proc = popen2.Popen3(string.join(l), 1) - process_cmd_output(proc.fromchild, proc.childerr, stdout, stderr) + proc = subprocess.Popen(string.join(l), + stdout=stdout, + stderr=stderr, + shell=True) stat = proc.wait() if stat & 0xff: return stat | 0x80 @@ -235,7 +242,7 @@ def generate(env): env['LIBSUFFIX'] = '.a' env['SHLIBPREFIX'] = '$LIBPREFIX' env['SHLIBSUFFIX'] = '.so' - env['LIBPREFIXES'] = '$LIBPREFIX' + env['LIBPREFIXES'] = [ '$LIBPREFIX' ] env['LIBSUFFIXES'] = [ '$LIBSUFFIX', '$SHLIBSUFFIX' ] env['PSPAWN'] = pspawn env['SPAWN'] = spawn diff --git a/scons/scons-local-0.97.0d20071212/SCons/Platform/sunos.py b/scons/scons-local-1.2.0/SCons/Platform/sunos.py similarity index 90% rename from scons/scons-local-0.97.0d20071212/SCons/Platform/sunos.py rename to scons/scons-local-1.2.0/SCons/Platform/sunos.py index cfa6384665..03435c6918 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Platform/sunos.py +++ b/scons/scons-local-1.2.0/SCons/Platform/sunos.py @@ -8,7 +8,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Platform/sunos.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Platform/sunos.py 3842 2008/12/20 22:59:52 scons" import posix diff --git a/scons/scons-local-0.97.0d20071212/SCons/Platform/win32.py b/scons/scons-local-1.2.0/SCons/Platform/win32.py similarity index 98% rename from scons/scons-local-0.97.0d20071212/SCons/Platform/win32.py rename to scons/scons-local-1.2.0/SCons/Platform/win32.py index 2e10ca3eab..3ec0a526d3 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Platform/win32.py +++ b/scons/scons-local-1.2.0/SCons/Platform/win32.py @@ -8,7 +8,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Platform/win32.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Platform/win32.py 3842 2008/12/20 22:59:52 scons" import os import os.path diff --git a/scons/scons-local-0.97.0d20071212/SCons/SConf.py b/scons/scons-local-1.2.0/SCons/SConf.py similarity index 93% rename from scons/scons-local-0.97.0d20071212/SCons/SConf.py rename to scons/scons-local-1.2.0/SCons/SConf.py index e0c16080ea..ec80fe97a4 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/SConf.py +++ b/scons/scons-local-1.2.0/SCons/SConf.py @@ -4,7 +4,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -26,9 +26,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/SConf.py 2523 2007/12/12 09:37:41 knight" - -import SCons.compat +__revision__ = "src/engine/SCons/SConf.py 3842 2008/12/20 22:59:52 scons" import os import re @@ -235,7 +233,9 @@ def failed(self): raise elif issubclass(exc_type, SCons.Errors.BuildError): # we ignore Build Errors (occurs, when a test doesn't pass) - pass + # Clear the exception to prevent the contained traceback + # to build a reference cycle. + self.exc_clear() else: self.display('Caught exception while building "%s":\n' % self.targets[0]) @@ -381,7 +381,7 @@ def __init__(self, env, custom_tests = {}, conf_dir='$CONFIGUREDIR', e.g. custom_tests={'CheckPrivate':MyPrivateTest}, where MyPrivateTest defines a custom test. Note also the conf_dir and log_file arguments (you may want to - build tests in the BuildDir, not in the SourceDir) + build tests in the VariantDir, not in the SourceDir) """ global SConfFS if not SConfFS: @@ -401,14 +401,19 @@ def __init__(self, env, custom_tests = {}, conf_dir='$CONFIGUREDIR', # add default tests default_tests = { + 'CheckCC' : CheckCC, + 'CheckCXX' : CheckCXX, + 'CheckSHCC' : CheckSHCC, + 'CheckSHCXX' : CheckSHCXX, 'CheckFunc' : CheckFunc, 'CheckType' : CheckType, 'CheckTypeSize' : CheckTypeSize, + 'CheckDeclaration' : CheckDeclaration, 'CheckHeader' : CheckHeader, 'CheckCHeader' : CheckCHeader, 'CheckCXXHeader' : CheckCXXHeader, 'CheckLib' : CheckLib, - 'CheckLibWithHeader' : CheckLibWithHeader + 'CheckLibWithHeader' : CheckLibWithHeader, } self.AddTests(default_tests) self.AddTests(custom_tests) @@ -425,6 +430,31 @@ def Finish(self): self._shutdown() return self.env + def Define(self, name, value = None, comment = None): + """ + Define a pre processor symbol name, with the optional given value in the + current config header. + + If value is None (default), then #define name is written. If value is not + none, then #define name value is written. + + comment is a string which will be put as a C comment in the + header, to explain the meaning of the value (appropriate C comments /* and + */ will be put automatically.""" + lines = [] + if comment: + comment_str = "/* %s */" % comment + lines.append(comment_str) + + if value is not None: + define_str = "#define %s %s" % (name, value) + else: + define_str = "#define %s" % name + lines.append(define_str) + lines.append('') + + self.config_h_text = self.config_h_text + string.join(lines, '\n') + def BuildNodes(self, nodes): """ Tries to build the given nodes immediately. Returns 1 on success, @@ -797,6 +827,17 @@ def CompileProg(self, text, ext): # TODO: should use self.vardict for $CC, $CPPFLAGS, etc. return not self.TryBuild(self.env.Object, text, ext) + def CompileSharedObject(self, text, ext): + self.sconf.cached = 1 + # TODO: should use self.vardict for $SHCC, $CPPFLAGS, etc. + return not self.TryBuild(self.env.SharedObject, text, ext) + + def RunProg(self, text, ext): + self.sconf.cached = 1 + # TODO: should use self.vardict for $CC, $CPPFLAGS, etc. + st, out = self.TryRun(text, ext) + return not st, out + def AppendLIBS(self, lib_name_list): oldLIBS = self.env.get( 'LIBS', [] ) self.env.Append(LIBS = lib_name_list) @@ -855,6 +896,13 @@ def CheckTypeSize(context, type_name, includes = "", language = None, expect = N context.did_show_result = 1 return res +def CheckDeclaration(context, declaration, includes = "", language = None): + res = SCons.Conftest.CheckDeclaration(context, declaration, + includes = includes, + language = language) + context.did_show_result = 1 + return not res + def createIncludesFromHeaders(headers, leaveLast, include_quotes = '""'): # used by CheckHeader and CheckLibWithHeader to produce C - #include # statements from the specified header (list) @@ -883,6 +931,22 @@ def CheckHeader(context, header, include_quotes = '<>', language = None): context.did_show_result = 1 return not res +def CheckCC(context): + res = SCons.Conftest.CheckCC(context) + return not res + +def CheckCXX(context): + res = SCons.Conftest.CheckCXX(context) + return not res + +def CheckSHCC(context): + res = SCons.Conftest.CheckSHCC(context) + return not res + +def CheckSHCXX(context): + res = SCons.Conftest.CheckSHCXX(context) + return not res + # Bram: Make this function obsolete? CheckHeader() is more generic. def CheckCHeader(context, header, include_quotes = '""'): diff --git a/scons/scons-local-0.97.0d20071212/SCons/SConsign.py b/scons/scons-local-1.2.0/SCons/SConsign.py similarity index 98% rename from scons/scons-local-0.97.0d20071212/SCons/SConsign.py rename to scons/scons-local-1.2.0/SCons/SConsign.py index 0e26f73ca7..8e4c30c145 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/SConsign.py +++ b/scons/scons-local-1.2.0/SCons/SConsign.py @@ -5,7 +5,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,9 +27,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/SConsign.py 2523 2007/12/12 09:37:41 knight" - -import SCons.compat +__revision__ = "src/engine/SCons/SConsign.py 3842 2008/12/20 22:59:52 scons" import cPickle import os diff --git a/scons/scons-local-1.2.0/SCons/Scanner/C.py b/scons/scons-local-1.2.0/SCons/Scanner/C.py new file mode 100644 index 0000000000..926493e767 --- /dev/null +++ b/scons/scons-local-1.2.0/SCons/Scanner/C.py @@ -0,0 +1,126 @@ +"""SCons.Scanner.C + +This module implements the depenency scanner for C/C++ code. + +""" + +# +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation +# +# 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__ = "src/engine/SCons/Scanner/C.py 3842 2008/12/20 22:59:52 scons" + +import SCons.Node.FS +import SCons.Scanner +import SCons.Util + +import SCons.cpp + +class SConsCPPScanner(SCons.cpp.PreProcessor): + """ + SCons-specific subclass of the cpp.py module's processing. + + We subclass this so that: 1) we can deal with files represented + by Nodes, not strings; 2) we can keep track of the files that are + missing. + """ + def __init__(self, *args, **kw): + apply(SCons.cpp.PreProcessor.__init__, (self,)+args, kw) + self.missing = [] + def initialize_result(self, fname): + self.result = SCons.Util.UniqueList([fname]) + def finalize_result(self, fname): + return self.result[1:] + def find_include_file(self, t): + keyword, quote, fname = t + result = SCons.Node.FS.find_file(fname, self.searchpath[quote]) + if not result: + self.missing.append((fname, self.current_file)) + return result + def read_file(self, file): + try: + fp = open(str(file.rfile())) + except EnvironmentError, e: + self.missing.append((file, self.current_file)) + return '' + else: + return fp.read() + +def dictify_CPPDEFINES(env): + cppdefines = env.get('CPPDEFINES', {}) + if cppdefines is None: + return {} + if SCons.Util.is_Sequence(cppdefines): + result = {} + for c in cppdefines: + if SCons.Util.is_Sequence(c): + result[c[0]] = c[1] + else: + result[c] = None + return result + if not SCons.Util.is_Dict(cppdefines): + return {cppdefines : None} + return cppdefines + +class SConsCPPScannerWrapper: + """ + The SCons wrapper around a cpp.py scanner. + + This is the actual glue between the calling conventions of generic + SCons scanners, and the (subclass of) cpp.py class that knows how + to look for #include lines with reasonably real C-preprocessor-like + evaluation of #if/#ifdef/#else/#elif lines. + """ + def __init__(self, name, variable): + self.name = name + self.path = SCons.Scanner.FindPathDirs(variable) + def __call__(self, node, env, path = ()): + cpp = SConsCPPScanner(current = node.get_dir(), + cpppath = path, + dict = dictify_CPPDEFINES(env)) + result = cpp(node) + for included, includer in cpp.missing: + fmt = "No dependency generated for file: %s (included from: %s) -- file not found" + SCons.Warnings.warn(SCons.Warnings.DependencyWarning, + fmt % (included, includer)) + return result + + def recurse_nodes(self, nodes): + return nodes + def select(self, node): + return self + +def CScanner(): + """Return a prototype Scanner instance for scanning source files + that use the C pre-processor""" + + # Here's how we would (or might) use the CPP scanner code above that + # knows how to evaluate #if/#ifdef/#else/#elif lines when searching + # for #includes. This is commented out for now until we add the + # right configurability to let users pick between the scanners. + #return SConsCPPScannerWrapper("CScanner", "CPPPATH") + + cs = SCons.Scanner.ClassicCPP("CScanner", + "$CPPSUFFIXES", + "CPPPATH", + '^[ \t]*#[ \t]*(?:include|import)[ \t]*(<|")([^>"]+)(>|")') + return cs diff --git a/scons/scons-local-0.97.0d20071212/SCons/Scanner/D.py b/scons/scons-local-1.2.0/SCons/Scanner/D.py similarity index 66% rename from scons/scons-local-0.97.0d20071212/SCons/Scanner/D.py rename to scons/scons-local-1.2.0/SCons/Scanner/D.py index 1abfaa04fc..97ece3a18a 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Scanner/D.py +++ b/scons/scons-local-1.2.0/SCons/Scanner/D.py @@ -8,7 +8,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,24 +30,39 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Scanner/D.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Scanner/D.py 3842 2008/12/20 22:59:52 scons" +import re import string import SCons.Scanner def DScanner(): """Return a prototype Scanner instance for scanning D source files""" - ds = D(name = "DScanner", - suffixes = '$DSUFFIXES', - path_variable = 'DPATH', - regex = 'import\s+([^\;]*)\;') + ds = D() return ds class D(SCons.Scanner.Classic): + def __init__ (self): + SCons.Scanner.Classic.__init__ (self, + name = "DScanner", + suffixes = '$DSUFFIXES', + path_variable = 'DPATH', + regex = 'import\s+(?:[a-zA-Z0-9_.]+)\s*(?:,\s*(?:[a-zA-Z0-9_.]+)\s*)*;') + + self.cre2 = re.compile ('(?:import\s)?\s*([a-zA-Z0-9_.]+)\s*(?:,|;)', re.M) + def find_include(self, include, source_dir, path): # translate dots (package separators) to slashes inc = string.replace(include, '.', '/') i = SCons.Node.FS.find_file(inc + '.d', (source_dir,) + path) + if i is None: + i = SCons.Node.FS.find_file (inc + '.di', (source_dir,) + path) return i, include + + def find_include_names(self, node): + includes = [] + for i in self.cre.findall(node.get_contents()): + includes = includes + self.cre2.findall(i) + return includes diff --git a/scons/scons-local-0.97.0d20071212/SCons/Scanner/Dir.py b/scons/scons-local-1.2.0/SCons/Scanner/Dir.py similarity index 95% rename from scons/scons-local-0.97.0d20071212/SCons/Scanner/Dir.py rename to scons/scons-local-1.2.0/SCons/Scanner/Dir.py index 7a6a55f390..35d500861c 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Scanner/Dir.py +++ b/scons/scons-local-1.2.0/SCons/Scanner/Dir.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Scanner/Dir.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Scanner/Dir.py 3842 2008/12/20 22:59:52 scons" import SCons.Node.FS import SCons.Scanner diff --git a/scons/scons-local-0.97.0d20071212/SCons/Scanner/Fortran.py b/scons/scons-local-1.2.0/SCons/Scanner/Fortran.py similarity index 98% rename from scons/scons-local-0.97.0d20071212/SCons/Scanner/Fortran.py rename to scons/scons-local-1.2.0/SCons/Scanner/Fortran.py index b3ebd0086d..e629b80b0e 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Scanner/Fortran.py +++ b/scons/scons-local-1.2.0/SCons/Scanner/Fortran.py @@ -5,7 +5,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,7 +27,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Scanner/Fortran.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Scanner/Fortran.py 3842 2008/12/20 22:59:52 scons" import re import string diff --git a/scons/scons-local-0.97.0d20071212/SCons/Scanner/IDL.py b/scons/scons-local-1.2.0/SCons/Scanner/IDL.py similarity index 90% rename from scons/scons-local-0.97.0d20071212/SCons/Scanner/IDL.py rename to scons/scons-local-1.2.0/SCons/Scanner/IDL.py index aee4b8f024..9bd1728737 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Scanner/IDL.py +++ b/scons/scons-local-1.2.0/SCons/Scanner/IDL.py @@ -6,7 +6,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -28,7 +28,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Scanner/IDL.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Scanner/IDL.py 3842 2008/12/20 22:59:52 scons" import SCons.Node.FS import SCons.Scanner diff --git a/scons/scons-local-1.2.0/SCons/Scanner/LaTeX.py b/scons/scons-local-1.2.0/SCons/Scanner/LaTeX.py new file mode 100644 index 0000000000..3e17e25488 --- /dev/null +++ b/scons/scons-local-1.2.0/SCons/Scanner/LaTeX.py @@ -0,0 +1,334 @@ +"""SCons.Scanner.LaTeX + +This module implements the dependency scanner for LaTeX code. + +""" + +# +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation +# +# 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__ = "src/engine/SCons/Scanner/LaTeX.py 3842 2008/12/20 22:59:52 scons" + +import os.path +import string +import re + +import SCons.Scanner +import SCons.Util + +# list of graphics file extensions for TeX and LaTeX +TexGraphics = ['.eps', '.ps'] +LatexGraphics = ['.pdf', '.png', '.jpg', '.gif', '.tif'] + +# Used as a return value of modify_env_var if the variable is not set. +class _Null: + pass +_null = _Null + +# The user specifies the paths in env[variable], similar to other builders. +# They may be relative and must be converted to absolute, as expected +# by LaTeX and Co. The environment may already have some paths in +# env['ENV'][var]. These paths are honored, but the env[var] paths have +# higher precedence. All changes are un-done on exit. +def modify_env_var(env, var, abspath): + try: + save = env['ENV'][var] + except KeyError: + save = _null + env.PrependENVPath(var, abspath) + try: + if SCons.Util.is_List(env[var]): + #TODO(1.5) + #env.PrependENVPath(var, [os.path.abspath(str(p)) for p in env[var]]) + env.PrependENVPath(var, map(lambda p: os.path.abspath(str(p)), env[var])) + else: + # Split at os.pathsep to convert into absolute path + #TODO(1.5) env.PrependENVPath(var, [os.path.abspath(p) for p in str(env[var]).split(os.pathsep)]) + env.PrependENVPath(var, map(lambda p: os.path.abspath(p), string.split(str(env[var]), os.pathsep))) + except KeyError: + pass + + # Convert into a string explicitly to append ":" (without which it won't search system + # paths as well). The problem is that env.AppendENVPath(var, ":") + # does not work, refuses to append ":" (os.pathsep). + + if SCons.Util.is_List(env['ENV'][var]): + # TODO(1.5) + #env['ENV'][var] = os.pathsep.join(env['ENV'][var]) + env['ENV'][var] = string.join(env['ENV'][var], os.pathsep) + # Append the trailing os.pathsep character here to catch the case with no env[var] + env['ENV'][var] = env['ENV'][var] + os.pathsep + + return save + +class FindENVPathDirs: + """A class to bind a specific *PATH variable name to a function that + will return all of the *path directories.""" + def __init__(self, variable): + self.variable = variable + def __call__(self, env, dir=None, target=None, source=None, argument=None): + import SCons.PathList + try: + path = env['ENV'][self.variable] + except KeyError: + return () + + dir = dir or env.fs._cwd + path = SCons.PathList.PathList(path).subst_path(env, target, source) + return tuple(dir.Rfindalldirs(path)) + + + +def LaTeXScanner(): + """Return a prototype Scanner instance for scanning LaTeX source files + when built with latex. + """ + ds = LaTeX(name = "LaTeXScanner", + suffixes = '$LATEXSUFFIXES', + # in the search order, see below in LaTeX class docstring + graphics_extensions = TexGraphics, + recursive = 0) + return ds + +def PDFLaTeXScanner(): + """Return a prototype Scanner instance for scanning LaTeX source files + when built with pdflatex. + """ + ds = LaTeX(name = "PDFLaTeXScanner", + suffixes = '$LATEXSUFFIXES', + # in the search order, see below in LaTeX class docstring + graphics_extensions = LatexGraphics, + recursive = 0) + return ds + +class LaTeX(SCons.Scanner.Base): + """Class for scanning LaTeX files for included files. + + Unlike most scanners, which use regular expressions that just + return the included file name, this returns a tuple consisting + of the keyword for the inclusion ("include", "includegraphics", + "input", or "bibliography"), and then the file name itself. + Based on a quick look at LaTeX documentation, it seems that we + should append .tex suffix for the "include" keywords, append .tex if + there is no extension for the "input" keyword, and need to add .bib + for the "bibliography" keyword that does not accept extensions by itself. + + Finally, if there is no extension for an "includegraphics" keyword + latex will append .ps or .eps to find the file, while pdftex may use .pdf, + .jpg, .tif, .mps, or .png. + + The actual subset and search order may be altered by + DeclareGraphicsExtensions command. This complication is ignored. + The default order corresponds to experimentation with teTeX + $ latex --version + pdfeTeX 3.141592-1.21a-2.2 (Web2C 7.5.4) + kpathsea version 3.5.4 + The order is: + ['.eps', '.ps'] for latex + ['.png', '.pdf', '.jpg', '.tif']. + + Another difference is that the search path is determined by the type + of the file being searched: + env['TEXINPUTS'] for "input" and "include" keywords + env['TEXINPUTS'] for "includegraphics" keyword + env['BIBINPUTS'] for "bibliography" keyword + env['BSTINPUTS'] for "bibliographystyle" keyword + + FIXME: also look for the class or style in document[class|style]{} + FIXME: also look for the argument of bibliographystyle{} + """ + keyword_paths = {'include': 'TEXINPUTS', + 'input': 'TEXINPUTS', + 'includegraphics': 'TEXINPUTS', + 'bibliography': 'BIBINPUTS', + 'bibliographystyle': 'BSTINPUTS', + 'usepackage': 'TEXINPUTS'} + env_variables = SCons.Util.unique(keyword_paths.values()) + + def __init__(self, name, suffixes, graphics_extensions, *args, **kw): + + # We have to include \n with the % we exclude from the first part + # part of the regex because the expression is compiled with re.M. + # Without the \n, the ^ could match the beginning of a *previous* + # line followed by one or more newline characters (i.e. blank + # lines), interfering with a match on the next line. + regex = r'^[^%\n]*\\(include|includegraphics(?:\[[^\]]+\])?|input|bibliography|usepackage){([^}]*)}' + self.cre = re.compile(regex, re.M) + self.graphics_extensions = graphics_extensions + + def _scan(node, env, path=(), self=self): + node = node.rfile() + if not node.exists(): + return [] + return self.scan(node, path) + + class FindMultiPathDirs: + """The stock FindPathDirs function has the wrong granularity: + it is called once per target, while we need the path that depends + on what kind of included files is being searched. This wrapper + hides multiple instances of FindPathDirs, one per the LaTeX path + variable in the environment. When invoked, the function calculates + and returns all the required paths as a dictionary (converted into + a tuple to become hashable). Then the scan function converts it + back and uses a dictionary of tuples rather than a single tuple + of paths. + """ + def __init__(self, dictionary): + self.dictionary = {} + for k,n in dictionary.items(): + self.dictionary[k] = ( SCons.Scanner.FindPathDirs(n), + FindENVPathDirs(n) ) + + def __call__(self, env, dir=None, target=None, source=None, + argument=None): + di = {} + for k,(c,cENV) in self.dictionary.items(): + di[k] = ( c(env, dir=None, target=None, source=None, + argument=None) , + cENV(env, dir=None, target=None, source=None, + argument=None) ) + # To prevent "dict is not hashable error" + return tuple(di.items()) + + class LaTeXScanCheck: + """Skip all but LaTeX source files, i.e., do not scan *.eps, + *.pdf, *.jpg, etc. + """ + def __init__(self, suffixes): + self.suffixes = suffixes + def __call__(self, node, env): + current = not node.has_builder() or node.is_up_to_date() + scannable = node.get_suffix() in env.subst_list(self.suffixes)[0] + # Returning false means that the file is not scanned. + return scannable and current + + kw['function'] = _scan + kw['path_function'] = FindMultiPathDirs(LaTeX.keyword_paths) + kw['recursive'] = 1 + kw['skeys'] = suffixes + kw['scan_check'] = LaTeXScanCheck(suffixes) + kw['name'] = name + + apply(SCons.Scanner.Base.__init__, (self,) + args, kw) + + def _latex_names(self, include): + filename = include[1] + if include[0] == 'input': + base, ext = os.path.splitext( filename ) + if ext == "": + return [filename + '.tex'] + if (include[0] == 'include'): + return [filename + '.tex'] + if include[0] == 'bibliography': + base, ext = os.path.splitext( filename ) + if ext == "": + return [filename + '.bib'] + if include[0] == 'usepackage': + base, ext = os.path.splitext( filename ) + if ext == "": + return [filename + '.sty'] + if include[0] == 'includegraphics': + base, ext = os.path.splitext( filename ) + if ext == "": + #TODO(1.5) return [filename + e for e in self.graphics_extensions] + return map(lambda e, f=filename: f+e, self.graphics_extensions) + return [filename] + + def sort_key(self, include): + return SCons.Node.FS._my_normcase(str(include)) + + def find_include(self, include, source_dir, path): + try: + sub_path = path[include[0]] + except (IndexError, KeyError): + sub_path = () + try_names = self._latex_names(include) + for n in try_names: + # see if we find it using the path in env[var] + i = SCons.Node.FS.find_file(n, (source_dir,) + sub_path[0]) + if i: + return i, include + # see if we find it using the path in env['ENV'][var] + i = SCons.Node.FS.find_file(n, (source_dir,) + sub_path[1]) + if i: + return i, include + return i, include + + def scan(self, node, path=()): + # Modify the default scan function to allow for the regular + # expression to return a comma separated list of file names + # as can be the case with the bibliography keyword. + + # Cache the includes list in node so we only scan it once: + path_dict = dict(list(path)) + noopt_cre = re.compile('\[.*$') + if node.includes != None: + includes = node.includes + else: + includes = self.cre.findall(node.get_contents()) + # 1. Split comma-separated lines, e.g. + # ('bibliography', 'phys,comp') + # should become two entries + # ('bibliography', 'phys') + # ('bibliography', 'comp') + # 2. Remove the options, e.g., such as + # ('includegraphics[clip,width=0.7\\linewidth]', 'picture.eps') + # should become + # ('includegraphics', 'picture.eps') + split_includes = [] + for include in includes: + inc_type = noopt_cre.sub('', include[0]) + inc_list = string.split(include[1],',') + for j in range(len(inc_list)): + split_includes.append( (inc_type, inc_list[j]) ) + # + includes = split_includes + node.includes = includes + + # This is a hand-coded DSU (decorate-sort-undecorate, or + # Schwartzian transform) pattern. The sort key is the raw name + # of the file as specifed on the \include, \input, etc. line. + # TODO: what about the comment in the original Classic scanner: + # """which lets + # us keep the sort order constant regardless of whether the file + # is actually found in a Repository or locally.""" + nodes = [] + source_dir = node.get_dir() + for include in includes: + # + # Handle multiple filenames in include[1] + # + n, i = self.find_include(include, source_dir, path_dict) + if n is None: + # Do not bother with 'usepackage' warnings, as they most + # likely refer to system-level files + if include[0] != 'usepackage': + SCons.Warnings.warn(SCons.Warnings.DependencyWarning, + "No dependency generated for file: %s (included from: %s) -- file not found" % (i, node)) + else: + sortkey = self.sort_key(n) + nodes.append((sortkey, n)) + # + nodes.sort() + nodes = map(lambda pair: pair[1], nodes) + return nodes diff --git a/scons/scons-local-0.97.0d20071212/SCons/Scanner/Prog.py b/scons/scons-local-1.2.0/SCons/Scanner/Prog.py similarity index 93% rename from scons/scons-local-0.97.0d20071212/SCons/Scanner/Prog.py rename to scons/scons-local-1.2.0/SCons/Scanner/Prog.py index aa7685f161..ad71ba4497 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Scanner/Prog.py +++ b/scons/scons-local-1.2.0/SCons/Scanner/Prog.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Scanner/Prog.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Scanner/Prog.py 3842 2008/12/20 22:59:52 scons" import string @@ -54,10 +54,8 @@ def scan(node, env, libpath = ()): return [] if SCons.Util.is_String(libs): libs = string.split(libs) - elif SCons.Util.is_List(libs): - libs = SCons.Util.flatten(libs) else: - libs = [libs] + libs = SCons.Util.flatten(libs) try: prefix = env['LIBPREFIXES'] diff --git a/scons/scons-local-0.97.0d20071212/SCons/Scanner/C.py b/scons/scons-local-1.2.0/SCons/Scanner/RC.py similarity index 57% rename from scons/scons-local-0.97.0d20071212/SCons/Scanner/C.py rename to scons/scons-local-1.2.0/SCons/Scanner/RC.py index a79bea7c4d..ecbc572569 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Scanner/C.py +++ b/scons/scons-local-1.2.0/SCons/Scanner/RC.py @@ -1,11 +1,12 @@ -"""SCons.Scanner.C +"""SCons.Scanner.RC -This module implements the depenency scanner for C/C++ code. +This module implements the depenency scanner for RC (Interface +Definition Language) files. """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,16 +28,22 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Scanner/C.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Scanner/RC.py 3842 2008/12/20 22:59:52 scons" import SCons.Node.FS import SCons.Scanner +import re -def CScanner(): - """Return a prototype Scanner instance for scanning source files - that use the C pre-processor""" - cs = SCons.Scanner.ClassicCPP("CScanner", - "$CPPSUFFIXES", - "CPPPATH", - '^[ \t]*#[ \t]*(?:include|import)[ \t]*(<|")([^>"]+)(>|")') - return cs +def RCScan(): + """Return a prototype Scanner instance for scanning RC source files""" + + res_re= r'^(?:\s*#\s*(?:include)|' \ + '.*?\s+(?:ICON|BITMAP|CURSOR|HTML|FONT|MESSAGETABLE|TYPELIB|REGISTRY|D3DFX)' \ + '\s*.*?)' \ + '\s*(<|"| )([^>"\s]+)(?:[>" ])*$' + resScanner = SCons.Scanner.ClassicCPP( "ResourceScanner", + "$RCSUFFIXES", + "CPPPATH", + res_re ) + + return resScanner diff --git a/scons/scons-local-0.97.0d20071212/SCons/Scanner/__init__.py b/scons/scons-local-1.2.0/SCons/Scanner/__init__.py similarity index 97% rename from scons/scons-local-0.97.0d20071212/SCons/Scanner/__init__.py rename to scons/scons-local-1.2.0/SCons/Scanner/__init__.py index 07243c89ad..e18f0fe306 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Scanner/__init__.py +++ b/scons/scons-local-1.2.0/SCons/Scanner/__init__.py @@ -5,7 +5,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,7 +27,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Scanner/__init__.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Scanner/__init__.py 3842 2008/12/20 22:59:52 scons" import re import string @@ -67,7 +67,7 @@ class FindPathDirs: will return all of the *path directories.""" def __init__(self, variable): self.variable = variable - def __call__(self, env, dir, target=None, source=None, argument=None): + def __call__(self, env, dir=None, target=None, source=None, argument=None): import SCons.PathList try: path = env[self.variable] @@ -346,13 +346,16 @@ def find_include(self, include, source_dir, path): def sort_key(self, include): return SCons.Node.FS._my_normcase(include) + def find_include_names(self, node): + return self.cre.findall(node.get_contents()) + def scan(self, node, path=()): # cache the includes list in node so we only scan it once: if node.includes != None: includes = node.includes else: - includes = self.cre.findall(node.get_contents()) + includes = self.find_include_names (node) node.includes = includes # This is a hand-coded DSU (decorate-sort-undecorate, or diff --git a/scons/scons-local-1.2.0/SCons/Script/Interactive.py b/scons/scons-local-1.2.0/SCons/Script/Interactive.py new file mode 100644 index 0000000000..13cc41409e --- /dev/null +++ b/scons/scons-local-1.2.0/SCons/Script/Interactive.py @@ -0,0 +1,376 @@ +# +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation +# +# 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__ = "src/engine/SCons/Script/Interactive.py 3842 2008/12/20 22:59:52 scons" + +__doc__ = """ +SCons interactive mode +""" + +# TODO: +# +# This has the potential to grow into something with a really big life +# of its own, which might or might not be a good thing. Nevertheless, +# here are some enhancements that will probably be requested some day +# and are worth keeping in mind (assuming this takes off): +# +# - A command to re-read / re-load the SConscript files. This may +# involve allowing people to specify command-line options (e.g. -f, +# -I, --no-site-dir) that affect how the SConscript files are read. +# +# - Additional command-line options on the "build" command. +# +# Of the supported options that seemed to make sense (after a quick +# pass through the list), the ones that seemed likely enough to be +# used are listed in the man page and have explicit test scripts. +# +# These had code changed in Script/Main.py to support them, but didn't +# seem likely to be used regularly, so had no test scripts added: +# +# build --diskcheck=* +# build --implicit-cache=* +# build --implicit-deps-changed=* +# build --implicit-deps-unchanged=* +# +# These look like they should "just work" with no changes to the +# existing code, but like those above, look unlikely to be used and +# therefore had no test scripts added: +# +# build --random +# +# These I'm not sure about. They might be useful for individual +# "build" commands, and may even work, but they seem unlikely enough +# that we'll wait until they're requested before spending any time on +# writing test scripts for them, or investigating whether they work. +# +# build -q [??? is there a useful analog to the exit status?] +# build --duplicate= +# build --profile= +# build --max-drift= +# build --warn=* +# build --Y +# +# - Most of the SCons command-line options that the "build" command +# supports should be settable as default options that apply to all +# subsequent "build" commands. Maybe a "set {option}" command that +# maps to "SetOption('{option}')". +# +# - Need something in the 'help' command that prints the -h output. +# +# - A command to run the configure subsystem separately (must see how +# this interacts with the new automake model). +# +# - Command-line completion of target names; maybe even of SCons options? +# Completion is something that's supported by the Python cmd module, +# so this should be doable without too much trouble. +# + +import cmd +import copy +import os +import re +import shlex +import string +import sys + +try: + import readline +except ImportError: + pass + +class SConsInteractiveCmd(cmd.Cmd): + """\ + build [TARGETS] Build the specified TARGETS and their dependencies. + 'b' is a synonym. + clean [TARGETS] Clean (remove) the specified TARGETS and their + dependencies. 'c' is a synonym. + exit Exit SCons interactive mode. + help [COMMAND] Prints help for the specified COMMAND. 'h' and + '?' are synonyms. + shell [COMMANDLINE] Execute COMMANDLINE in a subshell. 'sh' and '!' + are synonyms. + version Prints SCons version information. + """ + + synonyms = { + 'b' : 'build', + 'c' : 'clean', + 'h' : 'help', + 'scons' : 'build', + 'sh' : 'shell', + } + + def __init__(self, **kw): + cmd.Cmd.__init__(self) + for key, val in kw.items(): + setattr(self, key, val) + + if sys.platform == 'win32': + self.shell_variable = 'COMSPEC' + else: + self.shell_variable = 'SHELL' + + def default(self, argv): + print "*** Unknown command: %s" % argv[0] + + def onecmd(self, line): + line = string.strip(line) + if not line: + print self.lastcmd + return self.emptyline() + self.lastcmd = line + if line[0] == '!': + line = 'shell ' + line[1:] + elif line[0] == '?': + line = 'help ' + line[1:] + if os.sep == '\\': + line = string.replace(line, '\\', '\\\\') + argv = shlex.split(line) + argv[0] = self.synonyms.get(argv[0], argv[0]) + if not argv[0]: + return self.default(line) + else: + try: + func = getattr(self, 'do_' + argv[0]) + except AttributeError: + return self.default(argv) + return func(argv) + + def do_build(self, argv): + """\ + build [TARGETS] Build the specified TARGETS and their + dependencies. 'b' is a synonym. + """ + import SCons.Node + import SCons.SConsign + import SCons.Script.Main + + options = copy.deepcopy(self.options) + + options, targets = self.parser.parse_args(argv[1:], values=options) + + SCons.Script.COMMAND_LINE_TARGETS = targets + + if targets: + SCons.Script.BUILD_TARGETS = targets + else: + # If the user didn't specify any targets on the command line, + # use the list of default targets. + SCons.Script.BUILD_TARGETS = SCons.Script._build_plus_default + + nodes = SCons.Script.Main._build_targets(self.fs, + options, + targets, + self.target_top) + + if not nodes: + return + + # Call each of the Node's alter_targets() methods, which may + # provide additional targets that ended up as part of the build + # (the canonical example being a VariantDir() when we're building + # from a source directory) and which we therefore need their + # state cleared, too. + x = [] + for n in nodes: + x.extend(n.alter_targets()[0]) + nodes.extend(x) + + # Clean up so that we can perform the next build correctly. + # + # We do this by walking over all the children of the targets, + # and clearing their state. + # + # We currently have to re-scan each node to find their + # children, because built nodes have already been partially + # cleared and don't remember their children. (In scons + # 0.96.1 and earlier, this wasn't the case, and we didn't + # have to re-scan the nodes.) + # + # Because we have to re-scan each node, we can't clear the + # nodes as we walk over them, because we may end up rescanning + # a cleared node as we scan a later node. Therefore, only + # store the list of nodes that need to be cleared as we walk + # the tree, and clear them in a separate pass. + # + # XXX: Someone more familiar with the inner workings of scons + # may be able to point out a more efficient way to do this. + + SCons.Script.Main.progress_display("scons: Clearing cached node information ...") + + seen_nodes = {} + + def get_unseen_children(node, parent, seen_nodes=seen_nodes): + def is_unseen(node, seen_nodes=seen_nodes): + return not seen_nodes.has_key(node) + return filter(is_unseen, node.children(scan=1)) + + def add_to_seen_nodes(node, parent, seen_nodes=seen_nodes): + seen_nodes[node] = 1 + + # If this file is in a VariantDir and has a + # corresponding source file in the source tree, remember the + # node in the source tree, too. This is needed in + # particular to clear cached implicit dependencies on the + # source file, since the scanner will scan it if the + # VariantDir was created with duplicate=0. + try: + rfile_method = node.rfile + except AttributeError: + return + else: + rfile = rfile_method() + if rfile != node: + seen_nodes[rfile] = 1 + + for node in nodes: + walker = SCons.Node.Walker(node, + kids_func=get_unseen_children, + eval_func=add_to_seen_nodes) + n = walker.next() + while n: + n = walker.next() + + for node in seen_nodes.keys(): + # Call node.clear() to clear most of the state + node.clear() + # node.clear() doesn't reset node.state, so call + # node.set_state() to reset it manually + node.set_state(SCons.Node.no_state) + node.implicit = None + + # Debug: Uncomment to verify that all Taskmaster reference + # counts have been reset to zero. + #if node.ref_count != 0: + # from SCons.Debug import Trace + # Trace('node %s, ref_count %s !!!\n' % (node, node.ref_count)) + + SCons.SConsign.Reset() + SCons.Script.Main.progress_display("scons: done clearing node information.") + + def do_clean(self, argv): + """\ + clean [TARGETS] Clean (remove) the specified TARGETS + and their dependencies. 'c' is a synonym. + """ + return self.do_build(['build', '--clean'] + argv[1:]) + + def do_EOF(self, argv): + print + self.do_exit(argv) + + def _do_one_help(self, arg): + try: + # If help_() exists, then call it. + func = getattr(self, 'help_' + arg) + except AttributeError: + try: + func = getattr(self, 'do_' + arg) + except AttributeError: + doc = None + else: + doc = self._doc_to_help(func) + if doc: + sys.stdout.write(doc + '\n') + sys.stdout.flush() + else: + doc = self.strip_initial_spaces(func()) + if doc: + sys.stdout.write(doc + '\n') + sys.stdout.flush() + + def _doc_to_help(self, obj): + doc = obj.__doc__ + if doc is None: + return '' + return self._strip_initial_spaces(doc) + + def _strip_initial_spaces(self, s): + #lines = s.split('\n') + lines = string.split(s, '\n') + spaces = re.match(' *', lines[0]).group(0) + #def strip_spaces(l): + # if l.startswith(spaces): + # l = l[len(spaces):] + # return l + #return '\n'.join([ strip_spaces(l) for l in lines ]) + def strip_spaces(l, spaces=spaces): + if l[:len(spaces)] == spaces: + l = l[len(spaces):] + return l + lines = map(strip_spaces, lines) + return string.join(lines, '\n') + + def do_exit(self, argv): + """\ + exit Exit SCons interactive mode. + """ + sys.exit(0) + + def do_help(self, argv): + """\ + help [COMMAND] Prints help for the specified COMMAND. 'h' + and '?' are synonyms. + """ + if argv[1:]: + for arg in argv[1:]: + if self._do_one_help(arg): + break + else: + # If bare 'help' is called, print this class's doc + # string (if it has one). + doc = self._doc_to_help(self.__class__) + if doc: + sys.stdout.write(doc + '\n') + sys.stdout.flush() + + def do_shell(self, argv): + """\ + shell [COMMANDLINE] Execute COMMANDLINE in a subshell. 'sh' and + '!' are synonyms. + """ + import subprocess + argv = argv[1:] + if not argv: + argv = os.environ[self.shell_variable] + try: + p = subprocess.Popen(argv) + except EnvironmentError, e: + sys.stderr.write('scons: %s: %s\n' % (argv[0], e.strerror)) + else: + p.wait() + + def do_version(self, argv): + """\ + version Prints SCons version information. + """ + sys.stdout.write(self.parser.version + '\n') + +def interact(fs, parser, options, targets, target_top): + c = SConsInteractiveCmd(prompt = 'scons>>> ', + fs = fs, + parser = parser, + options = options, + targets = targets, + target_top = target_top) + c.cmdloop() diff --git a/scons/scons-local-0.97.0d20071212/SCons/Script/Main.py b/scons/scons-local-1.2.0/SCons/Script/Main.py similarity index 80% rename from scons/scons-local-0.97.0d20071212/SCons/Script/Main.py rename to scons/scons-local-1.2.0/SCons/Script/Main.py index 764cba67c3..5624038c08 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Script/Main.py +++ b/scons/scons-local-1.2.0/SCons/Script/Main.py @@ -12,7 +12,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -34,9 +34,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Script/Main.py 2523 2007/12/12 09:37:41 knight" - -import SCons.compat +__revision__ = "src/engine/SCons/Script/Main.py 3842 2008/12/20 22:59:52 scons" import os import os.path @@ -68,6 +66,18 @@ import SCons.Util import SCons.Warnings +import SCons.Script.Interactive + +def fetch_win32_parallel_msg(): + # A subsidiary function that exists solely to isolate this import + # so we don't have to pull it in on all platforms, and so that an + # in-line "import" statement in the _main() function below doesn't + # cause warnings about local names shadowing use of the 'SCons' + # globl in nest scopes and UnboundLocalErrors and the like in some + # versions (2.1) of Python. + import SCons.Platform.win32 + return SCons.Platform.win32.parallel_msg + # class SConsPrintHelpException(Exception): @@ -156,49 +166,60 @@ def prepare(self): self.progress(self.targets[0]) return SCons.Taskmaster.Task.prepare(self) - def execute(self): - for target in self.targets: - if target.get_state() == SCons.Node.up_to_date: - continue - if target.has_builder() and not hasattr(target.builder, 'status'): - if print_time: - start_time = time.time() - global first_command_start - if first_command_start is None: - first_command_start = start_time - SCons.Taskmaster.Task.execute(self) - if print_time: - global cumulative_command_time - global last_command_end - finish_time = time.time() - last_command_end = finish_time - cumulative_command_time = cumulative_command_time+finish_time-start_time - sys.stdout.write("Command execution time: %f seconds\n"%(finish_time-start_time)) - break + def needs_execute(self): + target = self.targets[0] + if target.get_state() == SCons.Node.executing: + return True else: if self.top and target.has_builder(): display("scons: `%s' is up to date." % str(self.node)) + return False + + def execute(self): + if print_time: + start_time = time.time() + global first_command_start + if first_command_start is None: + first_command_start = start_time + SCons.Taskmaster.Task.execute(self) + if print_time: + global cumulative_command_time + global last_command_end + finish_time = time.time() + last_command_end = finish_time + cumulative_command_time = cumulative_command_time+finish_time-start_time + sys.stdout.write("Command execution time: %f seconds\n"%(finish_time-start_time)) def do_failed(self, status=2): _BuildFailures.append(self.exception[1]) global exit_status + global this_build_status if self.options.ignore_errors: SCons.Taskmaster.Task.executed(self) elif self.options.keep_going: SCons.Taskmaster.Task.fail_continue(self) exit_status = status + this_build_status = status else: SCons.Taskmaster.Task.fail_stop(self) exit_status = status + this_build_status = status def executed(self): t = self.targets[0] if self.top and not t.has_builder() and not t.side_effect: if not t.exists(): - sys.stderr.write("scons: *** Do not know how to make target `%s'." % t) + errstr="Do not know how to make target `%s'." % t + sys.stderr.write("scons: *** " + errstr) if not self.options.keep_going: sys.stderr.write(" Stop.") sys.stderr.write("\n") + try: + raise SCons.Errors.BuildError(t, errstr) + except KeyboardInterrupt: + raise + except: + self.exception_set() self.do_failed() else: print "scons: Nothing to be done for `%s'." % t @@ -210,54 +231,55 @@ def failed(self): # Handle the failure of a build task. The primary purpose here # is to display the various types of Errors and Exceptions # appropriately. - status = 2 exc_info = self.exc_info() try: t, e, tb = exc_info except ValueError: t, e = exc_info tb = None + if t is None: # The Taskmaster didn't record an exception for this Task; # see if the sys module has one. - t, e = sys.exc_info()[:2] - - def nodestring(n): - if not SCons.Util.is_List(n): - n = [ n ] - return string.join(map(str, n), ', ') + try: + t, e, tb = sys.exc_info()[:] + except ValueError: + t, e = exc_info + tb = None + + # Deprecated string exceptions will have their string stored + # in the first entry of the tuple. + if e is None: + e = t + + buildError = SCons.Errors.convert_to_BuildError(e) + if not buildError.node: + buildError.node = self.node + + node = buildError.node + if not SCons.Util.is_List(node): + node = [ node ] + nodename = string.join(map(str, node), ', ') errfmt = "scons: *** [%s] %s\n" - - if t == SCons.Errors.BuildError: - tname = nodestring(e.node) - errstr = e.errstr - if e.filename: - errstr = e.filename + ': ' + errstr - sys.stderr.write(errfmt % (tname, errstr)) - elif t == SCons.Errors.TaskmasterException: - tname = nodestring(e.node) - sys.stderr.write(errfmt % (tname, e.errstr)) - type, value, trace = e.exc_info + sys.stderr.write(errfmt % (nodename, buildError)) + + if (buildError.exc_info[2] and buildError.exc_info[1] and + # TODO(1.5) + #not isinstance( + # buildError.exc_info[1], + # (EnvironmentError, SCons.Errors.StopError, SCons.Errors.UserError))): + not isinstance(buildError.exc_info[1], EnvironmentError) and + not isinstance(buildError.exc_info[1], SCons.Errors.StopError) and + not isinstance(buildError.exc_info[1], SCons.Errors.UserError)): + type, value, trace = buildError.exc_info traceback.print_exception(type, value, trace) - elif t == SCons.Errors.ExplicitExit: - status = e.status - tname = nodestring(e.node) - errstr = 'Explicit exit, status %s' % status - sys.stderr.write(errfmt % (tname, errstr)) - else: - if e is None: - e = t - s = str(e) - if t == SCons.Errors.StopError and not self.options.keep_going: - s = s + ' Stop.' - sys.stderr.write("scons: *** %s\n" % s) - - if tb and print_stacktrace: - sys.stderr.write("scons: internal stack trace:\n") - traceback.print_tb(tb, file=sys.stderr) + elif tb and print_stacktrace: + sys.stderr.write("scons: internal stack trace:\n") + traceback.print_tb(tb, file=sys.stderr) - self.do_failed(status) + self.exception = (e, buildError, tb) # type, value, traceback + self.do_failed(buildError.exitstatus) self.exc_clear() @@ -366,7 +388,9 @@ def execute(self): if self.targets[0].get_state() != SCons.Node.up_to_date or \ (self.top and not self.targets[0].exists()): global exit_status + global this_build_status exit_status = 1 + this_build_status = 1 self.tm.stop() def executed(self): @@ -392,6 +416,16 @@ def display(self, t): SCons.Util.print_tree(t, func, prune=self.prune, showtags=s) +def python_version_string(): + return string.split(sys.version)[0] + +def python_version_unsupported(version=sys.version_info): + return version < (1, 5, 2) + +def python_version_deprecated(version=sys.version_info): + return version < (2, 2, 0) + + # Global variables print_objects = 0 @@ -400,7 +434,8 @@ def display(self, t): print_time = 0 sconscript_time = 0 cumulative_command_time = 0 -exit_status = 0 # exit status, assume success by default +exit_status = 0 # final exit status, assume success by default +this_build_status = 0 # "exit status" of an individual build num_jobs = None delayed_warnings = [] @@ -566,57 +601,14 @@ def _scons_internal_error(): traceback.print_exc() sys.exit(2) -def _setup_warn(arg): - """The --warn option. An argument to this option - should be of the form or no-. - The warning class is munged in order to get an actual class - name from the SCons.Warnings module to enable or disable. - The supplied is split on hyphens, each element - is captialized, then smushed back together. Then the string - "SCons.Warnings." is added to the front and "Warning" is added - to the back to get the fully qualified class name. - - For example, --warn=deprecated will enable the - SCons.Warnings.DeprecatedWarning class. - - --warn=no-dependency will disable the - SCons.Warnings.DependencyWarning class. - - As a special case, --warn=all and --warn=no-all - will enable or disable (respectively) the base - class of all warnings, which is SCons.Warning.Warning.""" - - elems = string.split(string.lower(arg), '-') - enable = 1 - if elems[0] == 'no': - enable = 0 - del elems[0] - - if len(elems) == 1 and elems[0] == 'all': - class_name = "Warning" - else: - def _capitalize(s): - if s[:5] == "scons": - return "SCons" + s[5:] - else: - return string.capitalize(s) - class_name = string.join(map(_capitalize, elems), '') + "Warning" - try: - clazz = getattr(SCons.Warnings, class_name) - except AttributeError: - sys.stderr.write("No warning type: '%s'\n" % arg) - else: - if enable: - SCons.Warnings.enableWarningClass(clazz) - else: - SCons.Warnings.suppressWarningClass(clazz) - -def _SConstruct_exists(dirname='', repositories=[]): +def _SConstruct_exists(dirname='', repositories=[], filelist=None): """This function checks that an SConstruct file exists in a directory. If so, it returns the path of the file. By default, it checks the current directory. """ - for file in ['SConstruct', 'Sconstruct', 'sconstruct']: + if not filelist: + filelist = ['SConstruct', 'Sconstruct', 'sconstruct'] + for file in filelist: sfile = os.path.join(dirname, file) if os.path.isfile(sfile): return sfile @@ -730,8 +722,8 @@ def version_string(label, module): module.__buildsys__) def _main(parser): - import SCons global exit_status + global this_build_status options = parser.values @@ -745,17 +737,22 @@ def _main(parser): default_warnings = [ SCons.Warnings.CorruptSConsignWarning, SCons.Warnings.DeprecatedWarning, SCons.Warnings.DuplicateEnvironmentWarning, + SCons.Warnings.FutureReservedVariableWarning, + SCons.Warnings.LinkWarning, SCons.Warnings.MissingSConscriptWarning, SCons.Warnings.NoMD5ModuleWarning, SCons.Warnings.NoMetaclassSupportWarning, SCons.Warnings.NoObjectCountWarning, SCons.Warnings.NoParallelSupportWarning, - SCons.Warnings.MisleadingKeywordsWarning, ] + SCons.Warnings.MisleadingKeywordsWarning, + SCons.Warnings.ReservedVariableWarning, + SCons.Warnings.StackSizeWarning, + ] + for warning in default_warnings: SCons.Warnings.enableWarningClass(warning) SCons.Warnings._warningOut = _scons_internal_warning - if options.warn: - _setup_warn(options.warn) + SCons.Warnings.process_warn_strings(options.warn) # Now that we have the warnings configuration set up, we can actually # issue (or suppress) any warnings about warning-worthy things that @@ -788,13 +785,15 @@ def _main(parser): if options.climb_up: target_top = '.' # directory to prepend to targets script_dir = os.getcwd() # location of script - while script_dir and not _SConstruct_exists(script_dir, options.repository): + while script_dir and not _SConstruct_exists(script_dir, + options.repository, + options.file): script_dir, last_part = os.path.split(script_dir) if last_part: target_top = os.path.join(last_part, target_top) else: script_dir = '' - if script_dir: + if script_dir and script_dir != os.getcwd(): display("scons: Entering directory `%s'" % script_dir) os.chdir(script_dir) @@ -813,7 +812,8 @@ def _main(parser): if options.file: scripts.extend(options.file) if not scripts: - sfile = _SConstruct_exists(repositories=options.repository) + sfile = _SConstruct_exists(repositories=options.repository, + filelist=options.file) if sfile: scripts.append(sfile) @@ -835,10 +835,10 @@ def _main(parser): SCons.Node.implicit_cache = options.implicit_cache SCons.Node.implicit_deps_changed = options.implicit_deps_changed SCons.Node.implicit_deps_unchanged = options.implicit_deps_unchanged + if options.no_exec: SCons.SConf.dryrun = 1 SCons.Action.execute_actions = None - CleanTask.execute = CleanTask.show if options.question: SCons.SConf.dryrun = 1 if options.clean: @@ -850,19 +850,6 @@ def _main(parser): if options.no_progress or options.silent: progress_display.set_mode(0) - if options.silent: - display.set_mode(0) - if options.silent: - SCons.Action.print_actions = None - - if options.cache_disable: - SCons.CacheDir.CacheDir = SCons.Util.Null() - if options.cache_debug: - SCons.CacheDir.cache_debug = options.cache_debug - if options.cache_force: - SCons.CacheDir.cache_force = True - if options.cache_show: - SCons.CacheDir.cache_show = True if options.site_dir: _load_site_scons_dir(d, options.site_dir) @@ -887,7 +874,18 @@ def _main(parser): SCons.Script._Add_Targets(targets + parser.rargs) SCons.Script._Add_Arguments(xmit_args) - sys.stdout = SCons.Util.Unbuffered(sys.stdout) + # If stdout is not a tty, replace it with a wrapper object to call flush + # after every write. + # + # Tty devices automatically flush after every newline, so the replacement + # isn't necessary. Furthermore, if we replace sys.stdout, the readline + # module will no longer work. This affects the behavior during + # --interactive mode. --interactive should only be used when stdin and + # stdout refer to a tty. + if not sys.stdout.isatty(): + sys.stdout = SCons.Util.Unbuffered(sys.stdout) + if not sys.stderr.isatty(): + sys.stderr = SCons.Util.Unbuffered(sys.stderr) memory_stats.append('before reading SConscript files:') count_stats.append(('pre-', 'read')) @@ -902,7 +900,7 @@ def _main(parser): SCons.Script._SConscript._SConscript(fs, script) except SCons.Errors.StopError, e: # We had problems reading an SConscript file, such as it - # couldn't be copied in to the BuildDir. Since we're just + # couldn't be copied in to the VariantDir. Since we're just # reading SConscript files and haven't started building # things yet, stop regardless of whether they used -i or -k # or anything else. @@ -917,6 +915,26 @@ def _main(parser): memory_stats.append('after reading SConscript files:') count_stats.append(('post-', 'read')) + # Re-{enable,disable} warnings in case they disabled some in + # the SConscript file. + # + # We delay enabling the PythonVersionWarning class until here so that, + # if they explicity disabled it in either in the command line or in + # $SCONSFLAGS, or in the SConscript file, then the search through + # the list of deprecated warning classes will find that disabling + # first and not issue the warning. + SCons.Warnings.enableWarningClass(SCons.Warnings.PythonVersionWarning) + SCons.Warnings.process_warn_strings(options.warn) + + # Now that we've read the SConscript files, we can check for the + # warning about deprecated Python versions--delayed until here + # in case they disabled the warning in the SConscript files. + if python_version_deprecated(): + msg = "Support for pre-2.2 Python (%s) is deprecated.\n" + \ + " If this will cause hardship, contact dev@scons.tigris.org." + SCons.Warnings.warn(SCons.Warnings.PythonVersionWarning, + msg % python_version_string()) + if not options.help: SCons.SConf.CreateConfigHBuilder(SCons.Defaults.DefaultEnvironment()) @@ -943,7 +961,7 @@ def _main(parser): # Change directory to the top-level SConstruct directory, then tell # the Node.FS subsystem that we're all done reading the SConscript - # files and calling Repository() and BuildDir() and changing + # files and calling Repository() and VariantDir() and changing # directories and the like, so it can go ahead and start memoizing # the string values of file system nodes. @@ -957,6 +975,49 @@ def _main(parser): SCons.Node.FS.set_duplicate(options.duplicate) fs.set_max_drift(options.max_drift) + SCons.Job.explicit_stack_size = options.stack_size + + if options.md5_chunksize: + SCons.Node.FS.File.md5_chunksize = options.md5_chunksize + + platform = SCons.Platform.platform_module() + + if options.interactive: + SCons.Script.Interactive.interact(fs, OptionsParser, options, + targets, target_top) + + else: + + # Build the targets + nodes = _build_targets(fs, options, targets, target_top) + if not nodes: + exit_status = 2 + +def _build_targets(fs, options, targets, target_top): + + global this_build_status + this_build_status = 0 + + progress_display.set_mode(not (options.no_progress or options.silent)) + display.set_mode(not options.silent) + SCons.Action.print_actions = not options.silent + SCons.Action.execute_actions = not options.no_exec + SCons.Node.FS.do_store_info = not options.no_exec + SCons.SConf.dryrun = options.no_exec + + if options.diskcheck: + SCons.Node.FS.set_diskcheck(options.diskcheck) + + SCons.CacheDir.cache_enabled = not options.cache_disable + SCons.CacheDir.cache_debug = options.cache_debug + SCons.CacheDir.cache_force = options.cache_force + SCons.CacheDir.cache_show = options.cache_show + + if options.no_exec: + CleanTask.execute = CleanTask.show + else: + CleanTask.execute = CleanTask.remove + lookup_top = None if targets or SCons.Script.BUILD_TARGETS != SCons.Script._build_plus_default: # They specified targets on the command line or modified @@ -1003,7 +1064,7 @@ def check_dir(x, target_top=target_top): if not targets: sys.stderr.write("scons: *** No targets specified and no Default() targets found. Stop.\n") - sys.exit(2) + return None def Entry(x, ltop=lookup_top, ttop=target_top, fs=fs): if isinstance(x, SCons.Node.Node): @@ -1046,7 +1107,7 @@ def Entry(x, ltop=lookup_top, ttop=target_top, fs=fs): opening_message = "Cleaning targets ..." closing_message = "done cleaning targets." if options.keep_going: - closing_message = "done cleaning targets (errors occurred during clean)." + failure_message = "done cleaning targets (errors occurred during clean)." else: failure_message = "cleaning terminated because of errors." except AttributeError: @@ -1091,29 +1152,43 @@ def order(dependencies): msg = "parallel builds are unsupported by this version of Python;\n" + \ "\tignoring -j or num_jobs option.\n" elif sys.platform == 'win32': - import SCons.Platform.win32 - msg = SCons.Platform.win32.parallel_msg + msg = fetch_win32_parallel_msg() if msg: SCons.Warnings.warn(SCons.Warnings.NoParallelSupportWarning, msg) memory_stats.append('before building targets:') count_stats.append(('pre-', 'build')) - try: - progress_display("scons: " + opening_message) - jobs.run() - finally: - jobs.cleanup() - if exit_status: + def jobs_postfunc( + jobs=jobs, + options=options, + closing_message=closing_message, + failure_message=failure_message + ): + if jobs.were_interrupted(): + progress_display("scons: Build interrupted.") + global exit_status + global this_build_status + exit_status = 2 + this_build_status = 2 + + if this_build_status: progress_display("scons: " + failure_message) else: progress_display("scons: " + closing_message) if not options.no_exec: + if jobs.were_interrupted(): + progress_display("scons: writing .sconsign file.") SCons.SConsign.write() + progress_display("scons: " + opening_message) + jobs.run(postfunc = jobs_postfunc) + memory_stats.append('after building targets:') count_stats.append(('post-', 'build')) + return nodes + def _exec_main(parser, values): sconsflags = os.environ.get('SCONSFLAGS', '') all_args = string.split(sconsflags) + sys.argv[1:] @@ -1124,7 +1199,10 @@ def _exec_main(parser, values): import pdb pdb.Pdb().runcall(_main, parser) elif options.profile_file: - from profile import Profile + try: + from cProfile import Profile + except ImportError, e: + from profile import Profile # Some versions of Python 2.4 shipped a profiler that had the # wrong 'c_exception' entry in its dispatch table. Make sure @@ -1155,17 +1233,25 @@ def main(): global exit_status global first_command_start + # Check up front for a Python version we do not support. We + # delay the check for deprecated Python versions until later, + # after the SConscript files have been read, in case they + # disable that warning. + if python_version_unsupported(): + msg = "scons: *** SCons version %s does not run under Python version %s.\n" + sys.stderr.write(msg % (SCons.__version__, python_version_string())) + sys.exit(1) + parts = ["SCons by Steven Knight et al.:\n"] try: + import __main__ parts.append(version_string("script", __main__)) - except KeyboardInterrupt: - raise - except: + except (ImportError, AttributeError): # On Windows there is no scons.py, so there is no # __main__.__version__, hence there is no script version. pass parts.append(version_string("engine", SCons)) - parts.append("Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation") + parts.append("Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation") version = string.join(parts, '') import SConsOptions @@ -1180,7 +1266,7 @@ def main(): if s: exit_status = s except KeyboardInterrupt: - print "Build interrupted." + print("scons: Build interrupted.") sys.exit(2) except SyntaxError, e: _scons_syntax_error(e) @@ -1191,6 +1277,8 @@ def main(): except SConsPrintHelpException: parser.print_help() exit_status = 0 + except SCons.Errors.BuildError, e: + exit_status = e.exitstatus except: # An exception here is likely a builtin Python exception Python # code in an SConscript file. Show them precisely what the diff --git a/scons/scons-local-0.97.0d20071212/SCons/Script/SConsOptions.py b/scons/scons-local-1.2.0/SCons/Script/SConsOptions.py similarity index 87% rename from scons/scons-local-0.97.0d20071212/SCons/Script/SConsOptions.py rename to scons/scons-local-1.2.0/SCons/Script/SConsOptions.py index d466d43d81..636fd2024e 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Script/SConsOptions.py +++ b/scons/scons-local-1.2.0/SCons/Script/SConsOptions.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,15 +21,21 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Script/SConsOptions.py 2523 2007/12/12 09:37:41 knight" - -import SCons.compat +__revision__ = "src/engine/SCons/Script/SConsOptions.py 3842 2008/12/20 22:59:52 scons" import optparse +import re import string import sys import textwrap +try: + no_hyphen_re = re.compile(r'(\s+|(?<=[\w\!\"\'\&\.\,\?])-{2,}(?=\w))') +except re.error: + # Pre-2.0 Python versions don't have the (?<= negative + # look-behind assertion. + no_hyphen_re = re.compile(r'(\s+|-*\w{2,}-(?=\w{2,}))') + try: from gettext import gettext except ImportError: @@ -38,6 +44,7 @@ def gettext(message): _ = gettext import SCons.Node.FS +import SCons.Warnings OptionValueError = optparse.OptionValueError SUPPRESS_HELP = optparse.SUPPRESS_HELP @@ -119,9 +126,12 @@ def __getattr__(self, attr): 'help', 'implicit_cache', 'max_drift', + 'md5_chunksize', 'no_exec', 'num_jobs', 'random', + 'stack_size', + 'warn', ] def set_option(self, name, value): @@ -163,6 +173,21 @@ def set_option(self, name, value): # Set this right away so it can affect the rest of the # file/Node lookups while processing the SConscript files. SCons.Node.FS.set_diskcheck(value) + elif name == 'stack_size': + try: + value = int(value) + except ValueError: + raise SCons.Errors.UserError, "An integer is required: %s"%repr(value) + elif name == 'md5_chunksize': + try: + value = int(value) + except ValueError: + raise SCons.Errors.UserError, "An integer is required: %s"%repr(value) + elif name == 'warn': + if SCons.Util.is_String(value): + value = [value] + value = self.__SConscript_settings__.get(name, []) + value + SCons.Warnings.process_warn_strings(value) self.__SConscript_settings__[name] = value @@ -369,8 +394,16 @@ def format_heading(self, heading): def format_option(self, option): """ A copy of the normal optparse.IndentedHelpFormatter.format_option() - method, snarfed so we can set the subsequent_indent on the - textwrap.wrap() call below... + method. This has been snarfed so we can modify text wrapping to + out liking: + + -- add our own regular expression that doesn't break on hyphens + (so things like --no-print-directory don't get broken); + + -- wrap the list of options themselves when it's too long + (the wrapper.fill(opts) call below); + + -- set the subsequent_indent when wrapping the help_text. """ # The help for each option consists of two parts: # * the opt strings and metavars @@ -397,7 +430,11 @@ def format_option(self, option): opt_width = self.help_position - self.current_indent - 2 if len(opts) > opt_width: - opts = "%*s%s\n" % (self.current_indent, "", opts) + wrapper = textwrap.TextWrapper(width=self.width, + initial_indent = ' ', + subsequent_indent = ' ') + wrapper.wordsep_re = no_hyphen_re + opts = wrapper.fill(opts) + '\n' indent_first = self.help_position else: # start help on same line as opts opts = "%*s%-*s " % (self.current_indent, "", opt_width, opts) @@ -415,8 +452,10 @@ def format_option(self, option): help_text = expand_default(option) # SCons: indent every line of the help text but the first. - help_lines = textwrap.wrap(help_text, self.help_width, - subsequent_indent = ' ') + wrapper = textwrap.TextWrapper(width=self.help_width, + subsequent_indent = ' ') + wrapper.wordsep_re = no_hyphen_re + help_lines = wrapper.wrap(help_text) result.append("%*s%s\n" % (indent_first, "", help_lines[0])) for line in help_lines[1:]: result.append("%*s%s\n" % (self.help_position, "", line)) @@ -466,6 +505,7 @@ def Parser(version): usage="usage: scons [OPTION] [TARGET] ...",) op.preserve_unknown_options = True + op.version = version # Add the options to the parser we just created. # @@ -489,8 +529,13 @@ def Parser(version): # options ignored for compatibility def opt_ignore(option, opt, value, parser): sys.stderr.write("Warning: ignoring %s option\n" % opt) - op.add_option("-b", "-m", "-S", "-t", - "--no-keep-going", "--stop", "--touch", + op.add_option("-b", "-d", "-e", "-m", "-S", "-t", "-w", + "--environment-overrides", + "--no-keep-going", + "--no-print-directory", + "--print-directory", + "--stop", + "--touch", action="callback", callback=opt_ignore, help="Ignored for compatibility.") @@ -543,42 +588,38 @@ def opt_config(option, opt, value, parser, c_options=config_options): help = opt_config_help, metavar="MODE") - def opt_not_yet(option, opt, value, parser): - sys.stderr.write("Warning: the %s option is not yet implemented\n" % opt) - sys.exit(0) - op.add_option('-d', - action="callback", callback=opt_not_yet, - help = "Print file dependency information.") - op.add_option('-D', dest="climb_up", default=None, action="store_const", const=2, help="Search up directory tree for SConstruct, " "build all Default() targets.") - debug_options = ["count", "dtree", "explain", "findlibs", - "includes", "memoizer", "memory", "objects", - "pdb", "presub", "stacktrace", "stree", - "time", "tree"] - deprecated_debug_options = { - "nomemoizer" : ' and has no effect', + "dtree" : '; please use --tree=derived instead', + "nomemoizer" : ' and has no effect', + "stree" : '; please use --tree=all,status instead', + "tree" : '; please use --tree=all instead', } + debug_options = ["count", "explain", "findlibs", + "includes", "memoizer", "memory", "objects", + "pdb", "presub", "stacktrace", + "time"] + deprecated_debug_options.keys() + def opt_debug(option, opt, value, parser, debug_options=debug_options, deprecated_debug_options=deprecated_debug_options): if value in debug_options: parser.values.debug.append(value) - elif value in deprecated_debug_options.keys(): - try: - parser.values.delayed_warnings - except AttributeError: - parser.values.delayed_warnings = [] - msg = deprecated_debug_options[value] - w = "The --debug=%s option is deprecated%s." % (value, msg) - t = (SCons.Warnings.DeprecatedWarning, w) - parser.values.delayed_warnings.append(t) + if value in deprecated_debug_options.keys(): + try: + parser.values.delayed_warnings + except AttributeError: + parser.values.delayed_warnings = [] + msg = deprecated_debug_options[value] + w = "The --debug=%s option is deprecated%s." % (value, msg) + t = (SCons.Warnings.DeprecatedWarning, w) + parser.values.delayed_warnings.append(t) else: raise OptionValueError("Warning: %s is not a valid debug type" % value) opt_debug_help = "Print various types of debugging information: %s." \ @@ -667,6 +708,11 @@ def opt_implicit_deps(option, opt, value, parser): action="callback", callback=opt_implicit_deps, help="Ignore changes in implicit dependencies.") + op.add_option('--interact', '--interactive', + dest='interactive', default=False, + action="store_true", + help="Run in interactive mode.") + op.add_option('-j', '--jobs', nargs=1, type="int", dest="num_jobs", default=1, @@ -686,6 +732,13 @@ def opt_implicit_deps(option, opt, value, parser): help="Set maximum system clock drift to N seconds.", metavar="N") + op.add_option('--md5-chunksize', + nargs=1, type="int", + dest='md5_chunksize', default=SCons.Node.FS.File.md5_chunksize, + action="store", + help="Set chunk-size for MD5 signature computation to N kilobytes.", + metavar="N") + op.add_option('-n', '--no-exec', '--just-print', '--dry-run', '--recon', dest='no_exec', default=False, action="store_true", @@ -730,6 +783,13 @@ def opt_implicit_deps(option, opt, value, parser): help="Use DIR instead of the usual site_scons dir.", metavar="DIR") + op.add_option('--stack-size', + nargs=1, type="int", + dest='stack_size', + action="store", + help="Set the stack size of the threads used to run jobs to N kilobytes.", + metavar="N") + op.add_option('--taskmastertrace', nargs=1, dest="taskmastertrace_file", default=None, @@ -777,17 +837,22 @@ def opt_tree(option, opt, value, parser, tree_options=tree_options): help="Search up directory tree for SConstruct, " "build Default() targets from local SConscript.") - def opt_version(option, opt, value, parser, version=version): - sys.stdout.write(version + '\n') + def opt_version(option, opt, value, parser): + sys.stdout.write(parser.version + '\n') sys.exit(0) op.add_option("-v", "--version", action="callback", callback=opt_version, help="Print the SCons version number and exit.") + def opt_warn(option, opt, value, parser, tree_options=tree_options): + if SCons.Util.is_String(value): + value = string.split(value, ',') + parser.values.warn.extend(value) + op.add_option('--warn', '--warning', - nargs=1, - dest="warn", default=None, - action="store", + nargs=1, type="string", + dest="warn", default=[], + action="callback", callback=opt_warn, help="Enable or disable warnings.", metavar="WARNING-SPEC") @@ -802,11 +867,12 @@ def opt_version(option, opt, value, parser, version=version): # we don't want to change. These all get a "the -X option is not # yet implemented" message and don't show up in the help output. - op.add_option('-e', '--environment-overrides', - dest="environment_overrides", - action="callback", callback=opt_not_yet, - # help="Environment variables override makefiles." - help=SUPPRESS_HELP) + def opt_not_yet(option, opt, value, parser): + msg = "Warning: the %s option is not yet implemented\n" % opt + sys.stderr.write(msg) + sys.exit(0) + + op.add_option('-l', '--load-average', '--max-load', nargs=1, type="int", dest="load_average", default=0, @@ -853,16 +919,6 @@ def opt_version(option, opt, value, parser, version=version): dest="no_builtin_rules", # help="Clear default environments and variables." help=SUPPRESS_HELP) - op.add_option('-w', '--print-directory', - action="callback", callback=opt_not_yet, - dest="print_directory", - # help="Print the current directory." - help=SUPPRESS_HELP) - op.add_option('--no-print-directory', - action="callback", callback=opt_not_yet, - dest="no_print_directory", - # help="Turn off -w, even if it was turned on implicitly." - help=SUPPRESS_HELP) op.add_option('--write-filenames', nargs=1, type="string", dest="write_filenames", diff --git a/scons/scons-local-0.97.0d20071212/SCons/Script/SConscript.py b/scons/scons-local-1.2.0/SCons/Script/SConscript.py similarity index 93% rename from scons/scons-local-0.97.0d20071212/SCons/Script/SConscript.py rename to scons/scons-local-1.2.0/SCons/Script/SConscript.py index 42350d384e..c52c9798a5 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Script/SConscript.py +++ b/scons/scons-local-1.2.0/SCons/Script/SConscript.py @@ -6,7 +6,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -28,7 +28,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Script/SConscript.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Script/SConscript.py 3842 2008/12/20 22:59:52 scons" import SCons import SCons.Action @@ -39,7 +39,6 @@ import SCons.Node import SCons.Node.Alias import SCons.Node.FS -import SCons.Options import SCons.Platform import SCons.SConf import SCons.Script.Main @@ -82,7 +81,10 @@ def get_calling_namespaces(): """Return the locals and globals for the function that called into this module in the current call stack.""" try: 1/0 - except ZeroDivisionError: frame = sys.exc_info()[2].tb_frame + except ZeroDivisionError: + # Don't start iterating with the current stack-frame to + # prevent creating reference cycles (f_back is safe). + frame = sys.exc_info()[2].tb_frame.f_back # Find the first frame that *isn't* from this file. This means # that we expect all of the SCons frames that implement an Export() @@ -141,7 +143,8 @@ def __init__(self, fs, exports, sconscript): def Return(*vars, **kw): retval = [] try: - for var in vars: + fvars = SCons.Util.flatten(vars) + for var in fvars: for v in string.split(var): retval.append(call_stack[-1].globals[v]) except KeyError, x: @@ -276,7 +279,20 @@ def _SConscript(fs, *files, **kw): fs.chdir(frame.prev_dir, change_os_dir=0) rdir = frame.prev_dir.rdir() rdir._create() # Make sure there's a directory there. - os.chdir(rdir.get_abspath()) + try: + os.chdir(rdir.get_abspath()) + except OSError, e: + # We still couldn't chdir there, so raise the error, + # but only if actions are being executed. + # + # If the -n option was used, the directory would *not* + # have been created and we should just carry on and + # let things muddle through. This isn't guaranteed + # to work if the SConscript files are reading things + # from disk (for example), but it should work well + # enough for most configurations. + if SCons.Action.execute_actions: + raise e results.append(frame.retval) @@ -403,16 +419,16 @@ def _get_SConscript_filenames(self, ls, kw): if kw.get('exports'): exports.extend(self.Split(kw['exports'])) - build_dir = kw.get('build_dir') - if build_dir: + variant_dir = kw.get('variant_dir') or kw.get('build_dir') + if variant_dir: if len(files) != 1: raise SCons.Errors.UserError, \ - "Invalid SConscript() usage - can only specify one SConscript with a build_dir" + "Invalid SConscript() usage - can only specify one SConscript with a variant_dir" duplicate = kw.get('duplicate', 1) src_dir = kw.get('src_dir') if not src_dir: src_dir, fname = os.path.split(str(files[0])) - files = [os.path.join(str(build_dir), fname)] + files = [os.path.join(str(variant_dir), fname)] else: if not isinstance(src_dir, SCons.Node.Node): src_dir = self.fs.Dir(src_dir) @@ -422,11 +438,11 @@ def _get_SConscript_filenames(self, ls, kw): if fn.is_under(src_dir): # Get path relative to the source directory. fname = fn.get_path(src_dir) - files = [os.path.join(str(build_dir), fname)] + files = [os.path.join(str(variant_dir), fname)] else: files = [fn.abspath] - kw['src_dir'] = build_dir - self.fs.BuildDir(build_dir, src_dir, duplicate) + kw['src_dir'] = variant_dir + self.fs.VariantDir(variant_dir, src_dir, duplicate) return (files, exports) diff --git a/scons/scons-local-0.97.0d20071212/SCons/Script/__init__.py b/scons/scons-local-1.2.0/SCons/Script/__init__.py similarity index 95% rename from scons/scons-local-0.97.0d20071212/SCons/Script/__init__.py rename to scons/scons-local-1.2.0/SCons/Script/__init__.py index 414798caa0..ad99991313 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Script/__init__.py +++ b/scons/scons-local-1.2.0/SCons/Script/__init__.py @@ -12,7 +12,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -34,7 +34,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Script/__init__.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Script/__init__.py 3842 2008/12/20 22:59:52 scons" import time start_time = time.time() @@ -84,6 +84,7 @@ import SCons.Subst import SCons.Tool import SCons.Util +import SCons.Variables import SCons.Defaults import Main @@ -138,22 +139,31 @@ Action = SCons.Action.Action AddMethod = SCons.Util.AddMethod AllowSubstExceptions = SCons.Subst.SetAllowableExceptions -BoolOption = SCons.Options.BoolOption Builder = SCons.Builder.Builder Configure = _SConscript.Configure -EnumOption = SCons.Options.EnumOption Environment = SCons.Environment.Environment #OptParser = SCons.SConsOptions.OptParser FindPathDirs = SCons.Scanner.FindPathDirs -ListOption = SCons.Options.ListOption -PackageOption = SCons.Options.PackageOption -PathOption = SCons.Options.PathOption Platform = SCons.Platform.Platform Return = _SConscript.Return Scanner = SCons.Scanner.Base Tool = SCons.Tool.Tool WhereIs = SCons.Util.WhereIs +# +BoolVariable = SCons.Variables.BoolVariable +EnumVariable = SCons.Variables.EnumVariable +ListVariable = SCons.Variables.ListVariable +PackageVariable = SCons.Variables.PackageVariable +PathVariable = SCons.Variables.PathVariable + +# Deprecated names that will go away some day. +BoolOption = SCons.Options.BoolOption +EnumOption = SCons.Options.EnumOption +ListOption = SCons.Options.ListOption +PackageOption = SCons.Options.PackageOption +PathOption = SCons.Options.PathOption + # Action factories. Chmod = SCons.Defaults.Chmod Copy = SCons.Defaults.Copy @@ -262,6 +272,9 @@ def HelpFunction(text): sconscript_reading = 0 # +def Variables(files=[], args=ARGUMENTS): + return SCons.Variables.Variables(files, args) + def Options(files=[], args=ARGUMENTS): return SCons.Options.Options(files, args) @@ -321,6 +334,7 @@ def Options(files=[], args=ARGUMENTS): 'Tag', 'TargetSignatures', 'Value', + 'VariantDir', ] GlobalDefaultBuilders = [ diff --git a/scons/scons-local-0.97.0d20071212/SCons/Sig.py b/scons/scons-local-1.2.0/SCons/Sig.py similarity index 92% rename from scons/scons-local-0.97.0d20071212/SCons/Sig.py rename to scons/scons-local-1.2.0/SCons/Sig.py index 454f16460a..2e50308c51 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Sig.py +++ b/scons/scons-local-1.2.0/SCons/Sig.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Sig.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Sig.py 3842 2008/12/20 22:59:52 scons" __doc__ = """Place-holder for the old SCons.Sig module hierarchy diff --git a/scons/scons-local-0.97.0d20071212/SCons/Subst.py b/scons/scons-local-1.2.0/SCons/Subst.py similarity index 93% rename from scons/scons-local-0.97.0d20071212/SCons/Subst.py rename to scons/scons-local-1.2.0/SCons/Subst.py index bff27ae25b..afebca43fb 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Subst.py +++ b/scons/scons-local-1.2.0/SCons/Subst.py @@ -5,7 +5,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,9 +27,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Subst.py 2523 2007/12/12 09:37:41 knight" - -import SCons.compat +__revision__ = "src/engine/SCons/Subst.py 3842 2008/12/20 22:59:52 scons" import re import string @@ -39,11 +37,11 @@ import SCons.Errors -from SCons.Util import is_String, is_List, is_Tuple +from SCons.Util import is_String, is_Sequence # Indexed by the SUBST_* constants below. -_strconv = [SCons.Util.to_String, - SCons.Util.to_String, +_strconv = [SCons.Util.to_String_for_subst, + SCons.Util.to_String_for_subst, SCons.Util.to_String_for_signature] @@ -188,7 +186,7 @@ def _gen_nodelist(self): list = self.list if list is None: list = [] - elif not is_List(list) and not is_Tuple(list): + elif not is_Sequence(list): list = [list] # The map(self.func) call is what actually turns # a list into appropriate proxies. @@ -203,10 +201,10 @@ class Targets_or_Sources(UserList.UserList): wrapping a NLWrapper. This class handles the different methods used to access the list, calling the NLWrapper to create proxies on demand. - Note that we subclass UserList.UserList purely so that the is_List() - function will identify an object of this class as a list during - variable expansion. We're not really using any UserList.UserList - methods in practice. + Note that we subclass UserList.UserList purely so that the + is_Sequence() function will identify an object of this class as + a list during variable expansion. We're not really using any + UserList.UserList methods in practice. """ def __init__(self, nl): self.nl = nl @@ -272,7 +270,13 @@ def subst_dict(target, source): dict = {} if target: - tnl = NLWrapper(target, lambda x: x.get_subst_proxy()) + def get_tgt_subst_proxy(thing): + try: + subst_proxy = thing.get_subst_proxy() + except AttributeError: + subst_proxy = thing # probably a string, just return it + return subst_proxy + tnl = NLWrapper(target, get_tgt_subst_proxy) dict['TARGETS'] = Targets_or_Sources(tnl) dict['TARGET'] = Target_or_Source(tnl) else: @@ -287,7 +291,10 @@ def get_src_subst_proxy(node): pass else: node = rfile() - return node.get_subst_proxy() + try: + return node.get_subst_proxy() + except AttributeError: + return node # probably a String, just return it snl = NLWrapper(source, get_src_subst_proxy) dict['SOURCES'] = Targets_or_Sources(snl) dict['SOURCE'] = Target_or_Source(snl) @@ -312,6 +319,25 @@ def get_src_subst_proxy(node): # Indexed by the SUBST_* constants above. _regex_remove = [ _rm, None, _remove ] +def _rm_list(list): + #return [ l for l in list if not l in ('$(', '$)') ] + return filter(lambda l: not l in ('$(', '$)'), list) + +def _remove_list(list): + result = [] + do_append = result.append + for l in list: + if l == '$(': + do_append = lambda x: None + elif l == '$)': + do_append = result.append + else: + do_append(l) + return result + +# Indexed by the SUBST_* constants above. +_list_remove = [ _rm_list, None, _remove_list ] + # Regular expressions for splitting strings and handling substitutions, # for use by the scons_subst() and scons_subst_list() functions: # @@ -342,7 +368,8 @@ def get_src_subst_proxy(node): _space_sep = re.compile(r'[\t ]+(?![^{]*})') def scons_subst(strSubst, env, mode=SUBST_RAW, target=None, source=None, gvars={}, lvars={}, conv=None): - """Expand a string containing construction variable substitutions. + """Expand a string or list containing construction variable + substitutions. This is the work-horse function for substitutions in file names and the like. The companion scons_subst_list() function (below) @@ -427,11 +454,10 @@ def expand(self, s, lvars): var = string.split(key, '.')[0] lv[var] = '' return self.substitute(s, lv) - elif is_List(s) or is_Tuple(s): + elif is_Sequence(s): def func(l, conv=self.conv, substitute=self.substitute, lvars=lvars): return conv(substitute(l, lvars)) - r = map(func, s) - return string.join(r) + return map(func, s) elif callable(s): try: s = s(target=self.target, @@ -458,6 +484,7 @@ def substitute(self, args, lvars): separate tokens. """ if is_String(args) and not isinstance(args, CmdStringHolder): + args = str(args) # In case it's a UserString. try: def sub_match(match, conv=self.conv, expand=self.expand, lvars=lvars): return conv(expand(match.group(1), lvars)) @@ -472,11 +499,10 @@ def sub_match(match, conv=self.conv, expand=self.expand, lvars=lvars): result = [] for a in args: result.append(self.conv(self.expand(a, lvars))) - try: - result = string.join(result, '') - except TypeError: - if len(result) == 1: - result = result[0] + if len(result) == 1: + result = result[0] + else: + result = string.join(map(str, result), '') return result else: return self.expand(args, lvars) @@ -524,6 +550,10 @@ def sub_match(match, conv=self.conv, expand=self.expand, lvars=lvars): # Compress strings of white space characters into # a single space. result = string.strip(_space_sep.sub(' ', result)) + elif is_Sequence(result): + remove = _list_remove[mode] + if remove: + result = remove(result) return result @@ -542,7 +572,7 @@ def scons_subst_list(strSubst, env, mode=SUBST_RAW, target=None, source=None, gv # except KeyError: # Subst_List_Strings[strSubst] = 1 # import SCons.Debug -# SCons.Debug.caller(1) +# SCons.Debug.caller_trace(1) class ListSubber(UserList.UserList): """A class to construct the results of a scons_subst_list() call. @@ -634,7 +664,7 @@ def expand(self, s, lvars, within_list): lv[var] = '' self.substitute(s, lv, 0) self.this_word() - elif is_List(s) or is_Tuple(s): + elif is_Sequence(s): for a in s: self.substitute(a, lvars, 1) self.next_word() @@ -666,6 +696,7 @@ def substitute(self, args, lvars, within_list): """ if is_String(args) and not isinstance(args, CmdStringHolder): + args = str(args) # In case it's a UserString. args = _separate_args.findall(args) for a in args: if a[0] in ' \t\n\r\f\v': @@ -827,18 +858,18 @@ def sub_match(match, val=val, matchlist=matchlist): a = match.group(1) if a in matchlist: a = val - if is_List(a) or is_Tuple(a): + if is_Sequence(a): return string.join(map(str, a)) else: return str(a) - if is_List(strSubst) or is_Tuple(strSubst): + if is_Sequence(strSubst): result = [] for arg in strSubst: if is_String(arg): if arg in matchlist: arg = val - if is_List(arg) or is_Tuple(arg): + if is_Sequence(arg): result.extend(arg) else: result.append(arg) diff --git a/scons/scons-local-0.97.0d20071212/SCons/Taskmaster.py b/scons/scons-local-1.2.0/SCons/Taskmaster.py similarity index 50% rename from scons/scons-local-0.97.0d20071212/SCons/Taskmaster.py rename to scons/scons-local-1.2.0/SCons/Taskmaster.py index 2fc4b08aa5..354fcca4f0 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Taskmaster.py +++ b/scons/scons-local-1.2.0/SCons/Taskmaster.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -48,20 +48,24 @@ target(s) that it decides need to be evaluated and/or built. """ -__revision__ = "src/engine/SCons/Taskmaster.py 2523 2007/12/12 09:37:41 knight" - -import SCons.compat +__revision__ = "src/engine/SCons/Taskmaster.py 3842 2008/12/20 22:59:52 scons" +from itertools import chain import operator import string import sys import traceback -import SCons.Node import SCons.Errors +import SCons.Node StateString = SCons.Node.StateString - +NODE_NO_STATE = SCons.Node.no_state +NODE_PENDING = SCons.Node.pending +NODE_EXECUTING = SCons.Node.executing +NODE_UP_TO_DATE = SCons.Node.up_to_date +NODE_EXECUTED = SCons.Node.executed +NODE_FAILED = SCons.Node.failed # A subsystem for recording stats about how different Nodes are handled by @@ -134,6 +138,10 @@ def __init__(self, tm, targets, top, node): self.node = node self.exc_clear() + def trace_message(self, method, node, description='node'): + fmt = '%-20s %s %s\n' + return fmt % (method + ':', description, self.tm.trace_node(node)) + def display(self, message): """ Hook to allow the calling interface to display a message. @@ -155,6 +163,8 @@ def prepare(self): unlink underlying files and make all necessary directories before the Action is actually called to build the targets. """ + T = self.tm.trace + if T: T.write(self.trace_message('Task.prepare()', self.node)) # Now that it's the appropriate time, give the TaskMaster a # chance to raise any exceptions it encountered while preparing @@ -165,6 +175,17 @@ def prepare(self): self.display(self.tm.message) self.tm.message = None + # Let the targets take care of any necessary preparations. + # This includes verifying that all of the necessary sources + # and dependencies exist, removing the target file(s), etc. + # + # As of April 2008, the get_executor().prepare() method makes + # sure that all of the aggregate sources necessary to build this + # Task's target(s) exist in one up-front check. The individual + # target t.prepare() methods check that each target's explicit + # or implicit dependencies exists, and also initialize the + # .sconsign info. + self.targets[0].get_executor().prepare() for t in self.targets: t.prepare() for s in t.side_effects: @@ -175,6 +196,17 @@ def get_target(self): """ return self.node + def needs_execute(self): + """ + Called to determine whether the task's execute() method should + be run. + + This method allows one to skip the somethat costly execution + of the execute() method in a seperate thread. For example, + that would be unnecessary for up-to-date targets. + """ + return True + def execute(self): """ Called to execute the task. @@ -183,6 +215,8 @@ def execute(self): so only do thread safe stuff here. Do thread unsafe stuff in prepare(), executed() or failed(). """ + T = self.tm.trace + if T: T.write(self.trace_message('Task.execute()', self.node)) try: everything_was_cached = 1 @@ -192,8 +226,6 @@ def execute(self): break if not everything_was_cached: self.targets[0].build() - except KeyboardInterrupt: - raise except SystemExit: exc_value = sys.exc_info()[1] raise SCons.Errors.ExplicitExit(self.targets[0], exc_value.code) @@ -201,9 +233,11 @@ def execute(self): raise except SCons.Errors.BuildError: raise - except: - raise SCons.Errors.TaskmasterException(self.targets[0], - sys.exc_info()) + except Exception, e: + buildError = SCons.Errors.convert_to_BuildError(e) + buildError.node = self.targets[0] + buildError.exc_info = sys.exc_info() + raise buildError def executed_without_callbacks(self): """ @@ -211,11 +245,15 @@ def executed_without_callbacks(self): and the Taskmaster instance doesn't want to call the Node's callback methods. """ + T = self.tm.trace + if T: T.write(self.trace_message('Task.executed_without_callbacks()', + self.node)) + for t in self.targets: - if t.get_state() == SCons.Node.executing: + if t.get_state() == NODE_EXECUTING: for side_effect in t.side_effects: - side_effect.set_state(SCons.Node.no_state) - t.set_state(SCons.Node.executed) + side_effect.set_state(NODE_NO_STATE) + t.set_state(NODE_EXECUTED) def executed_with_callbacks(self): """ @@ -230,11 +268,15 @@ def executed_with_callbacks(self): post-visit actions that must take place regardless of whether or not the target was an actual built target or a source Node. """ + T = self.tm.trace + if T: T.write(self.trace_message('Task.executed_with_callbacks()', + self.node)) + for t in self.targets: - if t.get_state() == SCons.Node.executing: + if t.get_state() == NODE_EXECUTING: for side_effect in t.side_effects: - side_effect.set_state(SCons.Node.no_state) - t.set_state(SCons.Node.executed) + side_effect.set_state(NODE_NO_STATE) + t.set_state(NODE_EXECUTED) t.built() t.visited() @@ -243,15 +285,32 @@ def executed_with_callbacks(self): def failed(self): """ Default action when a task fails: stop the build. + + Note: Although this function is normally invoked on nodes in + the executing state, it might also be invoked on up-to-date + nodes when using Configure(). """ self.fail_stop() def fail_stop(self): """ Explicit stop-the-build failure. + + This sets failure status on the target nodes and all of + their dependent parent nodes. + + Note: Although this function is normally invoked on nodes in + the executing state, it might also be invoked on up-to-date + nodes when using Configure(). """ - for t in self.targets: - t.set_state(SCons.Node.failed) + T = self.tm.trace + if T: T.write(self.trace_message('Task.failed_stop()', self.node)) + + # Invoke will_not_build() to clean-up the pending children + # list. + self.tm.will_not_build(self.targets, lambda n: n.set_state(NODE_FAILED)) + + # Tell the taskmaster to not start any new tasks self.tm.stop() # We're stopping because of a build failure, but give the @@ -266,12 +325,15 @@ def fail_continue(self): This sets failure status on the target nodes and all of their dependent parent nodes. + + Note: Although this function is normally invoked on nodes in + the executing state, it might also be invoked on up-to-date + nodes when using Configure(). """ - for t in self.targets: - # Set failure state on all of the parents that were dependent - # on this failed build. - def set_state(node): node.set_state(SCons.Node.failed) - t.call_for_all_waiting_parents(set_state) + T = self.tm.trace + if T: T.write(self.trace_message('Task.failed_continue()', self.node)) + + self.tm.will_not_build(self.targets, lambda n: n.set_state(NODE_FAILED)) def make_ready_all(self): """ @@ -280,11 +342,14 @@ def make_ready_all(self): This is used when the interface needs every target Node to be visited--the canonical example being the "scons -c" option. """ + T = self.tm.trace + if T: T.write(self.trace_message('Task.make_ready_all()', self.node)) + self.out_of_date = self.targets[:] for t in self.targets: - t.disambiguate().set_state(SCons.Node.executing) + t.disambiguate().set_state(NODE_EXECUTING) for s in t.side_effects: - s.set_state(SCons.Node.executing) + s.set_state(NODE_EXECUTING) def make_ready_current(self): """ @@ -293,7 +358,12 @@ def make_ready_current(self): This is the default behavior for building only what's necessary. """ + T = self.tm.trace + if T: T.write(self.trace_message('Task.make_ready_current()', + self.node)) + self.out_of_date = [] + needs_executing = False for t in self.targets: try: t.disambiguate().make_ready() @@ -301,13 +371,24 @@ def make_ready_current(self): (not t.always_build and t.is_up_to_date()) except EnvironmentError, e: raise SCons.Errors.BuildError(node=t, errstr=e.strerror, filename=e.filename) - if is_up_to_date: - t.set_state(SCons.Node.up_to_date) - else: + + if not is_up_to_date: self.out_of_date.append(t) - t.set_state(SCons.Node.executing) + needs_executing = True + + if needs_executing: + for t in self.targets: + t.set_state(NODE_EXECUTING) for s in t.side_effects: - s.set_state(SCons.Node.executing) + s.set_state(NODE_EXECUTING) + else: + for t in self.targets: + # We must invoke visited() to ensure that the node + # information has been computed before allowing the + # parent nodes to execute. (That could occur in a + # parallel build...) + t.visited() + t.set_state(NODE_UP_TO_DATE) make_ready = make_ready_current @@ -321,6 +402,8 @@ def postprocess(self): waiting parent Nodes, or Nodes waiting on a common side effect, that can be put back on the candidates list. """ + T = self.tm.trace + if T: T.write(self.trace_message('Task.postprocess()', self.node)) # We may have built multiple targets, some of which may have # common parents waiting for this build. Count up how many @@ -331,24 +414,34 @@ def postprocess(self): targets = set(self.targets) + pending_children = self.tm.pending_children parents = {} for t in targets: - for p in t.waiting_parents.keys(): + # A node can only be in the pending_children set if it has + # some waiting_parents. + if t.waiting_parents: + if T: T.write(self.trace_message('Task.postprocess()', + t, + 'removing')) + pending_children.discard(t) + for p in t.waiting_parents: parents[p] = parents.get(p, 0) + 1 for t in targets: for s in t.side_effects: - if s.get_state() == SCons.Node.executing: - s.set_state(SCons.Node.no_state) - for p in s.waiting_parents.keys(): - if not parents.has_key(p): - parents[p] = 1 - for p in s.waiting_s_e.keys(): + if s.get_state() == NODE_EXECUTING: + s.set_state(NODE_NO_STATE) + for p in s.waiting_parents: + parents[p] = parents.get(p, 0) + 1 + for p in s.waiting_s_e: if p.ref_count == 0: self.tm.candidates.append(p) for p, subtract in parents.items(): p.ref_count = p.ref_count - subtract + if T: T.write(self.trace_message('Task.postprocess()', + p, + 'adjusted parent ref count')) if p.ref_count == 0: self.tm.candidates.append(p) @@ -409,12 +502,15 @@ def _exception_raise(self): raise exc_type, exc_value, exc_traceback -def find_cycle(stack): - if stack[0] == stack[-1]: - return stack - for n in stack[-1].waiting_parents.keys(): +def find_cycle(stack, visited): + if stack[-1] in visited: + return None + visited.add(stack[-1]) + for n in stack[-1].waiting_parents: stack.append(n) - if find_cycle(stack): + if stack[0] == stack[-1]: + return stack + if find_cycle(stack, visited): return stack stack.pop() return None @@ -437,6 +533,7 @@ def __init__(self, targets=[], tasker=Task, order=None, trace=None): self.message = None self.trace = trace self.next_candidate = self.find_next_candidate + self.pending_children = set() def find_next_candidate(self): """ @@ -477,9 +574,104 @@ def find_next_candidate(self): def no_next_candidate(self): """ Stops Taskmaster processing by not returning a next candidate. + + Note that we have to clean-up the Taskmaster candidate list + because the cycle detection depends on the fact all nodes have + been processed somehow. """ + while self.candidates: + candidates = self.candidates + self.candidates = [] + self.will_not_build(candidates) return None + def _validate_pending_children(self): + """ + Validate the content of the pending_children set. Assert if an + internal error is found. + + This function is used strictly for debugging the taskmaster by + checking that no invariants are violated. It is not used in + normal operation. + + The pending_children set is used to detect cycles in the + dependency graph. We call a "pending child" a child that is + found in the "pending" state when checking the dependencies of + its parent node. + + A pending child can occur when the Taskmaster completes a loop + through a cycle. For example, lets imagine a graph made of + three node (A, B and C) making a cycle. The evaluation starts + at node A. The taskmaster first consider whether node A's + child B is up-to-date. Then, recursively, node B needs to + check whether node C is up-to-date. This leaves us with a + dependency graph looking like: + + Next candidate \ + \ + Node A (Pending) --> Node B(Pending) --> Node C (NoState) + ^ | + | | + +-------------------------------------+ + + Now, when the Taskmaster examines the Node C's child Node A, + it finds that Node A is in the "pending" state. Therefore, + Node A is a pending child of node C. + + Pending children indicate that the Taskmaster has potentially + loop back through a cycle. We say potentially because it could + also occur when a DAG is evaluated in parallel. For example, + consider the following graph: + + + Node A (Pending) --> Node B(Pending) --> Node C (Pending) --> ... + | ^ + | | + +----------> Node D (NoState) --------+ + / + Next candidate / + + The Taskmaster first evaluates the nodes A, B, and C and + starts building some children of node C. Assuming, that the + maximum parallel level has not been reached, the Taskmaster + will examine Node D. It will find that Node C is a pending + child of Node D. + + In summary, evaluating a graph with a cycle will always + involve a pending child at one point. A pending child might + indicate either a cycle or a diamond-shaped DAG. Only a + fraction of the nodes ends-up being a "pending child" of + another node. This keeps the pending_children set small in + practice. + + We can differentiate between the two cases if we wait until + the end of the build. At this point, all the pending children + nodes due to a diamond-shaped DAG will have been properly + built (or will have failed to build). But, the pending + children involved in a cycle will still be in the pending + state. + + The taskmaster removes nodes from the pending_children set as + soon as a pending_children node moves out of the pending + state. This also helps to keep the pending_children set small. + """ + + for n in self.pending_children: + assert n.state in (NODE_PENDING, NODE_EXECUTING), \ + (str(n), StateString[n.state]) + assert len(n.waiting_parents) != 0, (str(n), len(n.waiting_parents)) + for p in n.waiting_parents: + assert p.ref_count > 0, (str(n), str(p), p.ref_count) + + + def trace_message(self, message): + return 'Taskmaster: %s\n' % message + + def trace_node(self, node): + return '<%-10s %-3s %s>' % (StateString[node.get_state()], + node.ref_count, + repr(str(node))) + def _find_next_ready_node(self): """ Finds the next node that is ready to be built. @@ -505,15 +697,25 @@ def _find_next_ready_node(self): self.ready_exc = None T = self.trace + if T: T.write('\n' + self.trace_message('Looking for a node to evaluate')) while 1: node = self.next_candidate() if node is None: + if T: T.write(self.trace_message('No candidate anymore.') + '\n') return None node = node.disambiguate() state = node.get_state() + # For debugging only: + # + # try: + # self._validate_pending_children() + # except: + # self.ready_exc = sys.exc_info() + # return node + if CollectStats: if not hasattr(node, 'stats'): node.stats = Stats() @@ -523,119 +725,138 @@ def _find_next_ready_node(self): else: S = None - if T: T.write('Taskmaster: %s:' % repr(str(node))) + if T: T.write(self.trace_message(' Considering node %s and its children:' % self.trace_node(node))) - # Skip this node if it has already been evaluated: - if state > SCons.Node.pending: + if state == NODE_NO_STATE: + # Mark this node as being on the execution stack: + node.set_state(NODE_PENDING) + elif state > NODE_PENDING: + # Skip this node if it has already been evaluated: if S: S.already_handled = S.already_handled + 1 - if T: T.write(' already handled (%s)\n' % StateString[state]) + if T: T.write(self.trace_message(' already handled (executed)')) continue - # Mark this node as being on the execution stack: - node.set_state(SCons.Node.pending) - try: - children = node.children() + node.prerequisites + children = node.children() except SystemExit: exc_value = sys.exc_info()[1] e = SCons.Errors.ExplicitExit(node, exc_value.code) self.ready_exc = (SCons.Errors.ExplicitExit, e) - if T: T.write(' SystemExit\n') + if T: T.write(self.trace_message(' SystemExit')) return node - except KeyboardInterrupt: - if T: T.write(' KeyboardInterrupt\n') - raise - except: + except Exception, e: # We had a problem just trying to figure out the # children (like a child couldn't be linked in to a - # BuildDir, or a Scanner threw something). Arrange to + # VariantDir, or a Scanner threw something). Arrange to # raise the exception when the Task is "executed." self.ready_exc = sys.exc_info() if S: S.problem = S.problem + 1 - if T: T.write(' exception\n') + if T: T.write(self.trace_message(' exception %s while scanning children.\n' % e)) return node - if T and children: - c = map(str, children) - c.sort() - T.write(' children:\n %s\n ' % c) - - childstate = map(lambda N: (N, N.get_state()), children) - - # Skip this node if any of its children have failed. This - # catches the case where we're descending a top-level target - # and one of our children failed while trying to be built - # by a *previous* descent of an earlier top-level target. - failed_children = filter(lambda I: I[1] == SCons.Node.failed, - childstate) - if failed_children: - node.set_state(SCons.Node.failed) + children_not_visited = [] + children_pending = set() + children_not_ready = [] + children_failed = False + + for child in chain(children,node.prerequisites): + childstate = child.get_state() + + if T: T.write(self.trace_message(' ' + self.trace_node(child))) + + if childstate == NODE_NO_STATE: + children_not_visited.append(child) + elif childstate == NODE_PENDING: + children_pending.add(child) + elif childstate == NODE_FAILED: + children_failed = True + + if childstate <= NODE_EXECUTING: + children_not_ready.append(child) + + + # These nodes have not even been visited yet. Add + # them to the list so that on some next pass we can + # take a stab at evaluating them (or their children). + children_not_visited.reverse() + self.candidates.extend(self.order(children_not_visited)) + #if T and children_not_visited: + # T.write(self.trace_message(' adding to candidates: %s' % map(str, children_not_visited))) + # T.write(self.trace_message(' candidates now: %s\n' % map(str, self.candidates))) + + # Skip this node if any of its children have failed. + # + # This catches the case where we're descending a top-level + # target and one of our children failed while trying to be + # built by a *previous* descent of an earlier top-level + # target. + # + # It can also occur if a node is reused in multiple + # targets. One first descends though the one of the + # target, the next time occurs through the other target. + # + # Note that we can only have failed_children if the + # --keep-going flag was used, because without it the build + # will stop before diving in the other branch. + # + # Note that even if one of the children fails, we still + # added the other children to the list of candidate nodes + # to keep on building (--keep-going). + if children_failed: + node.set_state(NODE_FAILED) + if S: S.child_failed = S.child_failed + 1 - if T: - c = map(str, failed_children) - c.sort() - T.write(' children failed:\n %s\n' % c) + if T: T.write(self.trace_message('****** %s\n' % self.trace_node(node))) continue - # Detect dependency cycles: - pending_nodes = filter(lambda I: I[1] == SCons.Node.pending, childstate) - if pending_nodes: - for p in pending_nodes: - cycle = find_cycle([p[0], node]) - if cycle: - desc = "Dependency cycle: " + string.join(map(str, cycle), " -> ") - if T: T.write(' dependency cycle\n') - raise SCons.Errors.UserError, desc - - not_built = filter(lambda I: I[1] <= SCons.Node.executing, childstate) - if not_built: - # We're waiting on one or more derived targets that have - # not yet finished building. - - not_visited = filter(lambda I: not I[1], not_built) - if not_visited: - # Some of them haven't even been visited yet. - # Add them to the list so that on some next pass - # we can take a stab at evaluating them (or - # their children). - not_visited = map(lambda I: I[0], not_visited) - not_visited.reverse() - self.candidates.extend(self.order(not_visited)) - - n_b_nodes = map(lambda I: I[0], not_built) - - # Add this node to the waiting parents lists of anything - # we're waiting on, with a reference count so we can be - # put back on the list for re-evaluation when they've - # all finished. - map(lambda n, P=node: n.add_to_waiting_parents(P), n_b_nodes) - node.ref_count = len(set(n_b_nodes)) - - if S: S.not_built = S.not_built + 1 + if children_not_ready: + for child in children_not_ready: + # We're waiting on one or more derived targets + # that have not yet finished building. + if S: S.not_built = S.not_built + 1 + + # Add this node to the waiting parents lists of + # anything we're waiting on, with a reference + # count so we can be put back on the list for + # re-evaluation when they've all finished. + node.ref_count = node.ref_count + child.add_to_waiting_parents(node) + if T: T.write(self.trace_message(' adjusted ref count: %s, child %s' % + (self.trace_node(node), repr(str(child))))) + if T: - c = map(str, n_b_nodes) - c.sort() - T.write(' waiting on unfinished children:\n %s\n' % c) + for pc in children_pending: + T.write(self.trace_message(' adding %s to the pending children set\n' % + self.trace_node(pc))) + self.pending_children = self.pending_children | children_pending + continue # Skip this node if it has side-effects that are # currently being built: - side_effects = filter(lambda N: - N.get_state() == SCons.Node.executing, - node.side_effects) - if side_effects: - map(lambda n, P=node: n.add_to_waiting_s_e(P), side_effects) + wait_side_effects = False + for se in node.side_effects: + if se.get_state() == NODE_EXECUTING: + se.add_to_waiting_s_e(node) + wait_side_effects = True + + if wait_side_effects: if S: S.side_effects = S.side_effects + 1 - if T: - c = map(str, side_effects) - c.sort() - T.write(' waiting on side effects:\n %s\n' % c) continue # The default when we've gotten through all of the checks above: # this node is ready to be built. if S: S.build = S.build + 1 - if T: T.write(' evaluating %s\n' % node) + if T: T.write(self.trace_message('Evaluating %s\n' % + self.trace_node(node))) + + # For debugging only: + # + # try: + # self._validate_pending_children() + # except: + # self.ready_exc = sys.exc_info() + # return node + return node return None @@ -657,11 +878,9 @@ def next_task(self): task = self.tasker(self, tlist, node in self.original_top, node) try: task.make_ready() - except KeyboardInterrupt: - raise except: # We had a problem just trying to get this task ready (like - # a child couldn't be linked in to a BuildDir when deciding + # a child couldn't be linked in to a VariantDir when deciding # whether this node is current). Arrange to raise the # exception when the Task is "executed." self.ready_exc = sys.exc_info() @@ -673,8 +892,94 @@ def next_task(self): return task + def will_not_build(self, nodes, node_func=lambda n: None): + """ + Perform clean-up about nodes that will never be built. Invokes + a user defined function on all of these nodes (including all + of their parents). + """ + + T = self.trace + + pending_children = self.pending_children + + to_visit = set(nodes) + pending_children = pending_children - to_visit + + if T: + for n in nodes: + T.write(self.trace_message(' removing node %s from the pending children set\n' % + self.trace_node(n))) + try: + while 1: + try: + node = to_visit.pop() + except AttributeError: + # Python 1.5.2 + if len(to_visit): + node = to_visit[0] + to_visit.remove(node) + else: + break + + node_func(node) + + # Prune recursion by flushing the waiting children + # list immediately. + parents = node.waiting_parents + node.waiting_parents = set() + + to_visit = to_visit | parents + pending_children = pending_children - parents + + for p in parents: + p.ref_count = p.ref_count - 1 + if T: T.write(self.trace_message(' removing parent %s from the pending children set\n' % + self.trace_node(p))) + except KeyError: + # The container to_visit has been emptied. + pass + + # We have the stick back the pending_children list into the + # task master because the python 1.5.2 compatibility does not + # allow us to use in-place updates + self.pending_children = pending_children + def stop(self): """ Stops the current build completely. """ self.next_candidate = self.no_next_candidate + + def cleanup(self): + """ + Check for dependency cycles. + """ + if not self.pending_children: + return + + # TODO(1.5) + #nclist = [ (n, find_cycle([n], set())) for n in self.pending_children ] + nclist = map(lambda n: (n, find_cycle([n], set())), self.pending_children) + + # TODO(1.5) + #genuine_cycles = [ + # node for node, cycle in nclist + # if cycle or node.get_state() != NODE_EXECUTED + #] + genuine_cycles = filter(lambda t: t[1] or t[0].get_state() != NODE_EXECUTED, nclist) + if not genuine_cycles: + # All of the "cycles" found were single nodes in EXECUTED state, + # which is to say, they really weren't cycles. Just return. + return + + desc = 'Found dependency cycle(s):\n' + for node, cycle in nclist: + if cycle: + desc = desc + " " + string.join(map(str, cycle), " -> ") + "\n" + else: + desc = desc + \ + " Internal Error: no cycle found for node %s (%s) in state %s\n" % \ + (node, repr(node), StateString[node.get_state()]) + + raise SCons.Errors.UserError, desc diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/386asm.py b/scons/scons-local-1.2.0/SCons/Tool/386asm.py similarity index 92% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/386asm.py rename to scons/scons-local-1.2.0/SCons/Tool/386asm.py index 6a0bd4da30..fc5c500048 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/386asm.py +++ b/scons/scons-local-1.2.0/SCons/Tool/386asm.py @@ -10,7 +10,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -32,7 +32,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/386asm.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/386asm.py 3842 2008/12/20 22:59:52 scons" from SCons.Tool.PharLapCommon import addPharLapPaths import SCons.Util diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/BitKeeper.py b/scons/scons-local-1.2.0/SCons/Tool/BitKeeper.py similarity index 92% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/BitKeeper.py rename to scons/scons-local-1.2.0/SCons/Tool/BitKeeper.py index 46dcc0051a..15d1f0ad3c 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/BitKeeper.py +++ b/scons/scons-local-1.2.0/SCons/Tool/BitKeeper.py @@ -10,7 +10,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -32,7 +32,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/BitKeeper.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/BitKeeper.py 3842 2008/12/20 22:59:52 scons" import SCons.Action import SCons.Builder diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/CVS.py b/scons/scons-local-1.2.0/SCons/Tool/CVS.py similarity index 93% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/CVS.py rename to scons/scons-local-1.2.0/SCons/Tool/CVS.py index 519a6f5908..e1cc04d1ed 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/CVS.py +++ b/scons/scons-local-1.2.0/SCons/Tool/CVS.py @@ -9,7 +9,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/CVS.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/CVS.py 3842 2008/12/20 22:59:52 scons" import SCons.Action import SCons.Builder diff --git a/scons/scons-local-1.2.0/SCons/Tool/FortranCommon.py b/scons/scons-local-1.2.0/SCons/Tool/FortranCommon.py new file mode 100644 index 0000000000..8d3204ff14 --- /dev/null +++ b/scons/scons-local-1.2.0/SCons/Tool/FortranCommon.py @@ -0,0 +1,241 @@ +"""SCons.Tool.FortranCommon + +Stuff for processing Fortran, common to all fortran dialects. + +""" + +# +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation +# +# 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__ = "src/engine/SCons/Tool/FortranCommon.py 3842 2008/12/20 22:59:52 scons" + +import re +import string +import os.path + +import SCons.Action +import SCons.Defaults +import SCons.Scanner.Fortran +import SCons.Tool +import SCons.Util + +def isfortran(env, source): + """Return 1 if any of code in source has fortran files in it, 0 + otherwise.""" + try: + fsuffixes = env['FORTRANSUFFIXES'] + except KeyError: + # If no FORTRANSUFFIXES, no fortran tool, so there is no need to look + # for fortran sources. + return 0 + + if not source: + # Source might be None for unusual cases like SConf. + return 0 + for s in source: + if s.sources: + ext = os.path.splitext(str(s.sources[0]))[1] + if ext in fsuffixes: + return 1 + return 0 + +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', target=target, source=source) + moddir = env.subst('$FORTRANMODDIR', target=target, source=source) + modules = map(lambda x, s=suffix: string.lower(x) + s, modules) + for m in modules: + target.append(env.fs.File(m, moddir)) + 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) + +def ComputeFortranSuffixes(suffixes, ppsuffixes): + """suffixes are fortran source files, and ppsuffixes the ones to be + pre-processed. Both should be sequences, not strings.""" + assert len(suffixes) > 0 + s = suffixes[0] + sup = string.upper(s) + upper_suffixes = map(string.upper, suffixes) + if SCons.Util.case_sensitive_suffixes(s, sup): + ppsuffixes.extend(upper_suffixes) + else: + suffixes.extend(upper_suffixes) + +def CreateDialectActions(dialect): + """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) + + return CompAction, CompPPAction, ShCompAction, ShCompPPAction + +def DialectAddToEnv(env, dialect, suffixes, ppsuffixes, support_module = 0): + """Add dialect specific construction variables.""" + ComputeFortranSuffixes(suffixes, ppsuffixes) + + fscan = SCons.Scanner.Fortran.FortranScan("%sPATH" % dialect) + + for suffix in suffixes + ppsuffixes: + SCons.Tool.SourceFileScanner.add_scanner(suffix, fscan) + + env.AppendUnique(FORTRANSUFFIXES = suffixes + ppsuffixes) + + compaction, compppaction, shcompaction, shcompppaction = \ + CreateDialectActions(dialect) + + static_obj, shared_obj = SCons.Tool.createObjBuilders(env) + + for suffix in suffixes: + static_obj.add_action(suffix, compaction) + shared_obj.add_action(suffix, shcompaction) + static_obj.add_emitter(suffix, FortranEmitter) + shared_obj.add_emitter(suffix, ShFortranEmitter) + + for suffix in ppsuffixes: + static_obj.add_action(suffix, compppaction) + shared_obj.add_action(suffix, shcompppaction) + static_obj.add_emitter(suffix, FortranEmitter) + shared_obj.add_emitter(suffix, ShFortranEmitter) + + if not env.has_key('%sFLAGS' % dialect): + env['%sFLAGS' % dialect] = SCons.Util.CLVar('') + + if not env.has_key('SH%sFLAGS' % dialect): + env['SH%sFLAGS' % dialect] = SCons.Util.CLVar('$%sFLAGS' % dialect) + + # If a tool does not define fortran prefix/suffix for include path, use C ones + if not env.has_key('INC%sPREFIX' % dialect): + env['INC%sPREFIX' % dialect] = '$INCPREFIX' + + if not env.has_key('INC%sSUFFIX' % dialect): + env['INC%sSUFFIX' % dialect] = '$INCSUFFIX' + + env['_%sINCFLAGS' % dialect] = '$( ${_concat(INC%sPREFIX, %sPATH, INC%sSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)' % (dialect, dialect, dialect) + + if support_module == 1: + 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) + 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) + +def add_fortran_to_env(env): + """Add Builders and construction variables for Fortran to an Environment.""" + 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 = 1) + + 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.""" + 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.""" + 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 = 1) + +def add_f95_to_env(env): + """Add Builders and construction variables for f95 to an Environment.""" + 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 = 1) + +def add_all_to_env(env): + """Add builders and construction variables for all supported fortran + dialects.""" + add_fortran_to_env(env) + add_f77_to_env(env) + add_f90_to_env(env) + add_f95_to_env(env) diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/JavaCommon.py b/scons/scons-local-1.2.0/SCons/Tool/JavaCommon.py similarity index 89% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/JavaCommon.py rename to scons/scons-local-1.2.0/SCons/Tool/JavaCommon.py index 2aedd85591..12c31f37fb 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/JavaCommon.py +++ b/scons/scons-local-1.2.0/SCons/Tool/JavaCommon.py @@ -5,7 +5,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,7 +27,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/JavaCommon.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/JavaCommon.py 3842 2008/12/20 22:59:52 scons" import os import os.path @@ -49,14 +49,16 @@ # double-backslashes; # a single-line comment "//"; # single or double quotes preceeded by a backslash; - # single quotes, double quotes, open or close braces, semi-colons; + # single quotes, double quotes, open or close braces, semi-colons, + # periods, open or close parentheses; + # floating-point numbers; # any alphanumeric token (keyword, class name, specifier); + # any alphanumeric token surrounded by angle brackets (generics); # the multi-line comment begin and end tokens /* and */; - # array declarations "[]"; - # semi-colons; - # periods. + # array declarations "[]". _reToken = re.compile(r'(\n|\\\\|//|\\[\'"]|[\'"\{\}\;\.\(\)]|' + - r'[A-Za-z_][\w\$\.]*|/\*|\*/|\[\])') + r'\d*\.\d*|[A-Za-z_][\w\$\.]*|<[A-Za-z_]\w+>|' + + r'/\*|\*/|\[\])') class OuterState: """The initial state for parsing a Java file for classes, @@ -73,6 +75,7 @@ def __init__(self, version=default_java_version): self.stackBrackets = [] self.brackets = 0 self.nextAnon = 1 + self.localClasses = [] self.stackAnonClassBrackets = [] self.anonStacksStack = [[0]] self.package = None @@ -124,6 +127,7 @@ def closeBracket(self): if len(self.stackBrackets) and \ self.brackets == self.stackBrackets[-1]: self.listOutputs.append(string.join(self.listClasses, '$')) + self.localClasses.pop() self.listClasses.pop() self.anonStacksStack.pop() self.stackBrackets.pop() @@ -199,6 +203,8 @@ def parseToken(self, token): return IgnoreState('*/', self) elif token == '\n': return self + elif token[0] == '<' and token[-1] == '>': + return self elif token == '(': self.brace_level = self.brace_level + 1 return self @@ -236,6 +242,20 @@ def parseToken(self, token): # the next non-whitespace token should be the name of the class if token == '\n': return self + # If that's an inner class which is declared in a method, it + # requires an index prepended to the class-name, e.g. + # 'Foo$1Inner' (Tigris Issue 2087) + if self.outer_state.localClasses and \ + self.outer_state.stackBrackets[-1] > \ + self.outer_state.stackBrackets[-2]+1: + locals = self.outer_state.localClasses[-1] + try: + idx = locals[token] + locals[token] = locals[token]+1 + except KeyError: + locals[token] = 1 + token = str(locals[token]) + token + self.outer_state.localClasses.append({}) self.outer_state.listClasses.append(token) self.outer_state.anonStacksStack.append([0]) return self.outer_state diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/Perforce.py b/scons/scons-local-1.2.0/SCons/Tool/Perforce.py similarity index 95% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/Perforce.py rename to scons/scons-local-1.2.0/SCons/Tool/Perforce.py index 6a06f752e3..97049f6467 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/Perforce.py +++ b/scons/scons-local-1.2.0/SCons/Tool/Perforce.py @@ -9,7 +9,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/Perforce.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/Perforce.py 3842 2008/12/20 22:59:52 scons" import os diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/PharLapCommon.py b/scons/scons-local-1.2.0/SCons/Tool/PharLapCommon.py similarity index 96% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/PharLapCommon.py rename to scons/scons-local-1.2.0/SCons/Tool/PharLapCommon.py index d50446c697..76a566ab83 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/PharLapCommon.py +++ b/scons/scons-local-1.2.0/SCons/Tool/PharLapCommon.py @@ -7,7 +7,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -29,7 +29,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/PharLapCommon.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/PharLapCommon.py 3842 2008/12/20 22:59:52 scons" import os import os.path diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/RCS.py b/scons/scons-local-1.2.0/SCons/Tool/RCS.py similarity index 92% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/RCS.py rename to scons/scons-local-1.2.0/SCons/Tool/RCS.py index 73b8346c1b..6d47060487 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/RCS.py +++ b/scons/scons-local-1.2.0/SCons/Tool/RCS.py @@ -9,7 +9,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/RCS.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/RCS.py 3842 2008/12/20 22:59:52 scons" import SCons.Action import SCons.Builder diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/SCCS.py b/scons/scons-local-1.2.0/SCons/Tool/SCCS.py similarity index 92% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/SCCS.py rename to scons/scons-local-1.2.0/SCons/Tool/SCCS.py index 16564e98ff..842db137fc 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/SCCS.py +++ b/scons/scons-local-1.2.0/SCons/Tool/SCCS.py @@ -9,7 +9,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/SCCS.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/SCCS.py 3842 2008/12/20 22:59:52 scons" import SCons.Action import SCons.Builder diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/Subversion.py b/scons/scons-local-1.2.0/SCons/Tool/Subversion.py similarity index 93% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/Subversion.py rename to scons/scons-local-1.2.0/SCons/Tool/Subversion.py index c8e8cf5300..a593c6abe0 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/Subversion.py +++ b/scons/scons-local-1.2.0/SCons/Tool/Subversion.py @@ -9,7 +9,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/Subversion.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/Subversion.py 3842 2008/12/20 22:59:52 scons" import os.path diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/__init__.py b/scons/scons-local-1.2.0/SCons/Tool/__init__.py similarity index 84% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/__init__.py rename to scons/scons-local-1.2.0/SCons/Tool/__init__.py index 17b7fd2d9c..0b032820bc 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/__init__.py +++ b/scons/scons-local-1.2.0/SCons/Tool/__init__.py @@ -14,7 +14,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -36,7 +36,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/__init__.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/__init__.py 3842 2008/12/20 22:59:52 scons" import imp import sys @@ -55,6 +55,7 @@ CScanner = SCons.Scanner.C.CScanner() DScanner = SCons.Scanner.D.DScanner() LaTeXScanner = SCons.Scanner.LaTeX.LaTeXScanner() +PDFLaTeXScanner = SCons.Scanner.LaTeX.PDFLaTeXScanner() ProgramScanner = SCons.Scanner.Prog.ProgramScanner() SourceFileScanner = SCons.Scanner.Base({}, name='SourceFileScanner') @@ -76,8 +77,13 @@ for suffix in DSuffixes: SourceFileScanner.add_scanner(suffix, DScanner) +# FIXME: what should be done here? Two scanners scan the same extensions, +# but look for different files, e.g., "picture.eps" vs. "picture.pdf". +# The builders for DVI and PDF explicitly reference their scanners +# I think that means this is not needed??? for suffix in LaTeXSuffixes: - SourceFileScanner.add_scanner(suffix, LaTeXScanner) + SourceFileScanner.add_scanner(suffix, LaTeXScanner) + SourceFileScanner.add_scanner(suffix, PDFLaTeXScanner) class Tool: def __init__(self, name, toolpath=[], **kw): @@ -136,7 +142,7 @@ def _tool_module(self): file.close() return module except ImportError, e: - if e!="No module named %s"%self.name: + if str(e)!="No module named %s"%self.name: raise SCons.Errors.EnvironmentError, e try: import zipimport @@ -163,10 +169,10 @@ def __call__(self, env, *args, **kw): kw = self.init_kw env.Append(TOOLS = [ self.name ]) if hasattr(self, 'options'): - from SCons.Options import Options + import SCons.Variables if not env.has_key('options'): from SCons.Script import ARGUMENTS - env['options']=Options(args=ARGUMENTS) + env['options']=SCons.Variables.Variables(args=ARGUMENTS) opts=env['options'] self.options(opts) @@ -422,32 +428,33 @@ def CreateJavaFileBuilder(env): env['JAVASUFFIX'] = '.java' return java_file -class ToolInitializer: +class ToolInitializerMethod: """ - A class for delayed initialization of Tools modules. - - This is intended to be added to a construction environment in - place of the method(s) normally called for a Builder (env.Object, - env.StaticObject, etc.). When called, it searches the specified - list of tools, applies the first one that exists to the construction - environment, and calls whatever builder was (presumably) added the - construction environment in our place. + This is added to a construction environment in place of a + method(s) normally called for a Builder (env.Object, env.StaticObject, + etc.). When called, it has its associated ToolInitializer + object search the specified list of tools and apply the first + one that exists to the construction environment. It then calls + whatever builder was (presumably) added to the construction + environment in place of this particular instance. """ - def __init__(self, name, tools): + def __init__(self, name, initializer): """ Note: we store the tool name as __name__ so it can be used by the class that attaches this to a construction environment. """ self.__name__ = name - if not SCons.Util.is_List(tools): - tools = [tools] - self.tools = tools - def __call__(self, env, *args, **kw): - for t in self.tools: - tool = SCons.Tool.Tool(t) - if tool.exists(env): - env.Tool(tool) - break + self.initializer = initializer + + def get_builder(self, env): + """ + Returns the appropriate real Builder for this method name + after having the associated ToolInitializer object apply + the appropriate Tool module. + """ + builder = getattr(env, self.__name__) + + self.initializer.apply_tools(env) builder = getattr(env, self.__name__) if builder is self: @@ -455,21 +462,79 @@ def __call__(self, env, *args, **kw): # for this name was found (or possibly there's a mismatch # between the name we were called by and the Builder name # added by the Tool module). - # - # (Eventually this is where we'll put a more informative - # error message about the inability to find that tool - # as cut over more Builders+Tools to using this. - return [], [] + return None - # Let the construction environment remove the added method - # so we no longer copy and re-bind this method when the - # construction environment gets cloned. - env.RemoveMethod(self) + self.initializer.remove_methods(env) + + return builder + + def __call__(self, env, *args, **kw): + """ + """ + builder = self.get_builder(env) + if builder is None: + return [], [] return apply(builder, args, kw) +class ToolInitializer: + """ + A class for delayed initialization of Tools modules. + + Instances of this class associate a list of Tool modules with + a list of Builder method names that will be added by those Tool + modules. As part of instantiating this object for a particular + construction environment, we also add the appropriate + ToolInitializerMethod objects for the various Builder methods + that we want to use to delay Tool searches until necessary. + """ + def __init__(self, env, tools, names): + if not SCons.Util.is_List(tools): + tools = [tools] + if not SCons.Util.is_List(names): + names = [names] + self.env = env + self.tools = tools + self.names = names + self.methods = {} + for name in names: + method = ToolInitializerMethod(name, self) + self.methods[name] = method + env.AddMethod(method) + + def remove_methods(self, env): + """ + Removes the methods that were added by the tool initialization + so we no longer copy and re-bind them when the construction + environment gets cloned. + """ + for method in self.methods.values(): + env.RemoveMethod(method) + + def apply_tools(self, env): + """ + Searches the list of associated Tool modules for one that + exists, and applies that to the construction environment. + """ + for t in self.tools: + tool = SCons.Tool.Tool(t) + if tool.exists(env): + env.Tool(tool) + return + + # If we fall through here, there was no tool module found. + # This is where we can put an informative error message + # about the inability to find the tool. We'll start doing + # this as we cut over more pre-defined Builder+Tools to use + # the ToolInitializer class. + def Initializers(env): - env.AddMethod(ToolInitializer('Install', 'install')) - env.AddMethod(ToolInitializer('InstallAs', 'install')) + ToolInitializer(env, ['install'], ['_InternalInstall', '_InternalInstallAs']) + def Install(self, *args, **kw): + return apply(self._InternalInstall, args, kw) + def InstallAs(self, *args, **kw): + return apply(self._InternalInstallAs, args, kw) + env.AddMethod(Install) + env.AddMethod(InstallAs) def FindTool(tools, env): for tool in tools: @@ -496,7 +561,7 @@ def tool_list(platform, env): c_compilers = ['msvc', 'mingw', 'gcc', 'intelc', 'icl', 'icc', 'cc', 'bcc32' ] cxx_compilers = ['msvc', 'intelc', 'icc', 'g++', 'c++', 'bcc32' ] assemblers = ['masm', 'nasm', 'gas', '386asm' ] - fortran_compilers = ['g77', 'ifl', 'cvf', 'f95', 'f90', 'fortran'] + fortran_compilers = ['gfortran', 'g77', 'ifl', 'cvf', 'f95', 'f90', 'fortran'] ars = ['mslib', 'ar', 'tlib'] elif str(platform) == 'os2': "prefer IBM tools on OS/2" @@ -520,7 +585,8 @@ def tool_list(platform, env): c_compilers = ['suncc', 'gcc', 'cc'] cxx_compilers = ['sunc++', 'g++', 'c++'] assemblers = ['as', 'gas'] - fortran_compilers = ['f95', 'f90', 'f77', 'g77', 'fortran'] + fortran_compilers = ['sunf95', 'sunf90', 'sunf77', 'f95', 'f90', 'f77', + 'gfortran', 'g77', 'fortran'] ars = ['sunar'] elif str(platform) == 'hpux': "prefer aCC tools on HP-UX" @@ -544,7 +610,7 @@ def tool_list(platform, env): c_compilers = ['gcc', 'cc'] cxx_compilers = ['g++', 'c++'] assemblers = ['as'] - fortran_compilers = ['f95', 'f90', 'g77'] + fortran_compilers = ['gfortran', 'f95', 'f90', 'g77'] ars = ['ar'] else: "prefer GNU tools on all other platforms" @@ -552,7 +618,7 @@ def tool_list(platform, env): c_compilers = ['gcc', 'msvc', 'intelc', 'icc', 'cc'] cxx_compilers = ['g++', 'msvc', 'intelc', 'icc', 'c++'] assemblers = ['gas', 'nasm', 'masm'] - fortran_compilers = ['f95', 'f90', 'g77', 'ifort', 'ifl', 'fortran'] + fortran_compilers = ['gfortran', 'g77', 'ifort', 'ifl', 'f95', 'f90', 'f77'] ars = ['ar', 'mslib'] c_compiler = FindTool(c_compilers, env) or c_compilers[0] diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/aixc++.py b/scons/scons-local-1.2.0/SCons/Tool/aixc++.py similarity index 93% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/aixc++.py rename to scons/scons-local-1.2.0/SCons/Tool/aixc++.py index 380a9b9512..5db91f7686 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/aixc++.py +++ b/scons/scons-local-1.2.0/SCons/Tool/aixc++.py @@ -9,7 +9,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/aixc++.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/aixc++.py 3842 2008/12/20 22:59:52 scons" import os.path diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/aixcc.py b/scons/scons-local-1.2.0/SCons/Tool/aixcc.py similarity index 92% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/aixcc.py rename to scons/scons-local-1.2.0/SCons/Tool/aixcc.py index 2e43faf177..3c0b9d7686 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/aixcc.py +++ b/scons/scons-local-1.2.0/SCons/Tool/aixcc.py @@ -8,7 +8,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/aixcc.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/aixcc.py 3842 2008/12/20 22:59:52 scons" import os.path diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/aixf77.py b/scons/scons-local-1.2.0/SCons/Tool/aixf77.py similarity index 93% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/aixf77.py rename to scons/scons-local-1.2.0/SCons/Tool/aixf77.py index 4b3567725c..794f7e2200 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/aixf77.py +++ b/scons/scons-local-1.2.0/SCons/Tool/aixf77.py @@ -8,7 +8,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/aixf77.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/aixf77.py 3842 2008/12/20 22:59:52 scons" import os.path diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/aixlink.py b/scons/scons-local-1.2.0/SCons/Tool/aixlink.py similarity index 93% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/aixlink.py rename to scons/scons-local-1.2.0/SCons/Tool/aixlink.py index 858121cf71..3a1182a645 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/aixlink.py +++ b/scons/scons-local-1.2.0/SCons/Tool/aixlink.py @@ -8,7 +8,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/aixlink.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/aixlink.py 3842 2008/12/20 22:59:52 scons" import os import os.path diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/applelink.py b/scons/scons-local-1.2.0/SCons/Tool/applelink.py similarity index 84% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/applelink.py rename to scons/scons-local-1.2.0/SCons/Tool/applelink.py index a63fcdf3fd..eb8df8caf6 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/applelink.py +++ b/scons/scons-local-1.2.0/SCons/Tool/applelink.py @@ -9,7 +9,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,23 +31,25 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/applelink.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/applelink.py 3842 2008/12/20 22:59:52 scons" import SCons.Util -import gnulink +# Even though the Mac is based on the GNU toolchain, it doesn't understand +# the -rpath option, so we use the "link" tool instead of "gnulink". +import link def generate(env): """Add Builders and construction variables for applelink to an Environment.""" - gnulink.generate(env) + link.generate(env) env['FRAMEWORKPATHPREFIX'] = '-F' env['_FRAMEWORKPATH'] = '${_concat(FRAMEWORKPATHPREFIX, FRAMEWORKPATH, "", __env__)}' env['_FRAMEWORKS'] = '${_concat("-framework ", FRAMEWORKS, "", __env__)}' - env['LINKCOM'] = env['LINKCOM'] + ' $_FRAMEWORKPATH $_FRAMEWORKS' + env['LINKCOM'] = env['LINKCOM'] + ' $_FRAMEWORKPATH $_FRAMEWORKS $FRAMEWORKSFLAGS' env['SHLINKFLAGS'] = SCons.Util.CLVar('$LINKFLAGS -dynamiclib') - env['SHLINKCOM'] = env['SHLINKCOM'] + ' $_FRAMEWORKPATH $_FRAMEWORKS' + env['SHLINKCOM'] = env['SHLINKCOM'] + ' $_FRAMEWORKPATH $_FRAMEWORKS $FRAMEWORKSFLAGS' # override the default for loadable modules, which are different # on OS X than dynamic shared libs. echoing what XCode does for @@ -60,5 +62,4 @@ def generate(env): def exists(env): - import sys - return sys.platform == 'darwin' + return env['PLATFORM'] == 'darwin' diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/ar.py b/scons/scons-local-1.2.0/SCons/Tool/ar.py similarity index 92% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/ar.py rename to scons/scons-local-1.2.0/SCons/Tool/ar.py index 65bec7fa7f..7812fb3f2c 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/ar.py +++ b/scons/scons-local-1.2.0/SCons/Tool/ar.py @@ -9,7 +9,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/ar.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/ar.py 3842 2008/12/20 22:59:52 scons" import SCons.Defaults import SCons.Tool diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/as.py b/scons/scons-local-1.2.0/SCons/Tool/as.py similarity index 93% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/as.py rename to scons/scons-local-1.2.0/SCons/Tool/as.py index 25fd5dbf12..623c8d75ce 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/as.py +++ b/scons/scons-local-1.2.0/SCons/Tool/as.py @@ -9,7 +9,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/as.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/as.py 3842 2008/12/20 22:59:52 scons" import SCons.Defaults import SCons.Tool @@ -40,7 +40,7 @@ assemblers = ['as'] ASSuffixes = ['.s', '.asm', '.ASM'] -ASPPSuffixes = ['.spp', '.SPP'] +ASPPSuffixes = ['.spp', '.SPP', '.sx'] if SCons.Util.case_sensitive_suffixes('.s', '.S'): ASPPSuffixes.extend(['.S']) else: diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/bcc32.py b/scons/scons-local-1.2.0/SCons/Tool/bcc32.py similarity index 94% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/bcc32.py rename to scons/scons-local-1.2.0/SCons/Tool/bcc32.py index 5a40c09a62..0488ba780f 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/bcc32.py +++ b/scons/scons-local-1.2.0/SCons/Tool/bcc32.py @@ -5,7 +5,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,7 +27,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/bcc32.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/bcc32.py 3842 2008/12/20 22:59:52 scons" import os import os.path diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/c++.py b/scons/scons-local-1.2.0/SCons/Tool/c++.py similarity index 88% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/c++.py rename to scons/scons-local-1.2.0/SCons/Tool/c++.py index 6b9f0a92bd..979814983e 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/c++.py +++ b/scons/scons-local-1.2.0/SCons/Tool/c++.py @@ -8,7 +8,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/c++.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/c++.py 3842 2008/12/20 22:59:52 scons" import os.path @@ -71,13 +71,13 @@ def generate(env): shared_obj.add_emitter(suffix, SCons.Defaults.SharedObjectEmitter) SCons.Tool.cc.add_common_cc_variables(env) - + env['CXX'] = 'c++' - env['CXXFLAGS'] = SCons.Util.CLVar('$CCFLAGS') - env['CXXCOM'] = '$CXX -o $TARGET -c $CXXFLAGS $_CCCOMCOM $SOURCES' + env['CXXFLAGS'] = SCons.Util.CLVar('') + env['CXXCOM'] = '$CXX -o $TARGET -c $CXXFLAGS $CCFLAGS $_CCCOMCOM $SOURCES' env['SHCXX'] = '$CXX' env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS') - env['SHCXXCOM'] = '$SHCXX -o $TARGET -c $SHCXXFLAGS $_CCCOMCOM $SOURCES' + env['SHCXXCOM'] = '$SHCXX -o $TARGET -c $SHCXXFLAGS $SHCCFLAGS $_CCCOMCOM $SOURCES' env['CPPDEFPREFIX'] = '-D' env['CPPDEFSUFFIX'] = '' diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/cc.py b/scons/scons-local-1.2.0/SCons/Tool/cc.py similarity index 96% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/cc.py rename to scons/scons-local-1.2.0/SCons/Tool/cc.py index e4e87c7e55..ef1249d4c2 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/cc.py +++ b/scons/scons-local-1.2.0/SCons/Tool/cc.py @@ -8,7 +8,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/cc.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/cc.py 3842 2008/12/20 22:59:52 scons" import SCons.Tool import SCons.Defaults diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/cvf.py b/scons/scons-local-1.2.0/SCons/Tool/cvf.py similarity index 93% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/cvf.py rename to scons/scons-local-1.2.0/SCons/Tool/cvf.py index 689038ea16..203d9e4142 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/cvf.py +++ b/scons/scons-local-1.2.0/SCons/Tool/cvf.py @@ -5,7 +5,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,7 +27,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/cvf.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/cvf.py 3842 2008/12/20 22:59:52 scons" import fortran diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/default.py b/scons/scons-local-1.2.0/SCons/Tool/default.py similarity index 89% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/default.py rename to scons/scons-local-1.2.0/SCons/Tool/default.py index 182aa947d1..a105f7f0cd 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/default.py +++ b/scons/scons-local-1.2.0/SCons/Tool/default.py @@ -9,7 +9,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/default.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/default.py 3842 2008/12/20 22:59:52 scons" import SCons.Tool diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/dmd.py b/scons/scons-local-1.2.0/SCons/Tool/dmd.py similarity index 87% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/dmd.py rename to scons/scons-local-1.2.0/SCons/Tool/dmd.py index 8ef3651895..88bff8abd0 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/dmd.py +++ b/scons/scons-local-1.2.0/SCons/Tool/dmd.py @@ -14,14 +14,15 @@ blah.lib from the directory where SConstruct resides. Compiler variables: - DC - The name of the D compiler to use. Defaults to dmd. + DC - The name of the D compiler to use. Defaults to dmd or gdmd, + whichever is found. DPATH - List of paths to search for import modules. DVERSIONS - List of version tags to enable when compiling. DDEBUG - List of debug tags to enable when compiling. Linker related variables: LIBS - List of library files to link in. - DLINK - Name of the linker to use. Defaults to dmd. + DLINK - Name of the linker to use. Defaults to dmd or gdmd. DLINKFLAGS - List of linker flags. Lib tool variables: @@ -31,7 +32,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -53,7 +54,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/dmd.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/dmd.py 3842 2008/12/20 22:59:52 scons" import os import string @@ -93,7 +94,8 @@ def generate(env): static_obj.add_emitter('.d', SCons.Defaults.StaticObjectEmitter) shared_obj.add_emitter('.d', SCons.Defaults.SharedObjectEmitter) - env['DC'] = 'dmd' + dc = env.Detect(['dmd', 'gdmd']) + env['DC'] = dc env['DCOM'] = '$DC $_DINCFLAGS $_DVERFLAGS $_DDEBUGFLAGS $_DFLAGS -c -of$TARGET $SOURCES' env['_DINCFLAGS'] = '$( ${_concat(DINCPREFIX, DPATH, DINCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)' env['_DVERFLAGS'] = '$( ${_concat(DVERPREFIX, DVERSIONS, DVERSUFFIX, __env__)} $)' @@ -105,14 +107,15 @@ def generate(env): env['DVERSIONS'] = [] env['DDEBUG'] = [] - # Add the path to the standard library. - # This is merely for the convenience of the dependency scanner. - dmd_path = env.WhereIs('dmd') - if dmd_path: - x = string.rindex(dmd_path, 'dmd') - phobosDir = dmd_path[:x] + '/../src/phobos' - if os.path.isdir(phobosDir): - env.Append(DPATH = [phobosDir]) + if dc: + # Add the path to the standard library. + # This is merely for the convenience of the dependency scanner. + dmd_path = env.WhereIs(dc) + if dmd_path: + x = string.rindex(dmd_path, dc) + phobosDir = dmd_path[:x] + '/../src/phobos' + if os.path.isdir(phobosDir): + env.Append(DPATH = [phobosDir]) env['DINCPREFIX'] = '-I' env['DINCSUFFIX'] = '' @@ -191,14 +194,17 @@ def _smartLib(source, target, env, for_signature, env['SMART_LINKCOM'] = smart_link[linkcom] except KeyError: def _smartLink(source, target, env, for_signature, - defaultLinker=linkcom): + defaultLinker=linkcom, dc=dc): if isD(source): try: libs = env['LIBS'] except KeyError: libs = [] if 'phobos' not in libs: - env.Append(LIBS = ['phobos']) + if dc is 'dmd': + env.Append(LIBS = ['phobos']) + elif dc is 'gdmd': + env.Append(LIBS = ['gphobos']) if 'pthread' not in libs: env.Append(LIBS = ['pthread']) if 'm' not in libs: @@ -209,4 +215,4 @@ def _smartLink(source, target, env, for_signature, env['LINKCOM'] = '$SMART_LINKCOM ' def exists(env): - return env.Detect('dmd') + return env.Detect(['dmd', 'gdmd']) diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/dvi.py b/scons/scons-local-1.2.0/SCons/Tool/dvi.py similarity index 92% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/dvi.py rename to scons/scons-local-1.2.0/SCons/Tool/dvi.py index a4eff52c08..af65671eac 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/dvi.py +++ b/scons/scons-local-1.2.0/SCons/Tool/dvi.py @@ -5,7 +5,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,7 +27,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/dvi.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/dvi.py 3842 2008/12/20 22:59:52 scons" import SCons.Builder import SCons.Tool diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/dvipdf.py b/scons/scons-local-1.2.0/SCons/Tool/dvipdf.py similarity index 62% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/dvipdf.py rename to scons/scons-local-1.2.0/SCons/Tool/dvipdf.py index eae34b0c76..821d125e67 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/dvipdf.py +++ b/scons/scons-local-1.2.0/SCons/Tool/dvipdf.py @@ -9,7 +9,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,14 +31,54 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/dvipdf.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/dvipdf.py 3842 2008/12/20 22:59:52 scons" import SCons.Action import SCons.Defaults import SCons.Tool.pdf +import SCons.Tool.tex import SCons.Util +_null = SCons.Scanner.LaTeX._null + +def DviPdfPsFunction(XXXDviAction, target = None, source= None, env=None): + """A builder for DVI files that sets the TEXPICTS environment + variable before running dvi2ps or dvipdf.""" + + try: + abspath = source[0].attributes.path + except AttributeError : + abspath = '' + + saved_env = SCons.Scanner.LaTeX.modify_env_var(env, 'TEXPICTS', abspath) + + result = XXXDviAction(target, source, env) + + if saved_env is _null: + try: + del env['ENV']['TEXPICTS'] + except KeyError: + pass # was never set + else: + env['ENV']['TEXPICTS'] = saved_env + + return result + +def DviPdfFunction(target = None, source= None, env=None): + result = DviPdfPsFunction(PDFAction,target,source,env) + return result + +def DviPdfStrFunction(target = None, source= None, env=None): + """A strfunction for dvipdf that returns the appropriate + command string for the no_exec options.""" + if env.GetOption("no_exec"): + result = env.subst('$DVIPDFCOM',0,target,source) + else: + result = '' + return result + PDFAction = None +DVIPDFAction = None def PDFEmitter(target, source, env): """Strips any .aux or .log files from the input source list. @@ -57,11 +97,15 @@ def generate(env): if PDFAction is None: PDFAction = SCons.Action.Action('$DVIPDFCOM', '$DVIPDFCOMSTR') + global DVIPDFAction + if DVIPDFAction is None: + DVIPDFAction = SCons.Action.Action(DviPdfFunction, strfunction = DviPdfStrFunction) + import pdf pdf.generate(env) bld = env['BUILDERS']['PDF'] - bld.add_action('.dvi', PDFAction) + bld.add_action('.dvi', DVIPDFAction) bld.add_emitter('.dvi', PDFEmitter) env['DVIPDF'] = 'dvipdf' diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/dvips.py b/scons/scons-local-1.2.0/SCons/Tool/dvips.py similarity index 71% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/dvips.py rename to scons/scons-local-1.2.0/SCons/Tool/dvips.py index 3d30f0cb77..db763f1d08 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/dvips.py +++ b/scons/scons-local-1.2.0/SCons/Tool/dvips.py @@ -9,7 +9,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,13 +31,28 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/dvips.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/dvips.py 3842 2008/12/20 22:59:52 scons" import SCons.Action import SCons.Builder +import SCons.Tool.dvipdf import SCons.Util +def DviPsFunction(target = None, source= None, env=None): + result = SCons.Tool.dvipdf.DviPdfPsFunction(PSAction,target,source,env) + return result + +def DviPsStrFunction(target = None, source= None, env=None): + """A strfunction for dvipdf that returns the appropriate + command string for the no_exec options.""" + if env.GetOption("no_exec"): + result = env.subst('$PSCOM',0,target,source) + else: + result = '' + return result + PSAction = None +DVIPSAction = None PSBuilder = None def generate(env): @@ -46,19 +61,24 @@ def generate(env): if PSAction is None: PSAction = SCons.Action.Action('$PSCOM', '$PSCOMSTR') + global DVIPSAction + if DVIPSAction is None: + DVIPSAction = SCons.Action.Action(DviPsFunction, strfunction = DviPsStrFunction) + global PSBuilder if PSBuilder is None: PSBuilder = SCons.Builder.Builder(action = PSAction, prefix = '$PSPREFIX', suffix = '$PSSUFFIX', src_suffix = '.dvi', - src_builder = 'DVI') + src_builder = 'DVI', + single_source=True) env['BUILDERS']['PostScript'] = PSBuilder env['DVIPS'] = 'dvips' env['DVIPSFLAGS'] = SCons.Util.CLVar('') - # I'm not quite sure I got the directories and filenames right for build_dir + # I'm not quite sure I got the directories and filenames right for variant_dir # We need to be in the correct directory for the sake of latex \includegraphics eps included files. env['PSCOM'] = 'cd ${TARGET.dir} && $DVIPS $DVIPSFLAGS -o ${TARGET.file} ${SOURCE.file}' env['PSPREFIX'] = '' diff --git a/scons/scons-local-1.2.0/SCons/Tool/f77.py b/scons/scons-local-1.2.0/SCons/Tool/f77.py new file mode 100644 index 0000000000..21ab6d82dd --- /dev/null +++ b/scons/scons-local-1.2.0/SCons/Tool/f77.py @@ -0,0 +1,56 @@ +"""engine.SCons.Tool.f77 + +Tool-specific initialization for the generic Posix f77 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 (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation +# +# 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__ = "src/engine/SCons/Tool/f77.py 3842 2008/12/20 22:59:52 scons" + +import SCons.Defaults +import SCons.Scanner.Fortran +import SCons.Tool +import SCons.Util +from SCons.Tool.FortranCommon import add_all_to_env, add_f77_to_env + +compilers = ['f77'] + +def generate(env): + add_all_to_env(env) + add_f77_to_env(env) + + fcomp = env.Detect(compilers) or 'f77' + env['F77'] = fcomp + env['SHF77'] = fcomp + + env['FORTRAN'] = fcomp + env['SHFORTRAN'] = fcomp + +def exists(env): + return env.Detect(compilers) diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/g77.py b/scons/scons-local-1.2.0/SCons/Tool/f90.py similarity index 67% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/g77.py rename to scons/scons-local-1.2.0/SCons/Tool/f90.py index 5afcc5fe48..1078d2ccaf 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/g77.py +++ b/scons/scons-local-1.2.0/SCons/Tool/f90.py @@ -1,6 +1,6 @@ -"""engine.SCons.Tool.g77 +"""engine.SCons.Tool.f90 -Tool-specific initialization for g77. +Tool-specific initialization for the generic Posix 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() @@ -9,7 +9,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,17 +31,26 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/g77.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/f90.py 3842 2008/12/20 22:59:52 scons" -import f77 +import SCons.Defaults +import SCons.Scanner.Fortran +import SCons.Tool +import SCons.Util +from SCons.Tool.FortranCommon import add_all_to_env, add_f90_to_env -compilers = ['g77', 'f77'] +compilers = ['f90'] def generate(env): - """Add Builders and construction variables for g77 to an Environment.""" - f77.generate(env) + add_all_to_env(env) + add_f90_to_env(env) - env['_FORTRAND'] = env.Detect(compilers) or 'g77' + fc = env.Detect(compilers) or 'f90' + env['F90'] = fc + env['SHF90'] = fc + + env['FORTRAN'] = fc + env['SHFORTRAN'] = fc def exists(env): return env.Detect(compilers) diff --git a/scons/scons-local-1.2.0/SCons/Tool/f95.py b/scons/scons-local-1.2.0/SCons/Tool/f95.py new file mode 100644 index 0000000000..012930ca7e --- /dev/null +++ b/scons/scons-local-1.2.0/SCons/Tool/f95.py @@ -0,0 +1,57 @@ +"""engine.SCons.Tool.f95 + +Tool-specific initialization for the generic Posix f95 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 (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation +# +# 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__ = "src/engine/SCons/Tool/f95.py 3842 2008/12/20 22:59:52 scons" + +import SCons.Defaults +import SCons.Tool +import SCons.Util +import fortran +from SCons.Tool.FortranCommon import add_all_to_env, add_f95_to_env + +compilers = ['f95'] + +def generate(env): + add_all_to_env(env) + add_f95_to_env(env) + + fcomp = env.Detect(compilers) or 'f95' + env['F95'] = fcomp + env['SHF95'] = fcomp + + env['FORTRAN'] = fcomp + env['SHFORTRAN'] = fcomp + + +def exists(env): + return env.Detect(compilers) diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/filesystem.py b/scons/scons-local-1.2.0/SCons/Tool/filesystem.py similarity index 94% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/filesystem.py rename to scons/scons-local-1.2.0/SCons/Tool/filesystem.py index ced41f86eb..dbab56202e 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/filesystem.py +++ b/scons/scons-local-1.2.0/SCons/Tool/filesystem.py @@ -8,7 +8,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/filesystem.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/filesystem.py 3842 2008/12/20 22:59:52 scons" import SCons from SCons.Tool.install import copyFunc diff --git a/scons/scons-local-1.2.0/SCons/Tool/fortran.py b/scons/scons-local-1.2.0/SCons/Tool/fortran.py new file mode 100644 index 0000000000..aa53cf61ba --- /dev/null +++ b/scons/scons-local-1.2.0/SCons/Tool/fortran.py @@ -0,0 +1,57 @@ +"""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 (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation +# +# 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__ = "src/engine/SCons/Tool/fortran.py 3842 2008/12/20 22:59:52 scons" + +import re +import string + +import SCons.Action +import SCons.Defaults +import SCons.Scanner.Fortran +import SCons.Tool +import SCons.Util +from SCons.Tool.FortranCommon import add_all_to_env, add_fortran_to_env + +compilers = ['f95', 'f90', 'f77'] + +def generate(env): + add_all_to_env(env) + add_fortran_to_env(env) + + fc = env.Detect(compilers) or 'f77' + env['SHFORTRAN'] = fc + env['FORTRAN'] = fc + +def exists(env): + return env.Detect(compilers) diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/g++.py b/scons/scons-local-1.2.0/SCons/Tool/g++.py similarity index 67% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/g++.py rename to scons/scons-local-1.2.0/SCons/Tool/g++.py index e3519a142d..feb39519e5 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/g++.py +++ b/scons/scons-local-1.2.0/SCons/Tool/g++.py @@ -9,7 +9,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,12 +31,12 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/g++.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/g++.py 3842 2008/12/20 22:59:52 scons" import os.path import re +import subprocess -import SCons.Defaults import SCons.Tool import SCons.Util @@ -53,35 +53,32 @@ def generate(env): env['CXX'] = env.Detect(compilers) # platform specific settings - if env['PLATFORM'] == 'cygwin': - env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS') - elif env['PLATFORM'] == 'aix': - # Original line from Christian Engel added -DPIC: - #env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS -DPIC -mminimal-toc') + if env['PLATFORM'] == 'aix': env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS -mminimal-toc') env['STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME'] = 1 env['SHOBJSUFFIX'] = '$OBJSUFFIX' elif env['PLATFORM'] == 'hpux': - # Original line from Christian Engel added -DPIC: - #env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS -fPIC -DPIC') - env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS -fPIC') env['SHOBJSUFFIX'] = '.pic.o' elif env['PLATFORM'] == 'sunos': - # Original line from Christian Engel added -DPIC: - #env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS -fPIC -DPIC') - env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS -fPIC') env['SHOBJSUFFIX'] = '.pic.o' - else: - # Original line from Christian Engel added -DPIC: - #env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS -fPIC -DPIC') - env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS -fPIC') # determine compiler version if env['CXX']: - line = os.popen(env['CXX'] + ' --version').readline() + #pipe = SCons.Action._subproc(env, [env['CXX'], '-dumpversion'], + pipe = SCons.Action._subproc(env, [env['CXX'], '--version'], + stdin = 'devnull', + stderr = 'devnull', + stdout = subprocess.PIPE) + if pipe.wait() != 0: return + # -dumpversion was added in GCC 3.0. As long as we're supporting + # GCC versions older than that, we should use --version and a + # regular expression. + #line = pipe.stdout.read().strip() + #if line: + # env['CXXVERSION'] = line + line = pipe.stdout.readline() match = re.search(r'[0-9]+(\.[0-9]+)+', line) if match: env['CXXVERSION'] = match.group(0) - def exists(env): return env.Detect(compilers) diff --git a/scons/scons-local-1.2.0/SCons/Tool/g77.py b/scons/scons-local-1.2.0/SCons/Tool/g77.py new file mode 100644 index 0000000000..effc9fcfcc --- /dev/null +++ b/scons/scons-local-1.2.0/SCons/Tool/g77.py @@ -0,0 +1,67 @@ +"""engine.SCons.Tool.g77 + +Tool-specific initialization for g77. + +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 (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation +# +# 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__ = "src/engine/SCons/Tool/g77.py 3842 2008/12/20 22:59:52 scons" + +import SCons.Util +from SCons.Tool.FortranCommon import add_all_to_env, add_f77_to_env + +compilers = ['g77', 'f77'] + +def generate(env): + """Add Builders and construction variables for g77 to an Environment.""" + add_all_to_env(env) + add_f77_to_env(env) + + fcomp = env.Detect(compilers) or 'g77' + if env['PLATFORM'] in ['cygwin', 'win32']: + env['SHFORTRANFLAGS'] = SCons.Util.CLVar('$FORTRANFLAGS') + env['SHF77FLAGS'] = SCons.Util.CLVar('$F77FLAGS') + else: + env['SHFORTRANFLAGS'] = SCons.Util.CLVar('$FORTRANFLAGS -fPIC') + env['SHF77FLAGS'] = SCons.Util.CLVar('$F77FLAGS -fPIC') + + env['FORTRAN'] = fcomp + env['SHFORTRAN'] = '$FORTRAN' + + env['F77'] = fcomp + env['SHF77'] = '$F77' + + env['INCFORTRANPREFIX'] = "-I" + env['INCFORTRANSUFFIX'] = "" + + env['INCF77PREFIX'] = "-I" + env['INCF77SUFFIX'] = "" + +def exists(env): + return env.Detect(compilers) diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/gas.py b/scons/scons-local-1.2.0/SCons/Tool/gas.py similarity index 90% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/gas.py rename to scons/scons-local-1.2.0/SCons/Tool/gas.py index e080c5e339..5595e9e136 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/gas.py +++ b/scons/scons-local-1.2.0/SCons/Tool/gas.py @@ -9,7 +9,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/gas.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/gas.py 3842 2008/12/20 22:59:52 scons" as_module = __import__('as', globals(), locals(), []) diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/gcc.py b/scons/scons-local-1.2.0/SCons/Tool/gcc.py similarity index 69% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/gcc.py rename to scons/scons-local-1.2.0/SCons/Tool/gcc.py index 81c1374115..db07575b2d 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/gcc.py +++ b/scons/scons-local-1.2.0/SCons/Tool/gcc.py @@ -9,7 +9,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,13 +31,14 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/gcc.py 2523 2007/12/12 09:37:41 knight" - -import SCons.Util +__revision__ = "src/engine/SCons/Tool/gcc.py 3842 2008/12/20 22:59:52 scons" import cc import os import re +import subprocess + +import SCons.Util compilers = ['gcc', 'cc'] @@ -52,7 +53,19 @@ def generate(env): env['SHCCFLAGS'] = SCons.Util.CLVar('$CCFLAGS -fPIC') # determine compiler version if env['CC']: - line = os.popen(env['CC'] + ' --version').readline() + #pipe = SCons.Action._subproc(env, [env['CC'], '-dumpversion'], + pipe = SCons.Action._subproc(env, [env['CC'], '--version'], + stdin = 'devnull', + stderr = 'devnull', + stdout = subprocess.PIPE) + if pipe.wait() != 0: return + # -dumpversion was added in GCC 3.0. As long as we're supporting + # GCC versions older than that, we should use --version and a + # regular expression. + #line = pipe.stdout.read().strip() + #if line: + # env['CCVERSION'] = line + line = pipe.stdout.readline() match = re.search(r'[0-9]+(\.[0-9]+)+', line) if match: env['CCVERSION'] = match.group(0) diff --git a/scons/scons-local-1.2.0/SCons/Tool/gfortran.py b/scons/scons-local-1.2.0/SCons/Tool/gfortran.py new file mode 100644 index 0000000000..7da19e4fd6 --- /dev/null +++ b/scons/scons-local-1.2.0/SCons/Tool/gfortran.py @@ -0,0 +1,58 @@ +"""SCons.Tool.gfortran + +Tool-specific initialization for gfortran, the GNU Fortran 95/Fortran +2003 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 (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation +# +# 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__ = "src/engine/SCons/Tool/gfortran.py 3842 2008/12/20 22:59:52 scons" + +import SCons.Util + +import fortran + +def generate(env): + """Add Builders and construction variables for gfortran to an + Environment.""" + fortran.generate(env) + + for dialect in ['F77', 'F90', 'FORTRAN', 'F95']: + env['%s' % dialect] = 'gfortran' + env['SH%s' % dialect] = '$%s' % dialect + if env['PLATFORM'] in ['cygwin', 'win32']: + env['SH%sFLAGS' % dialect] = SCons.Util.CLVar('$%sFLAGS' % dialect) + else: + env['SH%sFLAGS' % dialect] = SCons.Util.CLVar('$%sFLAGS -fPIC' % dialect) + + env['INC%sPREFIX' % dialect] = "-I" + env['INC%sSUFFIX' % dialect] = "" + +def exists(env): + return env.Detect('gfortran') diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/gnulink.py b/scons/scons-local-1.2.0/SCons/Tool/gnulink.py similarity index 92% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/gnulink.py rename to scons/scons-local-1.2.0/SCons/Tool/gnulink.py index 12d1a17286..de95ee1bbf 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/gnulink.py +++ b/scons/scons-local-1.2.0/SCons/Tool/gnulink.py @@ -9,7 +9,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/gnulink.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/gnulink.py 3842 2008/12/20 22:59:52 scons" import SCons.Util diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/gs.py b/scons/scons-local-1.2.0/SCons/Tool/gs.py similarity index 93% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/gs.py rename to scons/scons-local-1.2.0/SCons/Tool/gs.py index 7e7325c32b..c52440af63 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/gs.py +++ b/scons/scons-local-1.2.0/SCons/Tool/gs.py @@ -9,7 +9,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/gs.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/gs.py 3842 2008/12/20 22:59:52 scons" import SCons.Action import SCons.Platform diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/hpc++.py b/scons/scons-local-1.2.0/SCons/Tool/hpc++.py similarity index 93% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/hpc++.py rename to scons/scons-local-1.2.0/SCons/Tool/hpc++.py index 15eee3b3d8..299c701ed4 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/hpc++.py +++ b/scons/scons-local-1.2.0/SCons/Tool/hpc++.py @@ -9,7 +9,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/hpc++.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/hpc++.py 3842 2008/12/20 22:59:52 scons" import os.path import string diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/hpcc.py b/scons/scons-local-1.2.0/SCons/Tool/hpcc.py similarity index 90% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/hpcc.py rename to scons/scons-local-1.2.0/SCons/Tool/hpcc.py index 4b493e487a..a4da9568b5 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/hpcc.py +++ b/scons/scons-local-1.2.0/SCons/Tool/hpcc.py @@ -8,7 +8,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/hpcc.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/hpcc.py 3842 2008/12/20 22:59:52 scons" import SCons.Util diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/hplink.py b/scons/scons-local-1.2.0/SCons/Tool/hplink.py similarity index 92% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/hplink.py rename to scons/scons-local-1.2.0/SCons/Tool/hplink.py index 5a48155495..0eb5b0a6ba 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/hplink.py +++ b/scons/scons-local-1.2.0/SCons/Tool/hplink.py @@ -8,7 +8,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/hplink.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/hplink.py 3842 2008/12/20 22:59:52 scons" import os import os.path diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/icc.py b/scons/scons-local-1.2.0/SCons/Tool/icc.py similarity index 92% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/icc.py rename to scons/scons-local-1.2.0/SCons/Tool/icc.py index 5b1e1fd409..ac6d6aadea 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/icc.py +++ b/scons/scons-local-1.2.0/SCons/Tool/icc.py @@ -9,7 +9,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/icc.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/icc.py 3842 2008/12/20 22:59:52 scons" import cc diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/icl.py b/scons/scons-local-1.2.0/SCons/Tool/icl.py similarity index 91% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/icl.py rename to scons/scons-local-1.2.0/SCons/Tool/icl.py index 9ef0b120f0..322de79350 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/icl.py +++ b/scons/scons-local-1.2.0/SCons/Tool/icl.py @@ -9,7 +9,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/icl.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/icl.py 3842 2008/12/20 22:59:52 scons" import SCons.Tool.intelc diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/ifl.py b/scons/scons-local-1.2.0/SCons/Tool/ifl.py similarity index 71% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/ifl.py rename to scons/scons-local-1.2.0/SCons/Tool/ifl.py index d180d7fa58..bfb157e6e8 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/ifl.py +++ b/scons/scons-local-1.2.0/SCons/Tool/ifl.py @@ -9,7 +9,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,19 +31,32 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/ifl.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/ifl.py 3842 2008/12/20 22:59:52 scons" import SCons.Defaults - -import fortran +from SCons.Scanner.Fortran import FortranScan +from FortranCommon import add_all_to_env def generate(env): """Add Builders and construction variables for ifl to an Environment.""" - SCons.Tool.SourceFileScanner.add_scanner('.i90', fortran.FortranScan) - fortran.FortranSuffixes.extend(['.i90']) - fortran.generate(env) + fscan = FortranScan("FORTRANPATH") + SCons.Tool.SourceFileScanner.add_scanner('.i', fscan) + SCons.Tool.SourceFileScanner.add_scanner('.i90', fscan) + + if not env.has_key('FORTRANFILESUFFIXES'): + env['FORTRANFILESUFFIXES'] = ['.i'] + else: + env['FORTRANFILESUFFIXES'].append('.i') + + if not env.has_key('F90FILESUFFIXES'): + env['F90FILESUFFIXES'] = ['.i90'] + else: + env['F90FILESUFFIXES'].append('.i90') + + add_all_to_env(env) env['FORTRAN'] = 'ifl' + env['SHFORTRAN'] = '$FORTRAN' env['FORTRANCOM'] = '$FORTRAN $FORTRANFLAGS $_FORTRANINCFLAGS /c $SOURCES /Fo$TARGET' env['FORTRANPPCOM'] = '$FORTRAN $FORTRANFLAGS $CPPFLAGS $_CPPDEFFLAGS $_FORTRANINCFLAGS /c $SOURCES /Fo$TARGET' env['SHFORTRANCOM'] = '$SHFORTRAN $SHFORTRANFLAGS $_FORTRANINCFLAGS /c $SOURCES /Fo$TARGET' diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/ifort.py b/scons/scons-local-1.2.0/SCons/Tool/ifort.py similarity index 57% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/ifort.py rename to scons/scons-local-1.2.0/SCons/Tool/ifort.py index d89855bb2c..17b7bf7b3a 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/ifort.py +++ b/scons/scons-local-1.2.0/SCons/Tool/ifort.py @@ -1,7 +1,7 @@ """SCons.Tool.ifort Tool-specific initialization for newer versions of the Intel Fortran Compiler -for Linux. +for Linux/Windows (and possibly Mac OS X). There normally shouldn't be any need to import this module directly. It will usually be imported through the generic SCons.Tool.Tool() @@ -10,7 +10,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -32,42 +32,52 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/ifort.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/ifort.py 3842 2008/12/20 22:59:52 scons" import string import SCons.Defaults - -import fortran +from SCons.Scanner.Fortran import FortranScan +from FortranCommon import add_all_to_env def generate(env): """Add Builders and construction variables for ifort to an Environment.""" # ifort supports Fortran 90 and Fortran 95 # Additionally, ifort recognizes more file extensions. - SCons.Tool.SourceFileScanner.add_scanner('.i', fortran.FortranScan) - SCons.Tool.SourceFileScanner.add_scanner('.i90', fortran.FortranScan) - fortran.FortranSuffixes.extend(['.i', '.i90']) - fortran.generate(env) + fscan = FortranScan("FORTRANPATH") + SCons.Tool.SourceFileScanner.add_scanner('.i', fscan) + SCons.Tool.SourceFileScanner.add_scanner('.i90', fscan) + + if not env.has_key('FORTRANFILESUFFIXES'): + env['FORTRANFILESUFFIXES'] = ['.i'] + else: + env['FORTRANFILESUFFIXES'].append('.i') + + if not env.has_key('F90FILESUFFIXES'): + env['F90FILESUFFIXES'] = ['.i90'] + else: + env['F90FILESUFFIXES'].append('.i90') - env['_FORTRAND'] = 'ifort' + add_all_to_env(env) - # If files are compiled into objects, the Intel Fortran Compiler must use - # ld to link shared libraries. - env['SHLINK'] = 'ld' + fc = 'ifort' - # Additionally, no symbols can be defined in an archive file; to use - # Intel Fortran to create shared libraries, all external symbols must - # be in shared libraries. - env['SHLINKFLAGS'] = '-shared -no_archive' + for dialect in ['F77', 'F90', 'FORTRAN', 'F95']: + env['%s' % dialect] = fc + env['SH%s' % dialect] = '$%s' % dialect + env['SH%sFLAGS' % dialect] = SCons.Util.CLVar('$%sFLAGS -fPIC' % dialect) - # if env['PLATFORM'] == 'win32': # On Windows, the ifort compiler specifies the object on the # command line with -object:, not -o. Massage the necessary # command-line construction variables. - for var in ['_FORTRANCOMD', '_FORTRANPPCOMD', - '_SHFORTRANCOMD', '_SHFORTRANPPCOMD']: - env[var] = string.replace(env[var], '-o $TARGET', '-object:$TARGET') + for dialect in ['F77', 'F90', 'FORTRAN', 'F95']: + for var in ['%sCOM' % dialect, '%sPPCOM' % dialect, + 'SH%sCOM' % dialect, 'SH%sPPCOM' % dialect]: + env[var] = string.replace(env[var], '-o $TARGET', '-object:$TARGET') + env['FORTRANMODDIRPREFIX'] = "/module:" + else: + env['FORTRANMODDIRPREFIX'] = "-module " def exists(env): return env.Detect('ifort') diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/ilink.py b/scons/scons-local-1.2.0/SCons/Tool/ilink.py similarity index 91% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/ilink.py rename to scons/scons-local-1.2.0/SCons/Tool/ilink.py index faf3ece793..b443a6b688 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/ilink.py +++ b/scons/scons-local-1.2.0/SCons/Tool/ilink.py @@ -9,7 +9,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/ilink.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/ilink.py 3842 2008/12/20 22:59:52 scons" import SCons.Defaults import SCons.Tool diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/ilink32.py b/scons/scons-local-1.2.0/SCons/Tool/ilink32.py similarity index 89% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/ilink32.py rename to scons/scons-local-1.2.0/SCons/Tool/ilink32.py index b2cfe4de86..f357bec676 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/ilink32.py +++ b/scons/scons-local-1.2.0/SCons/Tool/ilink32.py @@ -5,7 +5,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,7 +27,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/ilink32.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/ilink32.py 3842 2008/12/20 22:59:52 scons" import SCons.Tool import SCons.Tool.bcc32 @@ -36,6 +36,7 @@ def generate(env): """Add Builders and construction variables for ilink to an Environment.""" + SCons.Tool.createSharedLibBuilder(env) SCons.Tool.createProgBuilder(env) env['LINK'] = '$CC' @@ -46,6 +47,7 @@ def generate(env): env['LIBLINKPREFIX']='' env['LIBLINKSUFFIX']='$LIBSUFFIX' + def exists(env): # Uses bcc32 to do linking as it generally knows where the standard # LIBS are and set up the linking correctly diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/install.py b/scons/scons-local-1.2.0/SCons/Tool/install.py similarity index 88% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/install.py rename to scons/scons-local-1.2.0/SCons/Tool/install.py index 1c7ff2e66e..be36be08c9 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/install.py +++ b/scons/scons-local-1.2.0/SCons/Tool/install.py @@ -8,7 +8,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/install.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/install.py 3842 2008/12/20 22:59:52 scons" import os import shutil @@ -75,7 +75,8 @@ def installFunc(target, source, env): except KeyError: raise SCons.Errors.UserError('Missing INSTALL construction variable.') - assert( len(target)==len(source) ) + assert len(target)==len(source), \ + "Installing source %s into target %s: target and source lists must have same length."%(map(str, source), map(str, target)) for t,s in zip(target,source): if install(t.get_path(),s.get_path(),env): return 1 @@ -131,8 +132,9 @@ def Dir(self, name): BaseInstallBuilder = None -def InstallBuilderWrapper(env, target, source, dir=None): +def InstallBuilderWrapper(env, target=None, source=None, dir=None, **kw): if target and dir: + import SCons.Errors raise SCons.Errors.UserError, "Both target and dir defined for Install(), only one may be defined." if not dir: dir=target @@ -156,13 +158,15 @@ def InstallBuilderWrapper(env, target, source, dir=None): # '#' on the file name portion as meaning the Node should # be relative to the top-level SConstruct directory. target = env.fs.Entry('.'+os.sep+src.name, dnode) - tgt.extend(BaseInstallBuilder(env, target, src)) + #tgt.extend(BaseInstallBuilder(env, target, src, **kw)) + tgt.extend(apply(BaseInstallBuilder, (env, target, src), kw)) return tgt -def InstallAsBuilderWrapper(env, target, source): +def InstallAsBuilderWrapper(env, target=None, source=None, **kw): result = [] for src, tgt in map(lambda x, y: (x, y), source, target): - result.extend(BaseInstallBuilder(env, tgt, src)) + #result.extend(BaseInstallBuilder(env, tgt, src, **kw)) + result.extend(apply(BaseInstallBuilder, (env, tgt, src), kw)) return result added = None @@ -195,15 +199,8 @@ def generate(env): emitter = [ add_targets_to_INSTALLED_FILES, ], name = 'InstallBuilder') - try: - env['BUILDERS']['Install'] - except KeyError, e: - env['BUILDERS']['Install'] = InstallBuilderWrapper - - try: - env['BUILDERS']['InstallAs'] - except KeyError, e: - env['BUILDERS']['InstallAs'] = InstallAsBuilderWrapper + env['BUILDERS']['_InternalInstall'] = InstallBuilderWrapper + env['BUILDERS']['_InternalInstallAs'] = InstallAsBuilderWrapper # We'd like to initialize this doing something like the following, # but there isn't yet support for a ${SOURCE.type} expansion that diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/intelc.py b/scons/scons-local-1.2.0/SCons/Tool/intelc.py similarity index 83% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/intelc.py rename to scons/scons-local-1.2.0/SCons/Tool/intelc.py index 7ecd70b555..dfdedc4abf 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/intelc.py +++ b/scons/scons-local-1.2.0/SCons/Tool/intelc.py @@ -10,7 +10,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -32,7 +32,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/intelc.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/intelc.py 3842 2008/12/20 22:59:52 scons" import math, sys, os.path, glob, string, re @@ -41,11 +41,14 @@ (os.environ.has_key('PROCESSOR_ARCHITEW6432') and os.environ['PROCESSOR_ARCHITEW6432'] == 'AMD64')) is_linux = sys.platform == 'linux2' +is_mac = sys.platform == 'darwin' if is_windows: import SCons.Tool.msvc elif is_linux: import SCons.Tool.gcc +elif is_mac: + import SCons.Tool.gcc import SCons.Util import SCons.Warnings @@ -98,14 +101,19 @@ def check_abi(abi): valid_abis = {'ia32' : 'ia32', 'x86' : 'ia32', 'ia64' : 'ia64', - 'em64t' : 'ia32e', - 'amd64' : 'ia32e'} + 'em64t' : 'em64t', + 'amd64' : 'em64t'} if is_linux: valid_abis = {'ia32' : 'ia32', 'x86' : 'ia32', 'x86_64' : 'x86_64', 'em64t' : 'x86_64', 'amd64' : 'x86_64'} + if is_mac: + valid_abis = {'ia32' : 'ia32', + 'x86' : 'ia32', + 'x86_64' : 'x86_64', + 'em64t' : 'x86_64'} try: abi = valid_abis[abi] except KeyError: @@ -196,8 +204,22 @@ def get_all_compiler_versions(): if ok: versions.append(subkey) else: - # Registry points to nonexistent dir. Ignore this version. - print "Ignoring "+str(get_intel_registry_value('ProductDir', subkey, 'IA32')) + try: + # Registry points to nonexistent dir. Ignore this + # version. + value = get_intel_registry_value('ProductDir', subkey, 'IA32') + except MissingRegistryError, e: + + # Registry key is left dangling (potentially + # after uninstalling). + + print \ + "scons: *** Ignoring the registry key for the Intel compiler version %s.\n" \ + "scons: *** It seems that the compiler was uninstalled and that the registry\n" \ + "scons: *** was not cleaned up properly.\n" % subkey + else: + print "scons: *** Ignoring "+str(value) + i = i + 1 except EnvironmentError: # no more subkeys @@ -205,11 +227,22 @@ def get_all_compiler_versions(): elif is_linux: for d in glob.glob('/opt/intel_cc_*'): # Typical dir here is /opt/intel_cc_80. - versions.append(re.search(r'cc_(.*)$', d).group(1)) + m = re.search(r'cc_(.*)$', d) + if m: + versions.append(m.group(1)) + for d in glob.glob('/opt/intel/cc*/*'): + # Typical dir here is /opt/intel/cc/9.0 for IA32, + # /opt/intel/cce/9.0 for EMT64 (AMD64) + m = re.search(r'([0-9.]+)$', d) + if m: + versions.append(m.group(1)) + elif is_mac: for d in glob.glob('/opt/intel/cc*/*'): # Typical dir here is /opt/intel/cc/9.0 for IA32, # /opt/intel/cce/9.0 for EMT64 (AMD64) - versions.append(re.search(r'([0-9.]+)$', d).group(1)) + m = re.search(r'([0-9.]+)$', d) + if m: + versions.append(m.group(1)) versions = uniquify(versions) # remove dups versions.sort(vercmp) return versions @@ -229,7 +262,7 @@ def get_intel_compiler_top(version, abi): if not os.path.exists(os.path.join(top, "Bin", "icl.exe")): raise MissingDirError, \ "Can't find Intel compiler in %s"%(top) - elif is_linux: + elif is_mac or is_linux: # first dir is new (>=9.0) style, second is old (8.0) style. dirs=('/opt/intel/cc/%s', '/opt/intel_cc_%s') if abi == 'x86_64': @@ -256,7 +289,7 @@ def generate(env, version=None, abi=None, topdir=None, verbose=0): If topdir is used, version and abi are ignored. verbose: (int) if >0, prints compiler version used. """ - if not (is_linux or is_windows): + if not (is_mac or is_linux or is_windows): # can't handle this platform return @@ -264,6 +297,8 @@ def generate(env, version=None, abi=None, topdir=None, verbose=0): SCons.Tool.msvc.generate(env) elif is_linux: SCons.Tool.gcc.generate(env) + elif is_mac: + SCons.Tool.gcc.generate(env) # if version is unspecified, use latest vlist = get_all_compiler_versions() @@ -284,7 +319,7 @@ def generate(env, version=None, abi=None, topdir=None, verbose=0): # alternatives are ia64 for Itanium, or amd64 or em64t or x86_64 (all synonyms here) abi = check_abi(abi) if abi is None: - if is_linux: + if is_mac or is_linux: # Check if we are on 64-bit linux, default to 64 then. uname_m = os.uname()[4] if uname_m == 'x86_64': @@ -308,7 +343,7 @@ def generate(env, version=None, abi=None, topdir=None, verbose=0): # on $PATH and the user is importing their env. class ICLTopDirWarning(SCons.Warnings.Warning): pass - if is_linux and not env.Detect('icc') or \ + if (is_mac or is_linux) and not env.Detect('icc') or \ is_windows and not env.Detect('icl'): SCons.Warnings.enableWarningClass(ICLTopDirWarning) @@ -325,11 +360,14 @@ class ICLTopDirWarning(SCons.Warnings.Warning): if topdir: if verbose: - print "Intel C compiler: using version '%s' (%g), abi %s, in '%s'"%\ - (version, linux_ver_normalize(version),abi,topdir) + print "Intel C compiler: using version %s (%g), abi %s, in '%s'"%\ + (repr(version), linux_ver_normalize(version),abi,topdir) if is_linux: # Show the actual compiler version by running the compiler. os.system('%s/bin/icc --version'%topdir) + if is_mac: + # Show the actual compiler version by running the compiler. + os.system('%s/bin/icc --version'%topdir) env['INTEL_C_COMPILER_TOP'] = topdir if is_linux: @@ -337,13 +375,24 @@ class ICLTopDirWarning(SCons.Warnings.Warning): 'LIB' : 'lib', 'PATH' : 'bin', 'LD_LIBRARY_PATH' : 'lib'} - for p in paths: + for p in paths.keys(): + env.PrependENVPath(p, os.path.join(topdir, paths[p])) + if is_mac: + paths={'INCLUDE' : 'include', + 'LIB' : 'lib', + 'PATH' : 'bin', + 'LD_LIBRARY_PATH' : 'lib'} + for p in paths.keys(): env.PrependENVPath(p, os.path.join(topdir, paths[p])) if is_windows: # env key reg valname default subdir of top paths=(('INCLUDE', 'IncludeDir', 'Include'), ('LIB' , 'LibDir', 'Lib'), ('PATH' , 'BinDir', 'Bin')) + # We are supposed to ignore version if topdir is set, so set + # it to the emptry string if it's not already set. + if version is None: + version = '' # Each path has a registry entry, use that or default to subdir for p in paths: try: @@ -392,7 +441,9 @@ class ICLTopDirWarning(SCons.Warnings.Warning): licdir = None for ld in [envlicdir, reglicdir]: - if ld and os.path.exists(ld): + # If the string contains an '@', then assume it's a network + # license (port@system) and good by definition. + if ld and (string.find(ld, '@') != -1 or os.path.exists(ld)): licdir = ld break if not licdir: @@ -409,7 +460,7 @@ class ICLLicenseDirWarning(SCons.Warnings.Warning): env['ENV']['INTEL_LICENSE_FILE'] = licdir def exists(env): - if not (is_linux or is_windows): + if not (is_mac or is_linux or is_windows): # can't handle this platform return 0 @@ -424,6 +475,8 @@ def exists(env): return env.Detect('icl') elif is_linux: return env.Detect('icc') + elif is_mac: + return env.Detect('icc') return detected # end of file diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/jar.py b/scons/scons-local-1.2.0/SCons/Tool/jar.py similarity index 79% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/jar.py rename to scons/scons-local-1.2.0/SCons/Tool/jar.py index dd2d6f1253..be50b016d7 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/jar.py +++ b/scons/scons-local-1.2.0/SCons/Tool/jar.py @@ -9,7 +9,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,26 +31,39 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/jar.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/jar.py 3842 2008/12/20 22:59:52 scons" import SCons.Subst import SCons.Util def jarSources(target, source, env, for_signature): """Only include sources that are not a manifest file.""" - jarchdir = env.subst('$JARCHDIR', target=target, source=source) - if jarchdir: - jarchdir = env.fs.Dir(jarchdir) + try: + env['JARCHDIR'] + except KeyError: + jarchdir_set = False + else: + jarchdir_set = True + jarchdir = env.subst('$JARCHDIR', target=target, source=source) + if jarchdir: + jarchdir = env.fs.Dir(jarchdir) result = [] for src in source: contents = src.get_contents() if contents[:16] != "Manifest-Version": - if jarchdir: + if jarchdir_set: + _chdir = jarchdir + else: + try: + _chdir = src.attributes.java_classdir + except AttributeError: + _chdir = None + if _chdir: # If we are changing the dir with -C, then sources should # be relative to that directory. - src = SCons.Subst.Literal(src.get_path(jarchdir)) + src = SCons.Subst.Literal(src.get_path(_chdir)) result.append('-C') - result.append(jarchdir) + result.append(_chdir) result.append(src) return result diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/javac.py b/scons/scons-local-1.2.0/SCons/Tool/javac.py similarity index 96% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/javac.py rename to scons/scons-local-1.2.0/SCons/Tool/javac.py index 54bc94e857..b8cabe89b9 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/javac.py +++ b/scons/scons-local-1.2.0/SCons/Tool/javac.py @@ -9,7 +9,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/javac.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/javac.py 3842 2008/12/20 22:59:52 scons" import os import os.path @@ -92,8 +92,9 @@ def visit(arg, dirname, names, fj=find_java, dirnode=entry.rdir()): raise SCons.Errors.UserError("Java source must be File or Dir, not '%s'" % entry.__class__) version = env.get('JAVAVERSION', '1.4') - tlist = [] + full_tlist = [] for f in slist: + tlist = [] source_file_based = True pkg_dir = None if not f.is_derived(): @@ -124,7 +125,12 @@ def visit(arg, dirname, names, fj=find_java, dirnode=entry.rdir()): t.attributes.java_classname = classname(base) tlist.append(t) - return tlist, slist + for t in tlist: + t.set_specific_source([f]) + + full_tlist.extend(tlist) + + return full_tlist, slist JavaAction = SCons.Action.Action('$JAVACCOM', '$JAVACCOMSTR') diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/javah.py b/scons/scons-local-1.2.0/SCons/Tool/javah.py similarity index 96% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/javah.py rename to scons/scons-local-1.2.0/SCons/Tool/javah.py index 195bfe068c..3a39aebcaf 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/javah.py +++ b/scons/scons-local-1.2.0/SCons/Tool/javah.py @@ -9,7 +9,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/javah.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/javah.py 3842 2008/12/20 22:59:52 scons" import os.path import string diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/latex.py b/scons/scons-local-1.2.0/SCons/Tool/latex.py similarity index 76% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/latex.py rename to scons/scons-local-1.2.0/SCons/Tool/latex.py index 6dab15e11c..549f6d3740 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/latex.py +++ b/scons/scons-local-1.2.0/SCons/Tool/latex.py @@ -9,7 +9,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/latex.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/latex.py 3842 2008/12/20 22:59:52 scons" import SCons.Action import SCons.Defaults @@ -43,9 +43,11 @@ LaTeXAction = None def LaTeXAuxFunction(target = None, source= None, env=None): - SCons.Tool.tex.InternalLaTeXAuxAction( LaTeXAction, target, source, env ) + result = SCons.Tool.tex.InternalLaTeXAuxAction( LaTeXAction, target, source, env ) + return result -LaTeXAuxAction = SCons.Action.Action(LaTeXAuxFunction, strfunction=None) +LaTeXAuxAction = SCons.Action.Action(LaTeXAuxFunction, + strfunction=SCons.Tool.tex.TeXLaTeXStrFunction) def generate(env): """Add Builders and construction variables for LaTeX to an Environment.""" @@ -56,14 +58,17 @@ def generate(env): import dvi dvi.generate(env) + import pdf + pdf.generate(env) + bld = env['BUILDERS']['DVI'] bld.add_action('.ltx', LaTeXAuxAction) bld.add_action('.latex', LaTeXAuxAction) - bld.add_emitter('.ltx', SCons.Tool.tex.tex_emitter) - bld.add_emitter('.latex', SCons.Tool.tex.tex_emitter) + bld.add_emitter('.ltx', SCons.Tool.tex.tex_eps_emitter) + bld.add_emitter('.latex', SCons.Tool.tex.tex_eps_emitter) env['LATEX'] = 'latex' - env['LATEXFLAGS'] = SCons.Util.CLVar('') + env['LATEXFLAGS'] = SCons.Util.CLVar('-interaction=nonstopmode') env['LATEXCOM'] = 'cd ${TARGET.dir} && $LATEX $LATEXFLAGS ${SOURCE.file}' env['LATEXRETRIES'] = 3 diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/lex.py b/scons/scons-local-1.2.0/SCons/Tool/lex.py similarity index 95% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/lex.py rename to scons/scons-local-1.2.0/SCons/Tool/lex.py index a710b64623..f2e0e856d5 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/lex.py +++ b/scons/scons-local-1.2.0/SCons/Tool/lex.py @@ -9,7 +9,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/lex.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/lex.py 3842 2008/12/20 22:59:52 scons" import os.path diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/link.py b/scons/scons-local-1.2.0/SCons/Tool/link.py similarity index 72% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/link.py rename to scons/scons-local-1.2.0/SCons/Tool/link.py index 97c6713da9..d02bb25fb4 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/link.py +++ b/scons/scons-local-1.2.0/SCons/Tool/link.py @@ -9,7 +9,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,19 +31,43 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/link.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/link.py 3842 2008/12/20 22:59:52 scons" import SCons.Defaults import SCons.Tool import SCons.Util +import SCons.Warnings + +from SCons.Tool.FortranCommon import isfortran cplusplus = __import__('c++', globals(), locals(), []) +issued_mixed_link_warning = False + def smart_link(source, target, env, for_signature): - if cplusplus.iscplusplus(source): + has_cplusplus = cplusplus.iscplusplus(source) + has_fortran = isfortran(env, source) + if has_cplusplus and has_fortran: + global issued_mixed_link_warning + if not issued_mixed_link_warning: + msg = "Using $CXX to link Fortran and C++ code together.\n\t" + \ + "This may generate a buggy executable if the %s\n\t" + \ + "compiler does not know how to deal with Fortran runtimes." + SCons.Warnings.warn(SCons.Warnings.FortranCxxMixWarning, + msg % repr(env.subst('$CXX'))) + issued_mixed_link_warning = True + return '$CXX' + elif has_fortran: + return '$FORTRAN' + elif has_cplusplus: return '$CXX' return '$CC' +def shlib_emitter(target, source, env): + for tgt in target: + tgt.attributes.shared = 1 + return (target, source) + def generate(env): """Add Builders and construction variables for gnulink to an Environment.""" SCons.Tool.createSharedLibBuilder(env) @@ -54,14 +78,14 @@ def generate(env): env['SHLINKCOM'] = '$SHLINK -o $TARGET $SHLINKFLAGS $SOURCES $_LIBDIRFLAGS $_LIBFLAGS' # don't set up the emitter, cause AppendUnique will generate a list # starting with None :-( - #env['SHLIBEMITTER']= None + env.Append(SHLIBEMITTER = [shlib_emitter]) env['SMARTLINK'] = smart_link env['LINK'] = "$SMARTLINK" env['LINKFLAGS'] = SCons.Util.CLVar('') env['LINKCOM'] = '$LINK -o $TARGET $LINKFLAGS $SOURCES $_LIBDIRFLAGS $_LIBFLAGS' env['LIBDIRPREFIX']='-L' env['LIBDIRSUFFIX']='' - env['_LIBFLAGS']='${_stripixes(LIBLINKPREFIX, LIBS, LIBLINKSUFFIX, LIBPREFIX, LIBSUFFIX, __env__)}' + env['_LIBFLAGS']='${_stripixes(LIBLINKPREFIX, LIBS, LIBLINKSUFFIX, LIBPREFIXES, LIBSUFFIXES, __env__)}' env['LIBLINKPREFIX']='-l' env['LIBLINKSUFFIX']='' diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/linkloc.py b/scons/scons-local-1.2.0/SCons/Tool/linkloc.py similarity index 95% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/linkloc.py rename to scons/scons-local-1.2.0/SCons/Tool/linkloc.py index 33e9c5c6e0..b0550c6e3b 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/linkloc.py +++ b/scons/scons-local-1.2.0/SCons/Tool/linkloc.py @@ -10,7 +10,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -32,7 +32,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/linkloc.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/linkloc.py 3842 2008/12/20 22:59:52 scons" import os.path import re diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/m4.py b/scons/scons-local-1.2.0/SCons/Tool/m4.py similarity index 92% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/m4.py rename to scons/scons-local-1.2.0/SCons/Tool/m4.py index fa9d50c5ad..0d81d7146f 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/m4.py +++ b/scons/scons-local-1.2.0/SCons/Tool/m4.py @@ -9,7 +9,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/m4.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/m4.py 3842 2008/12/20 22:59:52 scons" import SCons.Action import SCons.Builder diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/masm.py b/scons/scons-local-1.2.0/SCons/Tool/masm.py similarity index 93% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/masm.py rename to scons/scons-local-1.2.0/SCons/Tool/masm.py index 86f262c1af..8508900874 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/masm.py +++ b/scons/scons-local-1.2.0/SCons/Tool/masm.py @@ -9,7 +9,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,14 +31,14 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/masm.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/masm.py 3842 2008/12/20 22:59:52 scons" import SCons.Defaults import SCons.Tool import SCons.Util ASSuffixes = ['.s', '.asm', '.ASM'] -ASPPSuffixes = ['.spp', '.SPP'] +ASPPSuffixes = ['.spp', '.SPP', '.sx'] if SCons.Util.case_sensitive_suffixes('.s', '.S'): ASPPSuffixes.extend(['.S']) else: diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/midl.py b/scons/scons-local-1.2.0/SCons/Tool/midl.py similarity index 94% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/midl.py rename to scons/scons-local-1.2.0/SCons/Tool/midl.py index 4ca6c1a661..df1bf9a5d3 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/midl.py +++ b/scons/scons-local-1.2.0/SCons/Tool/midl.py @@ -9,7 +9,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/midl.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/midl.py 3842 2008/12/20 22:59:52 scons" import string diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/mingw.py b/scons/scons-local-1.2.0/SCons/Tool/mingw.py similarity index 96% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/mingw.py rename to scons/scons-local-1.2.0/SCons/Tool/mingw.py index 6dbf2ae926..faec2e9edb 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/mingw.py +++ b/scons/scons-local-1.2.0/SCons/Tool/mingw.py @@ -9,7 +9,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/mingw.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/mingw.py 3842 2008/12/20 22:59:52 scons" import os import os.path @@ -122,6 +122,7 @@ def generate(env): env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS') env['SHLINKFLAGS'] = SCons.Util.CLVar('$LINKFLAGS -shared') env['SHLINKCOM'] = shlib_action + env['LDMODULECOM'] = shlib_action env.Append(SHLIBEMITTER = [shlib_emitter]) env['AS'] = 'as' diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/mslib.py b/scons/scons-local-1.2.0/SCons/Tool/mslib.py similarity index 94% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/mslib.py rename to scons/scons-local-1.2.0/SCons/Tool/mslib.py index 038130f4f5..340f9927dd 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/mslib.py +++ b/scons/scons-local-1.2.0/SCons/Tool/mslib.py @@ -9,7 +9,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/mslib.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/mslib.py 3842 2008/12/20 22:59:52 scons" import SCons.Defaults import SCons.Tool diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/mslink.py b/scons/scons-local-1.2.0/SCons/Tool/mslink.py similarity index 86% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/mslink.py rename to scons/scons-local-1.2.0/SCons/Tool/mslink.py index 487dad98ce..298ae7c649 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/mslink.py +++ b/scons/scons-local-1.2.0/SCons/Tool/mslink.py @@ -9,7 +9,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/mslink.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/mslink.py 3842 2008/12/20 22:59:52 scons" import os.path @@ -76,6 +76,9 @@ def windowsShlinkSources(target, source, env, for_signature): def windowsLibEmitter(target, source, env): SCons.Tool.msvc.validate_vars(env) + extratargets = [] + extrasources = [] + dll = env.FindIxes(target, "SHLIBPREFIX", "SHLIBSUFFIX") no_import_lib = env.get('no_import_lib', 0) @@ -87,38 +90,44 @@ def windowsLibEmitter(target, source, env): not env.FindIxes(source, "WINDOWSDEFPREFIX", "WINDOWSDEFSUFFIX"): # append a def file to the list of sources - source.append(env.ReplaceIxes(dll, - "SHLIBPREFIX", "SHLIBSUFFIX", - "WINDOWSDEFPREFIX", "WINDOWSDEFSUFFIX")) + extrasources.append( + env.ReplaceIxes(dll, + "SHLIBPREFIX", "SHLIBSUFFIX", + "WINDOWSDEFPREFIX", "WINDOWSDEFSUFFIX")) version_num, suite = SCons.Tool.msvs.msvs_parse_version(env.get('MSVS_VERSION', '6.0')) if version_num >= 8.0 and env.get('WINDOWS_INSERT_MANIFEST', 0): # MSVC 8 automatically generates .manifest files that must be installed - target.append(env.ReplaceIxes(dll, - "SHLIBPREFIX", "SHLIBSUFFIX", - "WINDOWSSHLIBMANIFESTPREFIX", "WINDOWSSHLIBMANIFESTSUFFIX")) + extratargets.append( + env.ReplaceIxes(dll, + "SHLIBPREFIX", "SHLIBSUFFIX", + "WINDOWSSHLIBMANIFESTPREFIX", "WINDOWSSHLIBMANIFESTSUFFIX")) if env.has_key('PDB') and env['PDB']: pdb = env.arg2nodes('$PDB', target=target, source=source)[0] - target.append(pdb) + extratargets.append(pdb) target[0].attributes.pdb = pdb if not no_import_lib and \ not env.FindIxes(target, "LIBPREFIX", "LIBSUFFIX"): # Append an import library to the list of targets. - target.append(env.ReplaceIxes(dll, - "SHLIBPREFIX", "SHLIBSUFFIX", - "LIBPREFIX", "LIBSUFFIX")) + extratargets.append( + env.ReplaceIxes(dll, + "SHLIBPREFIX", "SHLIBSUFFIX", + "LIBPREFIX", "LIBSUFFIX")) # and .exp file is created if there are exports from a DLL - target.append(env.ReplaceIxes(dll, - "SHLIBPREFIX", "SHLIBSUFFIX", - "WINDOWSEXPPREFIX", "WINDOWSEXPSUFFIX")) + extratargets.append( + env.ReplaceIxes(dll, + "SHLIBPREFIX", "SHLIBSUFFIX", + "WINDOWSEXPPREFIX", "WINDOWSEXPSUFFIX")) - return (target, source) + return (target+extratargets, source+extrasources) def prog_emitter(target, source, env): SCons.Tool.msvc.validate_vars(env) + extratargets = [] + exe = env.FindIxes(target, "PROGPREFIX", "PROGSUFFIX") if not exe: raise SCons.Errors.UserError, "An executable should have exactly one target with the suffix: %s" % env.subst("$PROGSUFFIX") @@ -126,16 +135,17 @@ def prog_emitter(target, source, env): version_num, suite = SCons.Tool.msvs.msvs_parse_version(env.get('MSVS_VERSION', '6.0')) if version_num >= 8.0 and env.get('WINDOWS_INSERT_MANIFEST', 0): # MSVC 8 automatically generates .manifest files that have to be installed - target.append(env.ReplaceIxes(exe, - "PROGPREFIX", "PROGSUFFIX", - "WINDOWSPROGMANIFESTPREFIX", "WINDOWSPROGMANIFESTSUFFIX")) + extratargets.append( + env.ReplaceIxes(exe, + "PROGPREFIX", "PROGSUFFIX", + "WINDOWSPROGMANIFESTPREFIX", "WINDOWSPROGMANIFESTSUFFIX")) if env.has_key('PDB') and env['PDB']: pdb = env.arg2nodes('$PDB', target=target, source=source)[0] - target.append(pdb) + extratargets.append(pdb) target[0].attributes.pdb = pdb - return (target,source) + return (target+extratargets,source) def RegServerFunc(target, source, env): if env.has_key('register') and env['register']: diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/msvc.py b/scons/scons-local-1.2.0/SCons/Tool/msvc.py similarity index 93% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/msvc.py rename to scons/scons-local-1.2.0/SCons/Tool/msvc.py index 4f48750775..5b7874a202 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/msvc.py +++ b/scons/scons-local-1.2.0/SCons/Tool/msvc.py @@ -9,7 +9,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/msvc.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/msvc.py 3842 2008/12/20 22:59:52 scons" import os.path import re @@ -45,6 +45,7 @@ import SCons.Tool.msvs import SCons.Util import SCons.Warnings +import SCons.Scanner.RC CSuffixes = ['.c', '.C'] CXXSuffixes = ['.cc', '.cpp', '.cxx', '.c++', '.C++'] @@ -203,6 +204,11 @@ def _parse_msvc8_overrides(version,platform,suite): user_settings = doc.getElementsByTagName('UserSettings')[0] tool_options = user_settings.getElementsByTagName('ToolsOptions')[0] tool_options_categories = tool_options.getElementsByTagName('ToolsOptionsCategory') + environment_var_map = { + 'IncludeDirectories' : 'INCLUDE', + 'LibraryDirectories' : 'LIBRARY', + 'ExecutableDirectories' : 'PATH', + } for category in tool_options_categories: category_name = category.attributes.get('name') if category_name is not None and category_name.value == 'Projects': @@ -215,21 +221,21 @@ def _parse_msvc8_overrides(version,platform,suite): property_name = property.attributes.get('name') if property_name is None: continue - elif property_name.value == 'IncludeDirectories': - include_dirs = property.childNodes[0].data - # ToDo: Support for other destinations than Win32 - include_dirs = include_dirs.replace('Win32|', '') - dirs['INCLUDE'] = include_dirs - elif property_name.value == 'LibraryDirectories': - lib_dirs = property.childNodes[0].data.replace('Win32|', '') - # ToDo: Support for other destinations than Win32 - lib_dirs = lib_dirs.replace('Win32|', '') - dirs['LIBRARY'] = lib_dirs - elif property_name.value == 'ExecutableDirectories': - path_dirs = property.childNodes[0].data.replace('Win32|', '') - # ToDo: Support for other destinations than Win32 - path_dirs = path_dirs.replace('Win32|', '') - dirs['PATH'] = path_dirs + var_name = environment_var_map.get(property_name) + if var_name: + data = property.childNodes[0].data + value_list = string.split(data, '|') + if len(value_list) == 1: + dirs[var_name] = value_list[0] + else: + while value_list: + dest, value = value_list[:2] + del value_list[:2] + # ToDo: Support for destinations + # other than Win32 + if dest == 'Win32': + dirs[var_name] = value + break else: # There are no default directories in the registry for VS8 Express :( raise SCons.Errors.InternalError, "Unable to find MSVC paths in the registry." @@ -513,10 +519,6 @@ def _get_msvc8_default_paths(env, version, suite, use_mfc_dirs): include_paths.append( os.path.join( atlmfc_path, 'include' ) ) lib_paths.append( os.path.join( atlmfc_path, 'lib' ) ) - env_include_path = SCons.Util.get_environment_var('INCLUDE') - if env_include_path: - include_paths.append( env_include_path ) - if SCons.Util.can_read_reg and paths.has_key('FRAMEWORKSDKDIR'): fwdir = paths['FRAMEWORKSDKDIR'] include_paths.append( os.path.join( fwdir, 'include' ) ) @@ -659,13 +661,17 @@ def shared_object_emitter(target, source, env): pch_builder = SCons.Builder.Builder(action=pch_action, suffix='.pch', emitter=pch_emitter, source_scanner=SCons.Tool.SourceFileScanner) -res_action = SCons.Action.Action('$RCCOM', '$RCCOMSTR') + + +# Logic to build .rc files into .res files (resource files) +res_scanner = SCons.Scanner.RC.RCScan() +res_action = SCons.Action.Action('$RCCOM', '$RCCOMSTR') res_builder = SCons.Builder.Builder(action=res_action, src_suffix='.rc', suffix='.res', src_builder=[], - source_scanner=SCons.Tool.SourceFileScanner) -SCons.Tool.SourceFileScanner.add_scanner('.rc', SCons.Defaults.CScan) + source_scanner=res_scanner) + def generate(env): """Add Builders and construction variables for MSVC++ to an Environment.""" @@ -685,21 +691,21 @@ def generate(env): env['CCPDBFLAGS'] = SCons.Util.CLVar(['${(PDB and "/Z7") or ""}']) env['CCPCHFLAGS'] = SCons.Util.CLVar(['${(PCH and "/Yu%s /Fp%s"%(PCHSTOP or "",File(PCH))) or ""}']) - env['CCCOMFLAGS'] = '$CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS /c $SOURCES /Fo$TARGET $CCPCHFLAGS $CCPDBFLAGS' + env['_CCCOMCOM'] = '$CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS $CCPCHFLAGS $CCPDBFLAGS' env['CC'] = 'cl' env['CCFLAGS'] = SCons.Util.CLVar('/nologo') env['CFLAGS'] = SCons.Util.CLVar('') - env['CCCOM'] = '$CC $CFLAGS $CCFLAGS $CCCOMFLAGS' + env['CCCOM'] = '$CC /Fo$TARGET /c $SOURCES $CFLAGS $CCFLAGS $_CCCOMCOM' env['SHCC'] = '$CC' env['SHCCFLAGS'] = SCons.Util.CLVar('$CCFLAGS') env['SHCFLAGS'] = SCons.Util.CLVar('$CFLAGS') - env['SHCCCOM'] = '$SHCC $SHCFLAGS $SHCCFLAGS $CCCOMFLAGS' + env['SHCCCOM'] = '$SHCC /Fo$TARGET /c $SOURCES $SHCFLAGS $SHCCFLAGS $_CCCOMCOM' env['CXX'] = '$CC' env['CXXFLAGS'] = SCons.Util.CLVar('$CCFLAGS $( /TP $)') - env['CXXCOM'] = '$CXX $CXXFLAGS $CCCOMFLAGS' + env['CXXCOM'] = '$CXX /Fo$TARGET /c $SOURCES $CXXFLAGS $CCFLAGS $_CCCOMCOM' env['SHCXX'] = '$CXX' env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS') - env['SHCXXCOM'] = '$SHCXX $SHCXXFLAGS $CCCOMFLAGS' + env['SHCXXCOM'] = '$SHCXX /Fo$TARGET /c $SOURCES $SHCXXFLAGS $SHCCFLAGS $_CCCOMCOM' env['CPPDEFPREFIX'] = '/D' env['CPPDEFSUFFIX'] = '' env['INCPREFIX'] = '/I' @@ -710,6 +716,7 @@ def generate(env): env['RC'] = 'rc' env['RCFLAGS'] = SCons.Util.CLVar('') + env['RCSUFFIXES']=['.rc','.rc2'] env['RCCOM'] = '$RC $_CPPDEFFLAGS $_CPPINCFLAGS $RCFLAGS /fo$TARGET $SOURCES' env['BUILDERS']['RES'] = res_builder env['OBJPREFIX'] = '' diff --git a/scons/scons-local-0.97.0d20071212/SCons/Tool/msvs.py b/scons/scons-local-1.2.0/SCons/Tool/msvs.py similarity index 96% rename from scons/scons-local-0.97.0d20071212/SCons/Tool/msvs.py rename to scons/scons-local-1.2.0/SCons/Tool/msvs.py index 5e029321ac..f8a20ea1f0 100644 --- a/scons/scons-local-0.97.0d20071212/SCons/Tool/msvs.py +++ b/scons/scons-local-1.2.0/SCons/Tool/msvs.py @@ -9,7 +9,7 @@ """ # -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,10 +31,10 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/msvs.py 2523 2007/12/12 09:37:41 knight" +__revision__ = "src/engine/SCons/Tool/msvs.py 3842 2008/12/20 22:59:52 scons" import base64 -import md5 +import hashlib import os.path import pickle import re @@ -79,7 +79,11 @@ def _generateGUID(slnfile, name): based on the MD5 signatures of the sln filename plus the name of the project. It basically just needs to be unique, and not change with each invocation.""" - solution = _hexdigest(md5.new(str(slnfile)+str(name)).digest()).upper() + m = hashlib.md5() + m.update(str(slnfile) + str(name)) + # TODO(1.5) + #solution = m.hexdigest().upper() + solution = string.upper(_hexdigest(m.digest())) # convert most of the signature to GUID form (discard the rest) solution = "{" + solution[:8] + "-" + solution[8:12] + "-" + solution[12:16] + "-" + solution[16:20] + "-" + solution[20:32] + "}" return solution @@ -295,7 +299,9 @@ def __init__(self, dspfile, source, env): self.sources[t[0]].append(self.env[t[1]]) for n in sourcenames: - self.sources[n].sort(lambda a, b: cmp(a.lower(), b.lower())) + # TODO(1.5): + #self.sources[n].sort(lambda a, b: cmp(a.lower(), b.lower())) + self.sources[n].sort(lambda a, b: cmp(string.lower(a), string.lower(b))) def AddConfig(self, variant, buildtarget, outdir, runfile, cmdargs, dspfile=dspfile): config = Config() @@ -394,7 +400,9 @@ def PrintProject(self): for base in ("BASE ",""): self.file.write('# PROP %sUse_MFC 0\n' '# PROP %sUse_Debug_Libraries ' % (base, base)) - if kind.lower().find('debug') < 0: + # TODO(1.5): + #if kind.lower().find('debug') < 0: + if string.find(string.lower(kind), 'debug') < 0: self.file.write('0\n') else: self.file.write('1\n') @@ -445,13 +453,17 @@ def PrintSourceFiles(self): 'Other Files': ''} cats = categories.keys() - cats.sort(lambda a, b: cmp(a.lower(), b.lower())) + # TODO(1.5): + #cats.sort(lambda a, b: cmp(a.lower(), b.lower())) + cats.sort(lambda a, b: cmp(string.lower(a), string.lower(b))) for kind in cats: if not self.sources[kind]: continue # skip empty groups self.file.write('# Begin Group "' + kind + '"\n\n') - typelist = categories[kind].replace('|',';') + # TODO(1.5) + #typelist = categories[kind].replace('|', ';') + typelist = string.replace(categories[kind], '|', ';') self.file.write('# PROP Default_Filter "' + typelist + '"\n') for file in self.sources[kind]: @@ -474,7 +486,9 @@ def Parse(self): line = dspfile.readline() while line: - if line.find("# End Project") > -1: + # TODO(1.5): + #if line.find("# End Project") > -1: + if string.find(line, "# End Project") > -1: break line = dspfile.readline() @@ -692,7 +706,9 @@ def PrintProject(self): def printSources(self, hierarchy, commonprefix): sorteditems = hierarchy.items() - sorteditems.sort(lambda a, b: cmp(a[0].lower(), b[0].lower())) + # TODO(1.5): + #sorteditems.sort(lambda a, b: cmp(a[0].lower(), b[0].lower())) + sorteditems.sort(lambda a, b: cmp(string.lower(a[0]), string.lower(b[0]))) # First folders, then files for key, value in sorteditems: @@ -723,7 +739,9 @@ def PrintSourceFiles(self): self.file.write('\t\n') cats = categories.keys() - cats.sort(lambda a, b: cmp(a.lower(), b.lower())) + # TODO(1.5) + #cats.sort(lambda a, b: cmp(a.lower(), b.lower())) + cats.sort(lambda a, b: cmp(string.lower(a), string.lower(b))) cats = filter(lambda k, s=self: s.sources[k], cats) for kind in cats: if len(cats) > 1: @@ -772,7 +790,9 @@ def Parse(self): line = dspfile.readline() while line: - if line.find('