upgrade to the latest scons (0.97)
This commit is contained in:
parent
8887b9eb99
commit
6752dda07e
165 changed files with 20697 additions and 11194 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
|
@ -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
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -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
|
File diff suppressed because it is too large
Load diff
|
@ -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)
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -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 <top>/Bin/icl.exe,
|
||||
the include dir is <top>/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
|
File diff suppressed because it is too large
Load diff
|
@ -1,118 +0,0 @@
|
|||
"""SCons.Tool.tex
|
||||
|
||||
Tool-specific initialization for TeX.
|
||||
|
||||
There normally shouldn't be any need to import this module directly.
|
||||
It will usually be imported through the generic SCons.Tool.Tool()
|
||||
selection method.
|
||||
|
||||
"""
|
||||
|
||||
#
|
||||
# Copyright (c) 2001, 2002, 2003, 2004 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/tex.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
|
||||
import os.path
|
||||
import re
|
||||
import string
|
||||
|
||||
import SCons.Action
|
||||
import SCons.Defaults
|
||||
import SCons.Node
|
||||
import SCons.Node.FS
|
||||
import SCons.Util
|
||||
|
||||
# Define an action to build a generic tex file. This is sufficient for all
|
||||
# tex files.
|
||||
TeXAction = SCons.Action.CommandAction("$TEXCOM")
|
||||
|
||||
# Define an action to build a latex file. This action might be needed more
|
||||
# than once if we are dealing with labels and bibtex
|
||||
LaTeXAction = SCons.Action.CommandAction("$LATEXCOM")
|
||||
|
||||
# Define an action to run BibTeX on a file.
|
||||
BibTeXAction = SCons.Action.CommandAction("$BIBTEXCOM")
|
||||
|
||||
def LaTeXAuxAction(target = None, source= None, env=None):
|
||||
"""A builder for LaTeX files that checks the output in the aux file
|
||||
and decides how many times to use LaTeXAction, and BibTeXAction."""
|
||||
# Get the base name of the target
|
||||
basename, ext = os.path.splitext(str(target[0]))
|
||||
# Run LaTeX once to generate a new aux file.
|
||||
LaTeXAction(target,source,env)
|
||||
# Now if bibtex will need to be run.
|
||||
content = open(basename + ".aux","rb").read()
|
||||
if string.find(content, "bibdata") != -1:
|
||||
bibfile = env.fs.File(basename)
|
||||
BibTeXAction(None,bibfile,env)
|
||||
# Now check if latex needs to be run yet again.
|
||||
for trial in range(3):
|
||||
content = open(basename + ".log","rb").read()
|
||||
if not re.search("^LaTeX Warning:.*Rerun",content,re.MULTILINE):
|
||||
break
|
||||
LaTeXAction(target,source,env)
|
||||
return 0
|
||||
|
||||
def TeXLaTeXAction(target = None, source= None, env=None):
|
||||
"""A builder for TeX and LaTeX that scans the source file to
|
||||
decide the "flavor" of the source and then executes the appropriate
|
||||
program."""
|
||||
LaTeXFile = None
|
||||
for src in source:
|
||||
content = src.get_contents()
|
||||
if re.search("\\\\document(style|class)",content):
|
||||
LaTeXFile = 1
|
||||
break
|
||||
if LaTeXFile:
|
||||
LaTeXAuxAction(target,source,env)
|
||||
else:
|
||||
TeXAction(target,source,env)
|
||||
return 0
|
||||
|
||||
def generate(env):
|
||||
"""Add Builders and construction variables for TeX to an Environment."""
|
||||
try:
|
||||
bld = env['BUILDERS']['DVI']
|
||||
except KeyError:
|
||||
bld = SCons.Defaults.DVI()
|
||||
env['BUILDERS']['DVI'] = bld
|
||||
|
||||
bld.add_action('.tex', TeXLaTeXAction)
|
||||
|
||||
env['TEX'] = 'tex'
|
||||
env['TEXFLAGS'] = SCons.Util.CLVar('')
|
||||
env['TEXCOM'] = '$TEX $TEXFLAGS $SOURCES'
|
||||
|
||||
# Duplicate from latex.py. If latex.py goes away, then this is still OK.
|
||||
env['LATEX'] = 'latex'
|
||||
env['LATEXFLAGS'] = SCons.Util.CLVar('')
|
||||
env['LATEXCOM'] = '$LATEX $LATEXFLAGS $SOURCES'
|
||||
|
||||
env['BIBTEX'] = 'bibtex'
|
||||
env['BIBTEXFLAGS'] = SCons.Util.CLVar('')
|
||||
env['BIBTEXCOM'] = '$BIBTEX $BIBTEXFLAGS $SOURCES'
|
||||
|
||||
|
||||
def exists(env):
|
||||
return env.Detect('tex')
|
File diff suppressed because it is too large
Load diff
830
scons/scons-local-0.97/SCons/Action.py
Normal file
830
scons/scons-local-0.97/SCons/Action.py
Normal file
|
@ -0,0 +1,830 @@
|
|||
"""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.
|
||||
|
||||
A second-level base class is _ActionAction. This extends ActionBase
|
||||
by providing the methods that can be used to show and perform an
|
||||
action. True Action objects will subclass _ActionAction; Action
|
||||
factory class objects will subclass ActionBase.
|
||||
|
||||
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 obtain an (imprecise) representation
|
||||
of the Action operation for informative purposes.
|
||||
|
||||
|
||||
Subclasses also supply the following methods for internal use within
|
||||
this module:
|
||||
|
||||
__str__()
|
||||
Returns a string approximation of the Action; no variable
|
||||
substitution is performed.
|
||||
|
||||
execute()
|
||||
The internal method that really, truly, actually handles the
|
||||
execution of a command or Python function. This is used so
|
||||
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.
|
||||
|
||||
strfunction()
|
||||
Returns a substituted string representation of the Action.
|
||||
This is used by the _ActionAction.show() command to display the
|
||||
command/function that will be executed to generate the target(s).
|
||||
|
||||
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, 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/Action.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import dis
|
||||
import os
|
||||
import os.path
|
||||
import string
|
||||
import sys
|
||||
|
||||
from SCons.Debug import logInstanceCreation
|
||||
import SCons.Errors
|
||||
import SCons.Executor
|
||||
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 default_exitstatfunc(s):
|
||||
return s
|
||||
|
||||
try:
|
||||
SET_LINENO = dis.SET_LINENO
|
||||
HAVE_ARGUMENT = dis.HAVE_ARGUMENT
|
||||
except AttributeError:
|
||||
remove_set_lineno_codes = lambda x: x
|
||||
else:
|
||||
def remove_set_lineno_codes(code):
|
||||
result = []
|
||||
n = len(code)
|
||||
i = 0
|
||||
while i < n:
|
||||
c = code[i]
|
||||
op = ord(c)
|
||||
if op >= HAVE_ARGUMENT:
|
||||
if op != SET_LINENO:
|
||||
result.append(code[i:i+3])
|
||||
i = i+3
|
||||
else:
|
||||
result.append(c)
|
||||
i = i+1
|
||||
return string.join(result, '')
|
||||
|
||||
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 ])
|
||||
|
||||
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 callable(act):
|
||||
try:
|
||||
gen = kw['generator']
|
||||
del kw['generator']
|
||||
except KeyError:
|
||||
gen = 0
|
||||
if gen:
|
||||
action_type = CommandGeneratorAction
|
||||
else:
|
||||
action_type = FunctionAction
|
||||
return apply(action_type, (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.
|
||||
return apply(LazyAction, (var,)+args, kw)
|
||||
commands = string.split(str(act), '\n')
|
||||
if len(commands) == 1:
|
||||
return apply(CommandAction, (commands[0],)+args, kw)
|
||||
else:
|
||||
listCmdActions = map(lambda x, args=args, kw=kw:
|
||||
apply(CommandAction, (x,)+args, kw),
|
||||
commands)
|
||||
return ListAction(listCmdActions)
|
||||
return None
|
||||
|
||||
def Action(act, *args, **kw):
|
||||
"""A factory for action objects."""
|
||||
if SCons.Util.is_List(act):
|
||||
acts = map(lambda a, args=args, kw=kw:
|
||||
apply(_do_create_action, (a,)+args, kw),
|
||||
act)
|
||||
acts = filter(None, acts)
|
||||
if len(acts) == 1:
|
||||
return acts[0]
|
||||
else:
|
||||
return ListAction(acts)
|
||||
else:
|
||||
return apply(_do_create_action, (act,)+args, kw)
|
||||
|
||||
class ActionBase:
|
||||
"""Base class for all types of action objects that can be held by
|
||||
other objects (Builders, Executors, etc.) This provides the
|
||||
common methods for manipulating and combining those actions."""
|
||||
|
||||
def __cmp__(self, other):
|
||||
return cmp(self.__dict__, other)
|
||||
|
||||
def genstring(self, target, source, env):
|
||||
return str(self)
|
||||
|
||||
def __add__(self, other):
|
||||
return _actionAppend(self, other)
|
||||
|
||||
def __radd__(self, other):
|
||||
return _actionAppend(other, self)
|
||||
|
||||
def presub_lines(self, env):
|
||||
# CommandGeneratorAction needs a real environment
|
||||
# in order to return the proper string here, since
|
||||
# it may call LazyAction, 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 get_executor(self, env, overrides, tlist, slist, executor_kw):
|
||||
"""Return the Executor for this Action."""
|
||||
return SCons.Executor.Executor(self, env, overrides,
|
||||
tlist, slist, executor_kw)
|
||||
|
||||
class _ActionAction(ActionBase):
|
||||
"""Base class for actions that create output objects."""
|
||||
def __init__(self, strfunction=_null, presub=_null, chdir=None, exitstatfunc=None, **kw):
|
||||
if not strfunction is _null:
|
||||
self.strfunction = strfunction
|
||||
self.presub = presub
|
||||
self.chdir = chdir
|
||||
if not exitstatfunc:
|
||||
exitstatfunc = default_exitstatfunc
|
||||
self.exitstatfunc = exitstatfunc
|
||||
|
||||
def print_cmd_line(self, s, target, source, env):
|
||||
sys.stdout.write(s + "\n")
|
||||
|
||||
def __call__(self, target, source, env,
|
||||
exitstatfunc=_null,
|
||||
presub=_null,
|
||||
show=_null,
|
||||
execute=_null,
|
||||
chdir=_null):
|
||||
if not SCons.Util.is_List(target):
|
||||
target = [target]
|
||||
if not SCons.Util.is_List(source):
|
||||
source = [source]
|
||||
if exitstatfunc is _null: exitstatfunc = self.exitstatfunc
|
||||
if presub is _null:
|
||||
presub = self.presub
|
||||
if presub is _null:
|
||||
presub = print_actions_presub
|
||||
if show is _null: show = print_actions
|
||||
if execute is _null: execute = execute_actions
|
||||
if chdir is _null: chdir = self.chdir
|
||||
save_cwd = None
|
||||
if chdir:
|
||||
save_cwd = os.getcwd()
|
||||
try:
|
||||
chdir = str(chdir.abspath)
|
||||
except AttributeError:
|
||||
if not SCons.Util.is_String(chdir):
|
||||
chdir = str(target[0].dir)
|
||||
if presub:
|
||||
t = string.join(map(str, target), ' and ')
|
||||
l = string.join(self.presub_lines(env), '\n ')
|
||||
out = "Building %s with action:\n %s\n" % (t, l)
|
||||
sys.stdout.write(out)
|
||||
s = None
|
||||
if show and self.strfunction:
|
||||
s = self.strfunction(target, source, env)
|
||||
if s:
|
||||
if chdir:
|
||||
s = ('os.chdir(%s)\n' % repr(chdir)) + s
|
||||
try:
|
||||
get = env.get
|
||||
except AttributeError:
|
||||
print_func = self.print_cmd_line
|
||||
else:
|
||||
print_func = get('PRINT_CMD_LINE_FUNC')
|
||||
if not print_func:
|
||||
print_func = self.print_cmd_line
|
||||
print_func(s, target, source, env)
|
||||
stat = 0
|
||||
if execute:
|
||||
if chdir:
|
||||
os.chdir(chdir)
|
||||
try:
|
||||
stat = self.execute(target, source, env)
|
||||
stat = exitstatfunc(stat)
|
||||
finally:
|
||||
if save_cwd:
|
||||
os.chdir(save_cwd)
|
||||
if s and save_cwd:
|
||||
print_func('os.chdir(%s)' % repr(save_cwd), target, source, env)
|
||||
return stat
|
||||
|
||||
|
||||
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(_ActionAction):
|
||||
"""Class for command-execution actions."""
|
||||
def __init__(self, cmd, cmdstr=None, *args, **kw):
|
||||
# Cmd can actually be a list or a single item; if it's a
|
||||
# single item it should be the command string to execute; if a
|
||||
# list then it should be the words of the command string to
|
||||
# execute. Only a single command should be executed by this
|
||||
# object; lists of commands should be handled by embedding
|
||||
# these objects in a ListAction object (which the Action()
|
||||
# factory above does). cmd will be passed to
|
||||
# Environment.subst_list() for substituting environment
|
||||
# variables.
|
||||
if __debug__: logInstanceCreation(self, 'Action.CommandAction')
|
||||
|
||||
if not cmdstr is None:
|
||||
if callable(cmdstr):
|
||||
args = (cmdstr,)+args
|
||||
elif not SCons.Util.is_String(cmdstr):
|
||||
raise SCons.Errors.UserError(\
|
||||
'Invalid command display variable type. ' \
|
||||
'You must either pass a string or a callback which ' \
|
||||
'accepts (target, source, env) as parameters.')
|
||||
|
||||
apply(_ActionAction.__init__, (self,)+args, kw)
|
||||
if SCons.Util.is_List(cmd):
|
||||
if filter(SCons.Util.is_List, cmd):
|
||||
raise TypeError, "CommandAction should be given only " \
|
||||
"a single command"
|
||||
self.cmd_list = cmd
|
||||
self.cmdstr = cmdstr
|
||||
|
||||
def __str__(self):
|
||||
if SCons.Util.is_List(self.cmd_list):
|
||||
return string.join(map(str, self.cmd_list), ' ')
|
||||
return str(self.cmd_list)
|
||||
|
||||
def process(self, target, source, env):
|
||||
result = env.subst_list(self.cmd_list, 0, target, source)
|
||||
silent = None
|
||||
ignore = None
|
||||
while 1:
|
||||
try: c = result[0][0][0]
|
||||
except IndexError: c = None
|
||||
if c == '@': silent = 1
|
||||
elif c == '-': ignore = 1
|
||||
else: break
|
||||
result[0][0] = result[0][0][1:]
|
||||
try:
|
||||
if not result[0][0]:
|
||||
result[0] = result[0][1:]
|
||||
except IndexError:
|
||||
pass
|
||||
return result, ignore, silent
|
||||
|
||||
def strfunction(self, target, source, env):
|
||||
if not self.cmdstr is None:
|
||||
from SCons.Subst import SUBST_RAW
|
||||
c = env.subst(self.cmdstr, SUBST_RAW, target, source)
|
||||
if c:
|
||||
return c
|
||||
cmd_list, ignore, silent = self.process(target, source, env)
|
||||
if silent:
|
||||
return ''
|
||||
return _string_from_cmd_list(cmd_list[0])
|
||||
|
||||
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.
|
||||
"""
|
||||
from SCons.Subst import escape_list
|
||||
import SCons.Util
|
||||
flatten = SCons.Util.flatten
|
||||
is_String = SCons.Util.is_String
|
||||
is_List = SCons.Util.is_List
|
||||
|
||||
try:
|
||||
shell = env['SHELL']
|
||||
except KeyError:
|
||||
raise SCons.Errors.UserError('Missing SHELL construction variable.')
|
||||
|
||||
try:
|
||||
spawn = env['SPAWN']
|
||||
except KeyError:
|
||||
raise SCons.Errors.UserError('Missing SPAWN construction variable.')
|
||||
else:
|
||||
if is_String(spawn):
|
||||
spawn = env.subst(spawn, raw=1, conv=lambda x: x)
|
||||
|
||||
escape = env.get('ESCAPE', lambda x: x)
|
||||
|
||||
try:
|
||||
ENV = env['ENV']
|
||||
except KeyError:
|
||||
global default_ENV
|
||||
if not default_ENV:
|
||||
import SCons.Environment
|
||||
default_ENV = SCons.Environment.Environment()['ENV']
|
||||
ENV = default_ENV
|
||||
|
||||
# Ensure that the ENV values are all strings:
|
||||
for key, value in ENV.items():
|
||||
if not is_String(value):
|
||||
if is_List(value):
|
||||
# If the value is a list, then we assume it is a
|
||||
# path list, because that's a pretty common list-like
|
||||
# value to stick in an environment variable:
|
||||
value = flatten(value)
|
||||
ENV[key] = string.join(map(str, value), os.pathsep)
|
||||
else:
|
||||
# If it isn't a string or a list, then we just coerce
|
||||
# it to a string, which is the proper way to handle
|
||||
# Dir and File instances and will produce something
|
||||
# reasonable for just about everything else:
|
||||
ENV[key] = str(value)
|
||||
|
||||
cmd_list, ignore, silent = self.process(target, map(rfile, source), env)
|
||||
|
||||
# Use len() to filter out any "command" that's zero-length.
|
||||
for cmd_line in filter(len, cmd_list):
|
||||
# Escape the command line for the interpreter we are using.
|
||||
cmd_line = escape_list(cmd_line, escape)
|
||||
result = spawn(shell, escape, cmd_line[0], cmd_line, ENV)
|
||||
if not ignore and result:
|
||||
return result
|
||||
return 0
|
||||
|
||||
def get_contents(self, target, source, env):
|
||||
"""Return the signature contents of this action's command line.
|
||||
|
||||
This strips $(-$) and everything in between the string,
|
||||
since those parts don't affect signatures.
|
||||
"""
|
||||
from SCons.Subst import SUBST_SIG
|
||||
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, SUBST_SIG, target, source)
|
||||
|
||||
class CommandGeneratorAction(ActionBase):
|
||||
"""Class for command-generator actions."""
|
||||
def __init__(self, generator, *args, **kw):
|
||||
if __debug__: logInstanceCreation(self, 'Action.CommandGeneratorAction')
|
||||
self.generator = generator
|
||||
self.gen_args = args
|
||||
self.gen_kw = kw
|
||||
|
||||
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 = apply(Action, (ret,)+self.gen_args, self.gen_kw)
|
||||
if not gen_cmd:
|
||||
raise SCons.Errors.UserError("Object returned from command generator: %s cannot be used to create an Action." % repr(ret))
|
||||
return gen_cmd
|
||||
|
||||
def __str__(self):
|
||||
try:
|
||||
env = self.presub_env or {}
|
||||
except AttributeError:
|
||||
env = {}
|
||||
act = self._generate([], [], env, 1)
|
||||
return str(act)
|
||||
|
||||
def genstring(self, target, source, env):
|
||||
return self._generate(target, source, env, 1).genstring(target, source, env)
|
||||
|
||||
def __call__(self, target, source, env, exitstatfunc=_null, presub=_null,
|
||||
show=_null, execute=_null, chdir=_null):
|
||||
act = self._generate(target, source, env, 0)
|
||||
return act(target, source, env, exitstatfunc, presub,
|
||||
show, execute, chdir)
|
||||
|
||||
def get_contents(self, target, source, env):
|
||||
"""Return the signature contents of this action's command line.
|
||||
|
||||
This strips $(-$) and everything in between the string,
|
||||
since those parts don't affect signatures.
|
||||
"""
|
||||
return self._generate(target, source, env, 1).get_contents(target, source, env)
|
||||
|
||||
|
||||
|
||||
# A LazyAction is a kind of hybrid generator and command action for
|
||||
# strings of the form "$VAR". These strings normally expand to other
|
||||
# strings (think "$CCCOM" to "$CC -c -o $TARGET $SOURCE"), but we also
|
||||
# want to be able to replace them with functions in the construction
|
||||
# environment. Consequently, we want lazy evaluation and creation of
|
||||
# an Action in the case of the function, but that's overkill in the more
|
||||
# normal case of expansion to other strings.
|
||||
#
|
||||
# So we do this with a subclass that's both a generator *and*
|
||||
# a command action. The overridden methods all do a quick check
|
||||
# of the construction variable, and if it's a string we just call
|
||||
# the corresponding CommandAction method to do the heavy lifting.
|
||||
# If not, then we call the same-named CommandGeneratorAction method.
|
||||
# The CommandGeneratorAction methods work by using the overridden
|
||||
# _generate() method, that is, our own way of handling "generation" of
|
||||
# an action based on what's in the construction variable.
|
||||
|
||||
class LazyAction(CommandGeneratorAction, CommandAction):
|
||||
|
||||
def __init__(self, var, *args, **kw):
|
||||
if __debug__: logInstanceCreation(self, 'Action.LazyAction')
|
||||
apply(CommandAction.__init__, (self, '$'+var)+args, kw)
|
||||
self.var = SCons.Util.to_String(var)
|
||||
self.gen_args = args
|
||||
self.gen_kw = kw
|
||||
|
||||
def get_parent_class(self, env):
|
||||
c = env.get(self.var)
|
||||
if SCons.Util.is_String(c) and not '\n' in c:
|
||||
return CommandAction
|
||||
return CommandGeneratorAction
|
||||
|
||||
def _generate_cache(self, env):
|
||||
c = env.get(self.var, '')
|
||||
gen_cmd = apply(Action, (c,)+self.gen_args, self.gen_kw)
|
||||
if not gen_cmd:
|
||||
raise SCons.Errors.UserError("$%s value %s cannot be used to create an Action." % (self.var, repr(c)))
|
||||
return gen_cmd
|
||||
|
||||
def _generate(self, target, source, env, for_signature):
|
||||
return self._generate_cache(env)
|
||||
|
||||
def __call__(self, target, source, env, *args, **kw):
|
||||
args = (self, target, source, env) + args
|
||||
c = self.get_parent_class(env)
|
||||
return apply(c.__call__, args, kw)
|
||||
|
||||
def get_contents(self, target, source, env):
|
||||
c = self.get_parent_class(env)
|
||||
return c.get_contents(self, target, source, env)
|
||||
|
||||
|
||||
|
||||
class FunctionAction(_ActionAction):
|
||||
"""Class for Python function actions."""
|
||||
|
||||
def __init__(self, execfunction, cmdstr=_null, *args, **kw):
|
||||
if __debug__: logInstanceCreation(self, 'Action.FunctionAction')
|
||||
|
||||
if not cmdstr is _null:
|
||||
if callable(cmdstr):
|
||||
args = (cmdstr,)+args
|
||||
elif not (cmdstr is None or SCons.Util.is_String(cmdstr)):
|
||||
raise SCons.Errors.UserError(\
|
||||
'Invalid function display variable type. ' \
|
||||
'You must either pass a string or a callback which ' \
|
||||
'accepts (target, source, env) as parameters.')
|
||||
|
||||
self.execfunction = execfunction
|
||||
apply(_ActionAction.__init__, (self,)+args, kw)
|
||||
self.varlist = kw.get('varlist', [])
|
||||
self.cmdstr = cmdstr
|
||||
|
||||
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):
|
||||
if self.cmdstr is None:
|
||||
return None
|
||||
if not self.cmdstr is _null:
|
||||
from SCons.Subst import SUBST_RAW
|
||||
c = env.subst(self.cmdstr, SUBST_RAW, target, source)
|
||||
if c:
|
||||
return c
|
||||
def array(a):
|
||||
def quote(s):
|
||||
return '"' + str(s) + '"'
|
||||
return '[' + string.join(map(quote, a), ", ") + ']'
|
||||
try:
|
||||
strfunc = self.execfunction.strfunction
|
||||
except AttributeError:
|
||||
pass
|
||||
else:
|
||||
if strfunc is None:
|
||||
return None
|
||||
if callable(strfunc):
|
||||
return strfunc(target, source, env)
|
||||
name = self.function_name()
|
||||
tstr = array(target)
|
||||
sstr = array(source)
|
||||
return "%s(%s, %s)" % (name, tstr, sstr)
|
||||
|
||||
def __str__(self):
|
||||
name = self.function_name()
|
||||
if name == 'ActionCaller':
|
||||
return str(self.execfunction)
|
||||
return "%s(target, source, env)" % name
|
||||
|
||||
def execute(self, target, source, env):
|
||||
rsources = map(rfile, source)
|
||||
try:
|
||||
result = self.execfunction(target=target, source=rsources, env=env)
|
||||
except EnvironmentError, e:
|
||||
# If an IOError/OSError happens, raise a BuildError.
|
||||
# Report the name of the file or directory that caused the
|
||||
# error, which might be different from the target being built
|
||||
# (for example, failure to create the directory in which the
|
||||
# target file will appear).
|
||||
try: filename = e.filename
|
||||
except AttributeError: filename = None
|
||||
raise SCons.Errors.BuildError(node=target,
|
||||
errstr=e.strerror,
|
||||
filename=filename)
|
||||
return result
|
||||
|
||||
def get_contents(self, target, source, env):
|
||||
"""Return the signature contents of this callable action.
|
||||
|
||||
By providing direct access to the code object of the
|
||||
function, Python makes this extremely easy. Hooray!
|
||||
|
||||
Unfortunately, older versions of Python include line
|
||||
number indications in the compiled byte code. Boo!
|
||||
So we remove the line number byte codes to prevent
|
||||
recompilations from moving a Python function.
|
||||
"""
|
||||
execfunction = self.execfunction
|
||||
try:
|
||||
# Test if execfunction is a function.
|
||||
code = execfunction.func_code.co_code
|
||||
except AttributeError:
|
||||
try:
|
||||
# Test if execfunction is a method.
|
||||
code = execfunction.im_func.func_code.co_code
|
||||
except AttributeError:
|
||||
try:
|
||||
# Test if execfunction is a callable object.
|
||||
code = execfunction.__call__.im_func.func_code.co_code
|
||||
except AttributeError:
|
||||
try:
|
||||
# See if execfunction will do the heavy lifting for us.
|
||||
gc = self.execfunction.get_contents
|
||||
except AttributeError:
|
||||
# This is weird, just do the best we can.
|
||||
contents = str(self.execfunction)
|
||||
else:
|
||||
contents = gc(target, source, env)
|
||||
else:
|
||||
contents = str(code)
|
||||
else:
|
||||
contents = str(code)
|
||||
else:
|
||||
contents = str(code)
|
||||
contents = remove_set_lineno_codes(contents)
|
||||
return contents + env.subst(string.join(map(lambda v: '${'+v+'}',
|
||||
self.varlist)))
|
||||
|
||||
class ListAction(ActionBase):
|
||||
"""Class for lists of other actions."""
|
||||
def __init__(self, list):
|
||||
if __debug__: logInstanceCreation(self, 'Action.ListAction')
|
||||
def list_of_actions(x):
|
||||
if isinstance(x, ActionBase):
|
||||
return x
|
||||
return Action(x)
|
||||
self.list = map(list_of_actions, list)
|
||||
|
||||
def genstring(self, target, source, env):
|
||||
return string.join(map(lambda a, t=target, s=source, e=env:
|
||||
a.genstring(t, s, e),
|
||||
self.list),
|
||||
'\n')
|
||||
|
||||
def __str__(self):
|
||||
return string.join(map(str, self.list), '\n')
|
||||
|
||||
def presub_lines(self, env):
|
||||
return SCons.Util.flatten(map(lambda a, env=env:
|
||||
a.presub_lines(env),
|
||||
self.list))
|
||||
|
||||
def get_contents(self, target, source, env):
|
||||
"""Return the signature contents of this action list.
|
||||
|
||||
Simple concatenation of the signatures of the elements.
|
||||
"""
|
||||
return string.join(map(lambda x, t=target, s=source, e=env:
|
||||
x.get_contents(t, s, e),
|
||||
self.list),
|
||||
"")
|
||||
|
||||
def __call__(self, target, source, env, exitstatfunc=_null, presub=_null,
|
||||
show=_null, execute=_null, chdir=_null):
|
||||
for act in self.list:
|
||||
stat = act(target, source, env, exitstatfunc, presub,
|
||||
show, execute, chdir)
|
||||
if stat:
|
||||
return stat
|
||||
return 0
|
||||
|
||||
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):
|
||||
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)
|
||||
contents = remove_set_lineno_codes(contents)
|
||||
return contents
|
||||
def subst(self, s, target, source, env):
|
||||
# Special-case hack: Let a custom function wrapped in an
|
||||
# ActionCaller get at the environment through which the action
|
||||
# was called by using this hard-coded value as a special return.
|
||||
if s == '$__env__':
|
||||
return env
|
||||
else:
|
||||
return env.subst(s, 0, target, source)
|
||||
def subst_args(self, target, source, env):
|
||||
return map(lambda x, self=self, t=target, s=source, e=env:
|
||||
self.subst(x, t, s, e),
|
||||
self.args)
|
||||
def subst_kw(self, target, source, env):
|
||||
kw = {}
|
||||
for key in self.kw.keys():
|
||||
kw[key] = self.subst(self.kw[key], target, source, env)
|
||||
return kw
|
||||
def __call__(self, target, source, env):
|
||||
args = self.subst_args(target, source, env)
|
||||
kw = self.subst_kw(target, source, env)
|
||||
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)
|
||||
def __str__(self):
|
||||
return apply(self.parent.strfunc, self.args, self.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)
|
||||
action = Action(ac, strfunction=ac.strfunction)
|
||||
return action
|
|
@ -16,20 +16,9 @@ building new types of files in their configurations, without having to
|
|||
dive any deeper into this subsystem.
|
||||
|
||||
The base class here is BuilderBase. This is a concrete base class which
|
||||
does, in fact, represent most Builder objects that we (or users) create.
|
||||
does, in fact, represent the Builder objects that we (or users) create.
|
||||
|
||||
There is (at present) one subclasses:
|
||||
|
||||
MultiStepBuilder
|
||||
|
||||
This is a Builder that knows how to "chain" Builders so that
|
||||
users can specify a source file that requires multiple steps
|
||||
to turn into a target file. A canonical example is building a
|
||||
program from yacc input file, which requires invoking a builder
|
||||
to turn the .y into a .c, the .c into a .o, and the .o into an
|
||||
executable program.
|
||||
|
||||
There is also two proxies that look like Builders:
|
||||
There is also a proxy that looks like a Builder:
|
||||
|
||||
CompositeBuilder
|
||||
|
||||
|
@ -39,11 +28,6 @@ There is also two proxies that look like Builders:
|
|||
(compilers, compile options) for different flavors of source
|
||||
files.
|
||||
|
||||
ListBuilder
|
||||
|
||||
This proxies for a Builder *invocation* where the target
|
||||
is a list of files, not a single file.
|
||||
|
||||
Builders and their proxies have the following public interface methods
|
||||
used by other modules:
|
||||
|
||||
|
@ -95,7 +79,7 @@ There are the following methods for internal use within this module:
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -117,7 +101,9 @@ There are the following methods for internal use within this module:
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Builder.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Builder.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import SCons.compat
|
||||
|
||||
import UserDict
|
||||
import UserList
|
||||
|
@ -126,6 +112,8 @@ import SCons.Action
|
|||
from SCons.Debug import logInstanceCreation
|
||||
from SCons.Errors import InternalError, UserError
|
||||
import SCons.Executor
|
||||
import SCons.Memoize
|
||||
import SCons.Node
|
||||
import SCons.Node.FS
|
||||
import SCons.Util
|
||||
import SCons.Warnings
|
||||
|
@ -142,6 +130,10 @@ class DictCmdGenerator(SCons.Util.Selector):
|
|||
to return the proper action based on the file suffix of
|
||||
the source file."""
|
||||
|
||||
def __init__(self, dict=None, source_ext_match=1):
|
||||
SCons.Util.Selector.__init__(self, dict)
|
||||
self.source_ext_match = source_ext_match
|
||||
|
||||
def src_suffixes(self):
|
||||
return self.keys()
|
||||
|
||||
|
@ -151,12 +143,18 @@ class DictCmdGenerator(SCons.Util.Selector):
|
|||
self[suffix] = action
|
||||
|
||||
def __call__(self, target, source, env, for_signature):
|
||||
if not source:
|
||||
return []
|
||||
|
||||
if self.source_ext_match:
|
||||
ext = None
|
||||
for src in map(str, source):
|
||||
my_ext = SCons.Util.splitext(src)[1]
|
||||
if ext and my_ext != ext:
|
||||
raise UserError("While building `%s' from `%s': Cannot build multiple sources with different extensions: %s, %s" % (repr(map(str, target)), src, ext, my_ext))
|
||||
ext = my_ext
|
||||
else:
|
||||
ext = SCons.Util.splitext(str(source[0]))[1]
|
||||
|
||||
if not ext:
|
||||
raise UserError("While building `%s': Cannot deduce file extension from source files: %s" % (repr(map(str, target)), repr(map(str, source))))
|
||||
|
@ -166,7 +164,8 @@ class DictCmdGenerator(SCons.Util.Selector):
|
|||
except KeyError, e:
|
||||
raise UserError("Ambiguous suffixes after environment substitution: %s == %s == %s" % (e[0], e[1], e[2]))
|
||||
if ret is None:
|
||||
raise UserError("While building `%s': Don't know how to build a file with suffix `%s'." % (repr(map(str, target)), ext))
|
||||
raise UserError("While building `%s' from `%s': Don't know how to build from a source file with suffix `%s'. Expected a suffix in this list: %s." % \
|
||||
(repr(map(str, target)), repr(map(str, source)), ext, repr(self.keys())))
|
||||
return ret
|
||||
|
||||
class CallableSelector(SCons.Util.Selector):
|
||||
|
@ -214,25 +213,22 @@ class OverrideWarner(UserDict.UserDict):
|
|||
"""A class for warning about keyword arguments that we use as
|
||||
overrides in a Builder call.
|
||||
|
||||
This class exists to handle the fact that a single MultiStepBuilder
|
||||
call can actually invoke multiple builders as a result of a single
|
||||
user-level Builder call. This class only emits the warnings once,
|
||||
no matter how many Builders are invoked.
|
||||
This class exists to handle the fact that a single Builder call
|
||||
can actually invoke multiple builders. This class only emits the
|
||||
warnings once, no matter how many Builders are invoked.
|
||||
"""
|
||||
def __init__(self, dict):
|
||||
UserDict.UserDict.__init__(self, dict)
|
||||
if __debug__: logInstanceCreation(self, 'Builder.OverrideWarner')
|
||||
self.already_warned = None
|
||||
def warn(self):
|
||||
if self.already_warned:
|
||||
return
|
||||
for k in self.keys():
|
||||
try:
|
||||
if misleading_keywords.has_key(k):
|
||||
alt = misleading_keywords[k]
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
SCons.Warnings.warn(SCons.Warnings.MisleadingKeywordsWarning,
|
||||
"Did you mean to use `%s' instead of `%s'?" % (alt, k))
|
||||
msg = "Did you mean to use `%s' instead of `%s'?" % (alt, k)
|
||||
SCons.Warnings.warn(SCons.Warnings.MisleadingKeywordsWarning, msg)
|
||||
self.already_warned = 1
|
||||
|
||||
def Builder(**kw):
|
||||
|
@ -241,12 +237,18 @@ def Builder(**kw):
|
|||
if kw.has_key('generator'):
|
||||
if kw.has_key('action'):
|
||||
raise UserError, "You must not specify both an action and a generator."
|
||||
kw['action'] = SCons.Action.CommandGenerator(kw['generator'])
|
||||
kw['action'] = SCons.Action.CommandGeneratorAction(kw['generator'])
|
||||
del kw['generator']
|
||||
elif kw.has_key('action') and SCons.Util.is_Dict(kw['action']):
|
||||
composite = DictCmdGenerator(kw['action'])
|
||||
kw['action'] = SCons.Action.CommandGenerator(composite)
|
||||
elif kw.has_key('action'):
|
||||
source_ext_match = kw.get('source_ext_match', 1)
|
||||
if kw.has_key('source_ext_match'):
|
||||
del kw['source_ext_match']
|
||||
if SCons.Util.is_Dict(kw['action']):
|
||||
composite = DictCmdGenerator(kw['action'], source_ext_match)
|
||||
kw['action'] = SCons.Action.CommandGeneratorAction(composite)
|
||||
kw['src_suffix'] = composite.src_suffixes()
|
||||
else:
|
||||
kw['action'] = SCons.Action.Action(kw['action'])
|
||||
|
||||
if kw.has_key('emitter'):
|
||||
emitter = kw['emitter']
|
||||
|
@ -264,100 +266,51 @@ def Builder(**kw):
|
|||
elif SCons.Util.is_List(emitter):
|
||||
kw['emitter'] = ListEmitter(emitter)
|
||||
|
||||
if kw.has_key('src_builder'):
|
||||
ret = apply(MultiStepBuilder, (), kw)
|
||||
else:
|
||||
ret = apply(BuilderBase, (), kw)
|
||||
result = apply(BuilderBase, (), kw)
|
||||
|
||||
if not composite is None:
|
||||
ret = CompositeBuilder(ret, composite)
|
||||
result = CompositeBuilder(result, composite)
|
||||
|
||||
return ret
|
||||
return result
|
||||
|
||||
def _init_nodes(builder, env, overrides, tlist, slist):
|
||||
"""Initialize lists of target and source nodes with all of
|
||||
the proper Builder information.
|
||||
def _node_errors(builder, env, tlist, slist):
|
||||
"""Validate that the lists of target and source nodes are
|
||||
legal for this builder and environment. Raise errors or
|
||||
issue warnings as appropriate.
|
||||
"""
|
||||
|
||||
# First, figure out if there are any errors in the way the targets
|
||||
# were specified.
|
||||
for t in tlist:
|
||||
if t.side_effect:
|
||||
raise UserError, "Multiple ways to build the same target were specified for: %s" % str(t)
|
||||
if t.has_builder():
|
||||
raise UserError, "Multiple ways to build the same target were specified for: %s" % t
|
||||
if t.has_explicit_builder():
|
||||
if not t.env is None and not t.env is env:
|
||||
t_contents = t.builder.action.get_contents(tlist, slist, t.env)
|
||||
contents = t.builder.action.get_contents(tlist, slist, env)
|
||||
action = t.builder.action
|
||||
t_contents = action.get_contents(tlist, slist, t.env)
|
||||
contents = action.get_contents(tlist, slist, env)
|
||||
|
||||
if t_contents == contents:
|
||||
SCons.Warnings.warn(SCons.Warnings.DuplicateEnvironmentWarning,
|
||||
"Two different environments were specified for target %s,\n\tbut they appear to have the same action: %s"%(str(t), t.builder.action.strfunction(tlist, slist, t.env)))
|
||||
|
||||
msg = "Two different environments were specified for target %s,\n\tbut they appear to have the same action: %s" % (t, action.genstring(tlist, slist, t.env))
|
||||
SCons.Warnings.warn(SCons.Warnings.DuplicateEnvironmentWarning, msg)
|
||||
else:
|
||||
raise UserError, "Two environments with different actions were specified for the same target: %s"%str(t)
|
||||
|
||||
elif t.overrides != overrides:
|
||||
raise UserError, "Two different sets of overrides were specified for the same target: %s"%str(t)
|
||||
|
||||
elif builder.target_scanner and t.target_scanner and builder.target_scanner != t.target_scanner:
|
||||
raise UserError, "Two different scanners were specified for the same target: %s"%str(t)
|
||||
|
||||
msg = "Two environments with different actions were specified for the same target: %s" % t
|
||||
raise UserError, msg
|
||||
if builder.multi:
|
||||
if t.builder != builder:
|
||||
if isinstance(t.builder, ListBuilder) and isinstance(builder, ListBuilder) and t.builder.builder == builder.builder:
|
||||
raise UserError, "Two different target sets have a target in common: %s"%str(t)
|
||||
else:
|
||||
raise UserError, "Two different builders (%s and %s) were specified for the same target: %s"%(t.builder.get_name(env), builder.get_name(env), str(t))
|
||||
msg = "Two different builders (%s and %s) were specified for the same target: %s" % (t.builder.get_name(env), builder.get_name(env), t)
|
||||
raise UserError, msg
|
||||
if t.get_executor().targets != tlist:
|
||||
msg = "Two different target lists have a target in common: %s (from %s and from %s)" % (t, map(str, t.get_executor().targets), map(str, tlist))
|
||||
raise UserError, msg
|
||||
elif t.sources != slist:
|
||||
raise UserError, "Multiple ways to build the same target were specified for: %s" % str(t)
|
||||
msg = "Multiple ways to build the same target were specified for: %s (from %s and from %s)" % (t, map(str, t.sources), map(str, slist))
|
||||
raise UserError, msg
|
||||
|
||||
if builder.single_source:
|
||||
if len(slist) > 1:
|
||||
raise UserError, "More than one source given for single-source builder: targets=%s sources=%s" % (map(str,tlist), map(str,slist))
|
||||
|
||||
# The targets are fine, so find or make the appropriate Executor to
|
||||
# build this particular list of targets from this particular list of
|
||||
# sources.
|
||||
executor = None
|
||||
if builder.multi:
|
||||
try:
|
||||
executor = tlist[0].get_executor(create = 0)
|
||||
except AttributeError:
|
||||
pass
|
||||
else:
|
||||
executor.add_sources(slist)
|
||||
if executor is None:
|
||||
executor = SCons.Executor.Executor(builder.action,
|
||||
env or builder.env,
|
||||
[builder.overrides, overrides],
|
||||
tlist,
|
||||
slist)
|
||||
|
||||
# Now set up the relevant information in the target Nodes themselves.
|
||||
for t in tlist:
|
||||
t.overrides = overrides
|
||||
t.cwd = SCons.Node.FS.default_fs.getcwd()
|
||||
t.builder_set(builder)
|
||||
t.env_set(env)
|
||||
t.add_source(slist)
|
||||
t.set_executor(executor)
|
||||
if builder.target_scanner:
|
||||
t.target_scanner = builder.target_scanner
|
||||
if t.source_scanner is None:
|
||||
t.source_scanner = builder.source_scanner
|
||||
|
||||
# Add backup source scanners from the environment to the source
|
||||
# nodes. This may not be necessary if the node will have a real
|
||||
# source scanner added later (which is why these are the "backup"
|
||||
# source scanners, not the real ones), but because source nodes may
|
||||
# be used multiple times for different targets, it ends up being
|
||||
# more efficient to do this calculation once here, as opposed to
|
||||
# delaying it until later when we potentially have to calculate it
|
||||
# over and over and over.
|
||||
for s in slist:
|
||||
if s.source_scanner is None and s.backup_source_scanner is None:
|
||||
s.backup_source_scanner = env.get_scanner(s.scanner_key())
|
||||
|
||||
class EmitterProxy:
|
||||
"""This is a callable class that can act as a
|
||||
Builder emitter. It holds on to a string that
|
||||
|
@ -393,28 +346,37 @@ class BuilderBase:
|
|||
nodes (files) from input nodes (files).
|
||||
"""
|
||||
|
||||
if SCons.Memoize.use_memoizer:
|
||||
__metaclass__ = SCons.Memoize.Memoized_Metaclass
|
||||
|
||||
memoizer_counters = []
|
||||
|
||||
def __init__(self, action = None,
|
||||
prefix = '',
|
||||
suffix = '',
|
||||
src_suffix = '',
|
||||
target_factory = SCons.Node.FS.default_fs.File,
|
||||
source_factory = SCons.Node.FS.default_fs.File,
|
||||
target_factory = None,
|
||||
source_factory = None,
|
||||
target_scanner = None,
|
||||
source_scanner = None,
|
||||
emitter = None,
|
||||
multi = 0,
|
||||
env = None,
|
||||
single_source = 0,
|
||||
name = None,
|
||||
chdir = _null,
|
||||
is_explicit = 1,
|
||||
src_builder = [],
|
||||
**overrides):
|
||||
if __debug__: logInstanceCreation(self, 'BuilderBase')
|
||||
self.action = SCons.Action.Action(action)
|
||||
if __debug__: logInstanceCreation(self, 'Builder.BuilderBase')
|
||||
self._memo = {}
|
||||
self.action = action
|
||||
self.multi = multi
|
||||
if SCons.Util.is_Dict(prefix):
|
||||
prefix = CallableSelector(prefix)
|
||||
self.prefix = prefix
|
||||
if SCons.Util.is_Dict(suffix):
|
||||
suffix = CallableSelector(suffix)
|
||||
self.suffix = suffix
|
||||
self.env = env
|
||||
self.single_source = single_source
|
||||
if overrides.has_key('overrides'):
|
||||
|
@ -423,8 +385,14 @@ class BuilderBase:
|
|||
"\tspecify the items as keyword arguments to the Builder() call instead.")
|
||||
overrides.update(overrides['overrides'])
|
||||
del overrides['overrides']
|
||||
if overrides.has_key('scanner'):
|
||||
SCons.Warnings.warn(SCons.Warnings.DeprecatedWarning,
|
||||
"The \"scanner\" keyword to Builder() creation has been deprecated;\n"
|
||||
"\tuse: source_scanner or target_scanner as appropriate.")
|
||||
del overrides['scanner']
|
||||
self.overrides = overrides
|
||||
|
||||
self.set_suffix(suffix)
|
||||
self.set_src_suffix(src_suffix)
|
||||
|
||||
self.target_factory = target_factory
|
||||
|
@ -434,6 +402,19 @@ class BuilderBase:
|
|||
|
||||
self.emitter = emitter
|
||||
|
||||
# Optional Builder name should only be used for Builders
|
||||
# that don't get attached to construction environments.
|
||||
if name:
|
||||
self.name = name
|
||||
self.executor_kw = {}
|
||||
if not chdir is _null:
|
||||
self.executor_kw['chdir'] = chdir
|
||||
self.is_explicit = is_explicit
|
||||
|
||||
if not SCons.Util.is_List(src_builder):
|
||||
src_builder = [ src_builder ]
|
||||
self.src_builder = src_builder
|
||||
|
||||
def __nonzero__(self):
|
||||
raise InternalError, "Do not test for the Node.builder attribute directly; use Node.has_builder() instead"
|
||||
|
||||
|
@ -442,21 +423,51 @@ class BuilderBase:
|
|||
|
||||
Look at the BUILDERS variable of env, expecting it to be a
|
||||
dictionary containing this Builder, and return the key of the
|
||||
dictionary."""
|
||||
dictionary. If there's no key, then return a directly-configured
|
||||
name (if there is one) or the name of the class (by default)."""
|
||||
|
||||
try:
|
||||
index = env['BUILDERS'].values().index(self)
|
||||
return env['BUILDERS'].keys()[index]
|
||||
except (AttributeError, KeyError, ValueError):
|
||||
except (AttributeError, KeyError, TypeError, ValueError):
|
||||
try:
|
||||
return self.name
|
||||
except AttributeError:
|
||||
return str(self.__class__)
|
||||
|
||||
def __cmp__(self, other):
|
||||
return cmp(self.__dict__, other.__dict__)
|
||||
|
||||
def splitext(self, path):
|
||||
def splitext(self, path, env=None):
|
||||
if not env:
|
||||
env = self.env
|
||||
if env:
|
||||
matchsuf = filter(lambda S,path=path: path[-len(S):] == S,
|
||||
self.src_suffixes(env))
|
||||
if matchsuf:
|
||||
suf = max(map(None, map(len, matchsuf), matchsuf))[1]
|
||||
return [path[:-len(suf)], path[-len(suf):]]
|
||||
return SCons.Util.splitext(path)
|
||||
|
||||
def _create_nodes(self, env, overwarn, target = None, source = None):
|
||||
def get_single_executor(self, env, tlist, slist, executor_kw):
|
||||
if not self.action:
|
||||
raise UserError, "Builder %s must have an action to build %s."%(self.get_name(env or self.env), map(str,tlist))
|
||||
return self.action.get_executor(env or self.env,
|
||||
[], # env already has overrides
|
||||
tlist,
|
||||
slist,
|
||||
executor_kw)
|
||||
|
||||
def get_multi_executor(self, env, tlist, slist, executor_kw):
|
||||
try:
|
||||
executor = tlist[0].get_executor(create = 0)
|
||||
except (AttributeError, IndexError):
|
||||
return self.get_single_executor(env, tlist, slist, executor_kw)
|
||||
else:
|
||||
executor.add_sources(slist)
|
||||
return executor
|
||||
|
||||
def _create_nodes(self, env, target = None, source = None):
|
||||
"""Create and return lists of target and source nodes.
|
||||
"""
|
||||
def _adjustixes(files, pre, suf):
|
||||
|
@ -472,14 +483,13 @@ class BuilderBase:
|
|||
result.append(f)
|
||||
return result
|
||||
|
||||
overwarn.warn()
|
||||
|
||||
env = env.Override(overwarn.data)
|
||||
|
||||
src_suf = self.get_src_suffix(env)
|
||||
|
||||
target_factory = env.get_factory(self.target_factory)
|
||||
source_factory = env.get_factory(self.source_factory)
|
||||
|
||||
source = _adjustixes(source, None, src_suf)
|
||||
slist = env.arg2nodes(source, self.source_factory)
|
||||
slist = env.arg2nodes(source, source_factory)
|
||||
|
||||
pre = self.get_prefix(env, slist)
|
||||
suf = self.get_suffix(env, slist)
|
||||
|
@ -489,10 +499,14 @@ class BuilderBase:
|
|||
t_from_s = slist[0].target_from_source
|
||||
except AttributeError:
|
||||
raise UserError("Do not know how to create a target from source `%s'" % slist[0])
|
||||
tlist = [ t_from_s(pre, suf, self.splitext) ]
|
||||
except IndexError:
|
||||
tlist = []
|
||||
else:
|
||||
splitext = lambda S,self=self,env=env: self.splitext(S,env)
|
||||
tlist = [ t_from_s(pre, suf, splitext) ]
|
||||
else:
|
||||
target = _adjustixes(target, pre, suf)
|
||||
tlist = env.arg2nodes(target, self.target_factory)
|
||||
tlist = env.arg2nodes(target, target_factory)
|
||||
|
||||
if self.emitter:
|
||||
# The emitter is going to do str(node), but because we're
|
||||
|
@ -503,58 +517,97 @@ class BuilderBase:
|
|||
new_targets = []
|
||||
for t in tlist:
|
||||
if not t.is_derived():
|
||||
t.builder = self
|
||||
t.builder_set(self)
|
||||
new_targets.append(t)
|
||||
|
||||
target, source = self.emitter(target=tlist, source=slist, env=env)
|
||||
|
||||
# Now delete the temporary builders that we attached to any
|
||||
# new targets, so that _init_nodes() doesn't do weird stuff
|
||||
# new targets, so that _node_errors() doesn't do weird stuff
|
||||
# to them because it thinks they already have builders.
|
||||
for t in new_targets:
|
||||
if t.builder is self:
|
||||
# Only delete the temporary builder if the emitter
|
||||
# didn't change it on us.
|
||||
t.builder = None
|
||||
t.builder_set(None)
|
||||
|
||||
# Have to call arg2nodes yet again, since it is legal for
|
||||
# emitters to spit out strings as well as Node instances.
|
||||
slist = env.arg2nodes(source, self.source_factory)
|
||||
tlist = env.arg2nodes(target, self.target_factory)
|
||||
tlist = env.arg2nodes(target, target_factory)
|
||||
slist = env.arg2nodes(source, source_factory)
|
||||
|
||||
return tlist, slist
|
||||
|
||||
def _execute(self, env, target = None, source = _null, overwarn={}):
|
||||
if source is _null:
|
||||
source = target
|
||||
target = None
|
||||
def _execute(self, env, target, source, overwarn={}, executor_kw={}):
|
||||
# We now assume that target and source are lists or None.
|
||||
if self.src_builder:
|
||||
source = self.src_builder_sources(env, source, overwarn)
|
||||
|
||||
if(self.single_source and
|
||||
SCons.Util.is_List(source) and
|
||||
len(source) > 1 and
|
||||
target is None):
|
||||
if self.single_source and len(source) > 1 and target is None:
|
||||
result = []
|
||||
if target is None: target = [None]*len(source)
|
||||
for k in range(len(source)):
|
||||
t = self._execute(env, target[k], source[k], overwarn)
|
||||
if SCons.Util.is_List(t):
|
||||
result.extend(t)
|
||||
else:
|
||||
result.append(t)
|
||||
for tgt, src in zip(target, source):
|
||||
if not tgt is None: tgt = [tgt]
|
||||
if not src is None: src = [src]
|
||||
result.extend(self._execute(env, tgt, src, overwarn))
|
||||
return result
|
||||
|
||||
tlist, slist = self._create_nodes(env, overwarn, target, source)
|
||||
overwarn.warn()
|
||||
|
||||
if len(tlist) == 1:
|
||||
builder = self
|
||||
tlist, slist = self._create_nodes(env, target, source)
|
||||
|
||||
# Check for errors with the specified target/source lists.
|
||||
_node_errors(self, env, tlist, slist)
|
||||
|
||||
# The targets are fine, so find or make the appropriate Executor to
|
||||
# build this particular list of targets from this particular list of
|
||||
# sources.
|
||||
if self.multi:
|
||||
get_executor = self.get_multi_executor
|
||||
else:
|
||||
builder = ListBuilder(self, env, tlist)
|
||||
_init_nodes(builder, env, overwarn.data, tlist, slist)
|
||||
get_executor = self.get_single_executor
|
||||
executor = get_executor(env, tlist, slist, executor_kw)
|
||||
|
||||
return tlist
|
||||
# Now set up the relevant information in the target Nodes themselves.
|
||||
for t in tlist:
|
||||
t.cwd = env.fs.getcwd()
|
||||
t.builder_set(self)
|
||||
t.env_set(env)
|
||||
t.add_source(slist)
|
||||
t.set_executor(executor)
|
||||
t.set_explicit(self.is_explicit)
|
||||
|
||||
def __call__(self, env, target = None, source = _null, **kw):
|
||||
return self._execute(env, target, source, OverrideWarner(kw))
|
||||
return SCons.Node.NodeList(tlist)
|
||||
|
||||
def __call__(self, env, target=None, source=None, chdir=_null, **kw):
|
||||
# We now assume that target and source are lists or None.
|
||||
# The caller (typically Environment.BuilderWrapper) is
|
||||
# responsible for converting any scalar values to lists.
|
||||
if chdir is _null:
|
||||
ekw = self.executor_kw
|
||||
else:
|
||||
ekw = self.executor_kw.copy()
|
||||
ekw['chdir'] = chdir
|
||||
if kw:
|
||||
if kw.has_key('srcdir'):
|
||||
def prependDirIfRelative(f, srcdir=kw['srcdir']):
|
||||
import os.path
|
||||
if SCons.Util.is_String(f) and not os.path.isabs(f):
|
||||
f = os.path.join(srcdir, f)
|
||||
return f
|
||||
if not SCons.Util.is_List(source):
|
||||
source = [source]
|
||||
source = map(prependDirIfRelative, source)
|
||||
del kw['srcdir']
|
||||
if self.overrides:
|
||||
env_kw = self.overrides.copy()
|
||||
env_kw.update(kw)
|
||||
else:
|
||||
env_kw = kw
|
||||
else:
|
||||
env_kw = self.overrides
|
||||
env = env.Override(env_kw)
|
||||
return self._execute(env, target, source, OverrideWarner(kw), ekw)
|
||||
|
||||
def adjust_suffix(self, suff):
|
||||
if suff and not suff[0] in [ '.', '_', '$' ]:
|
||||
|
@ -567,24 +620,25 @@ class BuilderBase:
|
|||
prefix = prefix(env, sources)
|
||||
return env.subst(prefix)
|
||||
|
||||
def set_suffix(self, suffix):
|
||||
if not callable(suffix):
|
||||
suffix = self.adjust_suffix(suffix)
|
||||
self.suffix = suffix
|
||||
|
||||
def get_suffix(self, env, sources=[]):
|
||||
suffix = self.suffix
|
||||
if callable(suffix):
|
||||
suffix = suffix(env, sources)
|
||||
else:
|
||||
suffix = self.adjust_suffix(suffix)
|
||||
return env.subst(suffix)
|
||||
|
||||
def src_suffixes(self, env):
|
||||
return map(lambda x, s=self, e=env: e.subst(s.adjust_suffix(x)),
|
||||
self.src_suffix)
|
||||
|
||||
def set_src_suffix(self, src_suffix):
|
||||
if not src_suffix:
|
||||
src_suffix = []
|
||||
elif not SCons.Util.is_List(src_suffix):
|
||||
src_suffix = [ src_suffix ]
|
||||
self.src_suffix = src_suffix
|
||||
adjust = lambda suf, s=self: \
|
||||
callable(suf) and suf or s.adjust_suffix(suf)
|
||||
self.src_suffix = map(adjust, src_suffix)
|
||||
|
||||
def get_src_suffix(self, env):
|
||||
"""Get the first src_suffix in the list of src_suffixes."""
|
||||
|
@ -610,144 +664,166 @@ class BuilderBase:
|
|||
"""
|
||||
self.emitter[suffix] = emitter
|
||||
|
||||
class ListBuilder(SCons.Util.Proxy):
|
||||
"""A Proxy to support building an array of targets (for example,
|
||||
foo.o and foo.h from foo.y) from a single Action execution.
|
||||
def add_src_builder(self, builder):
|
||||
"""
|
||||
Add a new Builder to the list of src_builders.
|
||||
|
||||
def __init__(self, builder, env, tlist):
|
||||
if __debug__: logInstanceCreation(self)
|
||||
SCons.Util.Proxy.__init__(self, builder)
|
||||
self.builder = builder
|
||||
self.target_scanner = builder.target_scanner
|
||||
self.source_scanner = builder.source_scanner
|
||||
self.env = env
|
||||
self.tlist = tlist
|
||||
self.multi = builder.multi
|
||||
self.single_source = builder.single_source
|
||||
|
||||
def targets(self, node):
|
||||
"""Return the list of targets for this builder instance.
|
||||
This requires wiping out cached values so that the computed
|
||||
lists of source suffixes get re-calculated.
|
||||
"""
|
||||
return self.tlist
|
||||
self._memo = {}
|
||||
self.src_builder.append(builder)
|
||||
|
||||
def __cmp__(self, other):
|
||||
return cmp(self.__dict__, other.__dict__)
|
||||
|
||||
def get_name(self, env):
|
||||
"""Attempts to get the name of the Builder."""
|
||||
|
||||
return "ListBuilder(%s)" % self.builder.get_name(env)
|
||||
|
||||
class MultiStepBuilder(BuilderBase):
|
||||
"""This is a builder subclass that can build targets in
|
||||
multiple steps. The src_builder parameter to the constructor
|
||||
accepts a builder that is called to build sources supplied to
|
||||
this builder. The targets of that first build then become
|
||||
the sources of this builder.
|
||||
|
||||
If this builder has a src_suffix supplied, then the src_builder
|
||||
builder is NOT invoked if the suffix of a source file matches
|
||||
src_suffix.
|
||||
def _get_sdict(self, env):
|
||||
"""
|
||||
def __init__(self, src_builder,
|
||||
action = None,
|
||||
prefix = '',
|
||||
suffix = '',
|
||||
src_suffix = '',
|
||||
target_factory = SCons.Node.FS.default_fs.File,
|
||||
source_factory = SCons.Node.FS.default_fs.File,
|
||||
target_scanner = None,
|
||||
source_scanner = None,
|
||||
emitter=None,
|
||||
single_source=0):
|
||||
if __debug__: logInstanceCreation(self)
|
||||
BuilderBase.__init__(self, action, prefix, suffix, src_suffix,
|
||||
target_factory, source_factory,
|
||||
target_scanner, source_scanner, emitter,
|
||||
single_source = single_source)
|
||||
if not SCons.Util.is_List(src_builder):
|
||||
src_builder = [ src_builder ]
|
||||
self.src_builder = src_builder
|
||||
self.sdict = {}
|
||||
self.cached_src_suffixes = {} # source suffixes keyed on id(env)
|
||||
Returns a dictionary mapping all of the source suffixes of all
|
||||
src_builders of this Builder to the underlying Builder that
|
||||
should be called first.
|
||||
|
||||
def _execute(self, env, target = None, source = _null, overwarn={}):
|
||||
if source is _null:
|
||||
source = target
|
||||
target = None
|
||||
This dictionary is used for each target specified, so we save a
|
||||
lot of extra computation by memoizing it for each construction
|
||||
environment.
|
||||
|
||||
slist = env.arg2nodes(source, self.source_factory)
|
||||
final_sources = []
|
||||
Note that this is re-computed each time, not cached, because there
|
||||
might be changes to one of our source Builders (or one of their
|
||||
source Builders, and so on, and so on...) that we can't "see."
|
||||
|
||||
try:
|
||||
sdict = self.sdict[id(env)]
|
||||
except KeyError:
|
||||
The underlying methods we call cache their computed values,
|
||||
though, so we hope repeatedly aggregating them into a dictionary
|
||||
like this won't be too big a hit. We may need to look for a
|
||||
better way to do this if performance data show this has turned
|
||||
into a significant bottleneck.
|
||||
"""
|
||||
sdict = {}
|
||||
self.sdict[id(env)] = sdict
|
||||
for bld in self.src_builder:
|
||||
if SCons.Util.is_String(bld):
|
||||
try:
|
||||
bld = env['BUILDERS'][bld]
|
||||
except KeyError:
|
||||
continue
|
||||
for bld in self.get_src_builders(env):
|
||||
for suf in bld.src_suffixes(env):
|
||||
sdict[suf] = bld
|
||||
return sdict
|
||||
|
||||
def src_builder_sources(self, env, source, overwarn={}):
|
||||
source_factory = env.get_factory(self.source_factory)
|
||||
slist = env.arg2nodes(source, source_factory)
|
||||
|
||||
sdict = self._get_sdict(env)
|
||||
|
||||
src_suffixes = self.src_suffixes(env)
|
||||
|
||||
for snode in slist:
|
||||
try:
|
||||
get_suffix = snode.get_suffix
|
||||
except AttributeError:
|
||||
ext = self.splitext(str(snode))
|
||||
else:
|
||||
ext = get_suffix()
|
||||
try:
|
||||
subsidiary_builder = sdict[ext]
|
||||
except KeyError:
|
||||
final_sources.append(snode)
|
||||
else:
|
||||
tgt = subsidiary_builder._execute(env, None, snode, overwarn)
|
||||
# If the subsidiary Builder returned more than one target,
|
||||
# then filter out any sources that this Builder isn't
|
||||
# capable of building.
|
||||
if len(tgt) > 1:
|
||||
tgt = filter(lambda x, self=self, suf=src_suffixes:
|
||||
self.splitext(SCons.Util.to_String(x))[1] in suf,
|
||||
tgt)
|
||||
final_sources.extend(tgt)
|
||||
lengths_dict = {}
|
||||
for l in map(len, src_suffixes):
|
||||
lengths_dict[l] = None
|
||||
lengths = lengths_dict.keys()
|
||||
|
||||
return BuilderBase._execute(self, env, target, final_sources, overwarn)
|
||||
def match_src_suffix(node, src_suffixes=src_suffixes, lengths=lengths):
|
||||
node_suffixes = map(lambda l, n=node: n.name[-l:], lengths)
|
||||
for suf in src_suffixes:
|
||||
if suf in node_suffixes:
|
||||
return suf
|
||||
return None
|
||||
|
||||
result = []
|
||||
|
||||
for snode in slist:
|
||||
match_suffix = match_src_suffix(snode)
|
||||
if match_suffix:
|
||||
try:
|
||||
bld = sdict[match_suffix]
|
||||
except KeyError:
|
||||
result.append(snode)
|
||||
else:
|
||||
tlist = bld._execute(env, None, [snode], overwarn)
|
||||
# If the subsidiary Builder returned more than one
|
||||
# target, then filter out any sources that this
|
||||
# Builder isn't capable of building.
|
||||
if len(tlist) > 1:
|
||||
tlist = filter(match_src_suffix, tlist)
|
||||
result.extend(tlist)
|
||||
else:
|
||||
result.append(snode)
|
||||
|
||||
return result
|
||||
|
||||
def _get_src_builders_key(self, env):
|
||||
return id(env)
|
||||
|
||||
memoizer_counters.append(SCons.Memoize.CountDict('get_src_builders', _get_src_builders_key))
|
||||
|
||||
def get_src_builders(self, env):
|
||||
"""Return all the src_builders for this Builder.
|
||||
|
||||
This is essentially a recursive descent of the src_builder "tree."
|
||||
"""
|
||||
ret = []
|
||||
Returns the list of source Builders for this Builder.
|
||||
|
||||
This exists mainly to look up Builders referenced as
|
||||
strings in the 'BUILDER' variable of the construction
|
||||
environment and cache the result.
|
||||
"""
|
||||
memo_key = id(env)
|
||||
try:
|
||||
memo_dict = self._memo['get_src_builders']
|
||||
except KeyError:
|
||||
memo_dict = {}
|
||||
self._memo['get_src_builders'] = memo_dict
|
||||
else:
|
||||
try:
|
||||
return memo_dict[memo_key]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
builders = []
|
||||
for bld in self.src_builder:
|
||||
if SCons.Util.is_String(bld):
|
||||
# All Environments should have a BUILDERS
|
||||
# variable, so no need to check for it.
|
||||
try:
|
||||
bld = env['BUILDERS'][bld]
|
||||
except KeyError:
|
||||
continue
|
||||
ret.append(bld)
|
||||
return ret
|
||||
builders.append(bld)
|
||||
|
||||
memo_dict[memo_key] = builders
|
||||
return builders
|
||||
|
||||
def _subst_src_suffixes_key(self, env):
|
||||
return id(env)
|
||||
|
||||
memoizer_counters.append(SCons.Memoize.CountDict('subst_src_suffixes', _subst_src_suffixes_key))
|
||||
|
||||
def subst_src_suffixes(self, env):
|
||||
"""
|
||||
The suffix list may contain construction variable expansions,
|
||||
so we have to evaluate the individual strings. To avoid doing
|
||||
this over and over, we memoize the results for each construction
|
||||
environment.
|
||||
"""
|
||||
memo_key = id(env)
|
||||
try:
|
||||
memo_dict = self._memo['subst_src_suffixes']
|
||||
except KeyError:
|
||||
memo_dict = {}
|
||||
self._memo['subst_src_suffixes'] = memo_dict
|
||||
else:
|
||||
try:
|
||||
return memo_dict[memo_key]
|
||||
except KeyError:
|
||||
pass
|
||||
suffixes = map(lambda x, s=self, e=env: e.subst(x), self.src_suffix)
|
||||
memo_dict[memo_key] = suffixes
|
||||
return suffixes
|
||||
|
||||
def src_suffixes(self, env):
|
||||
"""Return a list of the src_suffix attributes for all
|
||||
src_builders of this Builder.
|
||||
"""
|
||||
try:
|
||||
return self.cached_src_suffixes[id(env)]
|
||||
except KeyError:
|
||||
suffixes = BuilderBase.src_suffixes(self, env)
|
||||
Returns the list of source suffixes for all src_builders of this
|
||||
Builder.
|
||||
|
||||
This is essentially a recursive descent of the src_builder "tree."
|
||||
(This value isn't cached because there may be changes in a
|
||||
src_builder many levels deep that we can't see.)
|
||||
"""
|
||||
sdict = {}
|
||||
suffixes = self.subst_src_suffixes(env)
|
||||
for s in suffixes:
|
||||
sdict[s] = 1
|
||||
for builder in self.get_src_builders(env):
|
||||
suffixes.extend(builder.src_suffixes(env))
|
||||
self.cached_src_suffixes[id(env)] = suffixes
|
||||
for s in builder.src_suffixes(env):
|
||||
if not sdict.has_key(s):
|
||||
sdict[s] = 1
|
||||
suffixes.append(s)
|
||||
return suffixes
|
||||
|
||||
class CompositeBuilder(SCons.Util.Proxy):
|
||||
|
@ -757,7 +833,7 @@ class CompositeBuilder(SCons.Util.Proxy):
|
|||
"""
|
||||
|
||||
def __init__(self, builder, cmdgen):
|
||||
if __debug__: logInstanceCreation(self)
|
||||
if __debug__: logInstanceCreation(self, 'Builder.CompositeBuilder')
|
||||
SCons.Util.Proxy.__init__(self, builder)
|
||||
|
||||
# cmdgen should always be an instance of DictCmdGenerator.
|
||||
|
@ -767,6 +843,3 @@ class CompositeBuilder(SCons.Util.Proxy):
|
|||
def add_action(self, suffix, action):
|
||||
self.cmdgen.add_action(suffix, action)
|
||||
self.set_src_suffix(self.cmdgen.src_suffixes())
|
||||
|
||||
def __cmp__(self, other):
|
||||
return cmp(self.__dict__, other.__dict__)
|
|
@ -78,6 +78,9 @@ Autoconf-like configuration support; low level implementation of tests.
|
|||
# The file must not exist or be empty when starting.
|
||||
# Empty or None to skip this (some tests will not work!).
|
||||
#
|
||||
# context.config_h (may be missing). If present, must be a string, which
|
||||
# will be filled with the contents of a config_h file.
|
||||
#
|
||||
# context.vardict Dictionary holding variables used for the tests and
|
||||
# stores results from the tests, used for the build
|
||||
# commands.
|
||||
|
@ -91,9 +94,17 @@ Autoconf-like configuration support; low level implementation of tests.
|
|||
# be a number and "SYSTEMNAME" a string.
|
||||
#
|
||||
|
||||
import re
|
||||
import string
|
||||
from types import IntType
|
||||
|
||||
#
|
||||
# PUBLIC VARIABLES
|
||||
#
|
||||
|
||||
LogInputFiles = 1 # Set that to log the input files in case of a failed test
|
||||
LogErrorMessages = 1 # Set that to log Conftest-generated error messages
|
||||
|
||||
#
|
||||
# PUBLIC FUNCTIONS
|
||||
#
|
||||
|
@ -123,7 +134,8 @@ def CheckBuilder(context, text = None, language = None):
|
|||
text = """
|
||||
int main() {
|
||||
return 0;
|
||||
}\n\n"""
|
||||
}
|
||||
"""
|
||||
|
||||
context.Display("Checking if building a %s file works... " % lang)
|
||||
ret = context.BuildProg(text, suffix)
|
||||
|
@ -187,7 +199,8 @@ def CheckFunc(context, function_name, header = None, language = None):
|
|||
#endif
|
||||
|
||||
return 0;
|
||||
}\n\n""" % { 'name': function_name,
|
||||
}
|
||||
""" % { 'name': function_name,
|
||||
'include': includetext,
|
||||
'hdr': header }
|
||||
|
||||
|
@ -290,7 +303,8 @@ def CheckType(context, type_name, fallback = None,
|
|||
return 0;
|
||||
if (sizeof (%(name)s))
|
||||
return 0;
|
||||
}\n\n""" % { 'include': includetext,
|
||||
}
|
||||
""" % { 'include': includetext,
|
||||
'header': header,
|
||||
'name': type_name }
|
||||
|
||||
|
@ -305,7 +319,7 @@ def CheckType(context, type_name, fallback = None,
|
|||
return ret
|
||||
|
||||
|
||||
def CheckLib(context, libs, func_name, header = None,
|
||||
def CheckLib(context, libs, func_name = None, header = None,
|
||||
extra_libs = None, call = None, language = None, autoadd = 1):
|
||||
"""
|
||||
Configure check for a C or C++ libraries "libs". Searches through
|
||||
|
@ -319,7 +333,8 @@ def CheckLib(context, libs, func_name, header = None,
|
|||
depends on.
|
||||
Optional "call" replaces the call to "func_name" in the test code. It must
|
||||
consist of complete C statements, including a trailing ";".
|
||||
There must either be a "func_name" or a "call" argument (or both).
|
||||
Both "func_name" and "call" arguments are optional, and in that case, just
|
||||
linking against the libs is tested.
|
||||
"language" should be "C" or "C++" and is used to select the compiler.
|
||||
Default is "C".
|
||||
Note that this uses the current value of compiler and linker flags, make
|
||||
|
@ -339,24 +354,29 @@ def CheckLib(context, libs, func_name, header = None,
|
|||
%s""" % (includetext, header)
|
||||
|
||||
# Add a function declaration if needed.
|
||||
if func_name and func_name != "main" and not header:
|
||||
if func_name and func_name != "main":
|
||||
if not header:
|
||||
text = text + """
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
char %s();""" % func_name
|
||||
char %s();
|
||||
""" % func_name
|
||||
|
||||
# The actual test code.
|
||||
if not call:
|
||||
call = "%s();" % func_name
|
||||
|
||||
# if no function to test, leave main() blank
|
||||
text = text + """
|
||||
int
|
||||
main() {
|
||||
%s
|
||||
return 0;
|
||||
}
|
||||
\n\n""" % call
|
||||
""" % (call or "")
|
||||
|
||||
if call:
|
||||
i = string.find(call, "\n")
|
||||
if i > 0:
|
||||
calltext = call[:i] + ".."
|
||||
|
@ -372,8 +392,15 @@ def CheckLib(context, libs, func_name, header = None,
|
|||
context.Display("Cannot check for library %s: %s\n" % (lib_name, msg))
|
||||
return msg
|
||||
|
||||
# if a function was specified to run in main(), say it
|
||||
if call:
|
||||
context.Display("Checking for %s in %s library %s... "
|
||||
% (calltext, lang, lib_name))
|
||||
# otherwise, just say the name of library and language
|
||||
else:
|
||||
context.Display("Checking for %s library %s... "
|
||||
% (lang, lib_name))
|
||||
|
||||
if lib_name:
|
||||
l = [ lib_name ]
|
||||
if extra_libs:
|
||||
|
@ -390,7 +417,7 @@ def CheckLib(context, libs, func_name, header = None,
|
|||
if oldLIBS != -1 and (ret or not autoadd):
|
||||
context.SetLIBS(oldLIBS)
|
||||
|
||||
if ret == "":
|
||||
if not ret:
|
||||
return ret
|
||||
|
||||
return ret
|
||||
|
@ -418,8 +445,8 @@ def _YesNoResult(context, ret, key, text):
|
|||
def _Have(context, key, have):
|
||||
"""
|
||||
Store result of a test in context.havedict and context.headerfilename.
|
||||
"key" is a "HAVE_abc" name. It is turned into all CAPITALS and ":./" are
|
||||
replaced by an underscore.
|
||||
"key" is a "HAVE_abc" name. It is turned into all CAPITALS and non-
|
||||
alphanumerics are replaced by an underscore.
|
||||
The value of "have" can be:
|
||||
1 - Feature is defined, add "#define key".
|
||||
0 - Feature is not defined, add "/* #undef key */".
|
||||
|
@ -432,22 +459,23 @@ def _Have(context, key, have):
|
|||
when desired and escape special characters!
|
||||
"""
|
||||
key_up = string.upper(key)
|
||||
key_up = string.replace(key_up, ':', '_')
|
||||
key_up = string.replace(key_up, '.', '_')
|
||||
key_up = string.replace(key_up, '/', '_')
|
||||
key_up = string.replace(key_up, ' ', '_')
|
||||
key_up = re.sub('[^A-Z0-9_]', '_', key_up)
|
||||
context.havedict[key_up] = have
|
||||
if have == 1:
|
||||
line = "#define %s\n" % key_up
|
||||
elif have == 0:
|
||||
line = "/* #undef %s */\n" % key_up
|
||||
elif type(have) == IntType:
|
||||
line = "#define %s %d\n" % (key_up, have)
|
||||
else:
|
||||
line = "#define %s %s\n" % (key_up, str(have))
|
||||
|
||||
if context.headerfilename:
|
||||
f = open(context.headerfilename, "a")
|
||||
if have == 1:
|
||||
f.write("#define %s\n" % key_up)
|
||||
elif have == 0:
|
||||
f.write("/* #undef %s */\n" % key_up)
|
||||
elif type(have) == IntType:
|
||||
f.write("#define %s %d\n" % (key_up, have))
|
||||
else:
|
||||
f.write("#define %s %s\n" % (key_up, str(have)))
|
||||
f.write(line)
|
||||
f.close()
|
||||
elif hasattr(context,'config_h'):
|
||||
context.config_h = context.config_h + line
|
||||
|
||||
|
||||
def _LogFailed(context, text, msg):
|
||||
|
@ -455,6 +483,7 @@ def _LogFailed(context, text, msg):
|
|||
Write to the log about a failed program.
|
||||
Add line numbers, so that error messages can be understood.
|
||||
"""
|
||||
if LogInputFiles:
|
||||
context.Log("Failed program was:\n")
|
||||
lines = string.split(text, '\n')
|
||||
if len(lines) and lines[-1] == '':
|
||||
|
@ -463,6 +492,7 @@ def _LogFailed(context, text, msg):
|
|||
for line in lines:
|
||||
context.Log("%d: %s\n" % (n, line))
|
||||
n = n + 1
|
||||
if LogErrorMessages:
|
||||
context.Log("Error message: %s\n" % msg)
|
||||
|
||||
|
|
@ -7,7 +7,7 @@ needed by most users.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -29,12 +29,13 @@ needed by most users.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Debug.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Debug.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
|
||||
# Recipe 14.10 from the Python Cookbook.
|
||||
import os
|
||||
import string
|
||||
import sys
|
||||
|
||||
# Recipe 14.10 from the Python Cookbook.
|
||||
try:
|
||||
import weakref
|
||||
except ImportError:
|
||||
|
@ -60,6 +61,10 @@ def string_to_classes(s):
|
|||
else:
|
||||
return string.split(s)
|
||||
|
||||
def fetchLoggedInstances(classes="*"):
|
||||
classnames = string_to_classes(classes)
|
||||
return map(lambda cn: (cn, len(tracked_classes[cn])), classnames)
|
||||
|
||||
def countLoggedInstances(classes, file=sys.stdout):
|
||||
for classname in string_to_classes(classes):
|
||||
file.write("%s: %d\n" % (classname, len(tracked_classes[classname])))
|
||||
|
@ -93,10 +98,102 @@ if sys.platform[:5] == "linux":
|
|||
else:
|
||||
try:
|
||||
import resource
|
||||
except ImportError:
|
||||
try:
|
||||
import win32process
|
||||
import win32api
|
||||
except ImportError:
|
||||
def memory():
|
||||
return 0
|
||||
else:
|
||||
def memory():
|
||||
process_handle = win32api.GetCurrentProcess()
|
||||
memory_info = win32process.GetProcessMemoryInfo( process_handle )
|
||||
return memory_info['PeakWorkingSetSize']
|
||||
else:
|
||||
def memory():
|
||||
res = resource.getrusage(resource.RUSAGE_SELF)
|
||||
return res[4]
|
||||
|
||||
|
||||
|
||||
caller_dicts = {}
|
||||
|
||||
def caller(*backlist):
|
||||
import traceback
|
||||
if not backlist:
|
||||
backlist = [0]
|
||||
result = []
|
||||
for back in backlist:
|
||||
tb = traceback.extract_stack(limit=3+back)
|
||||
key = tb[1][:3]
|
||||
try:
|
||||
entry = caller_dicts[key]
|
||||
except KeyError:
|
||||
entry = caller_dicts[key] = {}
|
||||
key = tb[0][:3]
|
||||
entry[key] = entry.get(key, 0) + 1
|
||||
result.append('%s:%d(%s)' % func_shorten(key))
|
||||
return result
|
||||
|
||||
def dump_caller_counts(file=sys.stdout):
|
||||
keys = caller_dicts.keys()
|
||||
keys.sort()
|
||||
for k in keys:
|
||||
file.write("Callers of %s:%d(%s):\n" % func_shorten(k))
|
||||
counts = caller_dicts[k]
|
||||
callers = counts.keys()
|
||||
callers.sort()
|
||||
for c in callers:
|
||||
#file.write(" counts[%s] = %s\n" % (c, counts[c]))
|
||||
t = ((counts[c],) + func_shorten(c))
|
||||
file.write(" %6d %s:%d(%s)\n" % t)
|
||||
|
||||
shorten_list = [
|
||||
( '/scons/SCons/', 1),
|
||||
( '/src/engine/SCons/', 1),
|
||||
( '/usr/lib/python', 0),
|
||||
]
|
||||
|
||||
if os.sep != '/':
|
||||
def platformize(t):
|
||||
return (string.replace(t[0], '/', os.sep), t[1])
|
||||
shorten_list = map(platformize, shorten_list)
|
||||
del platformize
|
||||
|
||||
def func_shorten(func_tuple):
|
||||
f = func_tuple[0]
|
||||
for t in shorten_list:
|
||||
i = string.find(f, t[0])
|
||||
if i >= 0:
|
||||
if t[1]:
|
||||
i = i + len(t[0])
|
||||
f = f[i:]
|
||||
break
|
||||
return (f,)+func_tuple[1:]
|
||||
|
||||
|
||||
|
||||
TraceFP = {}
|
||||
if sys.platform == 'win32':
|
||||
TraceDefault = 'con'
|
||||
else:
|
||||
TraceDefault = '/dev/tty'
|
||||
|
||||
def Trace(msg, file=None, mode='w'):
|
||||
"""Write a trace message to a file. Whenever a file is specified,
|
||||
it becomes the default for the next call to Trace()."""
|
||||
global TraceDefault
|
||||
if file is None:
|
||||
file = TraceDefault
|
||||
else:
|
||||
TraceDefault = file
|
||||
try:
|
||||
fp = TraceFP[file]
|
||||
except KeyError:
|
||||
try:
|
||||
fp = TraceFP[file] = open(file, mode)
|
||||
except TypeError:
|
||||
# Assume we were passed an open file pointer.
|
||||
fp = file
|
||||
fp.write(msg)
|
449
scons/scons-local-0.97/SCons/Defaults.py
Normal file
449
scons/scons-local-0.97/SCons/Defaults.py
Normal file
|
@ -0,0 +1,449 @@
|
|||
"""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, 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/Defaults.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
|
||||
|
||||
import os
|
||||
import os.path
|
||||
import shutil
|
||||
import stat
|
||||
import time
|
||||
import types
|
||||
import sys
|
||||
|
||||
import SCons.Action
|
||||
import SCons.Builder
|
||||
import SCons.Environment
|
||||
import SCons.PathList
|
||||
import SCons.Sig
|
||||
import SCons.Subst
|
||||
import SCons.Tool
|
||||
|
||||
# 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)
|
||||
|
||||
# Some people were using these variable name before we made
|
||||
# SourceFileScanner part of the public interface. Don't break their
|
||||
# SConscript files until we've given them some fair warning and a
|
||||
# transition period.
|
||||
CScan = SCons.Tool.CScanner
|
||||
DScan = SCons.Tool.DScanner
|
||||
LaTeXScan = SCons.Tool.LaTeXScanner
|
||||
ObjSourceScan = SCons.Tool.SourceFileScanner
|
||||
ProgScan = SCons.Tool.ProgramScanner
|
||||
|
||||
# This isn't really a tool scanner, so it doesn't quite belong with
|
||||
# the rest of those in Tool/__init__.py, but I'm not sure where else it
|
||||
# should go. Leave it here for now.
|
||||
import SCons.Scanner.Dir
|
||||
DirScanner = SCons.Scanner.Dir.DirScanner()
|
||||
DirEntryScanner = SCons.Scanner.Dir.DirEntryScanner()
|
||||
|
||||
# Actions for common languages.
|
||||
CAction = SCons.Action.Action("$CCCOM", "$CCCOMSTR")
|
||||
ShCAction = SCons.Action.Action("$SHCCCOM", "$SHCCCOMSTR")
|
||||
CXXAction = SCons.Action.Action("$CXXCOM", "$CXXCOMSTR")
|
||||
ShCXXAction = SCons.Action.Action("$SHCXXCOM", "$SHCXXCOMSTR")
|
||||
|
||||
ASAction = SCons.Action.Action("$ASCOM", "$ASCOMSTR")
|
||||
ASPPAction = SCons.Action.Action("$ASPPCOM", "$ASPPCOMSTR")
|
||||
|
||||
LinkAction = SCons.Action.Action("$LINKCOM", "$LINKCOMSTR")
|
||||
ShLinkAction = SCons.Action.Action("$SHLINKCOM", "$SHLINKCOMSTR")
|
||||
|
||||
LdModuleLinkAction = SCons.Action.Action("$LDMODULECOM", "$LDMODULECOMSTR")
|
||||
|
||||
# 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_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 not os.path.exists(entry) or 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 installFunc(dest, source, env):
|
||||
"""Install a source file or directory into a destination by copying,
|
||||
(including copying permission/mode bits)."""
|
||||
|
||||
if os.path.isdir(source):
|
||||
if os.path.exists(dest):
|
||||
if not os.path.isdir(dest):
|
||||
raise SCons.Errors.UserError, "cannot overwrite non-directory `%s' with a directory `%s'" % (str(dest), str(source))
|
||||
else:
|
||||
parent = os.path.split(dest)[0]
|
||||
if not os.path.exists(parent):
|
||||
os.makedirs(parent)
|
||||
shutil.copytree(source, dest)
|
||||
else:
|
||||
shutil.copy2(source, dest)
|
||||
st = os.stat(source)
|
||||
os.chmod(dest, stat.S_IMODE(st[stat.ST_MODE]) | stat.S_IWRITE)
|
||||
|
||||
return 0
|
||||
|
||||
def installStr(dest, source, env):
|
||||
source = str(source)
|
||||
if os.path.isdir(source):
|
||||
type = 'directory'
|
||||
else:
|
||||
type = 'file'
|
||||
return 'Install %s: "%s" as "%s"' % (type, source, dest)
|
||||
|
||||
def _concat(prefix, list, suffix, env, f=lambda x: x, target=None, source=None):
|
||||
"""
|
||||
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 calling _concat_ixes to concatenate 'prefix' and
|
||||
'suffix' onto each element of the list.
|
||||
"""
|
||||
if not list:
|
||||
return list
|
||||
|
||||
if SCons.Util.is_List(list):
|
||||
list = SCons.Util.flatten(list)
|
||||
|
||||
l = f(SCons.PathList.PathList(list).subst_path(env, target, source))
|
||||
if not l is None:
|
||||
list = l
|
||||
|
||||
return _concat_ixes(prefix, list, suffix, env)
|
||||
|
||||
def _concat_ixes(prefix, list, suffix, env):
|
||||
"""
|
||||
Creates a new list from 'list' by concatenating the 'prefix' and
|
||||
'suffix' arguments 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.
|
||||
"""
|
||||
|
||||
result = []
|
||||
|
||||
# ensure that prefix and suffix are strings
|
||||
prefix = str(env.subst(prefix, SCons.Subst.SUBST_RAW))
|
||||
suffix = str(env.subst(suffix, SCons.Subst.SUBST_RAW))
|
||||
|
||||
for x in list:
|
||||
if isinstance(x, SCons.Node.FS.File):
|
||||
result.append(x)
|
||||
continue
|
||||
x = str(x)
|
||||
if x:
|
||||
|
||||
if prefix:
|
||||
if prefix[-1] == ' ':
|
||||
result.append(prefix[:-1])
|
||||
elif x[:len(prefix)] != prefix:
|
||||
x = prefix + x
|
||||
|
||||
result.append(x)
|
||||
|
||||
if suffix:
|
||||
if suffix[0] == ' ':
|
||||
result.append(suffix[1:])
|
||||
elif x[-len(suffix):] != suffix:
|
||||
result[-1] = result[-1]+suffix
|
||||
|
||||
return result
|
||||
|
||||
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):
|
||||
result = []
|
||||
for l in list:
|
||||
if isinstance(l, SCons.Node.FS.File):
|
||||
result.append(l)
|
||||
continue
|
||||
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)]
|
||||
result.append(l)
|
||||
return result
|
||||
return c(prefix, list, suffix, env, f)
|
||||
|
||||
# This is an alternate _stripixes() function that passes all of our tests
|
||||
# (as of 21 February 2007), like the current version above. It's more
|
||||
# straightforward because it does its manipulation directly, not using
|
||||
# the funky f call-back function to _concat(). (In this respect it's
|
||||
# like the updated _defines() function below.)
|
||||
#
|
||||
# The most convoluted thing is that it still uses a custom _concat()
|
||||
# function if one was placed in the construction environment; there's
|
||||
# a specific test for that functionality, but it might be worth getting
|
||||
# rid of.
|
||||
#
|
||||
# Since this work was done while trying to get 0.97 out the door
|
||||
# (just prior to 0.96.96), I decided to be cautious and leave the old
|
||||
# function as is, to minimize the chance of other corner-case regressions.
|
||||
# The updated version is captured here so we can uncomment it and start
|
||||
# using it at a less sensitive time in the development cycle (or when
|
||||
# it's clearly required to fix something).
|
||||
#
|
||||
#def _stripixes(prefix, list, suffix, stripprefix, stripsuffix, env, c=None):
|
||||
# """
|
||||
# This is a wrapper around _concat()/_concat_ixes() that checks for the
|
||||
# existence of prefixes or suffixes on list elements and strips them
|
||||
# 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 list:
|
||||
# return list
|
||||
#
|
||||
# if not callable(c):
|
||||
# env_c = env['_concat']
|
||||
# if env_c != _concat and callable(env_c):
|
||||
# # There's a custom _concat() method in the construction
|
||||
# # environment, and we've allowed people to set that in
|
||||
# # the past (see test/custom-concat.py), so preserve the
|
||||
# # backwards compatibility.
|
||||
# c = env_c
|
||||
# else:
|
||||
# c = _concat_ixes
|
||||
#
|
||||
# if SCons.Util.is_List(list):
|
||||
# list = SCons.Util.flatten(list)
|
||||
#
|
||||
# lsp = len(stripprefix)
|
||||
# lss = len(stripsuffix)
|
||||
# stripped = []
|
||||
# for l in SCons.PathList.PathList(list).subst_path(env, None, None):
|
||||
# if isinstance(l, SCons.Node.FS.File):
|
||||
# stripped.append(l)
|
||||
# continue
|
||||
# if not SCons.Util.is_String(l):
|
||||
# l = str(l)
|
||||
# if l[:lsp] == stripprefix:
|
||||
# l = l[lsp:]
|
||||
# if l[-lss:] == stripsuffix:
|
||||
# l = l[:-lss]
|
||||
# stripped.append(l)
|
||||
#
|
||||
# return c(prefix, stripped, suffix, env)
|
||||
|
||||
def _defines(prefix, defs, suffix, env, c=_concat_ixes):
|
||||
"""A wrapper around _concat_ixes 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, env.subst_path(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
|
||||
|
||||
class Variable_Method_Caller:
|
||||
"""A class for finding a construction variable on the stack and
|
||||
calling one of its methods.
|
||||
|
||||
We use this to support "construction variables" in our string
|
||||
eval()s that actually stand in for methods--specifically, use
|
||||
of "RDirs" in call to _concat that should actually execute the
|
||||
"TARGET.RDirs" method. (We used to support this by creating a little
|
||||
"build dictionary" that mapped RDirs to the method, but this got in
|
||||
the way of Memoizing construction environments, because we had to
|
||||
create new environment objects to hold the variables.)
|
||||
"""
|
||||
def __init__(self, variable, method):
|
||||
self.variable = variable
|
||||
self.method = method
|
||||
def __call__(self, *args, **kw):
|
||||
try: 1/0
|
||||
except ZeroDivisionError: frame = sys.exc_info()[2].tb_frame
|
||||
variable = self.variable
|
||||
while frame:
|
||||
if frame.f_locals.has_key(variable):
|
||||
v = frame.f_locals[variable]
|
||||
if v:
|
||||
method = getattr(v, self.method)
|
||||
return apply(method, args, kw)
|
||||
frame = frame.f_back
|
||||
return None
|
||||
|
||||
ConstructionEnvironment = {
|
||||
'BUILDERS' : {},
|
||||
'SCANNERS' : [],
|
||||
'CONFIGUREDIR' : '#/.sconf_temp',
|
||||
'CONFIGURELOG' : '#/config.log',
|
||||
'CPPSUFFIXES' : SCons.Tool.CSuffixes,
|
||||
'DSUFFIXES' : SCons.Tool.DSuffixes,
|
||||
'ENV' : {},
|
||||
'IDLSUFFIXES' : SCons.Tool.IDLSuffixes,
|
||||
'INSTALL' : installFunc,
|
||||
'INSTALLSTR' : installStr,
|
||||
'_installStr' : installStr,
|
||||
'LATEXSUFFIXES' : SCons.Tool.LaTeXSuffixes,
|
||||
'_concat' : _concat,
|
||||
'_defines' : _defines,
|
||||
'_stripixes' : _stripixes,
|
||||
'_LIBFLAGS' : '${_concat(LIBLINKPREFIX, LIBS, LIBLINKSUFFIX, __env__)}',
|
||||
'_LIBDIRFLAGS' : '$( ${_concat(LIBDIRPREFIX, LIBPATH, LIBDIRSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)',
|
||||
'_CPPINCFLAGS' : '$( ${_concat(INCPREFIX, CPPPATH, INCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)',
|
||||
'_CPPDEFFLAGS' : '${_defines(CPPDEFPREFIX, CPPDEFINES, CPPDEFSUFFIX, __env__)}',
|
||||
'TEMPFILE' : NullCmdGenerator,
|
||||
'Dir' : Variable_Method_Caller('TARGET', 'Dir'),
|
||||
'Dirs' : Variable_Method_Caller('TARGET', 'Dirs'),
|
||||
'File' : Variable_Method_Caller('TARGET', 'File'),
|
||||
'RDirs' : Variable_Method_Caller('TARGET', 'RDirs'),
|
||||
}
|
1896
scons/scons-local-0.97/SCons/Environment.py
Normal file
1896
scons/scons-local-0.97/SCons/Environment.py
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,5 +1,5 @@
|
|||
#
|
||||
# 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
|
||||
|
@ -28,14 +28,15 @@ and user errors in SCons.
|
|||
|
||||
"""
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Errors.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Errors.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
|
||||
|
||||
class BuildError(Exception):
|
||||
def __init__(self, node=None, errstr="Unknown error", *args):
|
||||
def __init__(self, node=None, errstr="Unknown error", filename=None, *args):
|
||||
self.node = node
|
||||
self.errstr = errstr
|
||||
self.filename = filename
|
||||
apply(Exception.__init__, (self,) + args)
|
||||
|
||||
class InternalError(Exception):
|
||||
|
@ -53,8 +54,9 @@ class ExplicitExit(Exception):
|
|||
self.status = status
|
||||
apply(Exception.__init__, (self,) + args)
|
||||
|
||||
class ConfigureDryRunError(UserError):
|
||||
"""Raised when a file needs to be updated during a Configure process,
|
||||
but the user requested a dry-run"""
|
||||
def __init__(self,file):
|
||||
UserError.__init__(self,"Cannot update configure test (%s) within a dry-run." % str(file))
|
||||
class TaskmasterException(Exception):
|
||||
def __init__(self, node=None, exc_info=(None, None, None), *args):
|
||||
self.node = node
|
||||
self.errstr = "Exception"
|
||||
self.exc_info = exc_info
|
||||
apply(Exception.__init__, (self,) + args)
|
306
scons/scons-local-0.97/SCons/Executor.py
Normal file
306
scons/scons-local-0.97/SCons/Executor.py
Normal file
|
@ -0,0 +1,306 @@
|
|||
"""SCons.Executor
|
||||
|
||||
A module for executing actions with specific lists of target and source
|
||||
Nodes.
|
||||
|
||||
"""
|
||||
|
||||
#
|
||||
# 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/Executor.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import string
|
||||
|
||||
from SCons.Debug import logInstanceCreation
|
||||
import SCons.Memoize
|
||||
|
||||
|
||||
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.
|
||||
"""
|
||||
|
||||
if SCons.Memoize.use_memoizer:
|
||||
__metaclass__ = SCons.Memoize.Memoized_Metaclass
|
||||
|
||||
memoizer_counters = []
|
||||
|
||||
def __init__(self, action, env=None, overridelist=[{}],
|
||||
targets=[], sources=[], builder_kw={}):
|
||||
if __debug__: logInstanceCreation(self, 'Executor.Executor')
|
||||
self.set_action_list(action)
|
||||
self.pre_actions = []
|
||||
self.post_actions = []
|
||||
self.env = env
|
||||
self.overridelist = overridelist
|
||||
self.targets = targets
|
||||
self.sources = sources[:]
|
||||
self.builder_kw = builder_kw
|
||||
self._memo = {}
|
||||
|
||||
def set_action_list(self, action):
|
||||
import SCons.Util
|
||||
if not SCons.Util.is_List(action):
|
||||
if not action:
|
||||
import SCons.Errors
|
||||
raise SCons.Errors.UserError, "Executor must have an action."
|
||||
action = [action]
|
||||
self.action_list = action
|
||||
|
||||
def get_action_list(self):
|
||||
return self.pre_actions + self.action_list + self.post_actions
|
||||
|
||||
def get_build_env(self):
|
||||
"""Fetch or create the appropriate build Environment
|
||||
for this Executor.
|
||||
"""
|
||||
# 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)
|
||||
|
||||
import SCons.Defaults
|
||||
env = self.env or SCons.Defaults.DefaultEnvironment()
|
||||
build_env = env.Override(overrides)
|
||||
|
||||
return build_env
|
||||
|
||||
def get_build_scanner_path(self, scanner):
|
||||
"""Fetch the scanner path for this executor's targets
|
||||
and sources.
|
||||
"""
|
||||
env = self.get_build_env()
|
||||
try:
|
||||
cwd = self.targets[0].cwd
|
||||
except (IndexError, AttributeError):
|
||||
cwd = None
|
||||
return scanner.path(env, cwd, self.targets, self.sources)
|
||||
|
||||
def get_kw(self, kw={}):
|
||||
result = self.builder_kw.copy()
|
||||
result.update(kw)
|
||||
return result
|
||||
|
||||
def do_nothing(self, target, exitstatfunc, kw):
|
||||
pass
|
||||
|
||||
def do_execute(self, target, exitstatfunc, kw):
|
||||
"""Actually execute the action list."""
|
||||
env = self.get_build_env()
|
||||
kw = self.get_kw(kw)
|
||||
for act in self.get_action_list():
|
||||
apply(act,
|
||||
(self.targets, self.sources, env, exitstatfunc),
|
||||
kw)
|
||||
|
||||
# use extra indirection because with new-style objects (Python 2.2
|
||||
# and above) we can't override special methods, and nullify() needs
|
||||
# to be able to do this.
|
||||
|
||||
def __call__(self, target, exitstatfunc, **kw):
|
||||
self.do_execute(target, exitstatfunc, kw)
|
||||
|
||||
def cleanup(self):
|
||||
self._memo = {}
|
||||
|
||||
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 add_pre_action(self, action):
|
||||
self.pre_actions.append(action)
|
||||
|
||||
def add_post_action(self, action):
|
||||
self.post_actions.append(action)
|
||||
|
||||
# another extra indirection for new-style objects and nullify...
|
||||
|
||||
def my_str(self):
|
||||
env = self.get_build_env()
|
||||
get = lambda action, t=self.targets, s=self.sources, e=env: \
|
||||
action.genstring(t, s, e)
|
||||
return string.join(map(get, self.get_action_list()), "\n")
|
||||
|
||||
|
||||
def __str__(self):
|
||||
return self.my_str()
|
||||
|
||||
def nullify(self):
|
||||
self.cleanup()
|
||||
self.do_execute = self.do_nothing
|
||||
self.my_str = lambda S=self: ''
|
||||
|
||||
memoizer_counters.append(SCons.Memoize.CountValue('get_contents'))
|
||||
|
||||
def get_contents(self):
|
||||
"""Fetch the signature contents. This is the main 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._memo['get_contents']
|
||||
except KeyError:
|
||||
pass
|
||||
env = self.get_build_env()
|
||||
get = lambda action, t=self.targets, s=self.sources, e=env: \
|
||||
action.get_contents(t, s, e)
|
||||
result = string.join(map(get, self.get_action_list()), "")
|
||||
self._memo['get_contents'] = result
|
||||
return result
|
||||
|
||||
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
|
||||
|
||||
def scan_targets(self, scanner):
|
||||
self.scan(scanner, self.targets)
|
||||
|
||||
def scan_sources(self, scanner):
|
||||
if self.sources:
|
||||
self.scan(scanner, self.sources)
|
||||
|
||||
def scan(self, scanner, node_list):
|
||||
"""Scan a list of this Executor's files (targets or sources) for
|
||||
implicit dependencies and update all of the targets with them.
|
||||
This essentially short-circuits an N*M scan of the sources for
|
||||
each individual target, which is a hell of a lot more efficient.
|
||||
"""
|
||||
map(lambda N: N.disambiguate(), node_list)
|
||||
|
||||
env = self.get_build_env()
|
||||
select_specific_scanner = lambda t: (t[0], t[1].select(t[0]))
|
||||
remove_null_scanners = lambda t: not t[1] is None
|
||||
add_scanner_path = lambda t, s=self: \
|
||||
(t[0], t[1], s.get_build_scanner_path(t[1]))
|
||||
if scanner:
|
||||
scanner_list = map(lambda n, s=scanner: (n, s), node_list)
|
||||
else:
|
||||
kw = self.get_kw()
|
||||
get_initial_scanners = lambda n, e=env, kw=kw: \
|
||||
(n, n.get_env_scanner(e, kw))
|
||||
scanner_list = map(get_initial_scanners, node_list)
|
||||
scanner_list = filter(remove_null_scanners, scanner_list)
|
||||
|
||||
scanner_list = map(select_specific_scanner, scanner_list)
|
||||
scanner_list = filter(remove_null_scanners, scanner_list)
|
||||
scanner_path_list = map(add_scanner_path, scanner_list)
|
||||
deps = []
|
||||
for node, scanner, path in scanner_path_list:
|
||||
deps.extend(node.get_implicit_deps(env, scanner, path))
|
||||
|
||||
for tgt in self.targets:
|
||||
tgt.add_to_implicit(deps)
|
||||
|
||||
def get_missing_sources(self):
|
||||
"""
|
||||
"""
|
||||
return filter(lambda s: s.missing(), self.sources)
|
||||
|
||||
def _get_unignored_sources_key(self, ignore=()):
|
||||
return tuple(ignore)
|
||||
|
||||
memoizer_counters.append(SCons.Memoize.CountDict('get_unignored_sources', _get_unignored_sources_key))
|
||||
|
||||
def get_unignored_sources(self, ignore=()):
|
||||
ignore = tuple(ignore)
|
||||
try:
|
||||
memo_dict = self._memo['get_unignored_sources']
|
||||
except KeyError:
|
||||
memo_dict = {}
|
||||
self._memo['get_unignored_sources'] = memo_dict
|
||||
else:
|
||||
try:
|
||||
return memo_dict[ignore]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
sourcelist = self.sources
|
||||
if ignore:
|
||||
sourcelist = filter(lambda s, i=ignore: not s in i, sourcelist)
|
||||
|
||||
memo_dict[ignore] = sourcelist
|
||||
|
||||
return sourcelist
|
||||
|
||||
def _process_sources_key(self, func, ignore=()):
|
||||
return (func, tuple(ignore))
|
||||
|
||||
memoizer_counters.append(SCons.Memoize.CountDict('process_sources', _process_sources_key))
|
||||
|
||||
def process_sources(self, func, ignore=()):
|
||||
memo_key = (func, tuple(ignore))
|
||||
try:
|
||||
memo_dict = self._memo['process_sources']
|
||||
except KeyError:
|
||||
memo_dict = {}
|
||||
self._memo['process_sources'] = memo_dict
|
||||
else:
|
||||
try:
|
||||
return memo_dict[memo_key]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
result = map(func, self.get_unignored_sources(ignore))
|
||||
|
||||
memo_dict[memo_key] = result
|
||||
|
||||
return result
|
||||
|
||||
|
||||
_Executor = Executor
|
||||
|
||||
class Null(_Executor):
|
||||
"""A null Executor, with a null build Environment, that does
|
||||
nothing when the rest of the methods call it.
|
||||
|
||||
This might be able to disapper when we refactor things to
|
||||
disassociate Builders from Nodes entirely, so we're not
|
||||
going to worry about unit tests for this--at least for now.
|
||||
"""
|
||||
def __init__(self, *args, **kw):
|
||||
if __debug__: logInstanceCreation(self, 'Executor.Null')
|
||||
kw['action'] = []
|
||||
apply(_Executor.__init__, (self,), kw)
|
||||
def get_build_env(self):
|
||||
class NullEnvironment:
|
||||
def get_scanner(self, key):
|
||||
return None
|
||||
return NullEnvironment()
|
||||
def get_build_scanner_path(self):
|
||||
return None
|
||||
def cleanup(self):
|
||||
pass
|
|
@ -7,7 +7,7 @@ stop, and wait on jobs.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -29,7 +29,9 @@ stop, and wait on jobs.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Job.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Job.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import SCons.compat
|
||||
|
||||
class Jobs:
|
||||
"""An instance of this class initializes N jobs, and provides
|
||||
|
@ -89,8 +91,7 @@ class Serial:
|
|||
that needs to be executed, or None if there are no more tasks. The
|
||||
taskmaster's executed() method will be called for each task when it
|
||||
is successfully executed or failed() will be called if it failed to
|
||||
execute (e.g. execute() raised an exception). The taskmaster's
|
||||
is_blocked() method will not be called. """
|
||||
execute (e.g. execute() raised an exception)."""
|
||||
|
||||
self.taskmaster = taskmaster
|
||||
|
||||
|
@ -154,9 +155,9 @@ else:
|
|||
ok = False
|
||||
except:
|
||||
task.exception_set()
|
||||
ok = 0
|
||||
ok = False
|
||||
else:
|
||||
ok = 1
|
||||
ok = True
|
||||
|
||||
self.resultsQueue.put((task, ok))
|
||||
|
||||
|
@ -169,21 +170,19 @@ else:
|
|||
self.resultsQueue = Queue.Queue(0)
|
||||
|
||||
# Create worker threads
|
||||
for i in range(num):
|
||||
for _ in range(num):
|
||||
Worker(self.requestQueue, self.resultsQueue)
|
||||
|
||||
def put(self, obj):
|
||||
"""Put task into request queue."""
|
||||
self.requestQueue.put(obj)
|
||||
|
||||
def get(self, block = 1):
|
||||
def get(self, block = True):
|
||||
"""Remove and return a result tuple from the results queue."""
|
||||
return self.resultsQueue.get(block)
|
||||
|
||||
def get_nowait(self):
|
||||
"""Remove and result a result tuple from the results queue
|
||||
without blocking."""
|
||||
return self.get(0)
|
||||
def preparation_failed(self, obj):
|
||||
self.resultsQueue.put((obj, 0))
|
||||
|
||||
class Parallel:
|
||||
"""This class is used to execute tasks in parallel, and is somewhat
|
||||
|
@ -195,25 +194,21 @@ else:
|
|||
def __init__(self, taskmaster, num):
|
||||
"""Create a new parallel job given a taskmaster.
|
||||
|
||||
The taskmaster's next_task() method should return the next task
|
||||
that needs to be executed, or None if there are no more tasks. The
|
||||
taskmaster's executed() method will be called for each task when it
|
||||
is successfully executed or failed() will be called if the task
|
||||
failed to execute (i.e. execute() raised an exception). The
|
||||
taskmaster's is_blocked() method should return true iff there are
|
||||
more tasks, but they can't be executed until one or more other
|
||||
tasks have been executed. next_task() will be called iff
|
||||
is_blocked() returned false.
|
||||
The taskmaster's next_task() method should return the next
|
||||
task that needs to be executed, or None if there are no more
|
||||
tasks. The taskmaster's executed() method will be called
|
||||
for each task when it is successfully executed or failed()
|
||||
will be called if the task failed to execute (i.e. execute()
|
||||
raised an exception).
|
||||
|
||||
Note: calls to taskmaster are serialized, but calls to execute() on
|
||||
distinct tasks are not serialized, because that is the whole point
|
||||
of parallel jobs: they can execute multiple tasks
|
||||
simultaneously. """
|
||||
Note: calls to taskmaster are serialized, but calls to
|
||||
execute() on distinct tasks are not serialized, because
|
||||
that is the whole point of parallel jobs: they can execute
|
||||
multiple tasks simultaneously. """
|
||||
|
||||
self.taskmaster = taskmaster
|
||||
self.tp = ThreadPool(num)
|
||||
|
||||
self.jobs = 0
|
||||
self.maxjobs = num
|
||||
|
||||
def start(self):
|
||||
|
@ -222,8 +217,12 @@ else:
|
|||
more tasks. If a task fails to execute (i.e. execute() raises
|
||||
an exception), then the job will stop."""
|
||||
|
||||
jobs = 0
|
||||
|
||||
while 1:
|
||||
if self.jobs < self.maxjobs:
|
||||
# Start up as many available tasks as we're
|
||||
# allowed to.
|
||||
while jobs < self.maxjobs:
|
||||
task = self.taskmaster.next_task()
|
||||
if task is None:
|
||||
break
|
||||
|
@ -234,26 +233,31 @@ else:
|
|||
except KeyboardInterrupt:
|
||||
raise
|
||||
except:
|
||||
# Let the failed() callback function arrange for the
|
||||
# build to stop if that's appropriate.
|
||||
task.failed()
|
||||
# Let the failed() callback function arrange
|
||||
# for the build to stop if that's appropriate.
|
||||
task.exception_set()
|
||||
self.tp.preparation_failed(task)
|
||||
jobs = jobs + 1
|
||||
continue
|
||||
|
||||
# dispatch task
|
||||
self.tp.put(task)
|
||||
self.jobs = self.jobs + 1
|
||||
jobs = jobs + 1
|
||||
|
||||
if not task and not jobs: break
|
||||
|
||||
# Let any/all completed tasks finish up before we go
|
||||
# back and put the next batch of tasks on the queue.
|
||||
while 1:
|
||||
try:
|
||||
task, ok = self.tp.get_nowait()
|
||||
except Queue.Empty:
|
||||
if not (self.jobs is self.maxjobs or self.taskmaster.is_blocked()):
|
||||
break
|
||||
task, ok = self.tp.get()
|
||||
|
||||
self.jobs = self.jobs - 1
|
||||
jobs = jobs - 1
|
||||
if ok:
|
||||
task.executed()
|
||||
else:
|
||||
task.failed()
|
||||
|
||||
task.postprocess()
|
||||
|
||||
if self.tp.resultsQueue.empty():
|
||||
break
|
272
scons/scons-local-0.97/SCons/Memoize.py
Normal file
272
scons/scons-local-0.97/SCons/Memoize.py
Normal file
|
@ -0,0 +1,272 @@
|
|||
#
|
||||
# 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/Memoize.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
__doc__ = """Memoizer
|
||||
|
||||
A metaclass implementation to count hits and misses of the computed
|
||||
values that various methods cache in memory.
|
||||
|
||||
Use of this modules assumes that wrapped methods be coded to cache their
|
||||
values in a consistent way. Here is an example of wrapping a method
|
||||
that returns a computed value, with no input parameters:
|
||||
|
||||
memoizer_counters = [] # Memoization
|
||||
|
||||
memoizer_counters.append(SCons.Memoize.CountValue('foo')) # Memoization
|
||||
|
||||
def foo(self):
|
||||
|
||||
try: # Memoization
|
||||
return self._memo['foo'] # Memoization
|
||||
except KeyError: # Memoization
|
||||
pass # Memoization
|
||||
|
||||
result = self.compute_foo_value()
|
||||
|
||||
self._memo['foo'] = result # Memoization
|
||||
|
||||
return result
|
||||
|
||||
Here is an example of wrapping a method that will return different values
|
||||
based on one or more input arguments:
|
||||
|
||||
def _bar_key(self, argument): # Memoization
|
||||
return argument # Memoization
|
||||
|
||||
memoizer_counters.append(SCons.Memoize.CountDict('bar', _bar_key)) # Memoization
|
||||
|
||||
def bar(self, argument):
|
||||
|
||||
memo_key = argument # Memoization
|
||||
try: # Memoization
|
||||
memo_dict = self._memo['bar'] # Memoization
|
||||
except KeyError: # Memoization
|
||||
memo_dict = {} # Memoization
|
||||
self._memo['dict'] = memo_dict # Memoization
|
||||
else: # Memoization
|
||||
try: # Memoization
|
||||
return memo_dict[memo_key] # Memoization
|
||||
except KeyError: # Memoization
|
||||
pass # Memoization
|
||||
|
||||
result = self.compute_bar_value(argument)
|
||||
|
||||
memo_dict[memo_key] = result # Memoization
|
||||
|
||||
return result
|
||||
|
||||
At one point we avoided replicating this sort of logic in all the methods
|
||||
by putting it right into this module, but we've moved away from that at
|
||||
present (see the "Historical Note," below.).
|
||||
|
||||
Deciding what to cache is tricky, because different configurations
|
||||
can have radically different performance tradeoffs, and because the
|
||||
tradeoffs involved are often so non-obvious. Consequently, deciding
|
||||
whether or not to cache a given method will likely be more of an art than
|
||||
a science, but should still be based on available data from this module.
|
||||
Here are some VERY GENERAL guidelines about deciding whether or not to
|
||||
cache return values from a method that's being called a lot:
|
||||
|
||||
-- The first question to ask is, "Can we change the calling code
|
||||
so this method isn't called so often?" Sometimes this can be
|
||||
done by changing the algorithm. Sometimes the *caller* should
|
||||
be memoized, not the method you're looking at.
|
||||
|
||||
-- The memoized function should be timed with multiple configurations
|
||||
to make sure it doesn't inadvertently slow down some other
|
||||
configuration.
|
||||
|
||||
-- When memoizing values based on a dictionary key composed of
|
||||
input arguments, you don't need to use all of the arguments
|
||||
if some of them don't affect the return values.
|
||||
|
||||
Historical Note: The initial Memoizer implementation actually handled
|
||||
the caching of values for the wrapped methods, based on a set of generic
|
||||
algorithms for computing hashable values based on the method's arguments.
|
||||
This collected caching logic nicely, but had two drawbacks:
|
||||
|
||||
Running arguments through a generic key-conversion mechanism is slower
|
||||
(and less flexible) than just coding these things directly. Since the
|
||||
methods that need memoized values are generally performance-critical,
|
||||
slowing them down in order to collect the logic isn't the right
|
||||
tradeoff.
|
||||
|
||||
Use of the memoizer really obscured what was being called, because
|
||||
all the memoized methods were wrapped with re-used generic methods.
|
||||
This made it more difficult, for example, to use the Python profiler
|
||||
to figure out how to optimize the underlying methods.
|
||||
"""
|
||||
|
||||
import new
|
||||
|
||||
# A flag controlling whether or not we actually use memoization.
|
||||
use_memoizer = None
|
||||
|
||||
CounterList = []
|
||||
|
||||
class Counter:
|
||||
"""
|
||||
Base class for counting memoization hits and misses.
|
||||
|
||||
We expect that the metaclass initialization will have filled in
|
||||
the .name attribute that represents the name of the function
|
||||
being counted.
|
||||
"""
|
||||
def __init__(self, method_name):
|
||||
"""
|
||||
"""
|
||||
self.method_name = method_name
|
||||
self.hit = 0
|
||||
self.miss = 0
|
||||
CounterList.append(self)
|
||||
def display(self):
|
||||
fmt = " %7d hits %7d misses %s()"
|
||||
print fmt % (self.hit, self.miss, self.name)
|
||||
def __cmp__(self, other):
|
||||
try:
|
||||
return cmp(self.name, other.name)
|
||||
except AttributeError:
|
||||
return 0
|
||||
|
||||
class CountValue(Counter):
|
||||
"""
|
||||
A counter class for simple, atomic memoized values.
|
||||
|
||||
A CountValue object should be instantiated in a class for each of
|
||||
the class's methods that memoizes its return value by simply storing
|
||||
the return value in its _memo dictionary.
|
||||
|
||||
We expect that the metaclass initialization will fill in the
|
||||
.underlying_method attribute with the method that we're wrapping.
|
||||
We then call the underlying_method method after counting whether
|
||||
its memoized value has already been set (a hit) or not (a miss).
|
||||
"""
|
||||
def __call__(self, *args, **kw):
|
||||
obj = args[0]
|
||||
if obj._memo.has_key(self.method_name):
|
||||
self.hit = self.hit + 1
|
||||
else:
|
||||
self.miss = self.miss + 1
|
||||
return apply(self.underlying_method, args, kw)
|
||||
|
||||
class CountDict(Counter):
|
||||
"""
|
||||
A counter class for memoized values stored in a dictionary, with
|
||||
keys based on the method's input arguments.
|
||||
|
||||
A CountDict object is instantiated in a class for each of the
|
||||
class's methods that memoizes its return value in a dictionary,
|
||||
indexed by some key that can be computed from one or more of
|
||||
its input arguments.
|
||||
|
||||
We expect that the metaclass initialization will fill in the
|
||||
.underlying_method attribute with the method that we're wrapping.
|
||||
We then call the underlying_method method after counting whether the
|
||||
computed key value is already present in the memoization dictionary
|
||||
(a hit) or not (a miss).
|
||||
"""
|
||||
def __init__(self, method_name, keymaker):
|
||||
"""
|
||||
"""
|
||||
Counter.__init__(self, method_name)
|
||||
self.keymaker = keymaker
|
||||
def __call__(self, *args, **kw):
|
||||
obj = args[0]
|
||||
try:
|
||||
memo_dict = obj._memo[self.method_name]
|
||||
except KeyError:
|
||||
self.miss = self.miss + 1
|
||||
else:
|
||||
key = apply(self.keymaker, args, kw)
|
||||
if memo_dict.has_key(key):
|
||||
self.hit = self.hit + 1
|
||||
else:
|
||||
self.miss = self.miss + 1
|
||||
return apply(self.underlying_method, args, kw)
|
||||
|
||||
class Memoizer:
|
||||
"""Object which performs caching of method calls for its 'primary'
|
||||
instance."""
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
# Find out if we support metaclasses (Python 2.2 and later).
|
||||
|
||||
class M:
|
||||
def __init__(cls, name, bases, cls_dict):
|
||||
cls.has_metaclass = 1
|
||||
|
||||
class A:
|
||||
__metaclass__ = M
|
||||
|
||||
try:
|
||||
has_metaclass = A.has_metaclass
|
||||
except AttributeError:
|
||||
has_metaclass = None
|
||||
|
||||
del M
|
||||
del A
|
||||
|
||||
if not has_metaclass:
|
||||
|
||||
def Dump(title):
|
||||
pass
|
||||
|
||||
class Memoized_Metaclass:
|
||||
# Just a place-holder so pre-metaclass Python versions don't
|
||||
# have to have special code for the Memoized classes.
|
||||
pass
|
||||
|
||||
def EnableMemoization():
|
||||
import SCons.Warnings
|
||||
msg = 'memoization is not supported in this version of Python (no metaclasses)'
|
||||
raise SCons.Warnings.NoMetaclassSupportWarning, msg
|
||||
|
||||
else:
|
||||
|
||||
def Dump(title=None):
|
||||
if title:
|
||||
print title
|
||||
CounterList.sort()
|
||||
for counter in CounterList:
|
||||
counter.display()
|
||||
|
||||
class Memoized_Metaclass(type):
|
||||
def __init__(cls, name, bases, cls_dict):
|
||||
super(Memoized_Metaclass, cls).__init__(name, bases, cls_dict)
|
||||
|
||||
for counter in cls_dict.get('memoizer_counters', []):
|
||||
method_name = counter.method_name
|
||||
|
||||
counter.name = cls.__name__ + '.' + method_name
|
||||
counter.underlying_method = cls_dict[method_name]
|
||||
|
||||
replacement_method = new.instancemethod(counter, None, cls)
|
||||
setattr(cls, method_name, replacement_method)
|
||||
|
||||
def EnableMemoization():
|
||||
global use_memoizer
|
||||
use_memoizer = 1
|
|
@ -8,7 +8,7 @@ This creates a hash of global Aliases (dummy targets).
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -30,8 +30,9 @@ This creates a hash of global Aliases (dummy targets).
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Node/Alias.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Node/Alias.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import string
|
||||
import UserDict
|
||||
|
||||
import SCons.Errors
|
||||
|
@ -39,19 +40,33 @@ import SCons.Node
|
|||
import SCons.Util
|
||||
|
||||
class AliasNameSpace(UserDict.UserDict):
|
||||
def Alias(self, name):
|
||||
if self.has_key(name):
|
||||
raise SCons.Errors.UserError
|
||||
self[name] = SCons.Node.Alias.Alias(name)
|
||||
return self[name]
|
||||
def Alias(self, name, **kw):
|
||||
if isinstance(name, SCons.Node.Alias.Alias):
|
||||
return name
|
||||
try:
|
||||
a = self[name]
|
||||
except KeyError:
|
||||
a = apply(SCons.Node.Alias.Alias, (name,), kw)
|
||||
self[name] = a
|
||||
return a
|
||||
|
||||
def lookup(self, name):
|
||||
def lookup(self, name, **kw):
|
||||
try:
|
||||
return self[name]
|
||||
except KeyError:
|
||||
return None
|
||||
|
||||
class AliasNodeInfo(SCons.Node.NodeInfoBase):
|
||||
pass
|
||||
|
||||
class AliasBuildInfo(SCons.Node.BuildInfoBase):
|
||||
pass
|
||||
|
||||
class Alias(SCons.Node.Node):
|
||||
|
||||
NodeInfo = AliasNodeInfo
|
||||
BuildInfo = AliasBuildInfo
|
||||
|
||||
def __init__(self, name):
|
||||
SCons.Node.Node.__init__(self)
|
||||
self.name = name
|
||||
|
@ -59,16 +74,9 @@ class Alias(SCons.Node.Node):
|
|||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def build(self):
|
||||
"""A "builder" for aliases."""
|
||||
pass
|
||||
|
||||
really_build = SCons.Node.Node.build
|
||||
current = SCons.Node.Node.children_are_up_to_date
|
||||
|
||||
def sconsign(self):
|
||||
"""An Alias is not recorded in .sconsign files"""
|
||||
pass
|
||||
|
||||
def is_under(self, dir):
|
||||
# Make Alias nodes get built regardless of
|
||||
# what directory scons was run from. Alias nodes
|
||||
|
@ -78,10 +86,26 @@ class Alias(SCons.Node.Node):
|
|||
def get_contents(self):
|
||||
"""The contents of an alias is the concatenation
|
||||
of all the contents of its sources"""
|
||||
contents = ""
|
||||
for kid in self.children(None):
|
||||
contents = contents + kid.get_contents()
|
||||
return contents
|
||||
contents = map(lambda n: n.get_contents(), self.children())
|
||||
return string.join(contents, '')
|
||||
|
||||
def sconsign(self):
|
||||
"""An Alias is not recorded in .sconsign files"""
|
||||
pass
|
||||
|
||||
#
|
||||
#
|
||||
#
|
||||
|
||||
def build(self):
|
||||
"""A "builder" for aliases."""
|
||||
pass
|
||||
|
||||
def convert(self):
|
||||
try: del self.builder
|
||||
except AttributeError: pass
|
||||
self.reset_executor()
|
||||
self.build = self.really_build
|
||||
|
||||
default_ans = AliasNameSpace()
|
||||
|
2418
scons/scons-local-0.97/SCons/Node/FS.py
Normal file
2418
scons/scons-local-0.97/SCons/Node/FS.py
Normal file
File diff suppressed because it is too large
Load diff
|
@ -5,7 +5,7 @@ Python nodes.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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,24 +27,36 @@ Python nodes.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Node/Python.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Node/Python.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import SCons.Node
|
||||
|
||||
class ValueNodeInfo(SCons.Node.NodeInfoBase):
|
||||
pass
|
||||
|
||||
class ValueBuildInfo(SCons.Node.BuildInfoBase):
|
||||
pass
|
||||
|
||||
class Value(SCons.Node.Node):
|
||||
"""A class for Python variables, typically passed on the command line
|
||||
or generated by a script, but not from a file or some other source.
|
||||
"""
|
||||
def __init__(self, value):
|
||||
|
||||
NodeInfo = ValueNodeInfo
|
||||
BuildInfo = ValueBuildInfo
|
||||
|
||||
def __init__(self, value, built_value=None):
|
||||
SCons.Node.Node.__init__(self)
|
||||
self.value = value
|
||||
if not built_value is None:
|
||||
self.built_value = built_value
|
||||
|
||||
def __str__(self):
|
||||
return repr(self.value)
|
||||
|
||||
def build(self):
|
||||
"""A "builder" for Values."""
|
||||
pass
|
||||
def build(self, **kw):
|
||||
if not hasattr(self, 'built_value'):
|
||||
apply (SCons.Node.Node.build, (self,), kw)
|
||||
|
||||
current = SCons.Node.Node.children_are_up_to_date
|
||||
|
||||
|
@ -54,25 +66,39 @@ class Value(SCons.Node.Node):
|
|||
# are outside the filesystem:
|
||||
return 1
|
||||
|
||||
def write(self, built_value):
|
||||
"""Set the value of the node."""
|
||||
self.built_value = built_value
|
||||
|
||||
def read(self):
|
||||
"""Return the value. If necessary, the value is built."""
|
||||
self.build()
|
||||
if not hasattr(self, 'built_value'):
|
||||
self.built_value = self.value
|
||||
return self.built_value
|
||||
|
||||
def get_contents(self):
|
||||
"""The contents of a Value are the concatenation
|
||||
of all the contents of its sources with the node's value itself."""
|
||||
"""By the assumption that the node.built_value is a
|
||||
deterministic product of the sources, the contents of a Value
|
||||
are the concatenation of all the contents of its sources. As
|
||||
the value need not be built when get_contents() is called, we
|
||||
cannot use the actual node.built_value."""
|
||||
contents = str(self.value)
|
||||
for kid in self.children(None):
|
||||
contents = contents + kid.get_contents()
|
||||
return contents
|
||||
|
||||
def calc_csig(self, calc=None):
|
||||
def get_csig(self, calc=None):
|
||||
"""Because we're a Python value node and don't have a real
|
||||
timestamp, we get to ignore the calculator and just use the
|
||||
value contents."""
|
||||
try:
|
||||
binfo = self.binfo
|
||||
except:
|
||||
except AttributeError:
|
||||
binfo = self.binfo = self.new_binfo()
|
||||
try:
|
||||
return binfo.csig
|
||||
return binfo.ninfo.csig
|
||||
except AttributeError:
|
||||
binfo.csig = self.get_contents()
|
||||
binfo.ninfo.csig = self.get_contents()
|
||||
self.store_info(binfo)
|
||||
return binfo.csig
|
||||
return binfo.ninfo.csig
|
File diff suppressed because it is too large
Load diff
|
@ -10,7 +10,7 @@ See http://optik.sourceforge.net/
|
|||
# Copyright (c) 2001 Gregory P. Ward. All rights reserved.
|
||||
# See the README.txt distributed with Optik for licensing terms.
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Optik/__init__.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Optik/__init__.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
# Original Optik revision this is based on:
|
||||
__Optik_revision__ = "__init__.py,v 1.11 2002/04/11 19:17:34 gward Exp"
|
|
@ -3,7 +3,7 @@
|
|||
Exception classes used by Optik.
|
||||
"""
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Optik/errors.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Optik/errors.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
# Original Optik revision this is based on:
|
||||
__Optik_revision__ = "errors.py,v 1.5 2002/02/13 23:29:47 gward Exp"
|
|
@ -3,7 +3,7 @@
|
|||
Defines the Option class and some standard value-checking functions.
|
||||
"""
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Optik/option.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Optik/option.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
# Original Optik revision this is based on:
|
||||
__Optik_revision__ = "option.py,v 1.19.2.1 2002/07/23 01:51:14 gward Exp"
|
|
@ -3,7 +3,7 @@
|
|||
Provides the OptionParser and Values classes.
|
||||
"""
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Optik/option_parser.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Optik/option_parser.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
# Original Optik revision this is based on:
|
||||
__Optik_revision__ = "option_parser.py,v 1.38.2.1 2002/07/23 01:51:14 gward Exp"
|
|
@ -12,7 +12,7 @@ Usage example:
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -34,20 +34,18 @@ Usage example:
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Options/BoolOption.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Options/BoolOption.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
__all__ = ('BoolOption', 'True', 'False')
|
||||
__all__ = ('BoolOption')
|
||||
|
||||
import string
|
||||
|
||||
import SCons.compat
|
||||
import SCons.Errors
|
||||
|
||||
__true_strings = ('y', 'yes', 'true', 't', '1', 'on' , 'all' )
|
||||
__false_strings = ('n', 'no', 'false', 'f', '0', 'off', 'none')
|
||||
|
||||
# we need this since SCons should work version indepentant
|
||||
True, False = 1, 0
|
||||
|
||||
|
||||
def _text2bool(val):
|
||||
"""
|
|
@ -15,7 +15,7 @@ Usage example:
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -37,7 +37,7 @@ Usage example:
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Options/EnumOption.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Options/EnumOption.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
__all__ = ('EnumOption',)
|
||||
|
|
@ -25,7 +25,7 @@ Usage example:
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -47,7 +47,7 @@ Usage example:
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Options/ListOption.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Options/ListOption.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
# Know Bug: This should behave like a Set-Type, but does not really,
|
||||
# since elements can occur twice.
|
||||
|
@ -57,6 +57,8 @@ __all__ = ('ListOption',)
|
|||
import string
|
||||
import UserList
|
||||
|
||||
import SCons.Util
|
||||
|
||||
|
||||
class _ListOption(UserList.UserList):
|
||||
def __init__(self, initlist=[], allowedElems=[]):
|
||||
|
@ -84,10 +86,10 @@ class _ListOption(UserList.UserList):
|
|||
return 'all'
|
||||
else:
|
||||
return string.join(self, ',')
|
||||
#def __repr__(self):
|
||||
# todo: implement this
|
||||
def __repr__(self):
|
||||
return self.__str__()
|
||||
|
||||
def _converter(val, allowedElems):
|
||||
def _converter(val, allowedElems, mapdict):
|
||||
"""
|
||||
"""
|
||||
if val == 'none':
|
||||
|
@ -96,10 +98,8 @@ def _converter(val, allowedElems):
|
|||
val = allowedElems
|
||||
else:
|
||||
val = filter(None, string.split(val, ','))
|
||||
notAllowed = []
|
||||
for v in val:
|
||||
if not v in allowedElems:
|
||||
notAllowed.append(v)
|
||||
val = map(lambda v, m=mapdict: m.get(v, v), val)
|
||||
notAllowed = filter(lambda v, aE=allowedElems: not v in aE, val)
|
||||
if notAllowed:
|
||||
raise ValueError("Invalid value(s) for option: %s" %
|
||||
string.join(notAllowed, ','))
|
||||
|
@ -113,7 +113,7 @@ def _converter(val, allowedElems):
|
|||
## return 1
|
||||
|
||||
|
||||
def ListOption(key, help, default, names):
|
||||
def ListOption(key, help, default, names, map={}):
|
||||
"""
|
||||
The input parameters describe a 'package list' option, thus they
|
||||
are returned with the correct converter and validater appended. The
|
||||
|
@ -123,9 +123,11 @@ def ListOption(key, help, default, names):
|
|||
package names (separated by space).
|
||||
"""
|
||||
names_str = 'allowed names: %s' % string.join(names, ' ')
|
||||
if SCons.Util.is_List(default):
|
||||
default = string.join(default, ',')
|
||||
help = string.join(
|
||||
(help, '(all|none|comma-separated list of names)', names_str),
|
||||
'\n ')
|
||||
return (key, help, default,
|
||||
None, #_validator,
|
||||
lambda val, elems=names: _converter(val, elems))
|
||||
lambda val, elems=names, m=map: _converter(val, elems, m))
|
|
@ -28,7 +28,7 @@ Usage example:
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -50,17 +50,17 @@ Usage example:
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Options/PackageOption.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Options/PackageOption.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
__all__ = ('PackageOption', 'True', 'False')
|
||||
__all__ = ('PackageOption')
|
||||
|
||||
import string
|
||||
|
||||
from BoolOption import True, False
|
||||
import SCons.compat
|
||||
import SCons.Errors
|
||||
|
||||
__enable_strings = (str(True), 'yes', 'true', 'on', 'enable', 'search')
|
||||
__disable_strings = (str(False), 'no', 'false', 'off', 'disable')
|
||||
__enable_strings = ('1', 'yes', 'true', 'on', 'enable', 'search')
|
||||
__disable_strings = ('0', 'no', 'false', 'off', 'disable')
|
||||
|
||||
def _converter(val):
|
||||
"""
|
||||
|
@ -78,12 +78,10 @@ def _validator(key, val, env, searchfunc):
|
|||
"""
|
||||
# todo: write validator, check for path
|
||||
import os
|
||||
if env[key] == False:
|
||||
pass
|
||||
elif env[key] == True:
|
||||
if env[key] is True:
|
||||
if searchfunc:
|
||||
env[key] = searchfunc(key, val)
|
||||
elif not os.path.exists(val):
|
||||
elif env[key] and not os.path.exists(val):
|
||||
raise SCons.Errors.UserError(
|
||||
'Path does not exist for option %s: %s' % (key, val))
|
||||
|
134
scons/scons-local-0.97/SCons/Options/PathOption.py
Normal file
134
scons/scons-local-0.97/SCons/Options/PathOption.py
Normal file
|
@ -0,0 +1,134 @@
|
|||
"""SCons.Options.PathOption
|
||||
|
||||
This file defines an option type for SCons implementing path settings.
|
||||
|
||||
To be used whenever a a user-specified path override should be allowed.
|
||||
|
||||
Arguments to PathOption are:
|
||||
option-name = name of this option on the command line (e.g. "prefix")
|
||||
option-help = help string for option
|
||||
option-dflt = default value for this option
|
||||
validator = [optional] validator for option value. Predefined
|
||||
validators are:
|
||||
|
||||
PathAccept -- accepts any path setting; no validation
|
||||
PathIsDir -- path must be an existing directory
|
||||
PathIsDirCreate -- path must be a dir; will create
|
||||
PathIsFile -- path must be a file
|
||||
PathExists -- path must exist (any type) [default]
|
||||
|
||||
The validator is a function that is called and which
|
||||
should return True or False to indicate if the path
|
||||
is valid. The arguments to the validator function
|
||||
are: (key, val, env). The key is the name of the
|
||||
option, the val is the path specified for the option,
|
||||
and the env is the env to which the Otions have been
|
||||
added.
|
||||
|
||||
Usage example:
|
||||
|
||||
Examples:
|
||||
prefix=/usr/local
|
||||
|
||||
opts = Options()
|
||||
|
||||
opts = Options()
|
||||
opts.Add(PathOption('qtdir',
|
||||
'where the root of Qt is installed',
|
||||
qtdir, PathIsDir))
|
||||
opts.Add(PathOption('qt_includes',
|
||||
'where the Qt includes are installed',
|
||||
'$qtdir/includes', PathIsDirCreate))
|
||||
opts.Add(PathOption('qt_libraries',
|
||||
'where the Qt library is installed',
|
||||
'$qtdir/lib'))
|
||||
|
||||
"""
|
||||
|
||||
#
|
||||
# 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/Options/PathOption.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import os
|
||||
import os.path
|
||||
|
||||
import SCons.Errors
|
||||
|
||||
class _PathOptionClass:
|
||||
|
||||
def PathAccept(self, key, val, env):
|
||||
"""Accepts any path, no checking done."""
|
||||
pass
|
||||
|
||||
def PathIsDir(self, key, val, env):
|
||||
"""Validator to check if Path is a directory."""
|
||||
if not os.path.isdir(val):
|
||||
if os.path.isfile(val):
|
||||
m = 'Directory path for option %s is a file: %s'
|
||||
else:
|
||||
m = 'Directory path for option %s does not exist: %s'
|
||||
raise SCons.Errors.UserError(m % (key, val))
|
||||
|
||||
def PathIsDirCreate(self, key, val, env):
|
||||
"""Validator to check if Path is a directory,
|
||||
creating it if it does not exist."""
|
||||
if os.path.isfile(val):
|
||||
m = 'Path for option %s is a file, not a directory: %s'
|
||||
raise SCons.Errors.UserError(m % (key, val))
|
||||
if not os.path.isdir(val):
|
||||
os.makedirs(val)
|
||||
|
||||
def PathIsFile(self, key, val, env):
|
||||
"""validator to check if Path is a file"""
|
||||
if not os.path.isfile(val):
|
||||
if os.path.isdir(val):
|
||||
m = 'File path for option %s is a directory: %s'
|
||||
else:
|
||||
m = 'File path for option %s does not exist: %s'
|
||||
raise SCons.Errors.UserError(m % (key, val))
|
||||
|
||||
def PathExists(self, key, val, env):
|
||||
"""validator to check if Path exists"""
|
||||
if not os.path.exists(val):
|
||||
m = 'Path for option %s does not exist: %s'
|
||||
raise SCons.Errors.UserError(m % (key, val))
|
||||
|
||||
def __call__(self, key, help, default, validator=None):
|
||||
# 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() .
|
||||
|
||||
The 'default' option specifies the default path to use if the
|
||||
user does not specify an override with this option.
|
||||
|
||||
validator is a validator, see this file for examples
|
||||
"""
|
||||
if validator is None:
|
||||
validator = self.PathExists
|
||||
return (key, '%s ( /path/to/%s )' % (help, key), default,
|
||||
validator, None)
|
||||
|
||||
PathOption = _PathOptionClass()
|
|
@ -5,7 +5,7 @@ customizable variables to an SCons build.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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,15 +27,16 @@ customizable variables to an SCons build.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Options/__init__.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Options/__init__.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import os.path
|
||||
import string
|
||||
|
||||
import SCons.Errors
|
||||
import SCons.Util
|
||||
import SCons.Warnings
|
||||
|
||||
from BoolOption import BoolOption, True, False # okay
|
||||
from BoolOption import BoolOption # okay
|
||||
from EnumOption import EnumOption # okay
|
||||
from ListOption import ListOption # naja
|
||||
from PackageOption import PackageOption # naja
|
||||
|
@ -75,6 +76,11 @@ class Options:
|
|||
|
||||
self.options.append(option)
|
||||
|
||||
def keys(self):
|
||||
"""
|
||||
Returns the keywords for the options
|
||||
"""
|
||||
return map(lambda o: o.key, self.options)
|
||||
|
||||
def Add(self, key, help="", default=None, validator=None, converter=None, **kw):
|
||||
"""
|
||||
|
@ -97,16 +103,8 @@ class Options:
|
|||
not SCons.Util.is_valid_construction_var(key):
|
||||
raise SCons.Errors.UserError, "Illegal Options.Add() key `%s'" % str(key)
|
||||
|
||||
if kw.has_key('validater'):
|
||||
SCons.Warnings.warn(SCons.Warnings.DeprecatedWarning,
|
||||
"The 'validater' keyword of the Options.Add() method is deprecated\n" +\
|
||||
"and should be changed to 'validator'.")
|
||||
if validator is None:
|
||||
validator = kw['validater']
|
||||
|
||||
self._do_add(key, help, default, validator, converter)
|
||||
|
||||
|
||||
def AddOptions(self, *optlist):
|
||||
"""
|
||||
Add a list of options.
|
||||
|
@ -164,15 +162,18 @@ class Options:
|
|||
for option in self.options:
|
||||
if option.converter and values.has_key(option.key):
|
||||
value = env.subst('${%s}'%option.key)
|
||||
try:
|
||||
try:
|
||||
env[option.key] = option.converter(value)
|
||||
except TypeError:
|
||||
env[option.key] = option.converter(value, env)
|
||||
except ValueError, x:
|
||||
raise SCons.Errors.UserError, 'Error converting option: %s\n%s'%(option.key, x)
|
||||
|
||||
|
||||
# Finally validate the values:
|
||||
for option in self.options:
|
||||
if option.validator:
|
||||
if option.validator and values.has_key(option.key):
|
||||
option.validator(option.key, env.subst('${%s}'%option.key), env)
|
||||
|
||||
def Save(self, filename, env):
|
||||
|
@ -203,8 +204,12 @@ class Options:
|
|||
# Convert stuff that has a repr() that
|
||||
# cannot be evaluated into a string
|
||||
value = SCons.Util.to_String(value)
|
||||
if env.subst('${%s}' % option.key) != \
|
||||
env.subst(SCons.Util.to_String(option.default)):
|
||||
|
||||
defaultVal = env.subst(SCons.Util.to_String(option.default))
|
||||
if option.converter:
|
||||
defaultVal = option.converter(defaultVal)
|
||||
|
||||
if str(env.subst('${%s}' % option.key)) != str(defaultVal):
|
||||
fh.write('%s = %s\n' % (option.key, repr(value)))
|
||||
except KeyError:
|
||||
pass
|
||||
|
@ -222,19 +227,23 @@ class Options:
|
|||
of the options.
|
||||
"""
|
||||
|
||||
help_text = ""
|
||||
|
||||
if sort:
|
||||
options = self.options[:]
|
||||
options.sort(lambda x,y,func=sort: func(x.key,y.key))
|
||||
else:
|
||||
options = self.options
|
||||
|
||||
for option in options:
|
||||
help_text = help_text + '\n%s: %s\n default: %s\n'%(option.key, option.help, option.default)
|
||||
if env.has_key(option.key):
|
||||
help_text = help_text + ' actual: %s\n'%env.subst('${%s}'%option.key)
|
||||
def format(opt, self=self, env=env):
|
||||
if env.has_key(opt.key):
|
||||
actual = env.subst('${%s}' % opt.key)
|
||||
else:
|
||||
help_text = help_text + ' actual: None\n'
|
||||
actual = None
|
||||
return self.FormatOptionHelpText(env, opt.key, opt.help, opt.default, actual)
|
||||
lines = filter(None, map(format, options))
|
||||
|
||||
return help_text
|
||||
return string.join(lines, '')
|
||||
|
||||
format = '\n%s: %s\n default: %s\n actual: %s\n'
|
||||
|
||||
def FormatOptionHelpText(self, env, key, help, default, actual):
|
||||
return self.format % (key, help, default, actual)
|
226
scons/scons-local-0.97/SCons/PathList.py
Normal file
226
scons/scons-local-0.97/SCons/PathList.py
Normal file
|
@ -0,0 +1,226 @@
|
|||
#
|
||||
# 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/PathList.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
__doc__ = """SCons.PathList
|
||||
|
||||
A module for handling lists of directory paths (the sort of things
|
||||
that get set as CPPPATH, LIBPATH, etc.) with as much caching of data and
|
||||
efficiency as we can while still keeping the evaluation delayed so that we
|
||||
Do the Right Thing (almost) regardless of how the variable is specified.
|
||||
|
||||
"""
|
||||
|
||||
import os
|
||||
import string
|
||||
|
||||
import SCons.Memoize
|
||||
import SCons.Node
|
||||
import SCons.Util
|
||||
|
||||
#
|
||||
# Variables to specify the different types of entries in a PathList object:
|
||||
#
|
||||
|
||||
TYPE_STRING_NO_SUBST = 0 # string with no '$'
|
||||
TYPE_STRING_SUBST = 1 # string containing '$'
|
||||
TYPE_OBJECT = 2 # other object
|
||||
|
||||
def node_conv(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:
|
||||
if isinstance(obj, SCons.Node.Node):
|
||||
result = obj
|
||||
else:
|
||||
result = str(obj)
|
||||
else:
|
||||
result = get()
|
||||
return result
|
||||
|
||||
class _PathList:
|
||||
"""
|
||||
An actual PathList object.
|
||||
"""
|
||||
def __init__(self, pathlist):
|
||||
"""
|
||||
Initializes a PathList object, canonicalizing the input and
|
||||
pre-processing it for quicker substitution later.
|
||||
|
||||
The stored representation of the PathList is a list of tuples
|
||||
containing (type, value), where the "type" is one of the TYPE_*
|
||||
variables defined above. We distinguish between:
|
||||
|
||||
strings that contain no '$' and therefore need no
|
||||
delayed-evaluation string substitution (we expect that there
|
||||
will be many of these and that we therefore get a pretty
|
||||
big win from avoiding string substitution)
|
||||
|
||||
strings that contain '$' and therefore need substitution
|
||||
(the hard case is things like '${TARGET.dir}/include',
|
||||
which require re-evaluation for every target + source)
|
||||
|
||||
other objects (which may be something like an EntryProxy
|
||||
that needs a method called to return a Node)
|
||||
|
||||
Pre-identifying the type of each element in the PathList up-front
|
||||
and storing the type in the list of tuples is intended to reduce
|
||||
the amount of calculation when we actually do the substitution
|
||||
over and over for each target.
|
||||
"""
|
||||
if SCons.Util.is_String(pathlist):
|
||||
pathlist = string.split(pathlist, os.pathsep)
|
||||
elif not SCons.Util.is_Sequence(pathlist):
|
||||
pathlist = [pathlist]
|
||||
|
||||
pl = []
|
||||
for p in pathlist:
|
||||
try:
|
||||
index = string.find(p, '$')
|
||||
except (AttributeError, TypeError):
|
||||
type = TYPE_OBJECT
|
||||
else:
|
||||
if index == -1:
|
||||
type = TYPE_STRING_NO_SUBST
|
||||
else:
|
||||
type = TYPE_STRING_SUBST
|
||||
pl.append((type, p))
|
||||
|
||||
self.pathlist = tuple(pl)
|
||||
|
||||
def __len__(self): return len(self.pathlist)
|
||||
|
||||
def __getitem__(self, i): return self.pathlist[i]
|
||||
|
||||
def subst_path(self, env, target, source):
|
||||
"""
|
||||
Performs construction variable substitution on a pre-digested
|
||||
PathList for a specific target and source.
|
||||
"""
|
||||
result = []
|
||||
for type, value in self.pathlist:
|
||||
if type == TYPE_STRING_SUBST:
|
||||
value = env.subst(value, target=target, source=source,
|
||||
conv=node_conv)
|
||||
if SCons.Util.is_Sequence(value):
|
||||
# It came back as a string or tuple, which in this
|
||||
# case usually means some variable expanded to an
|
||||
# actually Dir node. Concatenate the values.
|
||||
value = string.join(map(str, value), '')
|
||||
elif type == TYPE_OBJECT:
|
||||
value = node_conv(value)
|
||||
result.append(value)
|
||||
return tuple(result)
|
||||
|
||||
|
||||
class PathListCache:
|
||||
"""
|
||||
A class to handle caching of PathList lookups.
|
||||
|
||||
This class gets instantiated once and then deleted from the namespace,
|
||||
so it's used as a Singleton (although we don't enforce that in the
|
||||
usual Pythonic ways). We could have just made the cache a dictionary
|
||||
in the module namespace, but putting it in this class allows us to
|
||||
use the same Memoizer pattern that we use elsewhere to count cache
|
||||
hits and misses, which is very valuable.
|
||||
|
||||
Lookup keys in the cache are computed by the _PathList_key() method.
|
||||
Cache lookup should be quick, so we don't spend cycles canonicalizing
|
||||
all forms of the same lookup key. For example, 'x:y' and ['x',
|
||||
'y'] logically represent the same list, but we don't bother to
|
||||
split string representations and treat those two equivalently.
|
||||
(Note, however, that we do, treat lists and tuples the same.)
|
||||
|
||||
The main type of duplication we're trying to catch will come from
|
||||
looking up the same path list from two different clones of the
|
||||
same construction environment. That is, given
|
||||
|
||||
env2 = env1.Clone()
|
||||
|
||||
both env1 and env2 will have the same CPPPATH value, and we can
|
||||
cheaply avoid re-parsing both values of CPPPATH by using the
|
||||
common value from this cache.
|
||||
"""
|
||||
if SCons.Memoize.use_memoizer:
|
||||
__metaclass__ = SCons.Memoize.Memoized_Metaclass
|
||||
|
||||
memoizer_counters = []
|
||||
|
||||
def __init__(self):
|
||||
self._memo = {}
|
||||
|
||||
def _PathList_key(self, pathlist):
|
||||
"""
|
||||
Returns the key for memoization of PathLists.
|
||||
|
||||
Note that we want this to be pretty quick, so we don't completely
|
||||
canonicalize all forms of the same list. For example,
|
||||
'dir1:$ROOT/dir2' and ['$ROOT/dir1', 'dir'] may logically
|
||||
represent the same list if you're executing from $ROOT, but
|
||||
we're not going to bother splitting strings into path elements,
|
||||
or massaging strings into Nodes, to identify that equivalence.
|
||||
We just want to eliminate obvious redundancy from the normal
|
||||
case of re-using exactly the same cloned value for a path.
|
||||
"""
|
||||
if SCons.Util.is_Sequence(pathlist):
|
||||
pathlist = tuple(SCons.Util.flatten(pathlist))
|
||||
return pathlist
|
||||
|
||||
memoizer_counters.append(SCons.Memoize.CountDict('PathList', _PathList_key))
|
||||
|
||||
def PathList(self, pathlist):
|
||||
"""
|
||||
Returns the cached _PathList object for the specified pathlist,
|
||||
creating and caching a new object as necessary.
|
||||
"""
|
||||
pathlist = self._PathList_key(pathlist)
|
||||
try:
|
||||
memo_dict = self._memo['PathList']
|
||||
except KeyError:
|
||||
memo_dict = {}
|
||||
self._memo['PathList'] = memo_dict
|
||||
else:
|
||||
try:
|
||||
return memo_dict[pathlist]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
result = _PathList(pathlist)
|
||||
|
||||
memo_dict[pathlist] = result
|
||||
|
||||
return result
|
||||
|
||||
PathList = PathListCache().PathList
|
||||
|
||||
|
||||
del PathListCache
|
216
scons/scons-local-0.97/SCons/Platform/__init__.py
Normal file
216
scons/scons-local-0.97/SCons/Platform/__init__.py
Normal file
|
@ -0,0 +1,216 @@
|
|||
"""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, 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/Platform/__init__.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import imp
|
||||
import os
|
||||
import string
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
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__)
|
||||
try:
|
||||
mod = imp.load_module(full_name, file, path, desc)
|
||||
finally:
|
||||
if file:
|
||||
file.close()
|
||||
except ImportError:
|
||||
try:
|
||||
import zipimport
|
||||
importer = zipimport.zipimporter( sys.modules['SCons.Platform'].__path__[0] )
|
||||
mod = importer.load_module(full_name)
|
||||
except ImportError:
|
||||
raise SCons.Errors.UserError, "No platform named '%s'" % name
|
||||
setattr(SCons.Platform, name, mod)
|
||||
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
|
||||
|
||||
class TempFileMunge:
|
||||
"""A callable class. You can set an Environment variable to this,
|
||||
then call it with a string argument, then it will perform temporary
|
||||
file substitution on it. This is used to circumvent the long command
|
||||
line limitation.
|
||||
|
||||
Example usage:
|
||||
env["TEMPFILE"] = TempFileMunge
|
||||
env["LINKCOM"] = "${TEMPFILE('$LINK $TARGET $SOURCES')}"
|
||||
|
||||
By default, the name of the temporary file used begins with a
|
||||
prefix of '@'. This may be configred for other tool chains by
|
||||
setting '$TEMPFILEPREFIX'.
|
||||
|
||||
env["TEMPFILEPREFIX"] = '-@' # diab compiler
|
||||
env["TEMPFILEPREFIX"] = '-via' # arm tool chain
|
||||
"""
|
||||
def __init__(self, cmd):
|
||||
self.cmd = cmd
|
||||
|
||||
def __call__(self, target, source, env, for_signature):
|
||||
if for_signature:
|
||||
return self.cmd
|
||||
cmd = env.subst_list(self.cmd, 0, target, source)[0]
|
||||
try:
|
||||
maxline = int(env.subst('$MAXLINELENGTH'))
|
||||
except ValueError:
|
||||
maxline = 2048
|
||||
|
||||
if (reduce(lambda x, y: x + len(y), cmd, 0) + len(cmd)) <= maxline:
|
||||
return self.cmd
|
||||
|
||||
# We do a normpath because mktemp() has what appears to be
|
||||
# a bug in Windows that will use a forward slash as a path
|
||||
# delimiter. Windows's link mistakes that for a command line
|
||||
# switch and barfs.
|
||||
#
|
||||
# We use the .lnk suffix for the benefit of the Phar Lap
|
||||
# linkloc linker, which likes to append an .lnk suffix if
|
||||
# none is given.
|
||||
tmp = os.path.normpath(tempfile.mktemp('.lnk'))
|
||||
native_tmp = SCons.Util.get_native_path(tmp)
|
||||
|
||||
if env['SHELL'] and env['SHELL'] == 'sh':
|
||||
# The sh shell will try to escape the backslashes in the
|
||||
# path, so unescape them.
|
||||
native_tmp = string.replace(native_tmp, '\\', r'\\\\')
|
||||
# In Cygwin, we want to use rm to delete the temporary
|
||||
# file, because del does not exist in the sh shell.
|
||||
rm = env.Detect('rm') or 'del'
|
||||
else:
|
||||
# Don't use 'rm' if the shell is not sh, because rm won't
|
||||
# work with the Windows shells (cmd.exe or command.com) or
|
||||
# Windows path names.
|
||||
rm = 'del'
|
||||
|
||||
prefix = env.subst('$TEMPFILEPREFIX')
|
||||
if not prefix:
|
||||
prefix = '@'
|
||||
|
||||
args = map(SCons.Subst.quote_spaces, cmd[1:])
|
||||
open(tmp, 'w').write(string.join(args, " ") + "\n")
|
||||
# XXX Using the SCons.Action.print_actions value directly
|
||||
# like this is bogus, but expedient. This class should
|
||||
# really be rewritten as an Action that defines the
|
||||
# __call__() and strfunction() methods and lets the
|
||||
# normal action-execution logic handle whether or not to
|
||||
# print/execute the action. The problem, though, is all
|
||||
# of that is decided before we execute this method as
|
||||
# part of expanding the $TEMPFILE construction variable.
|
||||
# Consequently, refactoring this will have to wait until
|
||||
# we get more flexible with allowing Actions to exist
|
||||
# independently and get strung together arbitrarily like
|
||||
# Ant tasks. In the meantime, it's going to be more
|
||||
# user-friendly to not let obsession with architectural
|
||||
# purity get in the way of just being helpful, so we'll
|
||||
# reach into SCons.Action directly.
|
||||
if SCons.Action.print_actions:
|
||||
print("Using tempfile "+native_tmp+" for command line:\n"+
|
||||
str(cmd[0]) + " " + string.join(args," "))
|
||||
return [ cmd[0], prefix + native_tmp + '\n' + rm, native_tmp ]
|
||||
|
||||
def Platform(name = platform_default()):
|
||||
"""Select a canned Platform specification.
|
||||
"""
|
||||
module = platform_module(name)
|
||||
spec = PlatformSpec(name)
|
||||
spec.__call__ = module.generate
|
||||
return spec
|
|
@ -8,7 +8,7 @@ selection method.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -30,20 +30,23 @@ selection method.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Platform/aix.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Platform/aix.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import os
|
||||
import string
|
||||
|
||||
import posix
|
||||
|
||||
def get_xlc(env, xlc, xlc_r, packages):
|
||||
def get_xlc(env, xlc=None, xlc_r=None, packages=[]):
|
||||
# Use the AIX package installer tool lslpp to figure out where a
|
||||
# given xl* compiler is installed and what version it is.
|
||||
xlcPath = None
|
||||
xlcVersion = None
|
||||
|
||||
if xlc is None:
|
||||
xlc = env.get('CC', 'xlc')
|
||||
if xlc_r is None:
|
||||
xlc_r = xlc + '_r'
|
||||
for package in packages:
|
||||
cmd = "lslpp -fc " + package + " 2>/dev/null | egrep '" + xlc + "([^-_a-zA-Z0-9].*)?$'"
|
||||
line = os.popen(cmd).readline()
|
||||
|
@ -57,3 +60,6 @@ def get_xlc(env, xlc, xlc_r, packages):
|
|||
|
||||
def generate(env):
|
||||
posix.generate(env)
|
||||
#Based on AIX 5.2: ARG_MAX=24576 - 3000 for environment expansion
|
||||
env['MAXLINELENGTH'] = 21576
|
||||
|
|
@ -8,7 +8,7 @@ selection method.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -30,10 +30,10 @@ selection method.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Platform/cygwin.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Platform/cygwin.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import posix
|
||||
import win32
|
||||
from SCons.Platform import TempFileMunge
|
||||
|
||||
def generate(env):
|
||||
posix.generate(env)
|
||||
|
@ -44,4 +44,6 @@ def generate(env):
|
|||
env['SHLIBSUFFIX'] = '.dll'
|
||||
env['LIBPREFIXES'] = [ '$LIBPREFIX', '$SHLIBPREFIX' ]
|
||||
env['LIBSUFFIXES'] = [ '$LIBSUFFIX', '$SHLIBSUFFIX' ]
|
||||
env['TEMPFILE'] = win32.TempFileMunge
|
||||
env['TEMPFILE'] = TempFileMunge
|
||||
env['TEMPFILEPREFIX'] = '@'
|
||||
env['MAXLINELENGTH'] = 2048
|
|
@ -8,7 +8,7 @@ selection method.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -30,11 +30,11 @@ selection method.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Platform/darwin.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Platform/darwin.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import posix
|
||||
import os
|
||||
|
||||
def generate(env):
|
||||
posix.generate(env)
|
||||
env['SHLIBSUFFIX'] = '.dylib'
|
||||
env['ENV']['PATH'] = env['ENV']['PATH'] + ':/sw/bin'
|
|
@ -8,7 +8,7 @@ selection method.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -30,9 +30,11 @@ selection method.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Platform/hpux.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Platform/hpux.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import posix
|
||||
|
||||
def generate(env):
|
||||
posix.generate(env)
|
||||
#Based on HP-UX11i: ARG_MAX=2048000 - 3000 for environment expansion
|
||||
env['MAXLINELENGTH'] = 2045000
|
|
@ -8,7 +8,7 @@ selection method.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -30,7 +30,7 @@ selection method.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Platform/irix.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Platform/irix.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import posix
|
||||
|
|
@ -8,7 +8,7 @@ selection method.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -30,7 +30,7 @@ selection method.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Platform/os2.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Platform/os2.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
def generate(env):
|
||||
if not env.has_key('ENV'):
|
|
@ -8,7 +8,7 @@ selection method.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -30,7 +30,7 @@ selection method.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Platform/posix.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Platform/posix.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import os
|
||||
import os.path
|
||||
|
@ -40,6 +40,7 @@ import sys
|
|||
import select
|
||||
|
||||
import SCons.Util
|
||||
from SCons.Platform import TempFileMunge
|
||||
|
||||
exitvalmap = {
|
||||
2 : 127,
|
||||
|
@ -57,42 +58,28 @@ def escape(arg):
|
|||
|
||||
return '"' + arg + '"'
|
||||
|
||||
def _get_env_command(sh, escape, cmd, args, env):
|
||||
if env:
|
||||
s = 'env - '
|
||||
for key in env.keys():
|
||||
s = s + '%s=%s '%(key, escape(env[key]))
|
||||
s = s + sh + ' -c '
|
||||
s = s + escape(string.join(args))
|
||||
else:
|
||||
s = string.join(args)
|
||||
return s
|
||||
|
||||
def env_spawn(sh, escape, cmd, args, env):
|
||||
s = _get_env_command( sh, escape, cmd, args, env)
|
||||
stat = os.system(s)
|
||||
def exec_system(l, env):
|
||||
stat = os.system(string.join(l))
|
||||
if stat & 0xff:
|
||||
return stat | 0x80
|
||||
return stat >> 8
|
||||
|
||||
def spawn_spawn(sh, escape, cmd, args, env):
|
||||
args = [sh, '-c', string.join(args)]
|
||||
stat = os.spawnvpe(os.P_WAIT, sh, args, env)
|
||||
def exec_spawnvpe(l, env):
|
||||
stat = os.spawnvpe(os.P_WAIT, l[0], l, env)
|
||||
# os.spawnvpe() returns the actual exit code, not the encoding
|
||||
# returned by os.waitpid() or os.system().
|
||||
return stat
|
||||
|
||||
def fork_spawn(sh, escape, cmd, args, env):
|
||||
def exec_fork(l, env):
|
||||
pid = os.fork()
|
||||
if not pid:
|
||||
# Child process.
|
||||
exitval = 127
|
||||
args = [sh, '-c', string.join(args)]
|
||||
try:
|
||||
os.execvpe(sh, args, env)
|
||||
os.execvpe(l[0], l, env)
|
||||
except OSError, e:
|
||||
exitval = exitvalmap[e[0]]
|
||||
sys.stderr.write("scons: %s: %s\n" % (cmd, e[1]))
|
||||
exitval = exitvalmap.get(e[0], e[0])
|
||||
sys.stderr.write("scons: %s: %s\n" % (l[0], e[1]))
|
||||
os._exit(exitval)
|
||||
else:
|
||||
# Parent process.
|
||||
|
@ -101,6 +88,24 @@ def fork_spawn(sh, escape, cmd, args, env):
|
|||
return stat | 0x80
|
||||
return stat >> 8
|
||||
|
||||
def _get_env_command(sh, escape, cmd, args, env):
|
||||
s = string.join(args)
|
||||
if env:
|
||||
l = ['env', '-'] + \
|
||||
map(lambda t, e=escape: t[0]+'='+e(t[1]), env.items()) + \
|
||||
[sh, '-c', escape(s)]
|
||||
s = string.join(l)
|
||||
return s
|
||||
|
||||
def env_spawn(sh, escape, cmd, args, env):
|
||||
return exec_system([_get_env_command( sh, escape, cmd, args, env)], env)
|
||||
|
||||
def spawnvpe_spawn(sh, escape, cmd, args, env):
|
||||
return exec_spawnvpe([sh, '-c', string.join(args)], env)
|
||||
|
||||
def fork_spawn(sh, escape, cmd, args, env):
|
||||
return exec_fork([sh, '-c', string.join(args)], env)
|
||||
|
||||
def process_cmd_output(cmd_stdout, cmd_stderr, stdout, stderr):
|
||||
stdout_eof = stderr_eof = 0
|
||||
while not (stdout_eof and stderr_eof):
|
||||
|
@ -120,20 +125,15 @@ def process_cmd_output(cmd_stdout, cmd_stderr, stdout, stderr):
|
|||
#sys.__stderr__.write( "str(stderr) = %s\n" % str )
|
||||
stderr.write(str)
|
||||
|
||||
|
||||
def piped_env_spawn(sh, escape, cmd, args, env, stdout, stderr):
|
||||
# spawn using Popen3 combined with the env command
|
||||
# the command name and the command's stdout is written to stdout
|
||||
# the command's stderr is written to stderr
|
||||
s = _get_env_command( sh, escape, cmd, args, env)
|
||||
proc = popen2.Popen3(s, 1)
|
||||
def exec_popen3(l, env, stdout, stderr):
|
||||
proc = popen2.Popen3(string.join(l), 1)
|
||||
process_cmd_output(proc.fromchild, proc.childerr, stdout, stderr)
|
||||
stat = proc.wait()
|
||||
if stat & 0xff:
|
||||
return stat | 0x80
|
||||
return stat >> 8
|
||||
|
||||
def piped_fork_spawn(sh, escape, cmd, args, env, stdout, stderr):
|
||||
def exec_piped_fork(l, env, stdout, stderr):
|
||||
# spawn using fork / exec and providing a pipe for the command's
|
||||
# stdout / stderr stream
|
||||
if stdout != stderr:
|
||||
|
@ -156,12 +156,11 @@ def piped_fork_spawn(sh, escape, cmd, args, env, stdout, stderr):
|
|||
if stdout != stderr:
|
||||
os.close( wFdErr )
|
||||
exitval = 127
|
||||
args = [sh, '-c', string.join(args)]
|
||||
try:
|
||||
os.execvpe(sh, args, env)
|
||||
os.execvpe(l[0], l, env)
|
||||
except OSError, e:
|
||||
exitval = exitvalmap[e[0]]
|
||||
stderr.write("scons: %s: %s\n" % (cmd, e[1]))
|
||||
exitval = exitvalmap.get(e[0], e[0])
|
||||
stderr.write("scons: %s: %s\n" % (l[0], e[1]))
|
||||
os._exit(exitval)
|
||||
else:
|
||||
# Parent process
|
||||
|
@ -182,6 +181,19 @@ def piped_fork_spawn(sh, escape, cmd, args, env, stdout, stderr):
|
|||
return stat | 0x80
|
||||
return stat >> 8
|
||||
|
||||
def piped_env_spawn(sh, escape, cmd, args, env, stdout, stderr):
|
||||
# spawn using Popen3 combined with the env command
|
||||
# the command name and the command's stdout is written to stdout
|
||||
# the command's stderr is written to stderr
|
||||
return exec_popen3([_get_env_command(sh, escape, cmd, args, env)],
|
||||
env, stdout, stderr)
|
||||
|
||||
def piped_fork_spawn(sh, escape, cmd, args, env, stdout, stderr):
|
||||
# spawn using fork / exec and providing a pipe for the command's
|
||||
# stdout / stderr stream
|
||||
return exec_piped_fork([sh, '-c', string.join(args)],
|
||||
env, stdout, stderr)
|
||||
|
||||
|
||||
|
||||
def generate(env):
|
||||
|
@ -199,7 +211,7 @@ def generate(env):
|
|||
# not be a default that works best for all users.
|
||||
|
||||
if os.__dict__.has_key('spawnvpe'):
|
||||
spawn = spawn_spawn
|
||||
spawn = spawnvpe_spawn
|
||||
elif env.Detect('env'):
|
||||
spawn = env_spawn
|
||||
else:
|
||||
|
@ -212,7 +224,7 @@ def generate(env):
|
|||
|
||||
if not env.has_key('ENV'):
|
||||
env['ENV'] = {}
|
||||
env['ENV']['PATH'] = '/usr/local/bin:/bin:/usr/bin'
|
||||
env['ENV']['PATH'] = '/usr/local/bin:/opt/bin:/bin:/usr/bin'
|
||||
env['OBJPREFIX'] = ''
|
||||
env['OBJSUFFIX'] = '.o'
|
||||
env['SHOBJPREFIX'] = '$OBJPREFIX'
|
||||
|
@ -229,6 +241,11 @@ def generate(env):
|
|||
env['SPAWN'] = spawn
|
||||
env['SHELL'] = 'sh'
|
||||
env['ESCAPE'] = escape
|
||||
env['TEMPFILE'] = TempFileMunge
|
||||
env['TEMPFILEPREFIX'] = '@'
|
||||
#Based on LINUX: ARG_MAX=ARG_MAX=131072 - 3000 for environment expansion
|
||||
#Note: specific platforms might rise or lower this value
|
||||
env['MAXLINELENGTH'] = 128072
|
||||
|
||||
# This platform supports RPATH specifications.
|
||||
env['__RPATH'] = '$_RPATH'
|
|
@ -8,7 +8,7 @@ selection method.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -30,9 +30,15 @@ selection method.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Platform/sunos.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Platform/sunos.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import posix
|
||||
|
||||
def generate(env):
|
||||
posix.generate(env)
|
||||
# Based on sunSparc 8:32bit
|
||||
# ARG_MAX=1048320 - 3000 for environment expansion
|
||||
env['MAXLINELENGTH'] = 1045320
|
||||
env['PKGINFO'] = 'pkginfo'
|
||||
env['PKGCHK'] = '/usr/sbin/pkgchk'
|
||||
env['ENV']['PATH'] = env['ENV']['PATH'] + ':/usr/ccs/bin'
|
|
@ -8,7 +8,7 @@ selection method.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -30,89 +30,22 @@ selection method.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Platform/win32.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Platform/win32.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import os
|
||||
import os.path
|
||||
import string
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
from SCons.Platform.posix import exitvalmap
|
||||
from SCons.Platform import TempFileMunge
|
||||
|
||||
# XXX See note below about why importing SCons.Action should be
|
||||
# eventually refactored.
|
||||
import SCons.Action
|
||||
import SCons.Util
|
||||
|
||||
class TempFileMunge:
|
||||
"""A callable class. You can set an Environment variable to this,
|
||||
then call it with a string argument, then it will perform temporary
|
||||
file substitution on it. This is used to circumvent the win32 long command
|
||||
line limitation.
|
||||
|
||||
Example usage:
|
||||
env["TEMPFILE"] = TempFileMunge
|
||||
env["LINKCOM"] = "${TEMPFILE('$LINK $TARGET $SOURCES')}"
|
||||
"""
|
||||
def __init__(self, cmd):
|
||||
self.cmd = cmd
|
||||
|
||||
def __call__(self, target, source, env, for_signature):
|
||||
if for_signature:
|
||||
return self.cmd
|
||||
cmd = env.subst_list(self.cmd, 0, target, source)[0]
|
||||
try:
|
||||
maxline = int(env.subst('$MAXLINELENGTH'))
|
||||
except ValueError:
|
||||
maxline = 2048
|
||||
if (reduce(lambda x, y: x + len(y), cmd, 0) + len(cmd)) <= maxline:
|
||||
return self.cmd
|
||||
else:
|
||||
# We do a normpath because mktemp() has what appears to be
|
||||
# a bug in Win32 that will use a forward slash as a path
|
||||
# delimiter. Win32's link mistakes that for a command line
|
||||
# switch and barfs.
|
||||
#
|
||||
# We use the .lnk suffix for the benefit of the Phar Lap
|
||||
# linkloc linker, which likes to append an .lnk suffix if
|
||||
# none is given.
|
||||
tmp = os.path.normpath(tempfile.mktemp('.lnk'))
|
||||
native_tmp = SCons.Util.get_native_path(tmp)
|
||||
|
||||
if env['SHELL'] and env['SHELL'] == 'sh':
|
||||
# The sh shell will try to escape the backslashes in the
|
||||
# path, so unescape them.
|
||||
native_tmp = string.replace(native_tmp, '\\', r'\\\\')
|
||||
# In Cygwin, we want to use rm to delete the temporary
|
||||
# file, because del does not exist in the sh shell.
|
||||
rm = env.Detect('rm') or 'del'
|
||||
else:
|
||||
# Don't use 'rm' if the shell is not sh, because rm won't
|
||||
# work with the win32 shells (cmd.exe or command.com) or
|
||||
# win32 path names.
|
||||
rm = 'del'
|
||||
|
||||
args = map(SCons.Util.quote_spaces, cmd[1:])
|
||||
open(tmp, 'w').write(string.join(args, " ") + "\n")
|
||||
# XXX Using the SCons.Action.print_actions value directly
|
||||
# like this is bogus, but expedient. This class should
|
||||
# really be rewritten as an Action that defines the
|
||||
# __call__() and strfunction() methods and lets the
|
||||
# normal action-execution logic handle whether or not to
|
||||
# print/execute the action. The problem, though, is all
|
||||
# of that is decided before we execute this method as
|
||||
# part of expanding the $TEMPFILE construction variable.
|
||||
# Consequently, refactoring this will have to wait until
|
||||
# we get more flexible with allowing Actions to exist
|
||||
# independently and get strung together arbitrarily like
|
||||
# Ant tasks. In the meantime, it's going to be more
|
||||
# user-friendly to not let obsession with architectural
|
||||
# purity get in the way of just being helpful, so we'll
|
||||
# reach into SCons.Action directly.
|
||||
if SCons.Action.print_actions:
|
||||
print("Using tempfile "+native_tmp+" for command line:\n"+
|
||||
str(cmd[0]) + " " + string.join(args," "))
|
||||
return [ cmd[0], '@' + native_tmp + '\n' + rm, native_tmp ]
|
||||
|
||||
# The upshot of all this is that, if you are using Python 1.5.2,
|
||||
# you had better have cmd or command.com in your PATH when you run
|
||||
|
@ -157,7 +90,10 @@ def piped_spawn(sh, escape, cmd, args, env, stdout, stderr):
|
|||
ret = os.spawnve(os.P_WAIT, sh, args, env)
|
||||
except OSError, e:
|
||||
# catch any error
|
||||
try:
|
||||
ret = exitvalmap[e[0]]
|
||||
except KeyError:
|
||||
sys.stderr.write("scons: unknown OSError exception code %d - %s: %s\n" % (e[0], cmd, e[1]))
|
||||
if stderr != None:
|
||||
stderr.write("scons: %s: %s\n" % (cmd, e[1]))
|
||||
# copy child output from tempfiles to our streams
|
||||
|
@ -177,22 +113,40 @@ def piped_spawn(sh, escape, cmd, args, env, stdout, stderr):
|
|||
pass
|
||||
return ret
|
||||
|
||||
def exec_spawn(l, env):
|
||||
try:
|
||||
result = os.spawnve(os.P_WAIT, l[0], l, env)
|
||||
except OSError, e:
|
||||
try:
|
||||
result = exitvalmap[e[0]]
|
||||
sys.stderr.write("scons: %s: %s\n" % (l[0], e[1]))
|
||||
except KeyError:
|
||||
result = 127
|
||||
if len(l) > 2:
|
||||
if len(l[2]) < 1000:
|
||||
command = string.join(l[0:3])
|
||||
else:
|
||||
command = l[0]
|
||||
else:
|
||||
command = l[0]
|
||||
sys.stderr.write("scons: unknown OSError exception code %d - '%s': %s\n" % (e[0], command, e[1]))
|
||||
return result
|
||||
|
||||
def spawn(sh, escape, cmd, args, env):
|
||||
if not sh:
|
||||
sys.stderr.write("scons: Could not find command interpreter, is it in your PATH?\n")
|
||||
return 127
|
||||
else:
|
||||
try:
|
||||
args = [sh, '/C', escape(string.join(args)) ]
|
||||
ret = os.spawnve(os.P_WAIT, sh, args, env)
|
||||
except OSError, e:
|
||||
ret = exitvalmap[e[0]]
|
||||
sys.stderr.write("scons: %s: %s\n" % (cmd, e[1]))
|
||||
return ret
|
||||
return exec_spawn([sh, '/C', escape(string.join(args))], env)
|
||||
|
||||
# Windows does not allow special characters in file names anyway, so
|
||||
# no need for a complex escape function, we will just quote the arg.
|
||||
escape = lambda x: '"' + x + '"'
|
||||
# Windows does not allow special characters in file names anyway, so no
|
||||
# need for a complex escape function, we will just quote the arg, except
|
||||
# that "cmd /c" requires that if an argument ends with a backslash it
|
||||
# needs to be escaped so as not to interfere with closing double quote
|
||||
# that we add.
|
||||
def escape(x):
|
||||
if x[-1] == '\\':
|
||||
x = x + '\\'
|
||||
return '"' + x + '"'
|
||||
|
||||
# Get the windows system directory name
|
||||
def get_system_root():
|
||||
|
@ -298,9 +252,11 @@ def generate(env):
|
|||
# environment's ENV. This is a potential slippery slope, because we
|
||||
# *don't* want to make builds dependent on the user's environment by
|
||||
# default. We're doing this for SYSTEMROOT, though, because it's
|
||||
# needed for anything that uses sockets, and seldom changes. Weigh
|
||||
# the impact carefully before adding other variables to this list.
|
||||
import_env = [ 'SYSTEMROOT' ]
|
||||
# needed for anything that uses sockets, and seldom changes, and
|
||||
# for SYSTEMDRIVE because it's related.
|
||||
#
|
||||
# Weigh the impact carefully before adding other variables to this list.
|
||||
import_env = [ 'SYSTEMDRIVE', 'SYSTEMROOT', 'TEMP', 'TMP' ]
|
||||
for var in import_env:
|
||||
v = os.environ.get(var)
|
||||
if v:
|
||||
|
@ -323,5 +279,6 @@ def generate(env):
|
|||
env['SPAWN'] = spawn
|
||||
env['SHELL'] = cmd_interp
|
||||
env['TEMPFILE'] = TempFileMunge
|
||||
env['TEMPFILEPREFIX'] = '@'
|
||||
env['MAXLINELENGTH'] = 2048
|
||||
env['ESCAPE'] = escape
|
|
@ -4,7 +4,7 @@ Autoconf-like configuration support.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -26,11 +26,12 @@ Autoconf-like configuration support.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/SConf.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/SConf.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import cPickle
|
||||
import os
|
||||
import re
|
||||
import string
|
||||
import StringIO
|
||||
import sys
|
||||
import traceback
|
||||
import types
|
||||
|
@ -38,41 +39,286 @@ import types
|
|||
import SCons.Action
|
||||
import SCons.Builder
|
||||
import SCons.Errors
|
||||
import SCons.Job
|
||||
import SCons.Node.FS
|
||||
import SCons.Taskmaster
|
||||
import SCons.Util
|
||||
import SCons.Warnings
|
||||
import SCons.Conftest
|
||||
|
||||
# First i thought of using a different filesystem as the default_fs,
|
||||
# but it showed up that there are too many side effects in doing that.
|
||||
SConfFS=SCons.Node.FS.default_fs
|
||||
# Turn off the Conftest error logging
|
||||
SCons.Conftest.LogInputFiles = 0
|
||||
SCons.Conftest.LogErrorMessages = 0
|
||||
|
||||
# to be set, if we are in dry-run mode
|
||||
dryrun = 0
|
||||
|
||||
_ac_build_counter = 0
|
||||
_ac_config_counter = 0
|
||||
_activeSConfObjects = {}
|
||||
AUTO=0 # use SCons dependency scanning for up-to-date checks
|
||||
FORCE=1 # force all tests to be rebuilt
|
||||
CACHE=2 # force all tests to be taken from cache (raise an error, if necessary)
|
||||
cache_mode = AUTO
|
||||
|
||||
def SetCacheMode(mode):
|
||||
"""Set the Configure cache mode. mode must be one of "auto", "force",
|
||||
or "cache"."""
|
||||
global cache_mode
|
||||
if mode == "auto":
|
||||
cache_mode = AUTO
|
||||
elif mode == "force":
|
||||
cache_mode = FORCE
|
||||
elif mode == "cache":
|
||||
cache_mode = CACHE
|
||||
else:
|
||||
raise ValueError, "SCons.SConf.SetCacheMode: Unknown mode " + mode
|
||||
|
||||
progress_display = SCons.Util.display # will be overwritten by SCons.Script
|
||||
def SetProgressDisplay(display):
|
||||
"""Set the progress display to use (called from SCons.Script)"""
|
||||
global progress_display
|
||||
progress_display = display
|
||||
|
||||
SConfFS = None
|
||||
|
||||
_ac_build_counter = 0 # incremented, whenever TryBuild is called
|
||||
_ac_config_logs = {} # all config.log files created in this build
|
||||
_ac_config_hs = {} # all config.h files created in this build
|
||||
sconf_global = None # current sconf object
|
||||
|
||||
def _createConfigH(target, source, env):
|
||||
t = open(str(target[0]), "w")
|
||||
defname = re.sub('[^A-Za-z0-9_]', '_', string.upper(str(target[0])))
|
||||
t.write("""#ifndef %(DEFNAME)s_SEEN
|
||||
#define %(DEFNAME)s_SEEN
|
||||
|
||||
""" % {'DEFNAME' : defname})
|
||||
t.write(source[0].get_contents())
|
||||
t.write("""
|
||||
#endif /* %(DEFNAME)s_SEEN */
|
||||
""" % {'DEFNAME' : defname})
|
||||
t.close()
|
||||
|
||||
def _stringConfigH(target, source, env):
|
||||
return "scons: Configure: creating " + str(target[0])
|
||||
|
||||
def CreateConfigHBuilder(env):
|
||||
"""Called just before the building targets phase begins."""
|
||||
if len(_ac_config_hs) == 0:
|
||||
return
|
||||
action = SCons.Action.Action(_createConfigH,
|
||||
_stringConfigH)
|
||||
sconfigHBld = SCons.Builder.Builder(action=action)
|
||||
env.Append( BUILDERS={'SConfigHBuilder':sconfigHBld} )
|
||||
for k in _ac_config_hs.keys():
|
||||
env.SConfigHBuilder(k, env.Value(_ac_config_hs[k]))
|
||||
|
||||
class SConfWarning(SCons.Warnings.Warning):
|
||||
pass
|
||||
SCons.Warnings.enableWarningClass(SConfWarning)
|
||||
|
||||
# action to create the source
|
||||
# some error definitions
|
||||
class SConfError(SCons.Errors.UserError):
|
||||
def __init__(self,msg):
|
||||
SCons.Errors.UserError.__init__(self,msg)
|
||||
|
||||
class ConfigureDryRunError(SConfError):
|
||||
"""Raised when a file or directory needs to be updated during a Configure
|
||||
process, but the user requested a dry-run"""
|
||||
def __init__(self,target):
|
||||
if not isinstance(target, SCons.Node.FS.File):
|
||||
msg = 'Cannot create configure directory "%s" within a dry-run.' % str(target)
|
||||
else:
|
||||
msg = 'Cannot update configure test "%s" within a dry-run.' % str(target)
|
||||
SConfError.__init__(self,msg)
|
||||
|
||||
class ConfigureCacheError(SConfError):
|
||||
"""Raised when a use explicitely requested the cache feature, but the test
|
||||
is run the first time."""
|
||||
def __init__(self,target):
|
||||
SConfError.__init__(self, '"%s" is not yet built and cache is forced.' % str(target))
|
||||
|
||||
# define actions for building text files
|
||||
def _createSource( target, source, env ):
|
||||
fd = open(str(target[0]), "w")
|
||||
fd.write(env['SCONF_TEXT'])
|
||||
fd.write(source[0].get_contents())
|
||||
fd.close()
|
||||
|
||||
def _stringSource( target, source, env ):
|
||||
import string
|
||||
return (str(target[0]) + ' <-\n |' +
|
||||
string.replace( env['SCONF_TEXT'], "\n", "\n |" ) )
|
||||
string.replace( source[0].get_contents(),
|
||||
'\n', "\n |" ) )
|
||||
|
||||
# python 2.2 introduces types.BooleanType
|
||||
BooleanTypes = [types.IntType]
|
||||
if hasattr(types, 'BooleanType'): BooleanTypes.append(types.BooleanType)
|
||||
|
||||
class SConfBuildInfo(SCons.Node.FS.FileBuildInfo):
|
||||
"""
|
||||
Special build info for targets of configure tests. Additional members
|
||||
are result (did the builder succeed last time?) and string, which
|
||||
contains messages of the original build phase.
|
||||
"""
|
||||
result = None # -> 0/None -> no error, != 0 error
|
||||
string = None # the stdout / stderr output when building the target
|
||||
|
||||
def __init__(self, node, result, string, sig):
|
||||
SCons.Node.FS.FileBuildInfo.__init__(self, node)
|
||||
self.result = result
|
||||
self.string = string
|
||||
self.ninfo.bsig = sig
|
||||
|
||||
|
||||
class Streamer:
|
||||
"""
|
||||
'Sniffer' for a file-like writable object. Similar to the unix tool tee.
|
||||
"""
|
||||
def __init__(self, orig):
|
||||
self.orig = orig
|
||||
self.s = StringIO.StringIO()
|
||||
|
||||
def write(self, str):
|
||||
if self.orig:
|
||||
self.orig.write(str)
|
||||
self.s.write(str)
|
||||
|
||||
def writelines(self, lines):
|
||||
for l in lines:
|
||||
self.write(l + '\n')
|
||||
|
||||
def getvalue(self):
|
||||
"""
|
||||
Return everything written to orig since the Streamer was created.
|
||||
"""
|
||||
return self.s.getvalue()
|
||||
|
||||
def flush(self):
|
||||
if self.orig:
|
||||
self.orig.flush()
|
||||
self.s.flush()
|
||||
|
||||
|
||||
class SConfBuildTask(SCons.Taskmaster.Task):
|
||||
"""
|
||||
This is almost the same as SCons.Script.BuildTask. Handles SConfErrors
|
||||
correctly and knows about the current cache_mode.
|
||||
"""
|
||||
def display(self, message):
|
||||
if sconf_global.logstream:
|
||||
sconf_global.logstream.write("scons: Configure: " + message + "\n")
|
||||
|
||||
def display_cached_string(self, bi):
|
||||
"""
|
||||
Logs the original builder messages, given the SConfBuildInfo instance
|
||||
bi.
|
||||
"""
|
||||
if not isinstance(bi, SConfBuildInfo):
|
||||
SCons.Warnings.warn(SConfWarning,
|
||||
"The stored build information has an unexpected class.")
|
||||
else:
|
||||
self.display("The original builder output was:\n" +
|
||||
string.replace(" |" + str(bi.string),
|
||||
"\n", "\n |"))
|
||||
|
||||
def failed(self):
|
||||
# check, if the reason was a ConfigureDryRunError or a
|
||||
# ConfigureCacheError and if yes, reraise the exception
|
||||
exc_type = self.exc_info()[0]
|
||||
if issubclass(exc_type, SConfError):
|
||||
raise
|
||||
elif issubclass(exc_type, SCons.Errors.BuildError):
|
||||
# we ignore Build Errors (occurs, when a test doesn't pass)
|
||||
pass
|
||||
else:
|
||||
self.display('Caught exception while building "%s":\n' %
|
||||
self.targets[0])
|
||||
try:
|
||||
excepthook = sys.excepthook
|
||||
except AttributeError:
|
||||
# Earlier versions of Python don't have sys.excepthook...
|
||||
def excepthook(type, value, tb):
|
||||
traceback.print_tb(tb)
|
||||
print type, value
|
||||
apply(excepthook, self.exc_info())
|
||||
return SCons.Taskmaster.Task.failed(self)
|
||||
|
||||
def collect_node_states(self):
|
||||
# returns (is_up_to_date, cached_error, cachable)
|
||||
# where is_up_to_date is 1, if the node(s) are up_to_date
|
||||
# cached_error is 1, if the node(s) are up_to_date, but the
|
||||
# build will fail
|
||||
# cachable is 0, if some nodes are not in our cache
|
||||
is_up_to_date = 1
|
||||
cached_error = 0
|
||||
cachable = 1
|
||||
for t in self.targets:
|
||||
bi = t.get_stored_info()
|
||||
if isinstance(bi, SConfBuildInfo):
|
||||
if cache_mode == CACHE:
|
||||
t.set_state(SCons.Node.up_to_date)
|
||||
else:
|
||||
new_bsig = t.calc_signature(sconf_global.calc)
|
||||
if t.env.use_build_signature():
|
||||
old_bsig = bi.ninfo.bsig
|
||||
else:
|
||||
old_bsig = bi.ninfo.csig
|
||||
is_up_to_date = (is_up_to_date and new_bsig == old_bsig)
|
||||
cached_error = cached_error or bi.result
|
||||
else:
|
||||
# the node hasn't been built in a SConf context or doesn't
|
||||
# exist
|
||||
cachable = 0
|
||||
is_up_to_date = 0
|
||||
return (is_up_to_date, cached_error, cachable)
|
||||
|
||||
def execute(self):
|
||||
sconf = sconf_global
|
||||
|
||||
is_up_to_date, cached_error, cachable = self.collect_node_states()
|
||||
|
||||
if cache_mode == CACHE and not cachable:
|
||||
raise ConfigureCacheError(self.targets[0])
|
||||
elif cache_mode == FORCE:
|
||||
is_up_to_date = 0
|
||||
|
||||
if cached_error and is_up_to_date:
|
||||
self.display("Building \"%s\" failed in a previous run and all "
|
||||
"its sources are up to date." % str(self.targets[0]))
|
||||
self.display_cached_string(self.targets[0].get_stored_info())
|
||||
raise SCons.Errors.BuildError # will be 'caught' in self.failed
|
||||
elif is_up_to_date:
|
||||
self.display("\"%s\" is up to date." % str(self.targets[0]))
|
||||
self.display_cached_string(self.targets[0].get_stored_info())
|
||||
elif dryrun:
|
||||
raise ConfigureDryRunError(self.targets[0])
|
||||
else:
|
||||
# note stdout and stderr are the same here
|
||||
s = sys.stdout = sys.stderr = Streamer(sys.stdout)
|
||||
try:
|
||||
env = self.targets[0].get_build_env()
|
||||
env['PSTDOUT'] = env['PSTDERR'] = s
|
||||
try:
|
||||
sconf.cached = 0
|
||||
self.targets[0].build()
|
||||
finally:
|
||||
sys.stdout = sys.stderr = env['PSTDOUT'] = \
|
||||
env['PSTDERR'] = sconf.logstream
|
||||
except KeyboardInterrupt:
|
||||
raise
|
||||
except SystemExit:
|
||||
exc_value = sys.exc_info()[1]
|
||||
raise SCons.Errors.ExplicitExit(self.targets[0],exc_value.code)
|
||||
except:
|
||||
for t in self.targets:
|
||||
sig = t.calc_signature(sconf.calc)
|
||||
string = s.getvalue()
|
||||
binfo = SConfBuildInfo(t,1,string,sig)
|
||||
t.dir.sconsign().set_entry(t.name, binfo)
|
||||
raise
|
||||
else:
|
||||
for t in self.targets:
|
||||
sig = t.calc_signature(sconf.calc)
|
||||
string = s.getvalue()
|
||||
binfo = SConfBuildInfo(t,0,string,sig)
|
||||
t.dir.sconsign().set_entry(t.name, binfo)
|
||||
|
||||
class SConf:
|
||||
"""This is simply a class to represent a configure context. After
|
||||
creating a SConf object, you can call any tests. After finished with your
|
||||
|
@ -86,30 +332,29 @@ class SConf:
|
|||
SConf run, we need to explicitely cache this error.
|
||||
"""
|
||||
|
||||
def __init__(self, env, custom_tests = {}, conf_dir='#/.sconf_temp',
|
||||
log_file='#/config.log'):
|
||||
def __init__(self, env, custom_tests = {}, conf_dir='$CONFIGUREDIR',
|
||||
log_file='$CONFIGURELOG', config_h = None, _depth = 0):
|
||||
"""Constructor. Pass additional tests in the custom_tests-dictinary,
|
||||
e.g. custom_tests={'CheckPrivate':MyPrivateTest}, where MyPrivateTest
|
||||
defines a custom test.
|
||||
Note also the conf_dir and log_file arguments (you may want to
|
||||
build tests in the BuildDir, not in the SourceDir)
|
||||
"""
|
||||
import SCons.Script.SConscript
|
||||
if not SCons.Script.SConscript.sconscript_reading:
|
||||
raise SCons.Errors.UserError, "Calling Configure from Builders is not supported."
|
||||
global SConfFS
|
||||
if not SConfFS:
|
||||
SConfFS = SCons.Node.FS.FS(SCons.Node.FS.default_fs.pathTop)
|
||||
if len(_activeSConfObjects.keys()) > 0:
|
||||
SConfFS = SCons.Node.FS.default_fs or \
|
||||
SCons.Node.FS.FS(env.fs.pathTop)
|
||||
if not sconf_global is None:
|
||||
raise (SCons.Errors.UserError,
|
||||
"Only one SConf object may be active at one time")
|
||||
self.env = env
|
||||
if log_file != None:
|
||||
self.logfile = SConfFS.File(log_file)
|
||||
else:
|
||||
self.logfile = None
|
||||
log_file = SConfFS.File(env.subst(log_file))
|
||||
self.logfile = log_file
|
||||
self.logstream = None
|
||||
self.lastTarget = None
|
||||
self.depth = _depth
|
||||
self.cached = 0 # will be set, if all test results are cached
|
||||
|
||||
# add default tests
|
||||
default_tests = {
|
||||
|
@ -123,83 +368,24 @@ class SConf:
|
|||
}
|
||||
self.AddTests(default_tests)
|
||||
self.AddTests(custom_tests)
|
||||
self.confdir = SConfFS.Dir(conf_dir)
|
||||
self.confdir = SConfFS.Dir(env.subst(conf_dir))
|
||||
self.calc = None
|
||||
self.cache = {}
|
||||
if not config_h is None:
|
||||
config_h = SConfFS.File(config_h)
|
||||
self.config_h = config_h
|
||||
self._startup()
|
||||
|
||||
def Finish(self):
|
||||
"""Call this method after finished with your tests:
|
||||
env = sconf.Finish()"""
|
||||
global _lastSConfObj
|
||||
_lastSConfObj = None
|
||||
self._shutdown()
|
||||
return self.env
|
||||
|
||||
def _setCache(self, nodes, already_done = []):
|
||||
# Set up actions used for caching errors
|
||||
# Caching positive tests should not be necessary, cause
|
||||
# the build system knows, if test objects/programs/outputs
|
||||
# are up to date.
|
||||
for n in nodes:
|
||||
# The 'n in already_done' expression is not really efficient.
|
||||
# We may do something more sophisticated in the future :-),
|
||||
# but there should not be that many dependencies in configure
|
||||
# tests
|
||||
if (n.has_builder() and
|
||||
not n in already_done):
|
||||
n.add_pre_action(SCons.Action.Action(self._preCache,
|
||||
self._stringCache))
|
||||
n.add_post_action(SCons.Action.Action(self._postCache,
|
||||
self._stringCache))
|
||||
already_done.append( n )
|
||||
self._setCache(n.children())
|
||||
|
||||
# Calling children() has set up the implicit cache (and
|
||||
# other state), but we're not really building things yet,
|
||||
# so generated files won't have been generated. Clear the
|
||||
# state so we will, in fact, build everything that's necessary
|
||||
# when we do the build.
|
||||
#
|
||||
# XXX - it would be good to find a better way to do this,
|
||||
# maybe by doing something with the actions in the actual
|
||||
# Taskmaster...?
|
||||
n.clear()
|
||||
|
||||
def BuildNodes(self, nodes):
|
||||
"""
|
||||
Tries to build the given nodes immediately. Returns 1 on success,
|
||||
0 on error.
|
||||
"""
|
||||
|
||||
global SCons
|
||||
import SCons.Script # really ugly, but we need BuildTask :-(
|
||||
# Is it better to provide a seperate Task for SConf builds ?
|
||||
class SConfBuildTask(SCons.Script.BuildTask):
|
||||
"""Errors in SConf builds are not fatal, so we override
|
||||
the do_failed method"""
|
||||
def do_failed(self, status=2):
|
||||
pass
|
||||
|
||||
class SConfDryRunTask(SConfBuildTask):
|
||||
"""Raise ConfiugreDryRunErrors whenever a target is to
|
||||
be built. Pass these Errors to the main script."""
|
||||
def execute(self):
|
||||
target = self.targets[0]
|
||||
if (target.get_state() != SCons.Node.up_to_date and
|
||||
target.has_builder() and
|
||||
not hasattr(target.builder, 'status')):
|
||||
|
||||
raise SCons.Errors.ConfigureDryRunError(target)
|
||||
|
||||
def failed(self):
|
||||
exc_type, exc_value = self.exc_info()[:2]
|
||||
if exc_type == SCons.Errors.ConfigureDryRunError:
|
||||
raise exc_type, exc_value
|
||||
# Should be SConfBuildTask.failed(), really,
|
||||
# but that causes name errors in Python 1.5.2.
|
||||
SCons.Script.BuildTask.failed(self)
|
||||
|
||||
if self.logstream != None:
|
||||
# override stdout / stderr to write in log file
|
||||
oldStdout = sys.stdout
|
||||
|
@ -212,26 +398,16 @@ class SConf:
|
|||
old_os_dir = os.getcwd()
|
||||
SConfFS.chdir(SConfFS.Top, change_os_dir=1)
|
||||
|
||||
self._setCache( nodes )
|
||||
ret = 1
|
||||
|
||||
try:
|
||||
# ToDo: use user options for calc
|
||||
self.calc = SCons.Sig.Calculator(max_drift=0)
|
||||
if dryrun:
|
||||
buildTask = SConfDryRunTask
|
||||
else:
|
||||
buildTask = SConfBuildTask
|
||||
tm = SCons.Taskmaster.Taskmaster( nodes, buildTask )
|
||||
save_max_drift = SConfFS.get_max_drift()
|
||||
SConfFS.set_max_drift(0)
|
||||
tm = SCons.Taskmaster.Taskmaster(nodes, SConfBuildTask)
|
||||
# we don't want to build tests in parallel
|
||||
jobs = SCons.Job.Jobs(1, tm )
|
||||
try:
|
||||
jobs.run()
|
||||
except SCons.Errors.BuildError, e:
|
||||
sys.stderr.write("scons: *** [%s] %s\n" % (e.node, e.errstr))
|
||||
if e.errstr == 'Exception':
|
||||
traceback.print_exception(e.args[0], e.args[1], e.args[2])
|
||||
|
||||
for n in nodes:
|
||||
state = n.get_state()
|
||||
if (state != SCons.Node.executed and
|
||||
|
@ -239,6 +415,7 @@ class SConf:
|
|||
# the node could not be built. we return 0 in this case
|
||||
ret = 0
|
||||
finally:
|
||||
SConfFS.set_max_drift(save_max_drift)
|
||||
os.chdir(old_os_dir)
|
||||
SConfFS.chdir(old_fs_dir, change_os_dir=0)
|
||||
if self.logstream != None:
|
||||
|
@ -247,6 +424,18 @@ class SConf:
|
|||
sys.stderr = oldStderr
|
||||
return ret
|
||||
|
||||
def pspawn_wrapper(self, sh, escape, cmd, args, env):
|
||||
"""Wrapper function for handling piped spawns.
|
||||
|
||||
This looks to the calling interface (in Action.py) like a "normal"
|
||||
spawn, but associates the call with the PSPAWN variable from
|
||||
the construction environment and with the streams to which we
|
||||
want the output logged. This gets slid into the construction
|
||||
environment as the SPAWN variable so Action.py doesn't have to
|
||||
know or care whether it's spawning a piped command or not.
|
||||
"""
|
||||
return self.pspawn(sh, escape, cmd, args, env, self.logstream, self.logstream)
|
||||
|
||||
|
||||
def TryBuild(self, builder, text = None, extension = ""):
|
||||
"""Low level TryBuild implementation. Normally you don't need to
|
||||
|
@ -254,21 +443,36 @@ class SConf:
|
|||
"""
|
||||
global _ac_build_counter
|
||||
|
||||
# Make sure we have a PSPAWN value, and save the current
|
||||
# SPAWN value.
|
||||
try:
|
||||
self.pspawn = self.env['PSPAWN']
|
||||
except KeyError:
|
||||
raise SCons.Errors.UserError('Missing PSPAWN construction variable.')
|
||||
try:
|
||||
save_spawn = self.env['SPAWN']
|
||||
except KeyError:
|
||||
raise SCons.Errors.UserError('Missing SPAWN construction variable.')
|
||||
|
||||
nodesToBeBuilt = []
|
||||
|
||||
f = "conftest_" + str(_ac_build_counter)
|
||||
pref = self.env.subst( builder.builder.prefix )
|
||||
suff = self.env.subst( builder.builder.suffix )
|
||||
target = self.confdir.File(pref + f + suff)
|
||||
self.env['SCONF_TEXT'] = text
|
||||
self.env['PIPE_BUILD'] = 1
|
||||
self.env['PSTDOUT'] = self.logstream
|
||||
self.env['PSTDERR'] = self.logstream
|
||||
|
||||
try:
|
||||
# Slide our wrapper into the construction environment as
|
||||
# the SPAWN function.
|
||||
self.env['SPAWN'] = self.pspawn_wrapper
|
||||
sourcetext = self.env.Value(text)
|
||||
|
||||
if text != None:
|
||||
source = self.confdir.File(f + extension)
|
||||
sourceNode = self.env.SConfSourceBuilder(target=source,
|
||||
source=None)
|
||||
nodesToBeBuilt.extend(sourceNode)
|
||||
textFile = self.confdir.File(f + extension)
|
||||
textFileNode = self.env.SConfSourceBuilder(target=textFile,
|
||||
source=sourcetext)
|
||||
nodesToBeBuilt.extend(textFileNode)
|
||||
source = textFileNode
|
||||
else:
|
||||
source = None
|
||||
|
||||
|
@ -276,21 +480,18 @@ class SConf:
|
|||
if not SCons.Util.is_List(nodes):
|
||||
nodes = [nodes]
|
||||
nodesToBeBuilt.extend(nodes)
|
||||
ret = self.BuildNodes(nodesToBeBuilt)
|
||||
result = self.BuildNodes(nodesToBeBuilt)
|
||||
|
||||
# clean up environment
|
||||
del self.env['PIPE_BUILD']
|
||||
del self.env['PSTDOUT']
|
||||
del self.env['PSTDERR']
|
||||
del self.env['SCONF_TEXT']
|
||||
finally:
|
||||
self.env['SPAWN'] = save_spawn
|
||||
|
||||
_ac_build_counter = _ac_build_counter + 1
|
||||
if ret:
|
||||
if result:
|
||||
self.lastTarget = nodes[0]
|
||||
else:
|
||||
self.lastTarget = None
|
||||
|
||||
return ret
|
||||
return result
|
||||
|
||||
def TryAction(self, action, text = None, extension = ""):
|
||||
"""Tries to execute the given action with optional source file
|
||||
|
@ -352,6 +553,8 @@ class SConf:
|
|||
"Test called after sconf.Finish()")
|
||||
context = CheckContext(self.sconf)
|
||||
ret = apply(self.test, (context,) + args, kw)
|
||||
if not self.sconf.config_h is None:
|
||||
self.sconf.config_h_text = self.sconf.config_h_text + context.config_h
|
||||
context.Result("error: no result")
|
||||
return ret
|
||||
|
||||
|
@ -367,75 +570,11 @@ class SConf:
|
|||
for name in tests.keys():
|
||||
self.AddTest(name, tests[name])
|
||||
|
||||
def _preCache(self, target, source, env):
|
||||
# Action before target is actually built
|
||||
#
|
||||
# We record errors in the cache. Only non-exisiting targets may
|
||||
# have recorded errors
|
||||
needs_rebuild = target[0].exists()
|
||||
buildSig = target[0].calc_signature(self.calc)
|
||||
for node in source:
|
||||
if node.get_state() != SCons.Node.up_to_date:
|
||||
# if any of the sources has changed, we cannot use our cache
|
||||
needs_rebuild = 1
|
||||
tname = str(target[0])
|
||||
if not self.cache.has_key( tname ):
|
||||
# We have no recorded error, so we try to build the target
|
||||
needs_rebuild = 1
|
||||
else:
|
||||
lastBuildSig = self.cache[tname]['builder']
|
||||
if lastBuildSig != buildSig:
|
||||
needs_rebuild = 1
|
||||
if not needs_rebuild:
|
||||
# When we are here, we can savely pass the recorded error
|
||||
print ('(cached): Building "%s" failed in a previous run.' %
|
||||
target[0])
|
||||
return 1
|
||||
else:
|
||||
# Otherwise, we try to record an error
|
||||
self.cache[tname] = {
|
||||
'builder' : buildSig
|
||||
}
|
||||
|
||||
def _postCache(self, target, source, env):
|
||||
# Action after target is successfully built
|
||||
#
|
||||
# No error during build -> remove the recorded error
|
||||
del self.cache[str(target[0])]
|
||||
|
||||
def _stringCache(self, target, source, env):
|
||||
return None
|
||||
|
||||
def _loadCache(self):
|
||||
# try to load build-error cache
|
||||
try:
|
||||
cacheDesc = cPickle.load(open(str(self.confdir.File(".cache"))))
|
||||
if cacheDesc['scons_version'] != SCons.__version__:
|
||||
raise Exception, "version mismatch"
|
||||
self.cache = cacheDesc['data']
|
||||
except KeyboardInterrupt:
|
||||
raise
|
||||
except:
|
||||
self.cache = {}
|
||||
|
||||
def _dumpCache(self):
|
||||
if dryrun:
|
||||
return
|
||||
# try to dump build-error cache
|
||||
try:
|
||||
cacheDesc = {'scons_version' : SCons.__version__,
|
||||
'data' : self.cache }
|
||||
cPickle.dump(cacheDesc, open(str(self.confdir.File(".cache")),"w"))
|
||||
except Exception, e:
|
||||
# this is most likely not only an IO error, but an error
|
||||
# inside SConf ...
|
||||
SCons.Warnings.warn( SConfWarning, "Couldn't dump SConf cache" )
|
||||
|
||||
def _createDir( self, node ):
|
||||
dirName = str(node)
|
||||
if dryrun:
|
||||
if not os.path.isdir( dirName ):
|
||||
raise SCons.Errors.ConfigureDryRunError(dirName)
|
||||
raise ConfigureDryRunError(dirName)
|
||||
else:
|
||||
if not os.path.isdir( dirName ):
|
||||
os.makedirs( dirName )
|
||||
|
@ -445,8 +584,8 @@ class SConf:
|
|||
"""Private method. Set up logstream, and set the environment
|
||||
variables necessary for a piped build
|
||||
"""
|
||||
global _ac_config_counter
|
||||
global _activeSConfObjects
|
||||
global _ac_config_logs
|
||||
global sconf_global
|
||||
global SConfFS
|
||||
|
||||
self.lastEnvFs = self.env.fs
|
||||
|
@ -457,41 +596,44 @@ class SConf:
|
|||
if self.logfile != None and not dryrun:
|
||||
# truncate logfile, if SConf.Configure is called for the first time
|
||||
# in a build
|
||||
if _ac_config_counter == 0:
|
||||
log_mode = "w"
|
||||
else:
|
||||
if _ac_config_logs.has_key(self.logfile):
|
||||
log_mode = "a"
|
||||
self.logstream = open(str(self.logfile), log_mode)
|
||||
else:
|
||||
_ac_config_logs[self.logfile] = None
|
||||
log_mode = "w"
|
||||
fp = open(str(self.logfile), log_mode)
|
||||
self.logstream = SCons.Util.Unbuffered(fp)
|
||||
# logfile may stay in a build directory, so we tell
|
||||
# the build system not to override it with a eventually
|
||||
# existing file with the same name in the source directory
|
||||
self.logfile.dir.add_ignore( [self.logfile] )
|
||||
|
||||
tb = traceback.extract_stack()[-3]
|
||||
|
||||
self.logstream.write( '\nfile %s,line %d:\n\tConfigure( confdir = %s )\n\n' %
|
||||
tb = traceback.extract_stack()[-3-self.depth]
|
||||
old_fs_dir = SConfFS.getcwd()
|
||||
SConfFS.chdir(SConfFS.Top, change_os_dir=0)
|
||||
self.logstream.write('file %s,line %d:\n\tConfigure(confdir = %s)\n' %
|
||||
(tb[0], tb[1], str(self.confdir)) )
|
||||
SConfFS.chdir(old_fs_dir)
|
||||
else:
|
||||
self.logstream = None
|
||||
# we use a special builder to create source files from TEXT
|
||||
action = SCons.Action.Action(_createSource,
|
||||
_stringSource,
|
||||
varlist=['SCONF_TEXT'])
|
||||
_stringSource)
|
||||
sconfSrcBld = SCons.Builder.Builder(action=action)
|
||||
self.env.Append( BUILDERS={'SConfSourceBuilder':sconfSrcBld} )
|
||||
self.config_h_text = _ac_config_hs.get(self.config_h, "")
|
||||
self.active = 1
|
||||
# only one SConf instance should be active at a time ...
|
||||
_activeSConfObjects[self] = None
|
||||
_ac_config_counter = _ac_config_counter + 1
|
||||
self._loadCache()
|
||||
sconf_global = self
|
||||
|
||||
def _shutdown(self):
|
||||
"""Private method. Reset to non-piped spawn"""
|
||||
global _activeSConfObjets
|
||||
global sconf_global, _ac_config_hs
|
||||
|
||||
if not self.active:
|
||||
raise SCons.Errors.UserError, "Finish may be called only once!"
|
||||
if self.logstream != None:
|
||||
if self.logstream != None and not dryrun:
|
||||
self.logstream.write("\n")
|
||||
self.logstream.close()
|
||||
self.logstream = None
|
||||
# remove the SConfSourceBuilder from the environment
|
||||
|
@ -499,8 +641,9 @@ class SConf:
|
|||
del blds['SConfSourceBuilder']
|
||||
self.env.Replace( BUILDERS=blds )
|
||||
self.active = 0
|
||||
del _activeSConfObjects[self]
|
||||
self._dumpCache()
|
||||
sconf_global = None
|
||||
if not self.config_h is None:
|
||||
_ac_config_hs[self.config_h] = self.config_h_text
|
||||
self.env.fs = self.lastEnvFs
|
||||
|
||||
class CheckContext:
|
||||
|
@ -524,22 +667,27 @@ class CheckContext:
|
|||
def __init__(self, sconf):
|
||||
"""Constructor. Pass the corresponding SConf instance."""
|
||||
self.sconf = sconf
|
||||
self.cached = 0
|
||||
self.did_show_result = 0
|
||||
|
||||
# for Conftest.py:
|
||||
self.vardict = {}
|
||||
self.havedict = {}
|
||||
self.headerfilename = None # XXX may cause trouble!
|
||||
self.headerfilename = None
|
||||
self.config_h = "" # config_h text will be stored here
|
||||
# we don't regenerate the config.h file after each test. That means,
|
||||
# that tests won't be able to include the config.h file, and so
|
||||
# they can't do an #ifdef HAVE_XXX_H. This shouldn't be a major
|
||||
# issue, though. If it turns out, that we need to include config.h
|
||||
# in tests, we must ensure, that the dependencies are worked out
|
||||
# correctly. Note that we can't use Conftest.py's support for config.h,
|
||||
# cause we will need to specify a builder for the config.h file ...
|
||||
|
||||
def Message(self, text):
|
||||
"""Inform about what we are doing right now, e.g.
|
||||
'Checking for SOMETHING ... '
|
||||
"""
|
||||
# write to config.log
|
||||
if self.sconf.logstream != None:
|
||||
self.sconf.logstream.write(text + '\n')
|
||||
sys.stdout.write(text)
|
||||
self.Display(text)
|
||||
self.sconf.cached = 1
|
||||
self.did_show_result = 0
|
||||
|
||||
def Result(self, res):
|
||||
|
@ -550,25 +698,19 @@ class CheckContext:
|
|||
"""
|
||||
if type(res) in BooleanTypes:
|
||||
if res:
|
||||
text = "ok"
|
||||
text = "yes"
|
||||
else:
|
||||
text = "failed"
|
||||
text = "no"
|
||||
elif type(res) == types.StringType:
|
||||
text = res
|
||||
else:
|
||||
raise TypeError, "Expected string, int or bool, got " + str(type(res))
|
||||
|
||||
if self.did_show_result == 0:
|
||||
if self.cached:
|
||||
text = text + " (cached)"
|
||||
|
||||
# Didn't show result yet, do it now.
|
||||
if self.sconf.logstream != None:
|
||||
self.sconf.logstream.write("Result: " + text + "\n\n")
|
||||
sys.stdout.write(text + "\n")
|
||||
self.Display(text + "\n")
|
||||
self.did_show_result = 1
|
||||
|
||||
|
||||
def TryBuild(self, *args, **kw):
|
||||
return apply(self.sconf.TryBuild, args, kw)
|
||||
|
||||
|
@ -595,32 +737,14 @@ class CheckContext:
|
|||
#### Stuff used by Conftest.py (look there for explanations).
|
||||
|
||||
def BuildProg(self, text, ext):
|
||||
self.sconf.cached = 1
|
||||
# TODO: should use self.vardict for $CC, $CPPFLAGS, etc.
|
||||
res = self.TryBuild(self.env.Program, text, ext)
|
||||
if type(res) in BooleanTypes:
|
||||
if res:
|
||||
ret = ""
|
||||
else:
|
||||
ret = "failed to build test program"
|
||||
elif type(res) == types.StringType:
|
||||
ret = res
|
||||
else:
|
||||
raise TypeError, "Expected string or int"
|
||||
return ret
|
||||
return not self.TryBuild(self.env.Program, text, ext)
|
||||
|
||||
def CompileProg(self, text, ext):
|
||||
self.sconf.cached = 1
|
||||
# TODO: should use self.vardict for $CC, $CPPFLAGS, etc.
|
||||
res = self.TryBuild(self.env.Object, text, ext)
|
||||
if type(res) in BooleanTypes:
|
||||
if res:
|
||||
ret = ""
|
||||
else:
|
||||
ret = "failed to compile test program"
|
||||
elif type(res) == types.StringType:
|
||||
ret = res
|
||||
else:
|
||||
raise TypeError, "Expected string or int"
|
||||
return ret
|
||||
return not self.TryBuild(self.env.Object, text, ext)
|
||||
|
||||
def AppendLIBS(self, lib_name_list):
|
||||
oldLIBS = self.env.get( 'LIBS', [] )
|
||||
|
@ -633,8 +757,14 @@ class CheckContext:
|
|||
return oldLIBS
|
||||
|
||||
def Display(self, msg):
|
||||
sys.stdout.write(msg)
|
||||
self.Log(msg)
|
||||
if self.sconf.cached:
|
||||
# We assume that Display is called twice for each test here
|
||||
# once for the Checking for ... message and once for the result.
|
||||
# The self.sconf.cached flag can only be set between those calls
|
||||
msg = "(cached) " + msg
|
||||
self.sconf.cached = 0
|
||||
progress_display(msg, append_newline=0)
|
||||
self.Log("scons: Configure: " + msg + "\n")
|
||||
|
||||
def Log(self, msg):
|
||||
if self.sconf.logstream != None:
|
||||
|
@ -643,40 +773,44 @@ class CheckContext:
|
|||
#### End of stuff used by Conftest.py.
|
||||
|
||||
|
||||
def CheckFunc(context, function_name, language = None):
|
||||
res = SCons.Conftest.CheckFunc(context, function_name, language = language)
|
||||
def CheckFunc(context, function_name, header = None, language = None):
|
||||
res = SCons.Conftest.CheckFunc(context, function_name, header = header, language = language)
|
||||
context.did_show_result = 1
|
||||
if not res:
|
||||
return 1 # Ok
|
||||
return 0 # Failed
|
||||
|
||||
return not res
|
||||
|
||||
def CheckType(context, type_name, includes = "", language = None):
|
||||
res = SCons.Conftest.CheckType(context, type_name,
|
||||
header = includes, language = language)
|
||||
context.did_show_result = 1
|
||||
if not res:
|
||||
return 1 # Ok
|
||||
return 0 # Failed
|
||||
return not res
|
||||
|
||||
def createIncludesFromHeaders(headers, leaveLast, include_quotes = '""'):
|
||||
# used by CheckHeader and CheckLibWithHeader to produce C - #include
|
||||
# statements from the specified header (list)
|
||||
if not SCons.Util.is_List(headers):
|
||||
headers = [headers]
|
||||
l = []
|
||||
if leaveLast:
|
||||
lastHeader = headers[-1]
|
||||
headers = headers[:-1]
|
||||
else:
|
||||
lastHeader = None
|
||||
for s in headers:
|
||||
l.append("#include %s%s%s\n"
|
||||
% (include_quotes[0], s, include_quotes[1]))
|
||||
return string.join(l, ''), lastHeader
|
||||
|
||||
def CheckHeader(context, header, include_quotes = '<>', language = None):
|
||||
"""
|
||||
A test for a C or C++ header file.
|
||||
"""
|
||||
if not SCons.Util.is_List(header):
|
||||
header = [header]
|
||||
l = []
|
||||
for s in header[:-1]:
|
||||
l.append("#include %s%s%s\n" % (include_quotes[0], s, include_quotes[1]))
|
||||
res = SCons.Conftest.CheckHeader(context, header[-1], string.join(l, ''),
|
||||
prog_prefix, hdr_to_check = \
|
||||
createIncludesFromHeaders(header, 1, include_quotes)
|
||||
res = SCons.Conftest.CheckHeader(context, hdr_to_check, prog_prefix,
|
||||
language = language,
|
||||
include_quotes = include_quotes)
|
||||
context.did_show_result = 1
|
||||
if not res:
|
||||
return 1 # Ok
|
||||
return 0 # Failed
|
||||
|
||||
return not res
|
||||
|
||||
# Bram: Make this function obsolete? CheckHeader() is more generic.
|
||||
|
||||
|
@ -696,8 +830,8 @@ def CheckCXXHeader(context, header, include_quotes = '""'):
|
|||
return CheckHeader(context, header, include_quotes, language = "C++")
|
||||
|
||||
|
||||
def CheckLib(context, library = None, symbol = "main", autoadd = 1,
|
||||
header = None, language = None):
|
||||
def CheckLib(context, library = None, symbol = "main",
|
||||
header = None, language = None, autoadd = 1):
|
||||
"""
|
||||
A test for a library. See also CheckLibWithHeader.
|
||||
Note that library may also be None to test whether the given symbol
|
||||
|
@ -714,16 +848,13 @@ def CheckLib(context, library = None, symbol = "main", autoadd = 1,
|
|||
res = SCons.Conftest.CheckLib(context, library, symbol, header = header,
|
||||
language = language, autoadd = autoadd)
|
||||
context.did_show_result = 1
|
||||
if not res:
|
||||
return 1 # Ok
|
||||
return 0 # Failed
|
||||
|
||||
return not res
|
||||
|
||||
# XXX
|
||||
# Bram: Can only include one header and can't use #ifdef HAVE_HEADER_H.
|
||||
|
||||
def CheckLibWithHeader(context, libs, header, language,
|
||||
call = "main();", autoadd = 1):
|
||||
call = None, autoadd = 1):
|
||||
# ToDo: accept path for library. Support system header files.
|
||||
"""
|
||||
Another (more sophisticated) test for a library.
|
||||
|
@ -732,25 +863,15 @@ def CheckLibWithHeader(context, libs, header, language,
|
|||
As in CheckLib, we support library=None, to test if the call compiles
|
||||
without extra link flags.
|
||||
"""
|
||||
|
||||
if not SCons.Util.is_List(header):
|
||||
header = [header]
|
||||
l = []
|
||||
for s in header:
|
||||
l.append('#include "%s"\n' % (s))
|
||||
|
||||
|
||||
prog_prefix, dummy = \
|
||||
createIncludesFromHeaders(header, 0)
|
||||
if libs == []:
|
||||
libs = [None]
|
||||
|
||||
if not SCons.Util.is_List(libs):
|
||||
libs = [libs]
|
||||
|
||||
res = SCons.Conftest.CheckLib(context, libs, "main", string.join(l, ''),
|
||||
res = SCons.Conftest.CheckLib(context, libs, None, prog_prefix,
|
||||
call = call, language = language, autoadd = autoadd)
|
||||
context.did_show_result = 1
|
||||
if not res:
|
||||
return 1 # Ok
|
||||
return 0 # Failed
|
||||
|
||||
|
||||
return not res
|
|
@ -5,7 +5,7 @@ Writing and reading information to the .sconsign file or files.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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,26 +27,85 @@ Writing and reading information to the .sconsign file or files.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/SConsign.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/SConsign.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import cPickle
|
||||
import os
|
||||
import os.path
|
||||
import time
|
||||
|
||||
import SCons.Node
|
||||
import SCons.dblite
|
||||
import SCons.Sig
|
||||
import SCons.Warnings
|
||||
|
||||
def corrupt_dblite_warning(filename):
|
||||
SCons.Warnings.warn(SCons.Warnings.CorruptSConsignWarning,
|
||||
"Ignoring corrupt .sconsign file: %s"%filename)
|
||||
|
||||
SCons.dblite.ignore_corrupt_dbfiles = 1
|
||||
SCons.dblite.corruption_warning = corrupt_dblite_warning
|
||||
|
||||
#XXX Get rid of the global array so this becomes re-entrant.
|
||||
sig_files = []
|
||||
|
||||
database = None
|
||||
# Info for the database SConsign implementation (now the default):
|
||||
# "DataBase" is a dictionary that maps top-level SConstruct directories
|
||||
# to open database handles.
|
||||
# "DB_Module" is the Python database module to create the handles.
|
||||
# "DB_Name" is the base name of the database file (minus any
|
||||
# extension the underlying DB module will add).
|
||||
DataBase = {}
|
||||
DB_Module = SCons.dblite
|
||||
DB_Name = ".sconsign"
|
||||
DB_sync_list = []
|
||||
|
||||
def Get_DataBase(dir):
|
||||
global DataBase, DB_Module, DB_Name
|
||||
top = dir.fs.Top
|
||||
if not os.path.isabs(DB_Name) and top.repositories:
|
||||
mode = "c"
|
||||
for d in [top] + top.repositories:
|
||||
if dir.is_under(d):
|
||||
try:
|
||||
return DataBase[d], mode
|
||||
except KeyError:
|
||||
path = d.entry_abspath(DB_Name)
|
||||
try: db = DataBase[d] = DB_Module.open(path, mode)
|
||||
except (IOError, OSError): pass
|
||||
else:
|
||||
if mode != "r":
|
||||
DB_sync_list.append(db)
|
||||
return db, mode
|
||||
mode = "r"
|
||||
try:
|
||||
return DataBase[top], "c"
|
||||
except KeyError:
|
||||
db = DataBase[top] = DB_Module.open(DB_Name, "c")
|
||||
DB_sync_list.append(db)
|
||||
return db, "c"
|
||||
except TypeError:
|
||||
print "DataBase =", DataBase
|
||||
raise
|
||||
|
||||
def Reset():
|
||||
"""Reset global state. Used by unit tests that end up using
|
||||
SConsign multiple times to get a clean slate for each test."""
|
||||
global sig_files, DB_sync_list
|
||||
sig_files = []
|
||||
DB_sync_list = []
|
||||
|
||||
normcase = os.path.normcase
|
||||
|
||||
def write():
|
||||
global sig_files
|
||||
for sig_file in sig_files:
|
||||
sig_file.write()
|
||||
sig_file.write(sync=0)
|
||||
for db in DB_sync_list:
|
||||
try:
|
||||
syncmethod = db.sync
|
||||
except AttributeError:
|
||||
pass # Not all anydbm modules have sync() methods.
|
||||
else:
|
||||
syncmethod()
|
||||
|
||||
class Base:
|
||||
"""
|
||||
|
@ -79,19 +138,28 @@ class Base:
|
|||
self.entries[filename] = obj
|
||||
self.dirty = 1
|
||||
|
||||
def do_not_set_entry(self, filename, obj):
|
||||
pass
|
||||
|
||||
class DB(Base):
|
||||
"""
|
||||
A Base subclass that reads and writes signature information
|
||||
from a global .sconsign.dbm file.
|
||||
from a global .sconsign.db* file--the actual file suffix is
|
||||
determined by the specified database module.
|
||||
"""
|
||||
def __init__(self, dir, module=None):
|
||||
Base.__init__(self, module)
|
||||
|
||||
self.dir = dir
|
||||
|
||||
db, mode = Get_DataBase(dir)
|
||||
|
||||
# Read using the path relative to the top of the Repository
|
||||
# (self.dir.tpath) from which we're fetching the signature
|
||||
# information.
|
||||
path = normcase(dir.tpath)
|
||||
try:
|
||||
global database
|
||||
rawentries = database[self.dir.path]
|
||||
rawentries = db[path]
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
|
@ -102,22 +170,45 @@ class DB(Base):
|
|||
raise TypeError
|
||||
except KeyboardInterrupt:
|
||||
raise
|
||||
except:
|
||||
except Exception, e:
|
||||
SCons.Warnings.warn(SCons.Warnings.CorruptSConsignWarning,
|
||||
"Ignoring corrupt sconsign entry : %s"%self.dir.path)
|
||||
"Ignoring corrupt sconsign entry : %s (%s)\n"%(self.dir.tpath, e))
|
||||
for key, entry in self.entries.items():
|
||||
entry.convert_from_sconsign(dir, key)
|
||||
|
||||
if mode == "r":
|
||||
# This directory is actually under a repository, which means
|
||||
# likely they're reaching in directly for a dependency on
|
||||
# a file there. Don't actually set any entry info, so we
|
||||
# won't try to write to that .sconsign.dblite file.
|
||||
self.set_entry = self.do_not_set_entry
|
||||
|
||||
global sig_files
|
||||
sig_files.append(self)
|
||||
|
||||
def write(self):
|
||||
if self.dirty:
|
||||
global database
|
||||
database[self.dir.path] = cPickle.dumps(self.entries, 1)
|
||||
def write(self, sync=1):
|
||||
if not self.dirty:
|
||||
return
|
||||
|
||||
db, mode = Get_DataBase(self.dir)
|
||||
|
||||
# Write using the path relative to the top of the SConstruct
|
||||
# directory (self.dir.path), not relative to the top of
|
||||
# the Repository; we only write to our own .sconsign file,
|
||||
# not to .sconsign files in Repositories.
|
||||
path = normcase(self.dir.path)
|
||||
for key, entry in self.entries.items():
|
||||
entry.convert_to_sconsign()
|
||||
db[path] = cPickle.dumps(self.entries, 1)
|
||||
|
||||
if sync:
|
||||
try:
|
||||
database.sync()
|
||||
syncmethod = db.sync
|
||||
except AttributeError:
|
||||
# Not all anydbm modules have sync() methods.
|
||||
pass
|
||||
else:
|
||||
syncmethod()
|
||||
|
||||
class Dir(Base):
|
||||
def __init__(self, fp=None, module=None):
|
||||
|
@ -162,7 +253,16 @@ class DirFile(Dir):
|
|||
global sig_files
|
||||
sig_files.append(self)
|
||||
|
||||
def write(self):
|
||||
def get_entry(self, filename):
|
||||
"""
|
||||
Fetch the specified entry attribute, converting from .sconsign
|
||||
format to in-memory format.
|
||||
"""
|
||||
entry = Dir.get_entry(self, filename)
|
||||
entry.convert_from_sconsign(self.dir, filename)
|
||||
return entry
|
||||
|
||||
def write(self, sync=1):
|
||||
"""
|
||||
Write the .sconsign file to disk.
|
||||
|
||||
|
@ -186,6 +286,8 @@ class DirFile(Dir):
|
|||
fname = self.sconsign
|
||||
except IOError:
|
||||
return
|
||||
for key, entry in self.entries.items():
|
||||
entry.convert_to_sconsign()
|
||||
cPickle.dump(self.entries, file, 1)
|
||||
file.close()
|
||||
if fname != self.sconsign:
|
||||
|
@ -193,31 +295,42 @@ class DirFile(Dir):
|
|||
mode = os.stat(self.sconsign)[0]
|
||||
os.chmod(self.sconsign, 0666)
|
||||
os.unlink(self.sconsign)
|
||||
except OSError:
|
||||
except (IOError, OSError):
|
||||
# Try to carry on in the face of either OSError
|
||||
# (things like permission issues) or IOError (disk
|
||||
# or network issues). If there's a really dangerous
|
||||
# issue, it should get re-raised by the calls below.
|
||||
pass
|
||||
try:
|
||||
os.rename(fname, self.sconsign)
|
||||
except OSError:
|
||||
# An OSError failure to rename may indicate something
|
||||
# like the directory has no write permission, but
|
||||
# the .sconsign file itself might still be writable,
|
||||
# so try writing on top of it directly. An IOError
|
||||
# here, or in any of the following calls, would get
|
||||
# raised, indicating something like a potentially
|
||||
# serious disk or network issue.
|
||||
open(self.sconsign, 'wb').write(open(fname, 'rb').read())
|
||||
os.chmod(self.sconsign, mode)
|
||||
try:
|
||||
os.unlink(temp)
|
||||
except OSError:
|
||||
except (IOError, OSError):
|
||||
pass
|
||||
|
||||
ForDirectory = DirFile
|
||||
ForDirectory = DB
|
||||
|
||||
def File(name, dbm_module=None):
|
||||
"""
|
||||
Arrange for all signatures to be stored in a global .sconsign.dbm
|
||||
Arrange for all signatures to be stored in a global .sconsign.db*
|
||||
file.
|
||||
"""
|
||||
global database
|
||||
if database is None:
|
||||
if dbm_module is None:
|
||||
import SCons.dblite
|
||||
dbm_module = SCons.dblite
|
||||
database = dbm_module.open(name, "c")
|
||||
|
||||
global ForDirectory
|
||||
global ForDirectory, DB_Name, DB_Module
|
||||
if name is None:
|
||||
ForDirectory = DirFile
|
||||
DB_Module = None
|
||||
else:
|
||||
ForDirectory = DB
|
||||
DB_Name = name
|
||||
if not dbm_module is None:
|
||||
DB_Module = dbm_module
|
|
@ -5,7 +5,7 @@ This module implements the depenency scanner for C/C++ code.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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,17 +27,16 @@ This module implements the depenency scanner for C/C++ code.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Scanner/C.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Scanner/C.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import SCons.Node.FS
|
||||
import SCons.Scanner
|
||||
|
||||
def CScan(fs = SCons.Node.FS.default_fs):
|
||||
def CScanner():
|
||||
"""Return a prototype Scanner instance for scanning source files
|
||||
that use the C pre-processor"""
|
||||
cs = SCons.Scanner.ClassicCPP("CScan",
|
||||
cs = SCons.Scanner.ClassicCPP("CScanner",
|
||||
"$CPPSUFFIXES",
|
||||
"CPPPATH",
|
||||
'^[ \t]*#[ \t]*(?:include|import)[ \t]*(<|")([^>"]+)(>|")',
|
||||
fs = fs)
|
||||
'^[ \t]*#[ \t]*(?:include|import)[ \t]*(<|")([^>"]+)(>|")')
|
||||
return cs
|
|
@ -8,7 +8,7 @@ Coded by Andy Friesen
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -30,27 +30,24 @@ Coded by Andy Friesen
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Scanner/D.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Scanner/D.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import string
|
||||
|
||||
import SCons.Scanner
|
||||
|
||||
def DScan(fs = SCons.Node.FS.default_fs):
|
||||
def DScanner():
|
||||
"""Return a prototype Scanner instance for scanning D source files"""
|
||||
ds = DScanner(name = "DScan",
|
||||
ds = D(name = "DScanner",
|
||||
suffixes = '$DSUFFIXES',
|
||||
path_variable = 'DPATH',
|
||||
regex = 'import\s+([^\;]*)\;',
|
||||
fs = fs)
|
||||
regex = 'import\s+([^\;]*)\;')
|
||||
return ds
|
||||
|
||||
class DScanner(SCons.Scanner.Classic):
|
||||
class D(SCons.Scanner.Classic):
|
||||
def find_include(self, include, source_dir, path):
|
||||
# translate dots (package separators) to slashes
|
||||
inc = string.replace(include, '.', '/')
|
||||
|
||||
i = SCons.Node.FS.find_file(inc + '.d',
|
||||
(source_dir,) + path,
|
||||
self.fs.File)
|
||||
i = SCons.Node.FS.find_file(inc + '.d', (source_dir,) + path)
|
||||
return i, include
|
105
scons/scons-local-0.97/SCons/Scanner/Dir.py
Normal file
105
scons/scons-local-0.97/SCons/Scanner/Dir.py
Normal file
|
@ -0,0 +1,105 @@
|
|||
#
|
||||
# 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/Scanner/Dir.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import SCons.Node.FS
|
||||
import SCons.Scanner
|
||||
|
||||
def only_dirs(nodes):
|
||||
is_Dir = lambda n: isinstance(n.disambiguate(), SCons.Node.FS.Dir)
|
||||
return filter(is_Dir, nodes)
|
||||
|
||||
def DirScanner(**kw):
|
||||
"""Return a prototype Scanner instance for scanning
|
||||
directories for on-disk files"""
|
||||
kw['node_factory'] = SCons.Node.FS.Entry
|
||||
kw['recursive'] = only_dirs
|
||||
return apply(SCons.Scanner.Base, (scan_on_disk, "DirScanner"), kw)
|
||||
|
||||
def DirEntryScanner(**kw):
|
||||
"""Return a prototype Scanner instance for "scanning"
|
||||
directory Nodes for their in-memory entries"""
|
||||
kw['node_factory'] = SCons.Node.FS.Entry
|
||||
kw['recursive'] = None
|
||||
return apply(SCons.Scanner.Base, (scan_in_memory, "DirEntryScanner"), kw)
|
||||
|
||||
skip_entry = {}
|
||||
|
||||
skip_entry_list = [
|
||||
'.',
|
||||
'..',
|
||||
'.sconsign',
|
||||
# Used by the native dblite.py module.
|
||||
'.sconsign.dblite',
|
||||
# Used by dbm and dumbdbm.
|
||||
'.sconsign.dir',
|
||||
# Used by dbm.
|
||||
'.sconsign.pag',
|
||||
# Used by dumbdbm.
|
||||
'.sconsign.dat',
|
||||
'.sconsign.bak',
|
||||
# Used by some dbm emulations using Berkeley DB.
|
||||
'.sconsign.db',
|
||||
]
|
||||
|
||||
for skip in skip_entry_list:
|
||||
skip_entry[skip] = 1
|
||||
skip_entry[SCons.Node.FS._my_normcase(skip)] = 1
|
||||
|
||||
do_not_scan = lambda k: not skip_entry.has_key(k)
|
||||
|
||||
def scan_on_disk(node, env, path=()):
|
||||
"""
|
||||
Scans a directory for on-disk files and directories therein.
|
||||
|
||||
Looking up the entries will add these to the in-memory Node tree
|
||||
representation of the file system, so all we have to do is just
|
||||
that and then call the in-memory scanning function.
|
||||
"""
|
||||
try:
|
||||
flist = node.fs.listdir(node.abspath)
|
||||
except (IOError, OSError):
|
||||
return []
|
||||
e = node.Entry
|
||||
for f in filter(do_not_scan, flist):
|
||||
# Add ./ to the beginning of the file name so if it begins with a
|
||||
# '#' we don't look it up relative to the top-level directory.
|
||||
e('./' + f)
|
||||
return scan_in_memory(node, env, path)
|
||||
|
||||
def scan_in_memory(node, env, path=()):
|
||||
"""
|
||||
"Scans" a Node.FS.Dir for its in-memory entries.
|
||||
"""
|
||||
try:
|
||||
entries = node.entries
|
||||
except AttributeError:
|
||||
# It's not a Node.FS.Dir (or doesn't look enough like one for
|
||||
# our purposes), which can happen if a target list containing
|
||||
# mixed Node types (Dirs and Files, for example) has a Dir as
|
||||
# the first entry.
|
||||
return []
|
||||
entry_list = filter(do_not_scan, entries.keys())
|
||||
entry_list.sort()
|
||||
return map(lambda n, e=entries: e[n], entry_list)
|
|
@ -5,7 +5,7 @@ This module implements the dependency scanner for Fortran code.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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 @@ This module implements the dependency scanner for Fortran code.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Scanner/Fortran.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Scanner/Fortran.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import re
|
||||
import string
|
||||
|
@ -54,18 +54,23 @@ class F90Scanner(SCons.Scanner.Classic):
|
|||
smart thing to do.
|
||||
"""
|
||||
|
||||
def __init__(self, name, suffixes, path_variable, use_regex,
|
||||
incl_regex, fs=SCons.Node.FS.default_fs, *args, **kw):
|
||||
def __init__(self, name, suffixes, path_variable,
|
||||
use_regex, incl_regex, def_regex, *args, **kw):
|
||||
|
||||
self.cre_use = re.compile(use_regex, re.M)
|
||||
self.cre_incl = re.compile(incl_regex, re.M)
|
||||
self.fs = fs
|
||||
self.cre_def = re.compile(def_regex, re.M)
|
||||
|
||||
def _scan(node, env, path, self=self):
|
||||
node = node.rfile()
|
||||
|
||||
if not node.exists():
|
||||
return []
|
||||
|
||||
def _scan(node, env, path, self=self, fs=fs):
|
||||
return self.scan(node, env, path)
|
||||
|
||||
kw['function'] = _scan
|
||||
kw['path_function'] = SCons.Scanner.FindPathDirs(path_variable, fs)
|
||||
kw['path_function'] = SCons.Scanner.FindPathDirs(path_variable)
|
||||
kw['recursive'] = 1
|
||||
kw['skeys'] = suffixes
|
||||
kw['name'] = name
|
||||
|
@ -73,10 +78,6 @@ class F90Scanner(SCons.Scanner.Classic):
|
|||
apply(SCons.Scanner.Current.__init__, (self,) + args, kw)
|
||||
|
||||
def scan(self, node, env, path=()):
|
||||
node = node.rfile()
|
||||
|
||||
if not node.exists():
|
||||
return []
|
||||
|
||||
# cache the includes list in node so we only scan it once:
|
||||
if node.includes != None:
|
||||
|
@ -86,6 +87,15 @@ class F90Scanner(SCons.Scanner.Classic):
|
|||
includes = self.cre_incl.findall(node.get_contents())
|
||||
# retrieve all USE'd module names
|
||||
modules = self.cre_use.findall(node.get_contents())
|
||||
# retrieve all defined module names
|
||||
defmodules = self.cre_def.findall(node.get_contents())
|
||||
|
||||
# Remove all USE'd module names that are defined in the same file
|
||||
d = {}
|
||||
for m in defmodules:
|
||||
d[m] = 1
|
||||
modules = filter(lambda m, d=d: not d.has_key(m), modules)
|
||||
#modules = self.undefinedModules(modules, defmodules)
|
||||
|
||||
# Convert module name to a .mod filename
|
||||
suffix = env.subst('$FORTRANMODSUFFIX')
|
||||
|
@ -94,44 +104,30 @@ class F90Scanner(SCons.Scanner.Classic):
|
|||
mods_and_includes = SCons.Util.unique(includes+modules)
|
||||
node.includes = mods_and_includes
|
||||
|
||||
# This is a hand-coded DSU (decorate-sort-undecorate, or
|
||||
# Schwartzian transform) pattern. The sort key is the raw name
|
||||
# of the file as specifed on the USE or INCLUDE line, which lets
|
||||
# us keep the sort order constant regardless of whether the file
|
||||
# is actually found in a Repository or locally.
|
||||
nodes = []
|
||||
source_dir = node.get_dir()
|
||||
if callable(path):
|
||||
path = path()
|
||||
for dep in mods_and_includes:
|
||||
n, i = self.find_include(dep, source_dir, path)
|
||||
|
||||
if not n is None:
|
||||
nodes.append(n)
|
||||
else:
|
||||
if n is None:
|
||||
SCons.Warnings.warn(SCons.Warnings.DependencyWarning,
|
||||
"No dependency generated for file: %s (referenced by: %s) -- file not found" % (i, node))
|
||||
else:
|
||||
sortkey = self.sort_key(dep)
|
||||
nodes.append((sortkey, n))
|
||||
|
||||
# Sort the list of dependencies
|
||||
nodes.sort()
|
||||
nodes = map(lambda pair: pair[1], nodes)
|
||||
return nodes
|
||||
|
||||
# Schwartzian transform from the Python FAQ Wizard
|
||||
def st(List, Metric):
|
||||
def pairing(element, M = Metric):
|
||||
return (M(element), element)
|
||||
def stripit(pair):
|
||||
return pair[1]
|
||||
paired = map(pairing, List)
|
||||
paired.sort()
|
||||
return map(stripit, paired)
|
||||
|
||||
def normalize(node):
|
||||
# We don't want the order of includes to be
|
||||
# modified by case changes on case insensitive OSes, so
|
||||
# normalize the case of the filename here:
|
||||
# (see test/win32pathmadness.py for a test of this)
|
||||
return SCons.Node.FS._my_normcase(str(node))
|
||||
|
||||
# Apply a Schwartzian transform to return the list of
|
||||
# dependencies, sorted according to their normalized names
|
||||
transformed = st(nodes, normalize)
|
||||
# print "ClassicF90: " + str(node) + " => " + str(map(lambda x: str(x),list(transformed)))
|
||||
return transformed
|
||||
|
||||
|
||||
def FortranScan(path_variable="FORTRANPATH", fs=SCons.Node.FS.default_fs):
|
||||
def FortranScan(path_variable="FORTRANPATH"):
|
||||
"""Return a prototype Scanner instance for scanning source files
|
||||
for Fortran USE & INCLUDE statements"""
|
||||
|
||||
|
@ -285,10 +281,34 @@ def FortranScan(path_variable="FORTRANPATH", fs=SCons.Node.FS.default_fs):
|
|||
|
||||
include_regex = """(?i)(?:^|['">]\s*;)\s*INCLUDE\s+(?:\w+_)?[<"'](.+?)(?=["'>])"""
|
||||
|
||||
# The MODULE statement regex finds module definitions by matching
|
||||
# the following:
|
||||
#
|
||||
# MODULE module_name
|
||||
#
|
||||
# but *not* the following:
|
||||
#
|
||||
# MODULE PROCEDURE procedure_name
|
||||
#
|
||||
# Here is a breakdown of the regex:
|
||||
#
|
||||
# (?i) : regex is case insensitive
|
||||
# ^\s* : any amount of white space
|
||||
# MODULE : match the string MODULE, case insensitive
|
||||
# \s+ : match one or more white space characters
|
||||
# (?!PROCEDURE) : but *don't* match if the next word matches
|
||||
# PROCEDURE (negative lookahead assertion),
|
||||
# case insensitive
|
||||
# (\w+) : match one or more alphanumeric characters
|
||||
# that make up the defined module name and
|
||||
# save it in a group
|
||||
|
||||
def_regex = """(?i)^\s*MODULE\s+(?!PROCEDURE)(\w+)"""
|
||||
|
||||
scanner = F90Scanner("FortranScan",
|
||||
"$FORTRANSUFFIXES",
|
||||
path_variable,
|
||||
use_regex,
|
||||
include_regex,
|
||||
fs = fs)
|
||||
def_regex)
|
||||
return scanner
|
|
@ -6,7 +6,7 @@ Definition Language) files.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -28,16 +28,15 @@ Definition Language) files.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Scanner/IDL.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Scanner/IDL.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import SCons.Node.FS
|
||||
import SCons.Scanner
|
||||
|
||||
def IDLScan(fs = SCons.Node.FS.default_fs):
|
||||
def IDLScan():
|
||||
"""Return a prototype Scanner instance for scanning IDL source files"""
|
||||
cs = SCons.Scanner.ClassicCPP("IDLScan",
|
||||
"$IDLSUFFIXES",
|
||||
"CPPPATH",
|
||||
'^[ \t]*(?:#[ \t]*include|[ \t]*import)[ \t]+(<|")([^>"]+)(>|")',
|
||||
fs = fs)
|
||||
'^[ \t]*(?:#[ \t]*include|[ \t]*import)[ \t]+(<|")([^>"]+)(>|")')
|
||||
return cs
|
122
scons/scons-local-0.97/SCons/Scanner/LaTeX.py
Normal file
122
scons/scons-local-0.97/SCons/Scanner/LaTeX.py
Normal file
|
@ -0,0 +1,122 @@
|
|||
"""SCons.Scanner.LaTeX
|
||||
|
||||
This module implements the dependency scanner for LaTeX code.
|
||||
|
||||
"""
|
||||
|
||||
#
|
||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining
|
||||
# a copy of this software and associated documentation files (the
|
||||
# "Software"), to deal in the Software without restriction, including
|
||||
# without limitation the rights to use, copy, modify, merge, publish,
|
||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
||||
# permit persons to whom the Software is furnished to do so, subject to
|
||||
# the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included
|
||||
# in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Scanner/LaTeX.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
|
||||
import SCons.Scanner
|
||||
import string
|
||||
import os.path
|
||||
|
||||
def LaTeXScanner(fs = SCons.Node.FS.default_fs):
|
||||
"""Return a prototype Scanner instance for scanning LaTeX source files"""
|
||||
ds = LaTeX(name = "LaTeXScanner",
|
||||
suffixes = '$LATEXSUFFIXES',
|
||||
path_variable = 'TEXINPUTS',
|
||||
regex = '\\\\(include|includegraphics(?:\[[^\]]+\])?|input|bibliography){([^}]*)}',
|
||||
recursive = 0)
|
||||
return ds
|
||||
|
||||
class LaTeX(SCons.Scanner.Classic):
|
||||
"""Class for scanning LaTeX files for included files.
|
||||
|
||||
Unlike most scanners, which use regular expressions that just
|
||||
return the included file name, this returns a tuple consisting
|
||||
of the keyword for the inclusion ("include", "includegraphics",
|
||||
"input", or "bibliography"), and then the file name itself.
|
||||
Based on a quick look at LaTeX documentation, it seems that we
|
||||
need a should append .tex suffix for the "include" keywords,
|
||||
append .tex if there is no extension for the "input" keyword,
|
||||
but leave the file name untouched for "includegraphics." For
|
||||
the "bibliography" keyword we need to add .bib if there is
|
||||
no extension. (This need to be revisited since if there
|
||||
is no extension for an :includegraphics" keyword latex will
|
||||
append .ps or .eps to find the file; while pdftex will use
|
||||
other extensions.)
|
||||
"""
|
||||
def latex_name(self, include):
|
||||
filename = include[1]
|
||||
if include[0] == 'input':
|
||||
base, ext = os.path.splitext( filename )
|
||||
if ext == "":
|
||||
filename = filename + '.tex'
|
||||
if (include[0] == 'include'):
|
||||
filename = filename + '.tex'
|
||||
if include[0] == 'bibliography':
|
||||
base, ext = os.path.splitext( filename )
|
||||
if ext == "":
|
||||
filename = filename + '.bib'
|
||||
return filename
|
||||
def sort_key(self, include):
|
||||
return SCons.Node.FS._my_normcase(self.latex_name(include))
|
||||
def find_include(self, include, source_dir, path):
|
||||
i = SCons.Node.FS.find_file(self.latex_name(include),
|
||||
(source_dir,) + path)
|
||||
return i, include
|
||||
|
||||
def scan(self, node, path=()):
|
||||
#
|
||||
# Modify the default scan function to allow for the regular
|
||||
# expression to return a comma separated list of file names
|
||||
# as can be the case with the bibliography keyword.
|
||||
#
|
||||
# cache the includes list in node so we only scan it once:
|
||||
if node.includes != None:
|
||||
includes = node.includes
|
||||
else:
|
||||
includes = self.cre.findall(node.get_contents())
|
||||
node.includes = includes
|
||||
|
||||
# This is a hand-coded DSU (decorate-sort-undecorate, or
|
||||
# Schwartzian transform) pattern. The sort key is the raw name
|
||||
# of the file as specifed on the #include line (including the
|
||||
# " or <, since that may affect what file is found), which lets
|
||||
# us keep the sort order constant regardless of whether the file
|
||||
# is actually found in a Repository or locally.
|
||||
nodes = []
|
||||
source_dir = node.get_dir()
|
||||
for include in includes:
|
||||
#
|
||||
# Handle multiple filenames in include[1]
|
||||
#
|
||||
inc_list = string.split(include[1],',')
|
||||
for j in range(len(inc_list)):
|
||||
include_local = [include[0],inc_list[j]]
|
||||
n, i = self.find_include(include_local, source_dir, path)
|
||||
|
||||
if n is None:
|
||||
SCons.Warnings.warn(SCons.Warnings.DependencyWarning,
|
||||
"No dependency generated for file: %s (included from: %s) -- file not found" % (i, node))
|
||||
else:
|
||||
sortkey = self.sort_key(include)
|
||||
nodes.append((sortkey, n))
|
||||
|
||||
nodes.sort()
|
||||
nodes = map(lambda pair: pair[1], nodes)
|
||||
return nodes
|
|
@ -1,5 +1,5 @@
|
|||
#
|
||||
# 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
|
||||
|
@ -21,7 +21,7 @@
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Scanner/Prog.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Scanner/Prog.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import string
|
||||
|
||||
|
@ -30,57 +30,70 @@ import SCons.Node.FS
|
|||
import SCons.Scanner
|
||||
import SCons.Util
|
||||
|
||||
def ProgScan(fs = SCons.Node.FS.default_fs):
|
||||
# global, set by --debug=findlibs
|
||||
print_find_libs = None
|
||||
|
||||
def ProgramScanner(**kw):
|
||||
"""Return a prototype Scanner instance for scanning executable
|
||||
files for static-lib dependencies"""
|
||||
pf = SCons.Scanner.FindPathDirs('LIBPATH', fs)
|
||||
ps = SCons.Scanner.Base(scan, "ProgScan", path_function = pf)
|
||||
kw['path_function'] = SCons.Scanner.FindPathDirs('LIBPATH')
|
||||
ps = apply(SCons.Scanner.Base, [scan, "ProgramScanner"], kw)
|
||||
return ps
|
||||
|
||||
def scan(node, env, libpath = (), fs = SCons.Node.FS.default_fs):
|
||||
def scan(node, env, libpath = ()):
|
||||
"""
|
||||
This scanner scans program files for static-library
|
||||
dependencies. It will search the LIBPATH environment variable
|
||||
for libraries specified in the LIBS variable, returning any
|
||||
files it finds as dependencies.
|
||||
"""
|
||||
|
||||
try:
|
||||
libs = env.Dictionary('LIBS')
|
||||
libs = env['LIBS']
|
||||
except KeyError:
|
||||
# There are no LIBS in this environment, so just return a null list:
|
||||
return []
|
||||
if SCons.Util.is_String(libs):
|
||||
libs = string.split(libs)
|
||||
elif not SCons.Util.is_List(libs):
|
||||
elif SCons.Util.is_List(libs):
|
||||
libs = SCons.Util.flatten(libs)
|
||||
else:
|
||||
libs = [libs]
|
||||
|
||||
try:
|
||||
prefix = env.Dictionary('LIBPREFIXES')
|
||||
prefix = env['LIBPREFIXES']
|
||||
if not SCons.Util.is_List(prefix):
|
||||
prefix = [ prefix ]
|
||||
except KeyError:
|
||||
prefix = [ '' ]
|
||||
|
||||
try:
|
||||
suffix = env.Dictionary('LIBSUFFIXES')
|
||||
suffix = env['LIBSUFFIXES']
|
||||
if not SCons.Util.is_List(suffix):
|
||||
suffix = [ suffix ]
|
||||
except KeyError:
|
||||
suffix = [ '' ]
|
||||
|
||||
find_file = SCons.Node.FS.find_file
|
||||
adjustixes = SCons.Util.adjustixes
|
||||
result = []
|
||||
pairs = []
|
||||
for suf in map(env.subst, suffix):
|
||||
for pref in map(env.subst, prefix):
|
||||
pairs.append((pref, suf))
|
||||
|
||||
result = []
|
||||
|
||||
if callable(libpath):
|
||||
libpath = libpath()
|
||||
|
||||
find_file = SCons.Node.FS.find_file
|
||||
adjustixes = SCons.Util.adjustixes
|
||||
for lib in libs:
|
||||
if SCons.Util.is_String(lib):
|
||||
lib = env.subst(lib)
|
||||
lib = adjustixes(lib, pref, suf)
|
||||
lib = find_file(lib, libpath, fs.File)
|
||||
if lib:
|
||||
result.append(lib)
|
||||
for pref, suf in pairs:
|
||||
l = adjustixes(lib, pref, suf)
|
||||
l = find_file(l, libpath, verbose=print_find_libs)
|
||||
if l:
|
||||
result.append(l)
|
||||
else:
|
||||
result.append(lib)
|
||||
|
||||
return result
|
|
@ -5,7 +5,7 @@ The Scanner package for the SCons software construction utility.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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,9 +27,10 @@ The Scanner package for the SCons software construction utility.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Scanner/__init__.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Scanner/__init__.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import re
|
||||
import string
|
||||
|
||||
import SCons.Node.FS
|
||||
import SCons.Sig
|
||||
|
@ -44,30 +45,41 @@ class _Null:
|
|||
_null = _Null
|
||||
|
||||
def Scanner(function, *args, **kw):
|
||||
"""Public interface factory function for creating different types
|
||||
"""
|
||||
Public interface factory function for creating different types
|
||||
of Scanners based on the different types of "functions" that may
|
||||
be supplied."""
|
||||
be supplied.
|
||||
|
||||
TODO: Deprecate this some day. We've moved the functionality
|
||||
inside the Base class and really don't need this factory function
|
||||
any more. It was, however, used by some of our Tool modules, so
|
||||
the call probably ended up in various people's custom modules
|
||||
patterned on SCons code.
|
||||
"""
|
||||
if SCons.Util.is_Dict(function):
|
||||
return apply(Selector, (function,) + args, kw)
|
||||
else:
|
||||
return apply(Base, (function,) + args, kw)
|
||||
|
||||
|
||||
|
||||
class FindPathDirs:
|
||||
"""A class to bind a specific *PATH variable name and the fs object
|
||||
to a function that will return all of the *path directories."""
|
||||
def __init__(self, variable, fs):
|
||||
"""A class to bind a specific *PATH variable name to a function that
|
||||
will return all of the *path directories."""
|
||||
def __init__(self, variable):
|
||||
self.variable = variable
|
||||
self.fs = fs
|
||||
def __call__(self, env, dir, argument=None):
|
||||
def __call__(self, env, dir, target=None, source=None, argument=None):
|
||||
import SCons.PathList
|
||||
try:
|
||||
path = env[self.variable]
|
||||
except KeyError:
|
||||
return ()
|
||||
|
||||
return tuple(self.fs.Rsearchall(env.subst_path(path),
|
||||
must_exist = 0,
|
||||
clazz = SCons.Node.FS.Dir,
|
||||
cwd = dir))
|
||||
dir = dir or env.fs._cwd
|
||||
path = SCons.PathList.PathList(path).subst_path(env, target, source)
|
||||
return tuple(dir.Rfindalldirs(path))
|
||||
|
||||
|
||||
|
||||
class Base:
|
||||
"""
|
||||
|
@ -79,10 +91,10 @@ class Base:
|
|||
function,
|
||||
name = "NONE",
|
||||
argument = _null,
|
||||
skeys = [],
|
||||
skeys = _null,
|
||||
path_function = None,
|
||||
node_class = SCons.Node.FS.Entry,
|
||||
node_factory = SCons.Node.FS.default_fs.File,
|
||||
node_factory = None,
|
||||
scan_check = None,
|
||||
recursive = None):
|
||||
"""
|
||||
|
@ -100,10 +112,14 @@ class Base:
|
|||
which scanner should be used for a given Node. In the case of File
|
||||
nodes, for example, the 'skeys' would be file suffixes.
|
||||
|
||||
'path_function' - a function that takes one to three arguments
|
||||
(a construction environment, optional directory, and optional
|
||||
argument for this instance) and returns a tuple of the
|
||||
directories that can be searched for implicit dependency files.
|
||||
'path_function' - a function that takes four or five arguments
|
||||
(a construction environment, Node for the directory containing
|
||||
the SConscript file that defined the primary target, list of
|
||||
target nodes, list of source nodes, and optional argument for
|
||||
this instance) and returns a tuple of the directories that can
|
||||
be searched for implicit dependency files. May also return a
|
||||
callable() which is called with no args and returns the tuple
|
||||
(supporting Bindable class).
|
||||
|
||||
'node_class' - the class of Nodes which this scan will return.
|
||||
If node_class is None, then this scanner will not enforce any
|
||||
|
@ -118,14 +134,19 @@ class Base:
|
|||
this node really needs to be scanned.
|
||||
|
||||
'recursive' - specifies that this scanner should be invoked
|
||||
recursively on the implicit dependencies it returns (the
|
||||
canonical example being #include lines in C source files).
|
||||
recursively on all of the implicit dependencies it returns
|
||||
(the canonical example being #include lines in C source files).
|
||||
May be a callable, which will be called to filter the list
|
||||
of nodes found to select a subset for recursive scanning
|
||||
(the canonical example being only recursively scanning
|
||||
subdirectories within a directory).
|
||||
|
||||
The scanner function's first argument will be the name of a file
|
||||
that should be scanned for dependencies, the second argument will
|
||||
be an Environment object, the third argument will be the value
|
||||
passed into 'argument', and the returned list should contain the
|
||||
Nodes for all the direct dependencies of the file.
|
||||
The scanner function's first argument will be a Node that should
|
||||
be scanned for dependencies, the second argument will be an
|
||||
Environment object, the third argument will be the tuple of paths
|
||||
returned by the path_function, and the fourth argument will be
|
||||
the value passed into 'argument', and the returned list should
|
||||
contain the Nodes for all the direct dependencies of the file.
|
||||
|
||||
Examples:
|
||||
|
||||
|
@ -146,19 +167,31 @@ class Base:
|
|||
self.path_function = path_function
|
||||
self.name = name
|
||||
self.argument = argument
|
||||
|
||||
if skeys is _null:
|
||||
if SCons.Util.is_Dict(function):
|
||||
skeys = function.keys()
|
||||
else:
|
||||
skeys = []
|
||||
self.skeys = skeys
|
||||
|
||||
self.node_class = node_class
|
||||
self.node_factory = node_factory
|
||||
self.scan_check = scan_check
|
||||
self.recursive = recursive
|
||||
if callable(recursive):
|
||||
self.recurse_nodes = recursive
|
||||
elif recursive:
|
||||
self.recurse_nodes = self._recurse_all_nodes
|
||||
else:
|
||||
self.recurse_nodes = self._recurse_no_nodes
|
||||
|
||||
def path(self, env, dir = None):
|
||||
def path(self, env, dir=None, target=None, source=None):
|
||||
if not self.path_function:
|
||||
return ()
|
||||
if not self.argument is _null:
|
||||
return self.path_function(env, dir, self.argument)
|
||||
return self.path_function(env, dir, target, source, self.argument)
|
||||
else:
|
||||
return self.path_function(env, dir)
|
||||
return self.path_function(env, dir, target, source)
|
||||
|
||||
def __call__(self, node, env, path = ()):
|
||||
"""
|
||||
|
@ -170,47 +203,85 @@ class Base:
|
|||
if self.scan_check and not self.scan_check(node, env):
|
||||
return []
|
||||
|
||||
self = self.select(node)
|
||||
|
||||
if not self.argument is _null:
|
||||
list = self.function(node, env, path, self.argument)
|
||||
else:
|
||||
list = self.function(node, env, path)
|
||||
|
||||
kw = {}
|
||||
if hasattr(node, 'dir'):
|
||||
kw['directory'] = node.dir
|
||||
node_factory = env.get_factory(self.node_factory)
|
||||
nodes = []
|
||||
for l in list:
|
||||
if self.node_class and not isinstance(l, self.node_class):
|
||||
l = apply(self.node_factory, (l,), kw)
|
||||
l = apply(node_factory, (l,), kw)
|
||||
nodes.append(l)
|
||||
return nodes
|
||||
|
||||
def __cmp__(self, other):
|
||||
try:
|
||||
return cmp(self.__dict__, other.__dict__)
|
||||
except AttributeError:
|
||||
# other probably doesn't have a __dict__
|
||||
return cmp(self.__dict__, other)
|
||||
|
||||
def __hash__(self):
|
||||
return hash(repr(self))
|
||||
return id(self)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def add_skey(self, skey):
|
||||
"""Add a skey to the list of skeys"""
|
||||
self.skeys.append(skey)
|
||||
|
||||
def get_skeys(self, env=None):
|
||||
if SCons.Util.is_String(self.skeys):
|
||||
if env and SCons.Util.is_String(self.skeys):
|
||||
return env.subst_list(self.skeys)[0]
|
||||
return self.skeys
|
||||
|
||||
def select(self, node):
|
||||
if SCons.Util.is_Dict(self.function):
|
||||
key = node.scanner_key()
|
||||
try:
|
||||
return self.function[key]
|
||||
except KeyError:
|
||||
return None
|
||||
else:
|
||||
return self
|
||||
|
||||
def _recurse_all_nodes(self, nodes):
|
||||
return nodes
|
||||
|
||||
def _recurse_no_nodes(self, nodes):
|
||||
return []
|
||||
|
||||
recurse_nodes = _recurse_no_nodes
|
||||
|
||||
def add_scanner(self, skey, scanner):
|
||||
self.function[skey] = scanner
|
||||
self.add_skey(skey)
|
||||
|
||||
|
||||
class Selector(Base):
|
||||
"""
|
||||
A class for selecting a more specific scanner based on the
|
||||
scanner_key() (suffix) for a specific Node.
|
||||
|
||||
TODO: This functionality has been moved into the inner workings of
|
||||
the Base class, and this class will be deprecated at some point.
|
||||
(It was never exposed directly as part of the public interface,
|
||||
although it is used by the Scanner() factory function that was
|
||||
used by various Tool modules and therefore was likely a template
|
||||
for custom modules that may be out there.)
|
||||
"""
|
||||
def __init__(self, dict, *args, **kw):
|
||||
Base.__init__(self, (None,)+args, kw)
|
||||
apply(Base.__init__, (self, None,)+args, kw)
|
||||
self.dict = dict
|
||||
self.skeys = dict.keys()
|
||||
|
||||
def __call__(self, node, env, path = ()):
|
||||
return self.select(node)(node, env, path)
|
||||
|
@ -223,6 +294,7 @@ class Selector(Base):
|
|||
|
||||
def add_scanner(self, skey, scanner):
|
||||
self.dict[skey] = scanner
|
||||
self.add_skey(skey)
|
||||
|
||||
|
||||
class Current(Base):
|
||||
|
@ -246,22 +318,23 @@ class Classic(Current):
|
|||
regular expressions to find the includes.
|
||||
|
||||
Note that in order for this to work "out of the box" (without
|
||||
overriding the find_include() method), the regular expression passed
|
||||
to the constructor must return the name of the include file in group
|
||||
0.
|
||||
overriding the find_include() and sort_key() methods), the regular
|
||||
expression passed to the constructor must return the name of the
|
||||
include file in group 0.
|
||||
"""
|
||||
|
||||
def __init__(self, name, suffixes, path_variable, regex,
|
||||
fs=SCons.Node.FS.default_fs, *args, **kw):
|
||||
def __init__(self, name, suffixes, path_variable, regex, *args, **kw):
|
||||
|
||||
self.cre = re.compile(regex, re.M)
|
||||
self.fs = fs
|
||||
|
||||
def _scan(node, env, path, self=self, fs=fs):
|
||||
return self.scan(node, env, path)
|
||||
def _scan(node, env, path=(), self=self):
|
||||
node = node.rfile()
|
||||
if not node.exists():
|
||||
return []
|
||||
return self.scan(node, path)
|
||||
|
||||
kw['function'] = _scan
|
||||
kw['path_function'] = FindPathDirs(path_variable, fs)
|
||||
kw['path_function'] = FindPathDirs(path_variable)
|
||||
kw['recursive'] = 1
|
||||
kw['skeys'] = suffixes
|
||||
kw['name'] = name
|
||||
|
@ -269,14 +342,13 @@ class Classic(Current):
|
|||
apply(Current.__init__, (self,) + args, kw)
|
||||
|
||||
def find_include(self, include, source_dir, path):
|
||||
n = SCons.Node.FS.find_file(include, (source_dir,) + path, self.fs.File)
|
||||
n = SCons.Node.FS.find_file(include, (source_dir,) + tuple(path))
|
||||
return n, include
|
||||
|
||||
def scan(self, node, env, path=()):
|
||||
node = node.rfile()
|
||||
def sort_key(self, include):
|
||||
return SCons.Node.FS._my_normcase(include)
|
||||
|
||||
if not node.exists():
|
||||
return []
|
||||
def scan(self, node, path=()):
|
||||
|
||||
# cache the includes list in node so we only scan it once:
|
||||
if node.includes != None:
|
||||
|
@ -285,37 +357,29 @@ class Classic(Current):
|
|||
includes = self.cre.findall(node.get_contents())
|
||||
node.includes = includes
|
||||
|
||||
# This is a hand-coded DSU (decorate-sort-undecorate, or
|
||||
# Schwartzian transform) pattern. The sort key is the raw name
|
||||
# of the file as specifed on the #include line (including the
|
||||
# " or <, since that may affect what file is found), which lets
|
||||
# us keep the sort order constant regardless of whether the file
|
||||
# is actually found in a Repository or locally.
|
||||
nodes = []
|
||||
source_dir = node.get_dir()
|
||||
if callable(path):
|
||||
path = path()
|
||||
for include in includes:
|
||||
n, i = self.find_include(include, source_dir, path)
|
||||
|
||||
if not n is None:
|
||||
nodes.append(n)
|
||||
else:
|
||||
if n is None:
|
||||
SCons.Warnings.warn(SCons.Warnings.DependencyWarning,
|
||||
"No dependency generated for file: %s (included from: %s) -- file not found" % (i, node))
|
||||
else:
|
||||
sortkey = self.sort_key(include)
|
||||
nodes.append((sortkey, n))
|
||||
|
||||
# Schwartzian transform from the Python FAQ Wizard
|
||||
def st(List, Metric):
|
||||
def pairing(element, M = Metric):
|
||||
return (M(element), element)
|
||||
def stripit(pair):
|
||||
return pair[1]
|
||||
paired = map(pairing, List)
|
||||
paired.sort()
|
||||
return map(stripit, paired)
|
||||
|
||||
def normalize(node):
|
||||
# We don't want the order of includes to be
|
||||
# modified by case changes on case insensitive OSes, so
|
||||
# normalize the case of the filename here:
|
||||
# (see test/win32pathmadness.py for a test of this)
|
||||
return SCons.Node.FS._my_normcase(str(node))
|
||||
|
||||
transformed = st(nodes, normalize)
|
||||
# print "Classic: " + str(node) + " => " + str(map(lambda x: str(x),list(transformed)))
|
||||
return transformed
|
||||
nodes.sort()
|
||||
nodes = map(lambda pair: pair[1], nodes)
|
||||
return nodes
|
||||
|
||||
class ClassicCPP(Classic):
|
||||
"""
|
||||
|
@ -329,11 +393,13 @@ class ClassicCPP(Classic):
|
|||
"""
|
||||
def find_include(self, include, source_dir, path):
|
||||
if include[0] == '"':
|
||||
n = SCons.Node.FS.find_file(include[1],
|
||||
(source_dir,) + path,
|
||||
self.fs.File)
|
||||
paths = (source_dir,) + tuple(path)
|
||||
else:
|
||||
n = SCons.Node.FS.find_file(include[1],
|
||||
path + (source_dir,),
|
||||
self.fs.File)
|
||||
paths = tuple(path) + (source_dir,)
|
||||
|
||||
n = SCons.Node.FS.find_file(include[1], paths)
|
||||
|
||||
return n, include[1]
|
||||
|
||||
def sort_key(self, include):
|
||||
return SCons.Node.FS._my_normcase(string.join(include))
|
File diff suppressed because it is too large
Load diff
|
@ -6,7 +6,7 @@ files.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -28,7 +28,7 @@ files.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Script/SConscript.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Script/SConscript.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import SCons
|
||||
import SCons.Action
|
||||
|
@ -42,7 +42,7 @@ import SCons.Node.FS
|
|||
import SCons.Options
|
||||
import SCons.Platform
|
||||
import SCons.SConf
|
||||
import SCons.Script
|
||||
import SCons.Script.Main
|
||||
import SCons.Tool
|
||||
import SCons.Util
|
||||
|
||||
|
@ -55,26 +55,19 @@ import traceback
|
|||
import types
|
||||
import UserList
|
||||
|
||||
# The following variables used to live in this module. Some
|
||||
# SConscript files out there may have referred to them directly as
|
||||
# SCons.Script.SConscript.*. This is now supported by some special
|
||||
# handling towards the bottom of the SConscript.__init__.py module.
|
||||
#Arguments = {}
|
||||
#ArgList = []
|
||||
#BuildTargets = TargetList()
|
||||
#CommandLineTargets = []
|
||||
#DefaultTargets = []
|
||||
|
||||
launch_dir = os.path.abspath(os.curdir)
|
||||
|
||||
def do_nothing(text): pass
|
||||
HelpFunction = do_nothing
|
||||
|
||||
Arguments = {}
|
||||
ArgList = []
|
||||
CommandLineTargets = []
|
||||
DefaultCalled = None
|
||||
DefaultTargets = []
|
||||
GlobalDict = {}
|
||||
|
||||
class TargetList(UserList.UserList):
|
||||
def _do_nothing(self, *args, **kw):
|
||||
pass
|
||||
def _add_Default(self, list):
|
||||
self.extend(list)
|
||||
def _clear(self):
|
||||
del self[:]
|
||||
BuildTargets = TargetList()
|
||||
GlobalDict = None
|
||||
|
||||
# global exports set by Export():
|
||||
global_exports = {}
|
||||
|
@ -82,29 +75,21 @@ global_exports = {}
|
|||
# chdir flag
|
||||
sconscript_chdir = 1
|
||||
|
||||
# will be set to 1, if we are reading a SConscript
|
||||
sconscript_reading = 0
|
||||
|
||||
def _scons_add_args(alist):
|
||||
for arg in alist:
|
||||
a, b = string.split(arg, '=', 1)
|
||||
Arguments[a] = b
|
||||
ArgList.append((a, b))
|
||||
|
||||
def _scons_add_targets(tlist):
|
||||
if tlist:
|
||||
CommandLineTargets.extend(tlist)
|
||||
BuildTargets.extend(tlist)
|
||||
BuildTargets._add_Default = BuildTargets._do_nothing
|
||||
BuildTargets._clear = BuildTargets._do_nothing
|
||||
|
||||
def get_calling_namespaces():
|
||||
"""Return the locals and globals for the function that called
|
||||
into this module in the current call stack."""
|
||||
try: 1/0
|
||||
except ZeroDivisionError: frame = sys.exc_info()[2].tb_frame
|
||||
|
||||
while frame.f_globals.get("__name__") == __name__: frame = frame.f_back
|
||||
# Find the first frame that *isn't* from this file. This means
|
||||
# that we expect all of the SCons frames that implement an Export()
|
||||
# or SConscript() call to be in this file, so that we can identify
|
||||
# the first non-Script.SConscript frame as the user's local calling
|
||||
# environment, and the locals and globals dictionaries from that
|
||||
# frame as the calling namespaces. See the comment below preceding
|
||||
# the DefaultEnvironmentCall block for even more explanation.
|
||||
while frame.f_globals.get("__name__") == __name__:
|
||||
frame = frame.f_back
|
||||
|
||||
return frame.f_locals, frame.f_globals
|
||||
|
||||
|
@ -130,22 +115,21 @@ def compute_exports(exports):
|
|||
|
||||
return retval
|
||||
|
||||
|
||||
class Frame:
|
||||
"""A frame on the SConstruct/SConscript call stack"""
|
||||
def __init__(self, exports, sconscript):
|
||||
def __init__(self, fs, exports, sconscript):
|
||||
self.globals = BuildDefaultGlobals()
|
||||
self.retval = None
|
||||
self.prev_dir = SCons.Node.FS.default_fs.getcwd()
|
||||
self.prev_dir = fs.getcwd()
|
||||
self.exports = compute_exports(exports) # exports from the calling SConscript
|
||||
# make sure the sconscript attr is a Node.
|
||||
if isinstance(sconscript, SCons.Node.Node):
|
||||
self.sconscript = sconscript
|
||||
else:
|
||||
self.sconscript = SCons.Node.FS.default_fs.File(str(sconscript))
|
||||
self.sconscript = fs.File(str(sconscript))
|
||||
|
||||
# the SConstruct/SConscript call stack:
|
||||
stack = []
|
||||
call_stack = []
|
||||
|
||||
# For documentation on the methods in this file, see the scons man-page
|
||||
|
||||
|
@ -154,14 +138,17 @@ def Return(*vars):
|
|||
try:
|
||||
for var in vars:
|
||||
for v in string.split(var):
|
||||
retval.append(stack[-1].globals[v])
|
||||
retval.append(call_stack[-1].globals[v])
|
||||
except KeyError, x:
|
||||
raise SCons.Errors.UserError, "Return of non-existent variable '%s'"%x
|
||||
|
||||
if len(retval) == 1:
|
||||
stack[-1].retval = retval[0]
|
||||
call_stack[-1].retval = retval[0]
|
||||
else:
|
||||
stack[-1].retval = tuple(retval)
|
||||
call_stack[-1].retval = tuple(retval)
|
||||
|
||||
|
||||
stack_bottom = '% Stack boTTom %' # hard to define a variable w/this name :)
|
||||
|
||||
def _SConscript(fs, *files, **kw):
|
||||
top = fs.Top
|
||||
|
@ -171,13 +158,12 @@ def _SConscript(fs, *files, **kw):
|
|||
# evaluate each SConscript file
|
||||
results = []
|
||||
for fn in files:
|
||||
stack.append(Frame(exports,fn))
|
||||
call_stack.append(Frame(fs, exports, fn))
|
||||
old_sys_path = sys.path
|
||||
try:
|
||||
global sconscript_reading
|
||||
sconscript_reading = 1
|
||||
SCons.Script.sconscript_reading = SCons.Script.sconscript_reading + 1
|
||||
if fn == "-":
|
||||
exec sys.stdin in stack[-1].globals
|
||||
exec sys.stdin in call_stack[-1].globals
|
||||
else:
|
||||
if isinstance(fn, SCons.Node.Node):
|
||||
f = fn
|
||||
|
@ -190,17 +176,17 @@ def _SConscript(fs, *files, **kw):
|
|||
# fs match so we can open the SConscript.
|
||||
fs.chdir(top, change_os_dir=1)
|
||||
if f.rexists():
|
||||
_file_ = open(f.rstr(), "r")
|
||||
_file_ = open(f.rfile().get_abspath(), "r")
|
||||
elif f.has_src_builder():
|
||||
# The SConscript file apparently exists in a source
|
||||
# code management system. Build it, but then clear
|
||||
# the builder so that it doesn't get built *again*
|
||||
# during the actual build phase.
|
||||
f.build()
|
||||
f.built()
|
||||
f.builder_set(None)
|
||||
s = str(f)
|
||||
if os.path.exists(s):
|
||||
_file_ = open(s, "r")
|
||||
if f.exists():
|
||||
_file_ = open(f.get_abspath(), "r")
|
||||
if _file_:
|
||||
# Chdir to the SConscript directory. Use a path
|
||||
# name relative to the SConstruct file so that if
|
||||
|
@ -212,6 +198,17 @@ def _SConscript(fs, *files, **kw):
|
|||
# where the SConstruct and SConscript files might be
|
||||
# in different Repositories. For now, cross that
|
||||
# bridge when someone comes to it.
|
||||
try:
|
||||
src_dir = kw['src_dir']
|
||||
except KeyError:
|
||||
ldir = fs.Dir(f.dir.get_path(sd))
|
||||
else:
|
||||
ldir = fs.Dir(src_dir)
|
||||
if not ldir.is_under(f.dir):
|
||||
# They specified a source directory, but
|
||||
# it's above the SConscript directory.
|
||||
# Do the sensible thing and just use the
|
||||
# SConcript directory.
|
||||
ldir = fs.Dir(f.dir.get_path(sd))
|
||||
try:
|
||||
fs.chdir(ldir, change_os_dir=sconscript_chdir)
|
||||
|
@ -223,6 +220,7 @@ def _SConscript(fs, *files, **kw):
|
|||
# interpret the stuff within the SConscript file
|
||||
# relative to where we are logically.
|
||||
fs.chdir(ldir, change_os_dir=0)
|
||||
# TODO Not sure how to handle src_dir here
|
||||
os.chdir(f.rfile().dir.get_abspath())
|
||||
|
||||
# Append the SConscript directory to the beginning
|
||||
|
@ -230,21 +228,32 @@ def _SConscript(fs, *files, **kw):
|
|||
# directory can be easily imported.
|
||||
sys.path = [ f.dir.get_abspath() ] + sys.path
|
||||
|
||||
# This is the magic line that actually reads up and
|
||||
# executes the stuff in the SConscript file. We
|
||||
# look for the "exec _file_ " from the beginning
|
||||
# of this line to find the right stack frame (the
|
||||
# next one) describing the SConscript file and line
|
||||
# number that creates a node.
|
||||
exec _file_ in stack[-1].globals
|
||||
# This is the magic line that actually reads up
|
||||
# and executes the stuff in the SConscript file.
|
||||
# The locals for this frame contain the special
|
||||
# bottom-of-the-stack marker so that any
|
||||
# exceptions that occur when processing this
|
||||
# SConscript can base the printed frames at this
|
||||
# level and not show SCons internals as well.
|
||||
call_stack[-1].globals.update({stack_bottom:1})
|
||||
old_file = call_stack[-1].globals.get('__file__')
|
||||
try:
|
||||
del call_stack[-1].globals['__file__']
|
||||
except KeyError:
|
||||
pass
|
||||
try:
|
||||
exec _file_ in call_stack[-1].globals
|
||||
finally:
|
||||
if old_file is not None:
|
||||
call_stack[-1].globals.update({__file__:old_file})
|
||||
else:
|
||||
SCons.Warnings.warn(SCons.Warnings.MissingSConscriptWarning,
|
||||
"Ignoring missing SConscript '%s'" % f.path)
|
||||
|
||||
finally:
|
||||
sconscript_reading = 0
|
||||
SCons.Script.sconscript_reading = SCons.Script.sconscript_reading - 1
|
||||
sys.path = old_sys_path
|
||||
frame = stack.pop()
|
||||
frame = call_stack.pop()
|
||||
try:
|
||||
fs.chdir(frame.prev_dir, change_os_dir=sconscript_chdir)
|
||||
except OSError:
|
||||
|
@ -252,7 +261,9 @@ def _SConscript(fs, *files, **kw):
|
|||
# Repository directory. Like above, we do this
|
||||
# directly.
|
||||
fs.chdir(frame.prev_dir, change_os_dir=0)
|
||||
os.chdir(frame.prev_dir.rdir().get_abspath())
|
||||
rdir = frame.prev_dir.rdir()
|
||||
rdir._create() # Make sure there's a directory there.
|
||||
os.chdir(rdir.get_abspath())
|
||||
|
||||
results.append(frame.retval)
|
||||
|
||||
|
@ -262,51 +273,41 @@ def _SConscript(fs, *files, **kw):
|
|||
else:
|
||||
return tuple(results)
|
||||
|
||||
def is_our_exec_statement(line):
|
||||
return not line is None and line[:12] == "exec _file_ "
|
||||
|
||||
def SConscript_exception(file=sys.stderr):
|
||||
"""Print an exception stack trace just for the SConscript file(s).
|
||||
This will show users who have Python errors where the problem is,
|
||||
without cluttering the output with all of the internal calls leading
|
||||
up to where we exec the SConscript."""
|
||||
exc_type, exc_value, exc_tb = sys.exc_info()
|
||||
stack = traceback.extract_tb(exc_tb)
|
||||
last_text = ""
|
||||
found = 0
|
||||
i = 0
|
||||
for frame in stack:
|
||||
if is_our_exec_statement(last_text):
|
||||
found = 1
|
||||
break
|
||||
i = i + 1
|
||||
last_text = frame[3]
|
||||
if not found:
|
||||
tb = exc_tb
|
||||
while tb and not tb.tb_frame.f_locals.has_key(stack_bottom):
|
||||
tb = tb.tb_next
|
||||
if not tb:
|
||||
# We did not find our exec statement, so this was actually a bug
|
||||
# in SCons itself. Show the whole stack.
|
||||
i = 0
|
||||
tb = exc_tb
|
||||
stack = traceback.extract_tb(tb)
|
||||
try:
|
||||
type = exc_type.__name__
|
||||
except AttributeError:
|
||||
type = str(exc_type)
|
||||
if type[:11] == "exceptions.":
|
||||
type = type[11:]
|
||||
file.write('%s: %s:\n' % (type, exc_value))
|
||||
for fname, line, func, text in stack[i:]:
|
||||
for fname, line, func, text in stack:
|
||||
file.write(' File "%s", line %d:\n' % (fname, line))
|
||||
file.write(' %s\n' % text)
|
||||
|
||||
def annotate(node):
|
||||
"""Annotate a node with the stack frame describing the
|
||||
SConscript file and line number that created it."""
|
||||
stack = traceback.extract_stack()
|
||||
last_text = ""
|
||||
for frame in stack:
|
||||
# If the script text of the previous frame begins with the
|
||||
# magic "exec _file_ " string, then this frame describes the
|
||||
# SConscript file and line number that caused this node to be
|
||||
# created. Record the tuple and carry on.
|
||||
if is_our_exec_statement(last_text):
|
||||
node.creator = frame
|
||||
return
|
||||
last_text = frame[3]
|
||||
tb = sys.exc_info()[2]
|
||||
while tb and not tb.tb_frame.f_locals.has_key(stack_bottom):
|
||||
tb = tb.tb_next
|
||||
if not tb:
|
||||
# We did not find any exec of an SConscript file: what?!
|
||||
raise SCons.Errors.InternalError, "could not find SConscript stack frame"
|
||||
node.creator = traceback.extract_stack(tb)[0]
|
||||
|
||||
# The following line would cause each Node to be annotated using the
|
||||
# above function. Unfortunately, this is a *huge* performance hit, so
|
||||
|
@ -330,14 +331,20 @@ class SConsEnvironment(SCons.Environment.Base):
|
|||
in 'v_major' and 'v_minor', and 0 otherwise."""
|
||||
return (major > v_major or (major == v_major and minor > v_minor))
|
||||
|
||||
def _get_major_minor(self, version_string):
|
||||
"""Split a version string into major and minor parts. This
|
||||
is complicated by the fact that a version string can be something
|
||||
like 3.2b1."""
|
||||
def _get_major_minor_revision(self, version_string):
|
||||
"""Split a version string into major, minor and (optionally)
|
||||
revision parts.
|
||||
|
||||
This is complicated by the fact that a version string can be
|
||||
something like 3.2b1."""
|
||||
version = string.split(string.split(version_string, ' ')[0], '.')
|
||||
v_major = int(version[0])
|
||||
v_minor = int(re.match('\d+', version[1]).group())
|
||||
return v_major, v_minor
|
||||
if len(version) >= 3:
|
||||
v_revision = int(re.match('\d+', version[2]).group())
|
||||
else:
|
||||
v_revision = 0
|
||||
return v_major, v_minor, v_revision
|
||||
|
||||
def _get_SConscript_filenames(self, ls, kw):
|
||||
"""
|
||||
|
@ -392,6 +399,7 @@ class SConsEnvironment(SCons.Environment.Base):
|
|||
src_dir = kw.get('src_dir')
|
||||
if not src_dir:
|
||||
src_dir, fname = os.path.split(str(files[0]))
|
||||
files = [os.path.join(str(build_dir), fname)]
|
||||
else:
|
||||
if not isinstance(src_dir, SCons.Node.Node):
|
||||
src_dir = self.fs.Dir(src_dir)
|
||||
|
@ -401,11 +409,11 @@ class SConsEnvironment(SCons.Environment.Base):
|
|||
if fn.is_under(src_dir):
|
||||
# Get path relative to the source directory.
|
||||
fname = fn.get_path(src_dir)
|
||||
else:
|
||||
# Fast way to only get the terminal path component of a Node.
|
||||
fname = fn.get_path(fn.dir)
|
||||
self.fs.BuildDir(build_dir, src_dir, duplicate)
|
||||
files = [os.path.join(str(build_dir), fname)]
|
||||
else:
|
||||
files = [fn.abspath]
|
||||
kw['src_dir'] = build_dir
|
||||
self.fs.BuildDir(build_dir, src_dir, duplicate)
|
||||
|
||||
return (files, exports)
|
||||
|
||||
|
@ -415,40 +423,35 @@ class SConsEnvironment(SCons.Environment.Base):
|
|||
# as global functions.
|
||||
#
|
||||
|
||||
def Default(self, *targets):
|
||||
global DefaultCalled
|
||||
global DefaultTargets
|
||||
DefaultCalled = 1
|
||||
for t in targets:
|
||||
if t is None:
|
||||
# Delete the elements from the list in-place, don't
|
||||
# reassign an empty list to DefaultTargets, so that the
|
||||
# DEFAULT_TARGETS variable will still point to the
|
||||
# same object we point to.
|
||||
del DefaultTargets[:]
|
||||
BuildTargets._clear()
|
||||
elif isinstance(t, SCons.Node.Node):
|
||||
DefaultTargets.append(t)
|
||||
BuildTargets._add_Default([t])
|
||||
else:
|
||||
nodes = self.arg2nodes(t, self.fs.Entry)
|
||||
DefaultTargets.extend(nodes)
|
||||
BuildTargets._add_Default(nodes)
|
||||
def Configure(self, *args, **kw):
|
||||
if not SCons.Script.sconscript_reading:
|
||||
raise SCons.Errors.UserError, "Calling Configure from Builders is not supported."
|
||||
kw['_depth'] = kw.get('_depth', 0) + 1
|
||||
return apply(SCons.Environment.Base.Configure, (self,)+args, kw)
|
||||
|
||||
def EnsureSConsVersion(self, major, minor):
|
||||
def Default(self, *targets):
|
||||
SCons.Script._Set_Default_Targets(self, targets)
|
||||
|
||||
def EnsureSConsVersion(self, major, minor, revision=0):
|
||||
"""Exit abnormally if the SCons version is not late enough."""
|
||||
v_major, v_minor = self._get_major_minor(SCons.__version__)
|
||||
if self._exceeds_version(major, minor, v_major, v_minor):
|
||||
print "SCons %d.%d or greater required, but you have SCons %s" %(major,minor,SCons.__version__)
|
||||
scons_ver = self._get_major_minor_revision(SCons.__version__)
|
||||
if scons_ver < (major, minor, revision):
|
||||
if revision:
|
||||
scons_ver_string = '%d.%d.%d' % (major, minor, revision)
|
||||
else:
|
||||
scons_ver_string = '%d.%d' % (major, minor)
|
||||
print "SCons %s or greater required, but you have SCons %s" % \
|
||||
(scons_ver_string, SCons.__version__)
|
||||
sys.exit(2)
|
||||
|
||||
def EnsurePythonVersion(self, major, minor):
|
||||
"""Exit abnormally if the Python version is not late enough."""
|
||||
try:
|
||||
v_major, v_minor, v_micro, release, serial = sys.version_info
|
||||
python_ver = (v_major, v_minor)
|
||||
except AttributeError:
|
||||
v_major, v_minor = self._get_major_minor(sys.version)
|
||||
if self._exceeds_version(major, minor, v_major, v_minor):
|
||||
python_ver = self._get_major_minor_revision(sys.version)[:2]
|
||||
if python_ver < (major, minor):
|
||||
v = string.split(sys.version, " ", 1)[0]
|
||||
print "Python %d.%d or greater required, but you have Python %s" %(major,minor,v)
|
||||
sys.exit(2)
|
||||
|
@ -466,30 +469,39 @@ class SConsEnvironment(SCons.Environment.Base):
|
|||
|
||||
def GetOption(self, name):
|
||||
name = self.subst(name)
|
||||
return SCons.Script.ssoptions.get(name)
|
||||
return SCons.Script.Main.ssoptions.get(name)
|
||||
|
||||
def Help(self, text):
|
||||
text = self.subst(text, raw=1)
|
||||
HelpFunction(text)
|
||||
SCons.Script.HelpFunction(text)
|
||||
|
||||
def Import(self, *vars):
|
||||
try:
|
||||
frame = call_stack[-1]
|
||||
globals = frame.globals
|
||||
exports = frame.exports
|
||||
for var in vars:
|
||||
var = self.Split(var)
|
||||
for v in var:
|
||||
if v == '*':
|
||||
stack[-1].globals.update(global_exports)
|
||||
stack[-1].globals.update(stack[-1].exports)
|
||||
globals.update(global_exports)
|
||||
globals.update(exports)
|
||||
else:
|
||||
if stack[-1].exports.has_key(v):
|
||||
stack[-1].globals[v] = stack[-1].exports[v]
|
||||
if exports.has_key(v):
|
||||
globals[v] = exports[v]
|
||||
else:
|
||||
stack[-1].globals[v] = global_exports[v]
|
||||
globals[v] = global_exports[v]
|
||||
except KeyError,x:
|
||||
raise SCons.Errors.UserError, "Import of non-existent variable '%s'"%x
|
||||
|
||||
def SConscript(self, *ls, **kw):
|
||||
ls = map(lambda l, self=self: self.subst(l), ls)
|
||||
def subst_element(x, subst=self.subst):
|
||||
if SCons.Util.is_List(x):
|
||||
x = map(subst, x)
|
||||
else:
|
||||
x = subst(x)
|
||||
return x
|
||||
ls = map(subst_element, ls)
|
||||
subst_kw = {}
|
||||
for key, val in kw.items():
|
||||
if SCons.Util.is_String(val):
|
||||
|
@ -504,8 +516,8 @@ class SConsEnvironment(SCons.Environment.Base):
|
|||
subst_kw[key] = val
|
||||
|
||||
files, exports = self._get_SConscript_filenames(ls, subst_kw)
|
||||
|
||||
return apply(_SConscript, [self.fs,] + files, {'exports' : exports})
|
||||
subst_kw['exports'] = exports
|
||||
return apply(_SConscript, [self.fs,] + files, subst_kw)
|
||||
|
||||
def SConscriptChdir(self, flag):
|
||||
global sconscript_chdir
|
||||
|
@ -513,48 +525,34 @@ class SConsEnvironment(SCons.Environment.Base):
|
|||
|
||||
def SetOption(self, name, value):
|
||||
name = self.subst(name)
|
||||
SCons.Script.ssoptions.set(name, value)
|
||||
SCons.Script.Main.ssoptions.set(name, value)
|
||||
|
||||
#
|
||||
#
|
||||
#
|
||||
SCons.Environment.Environment = SConsEnvironment
|
||||
|
||||
def Options(files=None, args=Arguments):
|
||||
return SCons.Options.Options(files, args)
|
||||
|
||||
def SetBuildSignatureType(type):
|
||||
SCons.Warnings.warn(SCons.Warnings.DeprecatedWarning,
|
||||
"The SetBuildSignatureType() function has been deprecated;\n" +\
|
||||
"\tuse the TargetSignatures() function instead.")
|
||||
SCons.Defaults.DefaultEnvironment().TargetSignatures(type)
|
||||
|
||||
def SetContentSignatureType(type):
|
||||
SCons.Warnings.warn(SCons.Warnings.DeprecatedWarning,
|
||||
"The SetContentSignatureType() function has been deprecated;\n" +\
|
||||
"\tuse the SourceSignatures() function instead.")
|
||||
SCons.Defaults.DefaultEnvironment().SourceSignatures(type)
|
||||
|
||||
def GetJobs():
|
||||
SCons.Warnings.warn(SCons.Warnings.DeprecatedWarning,
|
||||
"The GetJobs() function has been deprecated;\n" +\
|
||||
"\tuse GetOption('num_jobs') instead.")
|
||||
|
||||
return GetOption('num_jobs')
|
||||
|
||||
def SetJobs(num):
|
||||
SCons.Warnings.warn(SCons.Warnings.DeprecatedWarning,
|
||||
"The SetJobs() function has been deprecated;\n" +\
|
||||
"\tuse SetOption('num_jobs', num) instead.")
|
||||
SetOption('num_jobs', num)
|
||||
|
||||
def ParseConfig(env, command, function=None):
|
||||
SCons.Warnings.warn(SCons.Warnings.DeprecatedWarning,
|
||||
"The ParseConfig() function has been deprecated;\n" +\
|
||||
"\tuse the env.ParseConfig() method instead.")
|
||||
return env.ParseConfig(command, function)
|
||||
def Configure(*args, **kw):
|
||||
if not SCons.Script.sconscript_reading:
|
||||
raise SCons.Errors.UserError, "Calling Configure from Builders is not supported."
|
||||
kw['_depth'] = 1
|
||||
return apply(SCons.SConf.SConf, args, kw)
|
||||
|
||||
# It's very important that the DefaultEnvironmentCall() class stay in this
|
||||
# file, with the get_calling_namespaces() function, the compute_exports()
|
||||
# function, the Frame class and the SConsEnvironment.Export() method.
|
||||
# These things make up the calling stack leading up to the actual global
|
||||
# Export() or SConscript() call that the user issued. We want to allow
|
||||
# users to export local variables that they define, like so:
|
||||
#
|
||||
# def func():
|
||||
# x = 1
|
||||
# Export('x')
|
||||
#
|
||||
# To support this, the get_calling_namespaces() function assumes that
|
||||
# the *first* stack frame that's not from this file is the local frame
|
||||
# for the Export() or SConscript() call.
|
||||
|
||||
_DefaultEnvironmentProxy = None
|
||||
|
||||
def get_DefaultEnvironmentProxy():
|
||||
|
@ -573,92 +571,17 @@ class DefaultEnvironmentCall:
|
|||
thereby prevent expansion of construction variables (since from
|
||||
the user's point of view this was called as a global function,
|
||||
with no associated construction environment)."""
|
||||
def __init__(self, method_name):
|
||||
def __init__(self, method_name, subst=0):
|
||||
self.method_name = method_name
|
||||
if subst:
|
||||
self.factory = SCons.Defaults.DefaultEnvironment
|
||||
else:
|
||||
self.factory = get_DefaultEnvironmentProxy
|
||||
def __call__(self, *args, **kw):
|
||||
proxy = get_DefaultEnvironmentProxy()
|
||||
method = getattr(proxy, self.method_name)
|
||||
env = self.factory()
|
||||
method = getattr(env, self.method_name)
|
||||
return apply(method, args, kw)
|
||||
|
||||
# The list of global functions to add to the SConscript name space
|
||||
# that end up calling corresponding methods or Builders in the
|
||||
# DefaultEnvironment().
|
||||
GlobalDefaultEnvironmentFunctions = [
|
||||
# Methods from the SConsEnvironment class, above.
|
||||
'Default',
|
||||
'EnsurePythonVersion',
|
||||
'EnsureSConsVersion',
|
||||
'Exit',
|
||||
'Export',
|
||||
'GetLaunchDir',
|
||||
'GetOption',
|
||||
'Help',
|
||||
'Import',
|
||||
'SConscript',
|
||||
'SConscriptChdir',
|
||||
'SetOption',
|
||||
|
||||
# Methods from the Environment.Base class.
|
||||
'AddPostAction',
|
||||
'AddPreAction',
|
||||
'Alias',
|
||||
'AlwaysBuild',
|
||||
'BuildDir',
|
||||
'CacheDir',
|
||||
'Clean',
|
||||
'Command',
|
||||
'Depends',
|
||||
'Dir',
|
||||
'Execute',
|
||||
'File',
|
||||
'FindFile',
|
||||
'Flatten',
|
||||
'GetBuildPath',
|
||||
'Ignore',
|
||||
'Install',
|
||||
'InstallAs',
|
||||
'Literal',
|
||||
'Local',
|
||||
'Precious',
|
||||
'Repository',
|
||||
'SConsignFile',
|
||||
'SideEffect',
|
||||
'SourceCode',
|
||||
'SourceSignatures',
|
||||
'Split',
|
||||
'TargetSignatures',
|
||||
'Value',
|
||||
]
|
||||
|
||||
GlobalDefaultBuilders = [
|
||||
# Supported builders.
|
||||
'CFile',
|
||||
'CXXFile',
|
||||
'DVI',
|
||||
'Jar',
|
||||
'Java',
|
||||
'JavaH',
|
||||
'Library',
|
||||
'M4',
|
||||
'MSVSProject',
|
||||
'Object',
|
||||
'PCH',
|
||||
'PDF',
|
||||
'PostScript',
|
||||
'Program',
|
||||
'RES',
|
||||
'RMIC',
|
||||
'SharedLibrary',
|
||||
'SharedObject',
|
||||
'StaticLibrary',
|
||||
'StaticObject',
|
||||
'Tar',
|
||||
'TypeLibrary',
|
||||
'Zip',
|
||||
]
|
||||
|
||||
for name in GlobalDefaultEnvironmentFunctions + GlobalDefaultBuilders:
|
||||
GlobalDict[name] = DefaultEnvironmentCall(name)
|
||||
|
||||
def BuildDefaultGlobals():
|
||||
"""
|
||||
|
@ -666,52 +589,15 @@ def BuildDefaultGlobals():
|
|||
SConstruct and SConscript files.
|
||||
"""
|
||||
|
||||
globals = {
|
||||
# Global functions that don't get executed through the
|
||||
# default Environment.
|
||||
'Action' : SCons.Action.Action,
|
||||
'BoolOption' : SCons.Options.BoolOption,
|
||||
'Builder' : SCons.Builder.Builder,
|
||||
'Configure' : SCons.SConf.SConf,
|
||||
'EnumOption' : SCons.Options.EnumOption,
|
||||
'Environment' : SCons.Environment.Environment,
|
||||
'ListOption' : SCons.Options.ListOption,
|
||||
'Options' : Options,
|
||||
'PackageOption' : SCons.Options.PackageOption,
|
||||
'PathOption' : SCons.Options.PathOption,
|
||||
'Platform' : SCons.Platform.Platform,
|
||||
'Return' : Return,
|
||||
'Scanner' : SCons.Scanner.Base,
|
||||
'Tool' : SCons.Tool.Tool,
|
||||
'WhereIs' : SCons.Util.WhereIs,
|
||||
global GlobalDict
|
||||
if GlobalDict is None:
|
||||
GlobalDict = {}
|
||||
|
||||
# Action factories.
|
||||
'Chmod' : SCons.Defaults.Chmod,
|
||||
'Copy' : SCons.Defaults.Copy,
|
||||
'Delete' : SCons.Defaults.Delete,
|
||||
'Mkdir' : SCons.Defaults.Mkdir,
|
||||
'Move' : SCons.Defaults.Move,
|
||||
'Touch' : SCons.Defaults.Touch,
|
||||
import SCons.Script
|
||||
d = SCons.Script.__dict__
|
||||
def not_a_module(m, d=d, mtype=type(SCons.Script)):
|
||||
return type(d[m]) != mtype
|
||||
for m in filter(not_a_module, dir(SCons.Script)):
|
||||
GlobalDict[m] = d[m]
|
||||
|
||||
# Other variables we provide.
|
||||
'ARGUMENTS' : Arguments,
|
||||
'ARGLIST' : ArgList,
|
||||
'BUILD_TARGETS' : BuildTargets,
|
||||
'COMMAND_LINE_TARGETS' : CommandLineTargets,
|
||||
'DEFAULT_TARGETS' : DefaultTargets,
|
||||
}
|
||||
|
||||
# Functions we might still convert to Environment methods.
|
||||
globals['CScan'] = SCons.Defaults.CScan
|
||||
globals['DefaultEnvironment'] = SCons.Defaults.DefaultEnvironment
|
||||
|
||||
# Deprecated functions, leave these here for now.
|
||||
globals['GetJobs'] = GetJobs
|
||||
globals['ParseConfig'] = ParseConfig
|
||||
globals['SetBuildSignatureType'] = SetBuildSignatureType
|
||||
globals['SetContentSignatureType'] = SetContentSignatureType
|
||||
globals['SetJobs'] = SetJobs
|
||||
|
||||
globals.update(GlobalDict)
|
||||
|
||||
return globals
|
||||
return GlobalDict.copy()
|
382
scons/scons-local-0.97/SCons/Script/__init__.py
Normal file
382
scons/scons-local-0.97/SCons/Script/__init__.py
Normal file
|
@ -0,0 +1,382 @@
|
|||
"""SCons.Script
|
||||
|
||||
This file implements the main() function used by the scons script.
|
||||
|
||||
Architecturally, this *is* the scons script, and will likely only be
|
||||
called from the external "scons" wrapper. Consequently, anything here
|
||||
should not be, or be considered, part of the build engine. If it's
|
||||
something that we expect other software to want to use, it should go in
|
||||
some other module. If it's specific to the "scons" script invocation,
|
||||
it goes here.
|
||||
|
||||
"""
|
||||
|
||||
#
|
||||
# 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/Script/__init__.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import time
|
||||
start_time = time.time()
|
||||
|
||||
import os
|
||||
import string
|
||||
import sys
|
||||
import UserList
|
||||
|
||||
# Special chicken-and-egg handling of the "--debug=memoizer" flag:
|
||||
#
|
||||
# SCons.Memoize contains a metaclass implementation that affects how
|
||||
# the other classes are instantiated. The Memoizer may add shim methods
|
||||
# to classes that have methods that cache computed values in order to
|
||||
# count and report the hits and misses.
|
||||
#
|
||||
# If we wait to enable the Memoization until after we've parsed the
|
||||
# command line options normally, it will be too late, because the Memoizer
|
||||
# will have already analyzed the classes that it's Memoizing and decided
|
||||
# to not add the shims. So we use a special-case, up-front check for
|
||||
# the "--debug=memoizer" flag and enable Memoizer before we import any
|
||||
# of the other modules that use it.
|
||||
|
||||
_args = sys.argv + string.split(os.environ.get('SCONSFLAGS', ''))
|
||||
if "--debug=memoizer" in _args:
|
||||
import SCons.Memoize
|
||||
import SCons.Warnings
|
||||
try:
|
||||
SCons.Memoize.EnableMemoization()
|
||||
except SCons.Warnings.Warning:
|
||||
# Some warning was thrown (inability to --debug=memoizer on
|
||||
# Python 1.5.2 because it doesn't have metaclasses). Arrange
|
||||
# for it to be displayed or not after warnings are configured.
|
||||
import Main
|
||||
exc_type, exc_value, tb = sys.exc_info()
|
||||
Main.delayed_warnings.append(exc_type, exc_value)
|
||||
del _args
|
||||
|
||||
import SCons.Action
|
||||
import SCons.Builder
|
||||
import SCons.Environment
|
||||
import SCons.Node.FS
|
||||
import SCons.Options
|
||||
import SCons.Platform
|
||||
import SCons.Scanner
|
||||
import SCons.SConf
|
||||
import SCons.Subst
|
||||
import SCons.Tool
|
||||
import SCons.Util
|
||||
import SCons.Defaults
|
||||
|
||||
import Main
|
||||
|
||||
main = Main.main
|
||||
|
||||
# The following are global class definitions and variables that used to
|
||||
# live directly in this module back before 0.96.90, when it contained
|
||||
# a lot of code. Some SConscript files in widely-distributed packages
|
||||
# (Blender is the specific example) actually reached into SCons.Script
|
||||
# directly to use some of these. Rather than break those SConscript
|
||||
# files, we're going to propagate these names into the SCons.Script
|
||||
# namespace here.
|
||||
#
|
||||
# Some of these are commented out because it's *really* unlikely anyone
|
||||
# used them, but we're going to leave the comment here to try to make
|
||||
# it obvious what to do if the situation arises.
|
||||
BuildTask = Main.BuildTask
|
||||
CleanTask = Main.CleanTask
|
||||
QuestionTask = Main.QuestionTask
|
||||
#PrintHelp = Main.PrintHelp
|
||||
OptParser = Main.OptParser
|
||||
SConscriptSettableOptions = Main.SConscriptSettableOptions
|
||||
|
||||
keep_going_on_error = Main.keep_going_on_error
|
||||
#print_dtree = Main.print_dtree
|
||||
print_explanations = Main.print_explanations
|
||||
print_includes = Main.print_includes
|
||||
print_objects = Main.print_objects
|
||||
print_time = Main.print_time
|
||||
#print_tree = Main.print_tree
|
||||
memory_stats = Main.memory_stats
|
||||
ignore_errors = Main.ignore_errors
|
||||
#sconscript_time = Main.sconscript_time
|
||||
#command_time = Main.command_time
|
||||
#exit_status = Main.exit_status
|
||||
#profiling = Main.profiling
|
||||
repositories = Main.repositories
|
||||
|
||||
#
|
||||
import SConscript
|
||||
_SConscript = SConscript
|
||||
|
||||
call_stack = _SConscript.call_stack
|
||||
|
||||
#
|
||||
Action = SCons.Action.Action
|
||||
AllowSubstExceptions = SCons.Subst.SetAllowableExceptions
|
||||
BoolOption = SCons.Options.BoolOption
|
||||
Builder = SCons.Builder.Builder
|
||||
Configure = _SConscript.Configure
|
||||
EnumOption = SCons.Options.EnumOption
|
||||
Environment = SCons.Environment.Environment
|
||||
FindPathDirs = SCons.Scanner.FindPathDirs
|
||||
ListOption = SCons.Options.ListOption
|
||||
PackageOption = SCons.Options.PackageOption
|
||||
PathOption = SCons.Options.PathOption
|
||||
Platform = SCons.Platform.Platform
|
||||
Return = _SConscript.Return
|
||||
Scanner = SCons.Scanner.Base
|
||||
Tool = SCons.Tool.Tool
|
||||
WhereIs = SCons.Util.WhereIs
|
||||
|
||||
# Action factories.
|
||||
Chmod = SCons.Defaults.Chmod
|
||||
Copy = SCons.Defaults.Copy
|
||||
Delete = SCons.Defaults.Delete
|
||||
Mkdir = SCons.Defaults.Mkdir
|
||||
Move = SCons.Defaults.Move
|
||||
Touch = SCons.Defaults.Touch
|
||||
|
||||
# Pre-made, public scanners.
|
||||
CScanner = SCons.Tool.CScanner
|
||||
DScanner = SCons.Tool.DScanner
|
||||
DirScanner = SCons.Defaults.DirScanner
|
||||
ProgramScanner = SCons.Tool.ProgramScanner
|
||||
SourceFileScanner = SCons.Tool.SourceFileScanner
|
||||
|
||||
# Functions we might still convert to Environment methods.
|
||||
CScan = SCons.Defaults.CScan
|
||||
DefaultEnvironment = SCons.Defaults.DefaultEnvironment
|
||||
|
||||
# Other variables we provide.
|
||||
class TargetList(UserList.UserList):
|
||||
def _do_nothing(self, *args, **kw):
|
||||
pass
|
||||
def _add_Default(self, list):
|
||||
self.extend(list)
|
||||
def _clear(self):
|
||||
del self[:]
|
||||
|
||||
ARGUMENTS = {}
|
||||
ARGLIST = []
|
||||
BUILD_TARGETS = TargetList()
|
||||
COMMAND_LINE_TARGETS = []
|
||||
DEFAULT_TARGETS = []
|
||||
|
||||
# BUILD_TARGETS can be modified in the SConscript files. If so, we
|
||||
# want to treat the modified BUILD_TARGETS list as if they specified
|
||||
# targets on the command line. To do that, though, we need to know if
|
||||
# BUILD_TARGETS was modified through "official" APIs or by hand. We do
|
||||
# this by updating two lists in parallel, the documented BUILD_TARGETS
|
||||
# list, above, and this internal _build_plus_default targets list which
|
||||
# should only have "official" API changes. Then Script/Main.py can
|
||||
# compare these two afterwards to figure out if the user added their
|
||||
# own targets to BUILD_TARGETS.
|
||||
_build_plus_default = TargetList()
|
||||
|
||||
def _Add_Arguments(alist):
|
||||
for arg in alist:
|
||||
a, b = string.split(arg, '=', 1)
|
||||
ARGUMENTS[a] = b
|
||||
ARGLIST.append((a, b))
|
||||
|
||||
def _Add_Targets(tlist):
|
||||
if tlist:
|
||||
COMMAND_LINE_TARGETS.extend(tlist)
|
||||
BUILD_TARGETS.extend(tlist)
|
||||
BUILD_TARGETS._add_Default = BUILD_TARGETS._do_nothing
|
||||
BUILD_TARGETS._clear = BUILD_TARGETS._do_nothing
|
||||
_build_plus_default.extend(tlist)
|
||||
_build_plus_default._add_Default = _build_plus_default._do_nothing
|
||||
_build_plus_default._clear = _build_plus_default._do_nothing
|
||||
|
||||
def _Set_Default_Targets_Has_Been_Called(d, fs):
|
||||
return DEFAULT_TARGETS
|
||||
|
||||
def _Set_Default_Targets_Has_Not_Been_Called(d, fs):
|
||||
if d is None:
|
||||
d = [fs.Dir('.')]
|
||||
return d
|
||||
|
||||
_Get_Default_Targets = _Set_Default_Targets_Has_Not_Been_Called
|
||||
|
||||
def _Set_Default_Targets(env, tlist):
|
||||
global DEFAULT_TARGETS
|
||||
global _Get_Default_Targets
|
||||
_Get_Default_Targets = _Set_Default_Targets_Has_Been_Called
|
||||
for t in tlist:
|
||||
if t is None:
|
||||
# Delete the elements from the list in-place, don't
|
||||
# reassign an empty list to DEFAULT_TARGETS, so that the
|
||||
# variables will still point to the same object we point to.
|
||||
del DEFAULT_TARGETS[:]
|
||||
BUILD_TARGETS._clear()
|
||||
_build_plus_default._clear()
|
||||
elif isinstance(t, SCons.Node.Node):
|
||||
DEFAULT_TARGETS.append(t)
|
||||
BUILD_TARGETS._add_Default([t])
|
||||
_build_plus_default._add_Default([t])
|
||||
else:
|
||||
nodes = env.arg2nodes(t, env.fs.Entry)
|
||||
DEFAULT_TARGETS.extend(nodes)
|
||||
BUILD_TARGETS._add_Default(nodes)
|
||||
_build_plus_default._add_Default(nodes)
|
||||
|
||||
#
|
||||
help_text = None
|
||||
|
||||
def HelpFunction(text):
|
||||
global help_text
|
||||
if SCons.Script.help_text is None:
|
||||
SCons.Script.help_text = text
|
||||
else:
|
||||
help_text = help_text + text
|
||||
|
||||
#
|
||||
# Will be non-zero if we are reading an SConscript file.
|
||||
sconscript_reading = 0
|
||||
|
||||
#
|
||||
def Options(files=None, args=ARGUMENTS):
|
||||
return SCons.Options.Options(files, args)
|
||||
|
||||
# The list of global functions to add to the SConscript name space
|
||||
# that end up calling corresponding methods or Builders in the
|
||||
# DefaultEnvironment().
|
||||
GlobalDefaultEnvironmentFunctions = [
|
||||
# Methods from the SConsEnvironment class, above.
|
||||
'Default',
|
||||
'EnsurePythonVersion',
|
||||
'EnsureSConsVersion',
|
||||
'Exit',
|
||||
'Export',
|
||||
'GetLaunchDir',
|
||||
'GetOption',
|
||||
'Help',
|
||||
'Import',
|
||||
#'SConscript', is handled separately, below.
|
||||
'SConscriptChdir',
|
||||
'SetOption',
|
||||
|
||||
# Methods from the Environment.Base class.
|
||||
'AddPostAction',
|
||||
'AddPreAction',
|
||||
'Alias',
|
||||
'AlwaysBuild',
|
||||
'BuildDir',
|
||||
'CacheDir',
|
||||
'Clean',
|
||||
#The Command() method is handled separately, below.
|
||||
'Depends',
|
||||
'Dir',
|
||||
'NoClean',
|
||||
'NoCache',
|
||||
'Entry',
|
||||
'Execute',
|
||||
'File',
|
||||
'FindFile',
|
||||
'Flatten',
|
||||
'GetBuildPath',
|
||||
'Ignore',
|
||||
'Install',
|
||||
'InstallAs',
|
||||
'Literal',
|
||||
'Local',
|
||||
'ParseDepends',
|
||||
'Precious',
|
||||
'Repository',
|
||||
'SConsignFile',
|
||||
'SideEffect',
|
||||
'SourceCode',
|
||||
'SourceSignatures',
|
||||
'Split',
|
||||
'TargetSignatures',
|
||||
'Value',
|
||||
]
|
||||
|
||||
GlobalDefaultBuilders = [
|
||||
# Supported builders.
|
||||
'CFile',
|
||||
'CXXFile',
|
||||
'DVI',
|
||||
'Jar',
|
||||
'Java',
|
||||
'JavaH',
|
||||
'Library',
|
||||
'M4',
|
||||
'MSVSProject',
|
||||
'Object',
|
||||
'PCH',
|
||||
'PDF',
|
||||
'PostScript',
|
||||
'Program',
|
||||
'RES',
|
||||
'RMIC',
|
||||
'SharedLibrary',
|
||||
'SharedObject',
|
||||
'StaticLibrary',
|
||||
'StaticObject',
|
||||
'Tar',
|
||||
'TypeLibrary',
|
||||
'Zip',
|
||||
]
|
||||
|
||||
for name in GlobalDefaultEnvironmentFunctions + GlobalDefaultBuilders:
|
||||
exec "%s = _SConscript.DefaultEnvironmentCall(%s)" % (name, repr(name))
|
||||
del name
|
||||
|
||||
# There are a handful of variables that used to live in the
|
||||
# Script/SConscript.py module that some SConscript files out there were
|
||||
# accessing directly as SCons.Script.SConscript.*. The problem is that
|
||||
# "SConscript" in this namespace is no longer a module, it's a global
|
||||
# function call--or more precisely, an object that implements a global
|
||||
# function call through the default Environment. Nevertheless, we can
|
||||
# maintain backwards compatibility for SConscripts that were reaching in
|
||||
# this way by hanging some attributes off the "SConscript" object here.
|
||||
SConscript = _SConscript.DefaultEnvironmentCall('SConscript')
|
||||
|
||||
# Make SConscript look enough like the module it used to be so
|
||||
# that pychecker doesn't barf.
|
||||
SConscript.__name__ = 'SConscript'
|
||||
|
||||
SConscript.Arguments = ARGUMENTS
|
||||
SConscript.ArgList = ARGLIST
|
||||
SConscript.BuildTargets = BUILD_TARGETS
|
||||
SConscript.CommandLineTargets = COMMAND_LINE_TARGETS
|
||||
SConscript.DefaultTargets = DEFAULT_TARGETS
|
||||
|
||||
# The global Command() function must be handled differently than the
|
||||
# global functions for other construction environment methods because
|
||||
# we want people to be able to use Actions that must expand $TARGET
|
||||
# and $SOURCE later, when (and if) the Action is invoked to build
|
||||
# the target(s). We do this with the subst=1 argument, which creates
|
||||
# a DefaultEnvironmentCall instance that wraps up a normal default
|
||||
# construction environment that performs variable substitution, not a
|
||||
# proxy that doesn't.
|
||||
#
|
||||
# There's a flaw here, though, because any other $-variables on a command
|
||||
# line will *also* be expanded, each to a null string, but that should
|
||||
# only be a problem in the unusual case where someone was passing a '$'
|
||||
# on a command line and *expected* the $ to get through to the shell
|
||||
# because they were calling Command() and not env.Command()... This is
|
||||
# unlikely enough that we're going to leave this as is and cross that
|
||||
# bridge if someone actually comes to it.
|
||||
Command = _SConscript.DefaultEnvironmentCall('Command', subst=1)
|
|
@ -6,7 +6,7 @@ utility.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -28,13 +28,13 @@ utility.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Sig/MD5.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Sig/MD5.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import imp
|
||||
import string
|
||||
|
||||
# Force Python to load the builtin "md5" module. If we do this with a
|
||||
# normal import statement, then case-insensitive systems (Win32) get
|
||||
# normal import statement, then case-insensitive systems (Windows) get
|
||||
# confused and thinks there's a case mismatch with *this* MD5.py module.
|
||||
file, name, desc = imp.find_module('md5')
|
||||
try:
|
||||
|
@ -49,18 +49,30 @@ def current(new, old):
|
|||
"""
|
||||
return new == old
|
||||
|
||||
def hexdigest(s):
|
||||
"""Return a signature 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.
|
||||
try:
|
||||
md5.new('').hexdigest
|
||||
except AttributeError:
|
||||
# The md5 objects created by the module have no native hexdigest()
|
||||
# method (*cough* 1.5.2 *cough*) so provide an equivalent.
|
||||
class new_md5:
|
||||
def __init__(self, s):
|
||||
self.m = md5.new(str(s))
|
||||
#def copy(self):
|
||||
# return self.m.copy()
|
||||
def digest(self):
|
||||
return self.m.digest()
|
||||
def hexdigest(self):
|
||||
h = string.hexdigits
|
||||
r = ''
|
||||
for c in s:
|
||||
for c in self.m.digest():
|
||||
i = ord(c)
|
||||
r = r + h[(i >> 4) & 0xF] + h[i & 0xF]
|
||||
return r
|
||||
def update(self, s):
|
||||
return self.m.update(s)
|
||||
|
||||
else:
|
||||
new_md5 = lambda s: md5.new(str(s))
|
||||
|
||||
def collect(signatures):
|
||||
"""
|
||||
|
@ -72,8 +84,7 @@ def collect(signatures):
|
|||
if len(signatures) == 1:
|
||||
return signatures[0]
|
||||
else:
|
||||
contents = string.join(signatures, ', ')
|
||||
return hexdigest(md5.new(contents).digest())
|
||||
return new_md5(string.join(signatures, ', ')).hexdigest()
|
||||
|
||||
def signature(obj):
|
||||
"""Generate a signature for an object
|
||||
|
@ -82,7 +93,7 @@ def signature(obj):
|
|||
gc = obj.get_contents
|
||||
except AttributeError:
|
||||
raise AttributeError, "unable to fetch contents of '%s'" % str(obj)
|
||||
return hexdigest(md5.new(str(gc())).digest())
|
||||
return new_md5(gc()).hexdigest()
|
||||
|
||||
def to_string(signature):
|
||||
"""Convert a signature to a string"""
|
|
@ -6,7 +6,7 @@ utility.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -28,7 +28,7 @@ utility.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Sig/TimeStamp.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Sig/TimeStamp.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
def current(new, old):
|
||||
"""Return whether a new timestamp is up-to-date with
|
|
@ -5,7 +5,7 @@ The Signature package for the scons software construction utility.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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 @@ The Signature package for the scons software construction utility.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Sig/__init__.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Sig/__init__.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
try:
|
||||
import MD5
|
||||
|
@ -36,34 +36,18 @@ except ImportError:
|
|||
import TimeStamp
|
||||
default_module = TimeStamp
|
||||
|
||||
# XXX We should move max_drift into Node/FS.py,
|
||||
# since it's really something about files.
|
||||
default_max_drift = 2*24*60*60
|
||||
|
||||
class SConsignEntry:
|
||||
"""The old SConsignEntry format.
|
||||
We keep this around to handle conversions from old .sconsign files."""
|
||||
timestamp = None
|
||||
bsig = None
|
||||
csig = None
|
||||
implicit = None
|
||||
|
||||
class Calculator:
|
||||
"""
|
||||
Encapsulates signature calculations and .sconsign file generating
|
||||
for the build engine.
|
||||
"""
|
||||
|
||||
def __init__(self, module=default_module, max_drift=default_max_drift):
|
||||
def __init__(self, module=default_module):
|
||||
"""
|
||||
Initialize the calculator.
|
||||
|
||||
module - the signature module to use for signature calculations
|
||||
max_drift - the maximum system clock drift used to determine when to
|
||||
cache content signatures. A negative value means to never cache
|
||||
content signatures. (defaults to 2 days)
|
||||
"""
|
||||
self.module = module
|
||||
self.max_drift = max_drift
|
||||
|
||||
default_calc = Calculator()
|
853
scons/scons-local-0.97/SCons/Subst.py
Normal file
853
scons/scons-local-0.97/SCons/Subst.py
Normal file
|
@ -0,0 +1,853 @@
|
|||
"""SCons.Subst
|
||||
|
||||
SCons string substitution.
|
||||
|
||||
"""
|
||||
|
||||
#
|
||||
# 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/Subst.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import SCons.compat
|
||||
|
||||
import re
|
||||
import string
|
||||
import types
|
||||
import UserList
|
||||
import UserString
|
||||
|
||||
import SCons.Errors
|
||||
|
||||
from SCons.Util import is_String, is_List, is_Tuple
|
||||
|
||||
# Indexed by the SUBST_* constants below.
|
||||
_strconv = [SCons.Util.to_String,
|
||||
SCons.Util.to_String,
|
||||
SCons.Util.to_String_for_signature]
|
||||
|
||||
|
||||
|
||||
AllowableExceptions = (IndexError, NameError)
|
||||
|
||||
def SetAllowableExceptions(*excepts):
|
||||
global AllowableExceptions
|
||||
AllowableExceptions = filter(None, excepts)
|
||||
|
||||
def raise_exception(exception, target, s):
|
||||
name = exception.__class__.__name__
|
||||
msg = "%s `%s' trying to evaluate `%s'" % (name, exception, s)
|
||||
if target:
|
||||
raise SCons.Errors.BuildError, (target[0], msg)
|
||||
else:
|
||||
raise SCons.Errors.UserError, msg
|
||||
|
||||
|
||||
|
||||
class Literal:
|
||||
"""A wrapper for a string. If you use this object wrapped
|
||||
around a string, then it will be interpreted as literal.
|
||||
When passed to the command interpreter, all special
|
||||
characters will be escaped."""
|
||||
def __init__(self, lstr):
|
||||
self.lstr = lstr
|
||||
|
||||
def __str__(self):
|
||||
return self.lstr
|
||||
|
||||
def escape(self, escape_func):
|
||||
return escape_func(self.lstr)
|
||||
|
||||
def for_signature(self):
|
||||
return self.lstr
|
||||
|
||||
def is_literal(self):
|
||||
return 1
|
||||
|
||||
class SpecialAttrWrapper:
|
||||
"""This is a wrapper for what we call a 'Node special attribute.'
|
||||
This is any of the attributes of a Node that we can reference from
|
||||
Environment variable substitution, such as $TARGET.abspath or
|
||||
$SOURCES[1].filebase. We implement the same methods as Literal
|
||||
so we can handle special characters, plus a for_signature method,
|
||||
such that we can return some canonical string during signature
|
||||
calculation to avoid unnecessary rebuilds."""
|
||||
|
||||
def __init__(self, lstr, for_signature=None):
|
||||
"""The for_signature parameter, if supplied, will be the
|
||||
canonical string we return from for_signature(). Else
|
||||
we will simply return lstr."""
|
||||
self.lstr = lstr
|
||||
if for_signature:
|
||||
self.forsig = for_signature
|
||||
else:
|
||||
self.forsig = lstr
|
||||
|
||||
def __str__(self):
|
||||
return self.lstr
|
||||
|
||||
def escape(self, escape_func):
|
||||
return escape_func(self.lstr)
|
||||
|
||||
def for_signature(self):
|
||||
return self.forsig
|
||||
|
||||
def is_literal(self):
|
||||
return 1
|
||||
|
||||
def quote_spaces(arg):
|
||||
"""Generic function for putting double quotes around any string that
|
||||
has white space in it."""
|
||||
if ' ' in arg or '\t' in arg:
|
||||
return '"%s"' % arg
|
||||
else:
|
||||
return str(arg)
|
||||
|
||||
class CmdStringHolder(UserString.UserString):
|
||||
"""This is a special class used to hold strings generated by
|
||||
scons_subst() and scons_subst_list(). It defines a special method
|
||||
escape(). When passed a function with an escape algorithm for a
|
||||
particular platform, it will return the contained string with the
|
||||
proper escape sequences inserted.
|
||||
"""
|
||||
def __init__(self, cmd, literal=None):
|
||||
UserString.UserString.__init__(self, cmd)
|
||||
self.literal = literal
|
||||
|
||||
def is_literal(self):
|
||||
return self.literal
|
||||
|
||||
def escape(self, escape_func, quote_func=quote_spaces):
|
||||
"""Escape the string with the supplied function. The
|
||||
function is expected to take an arbitrary string, then
|
||||
return it with all special characters escaped and ready
|
||||
for passing to the command interpreter.
|
||||
|
||||
After calling this function, the next call to str() will
|
||||
return the escaped string.
|
||||
"""
|
||||
|
||||
if self.is_literal():
|
||||
return escape_func(self.data)
|
||||
elif ' ' in self.data or '\t' in self.data:
|
||||
return quote_func(self.data)
|
||||
else:
|
||||
return self.data
|
||||
|
||||
def escape_list(list, escape_func):
|
||||
"""Escape a list of arguments by running the specified escape_func
|
||||
on every object in the list that has an escape() method."""
|
||||
def escape(obj, escape_func=escape_func):
|
||||
try:
|
||||
e = obj.escape
|
||||
except AttributeError:
|
||||
return obj
|
||||
else:
|
||||
return e(escape_func)
|
||||
return map(escape, list)
|
||||
|
||||
class NLWrapper:
|
||||
"""A wrapper class that delays turning a list of sources or targets
|
||||
into a NodeList until it's needed. The specified function supplied
|
||||
when the object is initialized is responsible for turning raw nodes
|
||||
into proxies that implement the special attributes like .abspath,
|
||||
.source, etc. This way, we avoid creating those proxies just
|
||||
"in case" someone is going to use $TARGET or the like, and only
|
||||
go through the trouble if we really have to.
|
||||
|
||||
In practice, this might be a wash performance-wise, but it's a little
|
||||
cleaner conceptually...
|
||||
"""
|
||||
|
||||
def __init__(self, list, func):
|
||||
self.list = list
|
||||
self.func = func
|
||||
def _return_nodelist(self):
|
||||
return self.nodelist
|
||||
def _gen_nodelist(self):
|
||||
list = self.list
|
||||
if list is None:
|
||||
list = []
|
||||
elif not is_List(list) and not is_Tuple(list):
|
||||
list = [list]
|
||||
# The map(self.func) call is what actually turns
|
||||
# a list into appropriate proxies.
|
||||
self.nodelist = SCons.Util.NodeList(map(self.func, list))
|
||||
self._create_nodelist = self._return_nodelist
|
||||
return self.nodelist
|
||||
_create_nodelist = _gen_nodelist
|
||||
|
||||
|
||||
class Targets_or_Sources(UserList.UserList):
|
||||
"""A class that implements $TARGETS or $SOURCES expansions by in turn
|
||||
wrapping a NLWrapper. This class handles the different methods used
|
||||
to access the list, calling the NLWrapper to create proxies on demand.
|
||||
|
||||
Note that we subclass UserList.UserList purely so that the is_List()
|
||||
function will identify an object of this class as a list during
|
||||
variable expansion. We're not really using any UserList.UserList
|
||||
methods in practice.
|
||||
"""
|
||||
def __init__(self, nl):
|
||||
self.nl = nl
|
||||
def __getattr__(self, attr):
|
||||
nl = self.nl._create_nodelist()
|
||||
return getattr(nl, attr)
|
||||
def __getitem__(self, i):
|
||||
nl = self.nl._create_nodelist()
|
||||
return nl[i]
|
||||
def __getslice__(self, i, j):
|
||||
nl = self.nl._create_nodelist()
|
||||
i = max(i, 0); j = max(j, 0)
|
||||
return nl[i:j]
|
||||
def __str__(self):
|
||||
nl = self.nl._create_nodelist()
|
||||
return str(nl)
|
||||
def __repr__(self):
|
||||
nl = self.nl._create_nodelist()
|
||||
return repr(nl)
|
||||
|
||||
class Target_or_Source:
|
||||
"""A class that implements $TARGET or $SOURCE expansions by in turn
|
||||
wrapping a NLWrapper. This class handles the different methods used
|
||||
to access an individual proxy Node, calling the NLWrapper to create
|
||||
a proxy on demand.
|
||||
"""
|
||||
def __init__(self, nl):
|
||||
self.nl = nl
|
||||
def __getattr__(self, attr):
|
||||
nl = self.nl._create_nodelist()
|
||||
try:
|
||||
nl0 = nl[0]
|
||||
except IndexError:
|
||||
# If there is nothing in the list, then we have no attributes to
|
||||
# pass through, so raise AttributeError for everything.
|
||||
raise AttributeError, "NodeList has no attribute: %s" % attr
|
||||
return getattr(nl0, attr)
|
||||
def __str__(self):
|
||||
nl = self.nl._create_nodelist()
|
||||
if nl:
|
||||
return str(nl[0])
|
||||
return ''
|
||||
def __repr__(self):
|
||||
nl = self.nl._create_nodelist()
|
||||
if nl:
|
||||
return repr(nl[0])
|
||||
return ''
|
||||
|
||||
def subst_dict(target, source):
|
||||
"""Create a dictionary for substitution of special
|
||||
construction variables.
|
||||
|
||||
This translates the following special arguments:
|
||||
|
||||
target - the target (object or array of objects),
|
||||
used to generate the TARGET and TARGETS
|
||||
construction variables
|
||||
|
||||
source - the source (object or array of objects),
|
||||
used to generate the SOURCES and SOURCE
|
||||
construction variables
|
||||
"""
|
||||
dict = {}
|
||||
|
||||
if target:
|
||||
tnl = NLWrapper(target, lambda x: x.get_subst_proxy())
|
||||
dict['TARGETS'] = Targets_or_Sources(tnl)
|
||||
dict['TARGET'] = Target_or_Source(tnl)
|
||||
else:
|
||||
dict['TARGETS'] = None
|
||||
dict['TARGET'] = None
|
||||
|
||||
if source:
|
||||
def get_src_subst_proxy(node):
|
||||
try:
|
||||
rfile = node.rfile
|
||||
except AttributeError:
|
||||
pass
|
||||
else:
|
||||
node = rfile()
|
||||
return node.get_subst_proxy()
|
||||
snl = NLWrapper(source, get_src_subst_proxy)
|
||||
dict['SOURCES'] = Targets_or_Sources(snl)
|
||||
dict['SOURCE'] = Target_or_Source(snl)
|
||||
else:
|
||||
dict['SOURCES'] = None
|
||||
dict['SOURCE'] = None
|
||||
|
||||
return dict
|
||||
|
||||
# Constants for the "mode" parameter to scons_subst_list() and
|
||||
# scons_subst(). SUBST_RAW gives the raw command line. SUBST_CMD
|
||||
# gives a command line suitable for passing to a shell. SUBST_SIG
|
||||
# gives a command line appropriate for calculating the signature
|
||||
# of a command line...if this changes, we should rebuild.
|
||||
SUBST_CMD = 0
|
||||
SUBST_RAW = 1
|
||||
SUBST_SIG = 2
|
||||
|
||||
_rm = re.compile(r'\$[()]')
|
||||
_remove = re.compile(r'\$\([^\$]*(\$[^\)][^\$]*)*\$\)')
|
||||
|
||||
# Indexed by the SUBST_* constants above.
|
||||
_regex_remove = [ _rm, None, _remove ]
|
||||
|
||||
# Regular expressions for splitting strings and handling substitutions,
|
||||
# for use by the scons_subst() and scons_subst_list() functions:
|
||||
#
|
||||
# The first expression compiled matches all of the $-introduced tokens
|
||||
# that we need to process in some way, and is used for substitutions.
|
||||
# The expressions it matches are:
|
||||
#
|
||||
# "$$"
|
||||
# "$("
|
||||
# "$)"
|
||||
# "$variable" [must begin with alphabetic or underscore]
|
||||
# "${any stuff}"
|
||||
#
|
||||
# The second expression compiled is used for splitting strings into tokens
|
||||
# to be processed, and it matches all of the tokens listed above, plus
|
||||
# the following that affect how arguments do or don't get joined together:
|
||||
#
|
||||
# " " [white space]
|
||||
# "non-white-space" [without any dollar signs]
|
||||
# "$" [single dollar sign]
|
||||
#
|
||||
_dollar_exps_str = r'\$[\$\(\)]|\$[_a-zA-Z][\.\w]*|\${[^}]*}'
|
||||
_dollar_exps = re.compile(r'(%s)' % _dollar_exps_str)
|
||||
_separate_args = re.compile(r'(%s|\s+|[^\s\$]+|\$)' % _dollar_exps_str)
|
||||
|
||||
# This regular expression is used to replace strings of multiple white
|
||||
# space characters in the string result from the scons_subst() function.
|
||||
_space_sep = re.compile(r'[\t ]+(?![^{]*})')
|
||||
|
||||
def scons_subst(strSubst, env, mode=SUBST_RAW, target=None, source=None, gvars={}, lvars={}, conv=None):
|
||||
"""Expand a string containing construction variable substitutions.
|
||||
|
||||
This is the work-horse function for substitutions in file names
|
||||
and the like. The companion scons_subst_list() function (below)
|
||||
handles separating command lines into lists of arguments, so see
|
||||
that function if that's what you're looking for.
|
||||
"""
|
||||
if type(strSubst) == types.StringType and string.find(strSubst, '$') < 0:
|
||||
return strSubst
|
||||
|
||||
class StringSubber:
|
||||
"""A class to construct the results of a scons_subst() call.
|
||||
|
||||
This binds a specific construction environment, mode, target and
|
||||
source with two methods (substitute() and expand()) that handle
|
||||
the expansion.
|
||||
"""
|
||||
def __init__(self, env, mode, target, source, conv, gvars):
|
||||
self.env = env
|
||||
self.mode = mode
|
||||
self.target = target
|
||||
self.source = source
|
||||
self.conv = conv
|
||||
self.gvars = gvars
|
||||
|
||||
def expand(self, s, lvars):
|
||||
"""Expand a single "token" as necessary, returning an
|
||||
appropriate string containing the expansion.
|
||||
|
||||
This handles expanding different types of things (strings,
|
||||
lists, callables) appropriately. It calls the wrapper
|
||||
substitute() method to re-expand things as necessary, so that
|
||||
the results of expansions of side-by-side strings still get
|
||||
re-evaluated separately, not smushed together.
|
||||
"""
|
||||
if is_String(s):
|
||||
try:
|
||||
s0, s1 = s[:2]
|
||||
except (IndexError, ValueError):
|
||||
return s
|
||||
if s0 != '$':
|
||||
return s
|
||||
if s1 == '$':
|
||||
return '$'
|
||||
elif s1 in '()':
|
||||
return s
|
||||
else:
|
||||
key = s[1:]
|
||||
if key[0] == '{' or string.find(key, '.') >= 0:
|
||||
if key[0] == '{':
|
||||
key = key[1:-1]
|
||||
try:
|
||||
s = eval(key, self.gvars, lvars)
|
||||
except KeyboardInterrupt:
|
||||
raise
|
||||
except Exception, e:
|
||||
if e.__class__ in AllowableExceptions:
|
||||
return ''
|
||||
raise_exception(e, self.target, s)
|
||||
else:
|
||||
if lvars.has_key(key):
|
||||
s = lvars[key]
|
||||
elif self.gvars.has_key(key):
|
||||
s = self.gvars[key]
|
||||
elif not NameError in AllowableExceptions:
|
||||
raise_exception(NameError(key), self.target, s)
|
||||
else:
|
||||
return ''
|
||||
|
||||
# Before re-expanding the result, handle
|
||||
# recursive expansion by copying the local
|
||||
# variable dictionary and overwriting a null
|
||||
# string for the value of the variable name
|
||||
# we just expanded.
|
||||
#
|
||||
# This could potentially be optimized by only
|
||||
# copying lvars when s contains more expansions,
|
||||
# but lvars is usually supposed to be pretty
|
||||
# small, and deeply nested variable expansions
|
||||
# are probably more the exception than the norm,
|
||||
# so it should be tolerable for now.
|
||||
lv = lvars.copy()
|
||||
var = string.split(key, '.')[0]
|
||||
lv[var] = ''
|
||||
return self.substitute(s, lv)
|
||||
elif is_List(s) or is_Tuple(s):
|
||||
def func(l, conv=self.conv, substitute=self.substitute, lvars=lvars):
|
||||
return conv(substitute(l, lvars))
|
||||
r = map(func, s)
|
||||
return string.join(r)
|
||||
elif callable(s):
|
||||
try:
|
||||
s = s(target=self.target,
|
||||
source=self.source,
|
||||
env=self.env,
|
||||
for_signature=(self.mode != SUBST_CMD))
|
||||
except TypeError:
|
||||
# This probably indicates that it's a callable
|
||||
# object that doesn't match our calling arguments
|
||||
# (like an Action).
|
||||
if self.mode == SUBST_RAW:
|
||||
return s
|
||||
s = self.conv(s)
|
||||
return self.substitute(s, lvars)
|
||||
elif s is None:
|
||||
return ''
|
||||
else:
|
||||
return s
|
||||
|
||||
def substitute(self, args, lvars):
|
||||
"""Substitute expansions in an argument or list of arguments.
|
||||
|
||||
This serves as a wrapper for splitting up a string into
|
||||
separate tokens.
|
||||
"""
|
||||
if is_String(args) and not isinstance(args, CmdStringHolder):
|
||||
try:
|
||||
def sub_match(match, conv=self.conv, expand=self.expand, lvars=lvars):
|
||||
return conv(expand(match.group(1), lvars))
|
||||
result = _dollar_exps.sub(sub_match, args)
|
||||
except TypeError:
|
||||
# If the internal conversion routine doesn't return
|
||||
# strings (it could be overridden to return Nodes, for
|
||||
# example), then the 1.5.2 re module will throw this
|
||||
# exception. Back off to a slower, general-purpose
|
||||
# algorithm that works for all data types.
|
||||
args = _separate_args.findall(args)
|
||||
result = []
|
||||
for a in args:
|
||||
result.append(self.conv(self.expand(a, lvars)))
|
||||
try:
|
||||
result = string.join(result, '')
|
||||
except TypeError:
|
||||
if len(result) == 1:
|
||||
result = result[0]
|
||||
return result
|
||||
else:
|
||||
return self.expand(args, lvars)
|
||||
|
||||
if conv is None:
|
||||
conv = _strconv[mode]
|
||||
|
||||
# Doing this every time is a bit of a waste, since the Executor
|
||||
# has typically already populated the OverrideEnvironment with
|
||||
# $TARGET/$SOURCE variables. We're keeping this (for now), though,
|
||||
# because it supports existing behavior that allows us to call
|
||||
# an Action directly with an arbitrary target+source pair, which
|
||||
# we use in Tool/tex.py to handle calling $BIBTEX when necessary.
|
||||
# If we dropped that behavior (or found another way to cover it),
|
||||
# we could get rid of this call completely and just rely on the
|
||||
# Executor setting the variables.
|
||||
d = subst_dict(target, source)
|
||||
if d:
|
||||
lvars = lvars.copy()
|
||||
lvars.update(d)
|
||||
|
||||
# We're (most likely) going to eval() things. If Python doesn't
|
||||
# find a __builtins__ value in the global dictionary used for eval(),
|
||||
# it copies the current global values for you. Avoid this by
|
||||
# setting it explicitly and then deleting, so we don't pollute the
|
||||
# construction environment Dictionary(ies) that are typically used
|
||||
# for expansion.
|
||||
gvars['__builtins__'] = __builtins__
|
||||
|
||||
ss = StringSubber(env, mode, target, source, conv, gvars)
|
||||
result = ss.substitute(strSubst, lvars)
|
||||
|
||||
try:
|
||||
del gvars['__builtins__']
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
if is_String(result):
|
||||
# Remove $(-$) pairs and any stuff in between,
|
||||
# if that's appropriate.
|
||||
remove = _regex_remove[mode]
|
||||
if remove:
|
||||
result = remove.sub('', result)
|
||||
if mode != SUBST_RAW:
|
||||
# Compress strings of white space characters into
|
||||
# a single space.
|
||||
result = string.strip(_space_sep.sub(' ', result))
|
||||
|
||||
return result
|
||||
|
||||
#Subst_List_Strings = {}
|
||||
|
||||
def scons_subst_list(strSubst, env, mode=SUBST_RAW, target=None, source=None, gvars={}, lvars={}, conv=None):
|
||||
"""Substitute construction variables in a string (or list or other
|
||||
object) and separate the arguments into a command list.
|
||||
|
||||
The companion scons_subst() function (above) handles basic
|
||||
substitutions within strings, so see that function instead
|
||||
if that's what you're looking for.
|
||||
"""
|
||||
# try:
|
||||
# Subst_List_Strings[strSubst] = Subst_List_Strings[strSubst] + 1
|
||||
# except KeyError:
|
||||
# Subst_List_Strings[strSubst] = 1
|
||||
# import SCons.Debug
|
||||
# SCons.Debug.caller(1)
|
||||
class ListSubber(UserList.UserList):
|
||||
"""A class to construct the results of a scons_subst_list() call.
|
||||
|
||||
Like StringSubber, this class binds a specific construction
|
||||
environment, mode, target and source with two methods
|
||||
(substitute() and expand()) that handle the expansion.
|
||||
|
||||
In addition, however, this class is used to track the state of
|
||||
the result(s) we're gathering so we can do the appropriate thing
|
||||
whenever we have to append another word to the result--start a new
|
||||
line, start a new word, append to the current word, etc. We do
|
||||
this by setting the "append" attribute to the right method so
|
||||
that our wrapper methods only need ever call ListSubber.append(),
|
||||
and the rest of the object takes care of doing the right thing
|
||||
internally.
|
||||
"""
|
||||
def __init__(self, env, mode, target, source, conv, gvars):
|
||||
UserList.UserList.__init__(self, [])
|
||||
self.env = env
|
||||
self.mode = mode
|
||||
self.target = target
|
||||
self.source = source
|
||||
self.conv = conv
|
||||
self.gvars = gvars
|
||||
|
||||
if self.mode == SUBST_RAW:
|
||||
self.add_strip = lambda x, s=self: s.append(x)
|
||||
else:
|
||||
self.add_strip = lambda x, s=self: None
|
||||
self.in_strip = None
|
||||
self.next_line()
|
||||
|
||||
def expand(self, s, lvars, within_list):
|
||||
"""Expand a single "token" as necessary, appending the
|
||||
expansion to the current result.
|
||||
|
||||
This handles expanding different types of things (strings,
|
||||
lists, callables) appropriately. It calls the wrapper
|
||||
substitute() method to re-expand things as necessary, so that
|
||||
the results of expansions of side-by-side strings still get
|
||||
re-evaluated separately, not smushed together.
|
||||
"""
|
||||
|
||||
if is_String(s):
|
||||
try:
|
||||
s0, s1 = s[:2]
|
||||
except (IndexError, ValueError):
|
||||
self.append(s)
|
||||
return
|
||||
if s0 != '$':
|
||||
self.append(s)
|
||||
return
|
||||
if s1 == '$':
|
||||
self.append('$')
|
||||
elif s1 == '(':
|
||||
self.open_strip('$(')
|
||||
elif s1 == ')':
|
||||
self.close_strip('$)')
|
||||
else:
|
||||
key = s[1:]
|
||||
if key[0] == '{' or string.find(key, '.') >= 0:
|
||||
if key[0] == '{':
|
||||
key = key[1:-1]
|
||||
try:
|
||||
s = eval(key, self.gvars, lvars)
|
||||
except KeyboardInterrupt:
|
||||
raise
|
||||
except Exception, e:
|
||||
if e.__class__ in AllowableExceptions:
|
||||
return
|
||||
raise_exception(e, self.target, s)
|
||||
else:
|
||||
if lvars.has_key(key):
|
||||
s = lvars[key]
|
||||
elif self.gvars.has_key(key):
|
||||
s = self.gvars[key]
|
||||
elif not NameError in AllowableExceptions:
|
||||
raise_exception(NameError(), self.target, s)
|
||||
else:
|
||||
return
|
||||
|
||||
# Before re-expanding the result, handle
|
||||
# recursive expansion by copying the local
|
||||
# variable dictionary and overwriting a null
|
||||
# string for the value of the variable name
|
||||
# we just expanded.
|
||||
lv = lvars.copy()
|
||||
var = string.split(key, '.')[0]
|
||||
lv[var] = ''
|
||||
self.substitute(s, lv, 0)
|
||||
self.this_word()
|
||||
elif is_List(s) or is_Tuple(s):
|
||||
for a in s:
|
||||
self.substitute(a, lvars, 1)
|
||||
self.next_word()
|
||||
elif callable(s):
|
||||
try:
|
||||
s = s(target=self.target,
|
||||
source=self.source,
|
||||
env=self.env,
|
||||
for_signature=(self.mode != SUBST_CMD))
|
||||
except TypeError:
|
||||
# This probably indicates that it's a callable
|
||||
# object that doesn't match our calling arguments
|
||||
# (like an Action).
|
||||
if self.mode == SUBST_RAW:
|
||||
self.append(s)
|
||||
return
|
||||
s = self.conv(s)
|
||||
self.substitute(s, lvars, within_list)
|
||||
elif s is None:
|
||||
self.this_word()
|
||||
else:
|
||||
self.append(s)
|
||||
|
||||
def substitute(self, args, lvars, within_list):
|
||||
"""Substitute expansions in an argument or list of arguments.
|
||||
|
||||
This serves as a wrapper for splitting up a string into
|
||||
separate tokens.
|
||||
"""
|
||||
|
||||
if is_String(args) and not isinstance(args, CmdStringHolder):
|
||||
args = _separate_args.findall(args)
|
||||
for a in args:
|
||||
if a[0] in ' \t\n\r\f\v':
|
||||
if '\n' in a:
|
||||
self.next_line()
|
||||
elif within_list:
|
||||
self.append(a)
|
||||
else:
|
||||
self.next_word()
|
||||
else:
|
||||
self.expand(a, lvars, within_list)
|
||||
else:
|
||||
self.expand(args, lvars, within_list)
|
||||
|
||||
def next_line(self):
|
||||
"""Arrange for the next word to start a new line. This
|
||||
is like starting a new word, except that we have to append
|
||||
another line to the result."""
|
||||
UserList.UserList.append(self, [])
|
||||
self.next_word()
|
||||
|
||||
def this_word(self):
|
||||
"""Arrange for the next word to append to the end of the
|
||||
current last word in the result."""
|
||||
self.append = self.add_to_current_word
|
||||
|
||||
def next_word(self):
|
||||
"""Arrange for the next word to start a new word."""
|
||||
self.append = self.add_new_word
|
||||
|
||||
def add_to_current_word(self, x):
|
||||
"""Append the string x to the end of the current last word
|
||||
in the result. If that is not possible, then just add
|
||||
it as a new word. Make sure the entire concatenated string
|
||||
inherits the object attributes of x (in particular, the
|
||||
escape function) by wrapping it as CmdStringHolder."""
|
||||
|
||||
if not self.in_strip or self.mode != SUBST_SIG:
|
||||
try:
|
||||
current_word = self[-1][-1]
|
||||
except IndexError:
|
||||
self.add_new_word(x)
|
||||
else:
|
||||
# All right, this is a hack and it should probably
|
||||
# be refactored out of existence in the future.
|
||||
# The issue is that we want to smoosh words together
|
||||
# and make one file name that gets escaped if
|
||||
# we're expanding something like foo$EXTENSION,
|
||||
# but we don't want to smoosh them together if
|
||||
# it's something like >$TARGET, because then we'll
|
||||
# treat the '>' like it's part of the file name.
|
||||
# So for now, just hard-code looking for the special
|
||||
# command-line redirection characters...
|
||||
try:
|
||||
last_char = str(current_word)[-1]
|
||||
except IndexError:
|
||||
last_char = '\0'
|
||||
if last_char in '<>|':
|
||||
self.add_new_word(x)
|
||||
else:
|
||||
y = current_word + x
|
||||
|
||||
# We used to treat a word appended to a literal
|
||||
# as a literal itself, but this caused problems
|
||||
# with interpreting quotes around space-separated
|
||||
# targets on command lines. Removing this makes
|
||||
# none of the "substantive" end-to-end tests fail,
|
||||
# so we'll take this out but leave it commented
|
||||
# for now in case there's a problem not covered
|
||||
# by the test cases and we need to resurrect this.
|
||||
#literal1 = self.literal(self[-1][-1])
|
||||
#literal2 = self.literal(x)
|
||||
y = self.conv(y)
|
||||
if is_String(y):
|
||||
#y = CmdStringHolder(y, literal1 or literal2)
|
||||
y = CmdStringHolder(y, None)
|
||||
self[-1][-1] = y
|
||||
|
||||
def add_new_word(self, x):
|
||||
if not self.in_strip or self.mode != SUBST_SIG:
|
||||
literal = self.literal(x)
|
||||
x = self.conv(x)
|
||||
if is_String(x):
|
||||
x = CmdStringHolder(x, literal)
|
||||
self[-1].append(x)
|
||||
self.append = self.add_to_current_word
|
||||
|
||||
def literal(self, x):
|
||||
try:
|
||||
l = x.is_literal
|
||||
except AttributeError:
|
||||
return None
|
||||
else:
|
||||
return l()
|
||||
|
||||
def open_strip(self, x):
|
||||
"""Handle the "open strip" $( token."""
|
||||
self.add_strip(x)
|
||||
self.in_strip = 1
|
||||
|
||||
def close_strip(self, x):
|
||||
"""Handle the "close strip" $) token."""
|
||||
self.add_strip(x)
|
||||
self.in_strip = None
|
||||
|
||||
if conv is None:
|
||||
conv = _strconv[mode]
|
||||
|
||||
# Doing this every time is a bit of a waste, since the Executor
|
||||
# has typically already populated the OverrideEnvironment with
|
||||
# $TARGET/$SOURCE variables. We're keeping this (for now), though,
|
||||
# because it supports existing behavior that allows us to call
|
||||
# an Action directly with an arbitrary target+source pair, which
|
||||
# we use in Tool/tex.py to handle calling $BIBTEX when necessary.
|
||||
# If we dropped that behavior (or found another way to cover it),
|
||||
# we could get rid of this call completely and just rely on the
|
||||
# Executor setting the variables.
|
||||
d = subst_dict(target, source)
|
||||
if d:
|
||||
lvars = lvars.copy()
|
||||
lvars.update(d)
|
||||
|
||||
# We're (most likely) going to eval() things. If Python doesn't
|
||||
# find a __builtins__ value in the global dictionary used for eval(),
|
||||
# it copies the current global values for you. Avoid this by
|
||||
# setting it explicitly and then deleting, so we don't pollute the
|
||||
# construction environment Dictionary(ies) that are typically used
|
||||
# for expansion.
|
||||
gvars['__builtins__'] = __builtins__
|
||||
|
||||
ls = ListSubber(env, mode, target, source, conv, gvars)
|
||||
ls.substitute(strSubst, lvars, 0)
|
||||
|
||||
try:
|
||||
del gvars['__builtins__']
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
return ls.data
|
||||
|
||||
def scons_subst_once(strSubst, env, key):
|
||||
"""Perform single (non-recursive) substitution of a single
|
||||
construction variable keyword.
|
||||
|
||||
This is used when setting a variable when copying or overriding values
|
||||
in an Environment. We want to capture (expand) the old value before
|
||||
we override it, so people can do things like:
|
||||
|
||||
env2 = env.Clone(CCFLAGS = '$CCFLAGS -g')
|
||||
|
||||
We do this with some straightforward, brute-force code here...
|
||||
"""
|
||||
if type(strSubst) == types.StringType and string.find(strSubst, '$') < 0:
|
||||
return strSubst
|
||||
|
||||
matchlist = ['$' + key, '${' + key + '}']
|
||||
val = env.get(key, '')
|
||||
def sub_match(match, val=val, matchlist=matchlist):
|
||||
a = match.group(1)
|
||||
if a in matchlist:
|
||||
a = val
|
||||
if is_List(a) or is_Tuple(a):
|
||||
return string.join(map(str, a))
|
||||
else:
|
||||
return str(a)
|
||||
|
||||
if is_List(strSubst) or is_Tuple(strSubst):
|
||||
result = []
|
||||
for arg in strSubst:
|
||||
if is_String(arg):
|
||||
if arg in matchlist:
|
||||
arg = val
|
||||
if is_List(arg) or is_Tuple(arg):
|
||||
result.extend(arg)
|
||||
else:
|
||||
result.append(arg)
|
||||
else:
|
||||
result.append(_dollar_exps.sub(sub_match, arg))
|
||||
else:
|
||||
result.append(arg)
|
||||
return result
|
||||
elif is_String(strSubst):
|
||||
return _dollar_exps.sub(sub_match, strSubst)
|
||||
else:
|
||||
return strSubst
|
685
scons/scons-local-0.97/SCons/Taskmaster.py
Normal file
685
scons/scons-local-0.97/SCons/Taskmaster.py
Normal file
|
@ -0,0 +1,685 @@
|
|||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
__doc__ = """
|
||||
Generic Taskmaster module for the SCons build engine.
|
||||
|
||||
This module contains the primary interface(s) between a wrapping user
|
||||
interface and the SCons build engine. There are two key classes here:
|
||||
|
||||
Taskmaster
|
||||
This is the main engine for walking the dependency graph and
|
||||
calling things to decide what does or doesn't need to be built.
|
||||
|
||||
Task
|
||||
This is the base class for allowing a wrapping interface to
|
||||
decide what does or doesn't actually need to be done. The
|
||||
intention is for a wrapping interface to subclass this as
|
||||
appropriate for different types of behavior it may need.
|
||||
|
||||
The canonical example is the SCons native Python interface,
|
||||
which has Task subclasses that handle its specific behavior,
|
||||
like printing "`foo' is up to date" when a top-level target
|
||||
doesn't need to be built, and handling the -c option by removing
|
||||
targets as its "build" action. There is also a separate subclass
|
||||
for suppressing this output when the -q option is used.
|
||||
|
||||
The Taskmaster instantiates a Task object for each (set of)
|
||||
target(s) that it decides need to be evaluated and/or built.
|
||||
"""
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Taskmaster.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import SCons.compat
|
||||
|
||||
import operator
|
||||
import string
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
import SCons.Node
|
||||
import SCons.Errors
|
||||
|
||||
StateString = SCons.Node.StateString
|
||||
|
||||
|
||||
|
||||
# A subsystem for recording stats about how different Nodes are handled by
|
||||
# the main Taskmaster loop. There's no external control here (no need for
|
||||
# a --debug= option); enable it by changing the value of CollectStats.
|
||||
|
||||
CollectStats = None
|
||||
|
||||
class Stats:
|
||||
"""
|
||||
A simple class for holding statistics about the disposition of a
|
||||
Node by the Taskmaster. If we're collecting statistics, each Node
|
||||
processed by the Taskmaster gets one of these attached, in which case
|
||||
the Taskmaster records its decision each time it processes the Node.
|
||||
(Ideally, that's just once per Node.)
|
||||
"""
|
||||
def __init__(self):
|
||||
"""
|
||||
Instantiates a Taskmaster.Stats object, initializing all
|
||||
appropriate counters to zero.
|
||||
"""
|
||||
self.considered = 0
|
||||
self.already_handled = 0
|
||||
self.problem = 0
|
||||
self.child_failed = 0
|
||||
self.not_built = 0
|
||||
self.side_effects = 0
|
||||
self.build = 0
|
||||
|
||||
StatsNodes = []
|
||||
|
||||
fmt = "%(considered)3d "\
|
||||
"%(already_handled)3d " \
|
||||
"%(problem)3d " \
|
||||
"%(child_failed)3d " \
|
||||
"%(not_built)3d " \
|
||||
"%(side_effects)3d " \
|
||||
"%(build)3d "
|
||||
|
||||
def dump_stats():
|
||||
StatsNodes.sort(lambda a, b: cmp(str(a), str(b)))
|
||||
for n in StatsNodes:
|
||||
print (fmt % n.stats.__dict__) + str(n)
|
||||
|
||||
|
||||
|
||||
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
|
||||
self.exc_clear()
|
||||
|
||||
def display(self, message):
|
||||
"""
|
||||
Hook to allow the calling interface to display a message.
|
||||
|
||||
This hook gets called as part of preparing a task for execution
|
||||
(that is, a Node to be built). As part of figuring out what Node
|
||||
should be built next, the actually target list may be altered,
|
||||
along with a message describing the alteration. The calling
|
||||
interface can subclass Task and provide a concrete implementation
|
||||
of this method to see those messages.
|
||||
"""
|
||||
pass
|
||||
|
||||
def prepare(self):
|
||||
"""
|
||||
Called just before the task is executed.
|
||||
|
||||
This is mainly intended to give the target Nodes a chance to
|
||||
unlink underlying files and make all necessary directories before
|
||||
the Action is actually called to build the targets.
|
||||
"""
|
||||
|
||||
# Now that it's the appropriate time, give the TaskMaster a
|
||||
# chance to raise any exceptions it encountered while preparing
|
||||
# this task.
|
||||
self.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 get_target(self):
|
||||
"""Fetch the target being built or updated by this task.
|
||||
"""
|
||||
return self.node
|
||||
|
||||
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:
|
||||
raise SCons.Errors.TaskmasterException(self.targets[0],
|
||||
sys.exc_info())
|
||||
|
||||
def executed(self):
|
||||
"""
|
||||
Called when the task has been successfully executed.
|
||||
|
||||
This may have been a do-nothing operation (to preserve build
|
||||
order), so we have to check the node's state before deciding
|
||||
whether it was "built" or just "visited."
|
||||
"""
|
||||
for t in self.targets:
|
||||
if t.get_state() == SCons.Node.executing:
|
||||
t.set_state(SCons.Node.executed)
|
||||
t.built()
|
||||
else:
|
||||
t.visited()
|
||||
|
||||
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.stop()
|
||||
|
||||
# We're stopping because of a build failure, but give the
|
||||
# calling Task class a chance to postprocess() the top-level
|
||||
# target under which the build failure occurred.
|
||||
self.targets = [self.tm.current_top]
|
||||
self.top = 1
|
||||
|
||||
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)
|
||||
|
||||
def make_ready_all(self):
|
||||
"""
|
||||
Marks 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[:]
|
||||
for t in self.targets:
|
||||
t.disambiguate().set_state(SCons.Node.executing)
|
||||
for s in t.side_effects:
|
||||
s.set_state(SCons.Node.executing)
|
||||
|
||||
def make_ready_current(self):
|
||||
"""
|
||||
Marks 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:
|
||||
try:
|
||||
is_up_to_date = t.disambiguate().current()
|
||||
except EnvironmentError, e:
|
||||
raise SCons.Errors.BuildError(node=t, errstr=e.strerror, filename=e.filename)
|
||||
if is_up_to_date:
|
||||
t.set_state(SCons.Node.up_to_date)
|
||||
else:
|
||||
self.out_of_date.append(t)
|
||||
t.set_state(SCons.Node.executing)
|
||||
for s in t.side_effects:
|
||||
s.set_state(SCons.Node.executing)
|
||||
|
||||
make_ready = make_ready_current
|
||||
|
||||
def postprocess(self):
|
||||
"""
|
||||
Post-processes a task after it's been executed.
|
||||
|
||||
This examines all the targets just built (or not, we don't care
|
||||
if the build was successful, or even if there was no build
|
||||
because everything was up-to-date) to see if they have any
|
||||
waiting parent Nodes, or Nodes waiting on a common side effect,
|
||||
that can be put back on the candidates list.
|
||||
"""
|
||||
|
||||
# We may have built multiple targets, some of which may have
|
||||
# common parents waiting for this build. Count up how many
|
||||
# targets each parent was waiting for so we can subtract the
|
||||
# values later, and so we *don't* put waiting side-effect Nodes
|
||||
# back on the candidates list if the Node is also a waiting
|
||||
# parent.
|
||||
|
||||
parents = {}
|
||||
for t in self.targets:
|
||||
for p in t.waiting_parents.keys():
|
||||
parents[p] = parents.get(p, 0) + 1
|
||||
|
||||
for t in self.targets:
|
||||
for s in t.side_effects:
|
||||
if s.get_state() == SCons.Node.executing:
|
||||
s.set_state(SCons.Node.no_state)
|
||||
for p in s.waiting_parents.keys():
|
||||
if not parents.has_key(p):
|
||||
parents[p] = 1
|
||||
for p in s.waiting_s_e.keys():
|
||||
if p.ref_count == 0:
|
||||
self.tm.candidates.append(p)
|
||||
|
||||
for p, subtract in parents.items():
|
||||
p.ref_count = p.ref_count - subtract
|
||||
if p.ref_count == 0:
|
||||
self.tm.candidates.append(p)
|
||||
|
||||
for t in self.targets:
|
||||
t.postprocess()
|
||||
|
||||
# Exception handling subsystem.
|
||||
#
|
||||
# Exceptions that occur while walking the DAG or examining Nodes
|
||||
# must be raised, but must be raised at an appropriate time and in
|
||||
# a controlled manner so we can, if necessary, recover gracefully,
|
||||
# possibly write out signature information for Nodes we've updated,
|
||||
# etc. This is done by having the Taskmaster tell us about the
|
||||
# exception, and letting
|
||||
|
||||
def exc_info(self):
|
||||
"""
|
||||
Returns info about a recorded exception.
|
||||
"""
|
||||
return self.exception
|
||||
|
||||
def exc_clear(self):
|
||||
"""
|
||||
Clears any recorded exception.
|
||||
|
||||
This also changes the "exception_raise" attribute to point
|
||||
to the appropriate do-nothing method.
|
||||
"""
|
||||
self.exception = (None, None, None)
|
||||
self.exception_raise = self._no_exception_to_raise
|
||||
|
||||
def exception_set(self, exception=None):
|
||||
"""
|
||||
Records an exception to be raised at the appropriate time.
|
||||
|
||||
This also changes the "exception_raise" attribute to point
|
||||
to the method that will, in fact
|
||||
"""
|
||||
if not exception:
|
||||
exception = sys.exc_info()
|
||||
self.exception = exception
|
||||
self.exception_raise = self._exception_raise
|
||||
|
||||
def _no_exception_to_raise(self):
|
||||
pass
|
||||
|
||||
def _exception_raise(self):
|
||||
"""
|
||||
Raises a pending exception that was recorded while getting a
|
||||
Task ready for execution.
|
||||
"""
|
||||
exc = self.exc_info()[:]
|
||||
try:
|
||||
exc_type, exc_value, exc_traceback = exc
|
||||
except ValueError:
|
||||
exc_type, exc_value = exc
|
||||
exc_traceback = None
|
||||
raise exc_type, exc_value, exc_traceback
|
||||
|
||||
|
||||
def find_cycle(stack):
|
||||
if stack[0] == stack[-1]:
|
||||
return stack
|
||||
for n in stack[-1].waiting_parents.keys():
|
||||
stack.append(n)
|
||||
if find_cycle(stack):
|
||||
return stack
|
||||
stack.pop()
|
||||
return None
|
||||
|
||||
|
||||
class Taskmaster:
|
||||
"""
|
||||
The Taskmaster for walking the dependency DAG.
|
||||
"""
|
||||
|
||||
def __init__(self, targets=[], tasker=Task, order=None, trace=None):
|
||||
self.top_targets = targets[:]
|
||||
self.top_targets.reverse()
|
||||
self.candidates = []
|
||||
self.tasker = tasker
|
||||
if not order:
|
||||
order = lambda l: l
|
||||
self.order = order
|
||||
self.message = None
|
||||
self.trace = trace
|
||||
self.next_candidate = self.find_next_candidate
|
||||
|
||||
def find_next_candidate(self):
|
||||
"""
|
||||
Returns the next candidate Node for (potential) evaluation.
|
||||
|
||||
The candidate list (really a stack) initially consists of all of
|
||||
the top-level (command line) targets provided when the Taskmaster
|
||||
was initialized. While we walk the DAG, visiting Nodes, all the
|
||||
children that haven't finished processing get pushed on to the
|
||||
candidate list. Each child can then be popped and examined in
|
||||
turn for whether *their* children are all up-to-date, in which
|
||||
case a Task will be created for their actual evaluation and
|
||||
potential building.
|
||||
|
||||
Here is where we also allow candidate Nodes to alter the list of
|
||||
Nodes that should be examined. This is used, for example, when
|
||||
invoking SCons in a source directory. A source directory Node can
|
||||
return its corresponding build directory Node, essentially saying,
|
||||
"Hey, you really need to build this thing over here instead."
|
||||
"""
|
||||
try:
|
||||
return self.candidates.pop()
|
||||
except IndexError:
|
||||
pass
|
||||
try:
|
||||
node = self.top_targets.pop()
|
||||
except IndexError:
|
||||
return None
|
||||
self.current_top = node
|
||||
alt, message = node.alter_targets()
|
||||
if alt:
|
||||
self.message = message
|
||||
self.candidates.append(node)
|
||||
self.candidates.extend(self.order(alt))
|
||||
node = self.candidates.pop()
|
||||
return node
|
||||
|
||||
def no_next_candidate(self):
|
||||
"""
|
||||
Stops Taskmaster processing by not returning a next candidate.
|
||||
"""
|
||||
return None
|
||||
|
||||
def _find_next_ready_node(self):
|
||||
"""
|
||||
Finds the next node that is ready to be built.
|
||||
|
||||
This is *the* main guts of the DAG walk. We loop through the
|
||||
list of candidates, looking for something that has no un-built
|
||||
children (i.e., that is a leaf Node or has dependencies that are
|
||||
all leaf Nodes or up-to-date). Candidate Nodes are re-scanned
|
||||
(both the target Node itself and its sources, which are always
|
||||
scanned in the context of a given target) to discover implicit
|
||||
dependencies. A Node that must wait for some children to be
|
||||
built will be put back on the candidates list after the children
|
||||
have finished building. A Node that has been put back on the
|
||||
candidates list in this way may have itself (or its sources)
|
||||
re-scanned, in order to handle generated header files (e.g.) and
|
||||
the implicit dependencies therein.
|
||||
|
||||
Note that this method does not do any signature calculation or
|
||||
up-to-date check itself. All of that is handled by the Task
|
||||
class. This is purely concerned with the dependency graph walk.
|
||||
"""
|
||||
|
||||
self.ready_exc = None
|
||||
|
||||
T = self.trace
|
||||
|
||||
while 1:
|
||||
node = self.next_candidate()
|
||||
if node is None:
|
||||
return None
|
||||
|
||||
node = node.disambiguate()
|
||||
state = node.get_state()
|
||||
|
||||
if CollectStats:
|
||||
if not hasattr(node, 'stats'):
|
||||
node.stats = Stats()
|
||||
StatsNodes.append(node)
|
||||
S = node.stats
|
||||
S.considered = S.considered + 1
|
||||
else:
|
||||
S = None
|
||||
|
||||
if T: T.write('Taskmaster: %s:' % repr(str(node)))
|
||||
|
||||
# Skip this node if it has already been evaluated:
|
||||
if state > SCons.Node.pending:
|
||||
if S: S.already_handled = S.already_handled + 1
|
||||
if T: T.write(' already handled (%s)\n' % StateString[state])
|
||||
continue
|
||||
|
||||
# Mark this node as being on the execution stack:
|
||||
node.set_state(SCons.Node.pending)
|
||||
|
||||
try:
|
||||
children = node.children()
|
||||
except SystemExit:
|
||||
exc_value = sys.exc_info()[1]
|
||||
e = SCons.Errors.ExplicitExit(node, exc_value.code)
|
||||
self.ready_exc = (SCons.Errors.ExplicitExit, e)
|
||||
if T: T.write(' SystemExit\n')
|
||||
return node
|
||||
except KeyboardInterrupt:
|
||||
if T: T.write(' KeyboardInterrupt\n')
|
||||
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.ready_exc = sys.exc_info()
|
||||
if S: S.problem = S.problem + 1
|
||||
if T: T.write(' exception\n')
|
||||
return node
|
||||
|
||||
if T and children:
|
||||
c = map(str, children)
|
||||
c.sort()
|
||||
T.write(' children:\n %s\n ' % c)
|
||||
|
||||
childinfo = map(lambda N: (N.get_state(),
|
||||
N.is_derived() or N.is_pseudo_derived(),
|
||||
N), children)
|
||||
|
||||
# Skip this node if any of its children have failed. This
|
||||
# catches the case where we're descending a top-level target
|
||||
# and one of our children failed while trying to be built
|
||||
# by a *previous* descent of an earlier top-level target.
|
||||
failed_children = filter(lambda I: I[0] == SCons.Node.failed,
|
||||
childinfo)
|
||||
if failed_children:
|
||||
node.set_state(SCons.Node.failed)
|
||||
if S: S.child_failed = S.child_failed + 1
|
||||
if T:
|
||||
c = map(str, failed_children)
|
||||
c.sort()
|
||||
T.write(' children failed:\n %s\n' % c)
|
||||
continue
|
||||
|
||||
# Detect dependency cycles:
|
||||
pending_nodes = filter(lambda I: I[0] == SCons.Node.pending, childinfo)
|
||||
if pending_nodes:
|
||||
for p in pending_nodes:
|
||||
cycle = find_cycle([p[2], node])
|
||||
if cycle:
|
||||
desc = "Dependency cycle: " + string.join(map(str, cycle), " -> ")
|
||||
if T: T.write(' dependency cycle\n')
|
||||
raise SCons.Errors.UserError, desc
|
||||
|
||||
# Select all of the dependencies that are derived targets
|
||||
# (that is, children who have builders or are side effects).
|
||||
derived_children = filter(lambda I: I[1], childinfo)
|
||||
|
||||
not_started = filter(lambda I: not I[0], derived_children)
|
||||
if not_started:
|
||||
not_started = map(lambda I: I[2], not_started)
|
||||
|
||||
# We're waiting on one more derived targets that have
|
||||
# not yet started building. Add this node to the
|
||||
# waiting_parents lists of those derived files so that
|
||||
# when they've finished building, our implicit dependency
|
||||
# list will get cleared and we'll re-scan the newly-built
|
||||
# file(s) for updated implicit dependencies.
|
||||
added = map(lambda n, P=node: n.add_to_waiting_parents(P), not_started)
|
||||
node.ref_count = node.ref_count + reduce(operator.add, added, 0)
|
||||
|
||||
# Now we add these derived targets to the candidates
|
||||
# list so they can be examined and built. We have to
|
||||
# add ourselves back to the list first, though, so we get
|
||||
# a chance to re-scan and build after the dependencies.
|
||||
#
|
||||
# We reverse the order in which the children are added
|
||||
# to the candidates stack so the order in which they're
|
||||
# popped matches the order in which they show up in our
|
||||
# children's list. This is more logical / efficient for
|
||||
# builders with multiple targets, since the "primary"
|
||||
# target will be examined first.
|
||||
self.candidates.append(node)
|
||||
not_started.reverse()
|
||||
self.candidates.extend(self.order(not_started))
|
||||
|
||||
if S: S.not_started = S.not_started + 1
|
||||
if T:
|
||||
c = map(str, not_started)
|
||||
c.sort()
|
||||
T.write(' waiting on unstarted children:\n %s\n' % c)
|
||||
continue
|
||||
|
||||
not_built = filter(lambda I: I[0] <= SCons.Node.executing, derived_children)
|
||||
if not_built:
|
||||
not_built = map(lambda I: I[2], not_built)
|
||||
|
||||
# We're waiting on one or more derived targets that have
|
||||
# started building but not yet finished. Add this node
|
||||
# to the waiting parents lists of those derived files
|
||||
# so that when they've finished building, our implicit
|
||||
# dependency list will get cleared and we'll re-scan the
|
||||
# newly-built file(s) for updated implicit dependencies.
|
||||
added = map(lambda n, P=node: n.add_to_waiting_parents(P), not_built)
|
||||
node.ref_count = node.ref_count + reduce(operator.add, added, 0)
|
||||
|
||||
if S: S.not_built = S.not_built + 1
|
||||
if T:
|
||||
c = map(str, not_built)
|
||||
c.sort()
|
||||
T.write(' waiting on unfinished children:\n %s\n' % c)
|
||||
continue
|
||||
|
||||
# Skip this node if it has side-effects that are currently being
|
||||
# built themselves or waiting for something else being built.
|
||||
side_effects = filter(lambda N:
|
||||
N.get_state() == SCons.Node.executing,
|
||||
node.side_effects)
|
||||
if side_effects:
|
||||
map(lambda n, P=node: n.add_to_waiting_s_e(P), side_effects)
|
||||
if S: S.side_effects = S.side_effects + 1
|
||||
if T:
|
||||
c = map(str, side_effects)
|
||||
c.sort()
|
||||
T.write(' waiting on side effects:\n %s\n' % c)
|
||||
continue
|
||||
|
||||
# The default when we've gotten through all of the checks above:
|
||||
# this node is ready to be built.
|
||||
if S: S.build = S.build + 1
|
||||
if T: T.write(' evaluating %s\n' % node)
|
||||
return node
|
||||
|
||||
return None
|
||||
|
||||
def next_task(self):
|
||||
"""
|
||||
Returns the next task to be executed.
|
||||
|
||||
This simply asks for the next Node to be evaluated, and then wraps
|
||||
it in the specific Task subclass with which we were initialized.
|
||||
"""
|
||||
node = self._find_next_ready_node()
|
||||
|
||||
if node is None:
|
||||
return None
|
||||
|
||||
tlist = node.get_executor().targets
|
||||
|
||||
task = self.tasker(self, tlist, node is self.current_top, node)
|
||||
try:
|
||||
task.make_ready()
|
||||
except KeyboardInterrupt:
|
||||
raise
|
||||
except:
|
||||
# We had a problem just trying to get this task ready (like
|
||||
# a child couldn't be linked in to a BuildDir when deciding
|
||||
# whether this node is current). Arrange to raise the
|
||||
# exception when the Task is "executed."
|
||||
self.ready_exc = sys.exc_info()
|
||||
|
||||
if self.ready_exc:
|
||||
task.exception_set(self.ready_exc)
|
||||
|
||||
self.ready_exc = None
|
||||
|
||||
return task
|
||||
|
||||
def stop(self):
|
||||
"""
|
||||
Stops the current build completely.
|
||||
"""
|
||||
self.next_candidate = self.no_next_candidate
|
|
@ -10,7 +10,7 @@ selection method.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -32,21 +32,22 @@ selection method.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/386asm.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/386asm.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
from SCons.Tool.PharLapCommon import addPharLapPaths
|
||||
import SCons.Util
|
||||
|
||||
import as
|
||||
as_module = __import__('as', globals(), locals(), [])
|
||||
|
||||
def generate(env):
|
||||
"""Add Builders and construction variables for ar to an Environment."""
|
||||
as.generate(env)
|
||||
as_module.generate(env)
|
||||
|
||||
env['AS'] = '386asm'
|
||||
env['ASFLAGS'] = SCons.Util.CLVar('')
|
||||
env['ASPPFLAGS'] = '$ASFLAGS'
|
||||
env['ASCOM'] = '$AS $ASFLAGS $SOURCES -o $TARGET'
|
||||
env['ASPPCOM'] = '$CC $ASFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS $SOURCES -o $TARGET'
|
||||
env['ASPPCOM'] = '$CC $ASPPFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS $SOURCES -o $TARGET'
|
||||
|
||||
addPharLapPaths(env)
|
||||
|
|
@ -10,7 +10,7 @@ selection method.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -32,10 +32,9 @@ selection method.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/BitKeeper.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
|
||||
import os.path
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/BitKeeper.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import SCons.Action
|
||||
import SCons.Builder
|
||||
import SCons.Util
|
||||
|
||||
|
@ -45,7 +44,8 @@ def generate(env):
|
|||
|
||||
def BitKeeperFactory(env=env):
|
||||
""" """
|
||||
return SCons.Builder.Builder(action = "$BITKEEPERCOM", env = env)
|
||||
act = SCons.Action.Action("$BITKEEPERCOM", "$BITKEEPERCOMSTR")
|
||||
return SCons.Builder.Builder(action = act, env = env)
|
||||
|
||||
#setattr(env, 'BitKeeper', BitKeeperFactory)
|
||||
env.BitKeeper = BitKeeperFactory
|
|
@ -9,7 +9,7 @@ selection method.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -31,8 +31,9 @@ selection method.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/CVS.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/CVS.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import SCons.Action
|
||||
import SCons.Builder
|
||||
import SCons.Util
|
||||
|
||||
|
@ -48,7 +49,8 @@ def generate(env):
|
|||
# be across a network and must use POSIX slashes as separators.
|
||||
module = module + '/'
|
||||
env['CVSCOM'] = '$CVS $CVSFLAGS co $CVSCOFLAGS -d ${TARGET.dir} $CVSMODULE${TARGET.posix}'
|
||||
return SCons.Builder.Builder(action = '$CVSCOM',
|
||||
act = SCons.Action.Action('$CVSCOM', '$CVSCOMSTR')
|
||||
return SCons.Builder.Builder(action = act,
|
||||
env = env,
|
||||
CVSREPOSITORY = repos,
|
||||
CVSMODULE = module)
|
|
@ -5,7 +5,7 @@ Stuff for processing Java.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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 @@ Stuff for processing Java.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/JavaCommon.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/JavaCommon.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import os
|
||||
import os.path
|
||||
|
@ -42,13 +42,19 @@ if java_parsing:
|
|||
# This is a really cool parser from Charles Crain
|
||||
# that finds appropriate class names in Java source.
|
||||
|
||||
# A regular expression that will find, in a java file: newlines;
|
||||
# any alphanumeric token (keyword, class name, specifier); open or
|
||||
# close brackets; a single-line comment "//"; the multi-line comment
|
||||
# begin and end tokens /* and */; single or double quotes; and
|
||||
# single or double quotes preceeded by a backslash.
|
||||
_reToken = re.compile(r'(\n|//|\\[\'"]|[\'"\{\}]|[A-Za-z_][\w\.]*|' +
|
||||
r'/\*|\*/)')
|
||||
# A regular expression that will find, in a java file:
|
||||
# newlines;
|
||||
# double-backslashes;
|
||||
# a single-line comment "//";
|
||||
# single or double quotes preceeded by a backslash;
|
||||
# single quotes, double quotes, open or close braces, semi-colons;
|
||||
# any alphanumeric token (keyword, class name, specifier);
|
||||
# the multi-line comment begin and end tokens /* and */;
|
||||
# array declarations "[]";
|
||||
# semi-colons;
|
||||
# periods.
|
||||
_reToken = re.compile(r'(\n|\\\\|//|\\[\'"]|[\'"\{\}\;\.]|' +
|
||||
r'[A-Za-z_][\w\.]*|/\*|\*/|\[\])')
|
||||
|
||||
class OuterState:
|
||||
"""The initial state for parsing a Java file for classes,
|
||||
|
@ -61,6 +67,9 @@ if java_parsing:
|
|||
self.nextAnon = 1
|
||||
self.package = None
|
||||
|
||||
def trace(self):
|
||||
pass
|
||||
|
||||
def __getClassState(self):
|
||||
try:
|
||||
return self.classState
|
||||
|
@ -93,41 +102,51 @@ if java_parsing:
|
|||
self.skipState = ret
|
||||
return ret
|
||||
|
||||
def parseToken(self, token):
|
||||
if token[:2] == '//':
|
||||
return IgnoreState('\n', self)
|
||||
elif token == '/*':
|
||||
return IgnoreState('*/', self)
|
||||
elif token == '{':
|
||||
def openBracket(self):
|
||||
self.brackets = self.brackets + 1
|
||||
elif token == '}':
|
||||
|
||||
def closeBracket(self):
|
||||
self.brackets = self.brackets - 1
|
||||
if len(self.stackBrackets) and \
|
||||
self.brackets == self.stackBrackets[-1]:
|
||||
self.listOutputs.append(string.join(self.listClasses, '$'))
|
||||
self.listClasses.pop()
|
||||
self.stackBrackets.pop()
|
||||
elif token == '"' or token == "'":
|
||||
|
||||
def parseToken(self, token):
|
||||
if token[:2] == '//':
|
||||
return IgnoreState('\n', self)
|
||||
elif token == '/*':
|
||||
return IgnoreState('*/', self)
|
||||
elif token == '{':
|
||||
self.openBracket()
|
||||
elif token == '}':
|
||||
self.closeBracket()
|
||||
elif token in [ '"', "'" ]:
|
||||
return IgnoreState(token, self)
|
||||
elif token == "new":
|
||||
# anonymous inner class
|
||||
if len(self.listClasses) > 0:
|
||||
return self.__getAnonClassState()
|
||||
return self.__getSkipState() # Skip the class name
|
||||
elif token == 'class' or token == 'interface':
|
||||
elif token in ['class', 'interface', 'enum']:
|
||||
if len(self.listClasses) == 0:
|
||||
self.nextAnon = 1
|
||||
self.stackBrackets.append(self.brackets)
|
||||
return self.__getClassState()
|
||||
elif token == 'package':
|
||||
return self.__getPackageState()
|
||||
elif token == '.':
|
||||
# Skip the attribute, it might be named "class", in which
|
||||
# case we don't want to treat the following token as
|
||||
# an inner class name...
|
||||
return self.__getSkipState()
|
||||
return self
|
||||
|
||||
def addAnonClass(self):
|
||||
"""Add an anonymous inner class"""
|
||||
clazz = self.listClasses[0]
|
||||
self.listOutputs.append('%s$%d' % (clazz, self.nextAnon))
|
||||
self.brackets = self.brackets + 1
|
||||
self.nextAnon = self.nextAnon + 1
|
||||
|
||||
def setPackage(self, package):
|
||||
|
@ -140,9 +159,17 @@ if java_parsing:
|
|||
self.outer_state = outer_state
|
||||
self.tokens_to_find = 2
|
||||
def parseToken(self, token):
|
||||
# This is an anonymous class if and only if the next token is a bracket
|
||||
# This is an anonymous class if and only if the next
|
||||
# non-whitespace token is a bracket
|
||||
if token == '\n':
|
||||
return self
|
||||
if token == '{':
|
||||
self.outer_state.openBracket()
|
||||
self.outer_state.addAnonClass()
|
||||
elif token == '}':
|
||||
self.outer_state.closeBracket()
|
||||
elif token in ['"', "'"]:
|
||||
return IgnoreState(token, self)
|
||||
return self.outer_state
|
||||
|
||||
class SkipState:
|
||||
|
@ -193,7 +220,7 @@ if java_parsing:
|
|||
def parse_java_file(fn):
|
||||
return parse_java(open(fn, 'r').read())
|
||||
|
||||
def parse_java(contents):
|
||||
def parse_java(contents, trace=None):
|
||||
"""Parse a .java file and return a double of package directory,
|
||||
plus a list of .class files that compiling that .java file will
|
||||
produce"""
|
||||
|
@ -204,6 +231,7 @@ if java_parsing:
|
|||
# The regex produces a bunch of groups, but only one will
|
||||
# have anything in it.
|
||||
currstate = currstate.parseToken(token)
|
||||
if trace: trace(token, currstate)
|
||||
if initial.package:
|
||||
package = string.replace(initial.package, '.', os.sep)
|
||||
return (package, initial.listOutputs)
|
|
@ -9,7 +9,7 @@ selection method.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -31,10 +31,11 @@ selection method.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/Perforce.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/Perforce.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import os
|
||||
|
||||
import SCons.Action
|
||||
import SCons.Builder
|
||||
import SCons.Node.FS
|
||||
import SCons.Util
|
||||
|
@ -42,18 +43,21 @@ import SCons.Util
|
|||
# This function should maybe be moved to SCons.Util?
|
||||
from SCons.Tool.PharLapCommon import addPathIfNotExists
|
||||
|
||||
|
||||
|
||||
# Variables that we want to import from the base OS environment.
|
||||
_import_env = [ 'P4PORT', 'P4CLIENT', 'P4USER', 'USER', 'USERNAME', 'P4PASSWD',
|
||||
'P4CHARSET', 'P4LANGUAGE', 'SYSTEMROOT' ]
|
||||
|
||||
PerforceAction = SCons.Action.Action('$P4COM', '$P4COMSTR')
|
||||
|
||||
def generate(env):
|
||||
"""Add a Builder factory function and construction variables for
|
||||
Perforce to an Environment."""
|
||||
|
||||
def PerforceFactory(env=env):
|
||||
""" """
|
||||
return SCons.Builder.Builder(action = '$P4COM',
|
||||
env = env)
|
||||
return SCons.Builder.Builder(action = PerforceAction, env = env)
|
||||
|
||||
#setattr(env, 'Perforce', PerforceFactory)
|
||||
env.Perforce = PerforceFactory
|
||||
|
@ -70,8 +74,8 @@ def generate(env):
|
|||
# Perforce seems to use the PWD environment variable rather than
|
||||
# calling getcwd() for itself, which is odd. If no PWD variable
|
||||
# is present, p4 WILL call getcwd, but this seems to cause problems
|
||||
# with good ol' Win32's tilde-mangling for long file names.
|
||||
environ['PWD'] = SCons.Node.FS.default_fs.Dir('#').get_abspath()
|
||||
# with good ol' Windows's tilde-mangling for long file names.
|
||||
environ['PWD'] = env.Dir('#').get_abspath()
|
||||
|
||||
for var in _import_env:
|
||||
v = os.environ.get(var)
|
|
@ -7,7 +7,7 @@ Phar Lap ETS tool chain. Right now, this is linkloc and
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -29,7 +29,7 @@ Phar Lap ETS tool chain. Right now, this is linkloc and
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/PharLapCommon.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/PharLapCommon.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import os
|
||||
import os.path
|
|
@ -9,7 +9,7 @@ selection method.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -31,8 +31,9 @@ selection method.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/RCS.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/RCS.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import SCons.Action
|
||||
import SCons.Builder
|
||||
import SCons.Util
|
||||
|
||||
|
@ -42,7 +43,8 @@ def generate(env):
|
|||
|
||||
def RCSFactory(env=env):
|
||||
""" """
|
||||
return SCons.Builder.Builder(action = '$RCS_COCOM', env = env)
|
||||
act = SCons.Action.Action('$RCS_COCOM', '$RCS_COCOMSTR')
|
||||
return SCons.Builder.Builder(action = act, env = env)
|
||||
|
||||
#setattr(env, 'RCS', RCSFactory)
|
||||
env.RCS = RCSFactory
|
|
@ -9,7 +9,7 @@ selection method.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -31,8 +31,9 @@ selection method.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/SCCS.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/SCCS.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import SCons.Action
|
||||
import SCons.Builder
|
||||
import SCons.Util
|
||||
|
||||
|
@ -42,7 +43,8 @@ def generate(env):
|
|||
|
||||
def SCCSFactory(env=env):
|
||||
""" """
|
||||
return SCons.Builder.Builder(action = '$SCCSCOM', env = env)
|
||||
act = SCons.Action.Action('$SCCSCOM', '$SCCSCOMSTR')
|
||||
return SCons.Builder.Builder(action = act, env = env)
|
||||
|
||||
#setattr(env, 'SCCS', SCCSFactory)
|
||||
env.SCCS = SCCSFactory
|
|
@ -9,7 +9,7 @@ selection method.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -31,10 +31,11 @@ selection method.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/Subversion.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/Subversion.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import os.path
|
||||
|
||||
import SCons.Action
|
||||
import SCons.Builder
|
||||
import SCons.Util
|
||||
|
||||
|
@ -47,7 +48,8 @@ def generate(env):
|
|||
# fail if repos is not an absolute path name?
|
||||
if module != '':
|
||||
module = os.path.join(module, '')
|
||||
return SCons.Builder.Builder(action = '$SVNCOM',
|
||||
act = SCons.Action.Action('$SVNCOM', '$SVNCOMSTR')
|
||||
return SCons.Builder.Builder(action = act,
|
||||
env = env,
|
||||
SVNREPOSITORY = repos,
|
||||
SVNMODULE = module)
|
|
@ -14,7 +14,7 @@ tool definition.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -36,58 +36,129 @@ tool definition.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/__init__.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/__init__.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import imp
|
||||
import sys
|
||||
|
||||
import SCons.Builder
|
||||
import SCons.Errors
|
||||
import SCons.Defaults
|
||||
import SCons.Scanner
|
||||
import SCons.Scanner.C
|
||||
import SCons.Scanner.D
|
||||
import SCons.Scanner.LaTeX
|
||||
import SCons.Scanner.Prog
|
||||
|
||||
class ToolSpec:
|
||||
def __init__(self, name):
|
||||
DefaultToolpath=[]
|
||||
|
||||
CScanner = SCons.Scanner.C.CScanner()
|
||||
DScanner = SCons.Scanner.D.DScanner()
|
||||
LaTeXScanner = SCons.Scanner.LaTeX.LaTeXScanner()
|
||||
ProgramScanner = SCons.Scanner.Prog.ProgramScanner()
|
||||
SourceFileScanner = SCons.Scanner.Base({}, name='SourceFileScanner')
|
||||
|
||||
CSuffixes = [".c", ".C", ".cxx", ".cpp", ".c++", ".cc",
|
||||
".h", ".H", ".hxx", ".hpp", ".hh",
|
||||
".F", ".fpp", ".FPP",
|
||||
".m", ".mm",
|
||||
".S", ".spp", ".SPP"]
|
||||
|
||||
DSuffixes = ['.d']
|
||||
|
||||
IDLSuffixes = [".idl", ".IDL"]
|
||||
|
||||
LaTeXSuffixes = [".tex", ".ltx", ".latex"]
|
||||
|
||||
for suffix in CSuffixes:
|
||||
SourceFileScanner.add_scanner(suffix, CScanner)
|
||||
|
||||
for suffix in DSuffixes:
|
||||
SourceFileScanner.add_scanner(suffix, DScanner)
|
||||
|
||||
for suffix in LaTeXSuffixes:
|
||||
SourceFileScanner.add_scanner(suffix, LaTeXScanner)
|
||||
|
||||
class Tool:
|
||||
def __init__(self, name, toolpath=[], **kw):
|
||||
self.name = name
|
||||
self.toolpath = toolpath + DefaultToolpath
|
||||
# remember these so we can merge them into the call
|
||||
self.init_kw = kw
|
||||
|
||||
module = self._tool_module()
|
||||
self.generate = module.generate
|
||||
self.exists = module.exists
|
||||
|
||||
def _tool_module(self):
|
||||
oldpythonpath = sys.path
|
||||
sys.path = self.toolpath + sys.path
|
||||
|
||||
try:
|
||||
try:
|
||||
file, path, desc = imp.find_module(self.name, self.toolpath)
|
||||
try:
|
||||
return imp.load_module(self.name, file, path, desc)
|
||||
finally:
|
||||
if file:
|
||||
file.close()
|
||||
except ImportError, e:
|
||||
try:
|
||||
import zipimport
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
for aPath in self.toolpath:
|
||||
try:
|
||||
importer = zipimport.zipimporter(aPath)
|
||||
return importer.load_module(self.name)
|
||||
except ImportError, e:
|
||||
pass
|
||||
finally:
|
||||
sys.path = oldpythonpath
|
||||
|
||||
full_name = 'SCons.Tool.' + self.name
|
||||
try:
|
||||
return sys.modules[full_name]
|
||||
except KeyError:
|
||||
try:
|
||||
smpath = sys.modules['SCons.Tool'].__path__
|
||||
try:
|
||||
file, path, desc = imp.find_module(self.name, smpath)
|
||||
module = imp.load_module(full_name, file, path, desc)
|
||||
setattr(SCons.Tool, self.name, module)
|
||||
if file:
|
||||
file.close()
|
||||
return module
|
||||
except ImportError, e:
|
||||
try:
|
||||
import zipimport
|
||||
importer = zipimport.zipimporter( sys.modules['SCons.Tool'].__path__[0] )
|
||||
module = importer.load_module(full_name)
|
||||
setattr(SCons.Tool, self.name, module)
|
||||
return module
|
||||
except ImportError, e:
|
||||
m = "No tool named '%s': %s" % (self.name, e)
|
||||
raise SCons.Errors.UserError, m
|
||||
except ImportError, e:
|
||||
m = "No tool named '%s': %s" % (self.name, e)
|
||||
raise SCons.Errors.UserError, m
|
||||
|
||||
def __call__(self, env, *args, **kw):
|
||||
if self.init_kw is not None:
|
||||
# Merge call kws into init kws;
|
||||
# but don't bash self.init_kw.
|
||||
if kw is not None:
|
||||
call_kw = kw
|
||||
kw = self.init_kw.copy()
|
||||
kw.update(call_kw)
|
||||
else:
|
||||
kw = self.init_kw
|
||||
env.Append(TOOLS = [ self.name ])
|
||||
apply(self.generate, ( env, ) + args, kw)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def Tool(name, toolpath=[]):
|
||||
"Select a canned Tool specification, optionally searching in toolpath."
|
||||
|
||||
try:
|
||||
file, path, desc = imp.find_module(name, toolpath)
|
||||
try:
|
||||
module = imp.load_module(name, file, path, desc)
|
||||
spec = ToolSpec(name)
|
||||
spec.generate = module.generate
|
||||
spec.exists = module.exists
|
||||
return spec
|
||||
finally:
|
||||
if file:
|
||||
file.close()
|
||||
except ImportError, e:
|
||||
pass
|
||||
|
||||
full_name = 'SCons.Tool.' + name
|
||||
if not sys.modules.has_key(full_name):
|
||||
try:
|
||||
file, path, desc = imp.find_module(name,
|
||||
sys.modules['SCons.Tool'].__path__)
|
||||
mod = imp.load_module(full_name, file, path, desc)
|
||||
setattr(SCons.Tool, name, mod)
|
||||
except ImportError, e:
|
||||
raise SCons.Errors.UserError, "No tool named '%s': %s" % (name, e)
|
||||
if file:
|
||||
file.close()
|
||||
spec = ToolSpec(name)
|
||||
spec.generate = sys.modules[full_name].generate
|
||||
spec.exists = sys.modules[full_name].exists
|
||||
return spec
|
||||
|
||||
def createProgBuilder(env):
|
||||
"""This is a utility function that creates the Program
|
||||
Builder in an Environment if it is not there already.
|
||||
|
@ -98,13 +169,14 @@ def createProgBuilder(env):
|
|||
try:
|
||||
program = env['BUILDERS']['Program']
|
||||
except KeyError:
|
||||
import SCons.Defaults
|
||||
program = SCons.Builder.Builder(action = SCons.Defaults.LinkAction,
|
||||
emitter = '$PROGEMITTER',
|
||||
prefix = '$PROGPREFIX',
|
||||
suffix = '$PROGSUFFIX',
|
||||
src_suffix = '$OBJSUFFIX',
|
||||
src_builder = 'Object',
|
||||
target_scanner = SCons.Defaults.ProgScan)
|
||||
target_scanner = ProgramScanner)
|
||||
env['BUILDERS']['Program'] = program
|
||||
|
||||
return program
|
||||
|
@ -119,7 +191,12 @@ def createStaticLibBuilder(env):
|
|||
try:
|
||||
static_lib = env['BUILDERS']['StaticLibrary']
|
||||
except KeyError:
|
||||
static_lib = SCons.Builder.Builder(action = SCons.Defaults.ArAction,
|
||||
action_list = [ SCons.Action.Action("$ARCOM", "$ARCOMSTR") ]
|
||||
if env.Detect('ranlib'):
|
||||
ranlib_action = SCons.Action.Action("$RANLIBCOM", "$RANLIBCOMSTR")
|
||||
action_list.append(ranlib_action)
|
||||
|
||||
static_lib = SCons.Builder.Builder(action = action_list,
|
||||
emitter = '$LIBEMITTER',
|
||||
prefix = '$LIBPREFIX',
|
||||
suffix = '$LIBSUFFIX',
|
||||
|
@ -140,19 +217,44 @@ def createSharedLibBuilder(env):
|
|||
try:
|
||||
shared_lib = env['BUILDERS']['SharedLibrary']
|
||||
except KeyError:
|
||||
import SCons.Defaults
|
||||
action_list = [ SCons.Defaults.SharedCheck,
|
||||
SCons.Defaults.ShLinkAction ]
|
||||
shared_lib = SCons.Builder.Builder(action = action_list,
|
||||
emitter = "$SHLIBEMITTER",
|
||||
prefix = '$SHLIBPREFIX',
|
||||
suffix = '$SHLIBSUFFIX',
|
||||
target_scanner = SCons.Defaults.ProgScan,
|
||||
target_scanner = ProgramScanner,
|
||||
src_suffix = '$SHOBJSUFFIX',
|
||||
src_builder = 'SharedObject')
|
||||
env['BUILDERS']['SharedLibrary'] = shared_lib
|
||||
|
||||
return shared_lib
|
||||
|
||||
def createLoadableModuleBuilder(env):
|
||||
"""This is a utility function that creates the LoadableModule
|
||||
Builder in an Environment if it is not there already.
|
||||
|
||||
If it is already there, we return the existing one.
|
||||
"""
|
||||
|
||||
try:
|
||||
ld_module = env['BUILDERS']['LoadableModule']
|
||||
except KeyError:
|
||||
import SCons.Defaults
|
||||
action_list = [ SCons.Defaults.SharedCheck,
|
||||
SCons.Defaults.LdModuleLinkAction ]
|
||||
ld_module = SCons.Builder.Builder(action = action_list,
|
||||
emitter = "$SHLIBEMITTER",
|
||||
prefix = '$LDMODULEPREFIX',
|
||||
suffix = '$LDMODULESUFFIX',
|
||||
target_scanner = ProgramScanner,
|
||||
src_suffix = '$SHOBJSUFFIX',
|
||||
src_builder = 'SharedObject')
|
||||
env['BUILDERS']['LoadableModule'] = ld_module
|
||||
|
||||
return ld_module
|
||||
|
||||
def createObjBuilders(env):
|
||||
"""This is a utility function that creates the StaticObject
|
||||
and SharedObject Builders in an Environment if they
|
||||
|
@ -166,6 +268,7 @@ def createObjBuilders(env):
|
|||
The return is a 2-tuple of (StaticObject, SharedObject)
|
||||
"""
|
||||
|
||||
|
||||
try:
|
||||
static_obj = env['BUILDERS']['StaticObject']
|
||||
except KeyError:
|
||||
|
@ -174,7 +277,8 @@ def createObjBuilders(env):
|
|||
prefix = '$OBJPREFIX',
|
||||
suffix = '$OBJSUFFIX',
|
||||
src_builder = ['CFile', 'CXXFile'],
|
||||
source_scanner = SCons.Defaults.ObjSourceScan, single_source=1)
|
||||
source_scanner = SourceFileScanner,
|
||||
single_source = 1)
|
||||
env['BUILDERS']['StaticObject'] = static_obj
|
||||
env['BUILDERS']['Object'] = static_obj
|
||||
|
||||
|
@ -186,7 +290,8 @@ def createObjBuilders(env):
|
|||
prefix = '$SHOBJPREFIX',
|
||||
suffix = '$SHOBJSUFFIX',
|
||||
src_builder = ['CFile', 'CXXFile'],
|
||||
source_scanner = SCons.Defaults.ObjSourceScan, single_source=1)
|
||||
source_scanner = SourceFileScanner,
|
||||
single_source = 1)
|
||||
env['BUILDERS']['SharedObject'] = shared_obj
|
||||
|
||||
return (static_obj, shared_obj)
|
||||
|
@ -246,10 +351,10 @@ def tool_list(platform, env):
|
|||
if str(platform) == 'win32':
|
||||
"prefer Microsoft tools on Windows"
|
||||
linkers = ['mslink', 'gnulink', 'ilink', 'linkloc', 'ilink32' ]
|
||||
c_compilers = ['msvc', 'mingw', 'gcc', 'icl', 'icc', 'cc', 'bcc32' ]
|
||||
cxx_compilers = ['msvc', 'icc', 'g++', 'c++', 'bcc32' ]
|
||||
c_compilers = ['msvc', 'mingw', 'gcc', 'intelc', 'icl', 'icc', 'cc', 'bcc32' ]
|
||||
cxx_compilers = ['msvc', 'intelc', 'icc', 'g++', 'c++', 'bcc32' ]
|
||||
assemblers = ['masm', 'nasm', 'gas', '386asm' ]
|
||||
fortran_compilers = ['g77', 'ifl', 'cvf', 'fortran']
|
||||
fortran_compilers = ['g77', 'ifl', 'cvf', 'f95', 'f90', 'fortran']
|
||||
ars = ['mslib', 'ar', 'tlib']
|
||||
elif str(platform) == 'os2':
|
||||
"prefer IBM tools on OS/2"
|
||||
|
@ -265,7 +370,7 @@ def tool_list(platform, env):
|
|||
c_compilers = ['sgicc', 'gcc', 'cc']
|
||||
cxx_compilers = ['sgic++', 'g++', 'c++']
|
||||
assemblers = ['as', 'gas']
|
||||
fortran_compilers = ['f77', 'g77', 'fortran']
|
||||
fortran_compilers = ['f95', 'f90', 'f77', 'g77', 'fortran']
|
||||
ars = ['sgiar']
|
||||
elif str(platform) == 'sunos':
|
||||
"prefer Forte tools on SunOS"
|
||||
|
@ -273,7 +378,7 @@ def tool_list(platform, env):
|
|||
c_compilers = ['suncc', 'gcc', 'cc']
|
||||
cxx_compilers = ['sunc++', 'g++', 'c++']
|
||||
assemblers = ['as', 'gas']
|
||||
fortran_compilers = ['f77', 'g77', 'fortran']
|
||||
fortran_compilers = ['f95', 'f90', 'f77', 'g77', 'fortran']
|
||||
ars = ['sunar']
|
||||
elif str(platform) == 'hpux':
|
||||
"prefer aCC tools on HP-UX"
|
||||
|
@ -281,7 +386,7 @@ def tool_list(platform, env):
|
|||
c_compilers = ['hpcc', 'gcc', 'cc']
|
||||
cxx_compilers = ['hpc++', 'g++', 'c++']
|
||||
assemblers = ['as', 'gas']
|
||||
fortran_compilers = ['f77', 'g77', 'fortran']
|
||||
fortran_compilers = ['f95', 'f90', 'f77', 'g77', 'fortran']
|
||||
ars = ['ar']
|
||||
elif str(platform) == 'aix':
|
||||
"prefer AIX Visual Age tools on AIX"
|
||||
|
@ -289,15 +394,23 @@ def tool_list(platform, env):
|
|||
c_compilers = ['aixcc', 'gcc', 'cc']
|
||||
cxx_compilers = ['aixc++', 'g++', 'c++']
|
||||
assemblers = ['as', 'gas']
|
||||
fortran_compilers = ['aixf77', 'g77', 'fortran']
|
||||
fortran_compilers = ['f95', 'f90', 'aixf77', 'g77', 'fortran']
|
||||
ars = ['ar']
|
||||
elif str(platform) == 'darwin':
|
||||
"prefer GNU tools on Mac OS X, except for some linkers and IBM tools"
|
||||
linkers = ['applelink', 'gnulink']
|
||||
c_compilers = ['gcc', 'cc']
|
||||
cxx_compilers = ['g++', 'c++']
|
||||
assemblers = ['as']
|
||||
fortran_compilers = ['f95', 'f90', 'g77']
|
||||
ars = ['ar']
|
||||
else:
|
||||
"prefer GNU tools on all other platforms"
|
||||
linkers = ['gnulink', 'mslink', 'ilink']
|
||||
c_compilers = ['gcc', 'msvc', 'icc', 'cc']
|
||||
cxx_compilers = ['g++', 'msvc', 'icc', 'c++']
|
||||
c_compilers = ['gcc', 'msvc', 'intelc', 'icc', 'cc']
|
||||
cxx_compilers = ['g++', 'msvc', 'intelc', 'icc', 'c++']
|
||||
assemblers = ['gas', 'nasm', 'masm']
|
||||
fortran_compilers = ['g77', 'ifort', 'ifl', 'fortran']
|
||||
fortran_compilers = ['f95', 'f90', 'g77', 'ifort', 'ifl', 'fortran']
|
||||
ars = ['ar', 'mslib']
|
||||
|
||||
c_compiler = FindTool(c_compilers, env) or c_compilers[0]
|
||||
|
@ -314,7 +427,7 @@ def tool_list(platform, env):
|
|||
ar = None
|
||||
else:
|
||||
# Don't use g++ if the C compiler has built-in C++ support:
|
||||
if c_compiler in ('msvc', 'icc'):
|
||||
if c_compiler in ('msvc', 'intelc', 'icc'):
|
||||
cxx_compiler = None
|
||||
else:
|
||||
cxx_compiler = FindTool(cxx_compilers, env) or cxx_compilers[0]
|
||||
|
@ -327,12 +440,15 @@ def tool_list(platform, env):
|
|||
'dmd',
|
||||
'dvipdf', 'dvips', 'gs',
|
||||
'jar', 'javac', 'javah',
|
||||
'latex', 'lex', 'm4', 'midl', 'msvs',
|
||||
'latex', 'lex',
|
||||
'm4', 'midl', 'msvs',
|
||||
'pdflatex', 'pdftex', 'Perforce',
|
||||
'RCS', 'rmic', 'SCCS',
|
||||
'RCS', 'rmic', 'rpcgen',
|
||||
'SCCS',
|
||||
# 'Subversion',
|
||||
'swig',
|
||||
'tar', 'tex', 'yacc', 'zip'],
|
||||
'tar', 'tex',
|
||||
'yacc', 'zip'],
|
||||
env)
|
||||
|
||||
tools = ([linker, c_compiler, cxx_compiler,
|
|
@ -9,7 +9,7 @@ selection method.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -31,12 +31,11 @@ selection method.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/aixc++.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/aixc++.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import os.path
|
||||
|
||||
import SCons.Platform.aix
|
||||
import SCons.Script.SConscript
|
||||
|
||||
cplusplus = __import__('c++', globals(), locals(), [])
|
||||
|
||||
|
@ -48,7 +47,7 @@ def get_xlc(env):
|
|||
return SCons.Platform.aix.get_xlc(env, xlc, xlc_r, packages)
|
||||
|
||||
def smart_cxxflags(source, target, env, for_signature):
|
||||
build_dir = SCons.Script.SConscript.GetBuildPath()
|
||||
build_dir = env.GetBuildPath()
|
||||
if build_dir:
|
||||
return '-qtempinc=' + os.path.join(build_dir, 'tempinc')
|
||||
return ''
|
|
@ -8,7 +8,7 @@ selection method.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -30,7 +30,7 @@ selection method.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/aixcc.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/aixcc.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import os.path
|
||||
|
|
@ -8,7 +8,7 @@ selection method.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -30,7 +30,7 @@ selection method.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/aixf77.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/aixf77.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import os.path
|
||||
|
|
@ -8,7 +8,7 @@ selection method.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -30,7 +30,7 @@ selection method.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/aixlink.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/aixlink.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import os
|
||||
import os.path
|
|
@ -1,6 +1,6 @@
|
|||
"""SCons.Tool.swig
|
||||
"""SCons.Tool.applelink
|
||||
|
||||
Tool-specific initialization for swig.
|
||||
Tool-specific initialization for the Apple gnu-like linker.
|
||||
|
||||
There normally shouldn't be any need to import this module directly.
|
||||
It will usually be imported through the generic SCons.Tool.Tool()
|
||||
|
@ -9,7 +9,7 @@ selection method.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -31,33 +31,34 @@ selection method.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/swig.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/applelink.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import SCons.Defaults
|
||||
import SCons.Tool
|
||||
import SCons.Util
|
||||
|
||||
def swigSuffixEmitter(env, source):
|
||||
if '-c++' in SCons.Util.CLVar(env.subst("$SWIGFLAGS")):
|
||||
return '$SWIGCXXFILESUFFIX'
|
||||
else:
|
||||
return '$SWIGCFILESUFFIX'
|
||||
import gnulink
|
||||
|
||||
def generate(env):
|
||||
"""Add Builders and construction variables for swig to an Environment."""
|
||||
c_file, cxx_file = SCons.Tool.createCFileBuilders(env)
|
||||
"""Add Builders and construction variables for applelink to an
|
||||
Environment."""
|
||||
gnulink.generate(env)
|
||||
|
||||
c_file.suffix['.i'] = swigSuffixEmitter
|
||||
cxx_file.suffix['.i'] = swigSuffixEmitter
|
||||
env['FRAMEWORKPATHPREFIX'] = '-F'
|
||||
env['_FRAMEWORKPATH'] = '${_concat(FRAMEWORKPATHPREFIX, FRAMEWORKPATH, "", __env__)}'
|
||||
env['_FRAMEWORKS'] = '${_concat("-framework ", FRAMEWORKS, "", __env__)}'
|
||||
env['LINKCOM'] = env['LINKCOM'] + ' $_FRAMEWORKPATH $_FRAMEWORKS'
|
||||
env['SHLINKFLAGS'] = SCons.Util.CLVar('$LINKFLAGS -dynamiclib')
|
||||
env['SHLINKCOM'] = env['SHLINKCOM'] + ' $_FRAMEWORKPATH $_FRAMEWORKS'
|
||||
|
||||
# override the default for loadable modules, which are different
|
||||
# on OS X than dynamic shared libs. echoing what XCode does for
|
||||
# pre/suffixes:
|
||||
env['LDMODULEPREFIX'] = ''
|
||||
env['LDMODULESUFFIX'] = ''
|
||||
env['LDMODULEFLAGS'] = SCons.Util.CLVar('$LINKFLAGS -bundle')
|
||||
env['LDMODULECOM'] = '$LDMODULE -o ${TARGET} $LDMODULEFLAGS $SOURCES $_LIBDIRFLAGS $_LIBFLAGS $_FRAMEWORKPATH $_FRAMEWORKS $FRAMEWORKSFLAGS'
|
||||
|
||||
c_file.add_action('.i', '$SWIGCOM')
|
||||
cxx_file.add_action('.i', '$SWIGCOM')
|
||||
|
||||
env['SWIG'] = 'swig'
|
||||
env['SWIGFLAGS'] = SCons.Util.CLVar('')
|
||||
env['SWIGCFILESUFFIX'] = '_wrap$CFILESUFFIX'
|
||||
env['SWIGCXXFILESUFFIX'] = '_wrap$CXXFILESUFFIX'
|
||||
env['SWIGCOM'] = '$SWIG $SWIGFLAGS -o $TARGET $SOURCES'
|
||||
|
||||
def exists(env):
|
||||
return env.Detect(['swig'])
|
||||
import sys
|
||||
return sys.platform == 'darwin'
|
|
@ -9,7 +9,7 @@ selection method.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -31,28 +31,27 @@ selection method.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/ar.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/ar.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import SCons.Defaults
|
||||
import SCons.Tool
|
||||
import SCons.Util
|
||||
|
||||
|
||||
def generate(env):
|
||||
"""Add Builders and construction variables for ar to an Environment."""
|
||||
SCons.Tool.createStaticLibBuilder(env)
|
||||
|
||||
arcom = '$AR $ARFLAGS $TARGET $SOURCES'
|
||||
ranlib = 'ranlib'
|
||||
if env.Detect(ranlib):
|
||||
arcom = arcom + '\n$RANLIB $RANLIBFLAGS $TARGET'
|
||||
|
||||
env['AR'] = 'ar'
|
||||
env['ARFLAGS'] = SCons.Util.CLVar('r')
|
||||
env['RANLIB'] = ranlib
|
||||
env['RANLIBFLAGS'] = SCons.Util.CLVar('')
|
||||
env['ARCOM'] = arcom
|
||||
env['ARFLAGS'] = SCons.Util.CLVar('rc')
|
||||
env['ARCOM'] = '$AR $ARFLAGS $TARGET $SOURCES'
|
||||
env['LIBPREFIX'] = 'lib'
|
||||
env['LIBSUFFIX'] = '.a'
|
||||
|
||||
if env.Detect('ranlib'):
|
||||
env['RANLIB'] = 'ranlib'
|
||||
env['RANLIBFLAGS'] = SCons.Util.CLVar('')
|
||||
env['RANLIBCOM'] = '$RANLIB $RANLIBFLAGS $TARGET'
|
||||
|
||||
def exists(env):
|
||||
return env.Detect('ar')
|
|
@ -9,7 +9,7 @@ selection method.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -31,7 +31,7 @@ selection method.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/as.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/as.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import SCons.Defaults
|
||||
import SCons.Tool
|
||||
|
@ -52,16 +52,21 @@ def generate(env):
|
|||
|
||||
for suffix in ASSuffixes:
|
||||
static_obj.add_action(suffix, SCons.Defaults.ASAction)
|
||||
shared_obj.add_action(suffix, SCons.Defaults.ASAction)
|
||||
static_obj.add_emitter(suffix, SCons.Defaults.StaticObjectEmitter)
|
||||
shared_obj.add_emitter(suffix, SCons.Defaults.SharedObjectEmitter)
|
||||
|
||||
for suffix in ASPPSuffixes:
|
||||
static_obj.add_action(suffix, SCons.Defaults.ASPPAction)
|
||||
shared_obj.add_action(suffix, SCons.Defaults.ASPPAction)
|
||||
static_obj.add_emitter(suffix, SCons.Defaults.StaticObjectEmitter)
|
||||
shared_obj.add_emitter(suffix, SCons.Defaults.SharedObjectEmitter)
|
||||
|
||||
env['AS'] = env.Detect(assemblers) or 'as'
|
||||
env['ASFLAGS'] = SCons.Util.CLVar('')
|
||||
env['ASCOM'] = '$AS $ASFLAGS -o $TARGET $SOURCES'
|
||||
env['ASPPCOM'] = '$CC $ASFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -c -o $TARGET $SOURCES'
|
||||
env['ASPPFLAGS'] = '$ASFLAGS'
|
||||
env['ASPPCOM'] = '$CC $ASPPFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -c -o $TARGET $SOURCES'
|
||||
|
||||
def exists(env):
|
||||
return env.Detect(assemblers)
|
|
@ -5,7 +5,7 @@ XXX
|
|||
"""
|
||||
|
||||
#
|
||||
# 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 @@ XXX
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/bcc32.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/bcc32.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import os
|
||||
import os.path
|
||||
|
@ -63,10 +63,12 @@ def generate(env):
|
|||
|
||||
env['CC'] = 'bcc32'
|
||||
env['CCFLAGS'] = SCons.Util.CLVar('')
|
||||
env['CCCOM'] = '$CC -q $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -c -o $TARGET $SOURCES'
|
||||
env['CFLAGS'] = SCons.Util.CLVar('')
|
||||
env['CCCOM'] = '$CC -q $CFLAGS $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -c -o$TARGET $SOURCES'
|
||||
env['SHCC'] = '$CC'
|
||||
env['SHCCFLAGS'] = SCons.Util.CLVar('$CCFLAGS')
|
||||
env['SHCCCOM'] = '$SHCC -WD $SHCCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -c -o $TARGET $SOURCES'
|
||||
env['SHCFLAGS'] = SCons.Util.CLVar('$CFLAGS')
|
||||
env['SHCCCOM'] = '$SHCC -WD $SHCFLAGS $SHCCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -c -o$TARGET $SOURCES'
|
||||
env['CPPDEFPREFIX'] = '-D'
|
||||
env['CPPDEFSUFFIX'] = ''
|
||||
env['INCPREFIX'] = '-I'
|
|
@ -8,7 +8,7 @@ selection method.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -30,7 +30,7 @@ selection method.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/c++.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/c++.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import os.path
|
||||
|
||||
|
@ -40,7 +40,7 @@ import SCons.Util
|
|||
|
||||
compilers = ['CC', 'c++']
|
||||
|
||||
CXXSuffixes = ['.cpp', '.cc', '.cxx', '.c++', '.C++']
|
||||
CXXSuffixes = ['.cpp', '.cc', '.cxx', '.c++', '.C++', '.mm']
|
||||
if SCons.Util.case_sensitive_suffixes('.c', '.C'):
|
||||
CXXSuffixes.append('.C')
|
||||
|
||||
|
@ -60,6 +60,8 @@ def generate(env):
|
|||
Add Builders and construction variables for Visual Age C++ compilers
|
||||
to an Environment.
|
||||
"""
|
||||
import SCons.Tool
|
||||
import SCons.Tool.cc
|
||||
static_obj, shared_obj = SCons.Tool.createObjBuilders(env)
|
||||
|
||||
for suffix in CXXSuffixes:
|
||||
|
@ -68,12 +70,14 @@ def generate(env):
|
|||
static_obj.add_emitter(suffix, SCons.Defaults.StaticObjectEmitter)
|
||||
shared_obj.add_emitter(suffix, SCons.Defaults.SharedObjectEmitter)
|
||||
|
||||
SCons.Tool.cc.add_common_cc_variables(env)
|
||||
|
||||
env['CXX'] = 'c++'
|
||||
env['CXXFLAGS'] = SCons.Util.CLVar('$CCFLAGS')
|
||||
env['CXXCOM'] = '$CXX $CXXFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -c -o $TARGET $SOURCES'
|
||||
env['CXXCOM'] = '$CXX -o $TARGET -c $CXXFLAGS $_CCCOMCOM $SOURCES'
|
||||
env['SHCXX'] = '$CXX'
|
||||
env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS')
|
||||
env['SHCXXCOM'] = '$SHCXX $SHCXXFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -c -o $TARGET $SOURCES'
|
||||
env['SHCXXCOM'] = '$SHCXX -o $TARGET -c $SHCXXFLAGS $_CCCOMCOM $SOURCES'
|
||||
|
||||
env['CPPDEFPREFIX'] = '-D'
|
||||
env['CPPDEFSUFFIX'] = ''
|
|
@ -8,7 +8,7 @@ selection method.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -30,16 +30,38 @@ selection method.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/cc.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/cc.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import SCons.Tool
|
||||
import SCons.Defaults
|
||||
import SCons.Util
|
||||
|
||||
CSuffixes = ['.c']
|
||||
CSuffixes = ['.c', '.m']
|
||||
if not SCons.Util.case_sensitive_suffixes('.c', '.C'):
|
||||
CSuffixes.append('.C')
|
||||
|
||||
def add_common_cc_variables(env):
|
||||
"""
|
||||
Add underlying common "C compiler" variables that
|
||||
are used by multiple tools (specifically, c++).
|
||||
"""
|
||||
if not env.has_key('_CCCOMCOM'):
|
||||
env['_CCCOMCOM'] = '$CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS'
|
||||
# It's a hack to test for darwin here, but the alternative
|
||||
# of creating an applecc.py to contain this seems overkill.
|
||||
# Maybe someday the Apple platform will require more setup and
|
||||
# this logic will be moved.
|
||||
env['FRAMEWORKS'] = SCons.Util.CLVar('')
|
||||
env['FRAMEWORKPATH'] = SCons.Util.CLVar('')
|
||||
if env['PLATFORM'] == 'darwin':
|
||||
env['_CCCOMCOM'] = env['_CCCOMCOM'] + ' $_FRAMEWORKPATH'
|
||||
|
||||
if not env.has_key('CCFLAGS'):
|
||||
env['CCFLAGS'] = SCons.Util.CLVar('')
|
||||
|
||||
if not env.has_key('SHCCFLAGS'):
|
||||
env['SHCCFLAGS'] = SCons.Util.CLVar('$CCFLAGS')
|
||||
|
||||
def generate(env):
|
||||
"""
|
||||
Add Builders and construction variables for C compilers to an Environment.
|
||||
|
@ -52,12 +74,14 @@ def generate(env):
|
|||
static_obj.add_emitter(suffix, SCons.Defaults.StaticObjectEmitter)
|
||||
shared_obj.add_emitter(suffix, SCons.Defaults.SharedObjectEmitter)
|
||||
|
||||
add_common_cc_variables(env)
|
||||
|
||||
env['CC'] = 'cc'
|
||||
env['CCFLAGS'] = SCons.Util.CLVar('')
|
||||
env['CCCOM'] = '$CC $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -c -o $TARGET $SOURCES'
|
||||
env['CFLAGS'] = SCons.Util.CLVar('')
|
||||
env['CCCOM'] = '$CC -o $TARGET -c $CFLAGS $CCFLAGS $_CCCOMCOM $SOURCES'
|
||||
env['SHCC'] = '$CC'
|
||||
env['SHCCFLAGS'] = SCons.Util.CLVar('$CCFLAGS')
|
||||
env['SHCCCOM'] = '$SHCC $SHCCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -c -o $TARGET $SOURCES'
|
||||
env['SHCFLAGS'] = SCons.Util.CLVar('$CFLAGS')
|
||||
env['SHCCCOM'] = '$SHCC -o $TARGET -c $SHCFLAGS $SHCCFLAGS $_CCCOMCOM $SOURCES'
|
||||
|
||||
env['CPPDEFPREFIX'] = '-D'
|
||||
env['CPPDEFSUFFIX'] = ''
|
|
@ -5,7 +5,7 @@ Tool-specific initialization for the Compaq Visual Fortran compiler.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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,9 +27,8 @@ Tool-specific initialization for the Compaq Visual Fortran compiler.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/cvf.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/cvf.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import SCons.Util
|
||||
import fortran
|
||||
|
||||
compilers = ['f90']
|
||||
|
@ -40,10 +39,10 @@ def generate(env):
|
|||
fortran.generate(env)
|
||||
|
||||
env['FORTRAN'] = 'f90'
|
||||
env['FORTRANCOM'] = '$FORTRAN $FORTRANFLAGS $_FORTRANMODFLAG $_FORTRANINCFLAGS /compile_only ${SOURCES.win32} /object:${TARGET.win32}'
|
||||
env['FORTRANPPCOM'] = '$FORTRAN $FORTRANFLAGS $CPPFLAGS $_CPPDEFFLAGS $_FORTRANMODFLAG $_FORTRANINCFLAGS /compile_only ${SOURCES.win32} /object:${TARGET.win32}'
|
||||
env['SHFORTRANCOM'] = '$SHFORTRAN $SHFORTRANFLAGS $_FORTRANMODFLAG $_FORTRANINCFLAGS /compile_only ${SOURCES.win32} /object:${TARGET.win32}'
|
||||
env['SHFORTRANPPCOM'] = '$SHFORTRAN $SHFORTRANFLAGS $CPPFLAGS $_CPPDEFFLAGS $_FORTRANMODFLAG $_FORTRANINCFLAGS /compile_only ${SOURCES.win32} /object:${TARGET.win32}'
|
||||
env['FORTRANCOM'] = '$FORTRAN $FORTRANFLAGS $_FORTRANMODFLAG $_FORTRANINCFLAGS /compile_only ${SOURCES.windows} /object:${TARGET.windows}'
|
||||
env['FORTRANPPCOM'] = '$FORTRAN $FORTRANFLAGS $CPPFLAGS $_CPPDEFFLAGS $_FORTRANMODFLAG $_FORTRANINCFLAGS /compile_only ${SOURCES.windows} /object:${TARGET.windows}'
|
||||
env['SHFORTRANCOM'] = '$SHFORTRAN $SHFORTRANFLAGS $_FORTRANMODFLAG $_FORTRANINCFLAGS /compile_only ${SOURCES.windows} /object:${TARGET.windows}'
|
||||
env['SHFORTRANPPCOM'] = '$SHFORTRAN $SHFORTRANFLAGS $CPPFLAGS $_CPPDEFFLAGS $_FORTRANMODFLAG $_FORTRANINCFLAGS /compile_only ${SOURCES.windows} /object:${TARGET.windows}'
|
||||
env['OBJSUFFIX'] = '.obj'
|
||||
env['FORTRANMODDIR'] = '${TARGET.dir}'
|
||||
env['FORTRANMODDIRPREFIX'] = '/module:'
|
|
@ -9,7 +9,7 @@ selection method.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -31,7 +31,7 @@ selection method.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/default.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/default.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import SCons.Tool
|
||||
|
|
@ -7,7 +7,7 @@ Coded by Andy Friesen (andy@ikagames.com)
|
|||
15 November 2003
|
||||
|
||||
There are a number of problems with this script at this point in time.
|
||||
The one that irritates me the most is the win32 linker setup. The D
|
||||
The one that irritates me the most is the Windows linker setup. The D
|
||||
linker doesn't have a way to add lib paths on the commandline, as far
|
||||
as I can see. You have to specify paths relative to the SConscript or
|
||||
use absolute paths. To hack around it, add '#/blah'. This will link
|
||||
|
@ -31,7 +31,7 @@ Lib tool variables:
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -53,15 +53,16 @@ Lib tool variables:
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/dmd.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/dmd.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import os
|
||||
import string
|
||||
|
||||
import SCons.Tool
|
||||
import SCons.Scanner.D
|
||||
import SCons.Action
|
||||
import SCons.Builder
|
||||
import SCons.Defaults
|
||||
import SCons.Scanner.D
|
||||
import SCons.Tool
|
||||
|
||||
# Adapted from c++.py
|
||||
def isD(source):
|
||||
|
@ -85,14 +86,16 @@ def generate(env):
|
|||
|
||||
static_obj, shared_obj = SCons.Tool.createObjBuilders(env)
|
||||
|
||||
static_obj.add_action('.d', '$DCOM')
|
||||
shared_obj.add_action('.d', '$DCOM')
|
||||
DAction = SCons.Action.Action('$DCOM', '$DCOMSTR')
|
||||
|
||||
static_obj.add_action('.d', DAction)
|
||||
shared_obj.add_action('.d', DAction)
|
||||
static_obj.add_emitter('.d', SCons.Defaults.StaticObjectEmitter)
|
||||
shared_obj.add_emitter('.d', SCons.Defaults.SharedObjectEmitter)
|
||||
|
||||
env['DC'] = 'dmd'
|
||||
env['DCOM'] = '$DC $_DINCFLAGS $_DVERFLAGS $_DDEBUGFLAGS $_DFLAGS -c -of$TARGET $SOURCES'
|
||||
env['_DINCFLAGS'] = '$( ${_concat(DINCPREFIX, DPATH, DINCSUFFIX, __env__, RDirs)} $)'
|
||||
env['_DINCFLAGS'] = '$( ${_concat(DINCPREFIX, DPATH, DINCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)'
|
||||
env['_DVERFLAGS'] = '$( ${_concat(DVERPREFIX, DVERSIONS, DVERSUFFIX, __env__)} $)'
|
||||
env['_DDEBUGFLAGS'] = '$( ${_concat(DDEBUGPREFIX, DDEBUG, DDEBUGSUFFIX, __env__)} $)'
|
||||
env['_DFLAGS'] = '$( ${_concat(DFLAGPREFIX, DFLAGS, DFLAGSUFFIX, __env__)} $)'
|
||||
|
@ -129,7 +132,7 @@ def generate(env):
|
|||
env['DLIB'] = 'lib'
|
||||
env['DLIBCOM'] = '$DLIB $_DLIBFLAGS -c $TARGET $SOURCES $_DLINKLIBFLAGS'
|
||||
|
||||
env['_DLINKLIBFLAGS'] = '$( ${_concat(DLIBLINKPREFIX, LIBS, DLIBLINKSUFFIX, __env__, RDirs)} $)'
|
||||
env['_DLINKLIBFLAGS'] = '$( ${_concat(DLIBLINKPREFIX, LIBS, DLIBLINKSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)'
|
||||
env['_DLIBFLAGS'] = '$( ${_concat(DLIBFLAGPREFIX, DLIBFLAGS, DLIBFLAGSUFFIX, __env__)} $)'
|
||||
env['DLINKFLAGS'] = []
|
||||
env['DLIBLINKPREFIX'] = ''
|
||||
|
@ -152,6 +155,10 @@ def generate(env):
|
|||
def _smartLink(source, target, env, for_signature,
|
||||
defaultLinker=linkcom):
|
||||
if isD(source):
|
||||
# XXX I'm not sure how to add a $DLINKCOMSTR variable
|
||||
# so that it works with this _smartLink() logic,
|
||||
# and I don't have a D compiler/linker to try it out,
|
||||
# so we'll leave it alone for now.
|
||||
return '$DLINKCOM'
|
||||
else:
|
||||
return defaultLinker
|
||||
|
@ -164,6 +171,10 @@ def generate(env):
|
|||
def _smartLib(source, target, env, for_signature,
|
||||
defaultLib=arcom):
|
||||
if isD(source):
|
||||
# XXX I'm not sure how to add a $DLIBCOMSTR variable
|
||||
# so that it works with this _smartLib() logic, and
|
||||
# I don't have a D compiler/archiver to try it out,
|
||||
# so we'll leave it alone for now.
|
||||
return '$DLIBCOM'
|
||||
else:
|
||||
return defaultLib
|
||||
|
@ -190,6 +201,8 @@ def generate(env):
|
|||
env.Append(LIBS = ['phobos'])
|
||||
if 'pthread' not in libs:
|
||||
env.Append(LIBS = ['pthread'])
|
||||
if 'm' not in libs:
|
||||
env.Append(LIBS = ['m'])
|
||||
return defaultLinker
|
||||
env['SMART_LINKCOM'] = smart_link[linkcom] = _smartLink
|
||||
|
58
scons/scons-local-0.97/SCons/Tool/dvi.py
Normal file
58
scons/scons-local-0.97/SCons/Tool/dvi.py
Normal file
|
@ -0,0 +1,58 @@
|
|||
"""SCons.Tool.dvi
|
||||
|
||||
Common DVI Builder definition for various other Tool modules that use it.
|
||||
|
||||
"""
|
||||
|
||||
#
|
||||
# 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/Tool/dvi.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import SCons.Builder
|
||||
import SCons.Tool
|
||||
|
||||
DVIBuilder = None
|
||||
|
||||
def generate(env):
|
||||
try:
|
||||
env['BUILDERS']['DVI']
|
||||
except KeyError:
|
||||
global DVIBuilder
|
||||
|
||||
if DVIBuilder is None:
|
||||
# The suffix is hard-coded to '.dvi', not configurable via a
|
||||
# construction variable like $DVISUFFIX, because the output
|
||||
# file name is hard-coded within TeX.
|
||||
DVIBuilder = SCons.Builder.Builder(action = {},
|
||||
source_scanner = SCons.Tool.LaTeXScanner,
|
||||
suffix = '.dvi',
|
||||
emitter = {},
|
||||
source_ext_match = None)
|
||||
|
||||
env['BUILDERS']['DVI'] = DVIBuilder
|
||||
|
||||
def exists(env):
|
||||
# This only puts a skeleton Builder in place, so if someone
|
||||
# references this Tool directly, it's always "available."
|
||||
return 1
|
|
@ -9,7 +9,7 @@ selection method.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -31,23 +31,42 @@ selection method.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/dvipdf.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/dvipdf.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import SCons.Action
|
||||
import SCons.Defaults
|
||||
import SCons.Tool.pdf
|
||||
import SCons.Util
|
||||
|
||||
PDFAction = None
|
||||
|
||||
def PDFEmitter(target, source, env):
|
||||
"""Strips any .aux or .log files from the input source list.
|
||||
These are created by the TeX Builder that in all likelihood was
|
||||
used to generate the .dvi file we're using as input, and we only
|
||||
care about the .dvi file.
|
||||
"""
|
||||
def strip_suffixes(n):
|
||||
return not SCons.Util.splitext(str(n))[1] in ['.aux', '.log']
|
||||
source = filter(strip_suffixes, source)
|
||||
return (target, source)
|
||||
|
||||
def generate(env):
|
||||
"""Add Builders and construction variables for dvipdf to an Environment."""
|
||||
try:
|
||||
global PDFAction
|
||||
if PDFAction is None:
|
||||
PDFAction = SCons.Action.Action('$DVIPDFCOM', '$DVIPDFCOMSTR')
|
||||
|
||||
import pdf
|
||||
pdf.generate(env)
|
||||
|
||||
bld = env['BUILDERS']['PDF']
|
||||
except KeyError:
|
||||
bld = SCons.Defaults.PDF()
|
||||
env['BUILDERS']['PDF'] = bld
|
||||
bld.add_action('.dvi', '$PDFCOM')
|
||||
bld.add_action('.dvi', PDFAction)
|
||||
bld.add_emitter('.dvi', PDFEmitter)
|
||||
|
||||
env['DVIPDF'] = 'dvipdf'
|
||||
env['DVIPDFFLAGS'] = SCons.Util.CLVar('')
|
||||
env['DVIPDFCOM'] = '$DVIPDF $DVIPDFFLAGS $SOURCES $TARGET'
|
||||
env['DVIPDFCOM'] = 'cd ${TARGET.dir} && $DVIPDF $DVIPDFFLAGS ${SOURCE.file} ${TARGET.file}'
|
||||
|
||||
# Deprecated synonym.
|
||||
env['PDFCOM'] = ['$DVIPDFCOM']
|
|
@ -9,7 +9,7 @@ selection method.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -31,25 +31,38 @@ selection method.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/dvips.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/dvips.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import SCons.Action
|
||||
import SCons.Defaults
|
||||
import SCons.Builder
|
||||
import SCons.Util
|
||||
|
||||
PostScript = SCons.Builder.Builder(action = '$PSCOM',
|
||||
PSAction = None
|
||||
PSBuilder = None
|
||||
|
||||
def generate(env):
|
||||
"""Add Builders and construction variables for dvips to an Environment."""
|
||||
global PSAction
|
||||
if PSAction is None:
|
||||
PSAction = SCons.Action.Action('$PSCOM', '$PSCOMSTR')
|
||||
|
||||
global PSBuilder
|
||||
if PSBuilder is None:
|
||||
PSBuilder = SCons.Builder.Builder(action = PSAction,
|
||||
prefix = '$PSPREFIX',
|
||||
suffix = '$PSSUFFIX',
|
||||
src_suffix = '.dvi',
|
||||
src_builder = 'DVI')
|
||||
|
||||
def generate(env):
|
||||
"""Add Builders and construction variables for dvips to an Environment."""
|
||||
env['BUILDERS']['PostScript'] = PostScript
|
||||
env['BUILDERS']['PostScript'] = PSBuilder
|
||||
|
||||
env['DVIPS'] = 'dvips'
|
||||
env['DVIPSFLAGS'] = SCons.Util.CLVar('')
|
||||
env['PSCOM'] = '$DVIPS $DVIPSFLAGS -o $TARGET $SOURCES'
|
||||
# I'm not quite sure I got the directories and filenames right for build_dir
|
||||
# We need to be in the correct directory for the sake of latex \includegraphics eps included files.
|
||||
env['PSCOM'] = 'cd ${TARGET.dir} && $DVIPS $DVIPSFLAGS -o ${TARGET.file} ${SOURCE.file}'
|
||||
env['PSPREFIX'] = ''
|
||||
env['PSSUFFIX'] = '.ps'
|
||||
|
||||
def exists(env):
|
||||
return env.Detect('dvips')
|
|
@ -9,7 +9,7 @@ selection method.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -31,7 +31,7 @@ selection method.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/f77.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/f77.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import SCons.Defaults
|
||||
import SCons.Scanner.Fortran
|
||||
|
@ -53,7 +53,8 @@ else:
|
|||
F77Scan = SCons.Scanner.Fortran.FortranScan("F77PATH")
|
||||
|
||||
for suffix in F77Suffixes + F77PPSuffixes:
|
||||
SCons.Defaults.ObjSourceScan.add_scanner(suffix, F77Scan)
|
||||
SCons.Tool.SourceFileScanner.add_scanner(suffix, F77Scan)
|
||||
del suffix
|
||||
|
||||
#
|
||||
fVLG = fortran.VariableListGenerator
|
||||
|
@ -61,19 +62,23 @@ fVLG = fortran.VariableListGenerator
|
|||
F77Generator = fVLG('F77', 'FORTRAN', '_FORTRAND')
|
||||
F77FlagsGenerator = fVLG('F77FLAGS', 'FORTRANFLAGS')
|
||||
F77CommandGenerator = fVLG('F77COM', 'FORTRANCOM', '_F77COMD')
|
||||
F77CommandStrGenerator = fVLG('F77COMSTR', 'FORTRANCOMSTR', '_F77COMSTRD')
|
||||
F77PPCommandGenerator = fVLG('F77PPCOM', 'FORTRANPPCOM', '_F77PPCOMD')
|
||||
F77PPCommandStrGenerator = fVLG('F77PPCOMSTR', 'FORTRANPPCOMSTR', '_F77PPCOMSTRD')
|
||||
ShF77Generator = fVLG('SHF77', 'SHFORTRAN', 'F77', 'FORTRAN', '_FORTRAND')
|
||||
ShF77FlagsGenerator = fVLG('SHF77FLAGS', 'SHFORTRANFLAGS')
|
||||
ShF77CommandGenerator = fVLG('SHF77COM', 'SHFORTRANCOM', '_SHF77COMD')
|
||||
ShF77CommandStrGenerator = fVLG('SHF77COMSTR', 'SHFORTRANCOMSTR', '_SHF77COMSTRD')
|
||||
ShF77PPCommandGenerator = fVLG('SHF77PPCOM', 'SHFORTRANPPCOM', '_SHF77PPCOMD')
|
||||
ShF77PPCommandStrGenerator = fVLG('SHF77PPCOMSTR', 'SHFORTRANPPCOMSTR', '_SHF77PPCOMSTRD')
|
||||
|
||||
del fVLG
|
||||
|
||||
#
|
||||
F77Action = SCons.Action.Action('$_F77COMG ')
|
||||
F77PPAction = SCons.Action.Action('$_F77PPCOMG ')
|
||||
ShF77Action = SCons.Action.Action('$_SHF77COMG ')
|
||||
ShF77PPAction = SCons.Action.Action('$_SHF77PPCOMG ')
|
||||
F77Action = SCons.Action.Action('$_F77COMG ', '$_F77COMSTRG')
|
||||
F77PPAction = SCons.Action.Action('$_F77PPCOMG ', '$_F77PPCOMSTRG')
|
||||
ShF77Action = SCons.Action.Action('$_SHF77COMG ', '$_SHF77COMSTRG')
|
||||
ShF77PPAction = SCons.Action.Action('$_SHF77PPCOMG ', '$_SHF77PPCOMSTRG')
|
||||
|
||||
def add_to_env(env):
|
||||
"""Add Builders and construction variables for f77 to an Environment."""
|
||||
|
@ -97,18 +102,22 @@ def add_to_env(env):
|
|||
env['_F77FLAGSG'] = F77FlagsGenerator
|
||||
env['_F77COMG'] = F77CommandGenerator
|
||||
env['_F77PPCOMG'] = F77PPCommandGenerator
|
||||
env['_F77COMSTRG'] = F77CommandStrGenerator
|
||||
env['_F77PPCOMSTRG'] = F77PPCommandStrGenerator
|
||||
|
||||
env['_SHF77G'] = ShF77Generator
|
||||
env['_SHF77FLAGSG'] = ShF77FlagsGenerator
|
||||
env['_SHF77COMG'] = ShF77CommandGenerator
|
||||
env['_SHF77PPCOMG'] = ShF77PPCommandGenerator
|
||||
env['_SHF77COMSTRG'] = ShF77CommandStrGenerator
|
||||
env['_SHF77PPCOMSTRG'] = ShF77PPCommandStrGenerator
|
||||
|
||||
env['_F77INCFLAGS'] = '$( ${_concat(INCPREFIX, F77PATH, INCSUFFIX, __env__, RDirs)} $)'
|
||||
env['_F77INCFLAGS'] = '$( ${_concat(INCPREFIX, F77PATH, INCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)'
|
||||
|
||||
env['_F77COMD'] = '$_F77G $_F77FLAGSG $_F77INCFLAGS -c -o $TARGET $SOURCES'
|
||||
env['_F77PPCOMD'] = '$_F77G $_F77FLAGSG $CPPFLAGS $_CPPDEFFLAGS $_F77INCFLAGS -c -o $TARGET $SOURCES'
|
||||
env['_SHF77COMD'] = '$_SHF77G $_SHF77FLAGSG $_F77INCFLAGS -c -o $TARGET $SOURCES'
|
||||
env['_SHF77PPCOMD'] = '$_SHF77G $_SHF77FLAGSG $CPPFLAGS $_CPPDEFFLAGS $_F77INCFLAGS -c -o $TARGET $SOURCES'
|
||||
env['_F77COMD'] = '$_F77G -o $TARGET -c $_F77FLAGSG $_F77INCFLAGS $SOURCES'
|
||||
env['_F77PPCOMD'] = '$_F77G -o $TARGET -c $_F77FLAGSG $CPPFLAGS $_CPPDEFFLAGS $_F77INCFLAGS $SOURCES'
|
||||
env['_SHF77COMD'] = '$_SHF77G -o $TARGET -c $_SHF77FLAGSG $_F77INCFLAGS $SOURCES'
|
||||
env['_SHF77PPCOMD'] = '$_SHF77G -o $TARGET -c $_SHF77FLAGSG $CPPFLAGS $_CPPDEFFLAGS $_F77INCFLAGS $SOURCES'
|
||||
|
||||
def generate(env):
|
||||
fortran.add_to_env(env)
|
|
@ -9,7 +9,7 @@ selection method.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -31,7 +31,7 @@ selection method.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/f90.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/f90.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import SCons.Defaults
|
||||
import SCons.Scanner.Fortran
|
||||
|
@ -53,7 +53,8 @@ else:
|
|||
F90Scan = SCons.Scanner.Fortran.FortranScan("F90PATH")
|
||||
|
||||
for suffix in F90Suffixes + F90PPSuffixes:
|
||||
SCons.Defaults.ObjSourceScan.add_scanner(suffix, F90Scan)
|
||||
SCons.Tool.SourceFileScanner.add_scanner(suffix, F90Scan)
|
||||
del suffix
|
||||
|
||||
#
|
||||
fVLG = fortran.VariableListGenerator
|
||||
|
@ -61,19 +62,23 @@ fVLG = fortran.VariableListGenerator
|
|||
F90Generator = fVLG('F90', 'FORTRAN', '_FORTRAND')
|
||||
F90FlagsGenerator = fVLG('F90FLAGS', 'FORTRANFLAGS')
|
||||
F90CommandGenerator = fVLG('F90COM', 'FORTRANCOM', '_F90COMD')
|
||||
F90CommandStrGenerator = fVLG('F90COMSTR', 'FORTRANCOMSTR', '_F90COMSTRD')
|
||||
F90PPCommandGenerator = fVLG('F90PPCOM', 'FORTRANPPCOM', '_F90PPCOMD')
|
||||
F90PPCommandStrGenerator = fVLG('F90PPCOMSTR', 'FORTRANPPCOMSTR', '_F90PPCOMSTRD')
|
||||
ShF90Generator = fVLG('SHF90', 'SHFORTRAN', 'F90', 'FORTRAN', '_FORTRAND')
|
||||
ShF90FlagsGenerator = fVLG('SHF90FLAGS', 'SHFORTRANFLAGS')
|
||||
ShF90CommandGenerator = fVLG('SHF90COM', 'SHFORTRANCOM', '_SHF90COMD')
|
||||
ShF90CommandStrGenerator = fVLG('SHF90COMSTR', 'SHFORTRANCOMSTR', '_SHF90COMSTRD')
|
||||
ShF90PPCommandGenerator = fVLG('SHF90PPCOM', 'SHFORTRANPPCOM', '_SHF90PPCOMD')
|
||||
ShF90PPCommandStrGenerator = fVLG('SHF90PPCOMSTR', 'SHFORTRANPPCOMSTR', '_SHF90PPCOMSTRD')
|
||||
|
||||
del fVLG
|
||||
|
||||
#
|
||||
F90Action = SCons.Action.Action('$_F90COMG ')
|
||||
F90PPAction = SCons.Action.Action('$_F90PPCOMG ')
|
||||
ShF90Action = SCons.Action.Action('$_SHF90COMG ')
|
||||
ShF90PPAction = SCons.Action.Action('$_SHF90PPCOMG ')
|
||||
F90Action = SCons.Action.Action('$_F90COMG ', '$_F90COMSTRG')
|
||||
F90PPAction = SCons.Action.Action('$_F90PPCOMG ', '$_F90PPCOMSTRG')
|
||||
ShF90Action = SCons.Action.Action('$_SHF90COMG ', '$_SHF90COMSTRG')
|
||||
ShF90PPAction = SCons.Action.Action('$_SHF90PPCOMG ', '$_SHF90PPCOMSTRG')
|
||||
|
||||
def add_to_env(env):
|
||||
"""Add Builders and construction variables for f90 to an Environment."""
|
||||
|
@ -96,21 +101,29 @@ def add_to_env(env):
|
|||
env['_F90G'] = F90Generator
|
||||
env['_F90FLAGSG'] = F90FlagsGenerator
|
||||
env['_F90COMG'] = F90CommandGenerator
|
||||
env['_F90COMSTRG'] = F90CommandStrGenerator
|
||||
env['_F90PPCOMG'] = F90PPCommandGenerator
|
||||
env['_F90PPCOMSTRG'] = F90PPCommandStrGenerator
|
||||
|
||||
env['_SHF90G'] = ShF90Generator
|
||||
env['_SHF90FLAGSG'] = ShF90FlagsGenerator
|
||||
env['_SHF90COMG'] = ShF90CommandGenerator
|
||||
env['_SHF90COMSTRG'] = ShF90CommandStrGenerator
|
||||
env['_SHF90PPCOMG'] = ShF90PPCommandGenerator
|
||||
env['_SHF90PPCOMSTRG'] = ShF90PPCommandStrGenerator
|
||||
|
||||
env['_F90INCFLAGS'] = '$( ${_concat(INCPREFIX, F90PATH, INCSUFFIX, __env__, RDirs)} $)'
|
||||
env['_F90COMD'] = '$_F90G $_F90FLAGSG $_F90INCFLAGS $_FORTRANMODFLAG -c -o $TARGET $SOURCES'
|
||||
env['_F90PPCOMD'] = '$_F90G $_F90FLAGSG $CPPFLAGS $_CPPDEFFLAGS $_F90INCFLAGS $_FORTRANMODFLAG -c -o $TARGET $SOURCES'
|
||||
env['_SHF90COMD'] = '$_SHF90G $_SHF90FLAGSG $_F90INCFLAGS $_FORTRANMODFLAG -c -o $TARGET $SOURCES'
|
||||
env['_SHF90PPCOMD'] = '$_SHF90G $_SHF90FLAGSG $CPPFLAGS $_CPPDEFFLAGS $_F90INCFLAGS $_FORTRANMODFLAG -c -o $TARGET $SOURCES'
|
||||
env['_F90INCFLAGS'] = '$( ${_concat(INCPREFIX, F90PATH, INCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)'
|
||||
env['_F90COMD'] = '$_F90G -o $TARGET -c $_F90FLAGSG $_F90INCFLAGS $_FORTRANMODFLAG $SOURCES'
|
||||
env['_F90PPCOMD'] = '$_F90G -o $TARGET -c $_F90FLAGSG $CPPFLAGS $_CPPDEFFLAGS $_F90INCFLAGS $_FORTRANMODFLAG $SOURCES'
|
||||
env['_SHF90COMD'] = '$_SHF90G -o $TARGET -c $_SHF90FLAGSG $_F90INCFLAGS $_FORTRANMODFLAG $SOURCES'
|
||||
env['_SHF90PPCOMD'] = '$_SHF90G -o $TARGET -c $_SHF90FLAGSG $CPPFLAGS $_CPPDEFFLAGS $_F90INCFLAGS $_FORTRANMODFLAG $SOURCES'
|
||||
|
||||
def generate(env):
|
||||
fortran.add_to_env(env)
|
||||
|
||||
import f77
|
||||
f77.add_to_env(env)
|
||||
|
||||
add_to_env(env)
|
||||
|
||||
env['_FORTRAND'] = env.Detect(compilers) or 'f90'
|
|
@ -9,7 +9,7 @@ selection method.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -31,7 +31,7 @@ selection method.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/f95.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/f95.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import SCons.Defaults
|
||||
import SCons.Tool
|
||||
|
@ -52,7 +52,8 @@ else:
|
|||
F95Scan = SCons.Scanner.Fortran.FortranScan("F95PATH")
|
||||
|
||||
for suffix in F95Suffixes + F95PPSuffixes:
|
||||
SCons.Defaults.ObjSourceScan.add_scanner(suffix, F95Scan)
|
||||
SCons.Tool.SourceFileScanner.add_scanner(suffix, F95Scan)
|
||||
del suffix
|
||||
|
||||
#
|
||||
fVLG = fortran.VariableListGenerator
|
||||
|
@ -60,19 +61,23 @@ fVLG = fortran.VariableListGenerator
|
|||
F95Generator = fVLG('F95', 'FORTRAN', '_FORTRAND')
|
||||
F95FlagsGenerator = fVLG('F95FLAGS', 'FORTRANFLAGS')
|
||||
F95CommandGenerator = fVLG('F95COM', 'FORTRANCOM', '_F95COMD')
|
||||
F95CommandStrGenerator = fVLG('F95COMSTR', 'FORTRANCOMSTR', '_F95COMSTRD')
|
||||
F95PPCommandGenerator = fVLG('F95PPCOM', 'FORTRANPPCOM', '_F95PPCOMD')
|
||||
F95PPCommandStrGenerator = fVLG('F95PPCOMSTR', 'FORTRANPPCOMSTR', '_F95PPCOMSTRD')
|
||||
ShF95Generator = fVLG('SHF95', 'SHFORTRAN', 'F95', 'FORTRAN', '_FORTRAND')
|
||||
ShF95FlagsGenerator = fVLG('SHF95FLAGS', 'SHFORTRANFLAGS')
|
||||
ShF95CommandGenerator = fVLG('SHF95COM', 'SHFORTRANCOM', '_SHF95COMD')
|
||||
ShF95CommandStrGenerator = fVLG('SHF95COMSTR', 'SHFORTRANCOMSTR', '_SHF95COMSTRD')
|
||||
ShF95PPCommandGenerator = fVLG('SHF95PPCOM', 'SHFORTRANPPCOM', '_SHF95PPCOMD')
|
||||
ShF95PPCommandStrGenerator = fVLG('SHF95PPCOMSTR', 'SHFORTRANPPCOMSTR', '_SHF95PPCOMSTRD')
|
||||
|
||||
del fVLG
|
||||
|
||||
#
|
||||
F95Action = SCons.Action.Action('$_F95COMG ')
|
||||
F95PPAction = SCons.Action.Action('$_F95PPCOMG ')
|
||||
ShF95Action = SCons.Action.Action('$_SHF95COMG ')
|
||||
ShF95PPAction = SCons.Action.Action('$_SHF95PPCOMG ')
|
||||
F95Action = SCons.Action.Action('$_F95COMG ', '$_F95COMSTRG')
|
||||
F95PPAction = SCons.Action.Action('$_F95PPCOMG ', '$_F95PPCOMSTRG')
|
||||
ShF95Action = SCons.Action.Action('$_SHF95COMG ', '$_SHF95COMSTRG')
|
||||
ShF95PPAction = SCons.Action.Action('$_SHF95PPCOMG ', '$_SHF95PPCOMSTRG')
|
||||
|
||||
def add_to_env(env):
|
||||
"""Add Builders and construction variables for f95 to an Environment."""
|
||||
|
@ -95,22 +100,33 @@ def add_to_env(env):
|
|||
env['_F95G'] = F95Generator
|
||||
env['_F95FLAGSG'] = F95FlagsGenerator
|
||||
env['_F95COMG'] = F95CommandGenerator
|
||||
env['_F95COMSTRG'] = F95CommandStrGenerator
|
||||
env['_F95PPCOMG'] = F95PPCommandGenerator
|
||||
env['_F95PPCOMSTRG'] = F95PPCommandStrGenerator
|
||||
|
||||
env['_SHF95G'] = ShF95Generator
|
||||
env['_SHF95FLAGSG'] = ShF95FlagsGenerator
|
||||
env['_SHF95COMG'] = ShF95CommandGenerator
|
||||
env['_SHF95COMSTRG'] = ShF95CommandStrGenerator
|
||||
env['_SHF95PPCOMG'] = ShF95PPCommandGenerator
|
||||
env['_SHF95PPCOMSTRG'] = ShF95PPCommandStrGenerator
|
||||
|
||||
env['_F95INCFLAGS'] = '$( ${_concat(INCPREFIX, F95PATH, INCSUFFIX, __env__, RDirs)} $)'
|
||||
env['_F95INCFLAGS'] = '$( ${_concat(INCPREFIX, F95PATH, INCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)'
|
||||
|
||||
env['_F95COMD'] = '$_F95G $_F95FLAGSG $_F95INCFLAGS $_FORTRANMODFLAG -c -o $TARGET $SOURCES'
|
||||
env['_F95PPCOMD'] = '$_F95G $_F95FLAGSG $CPPFLAGS $_CPPDEFFLAGS $_F95INCFLAGS $_FORTRANMODFLAG -c -o $TARGET $SOURCES'
|
||||
env['_SHF95COMD'] = '$_SHF95G $_SHF95FLAGSG $_F95INCFLAGS $_FORTRANMODFLAG -c -o $TARGET $SOURCES'
|
||||
env['_SHF95PPCOMD'] = '$_SHF95G $_SHF95FLAGSG $CPPFLAGS $_CPPDEFFLAGS $_F95INCFLAGS $_FORTRANMODFLAG -c -o $TARGET $SOURCES'
|
||||
env['_F95COMD'] = '$_F95G -o $TARGET -c $_F95FLAGSG $_F95INCFLAGS $_FORTRANMODFLAG $SOURCES'
|
||||
env['_F95PPCOMD'] = '$_F95G -o $TARGET -c $_F95FLAGSG $CPPFLAGS $_CPPDEFFLAGS $_F95INCFLAGS $_FORTRANMODFLAG $SOURCES'
|
||||
env['_SHF95COMD'] = '$_SHF95G -o $TARGET -c $_SHF95FLAGSG $_F95INCFLAGS $_FORTRANMODFLAG $SOURCES'
|
||||
env['_SHF95PPCOMD'] = '$_SHF95G -o $TARGET -c $_SHF95FLAGSG $CPPFLAGS $_CPPDEFFLAGS $_F95INCFLAGS $_FORTRANMODFLAG $SOURCES'
|
||||
|
||||
def generate(env):
|
||||
fortran.add_to_env(env)
|
||||
|
||||
import f77
|
||||
f77.add_to_env(env)
|
||||
|
||||
import f90
|
||||
f90.add_to_env(env)
|
||||
|
||||
add_to_env(env)
|
||||
|
||||
env['_FORTRAND'] = env.Detect(compilers) or 'f95'
|
|
@ -9,7 +9,7 @@ selection method.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -31,7 +31,7 @@ selection method.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/fortran.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/fortran.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import re
|
||||
import string
|
||||
|
@ -62,7 +62,8 @@ else:
|
|||
FortranScan = SCons.Scanner.Fortran.FortranScan("FORTRANPATH")
|
||||
|
||||
for suffix in FortranSuffixes + FortranPPSuffixes:
|
||||
SCons.Defaults.ObjSourceScan.add_scanner(suffix, FortranScan)
|
||||
SCons.Tool.SourceFileScanner.add_scanner(suffix, FortranScan)
|
||||
del suffix
|
||||
|
||||
#
|
||||
def _fortranEmitter(target, source, env):
|
||||
|
@ -78,9 +79,10 @@ def _fortranEmitter(target, source, env):
|
|||
modules = SCons.Util.unique(modules)
|
||||
# Convert module name to a .mod filename
|
||||
suffix = env.subst('$FORTRANMODSUFFIX')
|
||||
moddir = env.subst('$FORTRANMODDIR')
|
||||
modules = map(lambda x, s=suffix: string.lower(x) + s, modules)
|
||||
for m in modules:
|
||||
target.append(env.fs.File(m))
|
||||
target.append(env.fs.File(m, moddir))
|
||||
return (target, source)
|
||||
|
||||
def FortranEmitter(target, source, env):
|
||||
|
@ -94,7 +96,7 @@ def ShFortranEmitter(target, source, env):
|
|||
class VariableListGenerator:
|
||||
def __init__(self, *variablelist):
|
||||
self.variablelist = variablelist
|
||||
def __call__(self, env, target, source, for_signature):
|
||||
def __call__(self, env, target, source, for_signature=0):
|
||||
for v in self.variablelist:
|
||||
try: return env[v]
|
||||
except KeyError: pass
|
||||
|
@ -104,17 +106,21 @@ class VariableListGenerator:
|
|||
FortranGenerator = VariableListGenerator('FORTRAN', 'F77', '_FORTRAND')
|
||||
FortranFlagsGenerator = VariableListGenerator('FORTRANFLAGS', 'F77FLAGS')
|
||||
FortranCommandGenerator = VariableListGenerator('FORTRANCOM', 'F77COM', '_FORTRANCOMD')
|
||||
FortranCommandStrGenerator = VariableListGenerator('FORTRANCOMSTR', 'F77COMSTR', '_FORTRANCOMSTRD')
|
||||
FortranPPCommandGenerator = VariableListGenerator('FORTRANPPCOM', 'F77PPCOM', '_FORTRANPPCOMD')
|
||||
FortranPPCommandStrGenerator = VariableListGenerator('FORTRANPPCOMSTR', 'F77PPCOMSTR', '_FORTRANPPCOMSTRD')
|
||||
ShFortranGenerator = VariableListGenerator('SHFORTRAN', 'SHF77', 'FORTRAN', 'F77', '_FORTRAND')
|
||||
ShFortranFlagsGenerator = VariableListGenerator('SHFORTRANFLAGS', 'SHF77FLAGS')
|
||||
ShFortranCommandGenerator = VariableListGenerator('SHFORTRANCOM', 'SHF77COM', '_SHFORTRANCOMD')
|
||||
ShFortranCommandStrGenerator = VariableListGenerator('SHFORTRANCOMSTR', 'SHF77COMSTR', '_SHFORTRANCOMSTRD')
|
||||
ShFortranPPCommandGenerator = VariableListGenerator('SHFORTRANPPCOM', 'SHF77PPCOM', '_SHFORTRANPPCOMD')
|
||||
ShFortranPPCommandStrGenerator = VariableListGenerator('SHFORTRANPPCOMSTR', 'SHF77PPCOMSTR', '_SHFORTRANPPCOMSTRD')
|
||||
|
||||
#
|
||||
FortranAction = SCons.Action.Action('$_FORTRANCOMG ')
|
||||
FortranPPAction = SCons.Action.Action('$_FORTRANPPCOMG ')
|
||||
ShFortranAction = SCons.Action.Action('$_SHFORTRANCOMG ')
|
||||
ShFortranPPAction = SCons.Action.Action('$_SHFORTRANPPCOMG ')
|
||||
FortranAction = SCons.Action.Action('$_FORTRANCOMG ', '$_FORTRANCOMSTRG')
|
||||
FortranPPAction = SCons.Action.Action('$_FORTRANPPCOMG ', '$_FORTRANPPCOMSTRG')
|
||||
ShFortranAction = SCons.Action.Action('$_SHFORTRANCOMG ', '$_SHFORTRANCOMSTRG')
|
||||
ShFortranPPAction = SCons.Action.Action('$_SHFORTRANPPCOMG ', '$_SHFORTRANPPCOMSTRG')
|
||||
|
||||
def add_to_env(env):
|
||||
"""Add Builders and construction variables for Fortran to an Environment."""
|
||||
|
@ -122,14 +128,18 @@ def add_to_env(env):
|
|||
env['_FORTRANG'] = FortranGenerator
|
||||
env['_FORTRANFLAGSG'] = FortranFlagsGenerator
|
||||
env['_FORTRANCOMG'] = FortranCommandGenerator
|
||||
env['_FORTRANCOMSTRG'] = FortranCommandStrGenerator
|
||||
env['_FORTRANPPCOMG'] = FortranPPCommandGenerator
|
||||
env['_FORTRANPPCOMSTRG'] = FortranPPCommandStrGenerator
|
||||
|
||||
env['_SHFORTRANG'] = ShFortranGenerator
|
||||
env['_SHFORTRANFLAGSG'] = ShFortranFlagsGenerator
|
||||
env['_SHFORTRANCOMG'] = ShFortranCommandGenerator
|
||||
env['_SHFORTRANCOMSTRG'] = ShFortranCommandStrGenerator
|
||||
env['_SHFORTRANPPCOMG'] = ShFortranPPCommandGenerator
|
||||
env['_SHFORTRANPPCOMSTRG'] = ShFortranPPCommandStrGenerator
|
||||
|
||||
env['_FORTRANINCFLAGS'] = '$( ${_concat(INCPREFIX, FORTRANPATH, INCSUFFIX, __env__, RDirs)} $)'
|
||||
env['_FORTRANINCFLAGS'] = '$( ${_concat(INCPREFIX, FORTRANPATH, INCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)'
|
||||
|
||||
env['FORTRANMODPREFIX'] = '' # like $LIBPREFIX
|
||||
env['FORTRANMODSUFFIX'] = '.mod' # like $LIBSUFFIX
|
||||
|
@ -137,7 +147,7 @@ def add_to_env(env):
|
|||
env['FORTRANMODDIR'] = '' # where the compiler should place .mod files
|
||||
env['FORTRANMODDIRPREFIX'] = '' # some prefix to $FORTRANMODDIR - similar to $INCPREFIX
|
||||
env['FORTRANMODDIRSUFFIX'] = '' # some suffix to $FORTRANMODDIR - similar to $INCSUFFIX
|
||||
env['_FORTRANMODFLAG'] = '$( ${_concat(FORTRANMODDIRPREFIX, FORTRANMODDIR, FORTRANMODDIRSUFFIX, __env__)} $)'
|
||||
env['_FORTRANMODFLAG'] = '$( ${_concat(FORTRANMODDIRPREFIX, FORTRANMODDIR, FORTRANMODDIRSUFFIX, __env__, RDirs)} $)'
|
||||
|
||||
env.AppendUnique(FORTRANSUFFIXES = FortranSuffixes + FortranPPSuffixes)
|
||||
|
||||
|
@ -155,10 +165,10 @@ def add_to_env(env):
|
|||
static_obj.add_emitter(suffix, FortranEmitter)
|
||||
shared_obj.add_emitter(suffix, ShFortranEmitter)
|
||||
|
||||
env['_FORTRANCOMD'] = '$_FORTRANG $_FORTRANFLAGSG $_FORTRANINCFLAGS $_FORTRANMODFLAG -c -o $TARGET $SOURCES'
|
||||
env['_FORTRANPPCOMD'] = '$_FORTRANG $_FORTRANFLAGSG $CPPFLAGS $_CPPDEFFLAGS $_FORTRANINCFLAGS $_FORTRANMODFLAG -c -o $TARGET $SOURCES'
|
||||
env['_SHFORTRANCOMD'] = '$_SHFORTRANG $_SHFORTRANFLAGSG $_FORTRANINCFLAGS $_FORTRANMODFLAG -c -o $TARGET $SOURCES'
|
||||
env['_SHFORTRANPPCOMD'] = '$_SHFORTRANG $_SHFORTRANFLAGSG $CPPFLAGS $_CPPDEFFLAGS $_FORTRANINCFLAGS $_FORTRANMODFLAG -c -o $TARGET $SOURCES'
|
||||
env['_FORTRANCOMD'] = '$_FORTRANG -o $TARGET -c $_FORTRANFLAGSG $_FORTRANINCFLAGS $_FORTRANMODFLAG $SOURCES'
|
||||
env['_FORTRANPPCOMD'] = '$_FORTRANG -o $TARGET -c $_FORTRANFLAGSG $CPPFLAGS $_CPPDEFFLAGS $_FORTRANINCFLAGS $_FORTRANMODFLAG $SOURCES'
|
||||
env['_SHFORTRANCOMD'] = '$_SHFORTRANG -o $TARGET -c $_SHFORTRANFLAGSG $_FORTRANINCFLAGS $_FORTRANMODFLAG $SOURCES'
|
||||
env['_SHFORTRANPPCOMD'] = '$_SHFORTRANG -o $TARGET -c $_SHFORTRANFLAGSG $CPPFLAGS $_CPPDEFFLAGS $_FORTRANINCFLAGS $_FORTRANMODFLAG $SOURCES'
|
||||
|
||||
def generate(env):
|
||||
import f77
|
|
@ -9,7 +9,7 @@ selection method.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -31,7 +31,7 @@ selection method.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/g++.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/g++.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import os.path
|
||||
import re
|
|
@ -9,7 +9,7 @@ selection method.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -31,7 +31,7 @@ selection method.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/g77.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/g77.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import f77
|
||||
|
|
@ -9,7 +9,7 @@ selection method.
|
|||
"""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
@ -31,15 +31,15 @@ selection method.
|
|||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/gas.py 0.96.1.D001 2004/08/23 09:55:29 knight"
|
||||
__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/gas.py 0.97.D001 2007/05/17 11:35:19 knight"
|
||||
|
||||
import as
|
||||
as_module = __import__('as', globals(), locals(), [])
|
||||
|
||||
assemblers = ['as', 'gas']
|
||||
|
||||
def generate(env):
|
||||
"""Add Builders and construction variables for as to an Environment."""
|
||||
as.generate(env)
|
||||
as_module.generate(env)
|
||||
|
||||
env['AS'] = env.Detect(assemblers) or 'as'
|
||||
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue