diff --git a/scons/scons-LICENSE b/scons/scons-LICENSE index 0e0b84cce..f16cda12d 100644 --- a/scons/scons-LICENSE +++ b/scons/scons-LICENSE @@ -1,9 +1,4 @@ - Copyright and license for SCons - a software construction tool - - 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 The SCons Foundation +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 diff --git a/scons/scons-README b/scons/scons-README index a563cb1d4..9f18e4d0c 100644 --- a/scons/scons-README +++ b/scons/scons-README @@ -1,42 +1,28 @@ -# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# src/README.txt 0.97.D001 2007/05/17 11:35:19 knight + SCons - a software construction tool -This is the scons-README file for a version of SCons packaged for local -execution--that is, execution out of a specific local directory, without -having to install SCons as a system-wide utility. + Version 0.97 -You are likely reading this file in one of the following two situations: - 1) You have unpacked an scons-local-{version} package and are - examining the contents. +This is a beta release of SCons, a tool for building software (and other +files). SCons is implemented in Python, and its "configuration files" +are actually Python scripts, allowing you to use the full power of a +real scripting language to solve build problems. You do not, however, +need to know Python to use SCons effectively. - In this case, you are presumably interested in using this - package to include a local copy of SCons with some other - software that you package, so that you can use SCons to build - your software without forcing all of your users to have it fully - installed. Instructions for this can be found below. +See the RELEASE.txt file for notes about this specific release, +including known problems. See the CHANGES.txt file for a list of +changes since the previous release. - If you are not looking to use SCons in this way, then please - use either the scons-{version} package to install SCons on your - system, or the scons-src-{version} package if you want the full - source to SCons, including its packaging code and underlying - tests and testing infrastructure. - - 2) This file was included in some other software package so that - the package could be built using SCons. - - In this case, follow the instructions provided with the - rest of the software package for how to use SCons to build - and/or install the software. The file containing build and - installation instructions will typically be named README or - INSTALL. LATEST VERSION ============== -Before going further, you can check for the latest version of the -scons-local package, or any SCons package, at the SCons download page: +Before going further, you can check that this package you have is +the latest version by checking the SCons download page at: http://www.scons.org/download.html @@ -45,93 +31,149 @@ EXECUTION REQUIREMENTS ====================== Running SCons requires Python version 1.5.2 or later. There should be -no other dependencies or requirements to run SCons. +no other dependencies or requirements to run SCons. (There is, however, +an additional requirement to *install* SCons from this particular +package; see the next section.) -The default SCons configuration assumes use of the Microsoft Visual C++ -compiler suite on WIN32 systems, and assumes a C compiler named 'cc', -a C++ compiler named 'c++', and a Fortran compiler named 'g77' (such -as found in the GNU C compiler suite) on any other type of system. -You may, of course, override these default values by appropriate +By default, SCons knows how to search for available programming tools +on various systems--see the SCons man page for details. You may, +of course, override the default SCons choices made by appropriate configuration of Environment construction variables. +INSTALLATION REQUIREMENTS +========================= + +Installing SCons from this package requires the Python distutils +package. The distutils package was not shipped as a standard part of +Python until Python version 1.6, so if your system is running Python +1.5.2, you may not have distutils installed. If you are running +Python version 1.6 or later, you should be fine. + +NOTE TO RED HAT USERS: Red Hat shipped Python 1.5.2 as the default all +the way up to Red Hat Linux 7.3, so you probably do *not* have distutils +installed, unless you have already done so manually or are running Red +Hat 8.0 or later. + +In this case, your options are: + + -- (Recommended.) Install from a pre-packaged SCons package that + does not require distutils: + + Red Hat Linux scons-0.97-1.noarch.rpm + + Debian GNU/Linux scons_0.97-1_all.deb + (or use apt-get) + + Windows scons-0.97.win32.exe + + -- (Optional.) Download the latest distutils package from the + following URL: + + http://www.python.org/sigs/distutils-sig/download.html + + Install the distutils according to the instructions on the page. + You can then proceed to the next section to install SCons from + this package. + + INSTALLATION ============ -Installation of this package should be as simple as unpacking the -archive (either .tar.gz or .zip) in any directory (top-level or a -subdirectory) within the software package with which you want to ship -SCons. +Assuming your system satisfies the installation requirements in the +previous section, install SCons from this package simply by running the +provided Python-standard setup script as follows: -Once you have installed this package, you should write an SConstruct -file at the top level of your source tree to build your software as you -see fit. + # python setup.py install -Then modify the build/install instructions for your package to instruct -your users to execute SCons as follows (if you installed this package in -your top-level directory): +By default, the above command will do the following: - $ python scons.py + -- Install the version-numbered "scons-0.97" and "sconsign-0.97" + scripts in the default system script directory (/usr/bin or + C:\Python*\Scripts, for example). This can be disabled by + specifying the "--no-version-script" option on the command + line. -Or (if, for example, you installed this package in a subdirectory named -"scons"): + -- Install scripts named "scons" and "sconsign" scripts in the + default system script directory (/usr/bin or C:\Python*\Scripts, + for example). This can be disabled by specifying the + "--no-scons-script" option on the command line, which is useful + if you want to install and experiment with a new version before + making it the default on your system. - $ python scons/scons.py + On UNIX or Linux systems, you can have the "scons" and "sconsign" + scripts be hard links or symbolic links to the "scons-0.97" and + "sconsign-0.97" scripts by specifying the "--hardlink-scons" + or "--symlink-scons" options on the command line. -That should be all you have to do. (If it isn't that simple, please let -us know!) + -- Install "scons-0.97.bat" and "scons.bat" wrapper scripts in the + Python prefix directory on Windows (C:\Python*, for example). + This can be disabled by specifying the "--no-install-bat" option + on the command line. + On UNIX or Linux systems, the "--install-bat" option may be + specified to have "scons-0.97.bat" and "scons.bat" files + installed in the default system script directory, which is useful + if you want to install SCons in a shared file system directory + that can be used to execute SCons from both UNIX/Linux and + Windows systems. -CONTENTS OF THIS PACKAGE -======================== + -- Install the SCons build engine (a Python module) in an + appropriate version-numbered SCons library directory + (/usr/lib/scons-0.97 or C:\Python*\scons-0.97, for example). + See below for more options related to installing the build + engine library. -This scons-local package consists of the following: + -- Install the troff-format man pages in an appropriate directory + on UNIX or Linux systems (/usr/share/man/man1 or /usr/man/man1, + for example). This can be disabled by specifying the + "--no-install-man" option on the command line. The man pages + can be installed on Windows systems by specifying the + "--install-man" option on the command line. -scons-LICENSE - A copy of the copyright and terms under which SCons is - distributed (the Open Source Initiative-approved MIT license). +Note that, by default, SCons does not install its build engine library +in the standard Python library directories. If you want to be able to +use the SCons library modules (the build engine) in other Python +scripts, specify the "--standard-lib" option on the command line, as +follows: - A disclaimer has been added to the beginning to make clear that - this license applies only to SCons, and not to any separate - software you've written with which you're planning to package - SCons. + # python setup.py install --standard-lib -scons-README - What you're looking at right now. +This will install the build engine in the standard Python library +directory (/usr/lib/python*/site-packages or +C:\Python*\Lib\site-packages). -scons-local-{version}/ - The SCons build engine. This is structured as a Python - library. +Alternatively, you can have SCons install its build engine library in a +hard-coded standalone library directory, instead of the default +version-numbered directory, by specifying the "--standalone-lib" option +on the command line, as follows: -scons.py - The SCons script itself. The script sets up the Python - sys.path variable to use the build engine found in the - scons-local-{version}/ directory in preference to any other - SCons build engine installed on your system. + # python setup.py install --standalone-lib + +This is usually not recommended, however. + +Note that, to install SCons in any of the above system directories, +you should have system installation privileges (that is, "root" or +"Administrator") when running the setup.py script. If you don't have +system installation privileges, you can use the --prefix option to +specify an alternate installation location, such as your home directory: + + $ python setup.py install --prefix=$HOME + +This will install SCons in the appropriate locations relative to +$HOME--that is, the scons script itself $HOME/bin and the associated +library in $HOME/lib/scons, for example. DOCUMENTATION ============= -Because this package is intended to be included with other software by -experienced users, we have not included any SCons documentation in this -package (other than this scons-README file you're reading right now). +See the RELEASE.txt file for notes about this specific release, +including known problems. See the CHANGES.txt file for a list of +changes since the previous release. -If, however, you need documentation about SCons, then consult any of the -following from the corresponding scons-{version} or scons-src-{version} -package: - - The RELEASE.txt file (src/RELEASE.txt file in the - scons-src-{version} package), which contains notes about this - specific release, including known problems. - - The CHANGES.txt file (src/CHANGES.txt file in the - scons-src-{version} package), which contains a list of changes - since the previous release. - - The scons.1 man page (doc/man/scons.1 in the scons-src-{version} - package), which contains a section of small examples for getting - started using SCons. +The scons.1 man page is included in this package, and contains a section +of small examples for getting started using SCons. Additional documentation for SCons is available at: @@ -142,8 +184,8 @@ LICENSING ========= SCons is distributed under the MIT license, a full copy of which is -available in the scons-LICENSE file in this package. The MIT license is -an approved Open Source license, which means: +available in the LICENSE.txt file. The MIT license is an approved Open +Source license, which means: This software is OSI Certified Open Source Software. OSI Certified is a certification mark of the Open Source Initiative. @@ -157,27 +199,51 @@ available at: REPORTING BUGS ============== -You can report bugs either by following the "Tracker - Bugs" link -on the SCons project page: +Please report bugs by following the detailed instructions on our Bug +Submission page: - http://sourceforge.net/projects/scons/ + http://scons.tigris.org/bug-submission.html -or by sending mail to the SCons developers mailing list: +You can also send mail to the SCons developers' mailing list: - scons-devel@lists.sourceforge.net + dev@scons.tigris.org + +But even if you send email to the mailing list please make sure that you +ALSO submit a bug report to the project page bug tracker, because bug +reports in email often get overlooked in the general flood of messages. MAILING LISTS ============= -A mailing list for users of SCons is available. You may send questions -or comments to the list at: +An active mailing list for users of SCons is available. You may send +questions or comments to the list at: - scons-users@lists.sourceforge.net + users@scons.tigris.org -You may subscribe to the scons-users mailing list at: +You may subscribe to the mailing list by sending email to: - http://lists.sourceforge.net/lists/listinfo/scons-users + users-subscribe@scons.tigris.org + +There is also a low-volume mailing list available for announcements +about SCons. Subscribe by sending email to: + + announce-subscribe@scons.tigris.org + +There are other mailing lists available for SCons developers, for +notification of SCons code changes, and for notification of updated +bug reports and project documents. Please see our mailing lists page +for details. + + +DONATIONS +========= + +If you find SCons helpful, please consider making a donation (of cash, +software, or hardware) to support continued work on the project. +Information is available at: + + http://www.scons.org/donate.html FOR MORE INFORMATION @@ -199,6 +265,9 @@ With plenty of help from the SCons Development team: Chad Austin Charles Crain Steve Leblanc + Greg Noel + Gary Oberbrunner Anthony Roach - Terrel Shumway + Greg Spencer + Christoph Wiedemann diff --git a/scons/scons-local-0.96.1/SCons/Action.py b/scons/scons-local-0.96.1/SCons/Action.py deleted file mode 100644 index accee0f52..000000000 --- a/scons/scons-local-0.96.1/SCons/Action.py +++ /dev/null @@ -1,642 +0,0 @@ -"""SCons.Action - -This encapsulates information about executing any sort of action that -can build one or more target Nodes (typically files) from one or more -source Nodes (also typically files) given a specific Environment. - -The base class here is ActionBase. The base class supplies just a few -OO utility methods and some generic methods for displaying information -about an Action in response to the various commands that control printing. - -The heavy lifting is handled by subclasses for the different types of -actions we might execute: - - CommandAction - CommandGeneratorAction - FunctionAction - ListAction - -The subclasses supply the following public interface methods used by -other modules: - - __call__() - THE public interface, "calling" an Action object executes the - command or Python function. This also takes care of printing - a pre-substitution command for debugging purposes. - - get_contents() - Fetches the "contents" of an Action for signature calculation. - This is what the Sig/*.py subsystem uses to decide if a target - needs to be rebuilt because its action changed. - - genstring() - Returns a string representation of the Action *without* command - substitution, but allows a CommandGeneratorAction to generate - the right action based on the specified target, source and env. - This is used by the Signature subsystem (through the Executor) - to compare the actions used to build a target last time and - this time. - -Subclasses also supply the following methods for internal use within -this module: - - __str__() - Returns a string representation of the Action *without* command - substitution. This is used by the __call__() methods to display - the pre-substitution command whenever the --debug=presub option - is used. - - strfunction() - Returns a substituted string representation of the Action. - This is used by the ActionBase.show() command to display the - command/function that will be executed to generate the target(s). - - execute() - The internal method that really, truly, actually handles the - execution of a command or Python function. This is used so - that the __call__() methods can take care of displaying any - pre-substitution representations, and *then* execute an action - without worrying about the specific Actions involved. - -There is a related independent ActionCaller class that looks like a -regular Action, and which serves as a wrapper for arbitrary functions -that we want to let the user specify the arguments to now, but actually -execute later (when an out-of-date check determines that it's needed to -be executed, for example). Objects of this class are returned by an -ActionFactory class that provides a __call__() method as a convenient -way for wrapping up the functions. - -""" - -# -# Copyright (c) 2001, 2002, 2003, 2004 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__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Action.py 0.96.1.D001 2004/08/23 09:55:29 knight" - -import os -import os.path -import re -import string -import sys - -from SCons.Debug import logInstanceCreation -import SCons.Errors -import SCons.Util - -class _Null: - pass - -_null = _Null - -print_actions = 1 -execute_actions = 1 -print_actions_presub = 0 - -default_ENV = None - -def rfile(n): - try: - return n.rfile() - except AttributeError: - return n - -def _actionAppend(act1, act2): - # This function knows how to slap two actions together. - # Mainly, it handles ListActions by concatenating into - # a single ListAction. - a1 = Action(act1) - a2 = Action(act2) - if a1 is None or a2 is None: - raise TypeError, "Cannot append %s to %s" % (type(act1), type(act2)) - if isinstance(a1, ListAction): - if isinstance(a2, ListAction): - return ListAction(a1.list + a2.list) - else: - return ListAction(a1.list + [ a2 ]) - else: - if isinstance(a2, ListAction): - return ListAction([ a1 ] + a2.list) - else: - return ListAction([ a1, a2 ]) - -class CommandGenerator: - """ - Wraps a command generator function so the Action() factory - function can tell a generator function from a function action. - """ - def __init__(self, generator): - self.generator = generator - - def __add__(self, other): - return _actionAppend(self, other) - - def __radd__(self, other): - return _actionAppend(other, self) - -def _do_create_action(act, *args, **kw): - """This is the actual "implementation" for the - Action factory method, below. This handles the - fact that passing lists to Action() itself has - different semantics than passing lists as elements - of lists. - - The former will create a ListAction, the latter - will create a CommandAction by converting the inner - list elements to strings.""" - - if isinstance(act, ActionBase): - return act - if SCons.Util.is_List(act): - return apply(CommandAction, (act,)+args, kw) - if isinstance(act, CommandGenerator): - return apply(CommandGeneratorAction, (act.generator,)+args, kw) - if callable(act): - return apply(FunctionAction, (act,)+args, kw) - if SCons.Util.is_String(act): - var=SCons.Util.get_environment_var(act) - if var: - # This looks like a string that is purely an Environment - # variable reference, like "$FOO" or "${FOO}". We do - # something special here...we lazily evaluate the contents - # of that Environment variable, so a user could put something - # like a function or a CommandGenerator in that variable - # instead of a string. - lcg = LazyCmdGenerator(var) - return apply(CommandGeneratorAction, (lcg,)+args, kw) - commands = string.split(str(act), '\n') - if len(commands) == 1: - return apply(CommandAction, (commands[0],)+args, kw) - else: - listCmdActions = map(lambda x: CommandAction(x), commands) - return apply(ListAction, (listCmdActions,)+args, kw) - return None - -def Action(act, strfunction=_null, varlist=[], presub=_null): - """A factory for action objects.""" - if SCons.Util.is_List(act): - acts = map(lambda x, s=strfunction, v=varlist, ps=presub: - _do_create_action(x, strfunction=s, varlist=v, presub=ps), - act) - acts = filter(lambda x: not x is None, acts) - if len(acts) == 1: - return acts[0] - else: - return ListAction(acts, strfunction=strfunction, varlist=varlist, presub=presub) - else: - return _do_create_action(act, strfunction=strfunction, varlist=varlist, presub=presub) - -class ActionBase: - """Base class for actions that create output objects.""" - def __init__(self, strfunction=_null, presub=_null, **kw): - if not strfunction is _null: - self.strfunction = strfunction - if presub is _null: - self.presub = print_actions_presub - else: - self.presub = presub - - def __cmp__(self, other): - return cmp(self.__dict__, other.__dict__) - - def __call__(self, target, source, env, - errfunc=None, - presub=_null, - show=_null, - execute=_null): - if not SCons.Util.is_List(target): - target = [target] - if not SCons.Util.is_List(source): - source = [source] - if presub is _null: presub = self.presub - if show is _null: show = print_actions - if execute is _null: execute = execute_actions - if presub: - t = string.join(map(str, target), 'and') - l = string.join(self.presub_lines(env), '\n ') - out = "Building %s with action(s):\n %s\n" % (t, l) - sys.stdout.write(out) - if show and self.strfunction: - s = self.strfunction(target, source, env) - if s: - sys.stdout.write(s + '\n') - if execute: - stat = self.execute(target, source, env) - if stat and errfunc: - errfunc(stat) - return stat - else: - return 0 - - def presub_lines(self, env): - # CommandGeneratorAction needs a real environment - # in order to return the proper string here, since - # it may call LazyCmdGenerator, which looks up a key - # in that env. So we temporarily remember the env here, - # and CommandGeneratorAction will use this env - # when it calls its __generate method. - self.presub_env = env - lines = string.split(str(self), '\n') - self.presub_env = None # don't need this any more - return lines - - def genstring(self, target, source, env): - return str(self) - - def get_actions(self): - return [self] - - def __add__(self, other): - return _actionAppend(self, other) - - def __radd__(self, other): - return _actionAppend(other, self) - -def _string_from_cmd_list(cmd_list): - """Takes a list of command line arguments and returns a pretty - representation for printing.""" - cl = [] - for arg in map(str, cmd_list): - if ' ' in arg or '\t' in arg: - arg = '"' + arg + '"' - cl.append(arg) - return string.join(cl) - -class CommandAction(ActionBase): - """Class for command-execution actions.""" - def __init__(self, cmd, **kw): - # Cmd list can actually be a list or a single item...basically - # anything that we could pass in as the first arg to - # Environment.subst_list(). - if __debug__: logInstanceCreation(self) - apply(ActionBase.__init__, (self,), kw) - self.cmd_list = cmd - - def __str__(self): - return str(self.cmd_list) - - def strfunction(self, target, source, env): - cmd_list = env.subst_list(self.cmd_list, 0, target, source) - return string.join(map(_string_from_cmd_list, cmd_list), "\n") - - def execute(self, target, source, env): - """Execute a command action. - - This will handle lists of commands as well as individual commands, - because construction variable substitution may turn a single - "command" into a list. This means that this class can actually - handle lists of commands, even though that's not how we use it - externally. - """ - import SCons.Util - - escape = env.get('ESCAPE', lambda x: x) - - if env.has_key('SHELL'): - shell = env['SHELL'] - else: - raise SCons.Errors.UserError('Missing SHELL construction variable.') - - # for SConf support (by now): check, if we want to pipe the command - # output to somewhere else - if env.has_key('PIPE_BUILD'): - pipe_build = 1 - if env.has_key('PSPAWN'): - pspawn = env['PSPAWN'] - else: - raise SCons.Errors.UserError('Missing PSPAWN construction variable.') - if env.has_key('PSTDOUT'): - pstdout = env['PSTDOUT'] - else: - raise SCons.Errors.UserError('Missing PSTDOUT construction variable.') - if env.has_key('PSTDERR'): - pstderr = env['PSTDERR'] - else: - raise SCons.Errors.UserError('Missing PSTDOUT construction variable.') - else: - pipe_build = 0 - if env.has_key('SPAWN'): - spawn = env['SPAWN'] - else: - raise SCons.Errors.UserError('Missing SPAWN construction variable.') - - cmd_list = env.subst_list(self.cmd_list, 0, target, source) - for cmd_line in cmd_list: - if len(cmd_line): - 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 - - # ensure that the ENV values are all strings: - for key, value in ENV.items(): - if SCons.Util.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(value) - ENV[key] = string.join(map(str, value), os.pathsep) - elif not SCons.Util.is_String(value): - # If it isn't a string or a list, then - # we just coerce it to a string, which - # is proper way to handle Dir and File instances - # and will produce something reasonable for - # just about everything else: - ENV[key] = str(value) - - # Escape the command line for the command - # interpreter we are using - cmd_line = SCons.Util.escape_list(cmd_line, escape) - if pipe_build: - ret = pspawn( shell, escape, cmd_line[0], cmd_line, - ENV, pstdout, pstderr ) - else: - ret = spawn(shell, escape, cmd_line[0], cmd_line, ENV) - if ret: - return ret - return 0 - - def get_contents(self, target, source, env, dict=None): - """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. - """ - cmd = self.cmd_list - if SCons.Util.is_List(cmd): - cmd = string.join(map(str, cmd)) - else: - cmd = str(cmd) - return env.subst_target_source(cmd, SCons.Util.SUBST_SIG, target, source, dict) - -class CommandGeneratorAction(ActionBase): - """Class for command-generator actions.""" - def __init__(self, generator, **kw): - if __debug__: logInstanceCreation(self) - apply(ActionBase.__init__, (self,), kw) - self.generator = generator - - 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): - target = [target] - - ret = self.generator(target=target, source=source, env=env, for_signature=for_signature) - gen_cmd = Action(ret) - 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 - - def strfunction(self, target, source, env): - if not SCons.Util.is_List(source): - source = [source] - rsources = map(rfile, source) - act = self.__generate(target, source, env, 0) - if act.strfunction: - return act.strfunction(target, rsources, env) - else: - return None - - def __str__(self): - try: - env = self.presub_env or {} - except AttributeError: - env = {} - act = self.__generate([], [], env, 0) - return str(act) - - def genstring(self, target, source, env): - return str(self.__generate(target, source, env, 0)) - - def execute(self, target, source, env): - rsources = map(rfile, source) - act = self.__generate(target, source, env, 0) - return act.execute(target, source, env) - - def get_contents(self, target, source, env, dict=None): - """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, dict=None) - -class LazyCmdGenerator: - """This is not really an Action, although it kind of looks like one. - This is really a simple callable class that acts as a command - generator. It holds on to a key into an Environment dictionary, - then waits until execution time to see what type it is, then tries - to create an Action out of it.""" - def __init__(self, var): - if __debug__: logInstanceCreation(self) - self.var = SCons.Util.to_String(var) - - def strfunction(self, target, source, env): - try: - return env[self.var] - except KeyError: - # The variable reference substitutes to nothing. - return '' - - def __str__(self): - return 'LazyCmdGenerator: %s'%str(self.var) - - def __call__(self, target, source, env, for_signature): - try: - return env[self.var] - except KeyError: - # The variable reference substitutes to nothing. - return '' - - def __cmp__(self, other): - return cmp(self.__dict__, other.__dict__) - -class FunctionAction(ActionBase): - """Class for Python function actions.""" - - def __init__(self, execfunction, **kw): - if __debug__: logInstanceCreation(self) - self.execfunction = execfunction - apply(ActionBase.__init__, (self,), kw) - self.varlist = kw.get('varlist', []) - - def function_name(self): - try: - return self.execfunction.__name__ - except AttributeError: - try: - return self.execfunction.__class__.__name__ - except AttributeError: - return "unknown_python_function" - - def strfunction(self, target, source, env): - def array(a): - def quote(s): - return '"' + str(s) + '"' - return '[' + string.join(map(quote, a), ", ") + ']' - name = self.function_name() - tstr = array(target) - sstr = array(source) - return "%s(%s, %s)" % (name, tstr, sstr) - - def __str__(self): - return "%s(env, target, source)" % self.function_name() - - def execute(self, target, source, env): - rsources = map(rfile, source) - return self.execfunction(target=target, source=rsources, env=env) - - def get_contents(self, target, source, env, dict=None): - """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! - """ - try: - # "self.execfunction" is a function. - contents = str(self.execfunction.func_code.co_code) - except AttributeError: - # "self.execfunction" is a callable object. - try: - contents = str(self.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, dict) - return contents + env.subst(string.join(map(lambda v: '${'+v+'}', - self.varlist))) - -class ListAction(ActionBase): - """Class for lists of other actions.""" - def __init__(self, list, **kw): - if __debug__: logInstanceCreation(self) - apply(ActionBase.__init__, (self,), kw) - self.list = map(lambda x: Action(x), list) - - def get_actions(self): - return self.list - - def __str__(self): - s = [] - for l in self.list: - s.append(str(l)) - return string.join(s, "\n") - - def strfunction(self, target, source, env): - s = [] - for l in self.list: - if l.strfunction: - x = l.strfunction(target, source, env) - if not SCons.Util.is_List(x): - x = [x] - s.extend(x) - return string.join(s, "\n") - - def execute(self, target, source, env): - for l in self.list: - r = l.execute(target, source, env) - if r: - return r - return 0 - - def get_contents(self, target, source, env, dict=None): - """Return the signature contents of this action list. - - Simple concatenation of the signatures of the elements. - """ - dict = SCons.Util.subst_dict(target, source) - return string.join(map(lambda x, t=target, s=source, e=env, d=dict: - x.get_contents(t, s, e, d), - self.list), - "") - -class ActionCaller: - """A class for delaying calling an Action function with specific - (positional and keyword) arguments until the Action is actually - executed. - - This class looks to the rest of the world like a normal Action object, - but what it's really doing is hanging on to the arguments until we - have a target, source and env to use for the expansion. - """ - def __init__(self, parent, args, kw): - self.parent = parent - self.args = args - self.kw = kw - def get_contents(self, target, source, env, dict=None): - actfunc = self.parent.actfunc - try: - # "self.actfunc" is a function. - contents = str(actfunc.func_code.co_code) - except AttributeError: - # "self.actfunc" is a callable object. - try: - contents = str(actfunc.__call__.im_func.func_code.co_code) - except AttributeError: - # No __call__() method, so it might be a builtin - # or something like that. Do the best we can. - contents = str(actfunc) - return contents - def subst_args(self, target, source, env): - return map(lambda x, e=env, t=target, s=source: - e.subst(x, 0, t, s), - self.args) - def subst_kw(self, target, source, env): - kw = {} - for key in self.kw.keys(): - kw[key] = env.subst(self.kw[key], 0, target, source) - return kw - def __call__(self, target, source, env): - args = self.subst_args(target, source, env) - kw = self.subst_kw(target, source, env) - 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) - return apply(self.parent.strfunc, args, kw) - -class ActionFactory: - """A factory class that will wrap up an arbitrary function - as an SCons-executable Action object. - - The real heavy lifting here is done by the ActionCaller class. - We just collect the (positional and keyword) arguments that we're - called with and give them to the ActionCaller object we create, - so it can hang onto them until it needs them. - """ - def __init__(self, actfunc, strfunc): - self.actfunc = actfunc - self.strfunc = strfunc - def __call__(self, *args, **kw): - ac = ActionCaller(self, args, kw) - return Action(ac, strfunction=ac.strfunction) diff --git a/scons/scons-local-0.96.1/SCons/Defaults.py b/scons/scons-local-0.96.1/SCons/Defaults.py deleted file mode 100644 index 25d6c4439..000000000 --- a/scons/scons-local-0.96.1/SCons/Defaults.py +++ /dev/null @@ -1,356 +0,0 @@ -"""SCons.Defaults - -Builders and other things for the local site. Here's where we'll -duplicate the functionality of autoconf until we move it into the -installation procedure or use something like qmconf. - -The code that reads the registry to find MSVC components was borrowed -from distutils.msvccompiler. - -""" - -# -# Copyright (c) 2001, 2002, 2003, 2004 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__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Defaults.py 0.96.1.D001 2004/08/23 09:55:29 knight" - - - -import os -import os.path -import shutil -import stat -import string -import time -import types - -import SCons.Action -import SCons.Builder -import SCons.Environment -import SCons.Scanner.C -import SCons.Scanner.D -import SCons.Scanner.Prog -import SCons.Sig - -# A placeholder for a default Environment (for fetching source files -# from source code management systems and the like). This must be -# initialized later, after the top-level directory is set by the calling -# interface. -_default_env = None - -# Lazily instantiate the default environment so the overhead of creating -# it doesn't apply when it's not needed. -def DefaultEnvironment(*args, **kw): - global _default_env - if not _default_env: - _default_env = apply(SCons.Environment.Environment, args, kw) - _default_env._build_signature = 1 - _default_env._calc_module = SCons.Sig.default_module - return _default_env - -# Emitters for setting the shared attribute on object files, -# and an action for checking that all of the source files -# going into a shared library are, in fact, shared. -def StaticObjectEmitter(target, source, env): - for tgt in target: - tgt.attributes.shared = None - return (target, source) - -def SharedObjectEmitter(target, source, env): - for tgt in target: - tgt.attributes.shared = 1 - return (target, source) - -def SharedFlagChecker(source, target, env): - same = env.subst('$STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME') - if same == '0' or same == '' or same == 'False': - for src in source: - try: - shared = src.attributes.shared - except AttributeError: - shared = None - if not shared: - raise SCons.Errors.UserError, "Source file: %s is static and is not compatible with shared target: %s" % (src, target[0]) - -SharedCheck = SCons.Action.Action(SharedFlagChecker, None) - -# Scanners and suffixes for common languages. -ObjSourceScan = SCons.Scanner.Scanner({}) - -CScan = SCons.Scanner.C.CScan() - -CSuffixes = [".c", ".C", ".cxx", ".cpp", ".c++", ".cc", - ".h", ".H", ".hxx", ".hpp", ".hh", - ".F", ".fpp", ".FPP", - ".S", ".spp", ".SPP"] - -for suffix in CSuffixes: - ObjSourceScan.add_scanner(suffix, CScan) - -DScan = SCons.Scanner.D.DScan() - -DSuffixes = ['.d'] - -for suffix in DSuffixes: - ObjSourceScan.add_scanner(suffix, DScan) - -IDLSuffixes = [".idl", ".IDL"] - -# cleanup -del suffix - -# Actions for common languages. -CAction = SCons.Action.Action("$CCCOM") -DAction = SCons.Action.Action("$DCOM") -ShCAction = SCons.Action.Action("$SHCCCOM") -CXXAction = SCons.Action.Action("$CXXCOM") -ShCXXAction = SCons.Action.Action("$SHCXXCOM") - -ASAction = SCons.Action.Action("$ASCOM") -ASPPAction = SCons.Action.Action("$ASPPCOM") - -LinkAction = SCons.Action.Action("$LINKCOM") -ShLinkAction = SCons.Action.Action("$SHLINKCOM") - -ArAction = SCons.Action.Action("$ARCOM") - -LexAction = SCons.Action.Action("$LEXCOM") -YaccAction = SCons.Action.Action("$YACCCOM") - -ProgScan = SCons.Scanner.Prog.ProgScan() - -def DVI(): - """Common function to generate a DVI file Builder.""" - return SCons.Builder.Builder(action = {}, - # The suffix is not configurable via a - # construction variable like $DVISUFFIX - # because the output file name is - # hard-coded within TeX. - suffix = '.dvi') - -def PDF(): - """A function for generating the PDF Builder.""" - return SCons.Builder.Builder(action = { }, - prefix = '$PDFPREFIX', - suffix = '$PDFSUFFIX') - -# Common tasks that we allow users to perform in platform-independent -# ways by creating ActionFactory instances. -ActionFactory = SCons.Action.ActionFactory - -Chmod = ActionFactory(os.chmod, - lambda dest, mode: 'Chmod("%s", 0%o)' % (dest, mode)) - -def Copy(dest, src): - def _copy_func(target, source, env, dest=dest, src=src): - dest = str(env.arg2nodes(dest, env.fs.Entry)[0]) - src = str(env.arg2nodes(src, env.fs.Entry)[0]) - shutil.copytree(src, dest, 1) - def _copy_str(target, source, env, dest=dest, src=src): - dest = str(env.arg2nodes(dest, env.fs.Entry)[0]) - src = str(env.arg2nodes(src, env.fs.Entry)[0]) - return 'Copy("%s", "%s")' % (dest, src) - return SCons.Action.Action(_copy_func, strfunction=_copy_str) - -def copy_func(dest, src): - if os.path.isfile(src): - return shutil.copy(src, dest) - else: - return shutil.copytree(src, dest, 1) - -Copy = ActionFactory(copy_func, - lambda dest, src: 'Copy("%s", "%s")' % (dest, src)) - -def delete_func(entry, must_exist=0): - if not must_exist and not os.path.exists(entry): - return None - if os.path.isfile(entry): - return os.unlink(entry) - else: - return shutil.rmtree(entry, 1) - -def delete_strfunc(entry, must_exist=0): - return 'Delete("%s")' % entry - -Delete = ActionFactory(delete_func, delete_strfunc) - -Mkdir = ActionFactory(os.makedirs, - lambda dir: 'Mkdir("%s")' % dir) - -Move = ActionFactory(lambda dest, src: os.rename(src, dest), - lambda dest, src: 'Move("%s", "%s")' % (dest, src)) - -def touch_func(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)) - -Touch = ActionFactory(touch_func, - lambda file: 'Touch("%s")' % file) - -# Internal utility functions -def copyFunc(dest, source, env): - """Install a source file into a destination by copying it (and its - permission/mode bits).""" - shutil.copy2(source, dest) - st = os.stat(source) - os.chmod(dest, stat.S_IMODE(st[stat.ST_MODE]) | stat.S_IWRITE) - return 0 - -def _concat(prefix, list, suffix, env, f=lambda x: x): - """Creates a new list from 'list' by first interpolating each - element in the list using the 'env' dictionary and then calling f - on the list, and finally concatenating 'prefix' and 'suffix' onto - each element of the list. A trailing space on 'prefix' or leading - space on 'suffix' will cause them to be put into separate list - elements rather than being concatenated.""" - - if not list: - return list - - list = f(env.subst_path(list)) - - ret = [] - - # ensure that prefix and suffix are strings - prefix = str(env.subst(prefix, SCons.Util.SUBST_RAW)) - suffix = str(env.subst(suffix, SCons.Util.SUBST_RAW)) - - for x in list: - x = str(x) - if x: - - if prefix: - if prefix[-1] == ' ': - ret.append(prefix[:-1]) - elif x[:len(prefix)] != prefix: - x = prefix + x - - ret.append(x) - - if suffix: - if suffix[0] == ' ': - ret.append(suffix[1:]) - elif x[-len(suffix):] != suffix: - ret[-1] = ret[-1]+suffix - - return ret - -def _stripixes(prefix, list, suffix, stripprefix, stripsuffix, env, c=None): - """This is a wrapper around _concat() that checks for the existence - of prefixes or suffixes on list elements and strips them where it - finds them. This is used by tools (like the GNU linker) that need - to turn something like 'libfoo.a' into '-lfoo'.""" - - if not callable(c): - if callable(env["_concat"]): - c = env["_concat"] - else: - c = _concat - def f(list, sp=stripprefix, ss=stripsuffix): - ret = [] - for l in list: - if not SCons.Util.is_String(l): - l = str(l) - if l[:len(sp)] == sp: - l = l[len(sp):] - if l[-len(ss):] == ss: - l = l[:-len(ss)] - ret.append(l) - return ret - return c(prefix, list, suffix, env, f) - -def _defines(prefix, defs, suffix, env, c=_concat): - """A wrapper around _concat that turns a list or string - into a list of C preprocessor command-line definitions. - """ - if SCons.Util.is_List(defs): - l = [] - for d in defs: - if SCons.Util.is_List(d) or type(d) is types.TupleType: - l.append(str(d[0]) + '=' + str(d[1])) - else: - l.append(str(d)) - elif SCons.Util.is_Dict(defs): - # The items in a dictionary are stored in random order, but - # if the order of the command-line options changes from - # invocation to invocation, then the signature of the command - # line will change and we'll get random unnecessary rebuilds. - # Consequently, we have to sort the keys to ensure a - # consistent order... - l = [] - keys = defs.keys() - keys.sort() - for k in keys: - v = defs[k] - if v is None: - l.append(str(k)) - else: - l.append(str(k) + '=' + str(v)) - else: - l = [str(defs)] - return c(prefix, l, suffix, env) - -class NullCmdGenerator: - """This is a callable class that can be used in place of other - command generators if you don't want them to do anything. - - The __call__ method for this class simply returns the thing - you instantiated it with. - - Example usage: - env["DO_NOTHING"] = NullCmdGenerator - env["LINKCOM"] = "${DO_NOTHING('$LINK $SOURCES $TARGET')}" - """ - - def __init__(self, cmd): - self.cmd = cmd - - def __call__(self, target, source, env, for_signature=None): - return self.cmd - -ConstructionEnvironment = { - 'BUILDERS' : {}, - 'SCANNERS' : [], - 'CPPSUFFIXES': CSuffixes, - 'DSUFFIXES' : DSuffixes, - 'IDLSUFFIXES': IDLSuffixes, - 'PDFPREFIX' : '', - 'PDFSUFFIX' : '.pdf', - 'PSPREFIX' : '', - 'PSSUFFIX' : '.ps', - 'ENV' : {}, - 'INSTALL' : copyFunc, - '_concat' : _concat, - '_defines' : _defines, - '_stripixes' : _stripixes, - '_LIBFLAGS' : '${_concat(LIBLINKPREFIX, LIBS, LIBLINKSUFFIX, __env__)}', - '_LIBDIRFLAGS' : '$( ${_concat(LIBDIRPREFIX, LIBPATH, LIBDIRSUFFIX, __env__, RDirs)} $)', - '_CPPINCFLAGS' : '$( ${_concat(INCPREFIX, CPPPATH, INCSUFFIX, __env__, RDirs)} $)', - '_CPPDEFFLAGS' : '${_defines(CPPDEFPREFIX, CPPDEFINES, CPPDEFSUFFIX, __env__)}', - 'TEMPFILE' : NullCmdGenerator - } diff --git a/scons/scons-local-0.96.1/SCons/Environment.py b/scons/scons-local-0.96.1/SCons/Environment.py deleted file mode 100644 index 9956ac643..000000000 --- a/scons/scons-local-0.96.1/SCons/Environment.py +++ /dev/null @@ -1,1271 +0,0 @@ -"""SCons.Environment - -Base class for construction Environments. These are -the primary objects used to communicate dependency and -construction information to the build engine. - -Keyword arguments supplied when the construction Environment -is created are construction variables used to initialize the -Environment -""" - -# -# Copyright (c) 2001, 2002, 2003, 2004 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__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Environment.py 0.96.1.D001 2004/08/23 09:55:29 knight" - - -import copy -import os -import os.path -import string -from UserDict import UserDict - -import SCons.Action -import SCons.Builder -from SCons.Debug import logInstanceCreation -import SCons.Defaults -import SCons.Errors -import SCons.Node -import SCons.Node.Alias -import SCons.Node.FS -import SCons.Node.Python -import SCons.Platform -import SCons.SConsign -import SCons.Sig -import SCons.Sig.MD5 -import SCons.Sig.TimeStamp -import SCons.Tool -import SCons.Util -import SCons.Warnings - -class _Null: - pass - -_null = _Null - -CleanTargets = {} -CalculatorArgs = {} - -# Pull UserError into the global name space for the benefit of -# Environment().SourceSignatures(), which has some import statements -# which seem to mess up its ability to reference SCons directly. -UserError = SCons.Errors.UserError - -def installFunc(target, source, env): - """Install a source file into a target using the function specified - as the INSTALL construction variable.""" - try: - install = env['INSTALL'] - except KeyError: - raise SCons.Errors.UserError('Missing INSTALL construction variable.') - return install(target[0].path, source[0].path, env) - -def installString(target, source, env): - return 'Install file: "%s" as "%s"' % (source[0], target[0]) - -installAction = SCons.Action.Action(installFunc, installString) - -InstallBuilder = SCons.Builder.Builder(action=installAction) - -def alias_builder(env, target, source): - pass - -AliasBuilder = SCons.Builder.Builder(action = alias_builder, - target_factory = SCons.Node.Alias.default_ans.Alias, - source_factory = SCons.Node.FS.default_fs.Entry, - multi = 1) - -def our_deepcopy(x): - """deepcopy lists and dictionaries, and just copy the reference - for everything else.""" - if SCons.Util.is_Dict(x): - copy = {} - for key in x.keys(): - copy[key] = our_deepcopy(x[key]) - elif SCons.Util.is_List(x): - copy = map(our_deepcopy, x) - try: - copy = x.__class__(copy) - except AttributeError: - pass - else: - copy = x - return copy - -def apply_tools(env, tools, toolpath): - if tools: - # Filter out null tools from the list. - tools = filter(None, tools) - for tool in tools: - if SCons.Util.is_String(tool): - env.Tool(tool, toolpath) - else: - tool(env) - -# 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'] - -def copy_non_reserved_keywords(dict): - result = our_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) - del result[k] - return result - -class BuilderWrapper: - """Wrapper class that associates an environment with a Builder at - instantiation.""" - def __init__(self, env, builder): - self.env = env - self.builder = builder - - def __call__(self, *args, **kw): - return apply(self.builder, (self.env,) + args, kw) - - # This allows a Builder to be executed directly - # through the Environment to which it's attached. - # In practice, we shouldn't need this, because - # builders actually get executed through a Node. - # But we do have a unit test for this, and can't - # yet rule out that it would be useful in the - # future, so leave it for now. - def execute(self, **kw): - kw['env'] = self.env - apply(self.builder.execute, (), kw) - -class BuilderDict(UserDict): - """This is a dictionary-like class used by an Environment to hold - the Builders. We need to do this because every time someone changes - the Builders in the Environment's BUILDERS dictionary, we must - update the Environment's attributes.""" - def __init__(self, dict, env): - # Set self.env before calling the superclass initialization, - # because it will end up calling our other methods, which will - # need to point the values in this dictionary to self.env. - self.env = env - UserDict.__init__(self, dict) - - def __setitem__(self, item, val): - UserDict.__setitem__(self, item, val) - try: - self.setenvattr(item, val) - except AttributeError: - # Have to catch this because sometimes __setitem__ gets - # called out of __init__, when we don't have an env - # attribute yet, nor do we want one! - pass - - def setenvattr(self, item, val): - """Set the corresponding environment attribute for this Builder. - - If the value is already a BuilderWrapper, we pull the builder - out of it and make another one, so that making a copy of an - existing BuilderDict is guaranteed separate wrappers for each - Builder + Environment pair.""" - try: - builder = val.builder - except AttributeError: - builder = val - setattr(self.env, item, BuilderWrapper(self.env, builder)) - - def __delitem__(self, item): - UserDict.__delitem__(self, item) - delattr(self.env, item) - - def update(self, dict): - for i, v in dict.items(): - self.__setitem__(i, v) - -class Base: - """Base class for construction Environments. These are - the primary objects used to communicate dependency and - construction information to the build engine. - - Keyword arguments supplied when the construction Environment - is created are construction variables used to initialize the - Environment. - """ - - ####################################################################### - # This is THE class for interacting with the SCons build engine, - # and it contains a lot of stuff, so we're going to try to keep this - # a little organized by grouping the methods. - ####################################################################### - - ####################################################################### - # Methods that make an Environment act like a dictionary. These have - # the expected standard names for Python mapping objects. Note that - # we don't actually make an Environment a subclass of UserDict for - # performance reasons. Note also that we only supply methods for - # dictionary functionality that we actually need and use. - ####################################################################### - - def __init__(self, - platform=None, - tools=None, - toolpath=[], - options=None, - **kw): - if __debug__: logInstanceCreation(self) - self.fs = SCons.Node.FS.default_fs - self.ans = SCons.Node.Alias.default_ans - self.lookup_list = SCons.Node.arg2nodes_lookups - self._dict = our_deepcopy(SCons.Defaults.ConstructionEnvironment) - - self._dict['__env__'] = self - self._dict['BUILDERS'] = BuilderDict(self._dict['BUILDERS'], self) - - if platform is None: - platform = self._dict.get('PLATFORM', None) - if platform is None: - platform = SCons.Platform.Platform() - if SCons.Util.is_String(platform): - platform = SCons.Platform.Platform(platform) - self._dict['PLATFORM'] = str(platform) - platform(self) - - # Apply the passed-in variables before calling the tools, - # because they may use some of them: - apply(self.Replace, (), kw) - - # Update the environment with the customizable options - # before calling the tools, since they may use some of the options: - if options: - options.Update(self) - - if tools is None: - tools = self._dict.get('TOOLS', None) - if tools is None: - tools = ['default'] - apply_tools(self, tools, toolpath) - - # Reapply the passed in variables after calling the tools, - # since they should overide anything set by the tools: - apply(self.Replace, (), kw) - - # Update the environment with the customizable options - # after calling the tools, since they should override anything - # set by the tools: - if options: - options.Update(self) - - def __cmp__(self, other): - # Since an Environment now has an '__env__' construction variable - # that refers to itself, delete that variable to avoid infinite - # loops when comparing the underlying dictionaries in some Python - # versions (*cough* 1.5.2 *cough*)... - sdict = self._dict.copy() - del sdict['__env__'] - odict = other._dict.copy() - del odict['__env__'] - return cmp(sdict, odict) - - def __getitem__(self, key): - return self._dict[key] - - def __setitem__(self, key, value): - if key in reserved_construction_var_names: - SCons.Warnings.warn(SCons.Warnings.ReservedVariableWarning, - "Ignoring attempt to set reserved variable `%s'" % key) - elif key == 'BUILDERS': - try: - bd = self._dict[key] - for k in bd.keys(): - del bd[k] - except KeyError: - self._dict[key] = BuilderDict(kwbd, self) - self._dict[key].update(value) - elif key == 'SCANNERS': - self._dict[key] = value - self.scanner_map_delete() - else: - if not SCons.Util.is_valid_construction_var(key): - raise SCons.Errors.UserError, "Illegal construction variable `%s'" % key - self._dict[key] = value - - def __delitem__(self, key): - del self._dict[key] - - def items(self): - "Emulates the items() method of dictionaries.""" - return self._dict.items() - - def has_key(self, key): - return self._dict.has_key(key) - - def get(self, key, default=None): - "Emulates the get() method of dictionaries.""" - return self._dict.get(key, default) - - ####################################################################### - # Utility methods that are primarily for internal use by SCons. - # These begin with lower-case letters. Note that the subst() method - # is actually already out of the closet and used by people. - ####################################################################### - - def arg2nodes(self, args, node_factory=_null, lookup_list=_null): - if node_factory is _null: - node_factory = self.fs.File - if lookup_list is _null: - lookup_list = self.lookup_list - - if not args: - return [] - - if SCons.Util.is_List(args): - args = SCons.Util.flatten(args) - else: - args = [args] - - nodes = [] - for v in args: - if SCons.Util.is_String(v): - n = None - for l in lookup_list: - n = l(v) - if not n is None: - break - if not n is None: - if SCons.Util.is_String(n): - n = self.subst(n, raw=1) - if node_factory: - n = node_factory(n) - if SCons.Util.is_List(n): - nodes.extend(n) - else: - nodes.append(n) - elif node_factory: - v = node_factory(self.subst(v, raw=1)) - if SCons.Util.is_List(v): - nodes.extend(v) - else: - nodes.append(v) - else: - nodes.append(v) - - return nodes - - def get_calculator(self): - try: - return self._calculator - except AttributeError: - try: - module = self._calc_module - c = apply(SCons.Sig.Calculator, (module,), CalculatorArgs) - except AttributeError: - # Note that we're calling get_calculator() here, so the - # DefaultEnvironment() must have a _calc_module attribute - # to avoid infinite recursion. - c = SCons.Defaults.DefaultEnvironment().get_calculator() - self._calculator = c - return c - - def get_builder(self, name): - """Fetch the builder with the specified name from the environment. - """ - try: - return self._dict['BUILDERS'][name] - except KeyError: - return None - - def get_scanner(self, skey): - """Find the appropriate scanner given a key (usually a file suffix). - """ - try: - sm = self.scanner_map - except AttributeError: - try: - scanners = self._dict['SCANNERS'] - except KeyError: - self.scanner_map = {} - return None - else: - self.scanner_map = sm = {} - # Reverse the scanner list so that, if multiple scanners - # claim they can scan the same suffix, earlier scanners - # in the list will overwrite later scanners, so that - # the result looks like a "first match" to the user. - if not SCons.Util.is_List(scanners): - scanners = [scanners] - scanners.reverse() - for scanner in scanners: - for k in scanner.get_skeys(self): - sm[k] = scanner - try: - return sm[skey] - except KeyError: - return None - - def scanner_map_delete(self, kw=None): - """Delete the cached scanner map (if we need to). - """ - if not kw is None and not kw.has_key('SCANNERS'): - return - try: - del self.scanner_map - except AttributeError: - pass - - def subst(self, string, raw=0, target=None, source=None, dict=None, conv=None): - """Recursively interpolates construction variables from the - Environment into the specified string, returning the expanded - result. Construction variables are specified by a $ prefix - in the string and begin with an initial underscore or - alphabetic character followed by any number of underscores - or alphanumeric characters. The construction variable names - may be surrounded by curly braces to separate the name from - trailing characters. - """ - return SCons.Util.scons_subst(string, self, raw, target, source, dict, conv) - - def subst_kw(self, kw, raw=0, target=None, source=None, dict=None): - nkw = {} - for k, v in kw.items(): - k = self.subst(k, raw, target, source, dict) - if SCons.Util.is_String(v): - v = self.subst(v, raw, target, source, dict) - nkw[k] = v - return nkw - - def subst_list(self, string, raw=0, target=None, source=None, dict=None, conv=None): - """Calls through to SCons.Util.scons_subst_list(). See - the documentation for that function.""" - return SCons.Util.scons_subst_list(string, self, raw, target, source, dict, conv) - - - def subst_path(self, path): - """Substitute a path list, turning EntryProxies into Nodes - and leaving Nodes (and other objects) as-is.""" - - if not SCons.Util.is_List(path): - path = [path] - - def s(obj): - """This is the "string conversion" routine that we have our - substitutions use to return Nodes, not strings. This relies - on the fact that an EntryProxy object has a get() method that - returns the underlying Node that it wraps, which is a bit of - architectural dependence that we might need to break or modify - in the future in response to additional requirements.""" - try: - get = obj.get - except AttributeError: - pass - else: - obj = get() - return obj - - r = [] - for p in path: - if SCons.Util.is_String(p): - p = self.subst(p, conv=s) - if SCons.Util.is_List(p): - if len(p) == 1: - p = p[0] - else: - # 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), '') - else: - p = s(p) - r.append(p) - return r - - subst_target_source = subst - - def _update(self, dict): - """Update an environment's values directly, bypassing the normal - checks that occur when users try to set items. - """ - self._dict.update(dict) - - def use_build_signature(self): - try: - return self._build_signature - except AttributeError: - b = SCons.Defaults.DefaultEnvironment()._build_signature - self._build_signature = b - return b - - ####################################################################### - # Public methods for manipulating an Environment. These begin with - # upper-case letters. The essential characteristic of methods in - # this section is that they do *not* have corresponding same-named - # global functions. For example, a stand-alone Append() function - # makes no sense, because Append() is all about appending values to - # an Environment's construction variables. - ####################################################################### - - def Append(self, **kw): - """Append values to existing construction variables - in an Environment. - """ - kw = copy_non_reserved_keywords(kw) - for key, val in kw.items(): - # It would be easier on the eyes to write this using - # "continue" statements whenever we finish processing an item, - # but Python 1.5.2 apparently doesn't let you use "continue" - # within try:-except: blocks, so we have to nest our code. - try: - orig = self._dict[key] - except KeyError: - # No existing variable in the environment, so just set - # it to the new value. - self._dict[key] = val - else: - try: - # Most straightforward: just try to add them - # together. This will work in most cases, when the - # original and new values are of compatible types. - self._dict[key] = orig + val - except TypeError: - try: - # Try to update a dictionary value with another. - # If orig isn't a dictionary, it won't have an - # update() method; if val isn't a dictionary, - # it won't have a keys() method. Either way, - # it's an AttributeError. - orig.update(val) - except AttributeError: - try: - # Check if the original is a list. - add_to_orig = orig.append - except AttributeError: - # The original isn't a list, but the new - # value is (by process of elimination), - # so insert the original in the new value - # (if there's one to insert) and replace - # the variable with it. - if orig: - val.insert(0, orig) - self._dict[key] = val - else: - # The original is a list, so append the new - # value to it (if there's a value to append). - if val: - add_to_orig(val) - self.scanner_map_delete(kw) - - def AppendENVPath(self, name, newpath, envname = 'ENV', sep = os.pathsep): - """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. - """ - - 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) - - if not self._dict.has_key(envname): - self._dict[envname] = {} - - self._dict[envname][name] = nv - - def AppendUnique(self, **kw): - """Append values to existing construction variables - in an Environment, if they're not already there. - """ - kw = copy_non_reserved_keywords(kw) - for key, val in kw.items(): - if not self._dict.has_key(key): - self._dict[key] = val - elif SCons.Util.is_Dict(self._dict[key]) and \ - SCons.Util.is_Dict(val): - self._dict[key].update(val) - elif SCons.Util.is_List(val): - dk = self._dict[key] - if not SCons.Util.is_List(dk): - dk = [dk] - 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): - if not val in dk: - self._dict[key] = dk + val - else: - self._dict[key] = self._dict[key] + val - self.scanner_map_delete(kw) - - def Copy(self, tools=None, toolpath=[], **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 - a reference is copied when an object is not deep-copyable - (like a function). There are no references to any mutable - objects in the original Environment. - """ - clone = copy.copy(self) - clone._dict = our_deepcopy(self._dict) - clone['__env__'] = clone - try: - cbd = clone._dict['BUILDERS'] - clone._dict['BUILDERS'] = BuilderDict(cbd, clone) - except KeyError: - pass - - apply_tools(clone, tools, toolpath) - - # Apply passed-in variables after the new tools. - kw = copy_non_reserved_keywords(kw) - new = {} - for key, value in kw.items(): - new[key] = SCons.Util.scons_subst_once(value, self, key) - apply(clone.Replace, (), new) - return clone - - def Detect(self, progs): - """Return the first available program in progs. - """ - if not SCons.Util.is_List(progs): - progs = [ progs ] - for prog in progs: - path = self.WhereIs(prog) - if path: return prog - return None - - def Dictionary(self, *args): - if not args: - return self._dict - dlist = map(lambda x, s=self: s._dict[x], args) - if len(dlist) == 1: - dlist = dlist[0] - return dlist - - def FindIxes(self, paths, prefix, suffix): - """ - Search a list of paths for something that matches the prefix and suffix. - - paths - the list of paths or nodes. - prefix - construction variable for the prefix. - suffix - construction variable for the suffix. - """ - - suffix = self.subst('$'+suffix) - prefix = self.subst('$'+prefix) - - for path in paths: - dir,name = os.path.split(str(path)) - if name[:len(prefix)] == prefix and name[-len(suffix):] == suffix: - return path - - def Override(self, overrides): - """ - Produce a modified environment whose variables - are overriden by the overrides dictionaries. - - overrides - a dictionary that will override - the variables of this environment. - - This function is much more efficient than Copy() - or creating a new Environment because it doesn't do - a deep copy of the dictionary, and doesn't do a copy - at all if there are no overrides. - """ - - if overrides: - env = copy.copy(self) - env._dict = copy.copy(self._dict) - env['__env__'] = env - overrides = copy_non_reserved_keywords(overrides) - new = {} - for key, value in overrides.items(): - new[key] = SCons.Util.scons_subst_once(value, self, key) - env._dict.update(new) - return env - else: - return self - - def ParseConfig(self, command, function=None): - """ - Use the specified function to parse the output of the command - in order to modify the current environment. The 'command' can - be a string or a list of strings representing a command and - it's arguments. 'Function' is an optional argument that takes - the environment and the output of the command. If no function is - specified, the output will be treated as the output of a typical - 'X-config' command (i.e. gtk-config) and used to append to the - ASFLAGS, CCFLAGS, CPPFLAGS, CPPPATH, LIBPATH, LIBS, LINKFLAGS - and CCFLAGS variables. - """ - - # the default parse function - def parse_conf(env, output): - dict = { - 'ASFLAGS' : [], - 'CCFLAGS' : [], - 'CPPFLAGS' : [], - 'CPPPATH' : [], - 'LIBPATH' : [], - 'LIBS' : [], - 'LINKFLAGS' : [], - } - static_libs = [] - - params = string.split(output) - for arg in params: - if arg[0] != '-': - static_libs.append(arg) - elif arg[:2] == '-L': - dict['LIBPATH'].append(arg[2:]) - elif arg[:2] == '-l': - dict['LIBS'].append(arg[2:]) - elif arg[:2] == '-I': - dict['CPPPATH'].append(arg[2:]) - elif arg[:4] == '-Wa,': - dict['ASFLAGS'].append(arg) - elif arg[:4] == '-Wl,': - dict['LINKFLAGS'].append(arg) - elif arg[:4] == '-Wp,': - dict['CPPFLAGS'].append(arg) - elif arg == '-pthread': - dict['CCFLAGS'].append(arg) - dict['LINKFLAGS'].append(arg) - else: - dict['CCFLAGS'].append(arg) - apply(env.Append, (), dict) - return static_libs - - if function is None: - function = parse_conf - if type(command) is type([]): - command = string.join(command) - command = self.subst(command) - return function(self, os.popen(command).read()) - - def Platform(self, platform): - platform = self.subst(platform) - return SCons.Platform.Platform(platform)(self) - - def Prepend(self, **kw): - """Prepend values to existing construction variables - in an Environment. - """ - kw = copy_non_reserved_keywords(kw) - for key, val in kw.items(): - # It would be easier on the eyes to write this using - # "continue" statements whenever we finish processing an item, - # but Python 1.5.2 apparently doesn't let you use "continue" - # within try:-except: blocks, so we have to nest our code. - try: - orig = self._dict[key] - except KeyError: - # No existing variable in the environment, so just set - # it to the new value. - self._dict[key] = val - else: - try: - # Most straightforward: just try to add them - # together. This will work in most cases, when the - # original and new values are of compatible types. - self._dict[key] = val + orig - except TypeError: - try: - # Try to update a dictionary value with another. - # If orig isn't a dictionary, it won't have an - # update() method; if val isn't a dictionary, - # it won't have a keys() method. Either way, - # it's an AttributeError. - orig.update(val) - except AttributeError: - try: - # Check if the added value is a list. - add_to_val = val.append - except AttributeError: - # The added value isn't a list, but the - # original is (by process of elimination), - # so insert the the new value in the original - # (if there's one to insert). - if val: - orig.insert(0, val) - else: - # The added value is a list, so append - # the original to it (if there's a value - # to append). - if orig: - add_to_val(orig) - self._dict[key] = val - self.scanner_map_delete(kw) - - def PrependENVPath(self, name, newpath, envname = 'ENV', sep = os.pathsep): - """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. - """ - - 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) - - 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 - in an Environment, if they're not already there. - """ - kw = copy_non_reserved_keywords(kw) - for key, val in kw.items(): - if not self._dict.has_key(key): - self._dict[key] = val - elif SCons.Util.is_Dict(self._dict[key]) and \ - SCons.Util.is_Dict(val): - self._dict[key].update(val) - elif SCons.Util.is_List(val): - dk = self._dict[key] - if not SCons.Util.is_List(dk): - dk = [dk] - 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): - if not val in dk: - self._dict[key] = val + dk - else: - self._dict[key] = val + dk - self.scanner_map_delete(kw) - - def Replace(self, **kw): - """Replace existing construction variables in an Environment - with new construction variables and/or values. - """ - try: - kwbd = our_deepcopy(kw['BUILDERS']) - del kw['BUILDERS'] - self.__setitem__('BUILDERS', kwbd) - except KeyError: - pass - kw = copy_non_reserved_keywords(kw) - self._dict.update(our_deepcopy(kw)) - self.scanner_map_delete(kw) - - def ReplaceIxes(self, path, old_prefix, old_suffix, new_prefix, new_suffix): - """ - Replace old_prefix with new_prefix and old_suffix with new_suffix. - - env - Environment used to interpolate variables. - path - the path that will be modified. - old_prefix - construction variable for the old prefix. - old_suffix - construction variable for the old suffix. - new_prefix - construction variable for the new prefix. - new_suffix - construction variable for the new suffix. - """ - old_prefix = self.subst('$'+old_prefix) - old_suffix = self.subst('$'+old_suffix) - - new_prefix = self.subst('$'+new_prefix) - new_suffix = self.subst('$'+new_suffix) - - dir,name = os.path.split(str(path)) - if name[:len(old_prefix)] == old_prefix: - name = name[len(old_prefix):] - if name[-len(old_suffix):] == old_suffix: - name = name[:-len(old_suffix)] - return os.path.join(dir, new_prefix+name+new_suffix) - - def Tool(self, tool, toolpath=[]): - tool = self.subst(tool) - return SCons.Tool.Tool(tool, map(self.subst, toolpath))(self) - - def WhereIs(self, prog, path=None, pathext=None, reject=[]): - """Find prog in the path. - """ - if path is None: - try: - path = self['ENV']['PATH'] - except KeyError: - pass - elif SCons.Util.is_String(path): - path = self.subst(path) - if pathext is None: - try: - pathext = self['ENV']['PATHEXT'] - except KeyError: - pass - elif SCons.Util.is_String(pathext): - pathext = self.subst(pathext) - path = SCons.Util.WhereIs(prog, path, pathext, reject) - if path: return path - return None - - ####################################################################### - # Public methods for doing real "SCons stuff" (manipulating - # dependencies, setting attributes on targets, etc.). These begin - # with upper-case letters. The essential characteristic of methods - # in this section is that they all *should* have corresponding - # same-named global functions. - ####################################################################### - - def Action(self, *args, **kw): - nargs = self.subst(args) - nkw = self.subst_kw(kw) - return apply(SCons.Action.Action, nargs, nkw) - - def AddPreAction(self, files, action): - nodes = self.arg2nodes(files, self.fs.Entry) - action = SCons.Action.Action(action) - for n in nodes: - n.add_pre_action(action) - return nodes - - def AddPostAction(self, files, action): - nodes = self.arg2nodes(files, self.fs.Entry) - action = SCons.Action.Action(action) - for n in nodes: - n.add_post_action(action) - return nodes - - def Alias(self, target, *source, **kw): - if not SCons.Util.is_List(target): - target = [target] - tlist = [] - for t in target: - if not isinstance(t, SCons.Node.Alias.Alias): - t = self.arg2nodes(self.subst(t), self.ans.Alias)[0] - tlist.append(t) - try: - s = kw['source'] - except KeyError: - try: - s = source[0] - except IndexError: - s = None - if s: - if not SCons.Util.is_List(s): - s = [s] - s = filter(None, s) - s = self.arg2nodes(s, self.fs.Entry) - for t in tlist: - AliasBuilder(self, t, s) - return tlist - - def AlwaysBuild(self, *targets): - tlist = [] - for t in targets: - tlist.extend(self.arg2nodes(t, self.fs.File)) - for t in tlist: - 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 Builder(self, **kw): - nkw = self.subst_kw(kw) - return apply(SCons.Builder.Builder, [], nkw) - - def CacheDir(self, path): - self.fs.CacheDir(self.subst(path)) - - def Clean(self, targets, files): - global CleanTargets - tlist = self.arg2nodes(targets, self.fs.Entry) - flist = self.arg2nodes(files, self.fs.Entry) - for t in tlist: - try: - CleanTargets[t].extend(flist) - except KeyError: - CleanTargets[t] = flist - - def Configure(self, *args, **kw): - nargs = [self] - if args: - nargs = nargs + self.subst_list(args)[0] - nkw = self.subst_kw(kw) - try: - nkw['custom_tests'] = self.subst_kw(nkw['custom_tests']) - except KeyError: - pass - return apply(SCons.SConf.SConf, nargs, nkw) - - def Command(self, target, source, action, **kw): - """Builds the supplied target files from the supplied - source files using the supplied action. Action may - be any type that the Builder constructor will accept - for an action.""" - nkw = self.subst_kw(kw) - nkw['action'] = action - nkw['source_factory'] = self.fs.Entry - bld = apply(SCons.Builder.Builder, (), nkw) - return bld(self, target, source) - - def Depends(self, target, dependency): - """Explicity specify that 'target's depend on 'dependency'.""" - tlist = self.arg2nodes(target, self.fs.Entry) - dlist = self.arg2nodes(dependency, self.fs.Entry) - for t in tlist: - t.add_dependency(dlist) - return tlist - - def Dir(self, name, *args, **kw): - """ - """ - return apply(self.fs.Dir, (self.subst(name),) + args, kw) - - def Environment(self, **kw): - return apply(SCons.Environment.Environment, [], self.subst_kw(kw)) - - def Execute(self, action, *args, **kw): - """Directly execute an action through an Environment - """ - action = apply(self.Action, (action,) + args, kw) - return action([], [], self) - - def File(self, name, *args, **kw): - """ - """ - return apply(self.fs.File, (self.subst(name),) + args, kw) - - def FindFile(self, file, dirs): - file = self.subst(file) - nodes = self.arg2nodes(dirs, self.fs.Dir) - return SCons.Node.FS.find_file(file, nodes, self.fs.File) - - def Flatten(self, sequence): - return SCons.Util.flatten(sequence) - - def GetBuildPath(self, files): - result = map(str, self.arg2nodes(files, self.fs.Entry)) - if SCons.Util.is_List(files): - return result - else: - return result[0] - - def Ignore(self, target, dependency): - """Ignore a dependency.""" - tlist = self.arg2nodes(target, self.fs.Entry) - dlist = self.arg2nodes(dependency, self.fs.Entry) - for t in tlist: - t.add_ignore(dlist) - return tlist - - def Install(self, dir, source): - """Install specified files in the given directory.""" - try: - dnodes = self.arg2nodes(dir, self.fs.Dir) - except TypeError: - raise SCons.Errors.UserError, "Target `%s' of Install() is a file, but should be a directory. Perhaps you have the Install() arguments backwards?" % str(dir) - try: - sources = self.arg2nodes(source, self.fs.File) - except TypeError: - if SCons.Util.is_List(source): - raise SCons.Errors.UserError, "Source `%s' of Install() contains one or more non-files. Install() source must be one or more files." % repr(map(str, source)) - else: - raise SCons.Errors.UserError, "Source `%s' of Install() is not a file. Install() source must be one or more files." % str(source) - tgt = [] - for dnode in dnodes: - for src in sources: - target = self.fs.File(src.name, dnode) - tgt.extend(InstallBuilder(self, target, src)) - return tgt - - def InstallAs(self, target, source): - """Install sources as targets.""" - sources = self.arg2nodes(source, self.fs.File) - targets = self.arg2nodes(target, self.fs.File) - result = [] - for src, tgt in map(lambda x, y: (x, y), sources, targets): - result.extend(InstallBuilder(self, tgt, src)) - return result - - def Literal(self, string): - return SCons.Util.Literal(string) - - def Local(self, *targets): - ret = [] - for targ in targets: - if isinstance(targ, SCons.Node.Node): - targ.set_local() - ret.append(targ) - else: - for t in self.arg2nodes(targ, self.fs.Entry): - t.set_local() - ret.append(t) - return ret - - def Precious(self, *targets): - tlist = [] - for t in targets: - tlist.extend(self.arg2nodes(t, self.fs.Entry)) - for t in tlist: - t.set_precious() - return tlist - - def Repository(self, *dirs, **kw): - dirs = self.arg2nodes(list(dirs), self.fs.Dir) - apply(self.fs.Repository, dirs, kw) - - def Scanner(self, *args, **kw): - nargs = [] - for arg in args: - if SCons.Util.is_String(arg): - arg = self.subst(arg) - nargs.append(arg) - nkw = self.subst_kw(kw) - return apply(SCons.Scanner.Scanner, nargs, nkw) - - 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) - SCons.SConsign.File(name, dbm_module) - - def SideEffect(self, side_effect, target): - """Tell scons that side_effects are built as side - effects of building targets.""" - side_effects = self.arg2nodes(side_effect, self.fs.Entry) - targets = self.arg2nodes(target, self.fs.Entry) - - for side_effect in side_effects: - if side_effect.multiple_side_effect_has_builder(): - raise SCons.Errors.UserError, "Multiple ways to build the same target were specified for: %s" % str(side_effect) - side_effect.add_source(targets) - side_effect.side_effect = 1 - self.Precious(side_effect) - for target in targets: - target.side_effects.append(side_effect) - return side_effects - - def SourceCode(self, entry, builder): - """Arrange for a source code builder for (part of) a tree.""" - entries = self.arg2nodes(entry, self.fs.Entry) - for entry in entries: - entry.set_src_builder(builder) - return entries - - def SourceSignatures(self, type): - type = self.subst(type) - if type == 'MD5': - import SCons.Sig.MD5 - self._calc_module = SCons.Sig.MD5 - elif type == 'timestamp': - import SCons.Sig.TimeStamp - self._calc_module = SCons.Sig.TimeStamp - else: - raise UserError, "Unknown source signature type '%s'"%type - - def Split(self, arg): - """This function converts a string or list into a list of strings - or Nodes. This makes things easier for users by allowing files to - be specified as a white-space separated list to be split. - The input rules are: - - A single string containing names separated by spaces. These will be - split apart at the spaces. - - A single Node instance - - A list containing either strings or Node instances. Any strings - in the list are not split at spaces. - In all cases, the function returns a list of Nodes and strings.""" - if SCons.Util.is_List(arg): - return map(self.subst, arg) - elif SCons.Util.is_String(arg): - return string.split(self.subst(arg)) - else: - return [self.subst(arg)] - - def TargetSignatures(self, type): - type = self.subst(type) - if type == 'build': - self._build_signature = 1 - elif type == 'content': - self._build_signature = 0 - else: - raise SCons.Errors.UserError, "Unknown target signature type '%s'"%type - - def Value(self, value): - """ - """ - return SCons.Node.Python.Value(value) - -# The entry point that will be used by the external world -# to refer to a construction environment. This allows the wrapper -# interface to extend a construction environment for its own purposes -# by subclassing SCons.Environment.Base and then assigning the -# class to SCons.Environment.Environment. - -Environment = Base - -# An entry point for returning a proxy subclass instance that overrides -# the subst*() methods so they don't actually perform construction -# variable substitution. This is specifically intended to be the shim -# layer in between global function calls (which don't want construction -# variable substitution) and the DefaultEnvironment() (which would -# substitute variables if left to its own devices).""" -# -# We have to wrap this in a function that allows us to delay definition of -# the class until it's necessary, so that when it subclasses Environment -# it will pick up whatever Environment subclass the wrapper interface -# might have assigned to SCons.Environment.Environment. - -def NoSubstitutionProxy(subject): - class _NoSubstitutionProxy(Environment): - def __init__(self, subject): - self.__dict__['__subject'] = subject - def __getattr__(self, name): - return getattr(self.__dict__['__subject'], name) - def __setattr__(self, name, value): - return setattr(self.__dict__['__subject'], name, value) - def raw_to_mode(self, dict): - try: - raw = dict['raw'] - except KeyError: - pass - else: - del dict['raw'] - dict['mode'] = raw - def subst(self, string, *args, **kwargs): - return string - def subst_kw(self, kw, *args, **kwargs): - return kw - def subst_list(self, string, *args, **kwargs): - nargs = (string, self,) + args - nkw = kwargs.copy() - nkw['gvars'] = {} - self.raw_to_mode(nkw) - return apply(SCons.Util.scons_subst_list, nargs, nkw) - def subst_target_source(self, string, *args, **kwargs): - nargs = (string, self,) + args - nkw = kwargs.copy() - nkw['gvars'] = {} - self.raw_to_mode(nkw) - return apply(SCons.Util.scons_subst, nargs, nkw) - return _NoSubstitutionProxy(subject) diff --git a/scons/scons-local-0.96.1/SCons/Executor.py b/scons/scons-local-0.96.1/SCons/Executor.py deleted file mode 100644 index d0c6d642b..000000000 --- a/scons/scons-local-0.96.1/SCons/Executor.py +++ /dev/null @@ -1,175 +0,0 @@ -"""SCons.Executor - -A module for executing actions with specific lists of target and source -Nodes. - -""" - -# -# Copyright (c) 2001, 2002, 2003, 2004 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__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Executor.py 0.96.1.D001 2004/08/23 09:55:29 knight" - - -from SCons.Debug import logInstanceCreation -import SCons.Util - - -class Executor: - """A class for controlling instances of executing an action. - - This largely exists to hold a single association of an action, - environment, list of environment override dictionaries, targets - and sources for later processing as needed. - """ - - def __init__(self, action, env=None, overridelist=[], targets=[], sources=[]): - if __debug__: logInstanceCreation(self) - self.action = action - self.env = env - self.overridelist = overridelist - self.targets = targets - self.sources = sources[:] - - def get_build_env(self): - """Fetch or create the appropriate build Environment - for this Executor. - """ - try: - return self.build_env - except AttributeError: - # Create the build environment instance with appropriate - # overrides. These get evaluated against the current - # environment's construction variables so that users can - # add to existing values by referencing the variable in - # the expansion. - overrides = {} - for odict in self.overridelist: - overrides.update(odict) - try: - generate_build_dict = self.targets[0].generate_build_dict - except (AttributeError, IndexError): - pass - else: - overrides.update(generate_build_dict()) - - import SCons.Defaults - env = self.env or SCons.Defaults.DefaultEnvironment() - self.build_env = env.Override(overrides) - - # Now update the build environment with the things that we - # don't want expanded against the current construction - # variables. - self.build_env._update(SCons.Util.subst_dict(self.targets, - self.sources)) - return self.build_env - - def get_action_list(self, target): - """Fetch or create the appropriate action list (for this target). - - There is an architectural mistake here: we cache the action list - for the Executor and re-use it regardless of which target is - being asked for. In practice, this doesn't seem to be a problem - because executing the action list will update all of the targets - involved, so only one target's pre- and post-actions will win, - anyway. This is probably a bug we should fix... - """ - try: - al = self.action_list - except AttributeError: - al = self.action.get_actions() - self.action_list = al - try: - # XXX shouldn't reach into node attributes like this - return target.pre_actions + al + target.post_actions - except AttributeError: - return al - - def __call__(self, target, errfunc, **kw): - """Actually execute the action list.""" - action_list = self.get_action_list(target) - if not action_list: - return - env = self.get_build_env() - for action in action_list: - apply(action, (self.targets, self.sources, env, errfunc), kw) - - def cleanup(self): - try: - del self.build_env - except AttributeError: - pass - - def add_sources(self, sources): - """Add source files to this Executor's list. This is necessary - for "multi" Builders that can be called repeatedly to build up - a source file list for a given target.""" - slist = filter(lambda x, s=self.sources: x not in s, sources) - self.sources.extend(slist) - - def __str__(self): - try: - return self.string - except AttributeError: - action = self.action - self.string = action.genstring(self.targets, - self.sources, - self.get_build_env()) - return self.string - - def get_raw_contents(self): - """Fetch the raw signature contents. This, along with - get_contents(), is the real reason this class exists, so we can - compute this once and cache it regardless of how many target or - source Nodes there are. - """ - try: - return self.raw_contents - except AttributeError: - action = self.action - self.raw_contents = action.get_raw_contents(self.targets, - self.sources, - self.get_build_env()) - return self.raw_contents - - def get_contents(self): - """Fetch the signature contents. This, along with - get_raw_contents(), is the real reason this class exists, so we - can compute this once and cache it regardless of how many target - or source Nodes there are. - """ - try: - return self.contents - except AttributeError: - action = self.action - self.contents = action.get_contents(self.targets, - self.sources, - self.get_build_env()) - return self.contents - - def get_timestamp(self): - """Fetch a time stamp for this Executor. We don't have one, of - course (only files do), but this is the interface used by the - timestamp module. - """ - return 0 diff --git a/scons/scons-local-0.96.1/SCons/Node/FS.py b/scons/scons-local-0.96.1/SCons/Node/FS.py deleted file mode 100644 index 06b7f8bfa..000000000 --- a/scons/scons-local-0.96.1/SCons/Node/FS.py +++ /dev/null @@ -1,1867 +0,0 @@ -"""scons.Node.FS - -File system nodes. - -These Nodes represent the canonical external objects that people think -of when they think of building software: files and directories. - -This initializes a "default_fs" Node with an FS at the current directory -for its own purposes, and for use by scripts or modules looking for the -canonical default. - -""" - -# -# Copyright (c) 2001, 2002, 2003, 2004 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__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Node/FS.py 0.96.1.D001 2004/08/23 09:55:29 knight" - -import os -import os.path -import shutil -import stat -import string -import sys -import time -import cStringIO - -import SCons.Action -from SCons.Debug import logInstanceCreation -import SCons.Errors -import SCons.Node -import SCons.Sig.MD5 -import SCons.Util -import SCons.Warnings - -# -# We stringify these file system Nodes a lot. Turning a file system Node -# into a string is non-trivial, because the final string representation -# can depend on a lot of factors: whether it's a derived target or not, -# whether it's linked to a repository or source directory, and whether -# there's duplication going on. The normal technique for optimizing -# calculations like this is to memoize (cache) the string value, so you -# only have to do the calculation once. -# -# 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 -# 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, -# to let this module know it can start returning saved string values -# for Nodes. -# -Save_Strings = None - -def save_strings(val): - global Save_Strings - Save_Strings = val - -# -# SCons.Action objects for interacting with the outside world. -# -# The Node.FS methods in this module should use these actions to -# create and/or remove files and directories; they should *not* use -# os.{link,symlink,unlink,mkdir}(), etc., directly. -# -# Using these SCons.Action objects ensures that descriptions of these -# external activities are properly displayed, that the displays are -# suppressed when the -s (silent) option is used, and (most importantly) -# the actions are disabled when the the -n option is used, in which case -# there should be *no* changes to the external file system(s)... -# - -def _copy_func(src, dest): - shutil.copy2(src, dest) - st=os.stat(src) - os.chmod(dest, stat.S_IMODE(st[stat.ST_MODE]) | stat.S_IWRITE) - -Valid_Duplicates = ['hard-soft-copy', 'soft-hard-copy', - 'hard-copy', 'soft-copy', 'copy'] - -Link_Funcs = [] # contains the callables of the specified duplication style - -def set_duplicate(duplicate): - # Fill in the Link_Funcs list according to the argument - # (discarding those not available on the platform). - - # Set up the dictionary that maps the argument names to the - # underlying implementations. We do this inside this function, - # not in the top-level module code, so that we can remap os.link - # and os.symlink for testing purposes. - try: - _hardlink_func = os.link - except AttributeError: - _hardlink_func = None - - try: - _softlink_func = os.symlink - except AttributeError: - _softlink_func = None - - link_dict = { - 'hard' : _hardlink_func, - 'soft' : _softlink_func, - 'copy' : _copy_func - } - - if not duplicate in Valid_Duplicates: - raise SCons.Errors.InternalError, ("The argument of set_duplicate " - "should be in Valid_Duplicates") - global Link_Funcs - Link_Funcs = [] - for func in string.split(duplicate,'-'): - if link_dict[func]: - Link_Funcs.append(link_dict[func]) - -def LinkFunc(target, source, env): - # Relative paths cause problems with symbolic links, so - # we use absolute paths, which may be a problem for people - # who want to move their soft-linked src-trees around. Those - # people should use the 'hard-copy' mode, softlinks cannot be - # used for that; at least I have no idea how ... - src = source[0].abspath - dest = target[0].abspath - dir, file = os.path.split(dest) - if dir and not os.path.isdir(dir): - os.makedirs(dir) - if not Link_Funcs: - # Set a default order of link functions. - set_duplicate('hard-soft-copy') - # Now link the files with the previously specified order. - for func in Link_Funcs: - try: - func(src,dest) - break - except OSError: - 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) -def LocalString(target, source, env): - return 'Local copy of %s from %s' % (target[0], source[0]) - -LocalCopy = SCons.Action.Action(LinkFunc, LocalString) - -def UnlinkFunc(target, source, env): - t = target[0] - t.fs.unlink(t.abspath) - return 0 - -Unlink = SCons.Action.Action(UnlinkFunc, None) - -def MkdirFunc(target, source, env): - t = target[0] - p = t.abspath - if not t.fs.exists(p): - t.fs.mkdir(p) - return 0 - -Mkdir = SCons.Action.Action(MkdirFunc, None, presub=None) - -MkdirBuilder = None - -def get_MkdirBuilder(): - global MkdirBuilder - if MkdirBuilder is None: - import SCons.Builder - # "env" will get filled in by Executor.get_build_env() - # calling SCons.Defaults.DefaultEnvironment() when necessary. - MkdirBuilder = SCons.Builder.Builder(action = Mkdir, - env = None, - explain = None) - return MkdirBuilder - -def CacheRetrieveFunc(target, source, env): - t = target[0] - fs = t.fs - cachedir, cachefile = t.cachepath() - if fs.exists(cachefile): - fs.copy2(cachefile, t.path) - st = fs.stat(cachefile) - fs.chmod(t.path, stat.S_IMODE(st[stat.ST_MODE]) | stat.S_IWRITE) - return 0 - return 1 - -def CacheRetrieveString(target, source, env): - t = target[0] - cachedir, cachefile = t.cachepath() - if t.fs.exists(cachefile): - return "Retrieved `%s' from cache" % t.path - return None - -CacheRetrieve = SCons.Action.Action(CacheRetrieveFunc, CacheRetrieveString) - -CacheRetrieveSilent = SCons.Action.Action(CacheRetrieveFunc, None) - -def CachePushFunc(target, source, env): - t = target[0] - fs = t.fs - cachedir, cachefile = t.cachepath() - if fs.exists(cachefile): - # Don't bother copying it if it's already there. - return - - if not fs.isdir(cachedir): - fs.makedirs(cachedir) - - tempfile = cachefile+'.tmp' - try: - fs.copy2(t.path, tempfile) - fs.rename(tempfile, cachefile) - st = fs.stat(t.path) - fs.chmod(cachefile, stat.S_IMODE(st[stat.ST_MODE]) | stat.S_IWRITE) - except OSError: - # It's possible someone else tried writing the file at the same - # time we did. Print a warning but don't stop the build, since - # it doesn't affect the correctness of the build. - SCons.Warnings.warn(SCons.Warnings.CacheWriteErrorWarning, - "Unable to copy %s to cache. Cache file is %s" - % (str(target), cachefile)) - return - -CachePush = SCons.Action.Action(CachePushFunc, None) - -class _Null: - pass - -_null = _Null() - -DefaultSCCSBuilder = None -DefaultRCSBuilder = None - -def get_DefaultSCCSBuilder(): - global DefaultSCCSBuilder - if DefaultSCCSBuilder is None: - import SCons.Builder - # "env" will get filled in by Executor.get_build_env() - # calling SCons.Defaults.DefaultEnvironment() when necessary. - DefaultSCCSBuilder = SCons.Builder.Builder(action = '$SCCSCOM', - env = None) - return DefaultSCCSBuilder - -def get_DefaultRCSBuilder(): - global DefaultRCSBuilder - if DefaultRCSBuilder is None: - import SCons.Builder - # "env" will get filled in by Executor.get_build_env() - # calling SCons.Defaults.DefaultEnvironment() when necessary. - DefaultRCSBuilder = SCons.Builder.Builder(action = '$RCS_COCOM', - env = None) - return DefaultRCSBuilder - -# -class ParentOfRoot: - """ - An instance of this class is used as the parent of the root of a - filesystem (POSIX) or drive (Win32). This isn't actually a node, - but it looks enough like one so that we don't have to have - special purpose code everywhere to deal with dir being None. - This class is an instance of the Null object pattern. - """ - def __init__(self): - self.abspath = '' - self.path = '' - self.name='' - self.duplicate=0 - self.srcdir=None - self.build_dirs=[] - - def is_under(self, dir): - return 0 - - def up(self): - return None - - def getRepositories(self): - return [] - - def get_dir(self): - return None - - def src_builder(self): - return _null - - def entry_abspath(self, name): - return name - - def entry_path(self, name): - return name - -# Cygwin's os.path.normcase pretends it's on a case-sensitive filesystem. -_is_cygwin = sys.platform == "cygwin" -if os.path.normcase("TeSt") == os.path.normpath("TeSt") and not _is_cygwin: - def _my_normcase(x): - return x -else: - def _my_normcase(x): - return string.upper(x) - -class EntryProxy(SCons.Util.Proxy): - def __get_abspath(self): - entry = self.get() - return SCons.Util.SpecialAttrWrapper(entry.get_abspath(), - entry.name + "_abspath") - - def __get_filebase(self): - name = self.get().name - return SCons.Util.SpecialAttrWrapper(SCons.Util.splitext(name)[0], - name + "_filebase") - - def __get_suffix(self): - name = self.get().name - return SCons.Util.SpecialAttrWrapper(SCons.Util.splitext(name)[1], - name + "_suffix") - - def __get_file(self): - name = self.get().name - return SCons.Util.SpecialAttrWrapper(name, name + "_file") - - def __get_base_path(self): - """Return the file's directory and file name, with the - suffix stripped.""" - entry = self.get() - return SCons.Util.SpecialAttrWrapper(SCons.Util.splitext(entry.get_path())[0], - entry.name + "_base") - - def __get_posix_path(self): - """Return the path with / as the path separator, - regardless of platform.""" - if os.sep == '/': - return self - else: - entry = self.get() - r = string.replace(entry.get_path(), os.sep, '/') - return SCons.Util.SpecialAttrWrapper(r, entry.name + "_posix") - - def __get_win32_path(self): - """Return the path with \ as the path separator, - regardless of platform.""" - if os.sep == '\\': - return self - else: - entry = self.get() - r = string.replace(entry.get_path(), os.sep, '\\') - return SCons.Util.SpecialAttrWrapper(r, entry.name + "_win32") - - def __get_srcnode(self): - return EntryProxy(self.get().srcnode()) - - 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.""" - return EntryProxy(self.get().srcnode().dir) - - def __get_rsrcnode(self): - return EntryProxy(self.get().srcnode().rfile()) - - 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.""" - return EntryProxy(self.get().srcnode().rfile().dir) - - def __get_dir(self): - return EntryProxy(self.get().dir) - - dictSpecialAttrs = { "base" : __get_base_path, - "posix" : __get_posix_path, - "win32" : __get_win32_path, - "srcpath" : __get_srcnode, - "srcdir" : __get_srcdir, - "dir" : __get_dir, - "abspath" : __get_abspath, - "filebase" : __get_filebase, - "suffix" : __get_suffix, - "file" : __get_file, - "rsrcpath" : __get_rsrcnode, - "rsrcdir" : __get_rsrcdir, - } - - def __getattr__(self, name): - # This is how we implement the "special" attributes - # such as base, posix, srcdir, etc. - try: - return self.dictSpecialAttrs[name](self) - except KeyError: - try: - attr = SCons.Util.Proxy.__getattr__(self, name) - except AttributeError: - entry = self.get() - classname = string.split(str(entry.__class__), '.')[-1] - raise AttributeError, "%s instance '%s' has no attribute '%s'" % (classname, entry.name, name) - return attr - -class Base(SCons.Node.Node): - """A generic class for file system entries. This class is for - when we don't know yet whether the entry being looked up is a file - or a directory. Instances of this class can morph into either - Dir or File objects by a later, more precise lookup. - - Note: this class does not define __cmp__ and __hash__ for - efficiency reasons. SCons does a lot of comparing of - Node.FS.{Base,Entry,File,Dir} objects, so those operations must be - as fast as possible, which means we want to use Python's built-in - object identity comparisons. - """ - - def __init__(self, name, directory, fs): - """Initialize a generic Node.FS.Base object. - - Call the superclass initialization, take care of setting up - our relative and absolute paths, identify our parent - directory, and indicate that this node should use - signatures.""" - if __debug__: logInstanceCreation(self, 'Node.FS.Base') - SCons.Node.Node.__init__(self) - - self.name = name - self.fs = fs - self.relpath = {self : '.'} - - assert directory, "A directory must be provided" - - self.abspath = directory.entry_abspath(name) - if directory.path == '.': - self.path = name - else: - self.path = directory.entry_path(name) - - self.dir = directory - self.cwd = None # will hold the SConscript directory for target nodes - self.duplicate = directory.duplicate - - def clear(self): - """Completely clear a Node.FS.Base object of all its cached - state (so that it can be re-evaluated by interfaces that do - continuous integration builds). - """ - SCons.Node.Node.clear(self) - try: - delattr(self, '_exists') - except AttributeError: - pass - try: - delattr(self, '_rexists') - except AttributeError: - pass - try: - delattr(self, '_str_val') - except AttributeError: - pass - self.relpath = {self : '.'} - - def get_dir(self): - return self.dir - - def get_suffix(self): - return SCons.Util.splitext(self.name)[1] - - def rfile(self): - return self - - def __str__(self): - """A Node.FS.Base object's string representation is its path - name.""" - try: - return self._str_val - except AttributeError: - global Save_Strings - if self.duplicate or self.is_derived(): - str_val = self.get_path() - else: - str_val = self.srcnode().get_path() - if Save_Strings: - self._str_val = str_val - return str_val - - rstr = __str__ - - def exists(self): - try: - return self._exists - except AttributeError: - self._exists = self.fs.exists(self.abspath) - return self._exists - - def rexists(self): - try: - return self._rexists - except AttributeError: - self._rexists = self.rfile().exists() - return self._rexists - - def is_under(self, dir): - if self is dir: - return 1 - else: - return self.dir.is_under(dir) - - def set_local(self): - self._local = 1 - - def srcnode(self): - """If this node is in a build path, return the node - corresponding to its source file. Otherwise, return - ourself.""" - try: - return self._srcnode - except AttributeError: - dir=self.dir - name=self.name - while dir: - if dir.srcdir: - self._srcnode = self.fs.Entry(name, dir.srcdir, - klass=self.__class__) - return self._srcnode - name = dir.name + os.sep + name - dir=dir.get_dir() - self._srcnode = self - return self._srcnode - - def get_path(self, dir=None): - """Return path relative to the current working directory of the - Node.FS.Base object that owns us.""" - if not dir: - dir = self.fs.getcwd() - try: - return self.relpath[dir] - except KeyError: - path_elems = [] - d = self - while d != dir and not isinstance(d, ParentOfRoot): - path_elems.append(d.name) - d = d.dir - path_elems.reverse() - ret = string.join(path_elems, os.sep) - self.relpath[dir] = ret - return ret - - def set_src_builder(self, builder): - """Set the source code builder for this node.""" - self.sbuilder = builder - if not self.has_builder(): - self.builder_set(builder) - - def src_builder(self): - """Fetch the source code builder for this node. - - If there isn't one, we cache the source code builder specified - for the directory (which in turn will cache the value from its - parent directory, and so on up to the file system root). - """ - try: - scb = self.sbuilder - except AttributeError: - scb = self.dir.src_builder() - self.sbuilder = scb - return scb - - def get_abspath(self): - """Get the absolute path of the file.""" - return self.abspath - - def for_signature(self): - # Return just our name. Even an absolute path would not work, - # because that can change thanks to symlinks or remapped network - # paths. - return self.name - - def get_subst_proxy(self): - try: - return self._proxy - except AttributeError: - ret = EntryProxy(self) - self._proxy = ret - return ret - -class Entry(Base): - """This is the class for generic Node.FS entries--that is, things - that could be a File or a Dir, but we're just not sure yet. - Consequently, the methods in this class really exist just to - transform their associated object into the right class when the - time comes, and then call the same-named method in the transformed - class.""" - - def rfile(self): - """We're a generic Entry, but the caller is actually looking for - a File at this point, so morph into one.""" - self.__class__ = File - self._morph() - self.clear() - return File.rfile(self) - - def get_found_includes(self, env, scanner, target): - """If we're looking for included files, it's because this Entry - is really supposed to be a File itself.""" - node = self.rfile() - return node.get_found_includes(env, scanner, target) - - def scanner_key(self): - return self.get_suffix() - - def get_contents(self): - """Fetch the contents of the entry. - - Since this should return the real contents from the file - system, we check to see into what sort of subclass we should - morph this Entry.""" - if self.fs.isfile(self.abspath): - self.__class__ = File - self._morph() - return File.get_contents(self) - if self.fs.isdir(self.abspath): - self.__class__ = Dir - self._morph() - return Dir.get_contents(self) - if self.fs.islink(self.abspath): - return '' # avoid errors for dangling symlinks - raise AttributeError - - def exists(self): - """Return if the Entry exists. Check the file system to see - what we should turn into first. Assume a file if there's no - directory.""" - if self.fs.isdir(self.abspath): - self.__class__ = Dir - self._morph() - return Dir.exists(self) - else: - self.__class__ = File - self._morph() - self.clear() - return File.exists(self) - - def calc_signature(self, calc=None): - """Return the Entry's calculated signature. Check the file - system to see what we should turn into first. Assume a file if - there's no directory.""" - if self.fs.isdir(self.abspath): - self.__class__ = Dir - self._morph() - return Dir.calc_signature(self, calc) - else: - self.__class__ = File - self._morph() - self.clear() - return File.calc_signature(self, calc) - - def must_be_a_Dir(self): - """Called to make sure a Node is a Dir. Since we're an - Entry, we can morph into one.""" - self.__class__ = Dir - self._morph() - -# This is for later so we can differentiate between Entry the class and Entry -# the method of the FS class. -_classEntry = Entry - - -class LocalFS: - # This class implements an abstraction layer for operations involving - # a local file system. Essentially, this wraps any function in - # the os, os.path or shutil modules that we use to actually go do - # anything with or to the local file system. - # - # Note that there's a very good chance we'll refactor this part of - # the architecture in some way as we really implement the interface(s) - # for remote file system Nodes. For example, the right architecture - # might be to have this be a subclass instead of a base class. - # Nevertheless, we're using this as a first step in that direction. - # - # We're not using chdir() yet because the calling subclass method - # needs to use os.chdir() directly to avoid recursion. Will we - # really need this one? - #def chdir(self, path): - # return os.chdir(path) - def chmod(self, path, mode): - return os.chmod(path, mode) - def copy2(self, src, dst): - return shutil.copy2(src, dst) - def exists(self, path): - return os.path.exists(path) - def getmtime(self, path): - return os.path.getmtime(path) - def isdir(self, path): - return os.path.isdir(path) - def isfile(self, path): - return os.path.isfile(path) - def link(self, src, dst): - return os.link(src, dst) - def listdir(self, path): - return os.listdir(path) - def makedirs(self, path): - return os.makedirs(path) - def mkdir(self, path): - return os.mkdir(path) - def rename(self, old, new): - return os.rename(old, new) - def stat(self, path): - return os.stat(path) - def symlink(self, src, dst): - return os.symlink(src, dst) - def open(self, path): - return open(path) - def unlink(self, path): - return os.unlink(path) - - if hasattr(os, 'symlink'): - def islink(self, path): - return os.path.islink(path) - def exists_or_islink(self, path): - return os.path.exists(path) or os.path.islink(path) - else: - def islink(self, path): - return 0 # no symlinks - exists_or_islink = exists - -#class RemoteFS: -# # Skeleton for the obvious methods we might need from the -# # abstraction layer for a remote filesystem. -# def upload(self, local_src, remote_dst): -# pass -# def download(self, remote_src, local_dst): -# pass - - -class FS(LocalFS): - def __init__(self, path = None): - """Initialize the Node.FS subsystem. - - The supplied path is the top of the source tree, where we - expect to find the top-level build file. If no path is - supplied, the current directory is the default. - - The path argument must be a valid absolute path. - """ - if __debug__: logInstanceCreation(self) - self.Top = None - if path == None: - self.pathTop = os.getcwd() - else: - self.pathTop = path - self.Root = {} - self.SConstruct_dir = None - self.CachePath = None - self.cache_force = None - self.cache_show = None - - def set_toplevel_dir(self, path): - assert not self.Top, "You can only set the top-level path on an FS object that has not had its File, Dir, or Entry methods called yet." - self.pathTop = path - - def set_SConstruct_dir(self, dir): - self.SConstruct_dir = dir - - def __setTopLevelDir(self): - if not self.Top: - self.Top = self.__doLookup(Dir, os.path.normpath(self.pathTop)) - self.Top.path = '.' - self._cwd = self.Top - - def getcwd(self): - self.__setTopLevelDir() - return self._cwd - - def __checkClass(self, node, klass): - if isinstance(node, klass) or klass == Entry: - return node - if node.__class__ == Entry: - node.__class__ = klass - node._morph() - return node - raise TypeError, "Tried to lookup %s '%s' as a %s." % \ - (node.__class__.__name__, node.path, klass.__name__) - - def __doLookup(self, fsclass, name, directory = None, create = 1): - """This method differs from the File and Dir factory methods in - one important way: the meaning of the directory parameter. - In this method, if directory is None or not supplied, the supplied - name is expected to be an absolute path. If you try to look up a - relative path with directory=None, then an AssertionError will be - raised.""" - - if not name: - # This is a stupid hack to compensate for the fact - # that the POSIX and Win32 versions of os.path.normpath() - # behave differently. In particular, in POSIX: - # os.path.normpath('./') == '.' - # in Win32 - # os.path.normpath('./') == '' - # os.path.normpath('.\\') == '' - # - # This is a definite bug in the Python library, but we have - # to live with it. - name = '.' - path_comp = string.split(name, os.sep) - drive, path_first = os.path.splitdrive(path_comp[0]) - if not path_first: - # Absolute path - drive = _my_normcase(drive) - try: - directory = self.Root[drive] - except KeyError: - if not create: - raise SCons.Errors.UserError - directory = RootDir(drive, ParentOfRoot(), self) - self.Root[drive] = directory - path_comp = path_comp[1:] - else: - path_comp = [ path_first, ] + path_comp[1:] - - if not path_comp: - path_comp = [''] - - # Lookup the directory - for path_name in path_comp[:-1]: - path_norm = _my_normcase(path_name) - try: - d = directory.entries[path_norm] - except KeyError: - if not create: - raise SCons.Errors.UserError - - # look at the actual filesystem and make sure there isn't - # a file already there - path = directory.entry_path(path_name) - if self.isfile(path): - raise TypeError, \ - "File %s found where directory expected." % path - - dir_temp = Dir(path_name, directory, self) - directory.entries[path_norm] = dir_temp - directory.add_wkid(dir_temp) - directory = dir_temp - else: - d.must_be_a_Dir() - directory = d - - entry_norm = _my_normcase(path_comp[-1]) - try: - e = directory.entries[entry_norm] - except KeyError: - if not create: - raise SCons.Errors.UserError - - # make sure we don't create File nodes when there is actually - # a directory at that path on the disk, and vice versa - path = directory.entry_path(path_comp[-1]) - if fsclass == File: - if self.isdir(path): - raise TypeError, \ - "Directory %s found where file expected." % path - elif fsclass == Dir: - if self.isfile(path): - raise TypeError, \ - "File %s found where directory expected." % path - - result = fsclass(path_comp[-1], directory, self) - directory.entries[entry_norm] = result - directory.add_wkid(result) - else: - result = self.__checkClass(e, fsclass) - return result - - def __transformPath(self, name, directory): - """Take care of setting up the correct top-level directory, - usually in preparation for a call to doLookup(). - - If the path name is prepended with a '#', then it is unconditionally - interpreted as relative to the top-level directory of this FS. - - If directory is None, and name is a relative path, - then the same applies. - """ - self.__setTopLevelDir() - if name and name[0] == '#': - directory = self.Top - name = name[1:] - if name and (name[0] == os.sep or name[0] == '/'): - # Correct such that '#/foo' is equivalent - # to '#foo'. - name = name[1:] - name = os.path.join('.', os.path.normpath(name)) - elif not directory: - directory = self._cwd - return (os.path.normpath(name), directory) - - def chdir(self, dir, change_os_dir=0): - """Change the current working directory for lookups. - If change_os_dir is true, we will also change the "real" cwd - to match. - """ - self.__setTopLevelDir() - curr=self._cwd - try: - if not dir is None: - self._cwd = dir - if change_os_dir: - os.chdir(dir.abspath) - except OSError: - self._cwd = curr - raise - - def Entry(self, name, directory = None, create = 1, klass=None): - """Lookup 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 - construction time) if no directory is supplied. - """ - - if not klass: - klass = Entry - - if isinstance(name, Base): - return self.__checkClass(name, klass) - else: - if directory and not isinstance(directory, Dir): - directory = self.Dir(directory) - name, directory = self.__transformPath(name, directory) - return self.__doLookup(klass, name, directory, create) - - def File(self, name, directory = None, create = 1): - """Lookup 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 - time) if no directory is supplied. - - This method will raise TypeError if a directory is found at the - specified path. - """ - - return self.Entry(name, directory, create, File) - - def Dir(self, name, directory = None, create = 1): - """Lookup 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 - time) if no directory is supplied. - - This method will raise TypeError if a normal file is found at the - specified path. - """ - - return self.Entry(name, directory, create, Dir) - - def BuildDir(self, build_dir, src_dir, duplicate=1): - """Link the supplied build directory to the source directory - for purposes of building files.""" - - self.__setTopLevelDir() - 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 not src_dir.is_under(self.Top): - raise SCons.Errors.UserError, "Source directory must be under top of build tree." - 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: - 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) - - def Repository(self, *dirs): - """Specify Repository directories to search.""" - for d in dirs: - if not isinstance(d, SCons.Node.Node): - d = self.Dir(d) - self.__setTopLevelDir() - self.Top.addRepository(d) - - def Rsearch(self, path, clazz=_classEntry, cwd=None): - """Search for something in a Repository. Returns the first - one found in the list, or None if there isn't one.""" - if isinstance(path, SCons.Node.Node): - return path - else: - name, d = self.__transformPath(path, cwd) - n = self.__doLookup(clazz, name, d) - if n.exists(): - return n - if isinstance(n, Dir): - # If n is a Directory that has Repositories directly - # attached to it, then any of those is a valid Repository - # path. Return the first one that exists. - reps = filter(lambda x: x.exists(), n.getRepositories()) - if len(reps): - return reps[0] - d = n.get_dir() - name = n.name - # Search repositories of all directories that this file is under. - while d: - for rep in d.getRepositories(): - try: - rnode = self.__doLookup(clazz, name, rep) - # Only find the node if it exists and it is not - # a derived file. If for some reason, we are - # explicitly building a file IN a Repository, we - # don't want it to show up in the build tree. - # This is usually the case with BuildDir(). - # We only want to find pre-existing files. - if rnode.exists() and \ - (isinstance(rnode, Dir) or not rnode.is_derived()): - return rnode - except TypeError: - pass # Wrong type of node. - # Prepend directory name - name = d.name + os.sep + name - # Go up one directory - d = d.get_dir() - return None - - def Rsearchall(self, pathlist, must_exist=1, clazz=_classEntry, cwd=None): - """Search for a list of somethings in the Repository list.""" - ret = [] - if SCons.Util.is_String(pathlist): - pathlist = string.split(pathlist, os.pathsep) - if not SCons.Util.is_List(pathlist): - pathlist = [pathlist] - for path in filter(None, pathlist): - if isinstance(path, SCons.Node.Node): - ret.append(path) - else: - name, d = self.__transformPath(path, cwd) - n = self.__doLookup(clazz, name, d) - if not must_exist or n.exists(): - ret.append(n) - if isinstance(n, Dir): - # If this node is a directory, then any repositories - # attached to this node can be repository paths. - ret.extend(filter(lambda x, me=must_exist, clazz=clazz: isinstance(x, clazz) and (not me or x.exists()), - n.getRepositories())) - - d = n.get_dir() - name = n.name - # Search repositories of all directories that this file - # is under. - while d: - for rep in d.getRepositories(): - try: - rnode = self.__doLookup(clazz, name, rep) - # Only find the node if it exists (or - # must_exist is zero) and it is not a - # derived file. If for some reason, we - # are explicitly building a file IN a - # Repository, we don't want it to show up in - # the build tree. This is usually the case - # with BuildDir(). We only want to find - # pre-existing files. - if (not must_exist or rnode.exists()) and \ - (not rnode.is_derived() or isinstance(rnode, Dir)): - ret.append(rnode) - except TypeError: - pass # Wrong type of node. - # Prepend directory name - name = d.name + os.sep + name - # Go up one directory - d = d.get_dir() - return ret - - def CacheDir(self, path): - self.CachePath = path - - def build_dir_target_climb(self, dir, tail): - """Create targets in corresponding build directories - - Climb the directory tree, and look up path names - relative to any linked build directories we find. - """ - targets = [] - message = None - while dir: - for bd in dir.build_dirs: - p = apply(os.path.join, [bd.path] + tail) - targets.append(self.Entry(p)) - tail = [dir.name] + tail - dir = dir.up() - if targets: - message = "building associated BuildDir targets: %s" % string.join(map(str, targets)) - return targets, message - -class DummyExecutor: - """Dummy executor class returned by Dir nodes to bamboozle SCons - into thinking we are an actual derived node, where our sources are - our directory entries.""" - def cleanup(self): - pass - def get_raw_contents(self): - return '' - def get_contents(self): - return '' - def get_timestamp(self): - return 0 - def get_build_env(self): - return None - -class Dir(Base): - """A class for directories in a file system. - """ - - def __init__(self, name, directory, fs): - if __debug__: logInstanceCreation(self, 'Node.FS.Dir') - Base.__init__(self, name, directory, fs) - self._morph() - - def _morph(self): - """Turn a file system Node (either a freshly initialized directory - object or a separate Entry object) into a proper directory object. - - Set up this directory's entries and hook it into the file - system tree. Specify that directories (this Node) don't use - signatures for calculating whether they're current.""" - - self.repositories = [] - self.srcdir = None - - self.entries = {} - self.entries['.'] = self - self.entries['..'] = self.dir - self.cwd = self - self.builder = get_MkdirBuilder() - self.searched = 0 - self._sconsign = None - self.build_dirs = [] - - def __clearRepositoryCache(self, duplicate=None): - """Called when we change the repository(ies) for a directory. - This clears any cached information that is invalidated by changing - the repository.""" - - for node in self.entries.values(): - if node != self.dir: - if node != self and isinstance(node, Dir): - node.__clearRepositoryCache(duplicate) - else: - try: - del node._srcreps - except AttributeError: - pass - try: - del node._rfile - except AttributeError: - pass - try: - del node._rexists - except AttributeError: - pass - try: - del node._exists - except AttributeError: - pass - try: - del node._srcnode - except AttributeError: - pass - try: - del node._str_val - except AttributeError: - pass - if duplicate != None: - node.duplicate=duplicate - - def __resetDuplicate(self, node): - if node != self: - node.duplicate = node.get_dir().duplicate - - def Entry(self, name): - """Create an entry node named 'name' relative to this directory.""" - return self.fs.Entry(name, self) - - def Dir(self, name): - """Create a directory node named 'name' relative to this directory.""" - return self.fs.Dir(name, self) - - def File(self, name): - """Create a file node named 'name' relative to this directory.""" - return self.fs.File(name, self) - - def link(self, srcdir, duplicate): - """Set this directory as the build directory for the - supplied source directory.""" - self.srcdir = srcdir - self.duplicate = duplicate - self.__clearRepositoryCache(duplicate) - srcdir.build_dirs.append(self) - - def getRepositories(self): - """Returns a list of repositories for this directory.""" - if self.srcdir and not self.duplicate: - try: - return self._srcreps - except AttributeError: - self._srcreps = self.fs.Rsearchall(self.srcdir.path, - clazz=Dir, - must_exist=0, - cwd=self.fs.Top) \ - + self.repositories - return self._srcreps - return self.repositories - - def addRepository(self, dir): - if not dir in self.repositories and dir != self: - self.repositories.append(dir) - self.__clearRepositoryCache() - - def up(self): - return self.entries['..'] - - def root(self): - if not self.entries['..']: - return self - else: - return self.entries['..'].root() - - def scan(self): - if not self.implicit is None: - return - self.implicit = [] - self.implicit_dict = {} - self._children_reset() - try: - for filename in self.fs.listdir(self.abspath): - if filename != '.sconsign': - self.Entry(filename) - except OSError: - # Directory does not exist. No big deal - pass - keys = filter(lambda k: k != '.' and k != '..', self.entries.keys()) - kids = map(lambda x, s=self: s.entries[x], keys) - def c(one, two): - return cmp(one.abspath, two.abspath) - kids.sort(c) - self._add_child(self.implicit, self.implicit_dict, kids) - - def get_actions(self): - """A null "builder" for directories.""" - return [] - - def build(self, **kw): - """A null "builder" for directories.""" - global MkdirBuilder - if not self.builder is MkdirBuilder: - apply(SCons.Node.Node.build, [self,], kw) - - def multiple_side_effect_has_builder(self): - global MkdirBuilder - return not self.builder is MkdirBuilder and self.has_builder() - - def alter_targets(self): - """Return any corresponding targets in a build directory. - """ - return self.fs.build_dir_target_climb(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 = cStringIO.StringIO() - for kid in self.children(): - contents.write(kid.get_contents()) - return contents.getvalue() - - def prepare(self): - pass - - def current(self, calc=None): - """If all of our children were up-to-date, then this - directory was up-to-date, too.""" - if not self.builder is MkdirBuilder and not self.exists(): - return 0 - state = 0 - for kid in self.children(): - s = kid.get_state() - if s and (not state or s > state): - state = s - import SCons.Node - if state == 0 or state == SCons.Node.up_to_date: - return 1 - else: - return 0 - - def rdir(self): - try: - return self._rdir - except AttributeError: - self._rdir = self - if not self.exists(): - n = self.fs.Rsearch(self.path, clazz=Dir, cwd=self.fs.Top) - if n: - self._rdir = n - return self._rdir - - def sconsign(self): - """Return the .sconsign file info for this directory, - creating it first if necessary.""" - if not self._sconsign: - import SCons.SConsign - self._sconsign = SCons.SConsign.ForDirectory(self) - return self._sconsign - - def srcnode(self): - """Dir has a special need for srcnode()...if we - have a srcdir attribute set, then that *is* our srcnode.""" - if self.srcdir: - return self.srcdir - return Base.srcnode(self) - - def get_timestamp(self): - """Return the latest timestamp from among our children""" - stamp = 0 - for kid in self.children(): - if kid.get_timestamp() > stamp: - stamp = kid.get_timestamp() - return stamp - - def entry_abspath(self, name): - return self.abspath + os.sep + name - - def entry_path(self, name): - return self.path + os.sep + name - - def must_be_a_Dir(self): - """Called to make sure a Node is a Dir. Since we're already - one, this is a no-op for us.""" - pass - -class RootDir(Dir): - """A class for the root directory of a file system. - - This is the same as a Dir class, except that the path separator - ('/' or '\\') is actually part of the name, so we don't need to - add a separator when creating the path names of entries within - this directory. - """ - def __init__(self, name, directory, fs): - if __debug__: logInstanceCreation(self, 'Node.FS.RootDir') - Base.__init__(self, name, directory, fs) - self.path = self.path + os.sep - self.abspath = self.abspath + os.sep - self._morph() - - def entry_abspath(self, name): - return self.abspath + name - - def entry_path(self, name): - return self.path + name - -class BuildInfo: - bsig = None - def __cmp__(self, other): - try: - return cmp(self.bsig, other.bsig) - except AttributeError: - return 1 - -class File(Base): - """A class for files in a file system. - """ - def __init__(self, name, directory, fs): - if __debug__: logInstanceCreation(self, 'Node.FS.File') - Base.__init__(self, name, directory, fs) - self._morph() - - def Entry(self, name): - """Create an entry node named 'name' relative to - the SConscript directory of this file.""" - return self.fs.Entry(name, self.cwd) - - def Dir(self, name): - """Create a directory node named 'name' relative to - the SConscript directory of this file.""" - return self.fs.Dir(name, self.cwd) - - def File(self, name): - """Create a file node named 'name' relative to - the SConscript directory of this file.""" - return self.fs.File(name, self.cwd) - - def RDirs(self, pathlist): - """Search for a list of directories in the Repository list.""" - return self.fs.Rsearchall(pathlist, clazz=Dir, must_exist=0, - cwd=self.cwd) - - def generate_build_dict(self): - """Return an appropriate dictionary of values for building - this File.""" - return {'Dir' : self.Dir, - 'File' : self.File, - 'RDirs' : self.RDirs} - - def _morph(self): - """Turn a file system node into a File object.""" - self.scanner_paths = {} - self.found_includes = {} - if not hasattr(self, '_local'): - self._local = 0 - - def root(self): - return self.dir.root() - - def scanner_key(self): - return self.get_suffix() - - def get_contents(self): - if not self.rexists(): - return '' - return open(self.rfile().abspath, "rb").read() - - def get_timestamp(self): - if self.rexists(): - return self.fs.getmtime(self.rfile().abspath) - else: - return 0 - - def store_info(self, obj): - # Merge our build information into the already-stored entry. - # 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. - entry = self.get_stored_info() - for key, val in obj.__dict__.items(): - entry.__dict__[key] = val - self.dir.sconsign().set_entry(self.name, entry) - - def get_stored_info(self): - try: - stored = self.dir.sconsign().get_entry(self.name) - if isinstance(stored, BuildInfo): - return stored - # The stored build information isn't a BuildInfo object. - # This probably means it's an old SConsignEntry from SCons - # 0.95 or before. The relevant attribute names are the same, - # though, so just copy the attributes over to an object of - # the correct type. - binfo = BuildInfo() - for key, val in stored.__dict__.items(): - setattr(binfo, key, val) - return binfo - except: - return BuildInfo() - - def get_stored_implicit(self): - binfo = self.get_stored_info() - try: - return binfo.bimplicit - except AttributeError: - return None - - def get_found_includes(self, env, scanner, target): - """Return the included implicit dependencies in this file. - Cache results so we only scan the file once regardless of - how many times this information is requested.""" - if not scanner: - return [] - - try: - path = target.scanner_paths[scanner] - except AttributeError: - # The target had no scanner_paths attribute, which means - # it's an Alias or some other node that's not actually a - # file. In that case, back off and use the path for this - # node itself. - try: - path = self.scanner_paths[scanner] - except KeyError: - path = scanner.path(env, self.cwd) - self.scanner_paths[scanner] = path - except KeyError: - path = scanner.path(env, target.cwd) - target.scanner_paths[scanner] = path - - try: - includes = self.found_includes[path] - except KeyError: - includes = scanner(self, env, path) - self.found_includes[path] = includes - - return includes - - def _createDir(self): - # ensure that the directories for this node are - # created. - - listDirs = [] - parent=self.dir - while parent: - if parent.exists(): - break - listDirs.append(parent) - p = parent.up() - if isinstance(p, ParentOfRoot): - raise SCons.Errors.StopError, parent.path - parent = p - listDirs.reverse() - for dirnode in listDirs: - try: - # Don't call dirnode.build(), call the base Node method - # directly because we definitely *must* create this - # directory. The dirnode.build() method will suppress - # the build if it's the default builder. - SCons.Node.Node.build(dirnode) - # The build() action may or may not have actually - # created the directory, depending on whether the -n - # option was used or not. Delete the _exists and - # _rexists attributes so they can be reevaluated. - try: - delattr(dirnode, '_exists') - except AttributeError: - pass - try: - delattr(dirnode, '_rexists') - except AttributeError: - pass - except OSError: - pass - - def retrieve_from_cache(self): - """Try to retrieve the node's content from a cache - - This method is called from multiple threads in a parallel build, - so only do thread safe stuff here. Do thread unsafe stuff in - built(). - - Returns true iff the node was successfully retrieved. - """ - b = self.is_derived() - if not b and not self.has_src_builder(): - return None - if b and self.fs.CachePath: - if self.fs.cache_show: - if CacheRetrieveSilent(self, [], None) == 0: - self.build(presub=0, execute=0) - return 1 - elif CacheRetrieve(self, [], None) == 0: - return 1 - return None - - def built(self): - """Called just after this node is sucessfully built.""" - # Push this file out to cache before the superclass Node.built() - # method has a chance to clear the build signature, which it - # will do if this file has a source scanner. - if self.fs.CachePath and self.fs.exists(self.path): - CachePush(self, [], None) - SCons.Node.Node.built(self) - self.found_includes = {} - try: - delattr(self, '_exists') - except AttributeError: - pass - try: - delattr(self, '_rexists') - except AttributeError: - pass - - def visited(self): - if self.fs.CachePath and self.fs.cache_force and self.fs.exists(self.path): - CachePush(self, None, None) - - def has_src_builder(self): - """Return whether this Node has a source builder or not. - - If this Node doesn't have an explicit source code builder, this - is where we figure out, on the fly, if there's a transparent - source code builder for it. - - Note that if we found a source builder, we also set the - self.builder attribute, so that all of the methods that actually - *build* this file don't have to do anything different. - """ - try: - scb = self.sbuilder - except AttributeError: - if self.rexists(): - scb = None - else: - scb = self.dir.src_builder() - if scb is _null: - scb = None - dir = self.dir.path - sccspath = os.path.join('SCCS', 's.' + self.name) - if dir != '.': - sccspath = os.path.join(dir, sccspath) - if self.fs.exists(sccspath): - scb = get_DefaultSCCSBuilder() - else: - rcspath = os.path.join('RCS', self.name + ',v') - if dir != '.': - rcspath = os.path.join(dir, rcspath) - if os.path.exists(rcspath): - scb = get_DefaultRCSBuilder() - self.builder = scb - self.sbuilder = scb - return not scb is None - - def alter_targets(self): - """Return any corresponding targets in a build directory. - """ - if self.is_derived(): - return [], None - return self.fs.build_dir_target_climb(self.dir, [self.name]) - - def is_pseudo_derived(self): - return self.has_src_builder() - - def prepare(self): - """Prepare for this file to be created.""" - SCons.Node.Node.prepare(self) - - if self.get_state() != SCons.Node.up_to_date: - if self.exists(): - if self.is_derived() and not self.precious: - try: - Unlink(self, [], None) - except OSError, e: - raise SCons.Errors.BuildError(node = self, - errstr = e.strerror) - try: - delattr(self, '_exists') - except AttributeError: - pass - else: - try: - self._createDir() - except SCons.Errors.StopError, drive: - desc = "No drive `%s' for target `%s'." % (drive, self) - raise SCons.Errors.StopError, desc - - def remove(self): - """Remove this file.""" - if self.fs.exists_or_islink(self.path): - self.fs.unlink(self.path) - return 1 - return None - - 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().rfile() - if src.exists() and src.abspath != self.abspath: - self._createDir() - try: - Unlink(self, None, None) - except OSError: - pass - try: - Link(self, src, None) - except IOError, e: - desc = "Cannot duplicate `%s' in `%s': %s." % (src, self.dir, e.strerror) - raise SCons.Errors.StopError, desc - self.linked = 1 - # The Link() action may or may not have actually - # created the file, depending on whether the -n - # option was used or not. Delete the _exists and - # _rexists attributes so they can be reevaluated. - try: - delattr(self, '_exists') - except AttributeError: - pass - try: - delattr(self, '_rexists') - except AttributeError: - pass - return Base.exists(self) - - def new_binfo(self): - return BuildInfo() - - def del_cinfo(self): - try: - del self.binfo.csig - except AttributeError: - pass - try: - del self.binfo.timestamp - except AttributeError: - pass - - def calc_csig(self, calc=None): - """ - Generate a node's content signature, the digested signature - of its content. - - node - the node - cache - alternate node to use for the signature cache - returns - the content signature - """ - if calc is None: - calc = self.calculator() - - try: - return self.binfo.csig - except AttributeError: - pass - - if calc.max_drift >= 0: - old = self.get_stored_info() - else: - old = BuildInfo() - - try: - mtime = self.get_timestamp() - except: - mtime = 0 - raise SCons.Errors.UserError, "no such %s" % self - - try: - if (old.timestamp and old.csig and old.timestamp == mtime): - # use the signature stored in the .sconsign file - csig = old.csig - else: - csig = calc.module.signature(self) - except AttributeError: - csig = calc.module.signature(self) - - if calc.max_drift >= 0 and (time.time() - mtime) > calc.max_drift: - try: - binfo = self.binfo - except AttributeError: - binfo = self.binfo = self.new_binfo() - binfo.csig = csig - binfo.timestamp = mtime - self.store_info(binfo) - - return csig - - def current(self, calc=None, scan=1): - self.binfo = self.gen_binfo(calc) - if self.always_build: - return None - if not self.exists(): - # The file doesn't exist locally... - r = self.rfile() - if r != self: - # ...but there is one in a Repository... - old = r.get_stored_info() - if old == self.binfo: - # ...and it's even up-to-date... - if self._local: - # ...and they'd like a local copy. - LocalCopy(self, r, None) - self.store_info(self.binfo) - return 1 - self._rfile = self - return None - else: - old = self.get_stored_info() - return (old == self.binfo) - - def rfile(self): - try: - return self._rfile - except AttributeError: - self._rfile = self - if not self.exists(): - n = self.fs.Rsearch(self.path, clazz=File, - cwd=self.fs.Top) - if n: - self._rfile = n - return self._rfile - - def rstr(self): - return str(self.rfile()) - - def cachepath(self): - if not self.fs.CachePath: - return None, None - if self.binfo.bsig is None: - raise SCons.Errors.InternalError, "cachepath(%s) found a bsig of None" % self.path - # 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. - cache_sig = SCons.Sig.MD5.collect([self.binfo.bsig, self.path]) - subdir = string.upper(cache_sig[0]) - dir = os.path.join(self.fs.CachePath, subdir) - return dir, os.path.join(dir, cache_sig) - - def target_from_source(self, prefix, suffix, splitext=SCons.Util.splitext): - return self.dir.File(prefix + splitext(self.name)[0] + suffix) - - def must_be_a_Dir(self): - """Called to make sure a Node is a Dir. Since we're already a - File, this is a TypeError...""" - raise TypeError, "Tried to lookup File '%s' as a Dir." % self.path - -default_fs = FS() - - -def find_file(filename, paths, node_factory = default_fs.File): - """ - find_file(str, [Dir()]) -> [nodes] - - filename - a filename to find - paths - a list of directory path *nodes* to search in - - returns - the node created from the found file. - - Find a node corresponding to either a derived file or a file - that exists already. - - Only the first file found is returned, and none is returned - if no file is found. - """ - retval = None - for dir in paths: - try: - node = node_factory(filename, dir) - # Return true if the node exists or is a derived node. - if node.is_derived() or \ - node.is_pseudo_derived() or \ - (isinstance(node, SCons.Node.FS.Base) and node.exists()): - retval = node - break - except TypeError: - # If we find a directory instead of a file, we don't care - pass - - return retval - -def find_files(filenames, paths, node_factory = default_fs.File): - """ - find_files([str], [Dir()]) -> [nodes] - - filenames - a list of filenames to find - paths - a list of directory path *nodes* to search in - - returns - the nodes created from the found files. - - Finds nodes corresponding to either derived files or files - that exist already. - - Only the first file found is returned for each filename, - and any files that aren't found are ignored. - """ - nodes = map(lambda x, paths=paths, node_factory=node_factory: - find_file(x, paths, node_factory), - filenames) - return filter(lambda x: x != None, nodes) diff --git a/scons/scons-local-0.96.1/SCons/Options/PathOption.py b/scons/scons-local-0.96.1/SCons/Options/PathOption.py deleted file mode 100644 index 246dae195..000000000 --- a/scons/scons-local-0.96.1/SCons/Options/PathOption.py +++ /dev/null @@ -1,85 +0,0 @@ -"""engine.SCons.Options.PathOption - -This file defines an option type for SCons implementing 'package -activation'. - -To be used whenever a 'package' may be enabled/disabled and the -package path may be specified. - -Usage example: - - Examples: - x11=no (disables X11 support) - x11=yes (will search for the package installation dir) - x11=/usr/local/X11 (will check this path for existance) - - To replace autoconf's --with-xxx=yyy - - opts = Options() - - opts = Options() - opts.Add(PathOption('qtdir', - 'where the root of Qt is installed', - qtdir)) - opts.Add(PathOption('qt_includes', - 'where the Qt includes are installed', - '$qtdir/includes')) - opts.Add(PathOption('qt_libraries', - 'where the Qt library is installed', - '$qtdir/lib')) - -""" - -# -# Copyright (c) 2001, 2002, 2003, 2004 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__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Options/PathOption.py 0.96.1.D001 2004/08/23 09:55:29 knight" - -__all__ = ('PathOption',) - -import os - -import SCons.Errors - -def _validator(key, val, env): - """ - """ - # todo: write validator, check for path - if not os.path.exists(val): - raise SCons.Errors.UserError( - 'Path does not exist for option %s: %s' % (key, val)) - - -def PathOption(key, help, default): - # NB: searchfunc is currenty undocumented and unsupported - """ - The input parameters describe a 'path list' option, thus they - are returned with the correct converter and validator appended. The - result is usable for input to opts.Add() . - - A 'package list' option may either be 'all', 'none' or a list of - package names (seperated by space). - """ - return (key, '%s ( /path/to/%s )' % (help, key), default, - _validator, None) - diff --git a/scons/scons-local-0.96.1/SCons/Platform/__init__.py b/scons/scons-local-0.96.1/SCons/Platform/__init__.py deleted file mode 100644 index cbc53093b..000000000 --- a/scons/scons-local-0.96.1/SCons/Platform/__init__.py +++ /dev/null @@ -1,126 +0,0 @@ -"""SCons.Platform - -SCons platform selection. - -This looks for modules that define a callable object that can modify a -construction environment as appropriate for a given platform. - -Note that we take a more simplistic view of "platform" than Python does. -We're looking for a single string that determines a set of -tool-independent variables with which to initialize a construction -environment. Consequently, we'll examine both sys.platform and os.name -(and anything else that might come in to play) in order to return some -specification which is unique enough for our purposes. - -Note that because this subsysem just *selects* a callable that can -modify a construction environment, it's possible for people to define -their own "platform specification" in an arbitrary callable function. -No one needs to use or tie in to this subsystem in order to roll -their own platform definition. -""" - -# -# Copyright (c) 2001, 2002, 2003, 2004 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__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Platform/__init__.py 0.96.1.D001 2004/08/23 09:55:29 knight" - -import imp -import os -import string -import sys - -import SCons.Errors -import SCons.Tool - -def platform_default(): - """Return the platform string for our execution environment. - - The returned value should map to one of the SCons/Platform/*.py - files. Since we're architecture independent, though, we don't - care about the machine architecture. - """ - osname = os.name - if osname == 'java': - osname = os._osType - if osname == 'posix': - if sys.platform == 'cygwin': - return 'cygwin' - elif string.find(sys.platform, 'irix') != -1: - return 'irix' - elif string.find(sys.platform, 'sunos') != -1: - return 'sunos' - elif string.find(sys.platform, 'hp-ux') != -1: - return 'hpux' - elif string.find(sys.platform, 'aix') != -1: - return 'aix' - elif string.find(sys.platform, 'darwin') != -1: - return 'darwin' - else: - return 'posix' - elif os.name == 'os2': - return 'os2' - else: - return sys.platform - -def platform_module(name = platform_default()): - """Return the imported module for the platform. - - This looks for a module name that matches the specified argument. - If the name is unspecified, we fetch the appropriate default for - our execution environment. - """ - full_name = 'SCons.Platform.' + name - if not sys.modules.has_key(full_name): - if os.name == 'java': - eval(full_name) - else: - try: - file, path, desc = imp.find_module(name, - sys.modules['SCons.Platform'].__path__) - mod = imp.load_module(full_name, file, path, desc) - setattr(SCons.Platform, name, mod) - except ImportError: - raise SCons.Errors.UserError, "No platform named '%s'" % name - if file: - file.close() - return sys.modules[full_name] - -def DefaultToolList(platform, env): - """Select a default tool list for the specified platform. - """ - return SCons.Tool.tool_list(platform, env) - -class PlatformSpec: - def __init__(self, name): - self.name = name - - def __str__(self): - return self.name - -def Platform(name = platform_default()): - """Select a canned Platform specification. - """ - module = platform_module(name) - spec = PlatformSpec(name) - spec.__call__ = module.generate - return spec diff --git a/scons/scons-local-0.96.1/SCons/Taskmaster.py b/scons/scons-local-0.96.1/SCons/Taskmaster.py deleted file mode 100644 index 1698d3cd0..000000000 --- a/scons/scons-local-0.96.1/SCons/Taskmaster.py +++ /dev/null @@ -1,452 +0,0 @@ -"""SCons.Taskmaster - -Generic Taskmaster. - -""" - -# -# Copyright (c) 2001, 2002, 2003, 2004 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__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Taskmaster.py 0.96.1.D001 2004/08/23 09:55:29 knight" - -import string -import sys -import traceback - -import SCons.Node -import SCons.Errors - -class Task: - """Default SCons build engine task. - - This controls the interaction of the actual building of node - and the rest of the engine. - - This is expected to handle all of the normally-customizable - aspects of controlling a build, so any given application - *should* be able to do what it wants by sub-classing this - class and overriding methods as appropriate. If an application - needs to customze something by sub-classing Taskmaster (or - some other build engine class), we should first try to migrate - that functionality into this class. - - Note that it's generally a good idea for sub-classes to call - these methods explicitly to update state, etc., rather than - roll their own interaction with Taskmaster from scratch.""" - def __init__(self, tm, targets, top, node): - self.tm = tm - self.targets = targets - self.top = top - self.node = node - - def display(self, message): - """Allow the calling interface to display a message - """ - pass - - def prepare(self): - """Called just before the task is executed. - - This unlinks all targets and makes all directories before - building anything.""" - - # Now that it's the appropriate time, give the TaskMaster a - # chance to raise any exceptions it encountered while preparing - # this task. - self.tm.exception_raise() - - if self.tm.message: - self.display(self.tm.message) - self.tm.message = None - - for t in self.targets: - t.prepare() - for s in t.side_effects: - s.prepare() - - def execute(self): - """Called to execute the task. - - This method is called from multiple threads in a parallel build, - so only do thread safe stuff here. Do thread unsafe stuff in - prepare(), executed() or failed().""" - - try: - everything_was_cached = 1 - for t in self.targets: - if not t.retrieve_from_cache(): - everything_was_cached = 0 - 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) - except SCons.Errors.UserError: - raise - except SCons.Errors.BuildError: - raise - except: - exc_type, exc_value, exc_traceback = sys.exc_info() - raise SCons.Errors.BuildError(self.targets[0], - "Exception", - exc_type, - exc_value, - exc_traceback) - - def get_target(self): - """Fetch the target being built or updated by this task. - """ - return self.node - - def executed(self): - """Called when the task has been successfully executed. - - This may have been a do-nothing operation (to preserve - build order), so check the node's state before updating - things. Most importantly, this calls back to the - Taskmaster to put any node tasks waiting on this one - back on the pending list.""" - - if self.targets[0].get_state() == SCons.Node.executing: - for t in self.targets: - for side_effect in t.side_effects: - side_effect.set_state(None) - t.set_state(SCons.Node.executed) - t.built() - else: - for t in self.targets: - t.visited() - - self.tm.executed(self.node) - - def failed(self): - """Default action when a task fails: stop the build.""" - self.fail_stop() - - def fail_stop(self): - """Explicit stop-the-build failure.""" - for t in self.targets: - t.set_state(SCons.Node.failed) - self.tm.failed(self.node) - self.tm.stop() - - def fail_continue(self): - """Explicit continue-the-build failure. - - This sets failure status on the target nodes and all of - their dependent parent nodes. - """ - 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) - - self.tm.executed(self.node) - - def mark_targets(self, state): - for t in self.targets: - t.set_state(state) - - def mark_targets_and_side_effects(self, state): - for t in self.targets: - for side_effect in t.side_effects: - side_effect.set_state(state) - t.set_state(state) - - def make_ready_all(self): - """Mark all targets in a task ready for execution. - - This is used when the interface needs every target Node to be - visited--the canonical example being the "scons -c" option. - """ - self.out_of_date = self.targets[:] - self.mark_targets_and_side_effects(SCons.Node.executing) - - def make_ready_current(self): - """Mark all targets in a task ready for execution if any target - is not current. - - This is the default behavior for building only what's necessary. - """ - self.out_of_date = [] - for t in self.targets: - if not t.current(): - self.out_of_date.append(t) - if self.out_of_date: - self.mark_targets_and_side_effects(SCons.Node.executing) - else: - self.mark_targets(SCons.Node.up_to_date) - - make_ready = make_ready_current - - def postprocess(self): - """Post process a task after it's been executed.""" - for t in self.targets: - t.postprocess() - - def exc_info(self): - return self.tm.exception - - def exc_clear(self): - self.tm.exception_clear() - - def exception_set(self): - self.tm.exception_set() - - - -def order(dependencies): - """Re-order a list of dependencies (if we need to).""" - return dependencies - - -class Taskmaster: - """A generic Taskmaster for handling a bunch of targets. - - Classes that override methods of this class should call - the base class method, so this class can do its thing. - """ - - def __init__(self, targets=[], tasker=Task, order=order): - self.targets = targets # top level targets - self.candidates = targets[:] # nodes that might be ready to be executed - self.candidates.reverse() - self.executing = [] # nodes that are currently executing - self.pending = [] # nodes that depend on a currently executing node - self.tasker = tasker - self.ready = None # the next task that is ready to be executed - self.order = order - self.exception_clear() - self.message = None - - def _find_next_ready_node(self): - """Find the next node that is ready to be built""" - - if self.ready: - return - - while self.candidates: - node = self.candidates[-1] - state = node.get_state() - - # Skip this node if it has already been executed: - if state != None and state != SCons.Node.stack: - self.candidates.pop() - continue - - # Mark this node as being on the execution stack: - node.set_state(SCons.Node.stack) - - try: - children = node.children() - except SystemExit: - exc_value = sys.exc_info()[1] - e = SCons.Errors.ExplicitExit(node, exc_value.code) - self.exception_set((SCons.Errors.ExplicitExit, e)) - self.candidates.pop() - self.ready = node - break - except KeyboardInterrupt: - raise - except: - # 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 - # raise the exception when the Task is "executed." - self.exception_set() - self.candidates.pop() - self.ready = node - break - - # Detect dependency cycles: - def in_stack(node): return node.get_state() == SCons.Node.stack - cycle = filter(in_stack, children) - if cycle: - nodes = filter(in_stack, self.candidates) + cycle - nodes.reverse() - desc = "Dependency cycle: " + string.join(map(str, nodes), " -> ") - raise SCons.Errors.UserError, desc - - # Find all of the derived dependencies (that is, - # children who have builders or are side effects): - try: - def derived_nodes(node): return node.is_derived() or node.is_pseudo_derived() - derived = filter(derived_nodes, children) - except KeyboardInterrupt: - raise - except: - # We had a problem just trying to figure out if any of - # the kids are derived (like a child couldn't be linked - # from a repository). Arrange to raise the exception - # when the Task is "executed." - self.exception_set() - self.candidates.pop() - self.ready = node - break - - # If there aren't any children with builders and this - # was a top-level argument, then see if we can find any - # corresponding targets in linked build directories: - if not derived and node in self.targets: - alt, message = node.alter_targets() - if alt: - self.message = message - self.candidates.pop() - self.candidates.extend(alt) - continue - - # Add derived files that have not been built - # to the candidates list: - def unbuilt_nodes(node): return node.get_state() == None - not_built = filter(unbuilt_nodes, derived) - if not_built: - # We're waiting on one more derived files that have not - # yet been built. Add this node to the waiting_parents - # list of each of those derived files. - def add_to_waiting_parents(child, parent=node): - child.add_to_waiting_parents(parent) - map(add_to_waiting_parents, not_built) - not_built.reverse() - self.candidates.extend(self.order(not_built)) - continue - - # Skip this node if it has side-effects that are - # currently being built: - cont = 0 - for side_effect in node.side_effects: - if side_effect.get_state() == SCons.Node.executing: - self.pending.append(node) - node.set_state(SCons.Node.pending) - self.candidates.pop() - cont = 1 - break - if cont: continue - - # Skip this node if it is pending on a currently - # executing node: - if node.depends_on(self.executing) or node.depends_on(self.pending): - self.pending.append(node) - node.set_state(SCons.Node.pending) - self.candidates.pop() - continue - - # The default when we've gotten through all of the checks above: - # this node is ready to be built. - self.candidates.pop() - self.ready = node - break - - def next_task(self): - """Return the next task to be executed.""" - - self._find_next_ready_node() - - node = self.ready - - if node is None: - return None - - try: - tlist = node.builder.targets(node) - except AttributeError: - tlist = [node] - self.executing.extend(tlist) - self.executing.extend(node.side_effects) - - task = self.tasker(self, tlist, node in self.targets, 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 - # whether this node is current). Arrange to raise the - # exception when the Task is "executed." - self.exception_set() - self.ready = None - - return task - - def is_blocked(self): - self._find_next_ready_node() - - return not self.ready and (self.pending or self.executing) - - def stop(self): - """Stop the current build completely.""" - self.candidates = [] - self.ready = None - self.pending = [] - - def failed(self, node): - try: - tlist = node.builder.targets(node) - except AttributeError: - tlist = [node] - for t in tlist: - self.executing.remove(t) - for side_effect in node.side_effects: - self.executing.remove(side_effect) - - def executed(self, node): - try: - tlist = node.builder.targets(node) - except AttributeError: - tlist = [node] - for t in tlist: - self.executing.remove(t) - for side_effect in node.side_effects: - self.executing.remove(side_effect) - - # move the current pending nodes to the candidates list: - # (they may not all be ready to build, but _find_next_ready_node() - # will figure out which ones are really ready) - for node in self.pending: - node.set_state(None) - self.pending.reverse() - self.candidates.extend(self.pending) - self.pending = [] - - def exception_set(self, exception=None): - if exception is None: - exception = sys.exc_info() - self.exception = exception - self.exception_raise = self._exception_raise - - def exception_clear(self): - self.exception = (None, None, None) - self.exception_raise = self._no_exception_to_raise - - def _no_exception_to_raise(self): - pass - - def _exception_raise(self): - """Raise a pending exception that was recorded while - getting a Task ready for execution.""" - exc_type, exc_value = self.exception[:2] - raise exc_type, exc_value diff --git a/scons/scons-local-0.96.1/SCons/Tool/icl.py b/scons/scons-local-0.96.1/SCons/Tool/icl.py deleted file mode 100644 index 873d4d67c..000000000 --- a/scons/scons-local-0.96.1/SCons/Tool/icl.py +++ /dev/null @@ -1,138 +0,0 @@ -"""engine.SCons.Tool.icl - -Tool-specific initialization for the Intel C/C++ 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 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__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/icl.py 0.96.1.D001 2004/08/23 09:55:29 knight" - -import os.path - -import SCons.Tool.msvc -import SCons.Util -import SCons.Warnings - -# Find Intel compiler: -# Could enumerate subkeys here to be more flexible. -def get_intel_compiler_top(version): - """ - Return the main path to the top-level dir of the Intel compiler, - using the given version or latest if 0. - The compiler will be in /Bin/icl.exe, - the include dir is /Include, etc. - """ - - if version == 0: - version = "7.0" # XXX: should scan for latest - - if not SCons.Util.can_read_reg: - raise SCons.Errors.InternalError, "No Windows registry module was found" - - K = ('Software\\Intel\\' + - 'Intel(R) C/C++ Compiler for 32-bit apps, Version ' + version) - # Note: v5 had slightly different key: - # HKCU\Software\Intel\Intel C/C++ Compiler for 32-bit apps, Version 5.0 - # Note no (R). - try: - k = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_CURRENT_USER, K) - except SCons.Util.RegError: - return None - - try: - # On my machine, this returns: - # c:\Program Files\Intel\Compiler70 - top = SCons.Util.RegQueryValueEx(k, "Directory")[0] - except SCons.Util.RegError: - raise SCons.Errors.InternalError, "%s was not found in the registry."%K - - if os.path.exists(os.path.join(top, "ia32")): - top = os.path.join(top, "ia32") - - if not os.path.exists(os.path.join(top, "Bin", "icl.exe")): - raise SCons.Errors.InternalError, "Can't find Intel compiler in %s"%top - - return top - - -def generate(env): - """Add Builders and construction variables for icl to an Environment.""" - SCons.Tool.msvc.generate(env) - - try: - icltop = get_intel_compiler_top(0) - except (SCons.Util.RegError, SCons.Errors.InternalError): - icltop = None - - if icltop: - env.PrependENVPath('INCLUDE', os.path.join(icltop, 'Include')) - env.PrependENVPath('LIB', os.path.join(icltop, 'Lib')) - env.PrependENVPath('PATH', os.path.join(icltop, 'Bin')) - - env['CC'] = 'icl' - env['CXX'] = 'icl' - env['LINK'] = 'xilink' - - # Look for license file dir. - envlicdir = os.environ.get("INTEL_LICENSE_FILE", '') - K = ('SOFTWARE\Intel\Licenses') - try: - k = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE, K) - reglicdir = SCons.Util.RegQueryValueEx(k, "w_cpp")[0] - except (AttributeError, SCons.Util.RegError): - reglicdir = "" - defaultlicdir = r'C:\Program Files\Common Files\Intel\Licenses' - - licdir = None - for ld in [envlicdir, reglicdir]: - if ld and os.path.exists(ld): - licdir = ld - break - if not licdir: - licdir = defaultlicdir - if not os.path.exists(licdir): - class ICLLicenseDirWarning(SCons.Warnings.Warning): - pass - SCons.Warnings.enableWarningClass(ICLLicenseDirWarning) - SCons.Warnings.warn(ICLLicenseDirWarning, - "Intel license dir was not found." - " Tried using the INTEL_LICENSE_FILE environment variable (%s), the registry (%s) and the default path (%s)." - " Using the default path as a last resort." - % (envlicdir, reglicdir, defaultlicdir)) - env['ENV']['INTEL_LICENSE_FILE'] = licdir - -def exists(env): - try: - top = get_intel_compiler_top(0) - except (SCons.Util.RegError, SCons.Errors.InternalError): - top = None - - if not top: - return env.Detect('icl') - return top is not None diff --git a/scons/scons-local-0.96.1/SCons/Tool/msvs.py b/scons/scons-local-0.96.1/SCons/Tool/msvs.py deleted file mode 100644 index 33e288ce7..000000000 --- a/scons/scons-local-0.96.1/SCons/Tool/msvs.py +++ /dev/null @@ -1,1128 +0,0 @@ -"""SCons.Tool.msvs - -Tool-specific initialization for Microsoft Visual Studio project files. - -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 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__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/msvs.py 0.96.1.D001 2004/08/23 09:55:29 knight" - -import base64 -import md5 -import os.path -import pickle -import re -import string -import sys -import types - -import SCons.Builder -import SCons.Node.FS -import SCons.Platform.win32 -import SCons.Script.SConscript -import SCons.Util -import SCons.Warnings - -############################################################################## -# Below here are the classes and functions for generation of -# DSP/DSW/SLN/VCPROJ files. -############################################################################## - -def _hexdigest(s): - """Return a string as a string of hex characters. - """ - # NOTE: This routine is a method in the Python 2.0 interface - # of the native md5 module, but we want SCons to operate all - # the way back to at least Python 1.5.2, which doesn't have it. - h = string.hexdigits - r = '' - for c in s: - i = ord(c) - r = r + h[(i >> 4) & 0xF] + h[i & 0xF] - return r - -def _generateGUID(slnfile, name): - """This generates a dummy GUID for the sln file to use. It is - 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() - # 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 - -# This is how we re-invoke SCons from inside MSVS Project files. -# The problem is that we might have been invoked as either scons.bat -# or scons.py. If we were invoked directly as scons.py, then we could -# use sys.argv[0] to find the SCons "executable," but that doesn't work -# if we were invoked as scons.bat, which uses "python -c" to execute -# things and ends up with "-c" as sys.argv[0]. Consequently, we have -# the MSVS Project file invoke SCons the same way that scons.bat does, -# which works regardless of how we were invoked. -exec_script_main = "from os.path import join; import sys; sys.path = [ join(sys.prefix, 'Lib', 'site-packages', 'scons-0.96.1'), join(sys.prefix, 'scons-0.96.1'), join(sys.prefix, 'Lib', 'site-packages', 'scons'), join(sys.prefix, 'scons') ] + sys.path; import SCons.Script; SCons.Script.main()" -exec_script_main_xml = string.replace(exec_script_main, "'", "'") - -# The string for the Python executable we tell the Project file to use -# is either sys.executable or, if an external PYTHON_ROOT environment -# variable exists, $(PYTHON)ROOT\\python.exe (generalized a little to -# pluck the actual executable name from sys.executable). -try: - python_root = os.environ['PYTHON_ROOT'] -except KeyError: - python_executable = sys.executable -else: - python_executable = os.path.join('$(PYTHON_ROOT)', - os.path.split(sys.executable)[1]) - -class Config: - pass - -class _DSPGenerator: - """ Base class for DSP generators """ - def __init__(self, dspfile, source, env): - if type(dspfile) == types.StringType: - self.dspfile = os.path.abspath(dspfile) - else: - self.dspfile = dspfile.get_abspath() - - try: - self.conspath = source[0].attributes.sconstruct.get_abspath() - except KeyError: - raise SCons.Errors.InternalError, \ - "Unable to determine where the SConstruct is" - - self.config = Config() - if env.has_key('variant'): - self.config.variant = env['variant'].capitalize() - else: - raise SCons.Errors.InternalError, \ - "You must specify a 'variant' argument (i.e. 'Debug' or " +\ - "'Release') to create an MSVSProject." - - if env.has_key('buildtarget'): - if type(env['buildtarget']) == types.StringType: - self.config.buildtarget = os.path.abspath(env['buildtarget']) - elif type(env['buildtarget']) == types.ListType: - self.config.buildtarget = env['buildtarget'][0].get_abspath() - else: - self.config.buildtarget = env['buildtarget'].get_abspath() - else: - raise SCons.Errors.InternalError, \ - "You must specify a target 'buildtarget' file argument (such as the target" +\ - " executable) to create an MSVSProject." - - self.config.outdir = os.path.dirname(self.config.buildtarget) - - if type(source[0]) == types.StringType: - self.source = os.path.abspath(source[0]) - else: - self.source = source[0].get_abspath() - - self.env = env - - if self.env.has_key('name'): - self.name = self.env['name'] - else: - self.name = os.path.basename(SCons.Util.splitext(self.dspfile)[0]) - - print "Adding '" + self.name + ' - ' + self.config.variant + "' to Visual Studio Project '" + str(dspfile) + "'" - - sourcenames = [ - ' Source Files', - 'Header Files', - 'Local Headers', - 'Resource Files', - 'Other Files'] - - srcargs = [ - 'srcs', - 'incs', - 'localincs', - 'resources', - 'misc'] - - self.sources = {} - for n in sourcenames: - self.sources[n] = [] - - self.configs = {} - - if os.path.exists(self.dspfile): - self.Parse() - - for t in zip(sourcenames,srcargs): - if self.env.has_key(t[1]): - if type(self.env[t[1]]) == types.ListType: - for i in self.env[t[1]]: - if not i in self.sources[t[0]]: - self.sources[t[0]].append(i) - else: - if not self.env[t[1]] in self.sources[t[0]]: - self.sources[t[0]].append(self.env[t[1]]) - - for n in sourcenames: - self.sources[n].sort() - - self.configs[self.config.variant] = self.config - - def Build(self): - pass - -class _GenerateV6DSP(_DSPGenerator): - """Generates a Project file for MSVS 6.0""" - - def PrintHeader(self): - name = self.name - # pick a default config - confkeys = self.configs.keys() - confkeys.sort() - - self.file.write('# Microsoft Developer Studio Project File - Name="%s" - Package Owner=<4>\n' - '# Microsoft Developer Studio Generated Build File, Format Version 6.00\n' - '# ** DO NOT EDIT **\n\n' - '# TARGTYPE "Win32 (x86) External Target" 0x0106\n\n' - 'CFG=%s - Win32 %s\n' - '!MESSAGE This is not a valid makefile. To build this project using NMAKE,\n' - '!MESSAGE use the Export Makefile command and run\n' - '!MESSAGE \n' - '!MESSAGE NMAKE /f "%s.mak".\n' - '!MESSAGE \n' - '!MESSAGE You can specify a configuration when running NMAKE\n' - '!MESSAGE by defining the macro CFG on the command line. For example:\n' - '!MESSAGE \n' - '!MESSAGE NMAKE /f "%s.mak" CFG="%s - Win32 %s"\n' - '!MESSAGE \n' - '!MESSAGE Possible choices for configuration are:\n' - '!MESSAGE \n' % (name,name,confkeys[0],name,name,name,confkeys[0])) - - for kind in confkeys: - self.file.write('!MESSAGE "%s - Win32 %s" (based on "Win32 (x86) External Target")\n' % (name, kind)) - - self.file.write('!MESSAGE \n\n') - - def PrintProject(self): - name = self.name - self.file.write('# Begin Project\n' - '# PROP AllowPerConfigDependencies 0\n' - '# PROP Scc_ProjName ""\n' - '# PROP Scc_LocalPath ""\n\n') - - first = 1 - confkeys = self.configs.keys() - confkeys.sort() - for kind in confkeys: - outdir = self.configs[kind].outdir - buildtarget = self.configs[kind].buildtarget - if first == 1: - self.file.write('!IF "$(CFG)" == "%s - Win32 %s"\n\n' % (name, kind)) - first = 0 - else: - self.file.write('\n!ELSEIF "$(CFG)" == "%s - Win32 %s"\n\n' % (name, kind)) - - # have to write this twice, once with the BASE settings, and once without - for base in ("BASE ",""): - self.file.write('# PROP %sUse_MFC 0\n' - '# PROP %sUse_Debug_Libraries ' % (base, base)) - if kind.lower().find('debug') < 0: - self.file.write('0\n') - else: - self.file.write('1\n') - self.file.write('# PROP %sOutput_Dir "%s"\n' - '# PROP %sIntermediate_Dir "%s"\n' % (base,outdir,base,outdir)) - (d,c) = os.path.split(str(self.conspath)) - cmd = '"%s" -c "%s" -C %s -f %s %s' % (python_executable, - exec_script_main, - d, c, buildtarget) - self.file.write('# PROP %sCmd_Line "%s"\n' - '# PROP %sRebuild_Opt "-c && %s"\n' - '# PROP %sTarget_File "%s"\n' - '# PROP %sBsc_Name ""\n' - '# PROP %sTarget_Dir ""\n'\ - %(base,cmd,base,cmd,base,buildtarget,base,base)) - - self.file.write('\n!ENDIF\n\n' - '# Begin Target\n\n') - for kind in confkeys: - self.file.write('# Name "%s - Win32 %s"\n' % (name,kind)) - self.file.write('\n') - first = 0 - for kind in confkeys: - if first == 0: - self.file.write('!IF "$(CFG)" == "%s - Win32 %s"\n\n' % (name,kind)) - first = 1 - else: - self.file.write('!ELSEIF "$(CFG)" == "%s - Win32 %s"\n\n' % (name,kind)) - self.file.write('!ENDIF \n\n') - self.PrintSourceFiles() - self.file.write('# End Target\n' - '# End Project\n') - - # now we pickle some data and add it to the file -- MSDEV will ignore it. - pdata = pickle.dumps(self.configs,1) - pdata = base64.encodestring(pdata) - self.file.write(pdata + '\n') - pdata = pickle.dumps(self.sources,1) - pdata = base64.encodestring(pdata) - self.file.write(pdata + '\n') - - def PrintSourceFiles(self): - categories = {' Source Files': 'cpp|c|cxx|l|y|def|odl|idl|hpj|bat', - 'Header Files': 'h|hpp|hxx|hm|inl', - 'Local Headers': 'h|hpp|hxx|hm|inl', - 'Resource Files': 'r|rc|ico|cur|bmp|dlg|rc2|rct|bin|cnt|rtf|gif|jpg|jpeg|jpe', - 'Other Files': ''} - - cats = categories.keys() - cats.sort() - 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('|',';') - self.file.write('# PROP Default_Filter "' + typelist + '"\n') - - for file in self.sources[kind]: - file = os.path.normpath(file) - self.file.write('# Begin Source File\n\n' - 'SOURCE="' + file + '"\n' - '# End Source File\n') - self.file.write('# End Group\n') - - # add the Conscript file outside of the groups - self.file.write('# Begin Source File\n\n' - 'SOURCE="' + str(self.source) + '"\n' - '# End Source File\n') - - def Parse(self): - try: - dspfile = open(self.dspfile,'r') - except IOError: - return # doesn't exist yet, so can't add anything to configs. - - line = dspfile.readline() - while line: - if line.find("# End Project") > -1: - break - line = dspfile.readline() - - line = dspfile.readline() - datas = line - while line and line != '\n': - line = dspfile.readline() - datas = datas + line - - # OK, we've found our little pickled cache of data. - try: - datas = base64.decodestring(datas) - data = pickle.loads(datas) - except KeyboardInterrupt: - raise - except: - return # unable to unpickle any data for some reason - - self.configs.update(data) - - data = None - line = dspfile.readline() - datas = line - while line and line != '\n': - line = dspfile.readline() - datas = datas + line - - # OK, we've found our little pickled cache of data. - # it has a "# " in front of it, so we strip that. - try: - datas = base64.decodestring(datas) - data = pickle.loads(datas) - except KeyboardInterrupt: - raise - except: - return # unable to unpickle any data for some reason - - self.sources.update(data) - - def Build(self): - try: - self.file = open(self.dspfile,'w') - except IOError, detail: - raise SCons.Errors.InternalError, 'Unable to open "' + self.dspfile + '" for writing:' + str(detail) - else: - self.PrintHeader() - self.PrintProject() - self.file.close() - -class _GenerateV7DSP(_DSPGenerator): - """Generates a Project file for MSVS .NET""" - - def __init__(self, dspfile, source, env): - _DSPGenerator.__init__(self, dspfile, source, env) - self.version = float(env['MSVS_VERSION']) - self.versionstr = '7.00' - if self.version >= 7.1: - self.versionstr = '7.10' - - def PrintHeader(self): - self.file.write('\n' - '\n' - ' \n' - ' \n' - ' \n' % (self.versionstr, self.name)) - - def PrintProject(self): - - - self.file.write(' \n') - - confkeys = self.configs.keys() - confkeys.sort() - for kind in confkeys: - outdir = self.configs[kind].outdir - buildtarget = self.configs[kind].buildtarget - - (d,c) = os.path.split(str(self.conspath)) - cmd = '"%s" -c "%s" -C %s -f %s %s' % (python_executable, - exec_script_main_xml, - d, c, buildtarget) - - cleancmd = '"%s" -c "%s" -C %s -f %s -c %s' % (python_executable, - exec_script_main_xml, - d, c, buildtarget) - - self.file.write(' \n' - ' \n' - ' \n' % (kind.capitalize(),outdir,outdir,\ - cmd,cleancmd,cmd,buildtarget)) - - self.file.write(' \n') - if self.version >= 7.1: - self.file.write(' \n') - self.file.write(' \n') - - self.PrintSourceFiles() - - self.file.write('\n') - - # now we pickle some data and add it to the file -- MSDEV will ignore it. - pdata = pickle.dumps(self.configs,1) - pdata = base64.encodestring(pdata) - self.file.write('\n') - - def PrintSourceFiles(self): - categories = {' Source Files': 'cpp;c;cxx;l;y;def;odl;idl;hpj;bat', - 'Header Files': 'h;hpp;hxx;hm;inl', - 'Local Headers': 'h;hpp;hxx;hm;inl', - 'Resource Files': 'r;rc;ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe', - 'Other Files': ''} - - self.file.write(' \n') - - cats = categories.keys() - cats.sort() - for kind in cats: - if not self.sources[kind]: - continue # skip empty groups - - self.file.write(' \n' % (kind, categories[kind])) - - for file in self.sources[kind]: - file = os.path.normpath(file) - self.file.write(' \n' - ' \n' % file) - - self.file.write(' \n') - - # add the Conscript file outside of the groups - self.file.write(' \n' - ' \n' - ' \n' - ' \n' - ' \n' % str(self.source)) - - def Parse(self): - try: - dspfile = open(self.dspfile,'r') - except IOError: - return # doesn't exist yet, so can't add anything to configs. - - line = dspfile.readline() - while line: - if line.find('\n') + + def printSources(self, hierarchy, commonprefix): + sorteditems = hierarchy.items() + sorteditems.sort(lambda a, b: cmp(a[0].lower(), b[0].lower())) + + # First folders, then files + for key, value in sorteditems: + if SCons.Util.is_Dict(value): + self.file.write('\t\t\t\n' % (key)) + self.printSources(value, commonprefix) + self.file.write('\t\t\t\n') + + for key, value in sorteditems: + if SCons.Util.is_String(value): + file = value + if commonprefix: + file = os.path.join(commonprefix, value) + file = os.path.normpath(file) + self.file.write('\t\t\t\n' + '\t\t\t\n' % (file)) + + def PrintSourceFiles(self): + categories = {'Source Files': 'cpp;c;cxx;l;y;def;odl;idl;hpj;bat', + 'Header Files': 'h;hpp;hxx;hm;inl', + 'Local Headers': 'h;hpp;hxx;hm;inl', + 'Resource Files': 'r;rc;ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe', + 'Other Files': ''} + + self.file.write('\t\n') + + cats = categories.keys() + cats.sort(lambda a, b: cmp(a.lower(), b.lower())) + cats = filter(lambda k, s=self: s.sources[k], cats) + for kind in cats: + if len(cats) > 1: + self.file.write('\t\t\n' % (kind, categories[kind])) + + sources = self.sources[kind] + + # First remove any common prefix + commonprefix = None + if len(sources) > 1: + s = map(os.path.normpath, sources) + # take the dirname because the prefix may include parts + # of the filenames (e.g. if you have 'dir\abcd' and + # 'dir\acde' then the cp will be 'dir\a' ) + cp = os.path.dirname( os.path.commonprefix(s) ) + if cp and s[0][len(cp)] == os.sep: + # +1 because the filename starts after the separator + sources = map(lambda s, l=len(cp)+1: s[l:], sources) + commonprefix = cp + elif len(sources) == 1: + commonprefix = os.path.dirname( sources[0] ) + sources[0] = os.path.basename( sources[0] ) + + hierarchy = makeHierarchy(sources) + self.printSources(hierarchy, commonprefix=commonprefix) + + if len(cats)>1: + self.file.write('\t\t\n') + + # add the SConscript file outside of the groups + self.file.write('\t\t\n' + '\t\t\n' % str(self.sconscript)) + + self.file.write('\t\n' + '\t\n' + '\t\n') + + def Parse(self): + try: + dspfile = open(self.dspabs,'r') + except IOError: + return # doesn't exist yet, so can't add anything to configs. + + line = dspfile.readline() + while line: + if line.find(' p2cread + # c2pread <--stdout--- c2pwrite + # errread <--stderr--- errwrite + # + # On POSIX, the child objects are file descriptors. On + # Windows, these are Windows file handles. The parent objects + # are file descriptors on both platforms. The parent objects + # are None when not using PIPEs. The child objects are None + # when not redirecting. + + (p2cread, p2cwrite, + c2pread, c2pwrite, + errread, errwrite) = self._get_handles(stdin, stdout, stderr) + + self._execute_child(args, executable, preexec_fn, close_fds, + cwd, env, universal_newlines, + startupinfo, creationflags, shell, + p2cread, p2cwrite, + c2pread, c2pwrite, + errread, errwrite) + + if p2cwrite: + self.stdin = os.fdopen(p2cwrite, 'wb', bufsize) + if c2pread: + if universal_newlines: + self.stdout = os.fdopen(c2pread, 'rU', bufsize) + else: + self.stdout = os.fdopen(c2pread, 'rb', bufsize) + if errread: + if universal_newlines: + self.stderr = os.fdopen(errread, 'rU', bufsize) + else: + self.stderr = os.fdopen(errread, 'rb', bufsize) + + + def _translate_newlines(self, data): + data = data.replace("\r\n", "\n") + data = data.replace("\r", "\n") + return data + + + def __del__(self): + if not self._child_created: + # We didn't get to successfully create a child process. + return + # In case the child hasn't been waited on, check if it's done. + self.poll(_deadstate=sys.maxint) + if self.returncode is None and _active is not None: + # Child is still running, keep us alive until we can wait on it. + _active.append(self) + + + def communicate(self, input=None): + """Interact with process: Send data to stdin. Read data from + stdout and stderr, until end-of-file is reached. Wait for + process to terminate. The optional input argument should be a + string to be sent to the child process, or None, if no data + should be sent to the child. + + communicate() returns a tuple (stdout, stderr).""" + + # Optimization: If we are only using one pipe, or no pipe at + # all, using select() or threads is unnecessary. + if [self.stdin, self.stdout, self.stderr].count(None) >= 2: + stdout = None + stderr = None + if self.stdin: + if input: + self.stdin.write(input) + self.stdin.close() + elif self.stdout: + stdout = self.stdout.read() + elif self.stderr: + stderr = self.stderr.read() + self.wait() + return (stdout, stderr) + + return self._communicate(input) + + + if mswindows: + # + # Windows methods + # + def _get_handles(self, stdin, stdout, stderr): + """Construct and return tupel with IO objects: + p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite + """ + if stdin is None and stdout is None and stderr is None: + return (None, None, None, None, None, None) + + p2cread, p2cwrite = None, None + c2pread, c2pwrite = None, None + errread, errwrite = None, None + + if stdin is None: + p2cread = GetStdHandle(STD_INPUT_HANDLE) + elif stdin == PIPE: + p2cread, p2cwrite = CreatePipe(None, 0) + # Detach and turn into fd + p2cwrite = p2cwrite.Detach() + p2cwrite = msvcrt.open_osfhandle(p2cwrite, 0) + elif is_int(stdin): + p2cread = msvcrt.get_osfhandle(stdin) + else: + # Assuming file-like object + p2cread = msvcrt.get_osfhandle(stdin.fileno()) + p2cread = self._make_inheritable(p2cread) + + if stdout is None: + c2pwrite = GetStdHandle(STD_OUTPUT_HANDLE) + elif stdout == PIPE: + c2pread, c2pwrite = CreatePipe(None, 0) + # Detach and turn into fd + c2pread = c2pread.Detach() + c2pread = msvcrt.open_osfhandle(c2pread, 0) + elif is_int(stdout): + c2pwrite = msvcrt.get_osfhandle(stdout) + else: + # Assuming file-like object + c2pwrite = msvcrt.get_osfhandle(stdout.fileno()) + c2pwrite = self._make_inheritable(c2pwrite) + + if stderr is None: + errwrite = GetStdHandle(STD_ERROR_HANDLE) + elif stderr == PIPE: + errread, errwrite = CreatePipe(None, 0) + # Detach and turn into fd + errread = errread.Detach() + errread = msvcrt.open_osfhandle(errread, 0) + elif stderr == STDOUT: + errwrite = c2pwrite + elif is_int(stderr): + errwrite = msvcrt.get_osfhandle(stderr) + else: + # Assuming file-like object + errwrite = msvcrt.get_osfhandle(stderr.fileno()) + errwrite = self._make_inheritable(errwrite) + + return (p2cread, p2cwrite, + c2pread, c2pwrite, + errread, errwrite) + + + def _make_inheritable(self, handle): + """Return a duplicate of handle, which is inheritable""" + return DuplicateHandle(GetCurrentProcess(), handle, + GetCurrentProcess(), 0, 1, + DUPLICATE_SAME_ACCESS) + + + def _find_w9xpopen(self): + """Find and return absolut path to w9xpopen.exe""" + w9xpopen = os.path.join(os.path.dirname(GetModuleFileName(0)), + "w9xpopen.exe") + if not os.path.exists(w9xpopen): + # Eeek - file-not-found - possibly an embedding + # situation - see if we can locate it in sys.exec_prefix + w9xpopen = os.path.join(os.path.dirname(sys.exec_prefix), + "w9xpopen.exe") + if not os.path.exists(w9xpopen): + raise RuntimeError("Cannot locate w9xpopen.exe, which is " + "needed for Popen to work with your " + "shell or platform.") + return w9xpopen + + + def _execute_child(self, args, executable, preexec_fn, close_fds, + cwd, env, universal_newlines, + startupinfo, creationflags, shell, + p2cread, p2cwrite, + c2pread, c2pwrite, + errread, errwrite): + """Execute program (MS Windows version)""" + + if not isinstance(args, types.StringTypes): + args = list2cmdline(args) + + # Process startup details + if startupinfo is None: + startupinfo = STARTUPINFO() + if None not in (p2cread, c2pwrite, errwrite): + startupinfo.dwFlags = startupinfo.dwFlags | STARTF_USESTDHANDLES + startupinfo.hStdInput = p2cread + startupinfo.hStdOutput = c2pwrite + startupinfo.hStdError = errwrite + + if shell: + startupinfo.dwFlags = startupinfo.dwFlags | STARTF_USESHOWWINDOW + startupinfo.wShowWindow = SW_HIDE + comspec = os.environ.get("COMSPEC", "cmd.exe") + args = comspec + " /c " + args + if (GetVersion() >= 0x80000000L or + os.path.basename(comspec).lower() == "command.com"): + # Win9x, or using command.com on NT. We need to + # use the w9xpopen intermediate program. For more + # information, see KB Q150956 + # (http://web.archive.org/web/20011105084002/http://support.microsoft.com/support/kb/articles/Q150/9/56.asp) + w9xpopen = self._find_w9xpopen() + args = '"%s" %s' % (w9xpopen, args) + # Not passing CREATE_NEW_CONSOLE has been known to + # cause random failures on win9x. Specifically a + # dialog: "Your program accessed mem currently in + # use at xxx" and a hopeful warning about the + # stability of your system. Cost is Ctrl+C wont + # kill children. + creationflags = creationflags | CREATE_NEW_CONSOLE + + # Start the process + try: + hp, ht, pid, tid = CreateProcess(executable, args, + # no special security + None, None, + # must inherit handles to pass std + # handles + 1, + creationflags, + env, + cwd, + startupinfo) + except pywintypes.error, e: + # Translate pywintypes.error to WindowsError, which is + # a subclass of OSError. FIXME: We should really + # translate errno using _sys_errlist (or simliar), but + # how can this be done from Python? + raise apply(WindowsError, e.args) + + # Retain the process handle, but close the thread handle + self._child_created = True + self._handle = hp + self.pid = pid + ht.Close() + + # Child is launched. Close the parent's copy of those pipe + # handles that only the child should have open. You need + # to make sure that no handles to the write end of the + # output pipe are maintained in this process or else the + # pipe will not close when the child process exits and the + # ReadFile will hang. + if p2cread is not None: + p2cread.Close() + if c2pwrite is not None: + c2pwrite.Close() + if errwrite is not None: + errwrite.Close() + + + def poll(self, _deadstate=None): + """Check if child process has terminated. Returns returncode + attribute.""" + if self.returncode is None: + if WaitForSingleObject(self._handle, 0) == WAIT_OBJECT_0: + self.returncode = GetExitCodeProcess(self._handle) + return self.returncode + + + def wait(self): + """Wait for child process to terminate. Returns returncode + attribute.""" + if self.returncode is None: + obj = WaitForSingleObject(self._handle, INFINITE) + self.returncode = GetExitCodeProcess(self._handle) + return self.returncode + + + def _readerthread(self, fh, buffer): + buffer.append(fh.read()) + + + def _communicate(self, input): + stdout = None # Return + stderr = None # Return + + if self.stdout: + stdout = [] + stdout_thread = threading.Thread(target=self._readerthread, + args=(self.stdout, stdout)) + stdout_thread.setDaemon(True) + stdout_thread.start() + if self.stderr: + stderr = [] + stderr_thread = threading.Thread(target=self._readerthread, + args=(self.stderr, stderr)) + stderr_thread.setDaemon(True) + stderr_thread.start() + + if self.stdin: + if input is not None: + self.stdin.write(input) + self.stdin.close() + + if self.stdout: + stdout_thread.join() + if self.stderr: + stderr_thread.join() + + # All data exchanged. Translate lists into strings. + if stdout is not None: + stdout = stdout[0] + if stderr is not None: + stderr = stderr[0] + + # Translate newlines, if requested. We cannot let the file + # object do the translation: It is based on stdio, which is + # impossible to combine with select (unless forcing no + # buffering). + if self.universal_newlines and hasattr(file, 'newlines'): + if stdout: + stdout = self._translate_newlines(stdout) + if stderr: + stderr = self._translate_newlines(stderr) + + self.wait() + return (stdout, stderr) + + else: + # + # POSIX methods + # + def _get_handles(self, stdin, stdout, stderr): + """Construct and return tupel with IO objects: + p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite + """ + p2cread, p2cwrite = None, None + c2pread, c2pwrite = None, None + errread, errwrite = None, None + + if stdin is None: + pass + elif stdin == PIPE: + p2cread, p2cwrite = os.pipe() + elif is_int(stdin): + p2cread = stdin + else: + # Assuming file-like object + p2cread = stdin.fileno() + + if stdout is None: + pass + elif stdout == PIPE: + c2pread, c2pwrite = os.pipe() + elif is_int(stdout): + c2pwrite = stdout + else: + # Assuming file-like object + c2pwrite = stdout.fileno() + + if stderr is None: + pass + elif stderr == PIPE: + errread, errwrite = os.pipe() + elif stderr == STDOUT: + errwrite = c2pwrite + elif is_int(stderr): + errwrite = stderr + else: + # Assuming file-like object + errwrite = stderr.fileno() + + return (p2cread, p2cwrite, + c2pread, c2pwrite, + errread, errwrite) + + + def _set_cloexec_flag(self, fd): + try: + cloexec_flag = fcntl.FD_CLOEXEC + except AttributeError: + cloexec_flag = 1 + + old = fcntl.fcntl(fd, fcntl.F_GETFD) + fcntl.fcntl(fd, fcntl.F_SETFD, old | cloexec_flag) + + + def _close_fds(self, but): + for i in xrange(3, MAXFD): + if i == but: + continue + try: + os.close(i) + except KeyboardInterrupt: + raise # SCons: don't swallow keyboard interrupts + except: + pass + + + def _execute_child(self, args, executable, preexec_fn, close_fds, + cwd, env, universal_newlines, + startupinfo, creationflags, shell, + p2cread, p2cwrite, + c2pread, c2pwrite, + errread, errwrite): + """Execute program (POSIX version)""" + + if is_string(args): + args = [args] + + if shell: + args = ["/bin/sh", "-c"] + args + + if executable is None: + executable = args[0] + + # For transferring possible exec failure from child to parent + # The first char specifies the exception type: 0 means + # OSError, 1 means some other error. + errpipe_read, errpipe_write = os.pipe() + self._set_cloexec_flag(errpipe_write) + + self.pid = os.fork() + self._child_created = True + if self.pid == 0: + # Child + try: + # Close parent's pipe ends + if p2cwrite: + os.close(p2cwrite) + if c2pread: + os.close(c2pread) + if errread: + os.close(errread) + os.close(errpipe_read) + + # Dup fds for child + if p2cread: + os.dup2(p2cread, 0) + if c2pwrite: + os.dup2(c2pwrite, 1) + if errwrite: + os.dup2(errwrite, 2) + + # Close pipe fds. Make sure we don't close the same + # fd more than once, or standard fds. + try: + set + except NameError: + # Fall-back for earlier Python versions, so epydoc + # can use this module directly to execute things. + if p2cread: + os.close(p2cread) + if c2pwrite and c2pwrite not in (p2cread,): + os.close(c2pwrite) + if errwrite and errwrite not in (p2cread, c2pwrite): + os.close(errwrite) + else: + for fd in set((p2cread, c2pwrite, errwrite))-set((0,1,2)): + if fd: os.close(fd) + + # Close all other fds, if asked for + if close_fds: + self._close_fds(but=errpipe_write) + + if cwd is not None: + os.chdir(cwd) + + if preexec_fn: + apply(preexec_fn) + + if env is None: + os.execvp(executable, args) + else: + os.execvpe(executable, args, env) + + except KeyboardInterrupt: + raise # SCons: don't swallow keyboard interrupts + + except: + exc_type, exc_value, tb = sys.exc_info() + # Save the traceback and attach it to the exception object + exc_lines = traceback.format_exception(exc_type, + exc_value, + tb) + exc_value.child_traceback = string.join(exc_lines, '') + os.write(errpipe_write, pickle.dumps(exc_value)) + + # This exitcode won't be reported to applications, so it + # really doesn't matter what we return. + os._exit(255) + + # Parent + os.close(errpipe_write) + if p2cread and p2cwrite: + os.close(p2cread) + if c2pwrite and c2pread: + os.close(c2pwrite) + if errwrite and errread: + os.close(errwrite) + + # Wait for exec to fail or succeed; possibly raising exception + data = os.read(errpipe_read, 1048576) # Exceptions limited to 1 MB + os.close(errpipe_read) + if data != "": + os.waitpid(self.pid, 0) + child_exception = pickle.loads(data) + raise child_exception + + + def _handle_exitstatus(self, sts): + if os.WIFSIGNALED(sts): + self.returncode = -os.WTERMSIG(sts) + elif os.WIFEXITED(sts): + self.returncode = os.WEXITSTATUS(sts) + else: + # Should never happen + raise RuntimeError("Unknown child exit status!") + + + def poll(self, _deadstate=None): + """Check if child process has terminated. Returns returncode + attribute.""" + if self.returncode is None: + try: + pid, sts = os.waitpid(self.pid, os.WNOHANG) + if pid == self.pid: + self._handle_exitstatus(sts) + except os.error: + if _deadstate is not None: + self.returncode = _deadstate + return self.returncode + + + def wait(self): + """Wait for child process to terminate. Returns returncode + attribute.""" + if self.returncode is None: + pid, sts = os.waitpid(self.pid, 0) + self._handle_exitstatus(sts) + return self.returncode + + + def _communicate(self, input): + read_set = [] + write_set = [] + stdout = None # Return + stderr = None # Return + + if self.stdin: + # Flush stdio buffer. This might block, if the user has + # been writing to .stdin in an uncontrolled fashion. + self.stdin.flush() + if input: + write_set.append(self.stdin) + else: + self.stdin.close() + if self.stdout: + read_set.append(self.stdout) + stdout = [] + if self.stderr: + read_set.append(self.stderr) + stderr = [] + + input_offset = 0 + while read_set or write_set: + rlist, wlist, xlist = select.select(read_set, write_set, []) + + if self.stdin in wlist: + # When select has indicated that the file is writable, + # we can write up to PIPE_BUF bytes without risk + # blocking. POSIX defines PIPE_BUF >= 512 + bytes_written = os.write(self.stdin.fileno(), buffer(input, input_offset, 512)) + input_offset = input_offset + bytes_written + if input_offset >= len(input): + self.stdin.close() + write_set.remove(self.stdin) + + if self.stdout in rlist: + data = os.read(self.stdout.fileno(), 1024) + if data == "": + self.stdout.close() + read_set.remove(self.stdout) + stdout.append(data) + + if self.stderr in rlist: + data = os.read(self.stderr.fileno(), 1024) + if data == "": + self.stderr.close() + read_set.remove(self.stderr) + stderr.append(data) + + # All data exchanged. Translate lists into strings. + if stdout is not None: + stdout = string.join(stdout, '') + if stderr is not None: + stderr = string.join(stderr, '') + + # Translate newlines, if requested. We cannot let the file + # object do the translation: It is based on stdio, which is + # impossible to combine with select (unless forcing no + # buffering). + if self.universal_newlines and hasattr(file, 'newlines'): + if stdout: + stdout = self._translate_newlines(stdout) + if stderr: + stderr = self._translate_newlines(stderr) + + self.wait() + return (stdout, stderr) + + +def _demo_posix(): + # + # Example 1: Simple redirection: Get process list + # + plist = Popen(["ps"], stdout=PIPE).communicate()[0] + print "Process list:" + print plist + + # + # Example 2: Change uid before executing child + # + if os.getuid() == 0: + p = Popen(["id"], preexec_fn=lambda: os.setuid(100)) + p.wait() + + # + # Example 3: Connecting several subprocesses + # + print "Looking for 'hda'..." + p1 = Popen(["dmesg"], stdout=PIPE) + p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE) + print repr(p2.communicate()[0]) + + # + # Example 4: Catch execution error + # + print + print "Trying a weird file..." + try: + print Popen(["/this/path/does/not/exist"]).communicate() + except OSError, e: + if e.errno == errno.ENOENT: + print "The file didn't exist. I thought so..." + print "Child traceback:" + print e.child_traceback + else: + print "Error", e.errno + else: + sys.stderr.write( "Gosh. No error.\n" ) + + +def _demo_windows(): + # + # Example 1: Connecting several subprocesses + # + print "Looking for 'PROMPT' in set output..." + p1 = Popen("set", stdout=PIPE, shell=True) + p2 = Popen('find "PROMPT"', stdin=p1.stdout, stdout=PIPE) + print repr(p2.communicate()[0]) + + # + # Example 2: Simple execution of program + # + print "Executing calc..." + p = Popen("calc") + p.wait() + + +if __name__ == "__main__": + if mswindows: + _demo_windows() + else: + _demo_posix() diff --git a/scons/scons-local-0.97/SCons/compat/builtins.py b/scons/scons-local-0.97/SCons/compat/builtins.py new file mode 100644 index 000000000..7a0a2a82f --- /dev/null +++ b/scons/scons-local-0.97/SCons/compat/builtins.py @@ -0,0 +1,141 @@ +# +# 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. +# + +# Portions of the following are derived from the compat.py file in +# Twisted, under the following copyright: +# +# Copyright (c) 2001-2004 Twisted Matrix Laboratories + +__doc__ = """ +Compatibility idioms for __builtin__ names + +This module adds names to the __builtin__ module for things that we want +to use in SCons but which don't show up until later Python versions than +the earliest ones we support. + +This module checks for the following __builtin__ names: + + bool() + dict() + True + False + zip() + +Implementations of functions are *NOT* guaranteed to be fully compliant +with these functions in later versions of Python. We are only concerned +with adding functionality that we actually use in SCons, so be wary +if you lift this code for other uses. (That said, making these more +nearly the same as later, official versions is still a desirable goal, +we just don't need to be obsessive about it.) + +If you're looking at this with pydoc and various names don't show up in +the FUNCTIONS or DATA output, that means those names are already built in +to this version of Python and we don't need to add them from this module. +""" + +__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/compat/builtins.py 0.97.D001 2007/05/17 11:35:19 knight" + +import __builtin__ + +try: + bool +except NameError: + # Pre-2.2 Python has no bool() function. + def bool(value): + """Demote a value to 0 or 1, depending on its truth value. + + This is not to be confused with types.BooleanType, which is + way too hard to duplicate in early Python versions to be + worth the trouble. + """ + return not not value + __builtin__.bool = bool + bool = bool + +try: + dict +except NameError: + # Pre-2.2 Python has no dict() keyword. + def dict(*arg, **kwargs): + """ + New dictionary initialization. + """ + d = apply(types.DictType, arg) + d.update(kwargs) + return d + __builtin__.dict = dict + +try: + False +except NameError: + # Pre-2.2 Python has no False keyword. + __builtin__.False = not 1 + # Assign to False in this module namespace so it shows up in pydoc output. + False = False + +try: + True +except NameError: + # Pre-2.2 Python has no True keyword. + __builtin__.True = not 0 + # Assign to True in this module namespace so it shows up in pydoc output. + True = True + +# +try: + zip +except NameError: + # Pre-2.2 Python has no zip() function. + def zip(*lists): + """ + Emulates the behavior we need from the built-in zip() function + added in Python 2.2. + + Returns a list of tuples, where each tuple contains the i-th + element rom each of the argument sequences. The returned + list is truncated in length to the length of the shortest + argument sequence. + """ + result = [] + for i in xrange(min(map(len, lists))): + result.append(tuple(map(lambda l, i=i: l[i], lists))) + return result + __builtin__.zip = zip + + + +#if sys.version_info[:3] in ((2, 2, 0), (2, 2, 1)): +# def lstrip(s, c=string.whitespace): +# while s and s[0] in c: +# s = s[1:] +# return s +# def rstrip(s, c=string.whitespace): +# while s and s[-1] in c: +# s = s[:-1] +# return s +# def strip(s, c=string.whitespace, l=lstrip, r=rstrip): +# return l(r(s, c), c) +# +# object.__setattr__(str, 'lstrip', lstrip) +# object.__setattr__(str, 'rstrip', rstrip) +# object.__setattr__(str, 'strip', strip) diff --git a/scons/scons-local-0.97/SCons/cpp.py b/scons/scons-local-0.97/SCons/cpp.py new file mode 100644 index 000000000..2f0ee4c0b --- /dev/null +++ b/scons/scons-local-0.97/SCons/cpp.py @@ -0,0 +1,548 @@ +# +# 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__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/cpp.py 0.97.D001 2007/05/17 11:35:19 knight" + +__doc__ = """ +SCons C Pre-Processor module +""" + +import SCons.compat + +import os +import re +import string + +# +# First "subsystem" of regular expressions that we set up: +# +# Stuff to turn the C preprocessor directives in a file's contents into +# a list of tuples that we can process easily. +# + +# A table of regular expressions that fetch the arguments from the rest of +# a C preprocessor line. Different directives have different arguments +# that we want to fetch, using the regular expressions to which the lists +# of preprocessor directives map. +cpp_lines_dict = { + # Fetch the rest of a #if/#elif/#ifdef/#ifndef/#import/#include/ + # #include_next line as one argument. + ('if', 'elif', 'ifdef', 'ifndef', 'import', 'include', 'include_next',) + : '\s+(.+)', + + # We don't care what comes after a #else or #endif line. + ('else', 'endif',) : '', + + # Fetch three arguments from a #define line: + # 1) The #defined keyword. + # 2) The optional parentheses and arguments (if it's a function-like + # macro, '' if it's not). + # 3) The expansion value. + ('define',) : '\s+([_A-Za-z][_A-Za-z0-9_]+)(\([^)]*\))?\s*(.*)', + + # Fetch the #undefed keyword from a #undef line. + ('undef',) : '\s+([_A-Za-z][A-Za-z0-9_]+)', +} + +# Create a table that maps each individual C preprocessor directive to +# the corresponding compiled regular expression that fetches the arguments +# we care about. +Table = {} +for op_list, expr in cpp_lines_dict.items(): + e = re.compile(expr) + for op in op_list: + Table[op] = e +del e +del op +del op_list + +# Create a list of the expressions we'll use to match all of the +# preprocessor directives. These are the same as the directives +# themselves *except* that we must use a negative lookahead assertion +# when matching "if" so it doesn't match the "if" in "ifdef." +override = { + 'if' : 'if(?!def)', +} +l = map(lambda x, o=override: o.get(x, x), Table.keys()) + + +# Turn the list of expressions into one big honkin' regular expression +# that will match all the preprocessor lines at once. This will return +# a list of tuples, one for each preprocessor line. The preprocessor +# directive will be the first element in each tuple, and the rest of +# the line will be the second element. +e = '^\s*#\s*(' + string.join(l, '|') + ')(.*)$' + +# And last but not least, compile the expression. +CPP_Expression = re.compile(e, re.M) + + + + +# +# Second "subsystem" of regular expressions that we set up: +# +# Stuff to translate a C preprocessor expression (as found on a #if or +# #elif line) into an equivalent Python expression that we can eval(). +# + +# A dictionary that maps the C representation of Boolean operators +# to their Python equivalents. +CPP_to_Python_Ops_Dict = { + '!' : ' not ', + '!=' : ' != ', + '&&' : ' and ', + '||' : ' or ', + '?' : ' and ', + ':' : ' or ', + '\r' : '', +} + +CPP_to_Python_Ops_Sub = lambda m, d=CPP_to_Python_Ops_Dict: d[m.group(0)] + +# We have to sort the keys by length so that longer expressions +# come *before* shorter expressions--in particular, "!=" must +# come before "!" in the alternation. Without this, the Python +# re module, as late as version 2.2.2, empirically matches the +# "!" in "!=" first, instead of finding the longest match. +# What's up with that? +l = CPP_to_Python_Ops_Dict.keys() +l.sort(lambda a, b: cmp(len(b), len(a))) + +# Turn the list of keys into one regular expression that will allow us +# to substitute all of the operators at once. +expr = string.join(map(re.escape, l), '|') + +# ...and compile the expression. +CPP_to_Python_Ops_Expression = re.compile(expr) + +# A separate list of expressions to be evaluated and substituted +# sequentially, not all at once. +CPP_to_Python_Eval_List = [ + ['defined\s+(\w+)', '__dict__.has_key("\\1")'], + ['defined\s*\((\w+)\)', '__dict__.has_key("\\1")'], + ['/\*.*\*/', ''], + ['/\*.*', ''], + ['//.*', ''], + ['(0x[0-9A-Fa-f]*)[UL]+', '\\1L'], +] + +# Replace the string representations of the regular expressions in the +# list with compiled versions. +for l in CPP_to_Python_Eval_List: + l[0] = re.compile(l[0]) + +# Wrap up all of the above into a handy function. +def CPP_to_Python(s): + """ + Converts a C pre-processor expression into an equivalent + Python expression that can be evaluated. + """ + s = CPP_to_Python_Ops_Expression.sub(CPP_to_Python_Ops_Sub, s) + for expr, repl in CPP_to_Python_Eval_List: + s = expr.sub(repl, s) + return s + + + +del expr +del l +del override + + + +class FunctionEvaluator: + """ + Handles delayed evaluation of a #define function call. + """ + def __init__(self, name, args, expansion): + """ + Squirrels away the arguments and expansion value of a #define + macro function for later evaluation when we must actually expand + a value that uses it. + """ + self.name = name + self.args = function_arg_separator.split(args) + self.expansion = string.split(expansion, '##') + def __call__(self, *values): + """ + Evaluates the expansion of a #define macro function called + with the specified values. + """ + if len(self.args) != len(values): + raise ValueError, "Incorrect number of arguments to `%s'" % self.name + # Create a dictionary that maps the macro arguments to the + # corresponding values in this "call." We'll use this when we + # eval() the expansion so that arguments will get expanded to + # the right values. + locals = {} + for k, v in zip(self.args, values): + locals[k] = v + + parts = [] + for s in self.expansion: + if not s in self.args: + s = repr(s) + parts.append(s) + statement = string.join(parts, ' + ') + + return eval(statement, globals(), locals) + + + +# Find line continuations. +line_continuations = re.compile('\\\\\r?\n') + +# Search for a "function call" macro on an expansion. Returns the +# two-tuple of the "function" name itself, and a string containing the +# arguments within the call parentheses. +function_name = re.compile('(\S+)\(([^)]*)\)') + +# Split a string containing comma-separated function call arguments into +# the separate arguments. +function_arg_separator = re.compile(',\s*') + + + +class PreProcessor: + """ + The main workhorse class for handling C pre-processing. + """ + def __init__(self, current='.', cpppath=[], dict={}, all=0): + global Table + + self.searchpath = { + '"' : [current] + cpppath, + '<' : cpppath + [current], + } + + # Initialize our C preprocessor namespace for tracking the + # values of #defined keywords. We use this namespace to look + # for keywords on #ifdef/#ifndef lines, and to eval() the + # expressions on #if/#elif lines (after massaging them from C to + # Python). + self.cpp_namespace = dict.copy() + self.cpp_namespace['__dict__'] = self.cpp_namespace + + if all: + self.do_include = self.all_include + + # For efficiency, a dispatch table maps each C preprocessor + # directive (#if, #define, etc.) to the method that should be + # called when we see it. We accomodate state changes (#if, + # #ifdef, #ifndef) by pushing the current dispatch table on a + # stack and changing what method gets called for each relevant + # directive we might see next at this level (#else, #elif). + # #endif will simply pop the stack. + d = {} + for op in Table.keys(): + d[op] = getattr(self, 'do_' + op) + self.default_table = d + + # Controlling methods. + + def tupleize(self, contents): + """ + Turns the contents of a file into a list of easily-processed + tuples describing the CPP lines in the file. + + The first element of each tuple is the line's preprocessor + directive (#if, #include, #define, etc., minus the initial '#'). + The remaining elements are specific to the type of directive, as + pulled apart by the regular expression. + """ + global CPP_Expression, Table + contents = line_continuations.sub('', contents) + cpp_tuples = CPP_Expression.findall(contents) + return map(lambda m, t=Table: + (m[0],) + t[m[0]].match(m[1]).groups(), + cpp_tuples) + + def __call__(self, contents): + """ + Pre-processes a file contents. + + This is the main entry point, which + """ + self.stack = [] + self.dispatch_table = self.default_table.copy() + self.tuples = self.tupleize(contents) + + self.result = [] + while self.tuples: + t = self.tuples.pop(0) + # Uncomment to see the list of tuples being processed (e.g., + # to validate the CPP lines are being translated correctly). + #print t + self.dispatch_table[t[0]](t) + + return self.result + + # Dispatch table stack manipulation methods. + + def save(self): + """ + Pushes the current dispatch table on the stack and re-initializes + the current dispatch table to the default. + """ + self.stack.append(self.dispatch_table) + self.dispatch_table = self.default_table.copy() + + def restore(self): + """ + Pops the previous dispatch table off the stack and makes it the + current one. + """ + try: self.dispatch_table = self.stack.pop() + except IndexError: pass + + # Utility methods. + + def do_nothing(self, t): + """ + Null method for when we explicitly want the action for a + specific preprocessor directive to do nothing. + """ + pass + + def eval_expression(self, t): + """ + Evaluates a C preprocessor expression. + + This is done by converting it to a Python equivalent and + eval()ing it in the C preprocessor namespace we use to + track #define values. + """ + t = CPP_to_Python(string.join(t[1:])) + try: return eval(t, self.cpp_namespace) + except (NameError, TypeError): return 0 + + def find_include_file(self, t): + """ + Finds the #include file for a given preprocessor tuple. + """ + fname = t[2] + for d in self.searchpath[t[1]]: + f = os.path.join(d, fname) + if os.path.isfile(f): + return f + return None + + # Start and stop processing include lines. + + def start_handling_includes(self, t=None): + """ + Causes the PreProcessor object to start processing #import, + #include and #include_next lines. + + This method will be called when a #if, #ifdef, #ifndef or #elif + evaluates True, or when we reach the #else in a #if, #ifdef, + #ifndef or #elif block where a condition already evaluated + False. + + """ + d = self.dispatch_table + d['import'] = self.do_import + d['include'] = self.do_include + d['include_next'] = self.do_include + + def stop_handling_includes(self, t=None): + """ + Causes the PreProcessor object to stop processing #import, + #include and #include_next lines. + + This method will be called when a #if, #ifdef, #ifndef or #elif + evaluates False, or when we reach the #else in a #if, #ifdef, + #ifndef or #elif block where a condition already evaluated True. + """ + d = self.dispatch_table + d['import'] = self.do_nothing + d['include'] = self.do_nothing + d['include_next'] = self.do_nothing + + # Default methods for handling all of the preprocessor directives. + # (Note that what actually gets called for a given directive at any + # point in time is really controlled by the dispatch_table.) + + def _do_if_else_condition(self, condition): + """ + Common logic for evaluating the conditions on #if, #ifdef and + #ifndef lines. + """ + self.save() + d = self.dispatch_table + if condition: + self.start_handling_includes() + d['elif'] = self.stop_handling_includes + d['else'] = self.stop_handling_includes + else: + self.stop_handling_includes() + d['elif'] = self.do_elif + d['else'] = self.start_handling_includes + + def do_ifdef(self, t): + """ + Default handling of a #ifdef line. + """ + self._do_if_else_condition(self.cpp_namespace.has_key(t[1])) + + def do_ifndef(self, t): + """ + Default handling of a #ifndef line. + """ + self._do_if_else_condition(not self.cpp_namespace.has_key(t[1])) + + def do_if(self, t): + """ + Default handling of a #if line. + """ + self._do_if_else_condition(self.eval_expression(t)) + + def do_elif(self, t): + """ + Default handling of a #elif line. + """ + d = self.dispatch_table + if self.eval_expression(t): + self.start_handling_includes() + d['elif'] = self.stop_handling_includes + d['else'] = self.stop_handling_includes + + def do_else(self, t): + """ + Default handling of a #else line. + """ + pass + + def do_endif(self, t): + """ + Default handling of a #endif line. + """ + self.restore() + + def do_define(self, t): + """ + Default handling of a #define line. + """ + _, name, args, expansion = t + try: + expansion = int(expansion) + except (TypeError, ValueError): + pass + if args: + evaluator = FunctionEvaluator(name, args[1:-1], expansion) + self.cpp_namespace[name] = evaluator + else: + self.cpp_namespace[name] = expansion + + def do_undef(self, t): + """ + Default handling of a #undef line. + """ + try: del self.cpp_namespace[t[1]] + except KeyError: pass + + def do_import(self, t): + """ + Default handling of a #import line. + """ + # XXX finish this -- maybe borrow/share logic from do_include()...? + pass + + def do_include(self, t): + """ + Default handling of a #include line. + """ + t = self.resolve_include(t) + include_file = self.find_include_file(t) + if include_file: + #print "include_file =", include_file + self.result.append(include_file) + contents = open(include_file).read() + new_tuples = self.tupleize(contents) + self.tuples[:] = new_tuples + self.tuples + + # Date: Tue, 22 Nov 2005 20:26:09 -0500 + # From: Stefan Seefeld + # + # By the way, #include_next is not the same as #include. The difference + # being that #include_next starts its search in the path following the + # path that let to the including file. In other words, if your system + # include paths are ['/foo', '/bar'], and you are looking at a header + # '/foo/baz.h', it might issue an '#include_next ' which would + # correctly resolve to '/bar/baz.h' (if that exists), but *not* see + # '/foo/baz.h' again. See http://www.delorie.com/gnu/docs/gcc/cpp_11.html + # for more reasoning. + # + # I have no idea in what context 'import' might be used. + + # XXX is #include_next really the same as #include ? + do_include_next = do_include + + # Utility methods for handling resolution of include files. + + def resolve_include(self, t): + """Resolve a tuple-ized #include line. + + This handles recursive expansion of values without "" or <> + surrounding the name until an initial " or < is found, to handle + #include FILE + where FILE is a #define somewhere else. + """ + s = t[1] + while not s[0] in '<"': + #print "s =", s + try: + s = self.cpp_namespace[s] + except KeyError: + m = function_name.search(s) + s = self.cpp_namespace[m.group(1)] + if callable(s): + args = function_arg_separator.split(m.group(2)) + s = apply(s, args) + if not s: + return None + return (t[0], s[0], s[1:-1]) + + def all_include(self, t): + """ + """ + self.result.append(self.resolve_include(t)) + +class DumbPreProcessor(PreProcessor): + """A preprocessor that ignores all #if/#elif/#else/#endif directives + and just reports back *all* of the #include files (like the classic + SCons scanner did). + + This is functionally equivalent to using a regular expression to + find all of the #include lines, only slower. It exists mainly as + an example of how the main PreProcessor class can be sub-classed + to tailor its behavior. + """ + def __init__(self, *args, **kw): + apply(PreProcessor.__init__, (self,)+args, kw) + d = self.default_table + for func in ['if', 'elif', 'else', 'endif', 'ifdef', 'ifndef']: + d[func] = d[func] = self.do_nothing + +del __revision__ diff --git a/scons/scons-local-0.96.1/SCons/dblite.py b/scons/scons-local-0.97/SCons/dblite.py similarity index 78% rename from scons/scons-local-0.96.1/SCons/dblite.py rename to scons/scons-local-0.97/SCons/dblite.py index c9845a751..36840c387 100644 --- a/scons/scons-local-0.96.1/SCons/dblite.py +++ b/scons/scons-local-0.97/SCons/dblite.py @@ -5,6 +5,7 @@ import cPickle import time import shutil import os +import os.path import types import __builtin__ @@ -13,6 +14,9 @@ _open = __builtin__.open # avoid name clash keep_all_files = 00000 ignore_corrupt_dbfiles = 0 +def corruption_warning(filename): + print "Warning: Discarding corrupt database:", filename + if hasattr(types, 'UnicodeType'): def is_string(s): t = type(s) @@ -26,14 +30,22 @@ try: except NameError: def unicode(s): return s +dblite_suffix = '.dblite' +tmp_suffix = '.tmp' + class dblite: def __init__(self, file_base_name, flag, mode): assert flag in (None, "r", "w", "c", "n") if (flag is None): flag = "r" - if file_base_name[-7:] != '.dblite': - file_base_name = file_base_name + '.dblite' - self._file_name = file_base_name + base, ext = os.path.splitext(file_base_name) + if ext == dblite_suffix: + # There's already a suffix on the file name, don't add one. + self._file_name = file_base_name + self._tmp_name = base + tmp_suffix + else: + self._file_name = file_base_name + dblite_suffix + self._tmp_name = file_base_name + tmp_suffix self._flag = flag self._mode = mode self._dict = {} @@ -52,10 +64,10 @@ class dblite: if (len(p) > 0): try: self._dict = cPickle.loads(p) - except: + except (cPickle.UnpicklingError, EOFError): if (ignore_corrupt_dbfiles == 0): raise if (ignore_corrupt_dbfiles == 1): - print "Warning: Discarding corrupt database:", self._file_name + corruption_warning(self._file_name) def __del__(self): if (self._needs_sync): @@ -63,9 +75,19 @@ class dblite: def sync(self): self._check_writable() - f = _open(self._file_name, "wb", self._mode) + f = _open(self._tmp_name, "wb", self._mode) cPickle.dump(self._dict, f, 1) f.close() + # Windows doesn't allow renaming if the file exists, so unlink + # it first, chmod'ing it to make sure we can do so. On UNIX, we + # may not be able to chmod the file if it's owned by someone else + # (e.g. from a previous run as root). We should still be able to + # unlink() the file if the directory's writable, though, so ignore + # any OSError exception thrown by the chmod() call. + try: os.chmod(self._file_name, 0777) + except OSError: pass + os.unlink(self._file_name) + os.rename(self._tmp_name, self._file_name) self._needs_sync = 00000 if (keep_all_files): shutil.copyfile( diff --git a/scons/scons-local-0.96.1/SCons/exitfuncs.py b/scons/scons-local-0.97/SCons/exitfuncs.py similarity index 94% rename from scons/scons-local-0.96.1/SCons/exitfuncs.py rename to scons/scons-local-0.97/SCons/exitfuncs.py index bb67e347e..9d7ca48c8 100644 --- a/scons/scons-local-0.96.1/SCons/exitfuncs.py +++ b/scons/scons-local-0.97/SCons/exitfuncs.py @@ -5,7 +5,7 @@ Register functions which are executed when SCons exits for any reason. """ # -# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation +# 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 @@ -27,7 +27,7 @@ Register functions which are executed when SCons exits for any reason. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/exitfuncs.py 0.96.1.D001 2004/08/23 09:55:29 knight" +__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/exitfuncs.py 0.97.D001 2007/05/17 11:35:19 knight" diff --git a/scons/scons.py b/scons/scons.py deleted file mode 100755 index 82afe6f5c..000000000 --- a/scons/scons.py +++ /dev/null @@ -1,144 +0,0 @@ -#! /usr/bin/env python -# -# SCons - a Software Constructor -# -# Copyright (c) 2001, 2002, 2003, 2004 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__ = "/home/scons/scons/branch.0/baseline/src/script/scons.py 0.96.1.D001 2004/08/23 09:55:29 knight" - -__version__ = "0.96.1" - -__build__ = "D001" - -__buildsys__ = "casablanca" - -__date__ = "2004/08/23 09:55:29" - -__developer__ = "knight" - -import os -import os.path -import sys - -############################################################################## -# BEGIN STANDARD SCons SCRIPT HEADER -# -# This is the cut-and-paste logic so that a self-contained script can -# interoperate correctly with different SCons versions and installation -# locations for the engine. If you modify anything in this section, you -# should also change other scripts that use this same header. -############################################################################## - -# Strip the script directory from sys.path() so on case-insensitive -# (WIN32) systems Python doesn't think that the "scons" script is the -# "SCons" package. Replace it with our own library directories -# (version-specific first, in case they installed by hand there, -# followed by generic) so we pick up the right version of the build -# engine modules if they're in either directory. - -script_dir = sys.path[0] - -if script_dir in sys.path: - sys.path.remove(script_dir) - -libs = [] - -if os.environ.has_key("SCONS_LIB_DIR"): - libs.append(os.environ["SCONS_LIB_DIR"]) - -local = 'scons-local-' + __version__ -if script_dir: - local = os.path.join(script_dir, local) -libs.append(local) - -scons_version = 'scons-%s' % __version__ - -prefs = [] - -if sys.platform == 'win32': - # sys.prefix is (likely) C:\Python*; - # check only C:\Python*. - prefs.append(sys.prefix) - prefs.append(os.path.join(sys.prefix, 'Lib', 'site-packages')) -else: - # On other (POSIX) platforms, things are more complicated due to - # the variety of path names and library locations. Try to be smart - # about it. - if script_dir == 'bin': - # script_dir is `pwd`/bin; - # check `pwd`/lib/scons*. - prefs.append(os.getcwd()) - else: - if script_dir == '.' or script_dir == '': - script_dir = os.getcwd() - head, tail = os.path.split(script_dir) - if tail == "bin": - # script_dir is /foo/bin; - # check /foo/lib/scons*. - prefs.append(head) - - head, tail = os.path.split(sys.prefix) - if tail == "usr": - # sys.prefix is /foo/usr; - # check /foo/usr/lib/scons* first, - # then /foo/usr/local/lib/scons*. - prefs.append(sys.prefix) - prefs.append(os.path.join(sys.prefix, "local")) - elif tail == "local": - h, t = os.path.split(head) - if t == "usr": - # sys.prefix is /foo/usr/local; - # check /foo/usr/local/lib/scons* first, - # then /foo/usr/lib/scons*. - prefs.append(sys.prefix) - prefs.append(head) - else: - # sys.prefix is /foo/local; - # check only /foo/local/lib/scons*. - prefs.append(sys.prefix) - else: - # sys.prefix is /foo (ends in neither /usr or /local); - # check only /foo/lib/scons*. - prefs.append(sys.prefix) - - temp = map(lambda x: os.path.join(x, 'lib'), prefs) - temp.extend(map(lambda x: os.path.join(x, - 'lib', - 'python' + sys.version[:3], - 'site-packages'), - prefs)) - prefs = temp - -# Look first for 'scons-__version__' in all of our preference libs, -# then for 'scons'. -libs.extend(map(lambda x: os.path.join(x, scons_version), prefs)) -libs.extend(map(lambda x: os.path.join(x, 'scons'), prefs)) - -sys.path = libs + sys.path - -############################################################################## -# END STANDARD SCons SCRIPT HEADER -############################################################################## - -import SCons.Script -SCons.Script.main() diff --git a/scons/sconsign.py b/scons/sconsign.py deleted file mode 100755 index aff43ba56..000000000 --- a/scons/sconsign.py +++ /dev/null @@ -1,406 +0,0 @@ -#! /usr/bin/env python -# -# SCons - a Software Constructor -# -# Copyright (c) 2001, 2002, 2003, 2004 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__ = "/home/scons/scons/branch.0/baseline/src/script/sconsign.py 0.96.1.D001 2004/08/23 09:55:29 knight" - -__version__ = "0.96.1" - -__build__ = "D001" - -__buildsys__ = "casablanca" - -__date__ = "2004/08/23 09:55:29" - -__developer__ = "knight" - -import os -import os.path -import sys -import time - -############################################################################## -# BEGIN STANDARD SCons SCRIPT HEADER -# -# This is the cut-and-paste logic so that a self-contained script can -# interoperate correctly with different SCons versions and installation -# locations for the engine. If you modify anything in this section, you -# should also change other scripts that use this same header. -############################################################################## - -# Strip the script directory from sys.path() so on case-insensitive -# (WIN32) systems Python doesn't think that the "scons" script is the -# "SCons" package. Replace it with our own library directories -# (version-specific first, in case they installed by hand there, -# followed by generic) so we pick up the right version of the build -# engine modules if they're in either directory. - -script_dir = sys.path[0] - -if script_dir in sys.path: - sys.path.remove(script_dir) - -libs = [] - -if os.environ.has_key("SCONS_LIB_DIR"): - libs.append(os.environ["SCONS_LIB_DIR"]) - -local = 'scons-local-' + __version__ -if script_dir: - local = os.path.join(script_dir, local) -libs.append(local) - -scons_version = 'scons-%s' % __version__ - -prefs = [] - -if sys.platform == 'win32': - # sys.prefix is (likely) C:\Python*; - # check only C:\Python*. - prefs.append(sys.prefix) - prefs.append(os.path.join(sys.prefix, 'Lib', 'site-packages')) -else: - # On other (POSIX) platforms, things are more complicated due to - # the variety of path names and library locations. Try to be smart - # about it. - if script_dir == 'bin': - # script_dir is `pwd`/bin; - # check `pwd`/lib/scons*. - prefs.append(os.getcwd()) - else: - if script_dir == '.' or script_dir == '': - script_dir = os.getcwd() - head, tail = os.path.split(script_dir) - if tail == "bin": - # script_dir is /foo/bin; - # check /foo/lib/scons*. - prefs.append(head) - - head, tail = os.path.split(sys.prefix) - if tail == "usr": - # sys.prefix is /foo/usr; - # check /foo/usr/lib/scons* first, - # then /foo/usr/local/lib/scons*. - prefs.append(sys.prefix) - prefs.append(os.path.join(sys.prefix, "local")) - elif tail == "local": - h, t = os.path.split(head) - if t == "usr": - # sys.prefix is /foo/usr/local; - # check /foo/usr/local/lib/scons* first, - # then /foo/usr/lib/scons*. - prefs.append(sys.prefix) - prefs.append(head) - else: - # sys.prefix is /foo/local; - # check only /foo/local/lib/scons*. - prefs.append(sys.prefix) - else: - # sys.prefix is /foo (ends in neither /usr or /local); - # check only /foo/lib/scons*. - prefs.append(sys.prefix) - - temp = map(lambda x: os.path.join(x, 'lib'), prefs) - temp.extend(map(lambda x: os.path.join(x, - 'lib', - 'python' + sys.version[:3], - 'site-packages'), - prefs)) - prefs = temp - -# Look first for 'scons-__version__' in all of our preference libs, -# then for 'scons'. -libs.extend(map(lambda x: os.path.join(x, scons_version), prefs)) -libs.extend(map(lambda x: os.path.join(x, 'scons'), prefs)) - -sys.path = libs + sys.path - -############################################################################## -# END STANDARD SCons SCRIPT HEADER -############################################################################## - -import cPickle -import imp -import string -import whichdb - -import SCons.SConsign - -def my_whichdb(filename): - try: - f = open(filename + ".dblite", "rb") - f.close() - return "SCons.dblite" - except IOError: - pass - return _orig_whichdb(filename) - -_orig_whichdb = whichdb.whichdb -whichdb.whichdb = my_whichdb - -def my_import(mname): - if '.' in mname: - i = string.rfind(mname, '.') - parent = my_import(mname[:i]) - fp, pathname, description = imp.find_module(mname[i+1:], - parent.__path__) - else: - fp, pathname, description = imp.find_module(mname) - return imp.load_module(mname, fp, pathname, description) - -class Flagger: - default_value = 1 - def __setitem__(self, item, value): - self.__dict__[item] = value - self.default_value = 0 - def __getitem__(self, item): - return self.__dict__.get(item, self.default_value) - -Do_Call = None -Print_Directories = [] -Print_Entries = [] -Print_Flags = Flagger() -Verbose = 0 -Readable = 0 - -def default_mapper(entry, name): - try: - val = eval("entry."+name) - except: - val = None - return str(val) - -def map_timestamp(entry, name): - try: - timestamp = entry.timestamp - except AttributeError: - timestamp = None - if Readable and timestamp: - return "'" + time.ctime(timestamp) + "'" - else: - return str(timestamp) - -def map_bkids(entry, name): - try: - bkids = entry.bsources + entry.bdepends + entry.bimplicit - bkidsigs = entry.bsourcesigs + entry.bdependsigs + entry.bimplicitsigs - except AttributeError: - return None - result = [] - for i in xrange(len(bkids)): - result.append("%s: %s" % (bkids[i], bkidsigs[i])) - if result == []: - return None - return string.join(result, "\n ") - -map_field = { - 'timestamp' : map_timestamp, - 'bkids' : map_bkids, -} - -map_name = { - 'implicit' : 'bkids', -} - -def printfield(name, entry): - def field(name, verbose=Verbose, entry=entry): - if not Print_Flags[name]: - return None - fieldname = map_name.get(name, name) - mapper = map_field.get(fieldname, default_mapper) - val = mapper(entry, name) - if verbose: - val = name + ": " + val - return val - - fieldlist = ["timestamp", "bsig", "csig"] - outlist = [name+":"] + filter(None, map(field, fieldlist)) - sep = Verbose and "\n " or " " - print string.join(outlist, sep) - - outlist = field("implicit", 0) - if outlist: - if Verbose: - print " implicit:" - print " " + outlist - -def printentries(entries): - if Print_Entries: - for name in Print_Entries: - try: - entry = entries[name] - except KeyError: - sys.stderr.write("sconsign: no entry `%s' in `%s'\n" % (name, args[0])) - else: - printfield(name, entry) - else: - for name, e in entries.items(): - printfield(name, e) - -class Do_SConsignDB: - def __init__(self, dbm_name, dbm): - self.dbm_name = dbm_name - self.dbm = dbm - - def __call__(self, fname): - # The *dbm modules stick their own file suffixes on the names - # that are passed in. This is causes us to jump through some - # hoops here to be able to allow the user - try: - # Try opening the specified file name. Example: - # SPECIFIED OPENED BY self.dbm.open() - # --------- ------------------------- - # .sconsign => .sconsign.dblite - # .sconsign.dblite => .sconsign.dblite.dblite - db = self.dbm.open(fname, "r") - except (IOError, OSError), e: - print_e = e - try: - # That didn't work, so try opening the base name, - # so that if the actually passed in 'sconsign.dblite' - # (for example), the dbm module will put the suffix back - # on for us and open it anyway. - db = self.dbm.open(os.path.splitext(fname)[0], "r") - except (IOError, OSError): - # That didn't work either. See if the file name - # they specified just exists (independent of the dbm - # suffix-mangling). - try: - open(fname, "r") - except (IOError, OSError), e: - # Nope, that file doesn't even exist, so report that - # fact back. - print_e = e - sys.stderr.write("sconsign: %s\n" % (print_e)) - return - except: - sys.stderr.write("sconsign: ignoring invalid `%s' file `%s'\n" % (self.dbm_name, fname)) - return - - if Print_Directories: - for dir in Print_Directories: - try: - val = db[dir] - except KeyError: - sys.stderr.write("sconsign: no dir `%s' in `%s'\n" % (dir, args[0])) - else: - self.printentries(dir, val) - else: - keys = db.keys() - keys.sort() - for dir in keys: - self.printentries(dir, db[dir]) - - def printentries(self, dir, val): - print '=== ' + dir + ':' - printentries(cPickle.loads(val)) - -def Do_SConsignDir(name): - try: - fp = open(name, 'rb') - except (IOError, OSError), e: - sys.stderr.write("sconsign: %s\n" % (e)) - return - try: - sconsign = SCons.SConsign.Dir(fp) - except: - sys.stderr.write("sconsign: ignoring invalid .sconsign file `%s'\n" % name) - return - printentries(sconsign.entries) - -############################################################################## - -import getopt - -helpstr = """\ -Usage: sconsign [OPTIONS] FILE [...] -Options: - -b, --bsig Print build signature information. - -c, --csig Print content signature information. - -d DIR, --dir=DIR Print only info about DIR. - -e ENTRY, --entry=ENTRY Print only info about ENTRY. - -f FORMAT, --format=FORMAT FILE is in the specified FORMAT. - -h, --help Print this message and exit. - -i, --implicit Print implicit dependency information. - -r, --readable Print timestamps in human-readable form. - -t, --timestamp Print timestamp information. - -v, --verbose Verbose, describe each field. -""" - -opts, args = getopt.getopt(sys.argv[1:], "bcd:e:f:hirtv", - ['bsig', 'csig', 'dir=', 'entry=', - 'format=', 'help', 'implicit', - 'readable', 'timestamp', 'verbose']) - - -for o, a in opts: - if o in ('-b', '--bsig'): - Print_Flags['bsig'] = 1 - elif o in ('-c', '--csig'): - Print_Flags['csig'] = 1 - elif o in ('-d', '--dir'): - Print_Directories.append(a) - elif o in ('-e', '--entry'): - Print_Entries.append(a) - elif o in ('-f', '--format'): - Module_Map = {'dblite' : 'SCons.dblite', - 'sconsign' : None} - dbm_name = Module_Map.get(a, a) - if dbm_name: - try: - dbm = my_import(dbm_name) - except: - sys.stderr.write("sconsign: illegal file format `%s'\n" % a) - print helpstr - sys.exit(2) - Do_Call = Do_SConsignDB(a, dbm) - else: - Do_Call = Do_SConsignDir - elif o in ('-h', '--help'): - print helpstr - sys.exit(0) - elif o in ('-i', '--implicit'): - Print_Flags['implicit'] = 1 - elif o in ('-r', '--readable'): - Readable = 1 - elif o in ('-t', '--timestamp'): - Print_Flags['timestamp'] = 1 - elif o in ('-v', '--verbose'): - Verbose = 1 - -if Do_Call: - for a in args: - Do_Call(a) -else: - for a in args: - dbm_name = whichdb.whichdb(a) - if dbm_name: - Map_Module = {'SCons.dblite' : 'dblite'} - dbm = my_import(dbm_name) - Do_SConsignDB(Map_Module.get(dbm_name, dbm_name), dbm)(a) - else: - Do_SConsignDir(a) - -sys.exit(0)