+ remove old scons
This commit is contained in:
parent
e2532bb5dc
commit
959516e56e
368 changed files with 0 additions and 93385 deletions
|
@ -1,25 +0,0 @@
|
||||||
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, 2005, 2006, 2007, 2008, 2009, 2010 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.
|
|
|
@ -1,204 +0,0 @@
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 The SCons Foundation
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
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:
|
|
||||||
|
|
||||||
http://www.scons.org/download.html
|
|
||||||
|
|
||||||
|
|
||||||
EXECUTION REQUIREMENTS
|
|
||||||
======================
|
|
||||||
|
|
||||||
Running SCons requires Python version 2.4 or later. There should be
|
|
||||||
no other dependencies or requirements to run SCons.
|
|
||||||
|
|
||||||
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
|
|
||||||
configuration of Environment construction variables.
|
|
||||||
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
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):
|
|
||||||
|
|
||||||
$ python scons.py
|
|
||||||
|
|
||||||
Or (if, for example, you installed this package in a subdirectory named
|
|
||||||
"scons"):
|
|
||||||
|
|
||||||
$ python scons/scons.py
|
|
||||||
|
|
||||||
That should be all you have to do. (If it isn't that simple, please let
|
|
||||||
us know!)
|
|
||||||
|
|
||||||
|
|
||||||
CONTENTS OF THIS PACKAGE
|
|
||||||
========================
|
|
||||||
|
|
||||||
This scons-local package consists of the following:
|
|
||||||
|
|
||||||
scons-LICENSE
|
|
||||||
A copy of the copyright and terms under which SCons is
|
|
||||||
distributed (the Open Source Initiative-approved MIT license).
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
scons-README
|
|
||||||
What you're looking at right now.
|
|
||||||
|
|
||||||
scons-local-{version}/
|
|
||||||
The SCons build engine. This is structured as a Python
|
|
||||||
library.
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
|
|
||||||
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).
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
Additional documentation for SCons is available at:
|
|
||||||
|
|
||||||
http://www.scons.org/doc.html
|
|
||||||
|
|
||||||
|
|
||||||
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:
|
|
||||||
|
|
||||||
This software is OSI Certified Open Source Software. OSI
|
|
||||||
Certified is a certification mark of the Open Source Initiative.
|
|
||||||
|
|
||||||
More information about OSI certifications and Open Source software is
|
|
||||||
available at:
|
|
||||||
|
|
||||||
http://www.opensource.org/
|
|
||||||
|
|
||||||
|
|
||||||
REPORTING BUGS
|
|
||||||
==============
|
|
||||||
|
|
||||||
You can report bugs either by following the "Tracker - Bugs" link
|
|
||||||
on the SCons project page:
|
|
||||||
|
|
||||||
http://sourceforge.net/projects/scons/
|
|
||||||
|
|
||||||
or by sending mail to the SCons developers mailing list:
|
|
||||||
|
|
||||||
scons-devel@lists.sourceforge.net
|
|
||||||
|
|
||||||
|
|
||||||
MAILING LISTS
|
|
||||||
=============
|
|
||||||
|
|
||||||
A mailing list for users of SCons is available. You may send questions
|
|
||||||
or comments to the list at:
|
|
||||||
|
|
||||||
scons-users@lists.sourceforge.net
|
|
||||||
|
|
||||||
You may subscribe to the scons-users mailing list at:
|
|
||||||
|
|
||||||
http://lists.sourceforge.net/lists/listinfo/scons-users
|
|
||||||
|
|
||||||
|
|
||||||
FOR MORE INFORMATION
|
|
||||||
====================
|
|
||||||
|
|
||||||
Check the SCons web site at:
|
|
||||||
|
|
||||||
http://www.scons.org/
|
|
||||||
|
|
||||||
|
|
||||||
AUTHOR INFO
|
|
||||||
===========
|
|
||||||
|
|
||||||
Steven Knight
|
|
||||||
knight at baldmt dot com
|
|
||||||
http://www.baldmt.com/~knight/
|
|
||||||
|
|
||||||
With plenty of help from the SCons Development team:
|
|
||||||
Chad Austin
|
|
||||||
Charles Crain
|
|
||||||
Steve Leblanc
|
|
||||||
Anthony Roach
|
|
||||||
Terrel Shumway
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,844 +0,0 @@
|
||||||
"""SCons.Builder
|
|
||||||
|
|
||||||
Builder object subsystem.
|
|
||||||
|
|
||||||
A Builder object is a callable that encapsulates information about how
|
|
||||||
to execute actions to create a target Node (file) from source Nodes
|
|
||||||
(files), and how to create those dependencies for tracking.
|
|
||||||
|
|
||||||
The main entry point here is the Builder() factory method. This provides
|
|
||||||
a procedural interface that creates the right underlying Builder object
|
|
||||||
based on the keyword arguments supplied and the types of the arguments.
|
|
||||||
|
|
||||||
The goal is for this external interface to be simple enough that the
|
|
||||||
vast majority of users can create new Builders as necessary to support
|
|
||||||
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 the Builder objects that we (or users) create.
|
|
||||||
|
|
||||||
There is also a proxy that looks like a Builder:
|
|
||||||
|
|
||||||
CompositeBuilder
|
|
||||||
|
|
||||||
This proxies for a Builder with an action that is actually a
|
|
||||||
dictionary that knows how to map file suffixes to a specific
|
|
||||||
action. This is so that we can invoke different actions
|
|
||||||
(compilers, compile options) for different flavors of source
|
|
||||||
files.
|
|
||||||
|
|
||||||
Builders and their proxies have the following public interface methods
|
|
||||||
used by other modules:
|
|
||||||
|
|
||||||
__call__()
|
|
||||||
THE public interface. Calling a Builder object (with the
|
|
||||||
use of internal helper methods) sets up the target and source
|
|
||||||
dependencies, appropriate mapping to a specific action, and the
|
|
||||||
environment manipulation necessary for overridden construction
|
|
||||||
variable. This also takes care of warning about possible mistakes
|
|
||||||
in keyword arguments.
|
|
||||||
|
|
||||||
add_emitter()
|
|
||||||
Adds an emitter for a specific file suffix, used by some Tool
|
|
||||||
modules to specify that (for example) a yacc invocation on a .y
|
|
||||||
can create a .h *and* a .c file.
|
|
||||||
|
|
||||||
add_action()
|
|
||||||
Adds an action for a specific file suffix, heavily used by
|
|
||||||
Tool modules to add their specific action(s) for turning
|
|
||||||
a source file into an object file to the global static
|
|
||||||
and shared object file Builders.
|
|
||||||
|
|
||||||
There are the following methods for internal use within this module:
|
|
||||||
|
|
||||||
_execute()
|
|
||||||
The internal method that handles the heavily lifting when a
|
|
||||||
Builder is called. This is used so that the __call__() methods
|
|
||||||
can set up warning about possible mistakes in keyword-argument
|
|
||||||
overrides, and *then* execute all of the steps necessary so that
|
|
||||||
the warnings only occur once.
|
|
||||||
|
|
||||||
get_name()
|
|
||||||
Returns the Builder's name within a specific Environment,
|
|
||||||
primarily used to try to return helpful information in error
|
|
||||||
messages.
|
|
||||||
|
|
||||||
adjust_suffix()
|
|
||||||
get_prefix()
|
|
||||||
get_suffix()
|
|
||||||
get_src_suffix()
|
|
||||||
set_src_suffix()
|
|
||||||
Miscellaneous stuff for handling the prefix and suffix
|
|
||||||
manipulation we use in turning source file names into target
|
|
||||||
file names.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Builder.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import UserDict
|
|
||||||
import UserList
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
class _Null:
|
|
||||||
pass
|
|
||||||
|
|
||||||
_null = _Null
|
|
||||||
|
|
||||||
class DictCmdGenerator(SCons.Util.Selector):
|
|
||||||
"""This is a callable class that can be used as a
|
|
||||||
command generator function. It holds on to a dictionary
|
|
||||||
mapping file suffixes to Actions. It uses that dictionary
|
|
||||||
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()
|
|
||||||
|
|
||||||
def add_action(self, suffix, action):
|
|
||||||
"""Add a suffix-action pair to the mapping.
|
|
||||||
"""
|
|
||||||
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))))
|
|
||||||
|
|
||||||
try:
|
|
||||||
ret = SCons.Util.Selector.__call__(self, env, source)
|
|
||||||
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' 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):
|
|
||||||
"""A callable dictionary that will, in turn, call the value it
|
|
||||||
finds if it can."""
|
|
||||||
def __call__(self, env, source):
|
|
||||||
value = SCons.Util.Selector.__call__(self, env, source)
|
|
||||||
if callable(value):
|
|
||||||
value = value(env, source)
|
|
||||||
return value
|
|
||||||
|
|
||||||
class DictEmitter(SCons.Util.Selector):
|
|
||||||
"""A callable dictionary that maps file suffixes to emitters.
|
|
||||||
When called, it finds the right emitter in its dictionary for the
|
|
||||||
suffix of the first source file, and calls that emitter to get the
|
|
||||||
right lists of targets and sources to return. If there's no emitter
|
|
||||||
for the suffix in its dictionary, the original target and source are
|
|
||||||
returned.
|
|
||||||
"""
|
|
||||||
def __call__(self, target, source, env):
|
|
||||||
emitter = SCons.Util.Selector.__call__(self, env, source)
|
|
||||||
if emitter:
|
|
||||||
target, source = emitter(target, source, env)
|
|
||||||
return (target, source)
|
|
||||||
|
|
||||||
class ListEmitter(UserList.UserList):
|
|
||||||
"""A callable list of emitters that calls each in sequence,
|
|
||||||
returning the result.
|
|
||||||
"""
|
|
||||||
def __call__(self, target, source, env):
|
|
||||||
for e in self.data:
|
|
||||||
target, source = e(target, source, env)
|
|
||||||
return (target, source)
|
|
||||||
|
|
||||||
# These are a common errors when calling a Builder;
|
|
||||||
# they are similar to the 'target' and 'source' keyword args to builders,
|
|
||||||
# so we issue warnings when we see them. The warnings can, of course,
|
|
||||||
# be disabled.
|
|
||||||
misleading_keywords = {
|
|
||||||
'targets' : 'target',
|
|
||||||
'sources' : 'source',
|
|
||||||
}
|
|
||||||
|
|
||||||
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 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():
|
|
||||||
if misleading_keywords.has_key(k):
|
|
||||||
alt = misleading_keywords[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):
|
|
||||||
"""A factory for builder objects."""
|
|
||||||
composite = None
|
|
||||||
if kw.has_key('generator'):
|
|
||||||
if kw.has_key('action'):
|
|
||||||
raise UserError, "You must not specify both an action and a generator."
|
|
||||||
kw['action'] = SCons.Action.CommandGeneratorAction(kw['generator'], {})
|
|
||||||
del kw['generator']
|
|
||||||
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']
|
|
||||||
if SCons.Util.is_String(emitter):
|
|
||||||
# This allows users to pass in an Environment
|
|
||||||
# variable reference (like "$FOO") as an emitter.
|
|
||||||
# We will look in that Environment variable for
|
|
||||||
# a callable to use as the actual emitter.
|
|
||||||
var = SCons.Util.get_environment_var(emitter)
|
|
||||||
if not var:
|
|
||||||
raise UserError, "Supplied emitter '%s' does not appear to refer to an Environment variable" % emitter
|
|
||||||
kw['emitter'] = EmitterProxy(var)
|
|
||||||
elif SCons.Util.is_Dict(emitter):
|
|
||||||
kw['emitter'] = DictEmitter(emitter)
|
|
||||||
elif SCons.Util.is_List(emitter):
|
|
||||||
kw['emitter'] = ListEmitter(emitter)
|
|
||||||
|
|
||||||
result = apply(BuilderBase, (), kw)
|
|
||||||
|
|
||||||
if not composite is None:
|
|
||||||
result = CompositeBuilder(result, composite)
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
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" % t
|
|
||||||
if t.has_explicit_builder():
|
|
||||||
if not t.env is None and not t.env is 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:
|
|
||||||
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:
|
|
||||||
msg = "Two environments with different actions were specified for the same target: %s" % t
|
|
||||||
raise UserError, msg
|
|
||||||
if builder.multi:
|
|
||||||
if t.builder != builder:
|
|
||||||
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:
|
|
||||||
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))
|
|
||||||
|
|
||||||
class EmitterProxy:
|
|
||||||
"""This is a callable class that can act as a
|
|
||||||
Builder emitter. It holds on to a string that
|
|
||||||
is a key into an Environment dictionary, and will
|
|
||||||
look there at actual build time to see if it holds
|
|
||||||
a callable. If so, we will call that as the actual
|
|
||||||
emitter."""
|
|
||||||
def __init__(self, var):
|
|
||||||
self.var = SCons.Util.to_String(var)
|
|
||||||
|
|
||||||
def __call__(self, target, source, env):
|
|
||||||
emitter = self.var
|
|
||||||
|
|
||||||
# Recursively substitute the variable.
|
|
||||||
# We can't use env.subst() because it deals only
|
|
||||||
# in strings. Maybe we should change that?
|
|
||||||
while SCons.Util.is_String(emitter) and env.has_key(emitter):
|
|
||||||
emitter = env[emitter]
|
|
||||||
if callable(emitter):
|
|
||||||
target, source = emitter(target, source, env)
|
|
||||||
elif SCons.Util.is_List(emitter):
|
|
||||||
for e in emitter:
|
|
||||||
target, source = e(target, source, env)
|
|
||||||
|
|
||||||
return (target, source)
|
|
||||||
|
|
||||||
|
|
||||||
def __cmp__(self, other):
|
|
||||||
return cmp(self.var, other.var)
|
|
||||||
|
|
||||||
class BuilderBase:
|
|
||||||
"""Base class for Builders, objects that create output
|
|
||||||
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 = 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 = None,
|
|
||||||
ensure_suffix = False,
|
|
||||||
**overrides):
|
|
||||||
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.env = env
|
|
||||||
self.single_source = single_source
|
|
||||||
if overrides.has_key('overrides'):
|
|
||||||
SCons.Warnings.warn(SCons.Warnings.DeprecatedWarning,
|
|
||||||
"The \"overrides\" keyword to Builder() creation has been deprecated;\n" +\
|
|
||||||
"\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.ensure_suffix = ensure_suffix
|
|
||||||
|
|
||||||
self.target_factory = target_factory
|
|
||||||
self.source_factory = source_factory
|
|
||||||
self.target_scanner = target_scanner
|
|
||||||
self.source_scanner = source_scanner
|
|
||||||
|
|
||||||
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 src_builder is None:
|
|
||||||
src_builder = []
|
|
||||||
elif 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"
|
|
||||||
|
|
||||||
def get_name(self, env):
|
|
||||||
"""Attempts to get the name of the Builder.
|
|
||||||
|
|
||||||
Look at the BUILDERS variable of env, expecting it to be a
|
|
||||||
dictionary containing this Builder, and return the key of the
|
|
||||||
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, 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, 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 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 _adjustixes(self, files, pre, suf, ensure_suffix=False):
|
|
||||||
if not files:
|
|
||||||
return []
|
|
||||||
result = []
|
|
||||||
if not SCons.Util.is_List(files):
|
|
||||||
files = [files]
|
|
||||||
|
|
||||||
for f in files:
|
|
||||||
if SCons.Util.is_String(f):
|
|
||||||
f = SCons.Util.adjustixes(f, pre, suf, ensure_suffix)
|
|
||||||
result.append(f)
|
|
||||||
return result
|
|
||||||
|
|
||||||
def _create_nodes(self, env, target = None, source = None):
|
|
||||||
"""Create and return lists of target and source nodes.
|
|
||||||
"""
|
|
||||||
src_suf = self.get_src_suffix(env)
|
|
||||||
|
|
||||||
target_factory = env.get_factory(self.target_factory)
|
|
||||||
source_factory = env.get_factory(self.source_factory)
|
|
||||||
|
|
||||||
source = self._adjustixes(source, None, src_suf)
|
|
||||||
slist = env.arg2nodes(source, source_factory)
|
|
||||||
|
|
||||||
pre = self.get_prefix(env, slist)
|
|
||||||
suf = self.get_suffix(env, slist)
|
|
||||||
|
|
||||||
if target is None:
|
|
||||||
try:
|
|
||||||
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])
|
|
||||||
except IndexError:
|
|
||||||
tlist = []
|
|
||||||
else:
|
|
||||||
splitext = lambda S,self=self,env=env: self.splitext(S,env)
|
|
||||||
tlist = [ t_from_s(pre, suf, splitext) ]
|
|
||||||
else:
|
|
||||||
target = self._adjustixes(target, pre, suf, self.ensure_suffix)
|
|
||||||
tlist = env.arg2nodes(target, target_factory, target=target, source=source)
|
|
||||||
|
|
||||||
if self.emitter:
|
|
||||||
# The emitter is going to do str(node), but because we're
|
|
||||||
# being called *from* a builder invocation, the new targets
|
|
||||||
# don't yet have a builder set on them and will look like
|
|
||||||
# source files. Fool the emitter's str() calls by setting
|
|
||||||
# up a temporary builder on the new targets.
|
|
||||||
new_targets = []
|
|
||||||
for t in tlist:
|
|
||||||
if not t.is_derived():
|
|
||||||
t.builder_set(self)
|
|
||||||
new_targets.append(t)
|
|
||||||
|
|
||||||
orig_tlist = tlist[:]
|
|
||||||
orig_slist = slist[:]
|
|
||||||
|
|
||||||
target, source = self.emitter(target=tlist, source=slist, env=env)
|
|
||||||
|
|
||||||
# Now delete the temporary builders that we attached to any
|
|
||||||
# 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_set(None)
|
|
||||||
|
|
||||||
# Have to call arg2nodes yet again, since it is legal for
|
|
||||||
# emitters to spit out strings as well as Node instances.
|
|
||||||
tlist = env.arg2nodes(target, target_factory,
|
|
||||||
target=orig_tlist, source=orig_slist)
|
|
||||||
slist = env.arg2nodes(source, source_factory,
|
|
||||||
target=orig_tlist, source=orig_slist)
|
|
||||||
|
|
||||||
return tlist, slist
|
|
||||||
|
|
||||||
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 len(source) > 1 and target is None:
|
|
||||||
result = []
|
|
||||||
if target is None: target = [None]*len(source)
|
|
||||||
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 SCons.Node.NodeList(result)
|
|
||||||
|
|
||||||
overwarn.warn()
|
|
||||||
|
|
||||||
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:
|
|
||||||
get_executor = self.get_single_executor
|
|
||||||
executor = get_executor(env, tlist, slist, executor_kw)
|
|
||||||
|
|
||||||
# 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)
|
|
||||||
|
|
||||||
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 [ '.', '_', '$' ]:
|
|
||||||
return '.' + suff
|
|
||||||
return suff
|
|
||||||
|
|
||||||
def get_prefix(self, env, sources=[]):
|
|
||||||
prefix = self.prefix
|
|
||||||
if callable(prefix):
|
|
||||||
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)
|
|
||||||
return env.subst(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 ]
|
|
||||||
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."""
|
|
||||||
ret = self.src_suffixes(env)
|
|
||||||
if not ret:
|
|
||||||
return ''
|
|
||||||
return ret[0]
|
|
||||||
|
|
||||||
def add_emitter(self, suffix, emitter):
|
|
||||||
"""Add a suffix-emitter mapping to this Builder.
|
|
||||||
|
|
||||||
This assumes that emitter has been initialized with an
|
|
||||||
appropriate dictionary type, and will throw a TypeError if
|
|
||||||
not, so the caller is responsible for knowing that this is an
|
|
||||||
appropriate method to call for the Builder in question.
|
|
||||||
"""
|
|
||||||
self.emitter[suffix] = emitter
|
|
||||||
|
|
||||||
def add_src_builder(self, builder):
|
|
||||||
"""
|
|
||||||
Add a new Builder to the list of src_builders.
|
|
||||||
|
|
||||||
This requires wiping out cached values so that the computed
|
|
||||||
lists of source suffixes get re-calculated.
|
|
||||||
"""
|
|
||||||
self._memo = {}
|
|
||||||
self.src_builder.append(builder)
|
|
||||||
|
|
||||||
def _get_sdict(self, 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.
|
|
||||||
|
|
||||||
This dictionary is used for each target specified, so we save a
|
|
||||||
lot of extra computation by memoizing it for each construction
|
|
||||||
environment.
|
|
||||||
|
|
||||||
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."
|
|
||||||
|
|
||||||
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 = {}
|
|
||||||
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={}):
|
|
||||||
sdict = self._get_sdict(env)
|
|
||||||
|
|
||||||
src_suffixes = self.src_suffixes(env)
|
|
||||||
|
|
||||||
lengths = list(set(map(len, src_suffixes)))
|
|
||||||
|
|
||||||
def match_src_suffix(name, src_suffixes=src_suffixes, lengths=lengths):
|
|
||||||
node_suffixes = map(lambda l, n=name: n[-l:], lengths)
|
|
||||||
for suf in src_suffixes:
|
|
||||||
if suf in node_suffixes:
|
|
||||||
return suf
|
|
||||||
return None
|
|
||||||
|
|
||||||
result = []
|
|
||||||
for s in SCons.Util.flatten(source):
|
|
||||||
if SCons.Util.is_String(s):
|
|
||||||
match_suffix = match_src_suffix(env.subst(s))
|
|
||||||
if not match_suffix and not '.' in s:
|
|
||||||
src_suf = self.get_src_suffix(env)
|
|
||||||
s = self._adjustixes(s, None, src_suf)[0]
|
|
||||||
else:
|
|
||||||
match_suffix = match_src_suffix(s.name)
|
|
||||||
if match_suffix:
|
|
||||||
try:
|
|
||||||
bld = sdict[match_suffix]
|
|
||||||
except KeyError:
|
|
||||||
result.append(s)
|
|
||||||
else:
|
|
||||||
tlist = bld._execute(env, None, [s], 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:
|
|
||||||
mss = lambda t, m=match_src_suffix: m(t.name)
|
|
||||||
tlist = filter(mss, tlist)
|
|
||||||
result.extend(tlist)
|
|
||||||
else:
|
|
||||||
result.append(s)
|
|
||||||
|
|
||||||
source_factory = env.get_factory(self.source_factory)
|
|
||||||
|
|
||||||
return env.arg2nodes(result, source_factory)
|
|
||||||
|
|
||||||
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):
|
|
||||||
"""
|
|
||||||
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):
|
|
||||||
try:
|
|
||||||
bld = env['BUILDERS'][bld]
|
|
||||||
except KeyError:
|
|
||||||
continue
|
|
||||||
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):
|
|
||||||
"""
|
|
||||||
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):
|
|
||||||
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):
|
|
||||||
"""A Builder Proxy whose main purpose is to always have
|
|
||||||
a DictCmdGenerator as its action, and to provide access
|
|
||||||
to the DictCmdGenerator's add_action() method.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, builder, cmdgen):
|
|
||||||
if __debug__: logInstanceCreation(self, 'Builder.CompositeBuilder')
|
|
||||||
SCons.Util.Proxy.__init__(self, builder)
|
|
||||||
|
|
||||||
# cmdgen should always be an instance of DictCmdGenerator.
|
|
||||||
self.cmdgen = cmdgen
|
|
||||||
self.builder = builder
|
|
||||||
|
|
||||||
def add_action(self, suffix, action):
|
|
||||||
self.cmdgen.add_action(suffix, action)
|
|
||||||
self.set_src_suffix(self.cmdgen.src_suffixes())
|
|
|
@ -1,217 +0,0 @@
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/CacheDir.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
__doc__ = """
|
|
||||||
CacheDir support
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os.path
|
|
||||||
import stat
|
|
||||||
import string
|
|
||||||
import sys
|
|
||||||
|
|
||||||
import SCons.Action
|
|
||||||
|
|
||||||
cache_enabled = True
|
|
||||||
cache_debug = False
|
|
||||||
cache_force = False
|
|
||||||
cache_show = False
|
|
||||||
|
|
||||||
def CacheRetrieveFunc(target, source, env):
|
|
||||||
t = target[0]
|
|
||||||
fs = t.fs
|
|
||||||
cd = env.get_CacheDir()
|
|
||||||
cachedir, cachefile = cd.cachepath(t)
|
|
||||||
if not fs.exists(cachefile):
|
|
||||||
cd.CacheDebug('CacheRetrieve(%s): %s not in cache\n', t, cachefile)
|
|
||||||
return 1
|
|
||||||
cd.CacheDebug('CacheRetrieve(%s): retrieving from %s\n', t, cachefile)
|
|
||||||
if SCons.Action.execute_actions:
|
|
||||||
if fs.islink(cachefile):
|
|
||||||
fs.symlink(fs.readlink(cachefile), t.path)
|
|
||||||
else:
|
|
||||||
env.copy_from_cache(cachefile, t.path)
|
|
||||||
st = fs.stat(cachefile)
|
|
||||||
fs.chmod(t.path, stat.S_IMODE(st[stat.ST_MODE]) | stat.S_IWRITE)
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def CacheRetrieveString(target, source, env):
|
|
||||||
t = target[0]
|
|
||||||
fs = t.fs
|
|
||||||
cd = env.get_CacheDir()
|
|
||||||
cachedir, cachefile = cd.cachepath(t)
|
|
||||||
if t.fs.exists(cachefile):
|
|
||||||
return "Retrieved `%s' from cache" % t.path
|
|
||||||
return None
|
|
||||||
|
|
||||||
CacheRetrieve = SCons.Action.Action(CacheRetrieveFunc, CacheRetrieveString)
|
|
||||||
|
|
||||||
CacheRetrieveSilent = SCons.Action.Action(CacheRetrieveFunc, None)
|
|
||||||
|
|
||||||
def CachePushFunc(target, source, env):
|
|
||||||
t = target[0]
|
|
||||||
if t.nocache:
|
|
||||||
return
|
|
||||||
fs = t.fs
|
|
||||||
cd = env.get_CacheDir()
|
|
||||||
cachedir, cachefile = cd.cachepath(t)
|
|
||||||
if fs.exists(cachefile):
|
|
||||||
# Don't bother copying it if it's already there. Note that
|
|
||||||
# usually this "shouldn't happen" because if the file already
|
|
||||||
# existed in cache, we'd have retrieved the file from there,
|
|
||||||
# not built it. This can happen, though, in a race, if some
|
|
||||||
# other person running the same build pushes their copy to
|
|
||||||
# the cache after we decide we need to build it but before our
|
|
||||||
# build completes.
|
|
||||||
cd.CacheDebug('CachePush(%s): %s already exists in cache\n', t, cachefile)
|
|
||||||
return
|
|
||||||
|
|
||||||
cd.CacheDebug('CachePush(%s): pushing to %s\n', t, cachefile)
|
|
||||||
|
|
||||||
tempfile = cachefile+'.tmp'+str(os.getpid())
|
|
||||||
errfmt = "Unable to copy %s to cache. Cache file is %s"
|
|
||||||
|
|
||||||
if not fs.isdir(cachedir):
|
|
||||||
try:
|
|
||||||
fs.makedirs(cachedir)
|
|
||||||
except EnvironmentError:
|
|
||||||
# We may have received an exception because another process
|
|
||||||
# has beaten us creating the directory.
|
|
||||||
if not fs.isdir(cachedir):
|
|
||||||
msg = errfmt % (str(target), cachefile)
|
|
||||||
raise SCons.Errors.EnvironmentError, msg
|
|
||||||
|
|
||||||
try:
|
|
||||||
if fs.islink(t.path):
|
|
||||||
fs.symlink(fs.readlink(t.path), tempfile)
|
|
||||||
else:
|
|
||||||
fs.copy2(t.path, tempfile)
|
|
||||||
fs.rename(tempfile, cachefile)
|
|
||||||
st = fs.stat(t.path)
|
|
||||||
fs.chmod(cachefile, stat.S_IMODE(st[stat.ST_MODE]) | stat.S_IWRITE)
|
|
||||||
except EnvironmentError:
|
|
||||||
# It's possible someone else tried writing the file at the
|
|
||||||
# same time we did, or else that there was some problem like
|
|
||||||
# the CacheDir being on a separate file system that's full.
|
|
||||||
# In any case, inability to push a file to cache doesn't affect
|
|
||||||
# the correctness of the build, so just print a warning.
|
|
||||||
msg = errfmt % (str(target), cachefile)
|
|
||||||
SCons.Warnings.warn(SCons.Warnings.CacheWriteErrorWarning, msg)
|
|
||||||
|
|
||||||
CachePush = SCons.Action.Action(CachePushFunc, None)
|
|
||||||
|
|
||||||
class CacheDir:
|
|
||||||
|
|
||||||
def __init__(self, path):
|
|
||||||
try:
|
|
||||||
import hashlib
|
|
||||||
except ImportError:
|
|
||||||
msg = "No hashlib or MD5 module available, CacheDir() not supported"
|
|
||||||
SCons.Warnings.warn(SCons.Warnings.NoMD5ModuleWarning, msg)
|
|
||||||
self.path = None
|
|
||||||
else:
|
|
||||||
self.path = path
|
|
||||||
self.current_cache_debug = None
|
|
||||||
self.debugFP = None
|
|
||||||
|
|
||||||
def CacheDebug(self, fmt, target, cachefile):
|
|
||||||
if cache_debug != self.current_cache_debug:
|
|
||||||
if cache_debug == '-':
|
|
||||||
self.debugFP = sys.stdout
|
|
||||||
elif cache_debug:
|
|
||||||
self.debugFP = open(cache_debug, 'w')
|
|
||||||
else:
|
|
||||||
self.debugFP = None
|
|
||||||
self.current_cache_debug = cache_debug
|
|
||||||
if self.debugFP:
|
|
||||||
self.debugFP.write(fmt % (target, os.path.split(cachefile)[1]))
|
|
||||||
|
|
||||||
def is_enabled(self):
|
|
||||||
return (cache_enabled and not self.path is None)
|
|
||||||
|
|
||||||
def cachepath(self, node):
|
|
||||||
"""
|
|
||||||
"""
|
|
||||||
if not self.is_enabled():
|
|
||||||
return None, None
|
|
||||||
|
|
||||||
sig = node.get_cachedir_bsig()
|
|
||||||
subdir = string.upper(sig[0])
|
|
||||||
dir = os.path.join(self.path, subdir)
|
|
||||||
return dir, os.path.join(dir, sig)
|
|
||||||
|
|
||||||
def retrieve(self, node):
|
|
||||||
"""
|
|
||||||
This method is called from multiple threads in a parallel build,
|
|
||||||
so only do thread safe stuff here. Do thread unsafe stuff in
|
|
||||||
built().
|
|
||||||
|
|
||||||
Note that there's a special trick here with the execute flag
|
|
||||||
(one that's not normally done for other actions). Basically
|
|
||||||
if the user requested a no_exec (-n) build, then
|
|
||||||
SCons.Action.execute_actions is set to 0 and when any action
|
|
||||||
is called, it does its showing but then just returns zero
|
|
||||||
instead of actually calling the action execution operation.
|
|
||||||
The problem for caching is that if the file does NOT exist in
|
|
||||||
cache then the CacheRetrieveString won't return anything to
|
|
||||||
show for the task, but the Action.__call__ won't call
|
|
||||||
CacheRetrieveFunc; instead it just returns zero, which makes
|
|
||||||
the code below think that the file *was* successfully
|
|
||||||
retrieved from the cache, therefore it doesn't do any
|
|
||||||
subsequent building. However, the CacheRetrieveString didn't
|
|
||||||
print anything because it didn't actually exist in the cache,
|
|
||||||
and no more build actions will be performed, so the user just
|
|
||||||
sees nothing. The fix is to tell Action.__call__ to always
|
|
||||||
execute the CacheRetrieveFunc and then have the latter
|
|
||||||
explicitly check SCons.Action.execute_actions itself.
|
|
||||||
"""
|
|
||||||
if not self.is_enabled():
|
|
||||||
return False
|
|
||||||
|
|
||||||
retrieved = False
|
|
||||||
|
|
||||||
if cache_show:
|
|
||||||
if CacheRetrieveSilent(node, [], node.get_build_env(), execute=1) == 0:
|
|
||||||
node.build(presub=0, execute=0)
|
|
||||||
retrieved = 1
|
|
||||||
else:
|
|
||||||
if CacheRetrieve(node, [], node.get_build_env(), execute=1) == 0:
|
|
||||||
retrieved = 1
|
|
||||||
if retrieved:
|
|
||||||
# Record build signature information, but don't
|
|
||||||
# push it out to cache. (We just got it from there!)
|
|
||||||
node.set_state(SCons.Node.executed)
|
|
||||||
SCons.Node.Node.built(node)
|
|
||||||
|
|
||||||
return retrieved
|
|
||||||
|
|
||||||
def push(self, node):
|
|
||||||
if not self.is_enabled():
|
|
||||||
return
|
|
||||||
return CachePush(node, [], node.get_build_env())
|
|
||||||
|
|
||||||
def push_if_forced(self, node):
|
|
||||||
if cache_force:
|
|
||||||
return self.push(node)
|
|
|
@ -1,778 +0,0 @@
|
||||||
"""SCons.Conftest
|
|
||||||
|
|
||||||
Autoconf-like configuration support; low level implementation of tests.
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2003 Stichting NLnet Labs
|
|
||||||
# Copyright (c) 2001, 2002, 2003 Steven Knight
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
#
|
|
||||||
|
|
||||||
#
|
|
||||||
# The purpose of this module is to define how a check is to be performed.
|
|
||||||
# Use one of the Check...() functions below.
|
|
||||||
#
|
|
||||||
|
|
||||||
#
|
|
||||||
# A context class is used that defines functions for carrying out the tests,
|
|
||||||
# logging and messages. The following methods and members must be present:
|
|
||||||
#
|
|
||||||
# context.Display(msg) Function called to print messages that are normally
|
|
||||||
# displayed for the user. Newlines are explicitly used.
|
|
||||||
# The text should also be written to the logfile!
|
|
||||||
#
|
|
||||||
# context.Log(msg) Function called to write to a log file.
|
|
||||||
#
|
|
||||||
# context.BuildProg(text, ext)
|
|
||||||
# Function called to build a program, using "ext" for the
|
|
||||||
# file extention. Must return an empty string for
|
|
||||||
# success, an error message for failure.
|
|
||||||
# For reliable test results building should be done just
|
|
||||||
# like an actual program would be build, using the same
|
|
||||||
# command and arguments (including configure results so
|
|
||||||
# far).
|
|
||||||
#
|
|
||||||
# context.CompileProg(text, ext)
|
|
||||||
# Function called to compile a program, using "ext" for
|
|
||||||
# the file extention. Must return an empty string for
|
|
||||||
# success, an error message for failure.
|
|
||||||
# For reliable test results compiling should be done just
|
|
||||||
# like an actual source file would be compiled, using the
|
|
||||||
# same command and arguments (including configure results
|
|
||||||
# so far).
|
|
||||||
#
|
|
||||||
# context.AppendLIBS(lib_name_list)
|
|
||||||
# Append "lib_name_list" to the value of LIBS.
|
|
||||||
# "lib_namelist" is a list of strings.
|
|
||||||
# Return the value of LIBS before changing it (any type
|
|
||||||
# can be used, it is passed to SetLIBS() later.
|
|
||||||
#
|
|
||||||
# context.SetLIBS(value)
|
|
||||||
# Set LIBS to "value". The type of "value" is what
|
|
||||||
# AppendLIBS() returned.
|
|
||||||
# Return the value of LIBS before changing it (any type
|
|
||||||
# can be used, it is passed to SetLIBS() later.
|
|
||||||
#
|
|
||||||
# context.headerfilename
|
|
||||||
# Name of file to append configure results to, usually
|
|
||||||
# "confdefs.h".
|
|
||||||
# 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.
|
|
||||||
# Normally contains "CC", "LIBS", "CPPFLAGS", etc.
|
|
||||||
#
|
|
||||||
# context.havedict Dictionary holding results from the tests that are to
|
|
||||||
# be used inside a program.
|
|
||||||
# Names often start with "HAVE_". These are zero
|
|
||||||
# (feature not present) or one (feature present). Other
|
|
||||||
# variables may have any value, e.g., "PERLVERSION" can
|
|
||||||
# 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
|
|
||||||
#
|
|
||||||
|
|
||||||
# Generic remarks:
|
|
||||||
# - When a language is specified which is not supported the test fails. The
|
|
||||||
# message is a bit different, because not all the arguments for the normal
|
|
||||||
# message are available yet (chicken-egg problem).
|
|
||||||
|
|
||||||
|
|
||||||
def CheckBuilder(context, text = None, language = None):
|
|
||||||
"""
|
|
||||||
Configure check to see if the compiler works.
|
|
||||||
Note that this uses the current value of compiler and linker flags, make
|
|
||||||
sure $CFLAGS, $CPPFLAGS and $LIBS are set correctly.
|
|
||||||
"language" should be "C" or "C++" and is used to select the compiler.
|
|
||||||
Default is "C".
|
|
||||||
"text" may be used to specify the code to be build.
|
|
||||||
Returns an empty string for success, an error message for failure.
|
|
||||||
"""
|
|
||||||
lang, suffix, msg = _lang2suffix(language)
|
|
||||||
if msg:
|
|
||||||
context.Display("%s\n" % msg)
|
|
||||||
return msg
|
|
||||||
|
|
||||||
if not text:
|
|
||||||
text = """
|
|
||||||
int main() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
context.Display("Checking if building a %s file works... " % lang)
|
|
||||||
ret = context.BuildProg(text, suffix)
|
|
||||||
_YesNoResult(context, ret, None, text)
|
|
||||||
return ret
|
|
||||||
|
|
||||||
def CheckCC(context):
|
|
||||||
"""
|
|
||||||
Configure check for a working C compiler.
|
|
||||||
|
|
||||||
This checks whether the C compiler, as defined in the $CC construction
|
|
||||||
variable, can compile a C source file. It uses the current $CCCOM value
|
|
||||||
too, so that it can test against non working flags.
|
|
||||||
|
|
||||||
"""
|
|
||||||
context.Display("Checking whether the C compiler works")
|
|
||||||
text = """
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
ret = _check_empty_program(context, 'CC', text, 'C')
|
|
||||||
_YesNoResult(context, ret, None, text)
|
|
||||||
return ret
|
|
||||||
|
|
||||||
def CheckSHCC(context):
|
|
||||||
"""
|
|
||||||
Configure check for a working shared C compiler.
|
|
||||||
|
|
||||||
This checks whether the C compiler, as defined in the $SHCC construction
|
|
||||||
variable, can compile a C source file. It uses the current $SHCCCOM value
|
|
||||||
too, so that it can test against non working flags.
|
|
||||||
|
|
||||||
"""
|
|
||||||
context.Display("Checking whether the (shared) C compiler works")
|
|
||||||
text = """
|
|
||||||
int foo()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
ret = _check_empty_program(context, 'SHCC', text, 'C', use_shared = True)
|
|
||||||
_YesNoResult(context, ret, None, text)
|
|
||||||
return ret
|
|
||||||
|
|
||||||
def CheckCXX(context):
|
|
||||||
"""
|
|
||||||
Configure check for a working CXX compiler.
|
|
||||||
|
|
||||||
This checks whether the CXX compiler, as defined in the $CXX construction
|
|
||||||
variable, can compile a CXX source file. It uses the current $CXXCOM value
|
|
||||||
too, so that it can test against non working flags.
|
|
||||||
|
|
||||||
"""
|
|
||||||
context.Display("Checking whether the C++ compiler works")
|
|
||||||
text = """
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
ret = _check_empty_program(context, 'CXX', text, 'C++')
|
|
||||||
_YesNoResult(context, ret, None, text)
|
|
||||||
return ret
|
|
||||||
|
|
||||||
def CheckSHCXX(context):
|
|
||||||
"""
|
|
||||||
Configure check for a working shared CXX compiler.
|
|
||||||
|
|
||||||
This checks whether the CXX compiler, as defined in the $SHCXX construction
|
|
||||||
variable, can compile a CXX source file. It uses the current $SHCXXCOM value
|
|
||||||
too, so that it can test against non working flags.
|
|
||||||
|
|
||||||
"""
|
|
||||||
context.Display("Checking whether the (shared) C++ compiler works")
|
|
||||||
text = """
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
ret = _check_empty_program(context, 'SHCXX', text, 'C++', use_shared = True)
|
|
||||||
_YesNoResult(context, ret, None, text)
|
|
||||||
return ret
|
|
||||||
|
|
||||||
def _check_empty_program(context, comp, text, language, use_shared = False):
|
|
||||||
"""Return 0 on success, 1 otherwise."""
|
|
||||||
if not context.env.has_key(comp) or not context.env[comp]:
|
|
||||||
# The compiler construction variable is not set or empty
|
|
||||||
return 1
|
|
||||||
|
|
||||||
lang, suffix, msg = _lang2suffix(language)
|
|
||||||
if msg:
|
|
||||||
return 1
|
|
||||||
|
|
||||||
if use_shared:
|
|
||||||
return context.CompileSharedObject(text, suffix)
|
|
||||||
else:
|
|
||||||
return context.CompileProg(text, suffix)
|
|
||||||
|
|
||||||
|
|
||||||
def CheckFunc(context, function_name, header = None, language = None):
|
|
||||||
"""
|
|
||||||
Configure check for a function "function_name".
|
|
||||||
"language" should be "C" or "C++" and is used to select the compiler.
|
|
||||||
Default is "C".
|
|
||||||
Optional "header" can be defined to define a function prototype, include a
|
|
||||||
header file or anything else that comes before main().
|
|
||||||
Sets HAVE_function_name in context.havedict according to the result.
|
|
||||||
Note that this uses the current value of compiler and linker flags, make
|
|
||||||
sure $CFLAGS, $CPPFLAGS and $LIBS are set correctly.
|
|
||||||
Returns an empty string for success, an error message for failure.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Remarks from autoconf:
|
|
||||||
# - Don't include <ctype.h> because on OSF/1 3.0 it includes <sys/types.h>
|
|
||||||
# which includes <sys/select.h> which contains a prototype for select.
|
|
||||||
# Similarly for bzero.
|
|
||||||
# - assert.h is included to define __stub macros and hopefully few
|
|
||||||
# prototypes, which can conflict with char $1(); below.
|
|
||||||
# - Override any gcc2 internal prototype to avoid an error.
|
|
||||||
# - We use char for the function declaration because int might match the
|
|
||||||
# return type of a gcc2 builtin and then its argument prototype would
|
|
||||||
# still apply.
|
|
||||||
# - The GNU C library defines this for functions which it implements to
|
|
||||||
# always fail with ENOSYS. Some functions are actually named something
|
|
||||||
# starting with __ and the normal name is an alias.
|
|
||||||
|
|
||||||
if context.headerfilename:
|
|
||||||
includetext = '#include "%s"' % context.headerfilename
|
|
||||||
else:
|
|
||||||
includetext = ''
|
|
||||||
if not header:
|
|
||||||
header = """
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C"
|
|
||||||
#endif
|
|
||||||
char %s();""" % function_name
|
|
||||||
|
|
||||||
lang, suffix, msg = _lang2suffix(language)
|
|
||||||
if msg:
|
|
||||||
context.Display("Cannot check for %s(): %s\n" % (function_name, msg))
|
|
||||||
return msg
|
|
||||||
|
|
||||||
text = """
|
|
||||||
%(include)s
|
|
||||||
#include <assert.h>
|
|
||||||
%(hdr)s
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
#if defined (__stub_%(name)s) || defined (__stub___%(name)s)
|
|
||||||
fail fail fail
|
|
||||||
#else
|
|
||||||
%(name)s();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
""" % { 'name': function_name,
|
|
||||||
'include': includetext,
|
|
||||||
'hdr': header }
|
|
||||||
|
|
||||||
context.Display("Checking for %s function %s()... " % (lang, function_name))
|
|
||||||
ret = context.BuildProg(text, suffix)
|
|
||||||
_YesNoResult(context, ret, "HAVE_" + function_name, text,
|
|
||||||
"Define to 1 if the system has the function `%s'." %\
|
|
||||||
function_name)
|
|
||||||
return ret
|
|
||||||
|
|
||||||
|
|
||||||
def CheckHeader(context, header_name, header = None, language = None,
|
|
||||||
include_quotes = None):
|
|
||||||
"""
|
|
||||||
Configure check for a C or C++ header file "header_name".
|
|
||||||
Optional "header" can be defined to do something before including the
|
|
||||||
header file (unusual, supported for consistency).
|
|
||||||
"language" should be "C" or "C++" and is used to select the compiler.
|
|
||||||
Default is "C".
|
|
||||||
Sets HAVE_header_name in context.havedict according to the result.
|
|
||||||
Note that this uses the current value of compiler and linker flags, make
|
|
||||||
sure $CFLAGS and $CPPFLAGS are set correctly.
|
|
||||||
Returns an empty string for success, an error message for failure.
|
|
||||||
"""
|
|
||||||
# Why compile the program instead of just running the preprocessor?
|
|
||||||
# It is possible that the header file exists, but actually using it may
|
|
||||||
# fail (e.g., because it depends on other header files). Thus this test is
|
|
||||||
# more strict. It may require using the "header" argument.
|
|
||||||
#
|
|
||||||
# Use <> by default, because the check is normally used for system header
|
|
||||||
# files. SCons passes '""' to overrule this.
|
|
||||||
|
|
||||||
# Include "confdefs.h" first, so that the header can use HAVE_HEADER_H.
|
|
||||||
if context.headerfilename:
|
|
||||||
includetext = '#include "%s"\n' % context.headerfilename
|
|
||||||
else:
|
|
||||||
includetext = ''
|
|
||||||
if not header:
|
|
||||||
header = ""
|
|
||||||
|
|
||||||
lang, suffix, msg = _lang2suffix(language)
|
|
||||||
if msg:
|
|
||||||
context.Display("Cannot check for header file %s: %s\n"
|
|
||||||
% (header_name, msg))
|
|
||||||
return msg
|
|
||||||
|
|
||||||
if not include_quotes:
|
|
||||||
include_quotes = "<>"
|
|
||||||
|
|
||||||
text = "%s%s\n#include %s%s%s\n\n" % (includetext, header,
|
|
||||||
include_quotes[0], header_name, include_quotes[1])
|
|
||||||
|
|
||||||
context.Display("Checking for %s header file %s... " % (lang, header_name))
|
|
||||||
ret = context.CompileProg(text, suffix)
|
|
||||||
_YesNoResult(context, ret, "HAVE_" + header_name, text,
|
|
||||||
"Define to 1 if you have the <%s> header file." % header_name)
|
|
||||||
return ret
|
|
||||||
|
|
||||||
|
|
||||||
def CheckType(context, type_name, fallback = None,
|
|
||||||
header = None, language = None):
|
|
||||||
"""
|
|
||||||
Configure check for a C or C++ type "type_name".
|
|
||||||
Optional "header" can be defined to include a header file.
|
|
||||||
"language" should be "C" or "C++" and is used to select the compiler.
|
|
||||||
Default is "C".
|
|
||||||
Sets HAVE_type_name in context.havedict according to the result.
|
|
||||||
Note that this uses the current value of compiler and linker flags, make
|
|
||||||
sure $CFLAGS, $CPPFLAGS and $LIBS are set correctly.
|
|
||||||
Returns an empty string for success, an error message for failure.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Include "confdefs.h" first, so that the header can use HAVE_HEADER_H.
|
|
||||||
if context.headerfilename:
|
|
||||||
includetext = '#include "%s"' % context.headerfilename
|
|
||||||
else:
|
|
||||||
includetext = ''
|
|
||||||
if not header:
|
|
||||||
header = ""
|
|
||||||
|
|
||||||
lang, suffix, msg = _lang2suffix(language)
|
|
||||||
if msg:
|
|
||||||
context.Display("Cannot check for %s type: %s\n" % (type_name, msg))
|
|
||||||
return msg
|
|
||||||
|
|
||||||
# Remarks from autoconf about this test:
|
|
||||||
# - Grepping for the type in include files is not reliable (grep isn't
|
|
||||||
# portable anyway).
|
|
||||||
# - Using "TYPE my_var;" doesn't work for const qualified types in C++.
|
|
||||||
# Adding an initializer is not valid for some C++ classes.
|
|
||||||
# - Using the type as parameter to a function either fails for K&$ C or for
|
|
||||||
# C++.
|
|
||||||
# - Using "TYPE *my_var;" is valid in C for some types that are not
|
|
||||||
# declared (struct something).
|
|
||||||
# - Using "sizeof(TYPE)" is valid when TYPE is actually a variable.
|
|
||||||
# - Using the previous two together works reliably.
|
|
||||||
text = """
|
|
||||||
%(include)s
|
|
||||||
%(header)s
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
if ((%(name)s *) 0)
|
|
||||||
return 0;
|
|
||||||
if (sizeof (%(name)s))
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
""" % { 'include': includetext,
|
|
||||||
'header': header,
|
|
||||||
'name': type_name }
|
|
||||||
|
|
||||||
context.Display("Checking for %s type %s... " % (lang, type_name))
|
|
||||||
ret = context.BuildProg(text, suffix)
|
|
||||||
_YesNoResult(context, ret, "HAVE_" + type_name, text,
|
|
||||||
"Define to 1 if the system has the type `%s'." % type_name)
|
|
||||||
if ret and fallback and context.headerfilename:
|
|
||||||
f = open(context.headerfilename, "a")
|
|
||||||
f.write("typedef %s %s;\n" % (fallback, type_name))
|
|
||||||
f.close()
|
|
||||||
|
|
||||||
return ret
|
|
||||||
|
|
||||||
def CheckTypeSize(context, type_name, header = None, language = None, expect = None):
|
|
||||||
"""This check can be used to get the size of a given type, or to check whether
|
|
||||||
the type is of expected size.
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
- type : str
|
|
||||||
the type to check
|
|
||||||
- includes : sequence
|
|
||||||
list of headers to include in the test code before testing the type
|
|
||||||
- language : str
|
|
||||||
'C' or 'C++'
|
|
||||||
- expect : int
|
|
||||||
if given, will test wether the type has the given number of bytes.
|
|
||||||
If not given, will automatically find the size.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
status : int
|
|
||||||
0 if the check failed, or the found size of the type if the check succeeded."""
|
|
||||||
|
|
||||||
# Include "confdefs.h" first, so that the header can use HAVE_HEADER_H.
|
|
||||||
if context.headerfilename:
|
|
||||||
includetext = '#include "%s"' % context.headerfilename
|
|
||||||
else:
|
|
||||||
includetext = ''
|
|
||||||
|
|
||||||
if not header:
|
|
||||||
header = ""
|
|
||||||
|
|
||||||
lang, suffix, msg = _lang2suffix(language)
|
|
||||||
if msg:
|
|
||||||
context.Display("Cannot check for %s type: %s\n" % (type_name, msg))
|
|
||||||
return msg
|
|
||||||
|
|
||||||
src = includetext + header
|
|
||||||
if not expect is None:
|
|
||||||
# Only check if the given size is the right one
|
|
||||||
context.Display('Checking %s is %d bytes... ' % (type_name, expect))
|
|
||||||
|
|
||||||
# test code taken from autoconf: this is a pretty clever hack to find that
|
|
||||||
# a type is of a given size using only compilation. This speeds things up
|
|
||||||
# quite a bit compared to straightforward code using TryRun
|
|
||||||
src = src + r"""
|
|
||||||
typedef %s scons_check_type;
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
static int test_array[1 - 2 * !(((long int) (sizeof(scons_check_type))) == %d)];
|
|
||||||
test_array[0] = 0;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
st = context.CompileProg(src % (type_name, expect), suffix)
|
|
||||||
if not st:
|
|
||||||
context.Display("yes\n")
|
|
||||||
_Have(context, "SIZEOF_%s" % type_name, expect,
|
|
||||||
"The size of `%s', as computed by sizeof." % type_name)
|
|
||||||
return expect
|
|
||||||
else:
|
|
||||||
context.Display("no\n")
|
|
||||||
_LogFailed(context, src, st)
|
|
||||||
return 0
|
|
||||||
else:
|
|
||||||
# Only check if the given size is the right one
|
|
||||||
context.Message('Checking size of %s ... ' % type_name)
|
|
||||||
|
|
||||||
# We have to be careful with the program we wish to test here since
|
|
||||||
# compilation will be attempted using the current environment's flags.
|
|
||||||
# So make sure that the program will compile without any warning. For
|
|
||||||
# example using: 'int main(int argc, char** argv)' will fail with the
|
|
||||||
# '-Wall -Werror' flags since the variables argc and argv would not be
|
|
||||||
# used in the program...
|
|
||||||
#
|
|
||||||
src = src + """
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
int main() {
|
|
||||||
printf("%d", (int)sizeof(""" + type_name + """));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
st, out = context.RunProg(src, suffix)
|
|
||||||
try:
|
|
||||||
size = int(out)
|
|
||||||
except ValueError:
|
|
||||||
# If cannot convert output of test prog to an integer (the size),
|
|
||||||
# something went wront, so just fail
|
|
||||||
st = 1
|
|
||||||
size = 0
|
|
||||||
|
|
||||||
if not st:
|
|
||||||
context.Display("yes\n")
|
|
||||||
_Have(context, "SIZEOF_%s" % type_name, size,
|
|
||||||
"The size of `%s', as computed by sizeof." % type_name)
|
|
||||||
return size
|
|
||||||
else:
|
|
||||||
context.Display("no\n")
|
|
||||||
_LogFailed(context, src, st)
|
|
||||||
return 0
|
|
||||||
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def CheckDeclaration(context, symbol, includes = None, language = None):
|
|
||||||
"""Checks whether symbol is declared.
|
|
||||||
|
|
||||||
Use the same test as autoconf, that is test whether the symbol is defined
|
|
||||||
as a macro or can be used as an r-value.
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
symbol : str
|
|
||||||
the symbol to check
|
|
||||||
includes : str
|
|
||||||
Optional "header" can be defined to include a header file.
|
|
||||||
language : str
|
|
||||||
only C and C++ supported.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
status : bool
|
|
||||||
True if the check failed, False if succeeded."""
|
|
||||||
|
|
||||||
# Include "confdefs.h" first, so that the header can use HAVE_HEADER_H.
|
|
||||||
if context.headerfilename:
|
|
||||||
includetext = '#include "%s"' % context.headerfilename
|
|
||||||
else:
|
|
||||||
includetext = ''
|
|
||||||
|
|
||||||
if not includes:
|
|
||||||
includes = ""
|
|
||||||
|
|
||||||
lang, suffix, msg = _lang2suffix(language)
|
|
||||||
if msg:
|
|
||||||
context.Display("Cannot check for declaration %s: %s\n" % (type_name, msg))
|
|
||||||
return msg
|
|
||||||
|
|
||||||
src = includetext + includes
|
|
||||||
context.Display('Checking whether %s is declared... ' % symbol)
|
|
||||||
|
|
||||||
src = src + r"""
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
#ifndef %s
|
|
||||||
(void) %s;
|
|
||||||
#endif
|
|
||||||
;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
""" % (symbol, symbol)
|
|
||||||
|
|
||||||
st = context.CompileProg(src, suffix)
|
|
||||||
_YesNoResult(context, st, "HAVE_DECL_" + symbol, src,
|
|
||||||
"Set to 1 if %s is defined." % symbol)
|
|
||||||
return st
|
|
||||||
|
|
||||||
def CheckLib(context, libs, func_name = None, header = None,
|
|
||||||
extra_libs = None, call = None, language = None, autoadd = 1):
|
|
||||||
"""
|
|
||||||
Configure check for a C or C++ libraries "libs". Searches through
|
|
||||||
the list of libraries, until one is found where the test succeeds.
|
|
||||||
Tests if "func_name" or "call" exists in the library. Note: if it exists
|
|
||||||
in another library the test succeeds anyway!
|
|
||||||
Optional "header" can be defined to include a header file. If not given a
|
|
||||||
default prototype for "func_name" is added.
|
|
||||||
Optional "extra_libs" is a list of library names to be added after
|
|
||||||
"lib_name" in the build command. To be used for libraries that "lib_name"
|
|
||||||
depends on.
|
|
||||||
Optional "call" replaces the call to "func_name" in the test code. It must
|
|
||||||
consist of complete C statements, including a trailing ";".
|
|
||||||
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
|
|
||||||
sure $CFLAGS, $CPPFLAGS and $LIBS are set correctly.
|
|
||||||
Returns an empty string for success, an error message for failure.
|
|
||||||
"""
|
|
||||||
# Include "confdefs.h" first, so that the header can use HAVE_HEADER_H.
|
|
||||||
if context.headerfilename:
|
|
||||||
includetext = '#include "%s"' % context.headerfilename
|
|
||||||
else:
|
|
||||||
includetext = ''
|
|
||||||
if not header:
|
|
||||||
header = ""
|
|
||||||
|
|
||||||
text = """
|
|
||||||
%s
|
|
||||||
%s""" % (includetext, header)
|
|
||||||
|
|
||||||
# Add a function declaration if needed.
|
|
||||||
if func_name and func_name != "main":
|
|
||||||
if not header:
|
|
||||||
text = text + """
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C"
|
|
||||||
#endif
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
""" % (call or "")
|
|
||||||
|
|
||||||
if call:
|
|
||||||
i = string.find(call, "\n")
|
|
||||||
if i > 0:
|
|
||||||
calltext = call[:i] + ".."
|
|
||||||
elif call[-1] == ';':
|
|
||||||
calltext = call[:-1]
|
|
||||||
else:
|
|
||||||
calltext = call
|
|
||||||
|
|
||||||
for lib_name in libs:
|
|
||||||
|
|
||||||
lang, suffix, msg = _lang2suffix(language)
|
|
||||||
if msg:
|
|
||||||
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:
|
|
||||||
l.extend(extra_libs)
|
|
||||||
oldLIBS = context.AppendLIBS(l)
|
|
||||||
sym = "HAVE_LIB" + lib_name
|
|
||||||
else:
|
|
||||||
oldLIBS = -1
|
|
||||||
sym = None
|
|
||||||
|
|
||||||
ret = context.BuildProg(text, suffix)
|
|
||||||
|
|
||||||
_YesNoResult(context, ret, sym, text,
|
|
||||||
"Define to 1 if you have the `%s' library." % lib_name)
|
|
||||||
if oldLIBS != -1 and (ret or not autoadd):
|
|
||||||
context.SetLIBS(oldLIBS)
|
|
||||||
|
|
||||||
if not ret:
|
|
||||||
return ret
|
|
||||||
|
|
||||||
return ret
|
|
||||||
|
|
||||||
#
|
|
||||||
# END OF PUBLIC FUNCTIONS
|
|
||||||
#
|
|
||||||
|
|
||||||
def _YesNoResult(context, ret, key, text, comment = None):
|
|
||||||
"""
|
|
||||||
Handle the result of a test with a "yes" or "no" result.
|
|
||||||
"ret" is the return value: empty if OK, error message when not.
|
|
||||||
"key" is the name of the symbol to be defined (HAVE_foo).
|
|
||||||
"text" is the source code of the program used for testing.
|
|
||||||
"comment" is the C comment to add above the line defining the symbol (the
|
|
||||||
comment is automatically put inside a /* */). If None, no comment is added.
|
|
||||||
"""
|
|
||||||
if key:
|
|
||||||
_Have(context, key, not ret, comment)
|
|
||||||
if ret:
|
|
||||||
context.Display("no\n")
|
|
||||||
_LogFailed(context, text, ret)
|
|
||||||
else:
|
|
||||||
context.Display("yes\n")
|
|
||||||
|
|
||||||
|
|
||||||
def _Have(context, key, have, comment = None):
|
|
||||||
"""
|
|
||||||
Store result of a test in context.havedict and context.headerfilename.
|
|
||||||
"key" is a "HAVE_abc" name. It is turned into all CAPITALS and non-
|
|
||||||
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 */".
|
|
||||||
Adding "undef" is what autoconf does. Not useful for the
|
|
||||||
compiler, but it shows that the test was done.
|
|
||||||
number - Feature is defined to this number "#define key have".
|
|
||||||
Doesn't work for 0 or 1, use a string then.
|
|
||||||
string - Feature is defined to this string "#define key have".
|
|
||||||
Give "have" as is should appear in the header file, include quotes
|
|
||||||
when desired and escape special characters!
|
|
||||||
"""
|
|
||||||
key_up = string.upper(key)
|
|
||||||
key_up = re.sub('[^A-Z0-9_]', '_', key_up)
|
|
||||||
context.havedict[key_up] = have
|
|
||||||
if have == 1:
|
|
||||||
line = "#define %s 1\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 comment is not None:
|
|
||||||
lines = "\n/* %s */\n" % comment + line
|
|
||||||
else:
|
|
||||||
lines = "\n" + line
|
|
||||||
|
|
||||||
if context.headerfilename:
|
|
||||||
f = open(context.headerfilename, "a")
|
|
||||||
f.write(lines)
|
|
||||||
f.close()
|
|
||||||
elif hasattr(context,'config_h'):
|
|
||||||
context.config_h = context.config_h + lines
|
|
||||||
|
|
||||||
|
|
||||||
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] == '':
|
|
||||||
lines = lines[:-1] # remove trailing empty line
|
|
||||||
n = 1
|
|
||||||
for line in lines:
|
|
||||||
context.Log("%d: %s\n" % (n, line))
|
|
||||||
n = n + 1
|
|
||||||
if LogErrorMessages:
|
|
||||||
context.Log("Error message: %s\n" % msg)
|
|
||||||
|
|
||||||
|
|
||||||
def _lang2suffix(lang):
|
|
||||||
"""
|
|
||||||
Convert a language name to a suffix.
|
|
||||||
When "lang" is empty or None C is assumed.
|
|
||||||
Returns a tuple (lang, suffix, None) when it works.
|
|
||||||
For an unrecognized language returns (None, None, msg).
|
|
||||||
Where:
|
|
||||||
lang = the unified language name
|
|
||||||
suffix = the suffix, including the leading dot
|
|
||||||
msg = an error message
|
|
||||||
"""
|
|
||||||
if not lang or lang in ["C", "c"]:
|
|
||||||
return ("C", ".c", None)
|
|
||||||
if lang in ["c++", "C++", "cpp", "CXX", "cxx"]:
|
|
||||||
return ("C++", ".cpp", None)
|
|
||||||
|
|
||||||
return None, None, "Unsupported language: %s" % lang
|
|
||||||
|
|
||||||
|
|
||||||
# vim: set sw=4 et sts=4 tw=79 fo+=l:
|
|
|
@ -1,216 +0,0 @@
|
||||||
"""SCons.Debug
|
|
||||||
|
|
||||||
Code for debugging SCons internal things. Not everything here is
|
|
||||||
guaranteed to work all the way back to Python 1.5.2, and shouldn't be
|
|
||||||
needed by most users.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Debug.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import os
|
|
||||||
import string
|
|
||||||
import sys
|
|
||||||
|
|
||||||
# Recipe 14.10 from the Python Cookbook.
|
|
||||||
try:
|
|
||||||
import weakref
|
|
||||||
except ImportError:
|
|
||||||
def logInstanceCreation(instance, name=None):
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
def logInstanceCreation(instance, name=None):
|
|
||||||
if name is None:
|
|
||||||
name = instance.__class__.__name__
|
|
||||||
if not tracked_classes.has_key(name):
|
|
||||||
tracked_classes[name] = []
|
|
||||||
tracked_classes[name].append(weakref.ref(instance))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
tracked_classes = {}
|
|
||||||
|
|
||||||
def string_to_classes(s):
|
|
||||||
if s == '*':
|
|
||||||
c = tracked_classes.keys()
|
|
||||||
c.sort()
|
|
||||||
return c
|
|
||||||
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])))
|
|
||||||
|
|
||||||
def listLoggedInstances(classes, file=sys.stdout):
|
|
||||||
for classname in string_to_classes(classes):
|
|
||||||
file.write('\n%s:\n' % classname)
|
|
||||||
for ref in tracked_classes[classname]:
|
|
||||||
obj = ref()
|
|
||||||
if obj is not None:
|
|
||||||
file.write(' %s\n' % repr(obj))
|
|
||||||
|
|
||||||
def dumpLoggedInstances(classes, file=sys.stdout):
|
|
||||||
for classname in string_to_classes(classes):
|
|
||||||
file.write('\n%s:\n' % classname)
|
|
||||||
for ref in tracked_classes[classname]:
|
|
||||||
obj = ref()
|
|
||||||
if obj is not None:
|
|
||||||
file.write(' %s:\n' % obj)
|
|
||||||
for key, value in obj.__dict__.items():
|
|
||||||
file.write(' %20s : %s\n' % (key, value))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if sys.platform[:5] == "linux":
|
|
||||||
# Linux doesn't actually support memory usage stats from getrusage().
|
|
||||||
def memory():
|
|
||||||
mstr = open('/proc/self/stat').read()
|
|
||||||
mstr = string.split(mstr)[22]
|
|
||||||
return int(mstr)
|
|
||||||
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]
|
|
||||||
|
|
||||||
# returns caller's stack
|
|
||||||
def caller_stack(*backlist):
|
|
||||||
import traceback
|
|
||||||
if not backlist:
|
|
||||||
backlist = [0]
|
|
||||||
result = []
|
|
||||||
for back in backlist:
|
|
||||||
tb = traceback.extract_stack(limit=3+back)
|
|
||||||
key = tb[0][:3]
|
|
||||||
result.append('%s:%d(%s)' % func_shorten(key))
|
|
||||||
return result
|
|
||||||
|
|
||||||
caller_bases = {}
|
|
||||||
caller_dicts = {}
|
|
||||||
|
|
||||||
# trace a caller's stack
|
|
||||||
def caller_trace(back=0):
|
|
||||||
import traceback
|
|
||||||
tb = traceback.extract_stack(limit=3+back)
|
|
||||||
tb.reverse()
|
|
||||||
callee = tb[1][:3]
|
|
||||||
caller_bases[callee] = caller_bases.get(callee, 0) + 1
|
|
||||||
for caller in tb[2:]:
|
|
||||||
caller = callee + caller[:3]
|
|
||||||
try:
|
|
||||||
entry = caller_dicts[callee]
|
|
||||||
except KeyError:
|
|
||||||
caller_dicts[callee] = entry = {}
|
|
||||||
entry[caller] = entry.get(caller, 0) + 1
|
|
||||||
callee = caller
|
|
||||||
|
|
||||||
# print a single caller and its callers, if any
|
|
||||||
def _dump_one_caller(key, file, level=0):
|
|
||||||
l = []
|
|
||||||
for c,v in caller_dicts[key].items():
|
|
||||||
l.append((-v,c))
|
|
||||||
l.sort()
|
|
||||||
leader = ' '*level
|
|
||||||
for v,c in l:
|
|
||||||
file.write("%s %6d %s:%d(%s)\n" % ((leader,-v) + func_shorten(c[-3:])))
|
|
||||||
if caller_dicts.has_key(c):
|
|
||||||
_dump_one_caller(c, file, level+1)
|
|
||||||
|
|
||||||
# print each call tree
|
|
||||||
def dump_caller_counts(file=sys.stdout):
|
|
||||||
keys = caller_bases.keys()
|
|
||||||
keys.sort()
|
|
||||||
for k in keys:
|
|
||||||
file.write("Callers of %s:%d(%s), %d calls:\n"
|
|
||||||
% (func_shorten(k) + (caller_bases[k],)))
|
|
||||||
_dump_one_caller(k, file)
|
|
||||||
|
|
||||||
shorten_list = [
|
|
||||||
( '/scons/SCons/', 1),
|
|
||||||
( '/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])
|
|
||||||
return (f[i:],)+func_tuple[1:]
|
|
||||||
return func_tuple
|
|
||||||
|
|
||||||
|
|
||||||
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)
|
|
||||||
fp.flush()
|
|
|
@ -1,463 +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, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Defaults.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import os
|
|
||||||
import os.path
|
|
||||||
import shutil
|
|
||||||
import stat
|
|
||||||
import string
|
|
||||||
import time
|
|
||||||
import types
|
|
||||||
import sys
|
|
||||||
|
|
||||||
import SCons.Action
|
|
||||||
import SCons.Builder
|
|
||||||
import SCons.CacheDir
|
|
||||||
import SCons.Environment
|
|
||||||
import SCons.PathList
|
|
||||||
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 _fetch_DefaultEnvironment(*args, **kw):
|
|
||||||
"""
|
|
||||||
Returns the already-created default construction environment.
|
|
||||||
"""
|
|
||||||
global _default_env
|
|
||||||
return _default_env
|
|
||||||
|
|
||||||
def DefaultEnvironment(*args, **kw):
|
|
||||||
"""
|
|
||||||
Initial public entry point for creating the default construction
|
|
||||||
Environment.
|
|
||||||
|
|
||||||
After creating the environment, we overwrite our name
|
|
||||||
(DefaultEnvironment) with the _fetch_DefaultEnvironment() function,
|
|
||||||
which more efficiently returns the initialized default construction
|
|
||||||
environment without checking for its existence.
|
|
||||||
|
|
||||||
(This function still exists with its _default_check because someone
|
|
||||||
else (*cough* Script/__init__.py *cough*) may keep a reference
|
|
||||||
to this function. So we can't use the fully functional idiom of
|
|
||||||
having the name originally be a something that *only* creates the
|
|
||||||
construction environment and then overwrites the name.)
|
|
||||||
"""
|
|
||||||
global _default_env
|
|
||||||
if not _default_env:
|
|
||||||
import SCons.Util
|
|
||||||
_default_env = apply(SCons.Environment.Environment, args, kw)
|
|
||||||
if SCons.Util.md5:
|
|
||||||
_default_env.Decider('MD5')
|
|
||||||
else:
|
|
||||||
_default_env.Decider('timestamp-match')
|
|
||||||
global DefaultEnvironment
|
|
||||||
DefaultEnvironment = _fetch_DefaultEnvironment
|
|
||||||
_default_env._CacheDir_path = None
|
|
||||||
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
|
|
||||||
|
|
||||||
# These aren't really tool scanners, so they don't quite belong with
|
|
||||||
# the rest of those in Tool/__init__.py, but I'm not sure where else
|
|
||||||
# they should go. Leave them 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
|
|
||||||
|
|
||||||
def get_paths_str(dest):
|
|
||||||
# If dest is a list, we need to manually call str() on each element
|
|
||||||
if SCons.Util.is_List(dest):
|
|
||||||
elem_strs = []
|
|
||||||
for element in dest:
|
|
||||||
elem_strs.append('"' + str(element) + '"')
|
|
||||||
return '[' + string.join(elem_strs, ', ') + ']'
|
|
||||||
else:
|
|
||||||
return '"' + str(dest) + '"'
|
|
||||||
|
|
||||||
def chmod_func(dest, mode):
|
|
||||||
SCons.Node.FS.invalidate_node_memos(dest)
|
|
||||||
if not SCons.Util.is_List(dest):
|
|
||||||
dest = [dest]
|
|
||||||
for element in dest:
|
|
||||||
os.chmod(str(element), mode)
|
|
||||||
|
|
||||||
def chmod_strfunc(dest, mode):
|
|
||||||
return 'Chmod(%s, 0%o)' % (get_paths_str(dest), mode)
|
|
||||||
|
|
||||||
Chmod = ActionFactory(chmod_func, chmod_strfunc)
|
|
||||||
|
|
||||||
def copy_func(dest, src):
|
|
||||||
SCons.Node.FS.invalidate_node_memos(dest)
|
|
||||||
if SCons.Util.is_List(src) and os.path.isdir(dest):
|
|
||||||
for file in src:
|
|
||||||
shutil.copy2(file, dest)
|
|
||||||
return 0
|
|
||||||
elif os.path.isfile(src):
|
|
||||||
return shutil.copy2(src, dest)
|
|
||||||
else:
|
|
||||||
return shutil.copytree(src, dest, 1)
|
|
||||||
|
|
||||||
Copy = ActionFactory(copy_func,
|
|
||||||
lambda dest, src: 'Copy("%s", "%s")' % (dest, src),
|
|
||||||
convert=str)
|
|
||||||
|
|
||||||
def delete_func(dest, must_exist=0):
|
|
||||||
SCons.Node.FS.invalidate_node_memos(dest)
|
|
||||||
if not SCons.Util.is_List(dest):
|
|
||||||
dest = [dest]
|
|
||||||
for entry in dest:
|
|
||||||
entry = str(entry)
|
|
||||||
if not must_exist and not os.path.exists(entry):
|
|
||||||
continue
|
|
||||||
if not os.path.exists(entry) or os.path.isfile(entry):
|
|
||||||
os.unlink(entry)
|
|
||||||
continue
|
|
||||||
else:
|
|
||||||
shutil.rmtree(entry, 1)
|
|
||||||
continue
|
|
||||||
|
|
||||||
def delete_strfunc(dest, must_exist=0):
|
|
||||||
return 'Delete(%s)' % get_paths_str(dest)
|
|
||||||
|
|
||||||
Delete = ActionFactory(delete_func, delete_strfunc)
|
|
||||||
|
|
||||||
def mkdir_func(dest):
|
|
||||||
SCons.Node.FS.invalidate_node_memos(dest)
|
|
||||||
if not SCons.Util.is_List(dest):
|
|
||||||
dest = [dest]
|
|
||||||
for entry in dest:
|
|
||||||
os.makedirs(str(entry))
|
|
||||||
|
|
||||||
Mkdir = ActionFactory(mkdir_func,
|
|
||||||
lambda dir: 'Mkdir(%s)' % get_paths_str(dir))
|
|
||||||
|
|
||||||
def move_func(dest, src):
|
|
||||||
SCons.Node.FS.invalidate_node_memos(dest)
|
|
||||||
SCons.Node.FS.invalidate_node_memos(src)
|
|
||||||
os.rename(src, dest)
|
|
||||||
|
|
||||||
Move = ActionFactory(move_func,
|
|
||||||
lambda dest, src: 'Move("%s", "%s")' % (dest, src),
|
|
||||||
convert=str)
|
|
||||||
|
|
||||||
def touch_func(dest):
|
|
||||||
SCons.Node.FS.invalidate_node_memos(dest)
|
|
||||||
if not SCons.Util.is_List(dest):
|
|
||||||
dest = [dest]
|
|
||||||
for file in dest:
|
|
||||||
file = str(file)
|
|
||||||
mtime = int(time.time())
|
|
||||||
if os.path.exists(file):
|
|
||||||
atime = os.path.getatime(file)
|
|
||||||
else:
|
|
||||||
open(file, 'w')
|
|
||||||
atime = mtime
|
|
||||||
os.utime(file, (atime, mtime))
|
|
||||||
|
|
||||||
Touch = ActionFactory(touch_func,
|
|
||||||
lambda file: 'Touch(%s)' % get_paths_str(file))
|
|
||||||
|
|
||||||
# Internal utility functions
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
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, stripprefixes, stripsuffixes, env, c=None):
|
|
||||||
"""
|
|
||||||
This is a wrapper around _concat()/_concat_ixes() that checks for the
|
|
||||||
existence of prefixes or suffixes on list elements and strips them
|
|
||||||
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
|
|
||||||
|
|
||||||
stripprefixes = map(env.subst, SCons.Util.flatten(stripprefixes))
|
|
||||||
stripsuffixes = map(env.subst, SCons.Util.flatten(stripsuffixes))
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
for stripprefix in stripprefixes:
|
|
||||||
lsp = len(stripprefix)
|
|
||||||
if l[:lsp] == stripprefix:
|
|
||||||
l = l[lsp:]
|
|
||||||
# Do not strip more than one prefix
|
|
||||||
break
|
|
||||||
|
|
||||||
for stripsuffix in stripsuffixes:
|
|
||||||
lss = len(stripsuffix)
|
|
||||||
if l[-lss:] == stripsuffix:
|
|
||||||
l = l[:-lss]
|
|
||||||
# Do not strip more than one suffix
|
|
||||||
break
|
|
||||||
|
|
||||||
stripped.append(l)
|
|
||||||
|
|
||||||
return c(prefix, stripped, suffix, env)
|
|
||||||
|
|
||||||
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:
|
|
||||||
# Don't start iterating with the current stack-frame to
|
|
||||||
# prevent creating reference cycles (f_back is safe).
|
|
||||||
frame = sys.exc_info()[2].tb_frame.f_back
|
|
||||||
variable = self.variable
|
|
||||||
while frame:
|
|
||||||
if frame.f_locals.has_key(variable):
|
|
||||||
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,
|
|
||||||
'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'),
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,198 +0,0 @@
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
"""SCons.Errors
|
|
||||||
|
|
||||||
This file contains the exception classes used to handle internal
|
|
||||||
and user errors in SCons.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Errors.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import SCons.Util
|
|
||||||
|
|
||||||
import exceptions
|
|
||||||
|
|
||||||
class BuildError(Exception):
|
|
||||||
""" Errors occuring while building.
|
|
||||||
|
|
||||||
BuildError have the following attributes:
|
|
||||||
|
|
||||||
Information about the cause of the build error:
|
|
||||||
-----------------------------------------------
|
|
||||||
|
|
||||||
errstr : a description of the error message
|
|
||||||
|
|
||||||
status : the return code of the action that caused the build
|
|
||||||
error. Must be set to a non-zero value even if the
|
|
||||||
build error is not due to an action returning a
|
|
||||||
non-zero returned code.
|
|
||||||
|
|
||||||
exitstatus : SCons exit status due to this build error.
|
|
||||||
Must be nonzero unless due to an explicit Exit()
|
|
||||||
call. Not always the same as status, since
|
|
||||||
actions return a status code that should be
|
|
||||||
respected, but SCons typically exits with 2
|
|
||||||
irrespective of the return value of the failed
|
|
||||||
action.
|
|
||||||
|
|
||||||
filename : The name of the file or directory that caused the
|
|
||||||
build error. Set to None if no files are associated with
|
|
||||||
this error. This might be different from the target
|
|
||||||
being built. For example, failure to create the
|
|
||||||
directory in which the target file will appear. It
|
|
||||||
can be None if the error is not due to a particular
|
|
||||||
filename.
|
|
||||||
|
|
||||||
exc_info : Info about exception that caused the build
|
|
||||||
error. Set to (None, None, None) if this build
|
|
||||||
error is not due to an exception.
|
|
||||||
|
|
||||||
|
|
||||||
Information about the cause of the location of the error:
|
|
||||||
---------------------------------------------------------
|
|
||||||
|
|
||||||
node : the error occured while building this target node(s)
|
|
||||||
|
|
||||||
executor : the executor that caused the build to fail (might
|
|
||||||
be None if the build failures is not due to the
|
|
||||||
executor failing)
|
|
||||||
|
|
||||||
action : the action that caused the build to fail (might be
|
|
||||||
None if the build failures is not due to the an
|
|
||||||
action failure)
|
|
||||||
|
|
||||||
command : the command line for the action that caused the
|
|
||||||
build to fail (might be None if the build failures
|
|
||||||
is not due to the an action failure)
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self,
|
|
||||||
node=None, errstr="Unknown error", status=2, exitstatus=2,
|
|
||||||
filename=None, executor=None, action=None, command=None,
|
|
||||||
exc_info=(None, None, None)):
|
|
||||||
|
|
||||||
self.errstr = errstr
|
|
||||||
self.status = status
|
|
||||||
self.exitstatus = exitstatus
|
|
||||||
self.filename = filename
|
|
||||||
self.exc_info = exc_info
|
|
||||||
|
|
||||||
self.node = node
|
|
||||||
self.executor = executor
|
|
||||||
self.action = action
|
|
||||||
self.command = command
|
|
||||||
|
|
||||||
Exception.__init__(self, node, errstr, status, exitstatus, filename,
|
|
||||||
executor, action, command, exc_info)
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
if self.filename:
|
|
||||||
return self.filename + ': ' + self.errstr
|
|
||||||
else:
|
|
||||||
return self.errstr
|
|
||||||
|
|
||||||
class InternalError(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class UserError(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class StopError(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class EnvironmentError(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class ExplicitExit(Exception):
|
|
||||||
def __init__(self, node=None, status=None, *args):
|
|
||||||
self.node = node
|
|
||||||
self.status = status
|
|
||||||
self.exitstatus = status
|
|
||||||
apply(Exception.__init__, (self,) + args)
|
|
||||||
|
|
||||||
def convert_to_BuildError(status, exc_info=None):
|
|
||||||
"""
|
|
||||||
Convert any return code a BuildError Exception.
|
|
||||||
|
|
||||||
`status' can either be a return code or an Exception.
|
|
||||||
The buildError.status we set here will normally be
|
|
||||||
used as the exit status of the "scons" process.
|
|
||||||
"""
|
|
||||||
if not exc_info and isinstance(status, Exception):
|
|
||||||
exc_info = (status.__class__, status, None)
|
|
||||||
|
|
||||||
if isinstance(status, BuildError):
|
|
||||||
buildError = status
|
|
||||||
buildError.exitstatus = 2 # always exit with 2 on build errors
|
|
||||||
elif isinstance(status, ExplicitExit):
|
|
||||||
status = status.status
|
|
||||||
errstr = 'Explicit exit, status %s' % status
|
|
||||||
buildError = BuildError(
|
|
||||||
errstr=errstr,
|
|
||||||
status=status, # might be 0, OK here
|
|
||||||
exitstatus=status, # might be 0, OK here
|
|
||||||
exc_info=exc_info)
|
|
||||||
# TODO(1.5):
|
|
||||||
#elif isinstance(status, (StopError, UserError)):
|
|
||||||
elif isinstance(status, StopError) or isinstance(status, UserError):
|
|
||||||
buildError = BuildError(
|
|
||||||
errstr=str(status),
|
|
||||||
status=2,
|
|
||||||
exitstatus=2,
|
|
||||||
exc_info=exc_info)
|
|
||||||
elif isinstance(status, exceptions.EnvironmentError):
|
|
||||||
# If an IOError/OSError happens, raise a BuildError.
|
|
||||||
# Report the name of the file or directory that caused the
|
|
||||||
# error, which might be different from the target being built
|
|
||||||
# (for example, failure to create the directory in which the
|
|
||||||
# target file will appear).
|
|
||||||
try: filename = status.filename
|
|
||||||
except AttributeError: filename = None
|
|
||||||
buildError = BuildError(
|
|
||||||
errstr=status.strerror,
|
|
||||||
status=status.errno,
|
|
||||||
exitstatus=2,
|
|
||||||
filename=filename,
|
|
||||||
exc_info=exc_info)
|
|
||||||
elif isinstance(status, Exception):
|
|
||||||
buildError = BuildError(
|
|
||||||
errstr='%s : %s' % (status.__class__.__name__, status),
|
|
||||||
status=2,
|
|
||||||
exitstatus=2,
|
|
||||||
exc_info=exc_info)
|
|
||||||
elif SCons.Util.is_String(status):
|
|
||||||
buildError = BuildError(
|
|
||||||
errstr=status,
|
|
||||||
status=2,
|
|
||||||
exitstatus=2)
|
|
||||||
else:
|
|
||||||
buildError = BuildError(
|
|
||||||
errstr="Error %s" % status,
|
|
||||||
status=status,
|
|
||||||
exitstatus=2)
|
|
||||||
|
|
||||||
#import sys
|
|
||||||
#sys.stderr.write("convert_to_BuildError: status %s => (errstr %s, status %s)"%(status,buildError.errstr, buildError.status))
|
|
||||||
return buildError
|
|
|
@ -1,393 +0,0 @@
|
||||||
"""SCons.Executor
|
|
||||||
|
|
||||||
A module for executing actions with specific lists of target and source
|
|
||||||
Nodes.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Executor.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import string
|
|
||||||
|
|
||||||
from SCons.Debug import logInstanceCreation
|
|
||||||
import SCons.Errors
|
|
||||||
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.sources_need_sorting = False
|
|
||||||
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
|
|
||||||
|
|
||||||
memoizer_counters.append(SCons.Memoize.CountValue('get_build_env'))
|
|
||||||
|
|
||||||
def get_build_env(self):
|
|
||||||
"""Fetch or create the appropriate build Environment
|
|
||||||
for this Executor.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
return self._memo['get_build_env']
|
|
||||||
except KeyError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# 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)
|
|
||||||
|
|
||||||
self._memo['get_build_env'] = build_env
|
|
||||||
|
|
||||||
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.get_sources())
|
|
||||||
|
|
||||||
def get_kw(self, kw={}):
|
|
||||||
result = self.builder_kw.copy()
|
|
||||||
result.update(kw)
|
|
||||||
return result
|
|
||||||
|
|
||||||
def do_nothing(self, target, kw):
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def do_execute(self, target, kw):
|
|
||||||
"""Actually execute the action list."""
|
|
||||||
env = self.get_build_env()
|
|
||||||
kw = self.get_kw(kw)
|
|
||||||
status = 0
|
|
||||||
for act in self.get_action_list():
|
|
||||||
status = apply(act, (self.targets, self.get_sources(), env), kw)
|
|
||||||
if isinstance(status, SCons.Errors.BuildError):
|
|
||||||
status.executor = self
|
|
||||||
raise status
|
|
||||||
elif status:
|
|
||||||
msg = "Error %s" % status
|
|
||||||
raise SCons.Errors.BuildError(
|
|
||||||
errstr=msg,
|
|
||||||
node=self.targets,
|
|
||||||
executor=self,
|
|
||||||
action=act)
|
|
||||||
return status
|
|
||||||
|
|
||||||
# use extra indirection because with new-style objects (Python 2.2
|
|
||||||
# and above) we can't override special methods, and nullify() needs
|
|
||||||
# to be able to do this.
|
|
||||||
|
|
||||||
def __call__(self, target, **kw):
|
|
||||||
return self.do_execute(target, 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."""
|
|
||||||
self.sources.extend(sources)
|
|
||||||
self.sources_need_sorting = True
|
|
||||||
|
|
||||||
def get_sources(self):
|
|
||||||
if self.sources_need_sorting:
|
|
||||||
self.sources = SCons.Util.uniquer_hashables(self.sources)
|
|
||||||
self.sources_need_sorting = False
|
|
||||||
return self.sources
|
|
||||||
|
|
||||||
def prepare(self):
|
|
||||||
"""
|
|
||||||
Preparatory checks for whether this Executor can go ahead
|
|
||||||
and (try to) build its targets.
|
|
||||||
"""
|
|
||||||
for s in self.get_sources():
|
|
||||||
if s.missing():
|
|
||||||
msg = "Source `%s' not found, needed by target `%s'."
|
|
||||||
raise SCons.Errors.StopError, msg % (s, self.targets[0])
|
|
||||||
|
|
||||||
def add_pre_action(self, action):
|
|
||||||
self.pre_actions.append(action)
|
|
||||||
|
|
||||||
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.get_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.get_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.get_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.
|
|
||||||
"""
|
|
||||||
env = self.get_build_env()
|
|
||||||
|
|
||||||
deps = []
|
|
||||||
if scanner:
|
|
||||||
for node in node_list:
|
|
||||||
node.disambiguate()
|
|
||||||
s = scanner.select(node)
|
|
||||||
if not s:
|
|
||||||
continue
|
|
||||||
path = self.get_build_scanner_path(s)
|
|
||||||
deps.extend(node.get_implicit_deps(env, s, path))
|
|
||||||
else:
|
|
||||||
kw = self.get_kw()
|
|
||||||
for node in node_list:
|
|
||||||
node.disambiguate()
|
|
||||||
scanner = node.get_env_scanner(env, kw)
|
|
||||||
if not scanner:
|
|
||||||
continue
|
|
||||||
scanner = scanner.select(node)
|
|
||||||
if not scanner:
|
|
||||||
continue
|
|
||||||
path = self.get_build_scanner_path(scanner)
|
|
||||||
deps.extend(node.get_implicit_deps(env, scanner, path))
|
|
||||||
|
|
||||||
deps.extend(self.get_implicit_deps())
|
|
||||||
|
|
||||||
for tgt in self.targets:
|
|
||||||
tgt.add_to_implicit(deps)
|
|
||||||
|
|
||||||
def _get_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.get_sources()
|
|
||||||
if ignore:
|
|
||||||
idict = {}
|
|
||||||
for i in ignore:
|
|
||||||
idict[i] = 1
|
|
||||||
sourcelist = filter(lambda s, i=idict: not i.has_key(s), 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
|
|
||||||
|
|
||||||
def get_implicit_deps(self):
|
|
||||||
"""Return the executor's implicit dependencies, i.e. the nodes of
|
|
||||||
the commands to be executed."""
|
|
||||||
result = []
|
|
||||||
build_env = self.get_build_env()
|
|
||||||
for act in self.get_action_list():
|
|
||||||
result.extend(act.get_implicit_deps(self.targets, self.get_sources(), build_env))
|
|
||||||
return result
|
|
||||||
|
|
||||||
nullenv = None
|
|
||||||
|
|
||||||
def get_NullEnvironment():
|
|
||||||
"""Use singleton pattern for Null Environments."""
|
|
||||||
global nullenv
|
|
||||||
|
|
||||||
import SCons.Util
|
|
||||||
class NullEnvironment(SCons.Util.Null):
|
|
||||||
import SCons.CacheDir
|
|
||||||
_CacheDir_path = None
|
|
||||||
_CacheDir = SCons.CacheDir.CacheDir(None)
|
|
||||||
def get_CacheDir(self):
|
|
||||||
return self._CacheDir
|
|
||||||
|
|
||||||
if not nullenv:
|
|
||||||
nullenv = NullEnvironment()
|
|
||||||
return nullenv
|
|
||||||
|
|
||||||
class Null:
|
|
||||||
"""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')
|
|
||||||
self.targets = kw['targets']
|
|
||||||
def get_build_env(self):
|
|
||||||
return get_NullEnvironment()
|
|
||||||
def get_build_scanner_path(self):
|
|
||||||
return None
|
|
||||||
def cleanup(self):
|
|
||||||
pass
|
|
||||||
def prepare(self):
|
|
||||||
pass
|
|
||||||
def get_unignored_sources(self, *args, **kw):
|
|
||||||
return tuple(())
|
|
||||||
def get_action_list(self):
|
|
||||||
return []
|
|
||||||
def __call__(self, *args, **kw):
|
|
||||||
return 0
|
|
||||||
def get_contents(self):
|
|
||||||
return ''
|
|
||||||
|
|
||||||
def _morph(self):
|
|
||||||
"""Morph this Null executor to a real Executor object."""
|
|
||||||
self.__class__ = Executor
|
|
||||||
self.__init__([], targets=self.targets)
|
|
||||||
|
|
||||||
# The following methods require morphing this Null Executor to a
|
|
||||||
# real Executor object.
|
|
||||||
|
|
||||||
def add_pre_action(self, action):
|
|
||||||
self._morph()
|
|
||||||
self.add_pre_action(action)
|
|
||||||
def add_post_action(self, action):
|
|
||||||
self._morph()
|
|
||||||
self.add_post_action(action)
|
|
||||||
def set_action_list(self, action):
|
|
||||||
self._morph()
|
|
||||||
self.set_action_list(action)
|
|
||||||
|
|
||||||
|
|
|
@ -1,429 +0,0 @@
|
||||||
"""SCons.Job
|
|
||||||
|
|
||||||
This module defines the Serial and Parallel classes that execute tasks to
|
|
||||||
complete a build. The Jobs class provides a higher level interface to start,
|
|
||||||
stop, and wait on jobs.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Job.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import os
|
|
||||||
import signal
|
|
||||||
|
|
||||||
import SCons.Errors
|
|
||||||
|
|
||||||
# The default stack size (in kilobytes) of the threads used to execute
|
|
||||||
# jobs in parallel.
|
|
||||||
#
|
|
||||||
# We use a stack size of 256 kilobytes. The default on some platforms
|
|
||||||
# is too large and prevents us from creating enough threads to fully
|
|
||||||
# parallelized the build. For example, the default stack size on linux
|
|
||||||
# is 8 MBytes.
|
|
||||||
|
|
||||||
explicit_stack_size = None
|
|
||||||
default_stack_size = 256
|
|
||||||
|
|
||||||
interrupt_msg = 'Build interrupted.'
|
|
||||||
|
|
||||||
|
|
||||||
class InterruptState:
|
|
||||||
def __init__(self):
|
|
||||||
self.interrupted = False
|
|
||||||
|
|
||||||
def set(self):
|
|
||||||
self.interrupted = True
|
|
||||||
|
|
||||||
def __call__(self):
|
|
||||||
return self.interrupted
|
|
||||||
|
|
||||||
|
|
||||||
class Jobs:
|
|
||||||
"""An instance of this class initializes N jobs, and provides
|
|
||||||
methods for starting, stopping, and waiting on all N jobs.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, num, taskmaster):
|
|
||||||
"""
|
|
||||||
create 'num' jobs using the given taskmaster.
|
|
||||||
|
|
||||||
If 'num' is 1 or less, then a serial job will be used,
|
|
||||||
otherwise a parallel job with 'num' worker threads will
|
|
||||||
be used.
|
|
||||||
|
|
||||||
The 'num_jobs' attribute will be set to the actual number of jobs
|
|
||||||
allocated. If more than one job is requested but the Parallel
|
|
||||||
class can't do it, it gets reset to 1. Wrapping interfaces that
|
|
||||||
care should check the value of 'num_jobs' after initialization.
|
|
||||||
"""
|
|
||||||
|
|
||||||
self.job = None
|
|
||||||
if num > 1:
|
|
||||||
stack_size = explicit_stack_size
|
|
||||||
if stack_size is None:
|
|
||||||
stack_size = default_stack_size
|
|
||||||
|
|
||||||
try:
|
|
||||||
self.job = Parallel(taskmaster, num, stack_size)
|
|
||||||
self.num_jobs = num
|
|
||||||
except NameError:
|
|
||||||
pass
|
|
||||||
if self.job is None:
|
|
||||||
self.job = Serial(taskmaster)
|
|
||||||
self.num_jobs = 1
|
|
||||||
|
|
||||||
def run(self, postfunc=lambda: None):
|
|
||||||
"""Run the jobs.
|
|
||||||
|
|
||||||
postfunc() will be invoked after the jobs has run. It will be
|
|
||||||
invoked even if the jobs are interrupted by a keyboard
|
|
||||||
interrupt (well, in fact by a signal such as either SIGINT,
|
|
||||||
SIGTERM or SIGHUP). The execution of postfunc() is protected
|
|
||||||
against keyboard interrupts and is guaranteed to run to
|
|
||||||
completion."""
|
|
||||||
self._setup_sig_handler()
|
|
||||||
try:
|
|
||||||
self.job.start()
|
|
||||||
finally:
|
|
||||||
postfunc()
|
|
||||||
self._reset_sig_handler()
|
|
||||||
|
|
||||||
def were_interrupted(self):
|
|
||||||
"""Returns whether the jobs were interrupted by a signal."""
|
|
||||||
return self.job.interrupted()
|
|
||||||
|
|
||||||
def _setup_sig_handler(self):
|
|
||||||
"""Setup an interrupt handler so that SCons can shutdown cleanly in
|
|
||||||
various conditions:
|
|
||||||
|
|
||||||
a) SIGINT: Keyboard interrupt
|
|
||||||
b) SIGTERM: kill or system shutdown
|
|
||||||
c) SIGHUP: Controlling shell exiting
|
|
||||||
|
|
||||||
We handle all of these cases by stopping the taskmaster. It
|
|
||||||
turns out that it very difficult to stop the build process
|
|
||||||
by throwing asynchronously an exception such as
|
|
||||||
KeyboardInterrupt. For example, the python Condition
|
|
||||||
variables (threading.Condition) and Queue's do not seem to
|
|
||||||
asynchronous-exception-safe. It would require adding a whole
|
|
||||||
bunch of try/finally block and except KeyboardInterrupt all
|
|
||||||
over the place.
|
|
||||||
|
|
||||||
Note also that we have to be careful to handle the case when
|
|
||||||
SCons forks before executing another process. In that case, we
|
|
||||||
want the child to exit immediately.
|
|
||||||
"""
|
|
||||||
def handler(signum, stack, self=self, parentpid=os.getpid()):
|
|
||||||
if os.getpid() == parentpid:
|
|
||||||
self.job.taskmaster.stop()
|
|
||||||
self.job.interrupted.set()
|
|
||||||
else:
|
|
||||||
os._exit(2)
|
|
||||||
|
|
||||||
self.old_sigint = signal.signal(signal.SIGINT, handler)
|
|
||||||
self.old_sigterm = signal.signal(signal.SIGTERM, handler)
|
|
||||||
try:
|
|
||||||
self.old_sighup = signal.signal(signal.SIGHUP, handler)
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def _reset_sig_handler(self):
|
|
||||||
"""Restore the signal handlers to their previous state (before the
|
|
||||||
call to _setup_sig_handler()."""
|
|
||||||
|
|
||||||
signal.signal(signal.SIGINT, self.old_sigint)
|
|
||||||
signal.signal(signal.SIGTERM, self.old_sigterm)
|
|
||||||
try:
|
|
||||||
signal.signal(signal.SIGHUP, self.old_sighup)
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
class Serial:
|
|
||||||
"""This class is used to execute tasks in series, and is more efficient
|
|
||||||
than Parallel, but is only appropriate for non-parallel builds. Only
|
|
||||||
one instance of this class should be in existence at a time.
|
|
||||||
|
|
||||||
This class is not thread safe.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, taskmaster):
|
|
||||||
"""Create a new serial 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 it failed to
|
|
||||||
execute (e.g. execute() raised an exception)."""
|
|
||||||
|
|
||||||
self.taskmaster = taskmaster
|
|
||||||
self.interrupted = InterruptState()
|
|
||||||
|
|
||||||
def start(self):
|
|
||||||
"""Start the job. This will begin pulling tasks from the taskmaster
|
|
||||||
and executing them, and return when there are no more tasks. If a task
|
|
||||||
fails to execute (i.e. execute() raises an exception), then the job will
|
|
||||||
stop."""
|
|
||||||
|
|
||||||
while 1:
|
|
||||||
task = self.taskmaster.next_task()
|
|
||||||
|
|
||||||
if task is None:
|
|
||||||
break
|
|
||||||
|
|
||||||
try:
|
|
||||||
task.prepare()
|
|
||||||
if task.needs_execute():
|
|
||||||
task.execute()
|
|
||||||
except:
|
|
||||||
if self.interrupted():
|
|
||||||
try:
|
|
||||||
raise SCons.Errors.BuildError(
|
|
||||||
task.targets[0], errstr=interrupt_msg)
|
|
||||||
except:
|
|
||||||
task.exception_set()
|
|
||||||
else:
|
|
||||||
task.exception_set()
|
|
||||||
|
|
||||||
# Let the failed() callback function arrange for the
|
|
||||||
# build to stop if that's appropriate.
|
|
||||||
task.failed()
|
|
||||||
else:
|
|
||||||
task.executed()
|
|
||||||
|
|
||||||
task.postprocess()
|
|
||||||
self.taskmaster.cleanup()
|
|
||||||
|
|
||||||
|
|
||||||
# Trap import failure so that everything in the Job module but the
|
|
||||||
# Parallel class (and its dependent classes) will work if the interpreter
|
|
||||||
# doesn't support threads.
|
|
||||||
try:
|
|
||||||
import Queue
|
|
||||||
import threading
|
|
||||||
except ImportError:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
class Worker(threading.Thread):
|
|
||||||
"""A worker thread waits on a task to be posted to its request queue,
|
|
||||||
dequeues the task, executes it, and posts a tuple including the task
|
|
||||||
and a boolean indicating whether the task executed successfully. """
|
|
||||||
|
|
||||||
def __init__(self, requestQueue, resultsQueue, interrupted):
|
|
||||||
threading.Thread.__init__(self)
|
|
||||||
self.setDaemon(1)
|
|
||||||
self.requestQueue = requestQueue
|
|
||||||
self.resultsQueue = resultsQueue
|
|
||||||
self.interrupted = interrupted
|
|
||||||
self.start()
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
while 1:
|
|
||||||
task = self.requestQueue.get()
|
|
||||||
|
|
||||||
if task is None:
|
|
||||||
# The "None" value is used as a sentinel by
|
|
||||||
# ThreadPool.cleanup(). This indicates that there
|
|
||||||
# are no more tasks, so we should quit.
|
|
||||||
break
|
|
||||||
|
|
||||||
try:
|
|
||||||
if self.interrupted():
|
|
||||||
raise SCons.Errors.BuildError(
|
|
||||||
task.targets[0], errstr=interrupt_msg)
|
|
||||||
task.execute()
|
|
||||||
except:
|
|
||||||
task.exception_set()
|
|
||||||
ok = False
|
|
||||||
else:
|
|
||||||
ok = True
|
|
||||||
|
|
||||||
self.resultsQueue.put((task, ok))
|
|
||||||
|
|
||||||
class ThreadPool:
|
|
||||||
"""This class is responsible for spawning and managing worker threads."""
|
|
||||||
|
|
||||||
def __init__(self, num, stack_size, interrupted):
|
|
||||||
"""Create the request and reply queues, and 'num' worker threads.
|
|
||||||
|
|
||||||
One must specify the stack size of the worker threads. The
|
|
||||||
stack size is specified in kilobytes.
|
|
||||||
"""
|
|
||||||
self.requestQueue = Queue.Queue(0)
|
|
||||||
self.resultsQueue = Queue.Queue(0)
|
|
||||||
|
|
||||||
try:
|
|
||||||
prev_size = threading.stack_size(stack_size*1024)
|
|
||||||
except AttributeError, e:
|
|
||||||
# Only print a warning if the stack size has been
|
|
||||||
# explicitly set.
|
|
||||||
if not explicit_stack_size is None:
|
|
||||||
msg = "Setting stack size is unsupported by this version of Python:\n " + \
|
|
||||||
e.args[0]
|
|
||||||
SCons.Warnings.warn(SCons.Warnings.StackSizeWarning, msg)
|
|
||||||
except ValueError, e:
|
|
||||||
msg = "Setting stack size failed:\n " + str(e)
|
|
||||||
SCons.Warnings.warn(SCons.Warnings.StackSizeWarning, msg)
|
|
||||||
|
|
||||||
# Create worker threads
|
|
||||||
self.workers = []
|
|
||||||
for _ in range(num):
|
|
||||||
worker = Worker(self.requestQueue, self.resultsQueue, interrupted)
|
|
||||||
self.workers.append(worker)
|
|
||||||
|
|
||||||
# Once we drop Python 1.5 we can change the following to:
|
|
||||||
#if 'prev_size' in locals():
|
|
||||||
if 'prev_size' in locals().keys():
|
|
||||||
threading.stack_size(prev_size)
|
|
||||||
|
|
||||||
def put(self, task):
|
|
||||||
"""Put task into request queue."""
|
|
||||||
self.requestQueue.put(task)
|
|
||||||
|
|
||||||
def get(self):
|
|
||||||
"""Remove and return a result tuple from the results queue."""
|
|
||||||
return self.resultsQueue.get()
|
|
||||||
|
|
||||||
def preparation_failed(self, task):
|
|
||||||
self.resultsQueue.put((task, False))
|
|
||||||
|
|
||||||
def cleanup(self):
|
|
||||||
"""
|
|
||||||
Shuts down the thread pool, giving each worker thread a
|
|
||||||
chance to shut down gracefully.
|
|
||||||
"""
|
|
||||||
# For each worker thread, put a sentinel "None" value
|
|
||||||
# on the requestQueue (indicating that there's no work
|
|
||||||
# to be done) so that each worker thread will get one and
|
|
||||||
# terminate gracefully.
|
|
||||||
for _ in self.workers:
|
|
||||||
self.requestQueue.put(None)
|
|
||||||
|
|
||||||
# Wait for all of the workers to terminate.
|
|
||||||
#
|
|
||||||
# If we don't do this, later Python versions (2.4, 2.5) often
|
|
||||||
# seem to raise exceptions during shutdown. This happens
|
|
||||||
# in requestQueue.get(), as an assertion failure that
|
|
||||||
# requestQueue.not_full is notified while not acquired,
|
|
||||||
# seemingly because the main thread has shut down (or is
|
|
||||||
# in the process of doing so) while the workers are still
|
|
||||||
# trying to pull sentinels off the requestQueue.
|
|
||||||
#
|
|
||||||
# Normally these terminations should happen fairly quickly,
|
|
||||||
# but we'll stick a one-second timeout on here just in case
|
|
||||||
# someone gets hung.
|
|
||||||
for worker in self.workers:
|
|
||||||
worker.join(1.0)
|
|
||||||
self.workers = []
|
|
||||||
|
|
||||||
class Parallel:
|
|
||||||
"""This class is used to execute tasks in parallel, and is somewhat
|
|
||||||
less efficient than Serial, but is appropriate for parallel builds.
|
|
||||||
|
|
||||||
This class is thread safe.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, taskmaster, num, stack_size):
|
|
||||||
"""Create a new parallel job given a taskmaster.
|
|
||||||
|
|
||||||
The taskmaster's next_task() method should return the next
|
|
||||||
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. """
|
|
||||||
|
|
||||||
self.taskmaster = taskmaster
|
|
||||||
self.interrupted = InterruptState()
|
|
||||||
self.tp = ThreadPool(num, stack_size, self.interrupted)
|
|
||||||
|
|
||||||
self.maxjobs = num
|
|
||||||
|
|
||||||
def start(self):
|
|
||||||
"""Start the job. This will begin pulling tasks from the
|
|
||||||
taskmaster and executing them, and return when there are no
|
|
||||||
more tasks. If a task fails to execute (i.e. execute() raises
|
|
||||||
an exception), then the job will stop."""
|
|
||||||
|
|
||||||
jobs = 0
|
|
||||||
|
|
||||||
while 1:
|
|
||||||
# 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
|
|
||||||
|
|
||||||
try:
|
|
||||||
# prepare task for execution
|
|
||||||
task.prepare()
|
|
||||||
except:
|
|
||||||
task.exception_set()
|
|
||||||
task.failed()
|
|
||||||
task.postprocess()
|
|
||||||
else:
|
|
||||||
if task.needs_execute():
|
|
||||||
# dispatch task
|
|
||||||
self.tp.put(task)
|
|
||||||
jobs = jobs + 1
|
|
||||||
else:
|
|
||||||
task.executed()
|
|
||||||
task.postprocess()
|
|
||||||
|
|
||||||
if not task and not jobs: break
|
|
||||||
|
|
||||||
# Let any/all completed tasks finish up before we go
|
|
||||||
# back and put the next batch of tasks on the queue.
|
|
||||||
while 1:
|
|
||||||
task, ok = self.tp.get()
|
|
||||||
jobs = jobs - 1
|
|
||||||
|
|
||||||
if ok:
|
|
||||||
task.executed()
|
|
||||||
else:
|
|
||||||
if self.interrupted():
|
|
||||||
try:
|
|
||||||
raise SCons.Errors.BuildError(
|
|
||||||
task.targets[0], errstr=interrupt_msg)
|
|
||||||
except:
|
|
||||||
task.exception_set()
|
|
||||||
|
|
||||||
# Let the failed() callback function arrange
|
|
||||||
# for the build to stop if that's appropriate.
|
|
||||||
task.failed()
|
|
||||||
|
|
||||||
task.postprocess()
|
|
||||||
|
|
||||||
if self.tp.resultsQueue.empty():
|
|
||||||
break
|
|
||||||
|
|
||||||
self.tp.cleanup()
|
|
||||||
self.taskmaster.cleanup()
|
|
|
@ -1,286 +0,0 @@
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Memoize.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
__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.use_metaclass = 1
|
|
||||||
def fake_method(self):
|
|
||||||
pass
|
|
||||||
new.instancemethod(fake_method, None, cls)
|
|
||||||
|
|
||||||
try:
|
|
||||||
class A:
|
|
||||||
__metaclass__ = M
|
|
||||||
|
|
||||||
use_metaclass = A.use_metaclass
|
|
||||||
except AttributeError:
|
|
||||||
use_metaclass = None
|
|
||||||
reason = 'no metaclasses'
|
|
||||||
except TypeError:
|
|
||||||
use_metaclass = None
|
|
||||||
reason = 'new.instancemethod() bug'
|
|
||||||
else:
|
|
||||||
del A
|
|
||||||
|
|
||||||
del M
|
|
||||||
|
|
||||||
if not use_metaclass:
|
|
||||||
|
|
||||||
def Dump(title):
|
|
||||||
pass
|
|
||||||
|
|
||||||
try:
|
|
||||||
class Memoized_Metaclass(type):
|
|
||||||
# Just a place-holder so pre-metaclass Python versions don't
|
|
||||||
# have to have special code for the Memoized classes.
|
|
||||||
pass
|
|
||||||
except TypeError:
|
|
||||||
class Memoized_Metaclass:
|
|
||||||
# A place-holder so pre-metaclass Python versions don't
|
|
||||||
# have to have special code for the Memoized classes.
|
|
||||||
pass
|
|
||||||
|
|
||||||
def EnableMemoization():
|
|
||||||
import SCons.Warnings
|
|
||||||
msg = 'memoization is not supported in this version of Python (%s)'
|
|
||||||
raise SCons.Warnings.NoMetaclassSupportWarning, msg % reason
|
|
||||||
|
|
||||||
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
|
|
|
@ -1,147 +0,0 @@
|
||||||
|
|
||||||
"""scons.Node.Alias
|
|
||||||
|
|
||||||
Alias nodes.
|
|
||||||
|
|
||||||
This creates a hash of global Aliases (dummy targets).
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Node/Alias.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import string
|
|
||||||
import UserDict
|
|
||||||
|
|
||||||
import SCons.Errors
|
|
||||||
import SCons.Node
|
|
||||||
import SCons.Util
|
|
||||||
|
|
||||||
class AliasNameSpace(UserDict.UserDict):
|
|
||||||
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, **kw):
|
|
||||||
try:
|
|
||||||
return self[name]
|
|
||||||
except KeyError:
|
|
||||||
return None
|
|
||||||
|
|
||||||
class AliasNodeInfo(SCons.Node.NodeInfoBase):
|
|
||||||
current_version_id = 1
|
|
||||||
field_list = ['csig']
|
|
||||||
def str_to_node(self, s):
|
|
||||||
return default_ans.Alias(s)
|
|
||||||
|
|
||||||
class AliasBuildInfo(SCons.Node.BuildInfoBase):
|
|
||||||
current_version_id = 1
|
|
||||||
|
|
||||||
class Alias(SCons.Node.Node):
|
|
||||||
|
|
||||||
NodeInfo = AliasNodeInfo
|
|
||||||
BuildInfo = AliasBuildInfo
|
|
||||||
|
|
||||||
def __init__(self, name):
|
|
||||||
SCons.Node.Node.__init__(self)
|
|
||||||
self.name = name
|
|
||||||
|
|
||||||
def str_for_display(self):
|
|
||||||
return '"' + self.__str__() + '"'
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return self.name
|
|
||||||
|
|
||||||
def make_ready(self):
|
|
||||||
self.get_csig()
|
|
||||||
|
|
||||||
really_build = SCons.Node.Node.build
|
|
||||||
is_up_to_date = SCons.Node.Node.children_are_up_to_date
|
|
||||||
|
|
||||||
def is_under(self, dir):
|
|
||||||
# Make Alias nodes get built regardless of
|
|
||||||
# what directory scons was run from. Alias nodes
|
|
||||||
# are outside the filesystem:
|
|
||||||
return 1
|
|
||||||
|
|
||||||
def get_contents(self):
|
|
||||||
"""The contents of an alias is the concatenation
|
|
||||||
of the content signatures of all its sources."""
|
|
||||||
childsigs = map(lambda n: n.get_csig(), self.children())
|
|
||||||
return string.join(childsigs, '')
|
|
||||||
|
|
||||||
def sconsign(self):
|
|
||||||
"""An Alias is not recorded in .sconsign files"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
#
|
|
||||||
#
|
|
||||||
#
|
|
||||||
|
|
||||||
def changed_since_last_build(self, target, prev_ni):
|
|
||||||
cur_csig = self.get_csig()
|
|
||||||
try:
|
|
||||||
return cur_csig != prev_ni.csig
|
|
||||||
except AttributeError:
|
|
||||||
return 1
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
def get_csig(self):
|
|
||||||
"""
|
|
||||||
Generate a node's content signature, the digested signature
|
|
||||||
of its content.
|
|
||||||
|
|
||||||
node - the node
|
|
||||||
cache - alternate node to use for the signature cache
|
|
||||||
returns - the content signature
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
return self.ninfo.csig
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
contents = self.get_contents()
|
|
||||||
csig = SCons.Util.MD5signature(contents)
|
|
||||||
self.get_ninfo().csig = csig
|
|
||||||
return csig
|
|
||||||
|
|
||||||
default_ans = AliasNameSpace()
|
|
||||||
|
|
||||||
SCons.Node.arg2nodes_lookups.append(default_ans.lookup)
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,119 +0,0 @@
|
||||||
"""scons.Node.Python
|
|
||||||
|
|
||||||
Python nodes.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Node/Python.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import SCons.Node
|
|
||||||
|
|
||||||
class ValueNodeInfo(SCons.Node.NodeInfoBase):
|
|
||||||
current_version_id = 1
|
|
||||||
|
|
||||||
field_list = ['csig']
|
|
||||||
|
|
||||||
def str_to_node(self, s):
|
|
||||||
return Value(s)
|
|
||||||
|
|
||||||
class ValueBuildInfo(SCons.Node.BuildInfoBase):
|
|
||||||
current_version_id = 1
|
|
||||||
|
|
||||||
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.
|
|
||||||
"""
|
|
||||||
|
|
||||||
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_for_display(self):
|
|
||||||
return repr(self.value)
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return str(self.value)
|
|
||||||
|
|
||||||
def make_ready(self):
|
|
||||||
self.get_csig()
|
|
||||||
|
|
||||||
def build(self, **kw):
|
|
||||||
if not hasattr(self, 'built_value'):
|
|
||||||
apply (SCons.Node.Node.build, (self,), kw)
|
|
||||||
|
|
||||||
is_up_to_date = SCons.Node.Node.children_are_up_to_date
|
|
||||||
|
|
||||||
def is_under(self, dir):
|
|
||||||
# Make Value nodes get built regardless of
|
|
||||||
# what directory scons was run from. Value nodes
|
|
||||||
# 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):
|
|
||||||
"""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 changed_since_last_build(self, target, prev_ni):
|
|
||||||
cur_csig = self.get_csig()
|
|
||||||
try:
|
|
||||||
return cur_csig != prev_ni.csig
|
|
||||||
except AttributeError:
|
|
||||||
return 1
|
|
||||||
|
|
||||||
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:
|
|
||||||
return self.ninfo.csig
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
contents = self.get_contents()
|
|
||||||
self.get_ninfo().csig = contents
|
|
||||||
return contents
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,44 +0,0 @@
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Options/BoolOption.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
__doc__ = """Place-holder for the old SCons.Options module hierarchy
|
|
||||||
|
|
||||||
This is for backwards compatibility. The new equivalent is the Variables/
|
|
||||||
class hierarchy. These will have deprecation warnings added (some day),
|
|
||||||
and will then be removed entirely (some day).
|
|
||||||
"""
|
|
||||||
|
|
||||||
import SCons.Variables
|
|
||||||
import SCons.Warnings
|
|
||||||
|
|
||||||
warned = False
|
|
||||||
|
|
||||||
def BoolOption(*args, **kw):
|
|
||||||
global warned
|
|
||||||
if not warned:
|
|
||||||
msg = "The BoolOption() function is deprecated; use the BoolVariable() function instead."
|
|
||||||
SCons.Warnings.warn(SCons.Warnings.DeprecatedOptionsWarning, msg)
|
|
||||||
warned = True
|
|
||||||
return apply(SCons.Variables.BoolVariable, args, kw)
|
|
|
@ -1,44 +0,0 @@
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Options/EnumOption.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
__doc__ = """Place-holder for the old SCons.Options module hierarchy
|
|
||||||
|
|
||||||
This is for backwards compatibility. The new equivalent is the Variables/
|
|
||||||
class hierarchy. These will have deprecation warnings added (some day),
|
|
||||||
and will then be removed entirely (some day).
|
|
||||||
"""
|
|
||||||
|
|
||||||
import SCons.Variables
|
|
||||||
import SCons.Warnings
|
|
||||||
|
|
||||||
warned = False
|
|
||||||
|
|
||||||
def EnumOption(*args, **kw):
|
|
||||||
global warned
|
|
||||||
if not warned:
|
|
||||||
msg = "The EnumOption() function is deprecated; use the EnumVariable() function instead."
|
|
||||||
SCons.Warnings.warn(SCons.Warnings.DeprecatedOptionsWarning, msg)
|
|
||||||
warned = True
|
|
||||||
return apply(SCons.Variables.EnumVariable, args, kw)
|
|
|
@ -1,44 +0,0 @@
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Options/ListOption.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
__doc__ = """Place-holder for the old SCons.Options module hierarchy
|
|
||||||
|
|
||||||
This is for backwards compatibility. The new equivalent is the Variables/
|
|
||||||
class hierarchy. These will have deprecation warnings added (some day),
|
|
||||||
and will then be removed entirely (some day).
|
|
||||||
"""
|
|
||||||
|
|
||||||
import SCons.Variables
|
|
||||||
import SCons.Warnings
|
|
||||||
|
|
||||||
warned = False
|
|
||||||
|
|
||||||
def ListOption(*args, **kw):
|
|
||||||
global warned
|
|
||||||
if not warned:
|
|
||||||
msg = "The ListOption() function is deprecated; use the ListVariable() function instead."
|
|
||||||
SCons.Warnings.warn(SCons.Warnings.DeprecatedOptionsWarning, msg)
|
|
||||||
warned = True
|
|
||||||
return apply(SCons.Variables.ListVariable, args, kw)
|
|
|
@ -1,44 +0,0 @@
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Options/PackageOption.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
__doc__ = """Place-holder for the old SCons.Options module hierarchy
|
|
||||||
|
|
||||||
This is for backwards compatibility. The new equivalent is the Variables/
|
|
||||||
class hierarchy. These will have deprecation warnings added (some day),
|
|
||||||
and will then be removed entirely (some day).
|
|
||||||
"""
|
|
||||||
|
|
||||||
import SCons.Variables
|
|
||||||
import SCons.Warnings
|
|
||||||
|
|
||||||
warned = False
|
|
||||||
|
|
||||||
def PackageOption(*args, **kw):
|
|
||||||
global warned
|
|
||||||
if not warned:
|
|
||||||
msg = "The PackageOption() function is deprecated; use the PackageVariable() function instead."
|
|
||||||
SCons.Warnings.warn(SCons.Warnings.DeprecatedOptionsWarning, msg)
|
|
||||||
warned = True
|
|
||||||
return apply(SCons.Variables.PackageVariable, args, kw)
|
|
|
@ -1,70 +0,0 @@
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Options/PathOption.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
__doc__ = """Place-holder for the old SCons.Options module hierarchy
|
|
||||||
|
|
||||||
This is for backwards compatibility. The new equivalent is the Variables/
|
|
||||||
class hierarchy. These will have deprecation warnings added (some day),
|
|
||||||
and will then be removed entirely (some day).
|
|
||||||
"""
|
|
||||||
|
|
||||||
import SCons.Variables
|
|
||||||
import SCons.Warnings
|
|
||||||
|
|
||||||
warned = False
|
|
||||||
|
|
||||||
class _PathOptionClass:
|
|
||||||
def warn(self):
|
|
||||||
global warned
|
|
||||||
if not warned:
|
|
||||||
msg = "The PathOption() function is deprecated; use the PathVariable() function instead."
|
|
||||||
SCons.Warnings.warn(SCons.Warnings.DeprecatedOptionsWarning, msg)
|
|
||||||
warned = True
|
|
||||||
|
|
||||||
def __call__(self, *args, **kw):
|
|
||||||
self.warn()
|
|
||||||
return apply(SCons.Variables.PathVariable, args, kw)
|
|
||||||
|
|
||||||
def PathAccept(self, *args, **kw):
|
|
||||||
self.warn()
|
|
||||||
return apply(SCons.Variables.PathVariable.PathAccept, args, kw)
|
|
||||||
|
|
||||||
def PathIsDir(self, *args, **kw):
|
|
||||||
self.warn()
|
|
||||||
return apply(SCons.Variables.PathVariable.PathIsDir, args, kw)
|
|
||||||
|
|
||||||
def PathIsDirCreate(self, *args, **kw):
|
|
||||||
self.warn()
|
|
||||||
return apply(SCons.Variables.PathVariable.PathIsDirCreate, args, kw)
|
|
||||||
|
|
||||||
def PathIsFile(self, *args, **kw):
|
|
||||||
self.warn()
|
|
||||||
return apply(SCons.Variables.PathVariable.PathIsFile, args, kw)
|
|
||||||
|
|
||||||
def PathExists(self, *args, **kw):
|
|
||||||
self.warn()
|
|
||||||
return apply(SCons.Variables.PathVariable.PathExists, args, kw)
|
|
||||||
|
|
||||||
PathOption = _PathOptionClass()
|
|
|
@ -1,68 +0,0 @@
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Options/__init__.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
__doc__ = """Place-holder for the old SCons.Options module hierarchy
|
|
||||||
|
|
||||||
This is for backwards compatibility. The new equivalent is the Variables/
|
|
||||||
class hierarchy. These will have deprecation warnings added (some day),
|
|
||||||
and will then be removed entirely (some day).
|
|
||||||
"""
|
|
||||||
|
|
||||||
import SCons.Variables
|
|
||||||
import SCons.Warnings
|
|
||||||
|
|
||||||
from BoolOption import BoolOption # okay
|
|
||||||
from EnumOption import EnumOption # okay
|
|
||||||
from ListOption import ListOption # naja
|
|
||||||
from PackageOption import PackageOption # naja
|
|
||||||
from PathOption import PathOption # okay
|
|
||||||
|
|
||||||
warned = False
|
|
||||||
|
|
||||||
class Options(SCons.Variables.Variables):
|
|
||||||
def __init__(self, *args, **kw):
|
|
||||||
global warned
|
|
||||||
if not warned:
|
|
||||||
msg = "The Options class is deprecated; use the Variables class instead."
|
|
||||||
SCons.Warnings.warn(SCons.Warnings.DeprecatedOptionsWarning, msg)
|
|
||||||
warned = True
|
|
||||||
apply(SCons.Variables.Variables.__init__,
|
|
||||||
(self,) + args,
|
|
||||||
kw)
|
|
||||||
|
|
||||||
def AddOptions(self, *args, **kw):
|
|
||||||
return apply(SCons.Variables.Variables.AddVariables,
|
|
||||||
(self,) + args,
|
|
||||||
kw)
|
|
||||||
|
|
||||||
def UnknownOptions(self, *args, **kw):
|
|
||||||
return apply(SCons.Variables.Variables.UnknownVariables,
|
|
||||||
(self,) + args,
|
|
||||||
kw)
|
|
||||||
|
|
||||||
def FormatOptionHelpText(self, *args, **kw):
|
|
||||||
return apply(SCons.Variables.Variables.FormatVariableHelpText,
|
|
||||||
(self,) + args,
|
|
||||||
kw)
|
|
|
@ -1,226 +0,0 @@
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/PathList.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
__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) or SCons.Util.is_Sequence( obj ):
|
|
||||||
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):
|
|
||||||
result.extend(value)
|
|
||||||
continue
|
|
||||||
|
|
||||||
elif type == TYPE_OBJECT:
|
|
||||||
value = node_conv(value)
|
|
||||||
if 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
|
|
|
@ -1,216 +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, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Platform/__init__.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
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
|
|
|
@ -1,65 +0,0 @@
|
||||||
"""engine.SCons.Platform.aix
|
|
||||||
|
|
||||||
Platform-specific initialization for IBM AIX systems.
|
|
||||||
|
|
||||||
There normally shouldn't be any need to import this module directly. It
|
|
||||||
will usually be imported through the generic SCons.Platform.Platform()
|
|
||||||
selection method.
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Platform/aix.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import os
|
|
||||||
import string
|
|
||||||
|
|
||||||
import posix
|
|
||||||
|
|
||||||
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()
|
|
||||||
if line:
|
|
||||||
v, p = string.split(line, ':')[1:3]
|
|
||||||
xlcVersion = string.split(v)[1]
|
|
||||||
xlcPath = string.split(p)[0]
|
|
||||||
xlcPath = xlcPath[:xlcPath.rindex('/')]
|
|
||||||
break
|
|
||||||
return (xlcPath, xlc, xlc_r, xlcVersion)
|
|
||||||
|
|
||||||
def generate(env):
|
|
||||||
posix.generate(env)
|
|
||||||
#Based on AIX 5.2: ARG_MAX=24576 - 3000 for environment expansion
|
|
||||||
env['MAXLINELENGTH'] = 21576
|
|
||||||
|
|
|
@ -1,49 +0,0 @@
|
||||||
"""SCons.Platform.cygwin
|
|
||||||
|
|
||||||
Platform-specific initialization for Cygwin systems.
|
|
||||||
|
|
||||||
There normally shouldn't be any need to import this module directly. It
|
|
||||||
will usually be imported through the generic SCons.Platform.Platform()
|
|
||||||
selection method.
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Platform/cygwin.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import posix
|
|
||||||
from SCons.Platform import TempFileMunge
|
|
||||||
|
|
||||||
def generate(env):
|
|
||||||
posix.generate(env)
|
|
||||||
|
|
||||||
env['PROGPREFIX'] = ''
|
|
||||||
env['PROGSUFFIX'] = '.exe'
|
|
||||||
env['SHLIBPREFIX'] = ''
|
|
||||||
env['SHLIBSUFFIX'] = '.dll'
|
|
||||||
env['LIBPREFIXES'] = [ '$LIBPREFIX', '$SHLIBPREFIX' ]
|
|
||||||
env['LIBSUFFIXES'] = [ '$LIBSUFFIX', '$SHLIBSUFFIX' ]
|
|
||||||
env['TEMPFILE'] = TempFileMunge
|
|
||||||
env['TEMPFILEPREFIX'] = '@'
|
|
||||||
env['MAXLINELENGTH'] = 2048
|
|
|
@ -1,40 +0,0 @@
|
||||||
"""engine.SCons.Platform.darwin
|
|
||||||
|
|
||||||
Platform-specific initialization for Mac OS X systems.
|
|
||||||
|
|
||||||
There normally shouldn't be any need to import this module directly. It
|
|
||||||
will usually be imported through the generic SCons.Platform.Platform()
|
|
||||||
selection method.
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Platform/darwin.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import posix
|
|
||||||
|
|
||||||
def generate(env):
|
|
||||||
posix.generate(env)
|
|
||||||
env['SHLIBSUFFIX'] = '.dylib'
|
|
||||||
env['ENV']['PATH'] = env['ENV']['PATH'] + ':/sw/bin'
|
|
|
@ -1,40 +0,0 @@
|
||||||
"""engine.SCons.Platform.hpux
|
|
||||||
|
|
||||||
Platform-specific initialization for HP-UX systems.
|
|
||||||
|
|
||||||
There normally shouldn't be any need to import this module directly. It
|
|
||||||
will usually be imported through the generic SCons.Platform.Platform()
|
|
||||||
selection method.
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Platform/hpux.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import posix
|
|
||||||
|
|
||||||
def generate(env):
|
|
||||||
posix.generate(env)
|
|
||||||
#Based on HP-UX11i: ARG_MAX=2048000 - 3000 for environment expansion
|
|
||||||
env['MAXLINELENGTH'] = 2045000
|
|
|
@ -1,38 +0,0 @@
|
||||||
"""SCons.Platform.irix
|
|
||||||
|
|
||||||
Platform-specific initialization for SGI IRIX systems.
|
|
||||||
|
|
||||||
There normally shouldn't be any need to import this module directly. It
|
|
||||||
will usually be imported through the generic SCons.Platform.Platform()
|
|
||||||
selection method.
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Platform/irix.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import posix
|
|
||||||
|
|
||||||
def generate(env):
|
|
||||||
posix.generate(env)
|
|
|
@ -1,49 +0,0 @@
|
||||||
"""SCons.Platform.os2
|
|
||||||
|
|
||||||
Platform-specific initialization for OS/2 systems.
|
|
||||||
|
|
||||||
There normally shouldn't be any need to import this module directly. It
|
|
||||||
will usually be imported through the generic SCons.Platform.Platform()
|
|
||||||
selection method.
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Platform/os2.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
def generate(env):
|
|
||||||
if not env.has_key('ENV'):
|
|
||||||
env['ENV'] = {}
|
|
||||||
env['OBJPREFIX'] = ''
|
|
||||||
env['OBJSUFFIX'] = '.obj'
|
|
||||||
env['SHOBJPREFIX'] = '$OBJPREFIX'
|
|
||||||
env['SHOBJSUFFIX'] = '$OBJSUFFIX'
|
|
||||||
env['PROGPREFIX'] = ''
|
|
||||||
env['PROGSUFFIX'] = '.exe'
|
|
||||||
env['LIBPREFIX'] = ''
|
|
||||||
env['LIBSUFFIX'] = '.lib'
|
|
||||||
env['SHLIBPREFIX'] = ''
|
|
||||||
env['SHLIBSUFFIX'] = '.dll'
|
|
||||||
env['LIBPREFIXES'] = '$LIBPREFIX'
|
|
||||||
env['LIBSUFFIXES'] = [ '$LIBSUFFIX', '$SHLIBSUFFIX' ]
|
|
|
@ -1,258 +0,0 @@
|
||||||
"""SCons.Platform.posix
|
|
||||||
|
|
||||||
Platform-specific initialization for POSIX (Linux, UNIX, etc.) systems.
|
|
||||||
|
|
||||||
There normally shouldn't be any need to import this module directly. It
|
|
||||||
will usually be imported through the generic SCons.Platform.Platform()
|
|
||||||
selection method.
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Platform/posix.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import errno
|
|
||||||
import os
|
|
||||||
import os.path
|
|
||||||
import string
|
|
||||||
import subprocess
|
|
||||||
import sys
|
|
||||||
import select
|
|
||||||
|
|
||||||
import SCons.Util
|
|
||||||
from SCons.Platform import TempFileMunge
|
|
||||||
|
|
||||||
exitvalmap = {
|
|
||||||
2 : 127,
|
|
||||||
13 : 126,
|
|
||||||
}
|
|
||||||
|
|
||||||
def escape(arg):
|
|
||||||
"escape shell special characters"
|
|
||||||
slash = '\\'
|
|
||||||
special = '"$()'
|
|
||||||
|
|
||||||
arg = string.replace(arg, slash, slash+slash)
|
|
||||||
for c in special:
|
|
||||||
arg = string.replace(arg, c, slash+c)
|
|
||||||
|
|
||||||
return '"' + arg + '"'
|
|
||||||
|
|
||||||
def exec_system(l, env):
|
|
||||||
stat = os.system(string.join(l))
|
|
||||||
if stat & 0xff:
|
|
||||||
return stat | 0x80
|
|
||||||
return stat >> 8
|
|
||||||
|
|
||||||
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 exec_fork(l, env):
|
|
||||||
pid = os.fork()
|
|
||||||
if not pid:
|
|
||||||
# Child process.
|
|
||||||
exitval = 127
|
|
||||||
try:
|
|
||||||
os.execvpe(l[0], l, env)
|
|
||||||
except OSError, e:
|
|
||||||
exitval = exitvalmap.get(e[0], e[0])
|
|
||||||
sys.stderr.write("scons: %s: %s\n" % (l[0], e[1]))
|
|
||||||
os._exit(exitval)
|
|
||||||
else:
|
|
||||||
# Parent process.
|
|
||||||
pid, stat = os.waitpid(pid, 0)
|
|
||||||
if stat & 0xff:
|
|
||||||
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: e(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):
|
|
||||||
try:
|
|
||||||
(i,o,e) = select.select([cmd_stdout, cmd_stderr], [], [])
|
|
||||||
if cmd_stdout in i:
|
|
||||||
str = cmd_stdout.read()
|
|
||||||
if len(str) == 0:
|
|
||||||
stdout_eof = 1
|
|
||||||
elif stdout != None:
|
|
||||||
stdout.write(str)
|
|
||||||
if cmd_stderr in i:
|
|
||||||
str = cmd_stderr.read()
|
|
||||||
if len(str) == 0:
|
|
||||||
#sys.__stderr__.write( "stderr_eof=1\n" )
|
|
||||||
stderr_eof = 1
|
|
||||||
else:
|
|
||||||
#sys.__stderr__.write( "str(stderr) = %s\n" % str )
|
|
||||||
stderr.write(str)
|
|
||||||
except select.error, (_errno, _strerror):
|
|
||||||
if _errno != errno.EINTR:
|
|
||||||
raise
|
|
||||||
|
|
||||||
def exec_popen3(l, env, stdout, stderr):
|
|
||||||
proc = subprocess.Popen(string.join(l),
|
|
||||||
stdout=stdout,
|
|
||||||
stderr=stderr,
|
|
||||||
shell=True)
|
|
||||||
stat = proc.wait()
|
|
||||||
if stat & 0xff:
|
|
||||||
return stat | 0x80
|
|
||||||
return stat >> 8
|
|
||||||
|
|
||||||
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:
|
|
||||||
(rFdOut, wFdOut) = os.pipe()
|
|
||||||
(rFdErr, wFdErr) = os.pipe()
|
|
||||||
else:
|
|
||||||
(rFdOut, wFdOut) = os.pipe()
|
|
||||||
rFdErr = rFdOut
|
|
||||||
wFdErr = wFdOut
|
|
||||||
# do the fork
|
|
||||||
pid = os.fork()
|
|
||||||
if not pid:
|
|
||||||
# Child process
|
|
||||||
os.close( rFdOut )
|
|
||||||
if rFdOut != rFdErr:
|
|
||||||
os.close( rFdErr )
|
|
||||||
os.dup2( wFdOut, 1 ) # is there some symbolic way to do that ?
|
|
||||||
os.dup2( wFdErr, 2 )
|
|
||||||
os.close( wFdOut )
|
|
||||||
if stdout != stderr:
|
|
||||||
os.close( wFdErr )
|
|
||||||
exitval = 127
|
|
||||||
try:
|
|
||||||
os.execvpe(l[0], l, env)
|
|
||||||
except OSError, e:
|
|
||||||
exitval = exitvalmap.get(e[0], e[0])
|
|
||||||
stderr.write("scons: %s: %s\n" % (l[0], e[1]))
|
|
||||||
os._exit(exitval)
|
|
||||||
else:
|
|
||||||
# Parent process
|
|
||||||
pid, stat = os.waitpid(pid, 0)
|
|
||||||
os.close( wFdOut )
|
|
||||||
if stdout != stderr:
|
|
||||||
os.close( wFdErr )
|
|
||||||
childOut = os.fdopen( rFdOut )
|
|
||||||
if stdout != stderr:
|
|
||||||
childErr = os.fdopen( rFdErr )
|
|
||||||
else:
|
|
||||||
childErr = childOut
|
|
||||||
process_cmd_output(childOut, childErr, stdout, stderr)
|
|
||||||
os.close( rFdOut )
|
|
||||||
if stdout != stderr:
|
|
||||||
os.close( rFdErr )
|
|
||||||
if stat & 0xff:
|
|
||||||
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):
|
|
||||||
# If os.spawnvpe() exists, we use it to spawn commands. Otherwise
|
|
||||||
# if the env utility exists, we use os.system() to spawn commands,
|
|
||||||
# finally we fall back on os.fork()/os.exec().
|
|
||||||
#
|
|
||||||
# os.spawnvpe() is prefered because it is the most efficient. But
|
|
||||||
# for Python versions without it, os.system() is prefered because it
|
|
||||||
# is claimed that it works better with threads (i.e. -j) and is more
|
|
||||||
# efficient than forking Python.
|
|
||||||
#
|
|
||||||
# NB: Other people on the scons-users mailing list have claimed that
|
|
||||||
# os.fork()/os.exec() works better than os.system(). There may just
|
|
||||||
# not be a default that works best for all users.
|
|
||||||
|
|
||||||
if os.__dict__.has_key('spawnvpe'):
|
|
||||||
spawn = spawnvpe_spawn
|
|
||||||
elif env.Detect('env'):
|
|
||||||
spawn = env_spawn
|
|
||||||
else:
|
|
||||||
spawn = fork_spawn
|
|
||||||
|
|
||||||
if env.Detect('env'):
|
|
||||||
pspawn = piped_env_spawn
|
|
||||||
else:
|
|
||||||
pspawn = piped_fork_spawn
|
|
||||||
|
|
||||||
if not env.has_key('ENV'):
|
|
||||||
env['ENV'] = {}
|
|
||||||
env['ENV']['PATH'] = '/usr/local/bin:/opt/bin:/bin:/usr/bin'
|
|
||||||
env['OBJPREFIX'] = ''
|
|
||||||
env['OBJSUFFIX'] = '.o'
|
|
||||||
env['SHOBJPREFIX'] = '$OBJPREFIX'
|
|
||||||
env['SHOBJSUFFIX'] = '$OBJSUFFIX'
|
|
||||||
env['PROGPREFIX'] = ''
|
|
||||||
env['PROGSUFFIX'] = ''
|
|
||||||
env['LIBPREFIX'] = 'lib'
|
|
||||||
env['LIBSUFFIX'] = '.a'
|
|
||||||
env['SHLIBPREFIX'] = '$LIBPREFIX'
|
|
||||||
env['SHLIBSUFFIX'] = '.so'
|
|
||||||
env['LIBPREFIXES'] = [ '$LIBPREFIX' ]
|
|
||||||
env['LIBSUFFIXES'] = [ '$LIBSUFFIX', '$SHLIBSUFFIX' ]
|
|
||||||
env['PSPAWN'] = pspawn
|
|
||||||
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'
|
|
|
@ -1,44 +0,0 @@
|
||||||
"""engine.SCons.Platform.sunos
|
|
||||||
|
|
||||||
Platform-specific initialization for Sun systems.
|
|
||||||
|
|
||||||
There normally shouldn't be any need to import this module directly. It
|
|
||||||
will usually be imported through the generic SCons.Platform.Platform()
|
|
||||||
selection method.
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Platform/sunos.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
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'] + ':/opt/SUNWspro/bin:/usr/ccs/bin'
|
|
|
@ -1,324 +0,0 @@
|
||||||
"""SCons.Platform.win32
|
|
||||||
|
|
||||||
Platform-specific initialization for Win32 systems.
|
|
||||||
|
|
||||||
There normally shouldn't be any need to import this module directly. It
|
|
||||||
will usually be imported through the generic SCons.Platform.Platform()
|
|
||||||
selection method.
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Platform/win32.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import os
|
|
||||||
import os.path
|
|
||||||
import string
|
|
||||||
import sys
|
|
||||||
import tempfile
|
|
||||||
|
|
||||||
from SCons.Platform.posix import exitvalmap
|
|
||||||
from SCons.Platform import TempFileMunge
|
|
||||||
import SCons.Util
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
try:
|
|
||||||
import msvcrt
|
|
||||||
import win32api
|
|
||||||
import win32con
|
|
||||||
|
|
||||||
msvcrt.get_osfhandle
|
|
||||||
win32api.SetHandleInformation
|
|
||||||
win32con.HANDLE_FLAG_INHERIT
|
|
||||||
except ImportError:
|
|
||||||
parallel_msg = \
|
|
||||||
"you do not seem to have the pywin32 extensions installed;\n" + \
|
|
||||||
"\tparallel (-j) builds may not work reliably with open Python files."
|
|
||||||
except AttributeError:
|
|
||||||
parallel_msg = \
|
|
||||||
"your pywin32 extensions do not support file handle operations;\n" + \
|
|
||||||
"\tparallel (-j) builds may not work reliably with open Python files."
|
|
||||||
else:
|
|
||||||
parallel_msg = None
|
|
||||||
|
|
||||||
import __builtin__
|
|
||||||
|
|
||||||
_builtin_file = __builtin__.file
|
|
||||||
_builtin_open = __builtin__.open
|
|
||||||
|
|
||||||
def _scons_file(*args, **kw):
|
|
||||||
fp = apply(_builtin_file, args, kw)
|
|
||||||
win32api.SetHandleInformation(msvcrt.get_osfhandle(fp.fileno()),
|
|
||||||
win32con.HANDLE_FLAG_INHERIT,
|
|
||||||
0)
|
|
||||||
return fp
|
|
||||||
|
|
||||||
def _scons_open(*args, **kw):
|
|
||||||
fp = apply(_builtin_open, args, kw)
|
|
||||||
win32api.SetHandleInformation(msvcrt.get_osfhandle(fp.fileno()),
|
|
||||||
win32con.HANDLE_FLAG_INHERIT,
|
|
||||||
0)
|
|
||||||
return fp
|
|
||||||
|
|
||||||
__builtin__.file = _scons_file
|
|
||||||
__builtin__.open = _scons_open
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# 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
|
|
||||||
# scons.
|
|
||||||
|
|
||||||
def piped_spawn(sh, escape, cmd, args, env, stdout, stderr):
|
|
||||||
# There is no direct way to do that in python. What we do
|
|
||||||
# here should work for most cases:
|
|
||||||
# In case stdout (stderr) is not redirected to a file,
|
|
||||||
# we redirect it into a temporary file tmpFileStdout
|
|
||||||
# (tmpFileStderr) and copy the contents of this file
|
|
||||||
# to stdout (stderr) given in the argument
|
|
||||||
if not sh:
|
|
||||||
sys.stderr.write("scons: Could not find command interpreter, is it in your PATH?\n")
|
|
||||||
return 127
|
|
||||||
else:
|
|
||||||
# one temporary file for stdout and stderr
|
|
||||||
tmpFileStdout = os.path.normpath(tempfile.mktemp())
|
|
||||||
tmpFileStderr = os.path.normpath(tempfile.mktemp())
|
|
||||||
|
|
||||||
# check if output is redirected
|
|
||||||
stdoutRedirected = 0
|
|
||||||
stderrRedirected = 0
|
|
||||||
for arg in args:
|
|
||||||
# are there more possibilities to redirect stdout ?
|
|
||||||
if (string.find( arg, ">", 0, 1 ) != -1 or
|
|
||||||
string.find( arg, "1>", 0, 2 ) != -1):
|
|
||||||
stdoutRedirected = 1
|
|
||||||
# are there more possibilities to redirect stderr ?
|
|
||||||
if string.find( arg, "2>", 0, 2 ) != -1:
|
|
||||||
stderrRedirected = 1
|
|
||||||
|
|
||||||
# redirect output of non-redirected streams to our tempfiles
|
|
||||||
if stdoutRedirected == 0:
|
|
||||||
args.append(">" + str(tmpFileStdout))
|
|
||||||
if stderrRedirected == 0:
|
|
||||||
args.append("2>" + str(tmpFileStderr))
|
|
||||||
|
|
||||||
# actually do the spawn
|
|
||||||
try:
|
|
||||||
args = [sh, '/C', escape(string.join(args)) ]
|
|
||||||
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
|
|
||||||
# and do clean up stuff
|
|
||||||
if stdout != None and stdoutRedirected == 0:
|
|
||||||
try:
|
|
||||||
stdout.write(open( tmpFileStdout, "r" ).read())
|
|
||||||
os.remove( tmpFileStdout )
|
|
||||||
except (IOError, OSError):
|
|
||||||
pass
|
|
||||||
|
|
||||||
if stderr != None and stderrRedirected == 0:
|
|
||||||
try:
|
|
||||||
stderr.write(open( tmpFileStderr, "r" ).read())
|
|
||||||
os.remove( tmpFileStderr )
|
|
||||||
except (IOError, OSError):
|
|
||||||
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
|
|
||||||
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, 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():
|
|
||||||
# A resonable default if we can't read the registry
|
|
||||||
try:
|
|
||||||
val = os.environ['SYSTEMROOT']
|
|
||||||
except KeyError:
|
|
||||||
val = "C:/WINDOWS"
|
|
||||||
pass
|
|
||||||
|
|
||||||
# First see if we can look in the registry...
|
|
||||||
if SCons.Util.can_read_reg:
|
|
||||||
try:
|
|
||||||
# Look for Windows NT system root
|
|
||||||
k=SCons.Util.RegOpenKeyEx(SCons.Util.hkey_mod.HKEY_LOCAL_MACHINE,
|
|
||||||
'Software\\Microsoft\\Windows NT\\CurrentVersion')
|
|
||||||
val, tok = SCons.Util.RegQueryValueEx(k, 'SystemRoot')
|
|
||||||
except SCons.Util.RegError:
|
|
||||||
try:
|
|
||||||
# Okay, try the Windows 9x system root
|
|
||||||
k=SCons.Util.RegOpenKeyEx(SCons.Util.hkey_mod.HKEY_LOCAL_MACHINE,
|
|
||||||
'Software\\Microsoft\\Windows\\CurrentVersion')
|
|
||||||
val, tok = SCons.Util.RegQueryValueEx(k, 'SystemRoot')
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
raise
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
return val
|
|
||||||
|
|
||||||
# Get the location of the program files directory
|
|
||||||
def get_program_files_dir():
|
|
||||||
# Now see if we can look in the registry...
|
|
||||||
val = ''
|
|
||||||
if SCons.Util.can_read_reg:
|
|
||||||
try:
|
|
||||||
# Look for Windows Program Files directory
|
|
||||||
k=SCons.Util.RegOpenKeyEx(SCons.Util.hkey_mod.HKEY_LOCAL_MACHINE,
|
|
||||||
'Software\\Microsoft\\Windows\\CurrentVersion')
|
|
||||||
val, tok = SCons.Util.RegQueryValueEx(k, 'ProgramFilesDir')
|
|
||||||
except SCons.Util.RegError:
|
|
||||||
val = ''
|
|
||||||
pass
|
|
||||||
|
|
||||||
if val == '':
|
|
||||||
# A reasonable default if we can't read the registry
|
|
||||||
# (Actually, it's pretty reasonable even if we can :-)
|
|
||||||
val = os.path.join(os.path.dirname(get_system_root()),"Program Files")
|
|
||||||
|
|
||||||
return val
|
|
||||||
|
|
||||||
def generate(env):
|
|
||||||
# Attempt to find cmd.exe (for WinNT/2k/XP) or
|
|
||||||
# command.com for Win9x
|
|
||||||
cmd_interp = ''
|
|
||||||
# First see if we can look in the registry...
|
|
||||||
if SCons.Util.can_read_reg:
|
|
||||||
try:
|
|
||||||
# Look for Windows NT system root
|
|
||||||
k=SCons.Util.RegOpenKeyEx(SCons.Util.hkey_mod.HKEY_LOCAL_MACHINE,
|
|
||||||
'Software\\Microsoft\\Windows NT\\CurrentVersion')
|
|
||||||
val, tok = SCons.Util.RegQueryValueEx(k, 'SystemRoot')
|
|
||||||
cmd_interp = os.path.join(val, 'System32\\cmd.exe')
|
|
||||||
except SCons.Util.RegError:
|
|
||||||
try:
|
|
||||||
# Okay, try the Windows 9x system root
|
|
||||||
k=SCons.Util.RegOpenKeyEx(SCons.Util.hkey_mod.HKEY_LOCAL_MACHINE,
|
|
||||||
'Software\\Microsoft\\Windows\\CurrentVersion')
|
|
||||||
val, tok = SCons.Util.RegQueryValueEx(k, 'SystemRoot')
|
|
||||||
cmd_interp = os.path.join(val, 'command.com')
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
raise
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# For the special case of not having access to the registry, we
|
|
||||||
# use a temporary path and pathext to attempt to find the command
|
|
||||||
# interpreter. If we fail, we try to find the interpreter through
|
|
||||||
# the env's PATH. The problem with that is that it might not
|
|
||||||
# contain an ENV and a PATH.
|
|
||||||
if not cmd_interp:
|
|
||||||
systemroot = r'C:\Windows'
|
|
||||||
if os.environ.has_key('SYSTEMROOT'):
|
|
||||||
systemroot = os.environ['SYSTEMROOT']
|
|
||||||
tmp_path = systemroot + os.pathsep + \
|
|
||||||
os.path.join(systemroot,'System32')
|
|
||||||
tmp_pathext = '.com;.exe;.bat;.cmd'
|
|
||||||
if os.environ.has_key('PATHEXT'):
|
|
||||||
tmp_pathext = os.environ['PATHEXT']
|
|
||||||
cmd_interp = SCons.Util.WhereIs('cmd', tmp_path, tmp_pathext)
|
|
||||||
if not cmd_interp:
|
|
||||||
cmd_interp = SCons.Util.WhereIs('command', tmp_path, tmp_pathext)
|
|
||||||
|
|
||||||
if not cmd_interp:
|
|
||||||
cmd_interp = env.Detect('cmd')
|
|
||||||
if not cmd_interp:
|
|
||||||
cmd_interp = env.Detect('command')
|
|
||||||
|
|
||||||
|
|
||||||
if not env.has_key('ENV'):
|
|
||||||
env['ENV'] = {}
|
|
||||||
|
|
||||||
# Import things from the external environment to the construction
|
|
||||||
# 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, 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:
|
|
||||||
env['ENV'][var] = v
|
|
||||||
|
|
||||||
env['ENV']['PATHEXT'] = '.COM;.EXE;.BAT;.CMD'
|
|
||||||
env['OBJPREFIX'] = ''
|
|
||||||
env['OBJSUFFIX'] = '.obj'
|
|
||||||
env['SHOBJPREFIX'] = '$OBJPREFIX'
|
|
||||||
env['SHOBJSUFFIX'] = '$OBJSUFFIX'
|
|
||||||
env['PROGPREFIX'] = ''
|
|
||||||
env['PROGSUFFIX'] = '.exe'
|
|
||||||
env['LIBPREFIX'] = ''
|
|
||||||
env['LIBSUFFIX'] = '.lib'
|
|
||||||
env['SHLIBPREFIX'] = ''
|
|
||||||
env['SHLIBSUFFIX'] = '.dll'
|
|
||||||
env['LIBPREFIXES'] = [ '$LIBPREFIX' ]
|
|
||||||
env['LIBSUFFIXES'] = [ '$LIBSUFFIX' ]
|
|
||||||
env['PSPAWN'] = piped_spawn
|
|
||||||
env['SPAWN'] = spawn
|
|
||||||
env['SHELL'] = cmd_interp
|
|
||||||
env['TEMPFILE'] = TempFileMunge
|
|
||||||
env['TEMPFILEPREFIX'] = '@'
|
|
||||||
env['MAXLINELENGTH'] = 2048
|
|
||||||
env['ESCAPE'] = escape
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,375 +0,0 @@
|
||||||
"""SCons.SConsign
|
|
||||||
|
|
||||||
Writing and reading information to the .sconsign file or files.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/SConsign.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import cPickle
|
|
||||||
import os
|
|
||||||
import os.path
|
|
||||||
|
|
||||||
import SCons.dblite
|
|
||||||
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 = []
|
|
||||||
|
|
||||||
# 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(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 SConsignEntry:
|
|
||||||
"""
|
|
||||||
Wrapper class for the generic entry in a .sconsign file.
|
|
||||||
The Node subclass populates it with attributes as it pleases.
|
|
||||||
|
|
||||||
XXX As coded below, we do expect a '.binfo' attribute to be added,
|
|
||||||
but we'll probably generalize this in the next refactorings.
|
|
||||||
"""
|
|
||||||
current_version_id = 1
|
|
||||||
def __init__(self):
|
|
||||||
# Create an object attribute from the class attribute so it ends up
|
|
||||||
# in the pickled data in the .sconsign file.
|
|
||||||
_version_id = self.current_version_id
|
|
||||||
def convert_to_sconsign(self):
|
|
||||||
self.binfo.convert_to_sconsign()
|
|
||||||
def convert_from_sconsign(self, dir, name):
|
|
||||||
self.binfo.convert_from_sconsign(dir, name)
|
|
||||||
|
|
||||||
class Base:
|
|
||||||
"""
|
|
||||||
This is the controlling class for the signatures for the collection of
|
|
||||||
entries associated with a specific directory. The actual directory
|
|
||||||
association will be maintained by a subclass that is specific to
|
|
||||||
the underlying storage method. This class provides a common set of
|
|
||||||
methods for fetching and storing the individual bits of information
|
|
||||||
that make up signature entry.
|
|
||||||
"""
|
|
||||||
def __init__(self):
|
|
||||||
self.entries = {}
|
|
||||||
self.dirty = False
|
|
||||||
self.to_be_merged = {}
|
|
||||||
|
|
||||||
def get_entry(self, filename):
|
|
||||||
"""
|
|
||||||
Fetch the specified entry attribute.
|
|
||||||
"""
|
|
||||||
return self.entries[filename]
|
|
||||||
|
|
||||||
def set_entry(self, filename, obj):
|
|
||||||
"""
|
|
||||||
Set the entry.
|
|
||||||
"""
|
|
||||||
self.entries[filename] = obj
|
|
||||||
self.dirty = True
|
|
||||||
|
|
||||||
def do_not_set_entry(self, filename, obj):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def store_info(self, filename, node):
|
|
||||||
entry = node.get_stored_info()
|
|
||||||
entry.binfo.merge(node.get_binfo())
|
|
||||||
self.to_be_merged[filename] = node
|
|
||||||
self.dirty = True
|
|
||||||
|
|
||||||
def do_not_store_info(self, filename, node):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def merge(self):
|
|
||||||
for key, node in self.to_be_merged.items():
|
|
||||||
entry = node.get_stored_info()
|
|
||||||
try:
|
|
||||||
ninfo = entry.ninfo
|
|
||||||
except AttributeError:
|
|
||||||
# This happens with SConf Nodes, because the configuration
|
|
||||||
# subsystem takes direct control over how the build decision
|
|
||||||
# is made and its information stored.
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
ninfo.merge(node.get_ninfo())
|
|
||||||
self.entries[key] = entry
|
|
||||||
self.to_be_merged = {}
|
|
||||||
|
|
||||||
class DB(Base):
|
|
||||||
"""
|
|
||||||
A Base subclass that reads and writes signature information
|
|
||||||
from a global .sconsign.db* file--the actual file suffix is
|
|
||||||
determined by the database module.
|
|
||||||
"""
|
|
||||||
def __init__(self, dir):
|
|
||||||
Base.__init__(self)
|
|
||||||
|
|
||||||
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:
|
|
||||||
rawentries = db[path]
|
|
||||||
except KeyError:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
self.entries = cPickle.loads(rawentries)
|
|
||||||
if type(self.entries) is not type({}):
|
|
||||||
self.entries = {}
|
|
||||||
raise TypeError
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
raise
|
|
||||||
except Exception, e:
|
|
||||||
SCons.Warnings.warn(SCons.Warnings.CorruptSConsignWarning,
|
|
||||||
"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
|
|
||||||
self.store_info = self.do_not_store_info
|
|
||||||
|
|
||||||
global sig_files
|
|
||||||
sig_files.append(self)
|
|
||||||
|
|
||||||
def write(self, sync=1):
|
|
||||||
if not self.dirty:
|
|
||||||
return
|
|
||||||
|
|
||||||
self.merge()
|
|
||||||
|
|
||||||
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:
|
|
||||||
syncmethod = db.sync
|
|
||||||
except AttributeError:
|
|
||||||
# Not all anydbm modules have sync() methods.
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
syncmethod()
|
|
||||||
|
|
||||||
class Dir(Base):
|
|
||||||
def __init__(self, fp=None, dir=None):
|
|
||||||
"""
|
|
||||||
fp - file pointer to read entries from
|
|
||||||
"""
|
|
||||||
Base.__init__(self)
|
|
||||||
|
|
||||||
if not fp:
|
|
||||||
return
|
|
||||||
|
|
||||||
self.entries = cPickle.load(fp)
|
|
||||||
if type(self.entries) is not type({}):
|
|
||||||
self.entries = {}
|
|
||||||
raise TypeError
|
|
||||||
|
|
||||||
if dir:
|
|
||||||
for key, entry in self.entries.items():
|
|
||||||
entry.convert_from_sconsign(dir, key)
|
|
||||||
|
|
||||||
class DirFile(Dir):
|
|
||||||
"""
|
|
||||||
Encapsulates reading and writing a per-directory .sconsign file.
|
|
||||||
"""
|
|
||||||
def __init__(self, dir):
|
|
||||||
"""
|
|
||||||
dir - the directory for the file
|
|
||||||
"""
|
|
||||||
|
|
||||||
self.dir = dir
|
|
||||||
self.sconsign = os.path.join(dir.path, '.sconsign')
|
|
||||||
|
|
||||||
try:
|
|
||||||
fp = open(self.sconsign, 'rb')
|
|
||||||
except IOError:
|
|
||||||
fp = None
|
|
||||||
|
|
||||||
try:
|
|
||||||
Dir.__init__(self, fp, dir)
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
raise
|
|
||||||
except:
|
|
||||||
SCons.Warnings.warn(SCons.Warnings.CorruptSConsignWarning,
|
|
||||||
"Ignoring corrupt .sconsign file: %s"%self.sconsign)
|
|
||||||
|
|
||||||
global sig_files
|
|
||||||
sig_files.append(self)
|
|
||||||
|
|
||||||
def write(self, sync=1):
|
|
||||||
"""
|
|
||||||
Write the .sconsign file to disk.
|
|
||||||
|
|
||||||
Try to write to a temporary file first, and rename it if we
|
|
||||||
succeed. If we can't write to the temporary file, it's
|
|
||||||
probably because the directory isn't writable (and if so,
|
|
||||||
how did we build anything in this directory, anyway?), so
|
|
||||||
try to write directly to the .sconsign file as a backup.
|
|
||||||
If we can't rename, try to copy the temporary contents back
|
|
||||||
to the .sconsign file. Either way, always try to remove
|
|
||||||
the temporary file at the end.
|
|
||||||
"""
|
|
||||||
if not self.dirty:
|
|
||||||
return
|
|
||||||
|
|
||||||
self.merge()
|
|
||||||
|
|
||||||
temp = os.path.join(self.dir.path, '.scons%d' % os.getpid())
|
|
||||||
try:
|
|
||||||
file = open(temp, 'wb')
|
|
||||||
fname = temp
|
|
||||||
except IOError:
|
|
||||||
try:
|
|
||||||
file = open(self.sconsign, 'wb')
|
|
||||||
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:
|
|
||||||
try:
|
|
||||||
mode = os.stat(self.sconsign)[0]
|
|
||||||
os.chmod(self.sconsign, 0666)
|
|
||||||
os.unlink(self.sconsign)
|
|
||||||
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 (IOError, OSError):
|
|
||||||
pass
|
|
||||||
|
|
||||||
ForDirectory = DB
|
|
||||||
|
|
||||||
def File(name, dbm_module=None):
|
|
||||||
"""
|
|
||||||
Arrange for all signatures to be stored in a global .sconsign.db*
|
|
||||||
file.
|
|
||||||
"""
|
|
||||||
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
|
|
|
@ -1,126 +0,0 @@
|
||||||
"""SCons.Scanner.C
|
|
||||||
|
|
||||||
This module implements the depenency scanner for C/C++ code.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Scanner/C.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import SCons.Node.FS
|
|
||||||
import SCons.Scanner
|
|
||||||
import SCons.Util
|
|
||||||
|
|
||||||
import SCons.cpp
|
|
||||||
|
|
||||||
class SConsCPPScanner(SCons.cpp.PreProcessor):
|
|
||||||
"""
|
|
||||||
SCons-specific subclass of the cpp.py module's processing.
|
|
||||||
|
|
||||||
We subclass this so that: 1) we can deal with files represented
|
|
||||||
by Nodes, not strings; 2) we can keep track of the files that are
|
|
||||||
missing.
|
|
||||||
"""
|
|
||||||
def __init__(self, *args, **kw):
|
|
||||||
apply(SCons.cpp.PreProcessor.__init__, (self,)+args, kw)
|
|
||||||
self.missing = []
|
|
||||||
def initialize_result(self, fname):
|
|
||||||
self.result = SCons.Util.UniqueList([fname])
|
|
||||||
def finalize_result(self, fname):
|
|
||||||
return self.result[1:]
|
|
||||||
def find_include_file(self, t):
|
|
||||||
keyword, quote, fname = t
|
|
||||||
result = SCons.Node.FS.find_file(fname, self.searchpath[quote])
|
|
||||||
if not result:
|
|
||||||
self.missing.append((fname, self.current_file))
|
|
||||||
return result
|
|
||||||
def read_file(self, file):
|
|
||||||
try:
|
|
||||||
fp = open(str(file.rfile()))
|
|
||||||
except EnvironmentError, e:
|
|
||||||
self.missing.append((file, self.current_file))
|
|
||||||
return ''
|
|
||||||
else:
|
|
||||||
return fp.read()
|
|
||||||
|
|
||||||
def dictify_CPPDEFINES(env):
|
|
||||||
cppdefines = env.get('CPPDEFINES', {})
|
|
||||||
if cppdefines is None:
|
|
||||||
return {}
|
|
||||||
if SCons.Util.is_Sequence(cppdefines):
|
|
||||||
result = {}
|
|
||||||
for c in cppdefines:
|
|
||||||
if SCons.Util.is_Sequence(c):
|
|
||||||
result[c[0]] = c[1]
|
|
||||||
else:
|
|
||||||
result[c] = None
|
|
||||||
return result
|
|
||||||
if not SCons.Util.is_Dict(cppdefines):
|
|
||||||
return {cppdefines : None}
|
|
||||||
return cppdefines
|
|
||||||
|
|
||||||
class SConsCPPScannerWrapper:
|
|
||||||
"""
|
|
||||||
The SCons wrapper around a cpp.py scanner.
|
|
||||||
|
|
||||||
This is the actual glue between the calling conventions of generic
|
|
||||||
SCons scanners, and the (subclass of) cpp.py class that knows how
|
|
||||||
to look for #include lines with reasonably real C-preprocessor-like
|
|
||||||
evaluation of #if/#ifdef/#else/#elif lines.
|
|
||||||
"""
|
|
||||||
def __init__(self, name, variable):
|
|
||||||
self.name = name
|
|
||||||
self.path = SCons.Scanner.FindPathDirs(variable)
|
|
||||||
def __call__(self, node, env, path = ()):
|
|
||||||
cpp = SConsCPPScanner(current = node.get_dir(),
|
|
||||||
cpppath = path,
|
|
||||||
dict = dictify_CPPDEFINES(env))
|
|
||||||
result = cpp(node)
|
|
||||||
for included, includer in cpp.missing:
|
|
||||||
fmt = "No dependency generated for file: %s (included from: %s) -- file not found"
|
|
||||||
SCons.Warnings.warn(SCons.Warnings.DependencyWarning,
|
|
||||||
fmt % (included, includer))
|
|
||||||
return result
|
|
||||||
|
|
||||||
def recurse_nodes(self, nodes):
|
|
||||||
return nodes
|
|
||||||
def select(self, node):
|
|
||||||
return self
|
|
||||||
|
|
||||||
def CScanner():
|
|
||||||
"""Return a prototype Scanner instance for scanning source files
|
|
||||||
that use the C pre-processor"""
|
|
||||||
|
|
||||||
# Here's how we would (or might) use the CPP scanner code above that
|
|
||||||
# knows how to evaluate #if/#ifdef/#else/#elif lines when searching
|
|
||||||
# for #includes. This is commented out for now until we add the
|
|
||||||
# right configurability to let users pick between the scanners.
|
|
||||||
#return SConsCPPScannerWrapper("CScanner", "CPPPATH")
|
|
||||||
|
|
||||||
cs = SCons.Scanner.ClassicCPP("CScanner",
|
|
||||||
"$CPPSUFFIXES",
|
|
||||||
"CPPPATH",
|
|
||||||
'^[ \t]*#[ \t]*(?:include|import)[ \t]*(<|")([^>"]+)(>|")')
|
|
||||||
return cs
|
|
|
@ -1,68 +0,0 @@
|
||||||
"""SCons.Scanner.D
|
|
||||||
|
|
||||||
Scanner for the Digital Mars "D" programming language.
|
|
||||||
|
|
||||||
Coded by Andy Friesen
|
|
||||||
17 Nov 2003
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Scanner/D.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import re
|
|
||||||
import string
|
|
||||||
|
|
||||||
import SCons.Scanner
|
|
||||||
|
|
||||||
def DScanner():
|
|
||||||
"""Return a prototype Scanner instance for scanning D source files"""
|
|
||||||
ds = D()
|
|
||||||
return ds
|
|
||||||
|
|
||||||
class D(SCons.Scanner.Classic):
|
|
||||||
def __init__ (self):
|
|
||||||
SCons.Scanner.Classic.__init__ (self,
|
|
||||||
name = "DScanner",
|
|
||||||
suffixes = '$DSUFFIXES',
|
|
||||||
path_variable = 'DPATH',
|
|
||||||
regex = 'import\s+(?:[a-zA-Z0-9_.]+)\s*(?:,\s*(?:[a-zA-Z0-9_.]+)\s*)*;')
|
|
||||||
|
|
||||||
self.cre2 = re.compile ('(?:import\s)?\s*([a-zA-Z0-9_.]+)\s*(?:,|;)', re.M)
|
|
||||||
|
|
||||||
def find_include(self, include, source_dir, path):
|
|
||||||
# translate dots (package separators) to slashes
|
|
||||||
inc = string.replace(include, '.', '/')
|
|
||||||
|
|
||||||
i = SCons.Node.FS.find_file(inc + '.d', (source_dir,) + path)
|
|
||||||
if i is None:
|
|
||||||
i = SCons.Node.FS.find_file (inc + '.di', (source_dir,) + path)
|
|
||||||
return i, include
|
|
||||||
|
|
||||||
def find_include_names(self, node):
|
|
||||||
includes = []
|
|
||||||
for i in self.cre.findall(node.get_contents()):
|
|
||||||
includes = includes + self.cre2.findall(i)
|
|
||||||
return includes
|
|
|
@ -1,105 +0,0 @@
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Scanner/Dir.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
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)
|
|
|
@ -1,314 +0,0 @@
|
||||||
"""SCons.Scanner.Fortran
|
|
||||||
|
|
||||||
This module implements the dependency scanner for Fortran code.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Scanner/Fortran.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import re
|
|
||||||
import string
|
|
||||||
|
|
||||||
import SCons.Node
|
|
||||||
import SCons.Node.FS
|
|
||||||
import SCons.Scanner
|
|
||||||
import SCons.Util
|
|
||||||
import SCons.Warnings
|
|
||||||
|
|
||||||
class F90Scanner(SCons.Scanner.Classic):
|
|
||||||
"""
|
|
||||||
A Classic Scanner subclass for Fortran source files which takes
|
|
||||||
into account both USE and INCLUDE statements. This scanner will
|
|
||||||
work for both F77 and F90 (and beyond) compilers.
|
|
||||||
|
|
||||||
Currently, this scanner assumes that the include files do not contain
|
|
||||||
USE statements. To enable the ability to deal with USE statements
|
|
||||||
in include files, add logic right after the module names are found
|
|
||||||
to loop over each include file, search for and locate each USE
|
|
||||||
statement, and append each module name to the list of dependencies.
|
|
||||||
Caching the search results in a common dictionary somewhere so that
|
|
||||||
the same include file is not searched multiple times would be a
|
|
||||||
smart thing to do.
|
|
||||||
"""
|
|
||||||
|
|
||||||
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.cre_def = re.compile(def_regex, re.M)
|
|
||||||
|
|
||||||
def _scan(node, env, path, self=self):
|
|
||||||
node = node.rfile()
|
|
||||||
|
|
||||||
if not node.exists():
|
|
||||||
return []
|
|
||||||
|
|
||||||
return self.scan(node, env, path)
|
|
||||||
|
|
||||||
kw['function'] = _scan
|
|
||||||
kw['path_function'] = SCons.Scanner.FindPathDirs(path_variable)
|
|
||||||
kw['recursive'] = 1
|
|
||||||
kw['skeys'] = suffixes
|
|
||||||
kw['name'] = name
|
|
||||||
|
|
||||||
apply(SCons.Scanner.Current.__init__, (self,) + args, kw)
|
|
||||||
|
|
||||||
def scan(self, node, env, path=()):
|
|
||||||
|
|
||||||
# cache the includes list in node so we only scan it once:
|
|
||||||
if node.includes != None:
|
|
||||||
mods_and_includes = node.includes
|
|
||||||
else:
|
|
||||||
# retrieve all included filenames
|
|
||||||
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')
|
|
||||||
modules = map(lambda x, s=suffix: string.lower(x) + s, modules)
|
|
||||||
# Remove unique items from the list
|
|
||||||
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 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))
|
|
||||||
|
|
||||||
nodes.sort()
|
|
||||||
nodes = map(lambda pair: pair[1], nodes)
|
|
||||||
return nodes
|
|
||||||
|
|
||||||
def FortranScan(path_variable="FORTRANPATH"):
|
|
||||||
"""Return a prototype Scanner instance for scanning source files
|
|
||||||
for Fortran USE & INCLUDE statements"""
|
|
||||||
|
|
||||||
# The USE statement regex matches the following:
|
|
||||||
#
|
|
||||||
# USE module_name
|
|
||||||
# USE :: module_name
|
|
||||||
# USE, INTRINSIC :: module_name
|
|
||||||
# USE, NON_INTRINSIC :: module_name
|
|
||||||
#
|
|
||||||
# Limitations
|
|
||||||
#
|
|
||||||
# -- While the regex can handle multiple USE statements on one line,
|
|
||||||
# it cannot properly handle them if they are commented out.
|
|
||||||
# In either of the following cases:
|
|
||||||
#
|
|
||||||
# ! USE mod_a ; USE mod_b [entire line is commented out]
|
|
||||||
# USE mod_a ! ; USE mod_b [in-line comment of second USE statement]
|
|
||||||
#
|
|
||||||
# the second module name (mod_b) will be picked up as a dependency
|
|
||||||
# even though it should be ignored. The only way I can see
|
|
||||||
# to rectify this would be to modify the scanner to eliminate
|
|
||||||
# the call to re.findall, read in the contents of the file,
|
|
||||||
# treating the comment character as an end-of-line character
|
|
||||||
# in addition to the normal linefeed, loop over each line,
|
|
||||||
# weeding out the comments, and looking for the USE statements.
|
|
||||||
# One advantage to this is that the regex passed to the scanner
|
|
||||||
# would no longer need to match a semicolon.
|
|
||||||
#
|
|
||||||
# -- I question whether or not we need to detect dependencies to
|
|
||||||
# INTRINSIC modules because these are built-in to the compiler.
|
|
||||||
# If we consider them a dependency, will SCons look for them, not
|
|
||||||
# find them, and kill the build? Or will we there be standard
|
|
||||||
# compiler-specific directories we will need to point to so the
|
|
||||||
# compiler and SCons can locate the proper object and mod files?
|
|
||||||
|
|
||||||
# Here is a breakdown of the regex:
|
|
||||||
#
|
|
||||||
# (?i) : regex is case insensitive
|
|
||||||
# ^ : start of line
|
|
||||||
# (?: : group a collection of regex symbols without saving the match as a "group"
|
|
||||||
# ^|; : matches either the start of the line or a semicolon - semicolon
|
|
||||||
# ) : end the unsaved grouping
|
|
||||||
# \s* : any amount of white space
|
|
||||||
# USE : match the string USE, case insensitive
|
|
||||||
# (?: : group a collection of regex symbols without saving the match as a "group"
|
|
||||||
# \s+| : match one or more whitespace OR .... (the next entire grouped set of regex symbols)
|
|
||||||
# (?: : group a collection of regex symbols without saving the match as a "group"
|
|
||||||
# (?: : establish another unsaved grouping of regex symbols
|
|
||||||
# \s* : any amount of white space
|
|
||||||
# , : match a comma
|
|
||||||
# \s* : any amount of white space
|
|
||||||
# (?:NON_)? : optionally match the prefix NON_, case insensitive
|
|
||||||
# INTRINSIC : match the string INTRINSIC, case insensitive
|
|
||||||
# )? : optionally match the ", INTRINSIC/NON_INTRINSIC" grouped expression
|
|
||||||
# \s* : any amount of white space
|
|
||||||
# :: : match a double colon that must appear after the INTRINSIC/NON_INTRINSIC attribute
|
|
||||||
# ) : end the unsaved grouping
|
|
||||||
# ) : end the unsaved grouping
|
|
||||||
# \s* : match any amount of white space
|
|
||||||
# (\w+) : match the module name that is being USE'd
|
|
||||||
#
|
|
||||||
#
|
|
||||||
use_regex = "(?i)(?:^|;)\s*USE(?:\s+|(?:(?:\s*,\s*(?:NON_)?INTRINSIC)?\s*::))\s*(\w+)"
|
|
||||||
|
|
||||||
|
|
||||||
# The INCLUDE statement regex matches the following:
|
|
||||||
#
|
|
||||||
# INCLUDE 'some_Text'
|
|
||||||
# INCLUDE "some_Text"
|
|
||||||
# INCLUDE "some_Text" ; INCLUDE "some_Text"
|
|
||||||
# INCLUDE kind_"some_Text"
|
|
||||||
# INCLUDE kind_'some_Text"
|
|
||||||
#
|
|
||||||
# where some_Text can include any alphanumeric and/or special character
|
|
||||||
# as defined by the Fortran 2003 standard.
|
|
||||||
#
|
|
||||||
# Limitations:
|
|
||||||
#
|
|
||||||
# -- The Fortran standard dictates that a " or ' in the INCLUDE'd
|
|
||||||
# string must be represented as a "" or '', if the quotes that wrap
|
|
||||||
# the entire string are either a ' or ", respectively. While the
|
|
||||||
# regular expression below can detect the ' or " characters just fine,
|
|
||||||
# the scanning logic, presently is unable to detect them and reduce
|
|
||||||
# them to a single instance. This probably isn't an issue since,
|
|
||||||
# in practice, ' or " are not generally used in filenames.
|
|
||||||
#
|
|
||||||
# -- This regex will not properly deal with multiple INCLUDE statements
|
|
||||||
# when the entire line has been commented out, ala
|
|
||||||
#
|
|
||||||
# ! INCLUDE 'some_file' ; INCLUDE 'some_file'
|
|
||||||
#
|
|
||||||
# In such cases, it will properly ignore the first INCLUDE file,
|
|
||||||
# but will actually still pick up the second. Interestingly enough,
|
|
||||||
# the regex will properly deal with these cases:
|
|
||||||
#
|
|
||||||
# INCLUDE 'some_file'
|
|
||||||
# INCLUDE 'some_file' !; INCLUDE 'some_file'
|
|
||||||
#
|
|
||||||
# To get around the above limitation, the FORTRAN programmer could
|
|
||||||
# simply comment each INCLUDE statement separately, like this
|
|
||||||
#
|
|
||||||
# ! INCLUDE 'some_file' !; INCLUDE 'some_file'
|
|
||||||
#
|
|
||||||
# The way I see it, the only way to get around this limitation would
|
|
||||||
# be to modify the scanning logic to replace the calls to re.findall
|
|
||||||
# with a custom loop that processes each line separately, throwing
|
|
||||||
# away fully commented out lines before attempting to match against
|
|
||||||
# the INCLUDE syntax.
|
|
||||||
#
|
|
||||||
# Here is a breakdown of the regex:
|
|
||||||
#
|
|
||||||
# (?i) : regex is case insensitive
|
|
||||||
# (?: : begin a non-saving group that matches the following:
|
|
||||||
# ^ : either the start of the line
|
|
||||||
# | : or
|
|
||||||
# ['">]\s*; : a semicolon that follows a single quote,
|
|
||||||
# double quote or greater than symbol (with any
|
|
||||||
# amount of whitespace in between). This will
|
|
||||||
# allow the regex to match multiple INCLUDE
|
|
||||||
# statements per line (although it also requires
|
|
||||||
# the positive lookahead assertion that is
|
|
||||||
# used below). It will even properly deal with
|
|
||||||
# (i.e. ignore) cases in which the additional
|
|
||||||
# INCLUDES are part of an in-line comment, ala
|
|
||||||
# " INCLUDE 'someFile' ! ; INCLUDE 'someFile2' "
|
|
||||||
# ) : end of non-saving group
|
|
||||||
# \s* : any amount of white space
|
|
||||||
# INCLUDE : match the string INCLUDE, case insensitive
|
|
||||||
# \s+ : match one or more white space characters
|
|
||||||
# (?\w+_)? : match the optional "kind-param _" prefix allowed by the standard
|
|
||||||
# [<"'] : match the include delimiter - an apostrophe, double quote, or less than symbol
|
|
||||||
# (.+?) : match one or more characters that make up
|
|
||||||
# the included path and file name and save it
|
|
||||||
# in a group. The Fortran standard allows for
|
|
||||||
# any non-control character to be used. The dot
|
|
||||||
# operator will pick up any character, including
|
|
||||||
# control codes, but I can't conceive of anyone
|
|
||||||
# putting control codes in their file names.
|
|
||||||
# The question mark indicates it is non-greedy so
|
|
||||||
# that regex will match only up to the next quote,
|
|
||||||
# double quote, or greater than symbol
|
|
||||||
# (?=["'>]) : positive lookahead assertion to match the include
|
|
||||||
# delimiter - an apostrophe, double quote, or
|
|
||||||
# greater than symbol. This level of complexity
|
|
||||||
# is required so that the include delimiter is
|
|
||||||
# not consumed by the match, thus allowing the
|
|
||||||
# sub-regex discussed above to uniquely match a
|
|
||||||
# set of semicolon-separated INCLUDE statements
|
|
||||||
# (as allowed by the F2003 standard)
|
|
||||||
|
|
||||||
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,
|
|
||||||
def_regex)
|
|
||||||
return scanner
|
|
|
@ -1,42 +0,0 @@
|
||||||
"""SCons.Scanner.IDL
|
|
||||||
|
|
||||||
This module implements the depenency scanner for IDL (Interface
|
|
||||||
Definition Language) files.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Scanner/IDL.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import SCons.Node.FS
|
|
||||||
import SCons.Scanner
|
|
||||||
|
|
||||||
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]+(<|")([^>"]+)(>|")')
|
|
||||||
return cs
|
|
|
@ -1,334 +0,0 @@
|
||||||
"""SCons.Scanner.LaTeX
|
|
||||||
|
|
||||||
This module implements the dependency scanner for LaTeX code.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Scanner/LaTeX.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import os.path
|
|
||||||
import string
|
|
||||||
import re
|
|
||||||
|
|
||||||
import SCons.Scanner
|
|
||||||
import SCons.Util
|
|
||||||
|
|
||||||
# list of graphics file extensions for TeX and LaTeX
|
|
||||||
TexGraphics = ['.eps', '.ps']
|
|
||||||
LatexGraphics = ['.pdf', '.png', '.jpg', '.gif', '.tif']
|
|
||||||
|
|
||||||
# Used as a return value of modify_env_var if the variable is not set.
|
|
||||||
class _Null:
|
|
||||||
pass
|
|
||||||
_null = _Null
|
|
||||||
|
|
||||||
# The user specifies the paths in env[variable], similar to other builders.
|
|
||||||
# They may be relative and must be converted to absolute, as expected
|
|
||||||
# by LaTeX and Co. The environment may already have some paths in
|
|
||||||
# env['ENV'][var]. These paths are honored, but the env[var] paths have
|
|
||||||
# higher precedence. All changes are un-done on exit.
|
|
||||||
def modify_env_var(env, var, abspath):
|
|
||||||
try:
|
|
||||||
save = env['ENV'][var]
|
|
||||||
except KeyError:
|
|
||||||
save = _null
|
|
||||||
env.PrependENVPath(var, abspath)
|
|
||||||
try:
|
|
||||||
if SCons.Util.is_List(env[var]):
|
|
||||||
#TODO(1.5)
|
|
||||||
#env.PrependENVPath(var, [os.path.abspath(str(p)) for p in env[var]])
|
|
||||||
env.PrependENVPath(var, map(lambda p: os.path.abspath(str(p)), env[var]))
|
|
||||||
else:
|
|
||||||
# Split at os.pathsep to convert into absolute path
|
|
||||||
#TODO(1.5) env.PrependENVPath(var, [os.path.abspath(p) for p in str(env[var]).split(os.pathsep)])
|
|
||||||
env.PrependENVPath(var, map(lambda p: os.path.abspath(p), string.split(str(env[var]), os.pathsep)))
|
|
||||||
except KeyError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# Convert into a string explicitly to append ":" (without which it won't search system
|
|
||||||
# paths as well). The problem is that env.AppendENVPath(var, ":")
|
|
||||||
# does not work, refuses to append ":" (os.pathsep).
|
|
||||||
|
|
||||||
if SCons.Util.is_List(env['ENV'][var]):
|
|
||||||
# TODO(1.5)
|
|
||||||
#env['ENV'][var] = os.pathsep.join(env['ENV'][var])
|
|
||||||
env['ENV'][var] = string.join(env['ENV'][var], os.pathsep)
|
|
||||||
# Append the trailing os.pathsep character here to catch the case with no env[var]
|
|
||||||
env['ENV'][var] = env['ENV'][var] + os.pathsep
|
|
||||||
|
|
||||||
return save
|
|
||||||
|
|
||||||
class FindENVPathDirs:
|
|
||||||
"""A class to bind a specific *PATH variable name to a function that
|
|
||||||
will return all of the *path directories."""
|
|
||||||
def __init__(self, variable):
|
|
||||||
self.variable = variable
|
|
||||||
def __call__(self, env, dir=None, target=None, source=None, argument=None):
|
|
||||||
import SCons.PathList
|
|
||||||
try:
|
|
||||||
path = env['ENV'][self.variable]
|
|
||||||
except KeyError:
|
|
||||||
return ()
|
|
||||||
|
|
||||||
dir = dir or env.fs._cwd
|
|
||||||
path = SCons.PathList.PathList(path).subst_path(env, target, source)
|
|
||||||
return tuple(dir.Rfindalldirs(path))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def LaTeXScanner():
|
|
||||||
"""Return a prototype Scanner instance for scanning LaTeX source files
|
|
||||||
when built with latex.
|
|
||||||
"""
|
|
||||||
ds = LaTeX(name = "LaTeXScanner",
|
|
||||||
suffixes = '$LATEXSUFFIXES',
|
|
||||||
# in the search order, see below in LaTeX class docstring
|
|
||||||
graphics_extensions = TexGraphics,
|
|
||||||
recursive = 0)
|
|
||||||
return ds
|
|
||||||
|
|
||||||
def PDFLaTeXScanner():
|
|
||||||
"""Return a prototype Scanner instance for scanning LaTeX source files
|
|
||||||
when built with pdflatex.
|
|
||||||
"""
|
|
||||||
ds = LaTeX(name = "PDFLaTeXScanner",
|
|
||||||
suffixes = '$LATEXSUFFIXES',
|
|
||||||
# in the search order, see below in LaTeX class docstring
|
|
||||||
graphics_extensions = LatexGraphics,
|
|
||||||
recursive = 0)
|
|
||||||
return ds
|
|
||||||
|
|
||||||
class LaTeX(SCons.Scanner.Base):
|
|
||||||
"""Class for scanning LaTeX files for included files.
|
|
||||||
|
|
||||||
Unlike most scanners, which use regular expressions that just
|
|
||||||
return the included file name, this returns a tuple consisting
|
|
||||||
of the keyword for the inclusion ("include", "includegraphics",
|
|
||||||
"input", or "bibliography"), and then the file name itself.
|
|
||||||
Based on a quick look at LaTeX documentation, it seems that we
|
|
||||||
should append .tex suffix for the "include" keywords, append .tex if
|
|
||||||
there is no extension for the "input" keyword, and need to add .bib
|
|
||||||
for the "bibliography" keyword that does not accept extensions by itself.
|
|
||||||
|
|
||||||
Finally, if there is no extension for an "includegraphics" keyword
|
|
||||||
latex will append .ps or .eps to find the file, while pdftex may use .pdf,
|
|
||||||
.jpg, .tif, .mps, or .png.
|
|
||||||
|
|
||||||
The actual subset and search order may be altered by
|
|
||||||
DeclareGraphicsExtensions command. This complication is ignored.
|
|
||||||
The default order corresponds to experimentation with teTeX
|
|
||||||
$ latex --version
|
|
||||||
pdfeTeX 3.141592-1.21a-2.2 (Web2C 7.5.4)
|
|
||||||
kpathsea version 3.5.4
|
|
||||||
The order is:
|
|
||||||
['.eps', '.ps'] for latex
|
|
||||||
['.png', '.pdf', '.jpg', '.tif'].
|
|
||||||
|
|
||||||
Another difference is that the search path is determined by the type
|
|
||||||
of the file being searched:
|
|
||||||
env['TEXINPUTS'] for "input" and "include" keywords
|
|
||||||
env['TEXINPUTS'] for "includegraphics" keyword
|
|
||||||
env['BIBINPUTS'] for "bibliography" keyword
|
|
||||||
env['BSTINPUTS'] for "bibliographystyle" keyword
|
|
||||||
|
|
||||||
FIXME: also look for the class or style in document[class|style]{}
|
|
||||||
FIXME: also look for the argument of bibliographystyle{}
|
|
||||||
"""
|
|
||||||
keyword_paths = {'include': 'TEXINPUTS',
|
|
||||||
'input': 'TEXINPUTS',
|
|
||||||
'includegraphics': 'TEXINPUTS',
|
|
||||||
'bibliography': 'BIBINPUTS',
|
|
||||||
'bibliographystyle': 'BSTINPUTS',
|
|
||||||
'usepackage': 'TEXINPUTS'}
|
|
||||||
env_variables = SCons.Util.unique(keyword_paths.values())
|
|
||||||
|
|
||||||
def __init__(self, name, suffixes, graphics_extensions, *args, **kw):
|
|
||||||
|
|
||||||
# We have to include \n with the % we exclude from the first part
|
|
||||||
# part of the regex because the expression is compiled with re.M.
|
|
||||||
# Without the \n, the ^ could match the beginning of a *previous*
|
|
||||||
# line followed by one or more newline characters (i.e. blank
|
|
||||||
# lines), interfering with a match on the next line.
|
|
||||||
regex = r'^[^%\n]*\\(include|includegraphics(?:\[[^\]]+\])?|input|bibliography|usepackage){([^}]*)}'
|
|
||||||
self.cre = re.compile(regex, re.M)
|
|
||||||
self.graphics_extensions = graphics_extensions
|
|
||||||
|
|
||||||
def _scan(node, env, path=(), self=self):
|
|
||||||
node = node.rfile()
|
|
||||||
if not node.exists():
|
|
||||||
return []
|
|
||||||
return self.scan(node, path)
|
|
||||||
|
|
||||||
class FindMultiPathDirs:
|
|
||||||
"""The stock FindPathDirs function has the wrong granularity:
|
|
||||||
it is called once per target, while we need the path that depends
|
|
||||||
on what kind of included files is being searched. This wrapper
|
|
||||||
hides multiple instances of FindPathDirs, one per the LaTeX path
|
|
||||||
variable in the environment. When invoked, the function calculates
|
|
||||||
and returns all the required paths as a dictionary (converted into
|
|
||||||
a tuple to become hashable). Then the scan function converts it
|
|
||||||
back and uses a dictionary of tuples rather than a single tuple
|
|
||||||
of paths.
|
|
||||||
"""
|
|
||||||
def __init__(self, dictionary):
|
|
||||||
self.dictionary = {}
|
|
||||||
for k,n in dictionary.items():
|
|
||||||
self.dictionary[k] = ( SCons.Scanner.FindPathDirs(n),
|
|
||||||
FindENVPathDirs(n) )
|
|
||||||
|
|
||||||
def __call__(self, env, dir=None, target=None, source=None,
|
|
||||||
argument=None):
|
|
||||||
di = {}
|
|
||||||
for k,(c,cENV) in self.dictionary.items():
|
|
||||||
di[k] = ( c(env, dir=None, target=None, source=None,
|
|
||||||
argument=None) ,
|
|
||||||
cENV(env, dir=None, target=None, source=None,
|
|
||||||
argument=None) )
|
|
||||||
# To prevent "dict is not hashable error"
|
|
||||||
return tuple(di.items())
|
|
||||||
|
|
||||||
class LaTeXScanCheck:
|
|
||||||
"""Skip all but LaTeX source files, i.e., do not scan *.eps,
|
|
||||||
*.pdf, *.jpg, etc.
|
|
||||||
"""
|
|
||||||
def __init__(self, suffixes):
|
|
||||||
self.suffixes = suffixes
|
|
||||||
def __call__(self, node, env):
|
|
||||||
current = not node.has_builder() or node.is_up_to_date()
|
|
||||||
scannable = node.get_suffix() in env.subst_list(self.suffixes)[0]
|
|
||||||
# Returning false means that the file is not scanned.
|
|
||||||
return scannable and current
|
|
||||||
|
|
||||||
kw['function'] = _scan
|
|
||||||
kw['path_function'] = FindMultiPathDirs(LaTeX.keyword_paths)
|
|
||||||
kw['recursive'] = 1
|
|
||||||
kw['skeys'] = suffixes
|
|
||||||
kw['scan_check'] = LaTeXScanCheck(suffixes)
|
|
||||||
kw['name'] = name
|
|
||||||
|
|
||||||
apply(SCons.Scanner.Base.__init__, (self,) + args, kw)
|
|
||||||
|
|
||||||
def _latex_names(self, include):
|
|
||||||
filename = include[1]
|
|
||||||
if include[0] == 'input':
|
|
||||||
base, ext = os.path.splitext( filename )
|
|
||||||
if ext == "":
|
|
||||||
return [filename + '.tex']
|
|
||||||
if (include[0] == 'include'):
|
|
||||||
return [filename + '.tex']
|
|
||||||
if include[0] == 'bibliography':
|
|
||||||
base, ext = os.path.splitext( filename )
|
|
||||||
if ext == "":
|
|
||||||
return [filename + '.bib']
|
|
||||||
if include[0] == 'usepackage':
|
|
||||||
base, ext = os.path.splitext( filename )
|
|
||||||
if ext == "":
|
|
||||||
return [filename + '.sty']
|
|
||||||
if include[0] == 'includegraphics':
|
|
||||||
base, ext = os.path.splitext( filename )
|
|
||||||
if ext == "":
|
|
||||||
#TODO(1.5) return [filename + e for e in self.graphics_extensions]
|
|
||||||
return map(lambda e, f=filename: f+e, self.graphics_extensions)
|
|
||||||
return [filename]
|
|
||||||
|
|
||||||
def sort_key(self, include):
|
|
||||||
return SCons.Node.FS._my_normcase(str(include))
|
|
||||||
|
|
||||||
def find_include(self, include, source_dir, path):
|
|
||||||
try:
|
|
||||||
sub_path = path[include[0]]
|
|
||||||
except (IndexError, KeyError):
|
|
||||||
sub_path = ()
|
|
||||||
try_names = self._latex_names(include)
|
|
||||||
for n in try_names:
|
|
||||||
# see if we find it using the path in env[var]
|
|
||||||
i = SCons.Node.FS.find_file(n, (source_dir,) + sub_path[0])
|
|
||||||
if i:
|
|
||||||
return i, include
|
|
||||||
# see if we find it using the path in env['ENV'][var]
|
|
||||||
i = SCons.Node.FS.find_file(n, (source_dir,) + sub_path[1])
|
|
||||||
if i:
|
|
||||||
return i, include
|
|
||||||
return i, include
|
|
||||||
|
|
||||||
def scan(self, node, path=()):
|
|
||||||
# Modify the default scan function to allow for the regular
|
|
||||||
# expression to return a comma separated list of file names
|
|
||||||
# as can be the case with the bibliography keyword.
|
|
||||||
|
|
||||||
# Cache the includes list in node so we only scan it once:
|
|
||||||
path_dict = dict(list(path))
|
|
||||||
noopt_cre = re.compile('\[.*$')
|
|
||||||
if node.includes != None:
|
|
||||||
includes = node.includes
|
|
||||||
else:
|
|
||||||
includes = self.cre.findall(node.get_contents())
|
|
||||||
# 1. Split comma-separated lines, e.g.
|
|
||||||
# ('bibliography', 'phys,comp')
|
|
||||||
# should become two entries
|
|
||||||
# ('bibliography', 'phys')
|
|
||||||
# ('bibliography', 'comp')
|
|
||||||
# 2. Remove the options, e.g., such as
|
|
||||||
# ('includegraphics[clip,width=0.7\\linewidth]', 'picture.eps')
|
|
||||||
# should become
|
|
||||||
# ('includegraphics', 'picture.eps')
|
|
||||||
split_includes = []
|
|
||||||
for include in includes:
|
|
||||||
inc_type = noopt_cre.sub('', include[0])
|
|
||||||
inc_list = string.split(include[1],',')
|
|
||||||
for j in range(len(inc_list)):
|
|
||||||
split_includes.append( (inc_type, inc_list[j]) )
|
|
||||||
#
|
|
||||||
includes = split_includes
|
|
||||||
node.includes = includes
|
|
||||||
|
|
||||||
# This is a hand-coded DSU (decorate-sort-undecorate, or
|
|
||||||
# Schwartzian transform) pattern. The sort key is the raw name
|
|
||||||
# of the file as specifed on the \include, \input, etc. line.
|
|
||||||
# TODO: what about the comment in the original Classic scanner:
|
|
||||||
# """which lets
|
|
||||||
# us keep the sort order constant regardless of whether the file
|
|
||||||
# is actually found in a Repository or locally."""
|
|
||||||
nodes = []
|
|
||||||
source_dir = node.get_dir()
|
|
||||||
for include in includes:
|
|
||||||
#
|
|
||||||
# Handle multiple filenames in include[1]
|
|
||||||
#
|
|
||||||
n, i = self.find_include(include, source_dir, path_dict)
|
|
||||||
if n is None:
|
|
||||||
# Do not bother with 'usepackage' warnings, as they most
|
|
||||||
# likely refer to system-level files
|
|
||||||
if include[0] != 'usepackage':
|
|
||||||
SCons.Warnings.warn(SCons.Warnings.DependencyWarning,
|
|
||||||
"No dependency generated for file: %s (included from: %s) -- file not found" % (i, node))
|
|
||||||
else:
|
|
||||||
sortkey = self.sort_key(n)
|
|
||||||
nodes.append((sortkey, n))
|
|
||||||
#
|
|
||||||
nodes.sort()
|
|
||||||
nodes = map(lambda pair: pair[1], nodes)
|
|
||||||
return nodes
|
|
|
@ -1,97 +0,0 @@
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Scanner/Prog.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import string
|
|
||||||
|
|
||||||
import SCons.Node
|
|
||||||
import SCons.Node.FS
|
|
||||||
import SCons.Scanner
|
|
||||||
import SCons.Util
|
|
||||||
|
|
||||||
# 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"""
|
|
||||||
kw['path_function'] = SCons.Scanner.FindPathDirs('LIBPATH')
|
|
||||||
ps = apply(SCons.Scanner.Base, [scan, "ProgramScanner"], kw)
|
|
||||||
return ps
|
|
||||||
|
|
||||||
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['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)
|
|
||||||
else:
|
|
||||||
libs = SCons.Util.flatten(libs)
|
|
||||||
|
|
||||||
try:
|
|
||||||
prefix = env['LIBPREFIXES']
|
|
||||||
if not SCons.Util.is_List(prefix):
|
|
||||||
prefix = [ prefix ]
|
|
||||||
except KeyError:
|
|
||||||
prefix = [ '' ]
|
|
||||||
|
|
||||||
try:
|
|
||||||
suffix = env['LIBSUFFIXES']
|
|
||||||
if not SCons.Util.is_List(suffix):
|
|
||||||
suffix = [ suffix ]
|
|
||||||
except KeyError:
|
|
||||||
suffix = [ '' ]
|
|
||||||
|
|
||||||
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)
|
|
||||||
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
|
|
|
@ -1,49 +0,0 @@
|
||||||
"""SCons.Scanner.RC
|
|
||||||
|
|
||||||
This module implements the depenency scanner for RC (Interface
|
|
||||||
Definition Language) files.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Scanner/RC.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import SCons.Node.FS
|
|
||||||
import SCons.Scanner
|
|
||||||
import re
|
|
||||||
|
|
||||||
def RCScan():
|
|
||||||
"""Return a prototype Scanner instance for scanning RC source files"""
|
|
||||||
|
|
||||||
res_re= r'^(?:\s*#\s*(?:include)|' \
|
|
||||||
'.*?\s+(?:ICON|BITMAP|CURSOR|HTML|FONT|MESSAGETABLE|TYPELIB|REGISTRY|D3DFX)' \
|
|
||||||
'\s*.*?)' \
|
|
||||||
'\s*(<|"| )([^>"\s]+)(?:[>" ])*$'
|
|
||||||
resScanner = SCons.Scanner.ClassicCPP( "ResourceScanner",
|
|
||||||
"$RCSUFFIXES",
|
|
||||||
"CPPPATH",
|
|
||||||
res_re )
|
|
||||||
|
|
||||||
return resScanner
|
|
|
@ -1,406 +0,0 @@
|
||||||
"""SCons.Scanner
|
|
||||||
|
|
||||||
The Scanner package for the SCons software construction utility.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Scanner/__init__.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import re
|
|
||||||
import string
|
|
||||||
|
|
||||||
import SCons.Node.FS
|
|
||||||
import SCons.Util
|
|
||||||
|
|
||||||
|
|
||||||
class _Null:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# This is used instead of None as a default argument value so None can be
|
|
||||||
# used as an actual argument value.
|
|
||||||
_null = _Null
|
|
||||||
|
|
||||||
def Scanner(function, *args, **kw):
|
|
||||||
"""
|
|
||||||
Public interface factory function for creating different types
|
|
||||||
of Scanners based on the different types of "functions" that may
|
|
||||||
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 to a function that
|
|
||||||
will return all of the *path directories."""
|
|
||||||
def __init__(self, variable):
|
|
||||||
self.variable = variable
|
|
||||||
def __call__(self, env, dir=None, target=None, source=None, argument=None):
|
|
||||||
import SCons.PathList
|
|
||||||
try:
|
|
||||||
path = env[self.variable]
|
|
||||||
except KeyError:
|
|
||||||
return ()
|
|
||||||
|
|
||||||
dir = dir or env.fs._cwd
|
|
||||||
path = SCons.PathList.PathList(path).subst_path(env, target, source)
|
|
||||||
return tuple(dir.Rfindalldirs(path))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Base:
|
|
||||||
"""
|
|
||||||
The base class for dependency scanners. This implements
|
|
||||||
straightforward, single-pass scanning of a single file.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self,
|
|
||||||
function,
|
|
||||||
name = "NONE",
|
|
||||||
argument = _null,
|
|
||||||
skeys = _null,
|
|
||||||
path_function = None,
|
|
||||||
node_class = SCons.Node.FS.Entry,
|
|
||||||
node_factory = None,
|
|
||||||
scan_check = None,
|
|
||||||
recursive = None):
|
|
||||||
"""
|
|
||||||
Construct a new scanner object given a scanner function.
|
|
||||||
|
|
||||||
'function' - a scanner function taking two or three
|
|
||||||
arguments and returning a list of strings.
|
|
||||||
|
|
||||||
'name' - a name for identifying this scanner object.
|
|
||||||
|
|
||||||
'argument' - an optional argument that, if specified, will be
|
|
||||||
passed to both the scanner function and the path_function.
|
|
||||||
|
|
||||||
'skeys' - an optional list argument that can be used to determine
|
|
||||||
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 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
|
|
||||||
Node conversion and will return the raw results from the
|
|
||||||
underlying scanner function.
|
|
||||||
|
|
||||||
'node_factory' - the factory function to be called to translate
|
|
||||||
the raw results returned by the scanner function into the
|
|
||||||
expected node_class objects.
|
|
||||||
|
|
||||||
'scan_check' - a function to be called to first check whether
|
|
||||||
this node really needs to be scanned.
|
|
||||||
|
|
||||||
'recursive' - specifies that this scanner should be invoked
|
|
||||||
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 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:
|
|
||||||
|
|
||||||
s = Scanner(my_scanner_function)
|
|
||||||
|
|
||||||
s = Scanner(function = my_scanner_function)
|
|
||||||
|
|
||||||
s = Scanner(function = my_scanner_function, argument = 'foo')
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Note: this class could easily work with scanner functions that take
|
|
||||||
# something other than a filename as an argument (e.g. a database
|
|
||||||
# node) and a dependencies list that aren't file names. All that
|
|
||||||
# would need to be changed is the documentation.
|
|
||||||
|
|
||||||
self.function = function
|
|
||||||
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
|
|
||||||
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, target=None, source=None):
|
|
||||||
if not self.path_function:
|
|
||||||
return ()
|
|
||||||
if not self.argument is _null:
|
|
||||||
return self.path_function(env, dir, target, source, self.argument)
|
|
||||||
else:
|
|
||||||
return self.path_function(env, dir, target, source)
|
|
||||||
|
|
||||||
def __call__(self, node, env, path = ()):
|
|
||||||
"""
|
|
||||||
This method scans a single object. 'node' is the node
|
|
||||||
that will be passed to the scanner function, and 'env' is the
|
|
||||||
environment that will be passed to the scanner function. A list of
|
|
||||||
direct dependency nodes for the specified node will be returned.
|
|
||||||
"""
|
|
||||||
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(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 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 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):
|
|
||||||
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)
|
|
||||||
|
|
||||||
def select(self, node):
|
|
||||||
try:
|
|
||||||
return self.dict[node.scanner_key()]
|
|
||||||
except KeyError:
|
|
||||||
return None
|
|
||||||
|
|
||||||
def add_scanner(self, skey, scanner):
|
|
||||||
self.dict[skey] = scanner
|
|
||||||
self.add_skey(skey)
|
|
||||||
|
|
||||||
|
|
||||||
class Current(Base):
|
|
||||||
"""
|
|
||||||
A class for scanning files that are source files (have no builder)
|
|
||||||
or are derived files and are current (which implies that they exist,
|
|
||||||
either locally or in a repository).
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, *args, **kw):
|
|
||||||
def current_check(node, env):
|
|
||||||
return not node.has_builder() or node.is_up_to_date()
|
|
||||||
kw['scan_check'] = current_check
|
|
||||||
apply(Base.__init__, (self,) + args, kw)
|
|
||||||
|
|
||||||
class Classic(Current):
|
|
||||||
"""
|
|
||||||
A Scanner subclass to contain the common logic for classic CPP-style
|
|
||||||
include scanning, but which can be customized to use different
|
|
||||||
regular expressions to find the includes.
|
|
||||||
|
|
||||||
Note that in order for this to work "out of the box" (without
|
|
||||||
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, *args, **kw):
|
|
||||||
|
|
||||||
self.cre = re.compile(regex, re.M)
|
|
||||||
|
|
||||||
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)
|
|
||||||
kw['recursive'] = 1
|
|
||||||
kw['skeys'] = suffixes
|
|
||||||
kw['name'] = name
|
|
||||||
|
|
||||||
apply(Current.__init__, (self,) + args, kw)
|
|
||||||
|
|
||||||
def find_include(self, include, source_dir, path):
|
|
||||||
n = SCons.Node.FS.find_file(include, (source_dir,) + tuple(path))
|
|
||||||
return n, include
|
|
||||||
|
|
||||||
def sort_key(self, include):
|
|
||||||
return SCons.Node.FS._my_normcase(include)
|
|
||||||
|
|
||||||
def find_include_names(self, node):
|
|
||||||
return self.cre.findall(node.get_contents())
|
|
||||||
|
|
||||||
def scan(self, node, path=()):
|
|
||||||
|
|
||||||
# cache the includes list in node so we only scan it once:
|
|
||||||
if node.includes != None:
|
|
||||||
includes = node.includes
|
|
||||||
else:
|
|
||||||
includes = self.find_include_names (node)
|
|
||||||
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 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
|
|
||||||
|
|
||||||
class ClassicCPP(Classic):
|
|
||||||
"""
|
|
||||||
A Classic Scanner subclass which takes into account the type of
|
|
||||||
bracketing used to include the file, and uses classic CPP rules
|
|
||||||
for searching for the files based on the bracketing.
|
|
||||||
|
|
||||||
Note that in order for this to work, the regular expression passed
|
|
||||||
to the constructor must return the leading bracket in group 0, and
|
|
||||||
the contained filename in group 1.
|
|
||||||
"""
|
|
||||||
def find_include(self, include, source_dir, path):
|
|
||||||
if include[0] == '"':
|
|
||||||
paths = (source_dir,) + tuple(path)
|
|
||||||
else:
|
|
||||||
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))
|
|
|
@ -1,376 +0,0 @@
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Script/Interactive.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
__doc__ = """
|
|
||||||
SCons interactive mode
|
|
||||||
"""
|
|
||||||
|
|
||||||
# TODO:
|
|
||||||
#
|
|
||||||
# This has the potential to grow into something with a really big life
|
|
||||||
# of its own, which might or might not be a good thing. Nevertheless,
|
|
||||||
# here are some enhancements that will probably be requested some day
|
|
||||||
# and are worth keeping in mind (assuming this takes off):
|
|
||||||
#
|
|
||||||
# - A command to re-read / re-load the SConscript files. This may
|
|
||||||
# involve allowing people to specify command-line options (e.g. -f,
|
|
||||||
# -I, --no-site-dir) that affect how the SConscript files are read.
|
|
||||||
#
|
|
||||||
# - Additional command-line options on the "build" command.
|
|
||||||
#
|
|
||||||
# Of the supported options that seemed to make sense (after a quick
|
|
||||||
# pass through the list), the ones that seemed likely enough to be
|
|
||||||
# used are listed in the man page and have explicit test scripts.
|
|
||||||
#
|
|
||||||
# These had code changed in Script/Main.py to support them, but didn't
|
|
||||||
# seem likely to be used regularly, so had no test scripts added:
|
|
||||||
#
|
|
||||||
# build --diskcheck=*
|
|
||||||
# build --implicit-cache=*
|
|
||||||
# build --implicit-deps-changed=*
|
|
||||||
# build --implicit-deps-unchanged=*
|
|
||||||
#
|
|
||||||
# These look like they should "just work" with no changes to the
|
|
||||||
# existing code, but like those above, look unlikely to be used and
|
|
||||||
# therefore had no test scripts added:
|
|
||||||
#
|
|
||||||
# build --random
|
|
||||||
#
|
|
||||||
# These I'm not sure about. They might be useful for individual
|
|
||||||
# "build" commands, and may even work, but they seem unlikely enough
|
|
||||||
# that we'll wait until they're requested before spending any time on
|
|
||||||
# writing test scripts for them, or investigating whether they work.
|
|
||||||
#
|
|
||||||
# build -q [??? is there a useful analog to the exit status?]
|
|
||||||
# build --duplicate=
|
|
||||||
# build --profile=
|
|
||||||
# build --max-drift=
|
|
||||||
# build --warn=*
|
|
||||||
# build --Y
|
|
||||||
#
|
|
||||||
# - Most of the SCons command-line options that the "build" command
|
|
||||||
# supports should be settable as default options that apply to all
|
|
||||||
# subsequent "build" commands. Maybe a "set {option}" command that
|
|
||||||
# maps to "SetOption('{option}')".
|
|
||||||
#
|
|
||||||
# - Need something in the 'help' command that prints the -h output.
|
|
||||||
#
|
|
||||||
# - A command to run the configure subsystem separately (must see how
|
|
||||||
# this interacts with the new automake model).
|
|
||||||
#
|
|
||||||
# - Command-line completion of target names; maybe even of SCons options?
|
|
||||||
# Completion is something that's supported by the Python cmd module,
|
|
||||||
# so this should be doable without too much trouble.
|
|
||||||
#
|
|
||||||
|
|
||||||
import cmd
|
|
||||||
import copy
|
|
||||||
import os
|
|
||||||
import re
|
|
||||||
import shlex
|
|
||||||
import string
|
|
||||||
import sys
|
|
||||||
|
|
||||||
try:
|
|
||||||
import readline
|
|
||||||
except ImportError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
class SConsInteractiveCmd(cmd.Cmd):
|
|
||||||
"""\
|
|
||||||
build [TARGETS] Build the specified TARGETS and their dependencies.
|
|
||||||
'b' is a synonym.
|
|
||||||
clean [TARGETS] Clean (remove) the specified TARGETS and their
|
|
||||||
dependencies. 'c' is a synonym.
|
|
||||||
exit Exit SCons interactive mode.
|
|
||||||
help [COMMAND] Prints help for the specified COMMAND. 'h' and
|
|
||||||
'?' are synonyms.
|
|
||||||
shell [COMMANDLINE] Execute COMMANDLINE in a subshell. 'sh' and '!'
|
|
||||||
are synonyms.
|
|
||||||
version Prints SCons version information.
|
|
||||||
"""
|
|
||||||
|
|
||||||
synonyms = {
|
|
||||||
'b' : 'build',
|
|
||||||
'c' : 'clean',
|
|
||||||
'h' : 'help',
|
|
||||||
'scons' : 'build',
|
|
||||||
'sh' : 'shell',
|
|
||||||
}
|
|
||||||
|
|
||||||
def __init__(self, **kw):
|
|
||||||
cmd.Cmd.__init__(self)
|
|
||||||
for key, val in kw.items():
|
|
||||||
setattr(self, key, val)
|
|
||||||
|
|
||||||
if sys.platform == 'win32':
|
|
||||||
self.shell_variable = 'COMSPEC'
|
|
||||||
else:
|
|
||||||
self.shell_variable = 'SHELL'
|
|
||||||
|
|
||||||
def default(self, argv):
|
|
||||||
print "*** Unknown command: %s" % argv[0]
|
|
||||||
|
|
||||||
def onecmd(self, line):
|
|
||||||
line = string.strip(line)
|
|
||||||
if not line:
|
|
||||||
print self.lastcmd
|
|
||||||
return self.emptyline()
|
|
||||||
self.lastcmd = line
|
|
||||||
if line[0] == '!':
|
|
||||||
line = 'shell ' + line[1:]
|
|
||||||
elif line[0] == '?':
|
|
||||||
line = 'help ' + line[1:]
|
|
||||||
if os.sep == '\\':
|
|
||||||
line = string.replace(line, '\\', '\\\\')
|
|
||||||
argv = shlex.split(line)
|
|
||||||
argv[0] = self.synonyms.get(argv[0], argv[0])
|
|
||||||
if not argv[0]:
|
|
||||||
return self.default(line)
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
func = getattr(self, 'do_' + argv[0])
|
|
||||||
except AttributeError:
|
|
||||||
return self.default(argv)
|
|
||||||
return func(argv)
|
|
||||||
|
|
||||||
def do_build(self, argv):
|
|
||||||
"""\
|
|
||||||
build [TARGETS] Build the specified TARGETS and their
|
|
||||||
dependencies. 'b' is a synonym.
|
|
||||||
"""
|
|
||||||
import SCons.Node
|
|
||||||
import SCons.SConsign
|
|
||||||
import SCons.Script.Main
|
|
||||||
|
|
||||||
options = copy.deepcopy(self.options)
|
|
||||||
|
|
||||||
options, targets = self.parser.parse_args(argv[1:], values=options)
|
|
||||||
|
|
||||||
SCons.Script.COMMAND_LINE_TARGETS = targets
|
|
||||||
|
|
||||||
if targets:
|
|
||||||
SCons.Script.BUILD_TARGETS = targets
|
|
||||||
else:
|
|
||||||
# If the user didn't specify any targets on the command line,
|
|
||||||
# use the list of default targets.
|
|
||||||
SCons.Script.BUILD_TARGETS = SCons.Script._build_plus_default
|
|
||||||
|
|
||||||
nodes = SCons.Script.Main._build_targets(self.fs,
|
|
||||||
options,
|
|
||||||
targets,
|
|
||||||
self.target_top)
|
|
||||||
|
|
||||||
if not nodes:
|
|
||||||
return
|
|
||||||
|
|
||||||
# Call each of the Node's alter_targets() methods, which may
|
|
||||||
# provide additional targets that ended up as part of the build
|
|
||||||
# (the canonical example being a VariantDir() when we're building
|
|
||||||
# from a source directory) and which we therefore need their
|
|
||||||
# state cleared, too.
|
|
||||||
x = []
|
|
||||||
for n in nodes:
|
|
||||||
x.extend(n.alter_targets()[0])
|
|
||||||
nodes.extend(x)
|
|
||||||
|
|
||||||
# Clean up so that we can perform the next build correctly.
|
|
||||||
#
|
|
||||||
# We do this by walking over all the children of the targets,
|
|
||||||
# and clearing their state.
|
|
||||||
#
|
|
||||||
# We currently have to re-scan each node to find their
|
|
||||||
# children, because built nodes have already been partially
|
|
||||||
# cleared and don't remember their children. (In scons
|
|
||||||
# 0.96.1 and earlier, this wasn't the case, and we didn't
|
|
||||||
# have to re-scan the nodes.)
|
|
||||||
#
|
|
||||||
# Because we have to re-scan each node, we can't clear the
|
|
||||||
# nodes as we walk over them, because we may end up rescanning
|
|
||||||
# a cleared node as we scan a later node. Therefore, only
|
|
||||||
# store the list of nodes that need to be cleared as we walk
|
|
||||||
# the tree, and clear them in a separate pass.
|
|
||||||
#
|
|
||||||
# XXX: Someone more familiar with the inner workings of scons
|
|
||||||
# may be able to point out a more efficient way to do this.
|
|
||||||
|
|
||||||
SCons.Script.Main.progress_display("scons: Clearing cached node information ...")
|
|
||||||
|
|
||||||
seen_nodes = {}
|
|
||||||
|
|
||||||
def get_unseen_children(node, parent, seen_nodes=seen_nodes):
|
|
||||||
def is_unseen(node, seen_nodes=seen_nodes):
|
|
||||||
return not seen_nodes.has_key(node)
|
|
||||||
return filter(is_unseen, node.children(scan=1))
|
|
||||||
|
|
||||||
def add_to_seen_nodes(node, parent, seen_nodes=seen_nodes):
|
|
||||||
seen_nodes[node] = 1
|
|
||||||
|
|
||||||
# If this file is in a VariantDir and has a
|
|
||||||
# corresponding source file in the source tree, remember the
|
|
||||||
# node in the source tree, too. This is needed in
|
|
||||||
# particular to clear cached implicit dependencies on the
|
|
||||||
# source file, since the scanner will scan it if the
|
|
||||||
# VariantDir was created with duplicate=0.
|
|
||||||
try:
|
|
||||||
rfile_method = node.rfile
|
|
||||||
except AttributeError:
|
|
||||||
return
|
|
||||||
else:
|
|
||||||
rfile = rfile_method()
|
|
||||||
if rfile != node:
|
|
||||||
seen_nodes[rfile] = 1
|
|
||||||
|
|
||||||
for node in nodes:
|
|
||||||
walker = SCons.Node.Walker(node,
|
|
||||||
kids_func=get_unseen_children,
|
|
||||||
eval_func=add_to_seen_nodes)
|
|
||||||
n = walker.next()
|
|
||||||
while n:
|
|
||||||
n = walker.next()
|
|
||||||
|
|
||||||
for node in seen_nodes.keys():
|
|
||||||
# Call node.clear() to clear most of the state
|
|
||||||
node.clear()
|
|
||||||
# node.clear() doesn't reset node.state, so call
|
|
||||||
# node.set_state() to reset it manually
|
|
||||||
node.set_state(SCons.Node.no_state)
|
|
||||||
node.implicit = None
|
|
||||||
|
|
||||||
# Debug: Uncomment to verify that all Taskmaster reference
|
|
||||||
# counts have been reset to zero.
|
|
||||||
#if node.ref_count != 0:
|
|
||||||
# from SCons.Debug import Trace
|
|
||||||
# Trace('node %s, ref_count %s !!!\n' % (node, node.ref_count))
|
|
||||||
|
|
||||||
SCons.SConsign.Reset()
|
|
||||||
SCons.Script.Main.progress_display("scons: done clearing node information.")
|
|
||||||
|
|
||||||
def do_clean(self, argv):
|
|
||||||
"""\
|
|
||||||
clean [TARGETS] Clean (remove) the specified TARGETS
|
|
||||||
and their dependencies. 'c' is a synonym.
|
|
||||||
"""
|
|
||||||
return self.do_build(['build', '--clean'] + argv[1:])
|
|
||||||
|
|
||||||
def do_EOF(self, argv):
|
|
||||||
print
|
|
||||||
self.do_exit(argv)
|
|
||||||
|
|
||||||
def _do_one_help(self, arg):
|
|
||||||
try:
|
|
||||||
# If help_<arg>() exists, then call it.
|
|
||||||
func = getattr(self, 'help_' + arg)
|
|
||||||
except AttributeError:
|
|
||||||
try:
|
|
||||||
func = getattr(self, 'do_' + arg)
|
|
||||||
except AttributeError:
|
|
||||||
doc = None
|
|
||||||
else:
|
|
||||||
doc = self._doc_to_help(func)
|
|
||||||
if doc:
|
|
||||||
sys.stdout.write(doc + '\n')
|
|
||||||
sys.stdout.flush()
|
|
||||||
else:
|
|
||||||
doc = self.strip_initial_spaces(func())
|
|
||||||
if doc:
|
|
||||||
sys.stdout.write(doc + '\n')
|
|
||||||
sys.stdout.flush()
|
|
||||||
|
|
||||||
def _doc_to_help(self, obj):
|
|
||||||
doc = obj.__doc__
|
|
||||||
if doc is None:
|
|
||||||
return ''
|
|
||||||
return self._strip_initial_spaces(doc)
|
|
||||||
|
|
||||||
def _strip_initial_spaces(self, s):
|
|
||||||
#lines = s.split('\n')
|
|
||||||
lines = string.split(s, '\n')
|
|
||||||
spaces = re.match(' *', lines[0]).group(0)
|
|
||||||
#def strip_spaces(l):
|
|
||||||
# if l.startswith(spaces):
|
|
||||||
# l = l[len(spaces):]
|
|
||||||
# return l
|
|
||||||
#return '\n'.join([ strip_spaces(l) for l in lines ])
|
|
||||||
def strip_spaces(l, spaces=spaces):
|
|
||||||
if l[:len(spaces)] == spaces:
|
|
||||||
l = l[len(spaces):]
|
|
||||||
return l
|
|
||||||
lines = map(strip_spaces, lines)
|
|
||||||
return string.join(lines, '\n')
|
|
||||||
|
|
||||||
def do_exit(self, argv):
|
|
||||||
"""\
|
|
||||||
exit Exit SCons interactive mode.
|
|
||||||
"""
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
def do_help(self, argv):
|
|
||||||
"""\
|
|
||||||
help [COMMAND] Prints help for the specified COMMAND. 'h'
|
|
||||||
and '?' are synonyms.
|
|
||||||
"""
|
|
||||||
if argv[1:]:
|
|
||||||
for arg in argv[1:]:
|
|
||||||
if self._do_one_help(arg):
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
# If bare 'help' is called, print this class's doc
|
|
||||||
# string (if it has one).
|
|
||||||
doc = self._doc_to_help(self.__class__)
|
|
||||||
if doc:
|
|
||||||
sys.stdout.write(doc + '\n')
|
|
||||||
sys.stdout.flush()
|
|
||||||
|
|
||||||
def do_shell(self, argv):
|
|
||||||
"""\
|
|
||||||
shell [COMMANDLINE] Execute COMMANDLINE in a subshell. 'sh' and
|
|
||||||
'!' are synonyms.
|
|
||||||
"""
|
|
||||||
import subprocess
|
|
||||||
argv = argv[1:]
|
|
||||||
if not argv:
|
|
||||||
argv = os.environ[self.shell_variable]
|
|
||||||
try:
|
|
||||||
p = subprocess.Popen(argv)
|
|
||||||
except EnvironmentError, e:
|
|
||||||
sys.stderr.write('scons: %s: %s\n' % (argv[0], e.strerror))
|
|
||||||
else:
|
|
||||||
p.wait()
|
|
||||||
|
|
||||||
def do_version(self, argv):
|
|
||||||
"""\
|
|
||||||
version Prints SCons version information.
|
|
||||||
"""
|
|
||||||
sys.stdout.write(self.parser.version + '\n')
|
|
||||||
|
|
||||||
def interact(fs, parser, options, targets, target_top):
|
|
||||||
c = SConsInteractiveCmd(prompt = 'scons>>> ',
|
|
||||||
fs = fs,
|
|
||||||
parser = parser,
|
|
||||||
options = options,
|
|
||||||
targets = targets,
|
|
||||||
target_top = target_top)
|
|
||||||
c.cmdloop()
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,940 +0,0 @@
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Script/SConsOptions.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import optparse
|
|
||||||
import re
|
|
||||||
import string
|
|
||||||
import sys
|
|
||||||
import textwrap
|
|
||||||
|
|
||||||
try:
|
|
||||||
no_hyphen_re = re.compile(r'(\s+|(?<=[\w\!\"\'\&\.\,\?])-{2,}(?=\w))')
|
|
||||||
except re.error:
|
|
||||||
# Pre-2.0 Python versions don't have the (?<= negative
|
|
||||||
# look-behind assertion.
|
|
||||||
no_hyphen_re = re.compile(r'(\s+|-*\w{2,}-(?=\w{2,}))')
|
|
||||||
|
|
||||||
try:
|
|
||||||
from gettext import gettext
|
|
||||||
except ImportError:
|
|
||||||
def gettext(message):
|
|
||||||
return message
|
|
||||||
_ = gettext
|
|
||||||
|
|
||||||
import SCons.Node.FS
|
|
||||||
import SCons.Warnings
|
|
||||||
|
|
||||||
OptionValueError = optparse.OptionValueError
|
|
||||||
SUPPRESS_HELP = optparse.SUPPRESS_HELP
|
|
||||||
|
|
||||||
diskcheck_all = SCons.Node.FS.diskcheck_types()
|
|
||||||
|
|
||||||
def diskcheck_convert(value):
|
|
||||||
if value is None:
|
|
||||||
return []
|
|
||||||
if not SCons.Util.is_List(value):
|
|
||||||
value = string.split(value, ',')
|
|
||||||
result = []
|
|
||||||
for v in map(string.lower, value):
|
|
||||||
if v == 'all':
|
|
||||||
result = diskcheck_all
|
|
||||||
elif v == 'none':
|
|
||||||
result = []
|
|
||||||
elif v in diskcheck_all:
|
|
||||||
result.append(v)
|
|
||||||
else:
|
|
||||||
raise ValueError, v
|
|
||||||
return result
|
|
||||||
|
|
||||||
class SConsValues(optparse.Values):
|
|
||||||
"""
|
|
||||||
Holder class for uniform access to SCons options, regardless
|
|
||||||
of whether or not they can be set on the command line or in the
|
|
||||||
SConscript files (using the SetOption() function).
|
|
||||||
|
|
||||||
A SCons option value can originate three different ways:
|
|
||||||
|
|
||||||
1) set on the command line;
|
|
||||||
2) set in an SConscript file;
|
|
||||||
3) the default setting (from the the op.add_option()
|
|
||||||
calls in the Parser() function, below).
|
|
||||||
|
|
||||||
The command line always overrides a value set in a SConscript file,
|
|
||||||
which in turn always overrides default settings. Because we want
|
|
||||||
to support user-specified options in the SConscript file itself,
|
|
||||||
though, we may not know about all of the options when the command
|
|
||||||
line is first parsed, so we can't make all the necessary precedence
|
|
||||||
decisions at the time the option is configured.
|
|
||||||
|
|
||||||
The solution implemented in this class is to keep these different sets
|
|
||||||
of settings separate (command line, SConscript file, and default)
|
|
||||||
and to override the __getattr__() method to check them in turn.
|
|
||||||
This should allow the rest of the code to just fetch values as
|
|
||||||
attributes of an instance of this class, without having to worry
|
|
||||||
about where they came from.
|
|
||||||
|
|
||||||
Note that not all command line options are settable from SConscript
|
|
||||||
files, and the ones that are must be explicitly added to the
|
|
||||||
"settable" list in this class, and optionally validated and coerced
|
|
||||||
in the set_option() method.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, defaults):
|
|
||||||
self.__dict__['__defaults__'] = defaults
|
|
||||||
self.__dict__['__SConscript_settings__'] = {}
|
|
||||||
|
|
||||||
def __getattr__(self, attr):
|
|
||||||
"""
|
|
||||||
Fetches an options value, checking first for explicit settings
|
|
||||||
from the command line (which are direct attributes), then the
|
|
||||||
SConscript file settings, then the default values.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
return self.__dict__[attr]
|
|
||||||
except KeyError:
|
|
||||||
try:
|
|
||||||
return self.__dict__['__SConscript_settings__'][attr]
|
|
||||||
except KeyError:
|
|
||||||
return getattr(self.__dict__['__defaults__'], attr)
|
|
||||||
|
|
||||||
settable = [
|
|
||||||
'clean',
|
|
||||||
'diskcheck',
|
|
||||||
'duplicate',
|
|
||||||
'help',
|
|
||||||
'implicit_cache',
|
|
||||||
'max_drift',
|
|
||||||
'md5_chunksize',
|
|
||||||
'no_exec',
|
|
||||||
'num_jobs',
|
|
||||||
'random',
|
|
||||||
'stack_size',
|
|
||||||
'warn',
|
|
||||||
]
|
|
||||||
|
|
||||||
def set_option(self, name, value):
|
|
||||||
"""
|
|
||||||
Sets an option from an SConscript file.
|
|
||||||
"""
|
|
||||||
if not name in self.settable:
|
|
||||||
raise SCons.Errors.UserError, "This option is not settable from a SConscript file: %s"%name
|
|
||||||
|
|
||||||
if name == 'num_jobs':
|
|
||||||
try:
|
|
||||||
value = int(value)
|
|
||||||
if value < 1:
|
|
||||||
raise ValueError
|
|
||||||
except ValueError:
|
|
||||||
raise SCons.Errors.UserError, "A positive integer is required: %s"%repr(value)
|
|
||||||
elif name == 'max_drift':
|
|
||||||
try:
|
|
||||||
value = int(value)
|
|
||||||
except ValueError:
|
|
||||||
raise SCons.Errors.UserError, "An integer is required: %s"%repr(value)
|
|
||||||
elif name == 'duplicate':
|
|
||||||
try:
|
|
||||||
value = str(value)
|
|
||||||
except ValueError:
|
|
||||||
raise SCons.Errors.UserError, "A string is required: %s"%repr(value)
|
|
||||||
if not value in SCons.Node.FS.Valid_Duplicates:
|
|
||||||
raise SCons.Errors.UserError, "Not a valid duplication style: %s" % value
|
|
||||||
# Set the duplicate style right away so it can affect linking
|
|
||||||
# of SConscript files.
|
|
||||||
SCons.Node.FS.set_duplicate(value)
|
|
||||||
elif name == 'diskcheck':
|
|
||||||
try:
|
|
||||||
value = diskcheck_convert(value)
|
|
||||||
except ValueError, v:
|
|
||||||
raise SCons.Errors.UserError, "Not a valid diskcheck value: %s"%v
|
|
||||||
if not self.__dict__.has_key('diskcheck'):
|
|
||||||
# No --diskcheck= option was specified on the command line.
|
|
||||||
# Set this right away so it can affect the rest of the
|
|
||||||
# file/Node lookups while processing the SConscript files.
|
|
||||||
SCons.Node.FS.set_diskcheck(value)
|
|
||||||
elif name == 'stack_size':
|
|
||||||
try:
|
|
||||||
value = int(value)
|
|
||||||
except ValueError:
|
|
||||||
raise SCons.Errors.UserError, "An integer is required: %s"%repr(value)
|
|
||||||
elif name == 'md5_chunksize':
|
|
||||||
try:
|
|
||||||
value = int(value)
|
|
||||||
except ValueError:
|
|
||||||
raise SCons.Errors.UserError, "An integer is required: %s"%repr(value)
|
|
||||||
elif name == 'warn':
|
|
||||||
if SCons.Util.is_String(value):
|
|
||||||
value = [value]
|
|
||||||
value = self.__SConscript_settings__.get(name, []) + value
|
|
||||||
SCons.Warnings.process_warn_strings(value)
|
|
||||||
|
|
||||||
self.__SConscript_settings__[name] = value
|
|
||||||
|
|
||||||
class SConsOption(optparse.Option):
|
|
||||||
def convert_value(self, opt, value):
|
|
||||||
if value is not None:
|
|
||||||
if self.nargs in (1, '?'):
|
|
||||||
return self.check_value(opt, value)
|
|
||||||
else:
|
|
||||||
return tuple(map(lambda v, o=opt, s=self: s.check_value(o, v), value))
|
|
||||||
|
|
||||||
def process(self, opt, value, values, parser):
|
|
||||||
|
|
||||||
# First, convert the value(s) to the right type. Howl if any
|
|
||||||
# value(s) are bogus.
|
|
||||||
value = self.convert_value(opt, value)
|
|
||||||
|
|
||||||
# And then take whatever action is expected of us.
|
|
||||||
# This is a separate method to make life easier for
|
|
||||||
# subclasses to add new actions.
|
|
||||||
return self.take_action(
|
|
||||||
self.action, self.dest, opt, value, values, parser)
|
|
||||||
|
|
||||||
def _check_nargs_optional(self):
|
|
||||||
if self.nargs == '?' and self._short_opts:
|
|
||||||
fmt = "option %s: nargs='?' is incompatible with short options"
|
|
||||||
raise SCons.Errors.UserError, fmt % self._short_opts[0]
|
|
||||||
|
|
||||||
try:
|
|
||||||
_orig_CONST_ACTIONS = optparse.Option.CONST_ACTIONS
|
|
||||||
|
|
||||||
_orig_CHECK_METHODS = optparse.Option.CHECK_METHODS
|
|
||||||
|
|
||||||
except AttributeError:
|
|
||||||
# optparse.Option had no CONST_ACTIONS before Python 2.5.
|
|
||||||
|
|
||||||
_orig_CONST_ACTIONS = ("store_const",)
|
|
||||||
|
|
||||||
def _check_const(self):
|
|
||||||
if self.action not in self.CONST_ACTIONS and self.const is not None:
|
|
||||||
raise OptionError(
|
|
||||||
"'const' must not be supplied for action %r" % self.action,
|
|
||||||
self)
|
|
||||||
|
|
||||||
# optparse.Option collects its list of unbound check functions
|
|
||||||
# up front. This sucks because it means we can't just override
|
|
||||||
# the _check_const() function like a normal method, we have to
|
|
||||||
# actually replace it in the list. This seems to be the most
|
|
||||||
# straightforward way to do that.
|
|
||||||
|
|
||||||
_orig_CHECK_METHODS = [optparse.Option._check_action,
|
|
||||||
optparse.Option._check_type,
|
|
||||||
optparse.Option._check_choice,
|
|
||||||
optparse.Option._check_dest,
|
|
||||||
_check_const,
|
|
||||||
optparse.Option._check_nargs,
|
|
||||||
optparse.Option._check_callback]
|
|
||||||
|
|
||||||
CHECK_METHODS = _orig_CHECK_METHODS + [_check_nargs_optional]
|
|
||||||
|
|
||||||
CONST_ACTIONS = _orig_CONST_ACTIONS + optparse.Option.TYPED_ACTIONS
|
|
||||||
|
|
||||||
class SConsOptionGroup(optparse.OptionGroup):
|
|
||||||
"""
|
|
||||||
A subclass for SCons-specific option groups.
|
|
||||||
|
|
||||||
The only difference between this and the base class is that we print
|
|
||||||
the group's help text flush left, underneath their own title but
|
|
||||||
lined up with the normal "SCons Options".
|
|
||||||
"""
|
|
||||||
def format_help(self, formatter):
|
|
||||||
"""
|
|
||||||
Format an option group's help text, outdenting the title so it's
|
|
||||||
flush with the "SCons Options" title we print at the top.
|
|
||||||
"""
|
|
||||||
formatter.dedent()
|
|
||||||
result = formatter.format_heading(self.title)
|
|
||||||
formatter.indent()
|
|
||||||
result = result + optparse.OptionContainer.format_help(self, formatter)
|
|
||||||
return result
|
|
||||||
|
|
||||||
class SConsOptionParser(optparse.OptionParser):
|
|
||||||
preserve_unknown_options = False
|
|
||||||
|
|
||||||
def error(self, msg):
|
|
||||||
self.print_usage(sys.stderr)
|
|
||||||
sys.stderr.write("SCons error: %s\n" % msg)
|
|
||||||
sys.exit(2)
|
|
||||||
|
|
||||||
def _process_long_opt(self, rargs, values):
|
|
||||||
"""
|
|
||||||
SCons-specific processing of long options.
|
|
||||||
|
|
||||||
This is copied directly from the normal
|
|
||||||
optparse._process_long_opt() method, except that, if configured
|
|
||||||
to do so, we catch the exception thrown when an unknown option
|
|
||||||
is encountered and just stick it back on the "leftover" arguments
|
|
||||||
for later (re-)processing.
|
|
||||||
"""
|
|
||||||
arg = rargs.pop(0)
|
|
||||||
|
|
||||||
# Value explicitly attached to arg? Pretend it's the next
|
|
||||||
# argument.
|
|
||||||
if "=" in arg:
|
|
||||||
(opt, next_arg) = string.split(arg, "=", 1)
|
|
||||||
rargs.insert(0, next_arg)
|
|
||||||
had_explicit_value = True
|
|
||||||
else:
|
|
||||||
opt = arg
|
|
||||||
had_explicit_value = False
|
|
||||||
|
|
||||||
try:
|
|
||||||
opt = self._match_long_opt(opt)
|
|
||||||
except optparse.BadOptionError:
|
|
||||||
if self.preserve_unknown_options:
|
|
||||||
# SCons-specific: if requested, add unknown options to
|
|
||||||
# the "leftover arguments" list for later processing.
|
|
||||||
self.largs.append(arg)
|
|
||||||
if had_explicit_value:
|
|
||||||
# The unknown option will be re-processed later,
|
|
||||||
# so undo the insertion of the explicit value.
|
|
||||||
rargs.pop(0)
|
|
||||||
return
|
|
||||||
raise
|
|
||||||
|
|
||||||
option = self._long_opt[opt]
|
|
||||||
if option.takes_value():
|
|
||||||
nargs = option.nargs
|
|
||||||
if nargs == '?':
|
|
||||||
if had_explicit_value:
|
|
||||||
value = rargs.pop(0)
|
|
||||||
else:
|
|
||||||
value = option.const
|
|
||||||
elif len(rargs) < nargs:
|
|
||||||
if nargs == 1:
|
|
||||||
self.error(_("%s option requires an argument") % opt)
|
|
||||||
else:
|
|
||||||
self.error(_("%s option requires %d arguments")
|
|
||||||
% (opt, nargs))
|
|
||||||
elif nargs == 1:
|
|
||||||
value = rargs.pop(0)
|
|
||||||
else:
|
|
||||||
value = tuple(rargs[0:nargs])
|
|
||||||
del rargs[0:nargs]
|
|
||||||
|
|
||||||
elif had_explicit_value:
|
|
||||||
self.error(_("%s option does not take a value") % opt)
|
|
||||||
|
|
||||||
else:
|
|
||||||
value = None
|
|
||||||
|
|
||||||
option.process(opt, value, values, self)
|
|
||||||
|
|
||||||
def add_local_option(self, *args, **kw):
|
|
||||||
"""
|
|
||||||
Adds a local option to the parser.
|
|
||||||
|
|
||||||
This is initiated by a SetOption() call to add a user-defined
|
|
||||||
command-line option. We add the option to a separate option
|
|
||||||
group for the local options, creating the group if necessary.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
group = self.local_option_group
|
|
||||||
except AttributeError:
|
|
||||||
group = SConsOptionGroup(self, 'Local Options')
|
|
||||||
group = self.add_option_group(group)
|
|
||||||
self.local_option_group = group
|
|
||||||
|
|
||||||
result = apply(group.add_option, args, kw)
|
|
||||||
|
|
||||||
if result:
|
|
||||||
# The option was added succesfully. We now have to add the
|
|
||||||
# default value to our object that holds the default values
|
|
||||||
# (so that an attempt to fetch the option's attribute will
|
|
||||||
# yield the default value when not overridden) and then
|
|
||||||
# we re-parse the leftover command-line options, so that
|
|
||||||
# any value overridden on the command line is immediately
|
|
||||||
# available if the user turns around and does a GetOption()
|
|
||||||
# right away.
|
|
||||||
setattr(self.values.__defaults__, result.dest, result.default)
|
|
||||||
self.parse_args(self.largs, self.values)
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
class SConsIndentedHelpFormatter(optparse.IndentedHelpFormatter):
|
|
||||||
def format_usage(self, usage):
|
|
||||||
return "usage: %s\n" % usage
|
|
||||||
|
|
||||||
def format_heading(self, heading):
|
|
||||||
"""
|
|
||||||
This translates any heading of "options" or "Options" into
|
|
||||||
"SCons Options." Unfortunately, we have to do this here,
|
|
||||||
because those titles are hard-coded in the optparse calls.
|
|
||||||
"""
|
|
||||||
if heading == 'options':
|
|
||||||
# The versions of optparse.py shipped with Pythons 2.3 and
|
|
||||||
# 2.4 pass this in uncapitalized; override that so we get
|
|
||||||
# consistent output on all versions.
|
|
||||||
heading = "Options"
|
|
||||||
if heading == 'Options':
|
|
||||||
heading = "SCons Options"
|
|
||||||
return optparse.IndentedHelpFormatter.format_heading(self, heading)
|
|
||||||
|
|
||||||
def format_option(self, option):
|
|
||||||
"""
|
|
||||||
A copy of the normal optparse.IndentedHelpFormatter.format_option()
|
|
||||||
method. This has been snarfed so we can modify text wrapping to
|
|
||||||
out liking:
|
|
||||||
|
|
||||||
-- add our own regular expression that doesn't break on hyphens
|
|
||||||
(so things like --no-print-directory don't get broken);
|
|
||||||
|
|
||||||
-- wrap the list of options themselves when it's too long
|
|
||||||
(the wrapper.fill(opts) call below);
|
|
||||||
|
|
||||||
-- set the subsequent_indent when wrapping the help_text.
|
|
||||||
"""
|
|
||||||
# The help for each option consists of two parts:
|
|
||||||
# * the opt strings and metavars
|
|
||||||
# eg. ("-x", or "-fFILENAME, --file=FILENAME")
|
|
||||||
# * the user-supplied help string
|
|
||||||
# eg. ("turn on expert mode", "read data from FILENAME")
|
|
||||||
#
|
|
||||||
# If possible, we write both of these on the same line:
|
|
||||||
# -x turn on expert mode
|
|
||||||
#
|
|
||||||
# But if the opt string list is too long, we put the help
|
|
||||||
# string on a second line, indented to the same column it would
|
|
||||||
# start in if it fit on the first line.
|
|
||||||
# -fFILENAME, --file=FILENAME
|
|
||||||
# read data from FILENAME
|
|
||||||
result = []
|
|
||||||
|
|
||||||
try:
|
|
||||||
opts = self.option_strings[option]
|
|
||||||
except AttributeError:
|
|
||||||
# The Python 2.3 version of optparse attaches this to
|
|
||||||
# to the option argument, not to this object.
|
|
||||||
opts = option.option_strings
|
|
||||||
|
|
||||||
opt_width = self.help_position - self.current_indent - 2
|
|
||||||
if len(opts) > opt_width:
|
|
||||||
wrapper = textwrap.TextWrapper(width=self.width,
|
|
||||||
initial_indent = ' ',
|
|
||||||
subsequent_indent = ' ')
|
|
||||||
wrapper.wordsep_re = no_hyphen_re
|
|
||||||
opts = wrapper.fill(opts) + '\n'
|
|
||||||
indent_first = self.help_position
|
|
||||||
else: # start help on same line as opts
|
|
||||||
opts = "%*s%-*s " % (self.current_indent, "", opt_width, opts)
|
|
||||||
indent_first = 0
|
|
||||||
result.append(opts)
|
|
||||||
if option.help:
|
|
||||||
|
|
||||||
try:
|
|
||||||
expand_default = self.expand_default
|
|
||||||
except AttributeError:
|
|
||||||
# The HelpFormatter base class in the Python 2.3 version
|
|
||||||
# of optparse has no expand_default() method.
|
|
||||||
help_text = option.help
|
|
||||||
else:
|
|
||||||
help_text = expand_default(option)
|
|
||||||
|
|
||||||
# SCons: indent every line of the help text but the first.
|
|
||||||
wrapper = textwrap.TextWrapper(width=self.help_width,
|
|
||||||
subsequent_indent = ' ')
|
|
||||||
wrapper.wordsep_re = no_hyphen_re
|
|
||||||
help_lines = wrapper.wrap(help_text)
|
|
||||||
result.append("%*s%s\n" % (indent_first, "", help_lines[0]))
|
|
||||||
for line in help_lines[1:]:
|
|
||||||
result.append("%*s%s\n" % (self.help_position, "", line))
|
|
||||||
elif opts[-1] != "\n":
|
|
||||||
result.append("\n")
|
|
||||||
return string.join(result, "")
|
|
||||||
|
|
||||||
# For consistent help output across Python versions, we provide a
|
|
||||||
# subclass copy of format_option_strings() and these two variables.
|
|
||||||
# This is necessary (?) for Python2.3, which otherwise concatenates
|
|
||||||
# a short option with its metavar.
|
|
||||||
_short_opt_fmt = "%s %s"
|
|
||||||
_long_opt_fmt = "%s=%s"
|
|
||||||
|
|
||||||
def format_option_strings(self, option):
|
|
||||||
"""Return a comma-separated list of option strings & metavariables."""
|
|
||||||
if option.takes_value():
|
|
||||||
metavar = option.metavar or string.upper(option.dest)
|
|
||||||
short_opts = []
|
|
||||||
for sopt in option._short_opts:
|
|
||||||
short_opts.append(self._short_opt_fmt % (sopt, metavar))
|
|
||||||
long_opts = []
|
|
||||||
for lopt in option._long_opts:
|
|
||||||
long_opts.append(self._long_opt_fmt % (lopt, metavar))
|
|
||||||
else:
|
|
||||||
short_opts = option._short_opts
|
|
||||||
long_opts = option._long_opts
|
|
||||||
|
|
||||||
if self.short_first:
|
|
||||||
opts = short_opts + long_opts
|
|
||||||
else:
|
|
||||||
opts = long_opts + short_opts
|
|
||||||
|
|
||||||
return string.join(opts, ", ")
|
|
||||||
|
|
||||||
def Parser(version):
|
|
||||||
"""
|
|
||||||
Returns an options parser object initialized with the standard
|
|
||||||
SCons options.
|
|
||||||
"""
|
|
||||||
|
|
||||||
formatter = SConsIndentedHelpFormatter(max_help_position=30)
|
|
||||||
|
|
||||||
op = SConsOptionParser(option_class=SConsOption,
|
|
||||||
add_help_option=False,
|
|
||||||
formatter=formatter,
|
|
||||||
usage="usage: scons [OPTION] [TARGET] ...",)
|
|
||||||
|
|
||||||
op.preserve_unknown_options = True
|
|
||||||
op.version = version
|
|
||||||
|
|
||||||
# Add the options to the parser we just created.
|
|
||||||
#
|
|
||||||
# These are in the order we want them to show up in the -H help
|
|
||||||
# text, basically alphabetical. Each op.add_option() call below
|
|
||||||
# should have a consistent format:
|
|
||||||
#
|
|
||||||
# op.add_option("-L", "--long-option-name",
|
|
||||||
# nargs=1, type="string",
|
|
||||||
# dest="long_option_name", default='foo',
|
|
||||||
# action="callback", callback=opt_long_option,
|
|
||||||
# help="help text goes here",
|
|
||||||
# metavar="VAR")
|
|
||||||
#
|
|
||||||
# Even though the optparse module constructs reasonable default
|
|
||||||
# destination names from the long option names, we're going to be
|
|
||||||
# explicit about each one for easier readability and so this code
|
|
||||||
# will at least show up when grepping the source for option attribute
|
|
||||||
# names, or otherwise browsing the source code.
|
|
||||||
|
|
||||||
# options ignored for compatibility
|
|
||||||
def opt_ignore(option, opt, value, parser):
|
|
||||||
sys.stderr.write("Warning: ignoring %s option\n" % opt)
|
|
||||||
op.add_option("-b", "-d", "-e", "-m", "-S", "-t", "-w",
|
|
||||||
"--environment-overrides",
|
|
||||||
"--no-keep-going",
|
|
||||||
"--no-print-directory",
|
|
||||||
"--print-directory",
|
|
||||||
"--stop",
|
|
||||||
"--touch",
|
|
||||||
action="callback", callback=opt_ignore,
|
|
||||||
help="Ignored for compatibility.")
|
|
||||||
|
|
||||||
op.add_option('-c', '--clean', '--remove',
|
|
||||||
dest="clean", default=False,
|
|
||||||
action="store_true",
|
|
||||||
help="Remove specified targets and dependencies.")
|
|
||||||
|
|
||||||
op.add_option('-C', '--directory',
|
|
||||||
nargs=1, type="string",
|
|
||||||
dest="directory", default=[],
|
|
||||||
action="append",
|
|
||||||
help="Change to DIR before doing anything.",
|
|
||||||
metavar="DIR")
|
|
||||||
|
|
||||||
op.add_option('--cache-debug',
|
|
||||||
nargs=1,
|
|
||||||
dest="cache_debug", default=None,
|
|
||||||
action="store",
|
|
||||||
help="Print CacheDir debug info to FILE.",
|
|
||||||
metavar="FILE")
|
|
||||||
|
|
||||||
op.add_option('--cache-disable', '--no-cache',
|
|
||||||
dest='cache_disable', default=False,
|
|
||||||
action="store_true",
|
|
||||||
help="Do not retrieve built targets from CacheDir.")
|
|
||||||
|
|
||||||
op.add_option('--cache-force', '--cache-populate',
|
|
||||||
dest='cache_force', default=False,
|
|
||||||
action="store_true",
|
|
||||||
help="Copy already-built targets into the CacheDir.")
|
|
||||||
|
|
||||||
op.add_option('--cache-show',
|
|
||||||
dest='cache_show', default=False,
|
|
||||||
action="store_true",
|
|
||||||
help="Print build actions for files from CacheDir.")
|
|
||||||
|
|
||||||
config_options = ["auto", "force" ,"cache"]
|
|
||||||
|
|
||||||
def opt_config(option, opt, value, parser, c_options=config_options):
|
|
||||||
if not value in c_options:
|
|
||||||
raise OptionValueError("Warning: %s is not a valid config type" % value)
|
|
||||||
setattr(parser.values, option.dest, value)
|
|
||||||
opt_config_help = "Controls Configure subsystem: %s." \
|
|
||||||
% string.join(config_options, ", ")
|
|
||||||
op.add_option('--config',
|
|
||||||
nargs=1, type="string",
|
|
||||||
dest="config", default="auto",
|
|
||||||
action="callback", callback=opt_config,
|
|
||||||
help = opt_config_help,
|
|
||||||
metavar="MODE")
|
|
||||||
|
|
||||||
op.add_option('-D',
|
|
||||||
dest="climb_up", default=None,
|
|
||||||
action="store_const", const=2,
|
|
||||||
help="Search up directory tree for SConstruct, "
|
|
||||||
"build all Default() targets.")
|
|
||||||
|
|
||||||
deprecated_debug_options = {
|
|
||||||
"dtree" : '; please use --tree=derived instead',
|
|
||||||
"nomemoizer" : ' and has no effect',
|
|
||||||
"stree" : '; please use --tree=all,status instead',
|
|
||||||
"tree" : '; please use --tree=all instead',
|
|
||||||
}
|
|
||||||
|
|
||||||
debug_options = ["count", "explain", "findlibs",
|
|
||||||
"includes", "memoizer", "memory", "objects",
|
|
||||||
"pdb", "presub", "stacktrace",
|
|
||||||
"time"] + deprecated_debug_options.keys()
|
|
||||||
|
|
||||||
def opt_debug(option, opt, value, parser,
|
|
||||||
debug_options=debug_options,
|
|
||||||
deprecated_debug_options=deprecated_debug_options):
|
|
||||||
if value in debug_options:
|
|
||||||
parser.values.debug.append(value)
|
|
||||||
if value in deprecated_debug_options.keys():
|
|
||||||
try:
|
|
||||||
parser.values.delayed_warnings
|
|
||||||
except AttributeError:
|
|
||||||
parser.values.delayed_warnings = []
|
|
||||||
msg = deprecated_debug_options[value]
|
|
||||||
w = "The --debug=%s option is deprecated%s." % (value, msg)
|
|
||||||
t = (SCons.Warnings.DeprecatedWarning, w)
|
|
||||||
parser.values.delayed_warnings.append(t)
|
|
||||||
else:
|
|
||||||
raise OptionValueError("Warning: %s is not a valid debug type" % value)
|
|
||||||
opt_debug_help = "Print various types of debugging information: %s." \
|
|
||||||
% string.join(debug_options, ", ")
|
|
||||||
op.add_option('--debug',
|
|
||||||
nargs=1, type="string",
|
|
||||||
dest="debug", default=[],
|
|
||||||
action="callback", callback=opt_debug,
|
|
||||||
help=opt_debug_help,
|
|
||||||
metavar="TYPE")
|
|
||||||
|
|
||||||
def opt_diskcheck(option, opt, value, parser):
|
|
||||||
try:
|
|
||||||
diskcheck_value = diskcheck_convert(value)
|
|
||||||
except ValueError, e:
|
|
||||||
raise OptionValueError("Warning: `%s' is not a valid diskcheck type" % e)
|
|
||||||
setattr(parser.values, option.dest, diskcheck_value)
|
|
||||||
|
|
||||||
op.add_option('--diskcheck',
|
|
||||||
nargs=1, type="string",
|
|
||||||
dest='diskcheck', default=None,
|
|
||||||
action="callback", callback=opt_diskcheck,
|
|
||||||
help="Enable specific on-disk checks.",
|
|
||||||
metavar="TYPE")
|
|
||||||
|
|
||||||
def opt_duplicate(option, opt, value, parser):
|
|
||||||
if not value in SCons.Node.FS.Valid_Duplicates:
|
|
||||||
raise OptionValueError("`%s' is not a valid duplication style." % value)
|
|
||||||
setattr(parser.values, option.dest, value)
|
|
||||||
# Set the duplicate style right away so it can affect linking
|
|
||||||
# of SConscript files.
|
|
||||||
SCons.Node.FS.set_duplicate(value)
|
|
||||||
|
|
||||||
opt_duplicate_help = "Set the preferred duplication methods. Must be one of " \
|
|
||||||
+ string.join(SCons.Node.FS.Valid_Duplicates, ", ")
|
|
||||||
|
|
||||||
op.add_option('--duplicate',
|
|
||||||
nargs=1, type="string",
|
|
||||||
dest="duplicate", default='hard-soft-copy',
|
|
||||||
action="callback", callback=opt_duplicate,
|
|
||||||
help=opt_duplicate_help)
|
|
||||||
|
|
||||||
op.add_option('-f', '--file', '--makefile', '--sconstruct',
|
|
||||||
nargs=1, type="string",
|
|
||||||
dest="file", default=[],
|
|
||||||
action="append",
|
|
||||||
help="Read FILE as the top-level SConstruct file.")
|
|
||||||
|
|
||||||
op.add_option('-h', '--help',
|
|
||||||
dest="help", default=False,
|
|
||||||
action="store_true",
|
|
||||||
help="Print defined help message, or this one.")
|
|
||||||
|
|
||||||
op.add_option("-H", "--help-options",
|
|
||||||
action="help",
|
|
||||||
help="Print this message and exit.")
|
|
||||||
|
|
||||||
op.add_option('-i', '--ignore-errors',
|
|
||||||
dest='ignore_errors', default=False,
|
|
||||||
action="store_true",
|
|
||||||
help="Ignore errors from build actions.")
|
|
||||||
|
|
||||||
op.add_option('-I', '--include-dir',
|
|
||||||
nargs=1,
|
|
||||||
dest='include_dir', default=[],
|
|
||||||
action="append",
|
|
||||||
help="Search DIR for imported Python modules.",
|
|
||||||
metavar="DIR")
|
|
||||||
|
|
||||||
op.add_option('--implicit-cache',
|
|
||||||
dest='implicit_cache', default=False,
|
|
||||||
action="store_true",
|
|
||||||
help="Cache implicit dependencies")
|
|
||||||
|
|
||||||
def opt_implicit_deps(option, opt, value, parser):
|
|
||||||
setattr(parser.values, 'implicit_cache', True)
|
|
||||||
setattr(parser.values, option.dest, True)
|
|
||||||
|
|
||||||
op.add_option('--implicit-deps-changed',
|
|
||||||
dest="implicit_deps_changed", default=False,
|
|
||||||
action="callback", callback=opt_implicit_deps,
|
|
||||||
help="Ignore cached implicit dependencies.")
|
|
||||||
|
|
||||||
op.add_option('--implicit-deps-unchanged',
|
|
||||||
dest="implicit_deps_unchanged", default=False,
|
|
||||||
action="callback", callback=opt_implicit_deps,
|
|
||||||
help="Ignore changes in implicit dependencies.")
|
|
||||||
|
|
||||||
op.add_option('--interact', '--interactive',
|
|
||||||
dest='interactive', default=False,
|
|
||||||
action="store_true",
|
|
||||||
help="Run in interactive mode.")
|
|
||||||
|
|
||||||
op.add_option('-j', '--jobs',
|
|
||||||
nargs=1, type="int",
|
|
||||||
dest="num_jobs", default=1,
|
|
||||||
action="store",
|
|
||||||
help="Allow N jobs at once.",
|
|
||||||
metavar="N")
|
|
||||||
|
|
||||||
op.add_option('-k', '--keep-going',
|
|
||||||
dest='keep_going', default=False,
|
|
||||||
action="store_true",
|
|
||||||
help="Keep going when a target can't be made.")
|
|
||||||
|
|
||||||
op.add_option('--max-drift',
|
|
||||||
nargs=1, type="int",
|
|
||||||
dest='max_drift', default=SCons.Node.FS.default_max_drift,
|
|
||||||
action="store",
|
|
||||||
help="Set maximum system clock drift to N seconds.",
|
|
||||||
metavar="N")
|
|
||||||
|
|
||||||
op.add_option('--md5-chunksize',
|
|
||||||
nargs=1, type="int",
|
|
||||||
dest='md5_chunksize', default=SCons.Node.FS.File.md5_chunksize,
|
|
||||||
action="store",
|
|
||||||
help="Set chunk-size for MD5 signature computation to N kilobytes.",
|
|
||||||
metavar="N")
|
|
||||||
|
|
||||||
op.add_option('-n', '--no-exec', '--just-print', '--dry-run', '--recon',
|
|
||||||
dest='no_exec', default=False,
|
|
||||||
action="store_true",
|
|
||||||
help="Don't build; just print commands.")
|
|
||||||
|
|
||||||
op.add_option('--no-site-dir',
|
|
||||||
dest='no_site_dir', default=False,
|
|
||||||
action="store_true",
|
|
||||||
help="Don't search or use the usual site_scons dir.")
|
|
||||||
|
|
||||||
op.add_option('--profile',
|
|
||||||
nargs=1,
|
|
||||||
dest="profile_file", default=None,
|
|
||||||
action="store",
|
|
||||||
help="Profile SCons and put results in FILE.",
|
|
||||||
metavar="FILE")
|
|
||||||
|
|
||||||
op.add_option('-q', '--question',
|
|
||||||
dest="question", default=False,
|
|
||||||
action="store_true",
|
|
||||||
help="Don't build; exit status says if up to date.")
|
|
||||||
|
|
||||||
op.add_option('-Q',
|
|
||||||
dest='no_progress', default=False,
|
|
||||||
action="store_true",
|
|
||||||
help="Suppress \"Reading/Building\" progress messages.")
|
|
||||||
|
|
||||||
op.add_option('--random',
|
|
||||||
dest="random", default=False,
|
|
||||||
action="store_true",
|
|
||||||
help="Build dependencies in random order.")
|
|
||||||
|
|
||||||
op.add_option('-s', '--silent', '--quiet',
|
|
||||||
dest="silent", default=False,
|
|
||||||
action="store_true",
|
|
||||||
help="Don't print commands.")
|
|
||||||
|
|
||||||
op.add_option('--site-dir',
|
|
||||||
nargs=1,
|
|
||||||
dest='site_dir', default=None,
|
|
||||||
action="store",
|
|
||||||
help="Use DIR instead of the usual site_scons dir.",
|
|
||||||
metavar="DIR")
|
|
||||||
|
|
||||||
op.add_option('--stack-size',
|
|
||||||
nargs=1, type="int",
|
|
||||||
dest='stack_size',
|
|
||||||
action="store",
|
|
||||||
help="Set the stack size of the threads used to run jobs to N kilobytes.",
|
|
||||||
metavar="N")
|
|
||||||
|
|
||||||
op.add_option('--taskmastertrace',
|
|
||||||
nargs=1,
|
|
||||||
dest="taskmastertrace_file", default=None,
|
|
||||||
action="store",
|
|
||||||
help="Trace Node evaluation to FILE.",
|
|
||||||
metavar="FILE")
|
|
||||||
|
|
||||||
tree_options = ["all", "derived", "prune", "status"]
|
|
||||||
|
|
||||||
def opt_tree(option, opt, value, parser, tree_options=tree_options):
|
|
||||||
import Main
|
|
||||||
tp = Main.TreePrinter()
|
|
||||||
for o in string.split(value, ','):
|
|
||||||
if o == 'all':
|
|
||||||
tp.derived = False
|
|
||||||
elif o == 'derived':
|
|
||||||
tp.derived = True
|
|
||||||
elif o == 'prune':
|
|
||||||
tp.prune = True
|
|
||||||
elif o == 'status':
|
|
||||||
tp.status = True
|
|
||||||
else:
|
|
||||||
raise OptionValueError("Warning: %s is not a valid --tree option" % o)
|
|
||||||
parser.values.tree_printers.append(tp)
|
|
||||||
|
|
||||||
opt_tree_help = "Print a dependency tree in various formats: %s." \
|
|
||||||
% string.join(tree_options, ", ")
|
|
||||||
|
|
||||||
op.add_option('--tree',
|
|
||||||
nargs=1, type="string",
|
|
||||||
dest="tree_printers", default=[],
|
|
||||||
action="callback", callback=opt_tree,
|
|
||||||
help=opt_tree_help,
|
|
||||||
metavar="OPTIONS")
|
|
||||||
|
|
||||||
op.add_option('-u', '--up', '--search-up',
|
|
||||||
dest="climb_up", default=0,
|
|
||||||
action="store_const", const=1,
|
|
||||||
help="Search up directory tree for SConstruct, "
|
|
||||||
"build targets at or below current directory.")
|
|
||||||
|
|
||||||
op.add_option('-U',
|
|
||||||
dest="climb_up", default=0,
|
|
||||||
action="store_const", const=3,
|
|
||||||
help="Search up directory tree for SConstruct, "
|
|
||||||
"build Default() targets from local SConscript.")
|
|
||||||
|
|
||||||
def opt_version(option, opt, value, parser):
|
|
||||||
sys.stdout.write(parser.version + '\n')
|
|
||||||
sys.exit(0)
|
|
||||||
op.add_option("-v", "--version",
|
|
||||||
action="callback", callback=opt_version,
|
|
||||||
help="Print the SCons version number and exit.")
|
|
||||||
|
|
||||||
def opt_warn(option, opt, value, parser, tree_options=tree_options):
|
|
||||||
if SCons.Util.is_String(value):
|
|
||||||
value = string.split(value, ',')
|
|
||||||
parser.values.warn.extend(value)
|
|
||||||
|
|
||||||
op.add_option('--warn', '--warning',
|
|
||||||
nargs=1, type="string",
|
|
||||||
dest="warn", default=[],
|
|
||||||
action="callback", callback=opt_warn,
|
|
||||||
help="Enable or disable warnings.",
|
|
||||||
metavar="WARNING-SPEC")
|
|
||||||
|
|
||||||
op.add_option('-Y', '--repository', '--srcdir',
|
|
||||||
nargs=1,
|
|
||||||
dest="repository", default=[],
|
|
||||||
action="append",
|
|
||||||
help="Search REPOSITORY for source and target files.")
|
|
||||||
|
|
||||||
# Options from Make and Cons classic that we do not yet support,
|
|
||||||
# but which we may support someday and whose (potential) meanings
|
|
||||||
# we don't want to change. These all get a "the -X option is not
|
|
||||||
# yet implemented" message and don't show up in the help output.
|
|
||||||
|
|
||||||
def opt_not_yet(option, opt, value, parser):
|
|
||||||
msg = "Warning: the %s option is not yet implemented\n" % opt
|
|
||||||
sys.stderr.write(msg)
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
|
|
||||||
op.add_option('-l', '--load-average', '--max-load',
|
|
||||||
nargs=1, type="int",
|
|
||||||
dest="load_average", default=0,
|
|
||||||
action="callback", callback=opt_not_yet,
|
|
||||||
# action="store",
|
|
||||||
# help="Don't start multiple jobs unless load is below "
|
|
||||||
# "LOAD-AVERAGE."
|
|
||||||
help=SUPPRESS_HELP)
|
|
||||||
op.add_option('--list-actions',
|
|
||||||
dest="list_actions",
|
|
||||||
action="callback", callback=opt_not_yet,
|
|
||||||
# help="Don't build; list files and build actions."
|
|
||||||
help=SUPPRESS_HELP)
|
|
||||||
op.add_option('--list-derived',
|
|
||||||
dest="list_derived",
|
|
||||||
action="callback", callback=opt_not_yet,
|
|
||||||
# help="Don't build; list files that would be built."
|
|
||||||
help=SUPPRESS_HELP)
|
|
||||||
op.add_option('--list-where',
|
|
||||||
dest="list_where",
|
|
||||||
action="callback", callback=opt_not_yet,
|
|
||||||
# help="Don't build; list files and where defined."
|
|
||||||
help=SUPPRESS_HELP)
|
|
||||||
op.add_option('-o', '--old-file', '--assume-old',
|
|
||||||
nargs=1, type="string",
|
|
||||||
dest="old_file", default=[],
|
|
||||||
action="callback", callback=opt_not_yet,
|
|
||||||
# action="append",
|
|
||||||
# help = "Consider FILE to be old; don't rebuild it."
|
|
||||||
help=SUPPRESS_HELP)
|
|
||||||
op.add_option('--override',
|
|
||||||
nargs=1, type="string",
|
|
||||||
action="callback", callback=opt_not_yet,
|
|
||||||
dest="override",
|
|
||||||
# help="Override variables as specified in FILE."
|
|
||||||
help=SUPPRESS_HELP)
|
|
||||||
op.add_option('-p',
|
|
||||||
action="callback", callback=opt_not_yet,
|
|
||||||
dest="p",
|
|
||||||
# help="Print internal environments/objects."
|
|
||||||
help=SUPPRESS_HELP)
|
|
||||||
op.add_option('-r', '-R', '--no-builtin-rules', '--no-builtin-variables',
|
|
||||||
action="callback", callback=opt_not_yet,
|
|
||||||
dest="no_builtin_rules",
|
|
||||||
# help="Clear default environments and variables."
|
|
||||||
help=SUPPRESS_HELP)
|
|
||||||
op.add_option('--write-filenames',
|
|
||||||
nargs=1, type="string",
|
|
||||||
dest="write_filenames",
|
|
||||||
action="callback", callback=opt_not_yet,
|
|
||||||
# help="Write all filenames examined into FILE."
|
|
||||||
help=SUPPRESS_HELP)
|
|
||||||
op.add_option('-W', '--new-file', '--assume-new', '--what-if',
|
|
||||||
nargs=1, type="string",
|
|
||||||
dest="new_file",
|
|
||||||
action="callback", callback=opt_not_yet,
|
|
||||||
# help="Consider FILE to be changed."
|
|
||||||
help=SUPPRESS_HELP)
|
|
||||||
op.add_option('--warn-undefined-variables',
|
|
||||||
dest="warn_undefined_variables",
|
|
||||||
action="callback", callback=opt_not_yet,
|
|
||||||
# help="Warn when an undefined variable is referenced."
|
|
||||||
help=SUPPRESS_HELP)
|
|
||||||
|
|
||||||
return op
|
|
|
@ -1,632 +0,0 @@
|
||||||
"""SCons.Script.SConscript
|
|
||||||
|
|
||||||
This module defines the Python API provided to SConscript and SConstruct
|
|
||||||
files.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Script/SConscript.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import SCons
|
|
||||||
import SCons.Action
|
|
||||||
import SCons.Builder
|
|
||||||
import SCons.Defaults
|
|
||||||
import SCons.Environment
|
|
||||||
import SCons.Errors
|
|
||||||
import SCons.Node
|
|
||||||
import SCons.Node.Alias
|
|
||||||
import SCons.Node.FS
|
|
||||||
import SCons.Platform
|
|
||||||
import SCons.SConf
|
|
||||||
import SCons.Script.Main
|
|
||||||
import SCons.Tool
|
|
||||||
import SCons.Util
|
|
||||||
|
|
||||||
import os
|
|
||||||
import os.path
|
|
||||||
import re
|
|
||||||
import string
|
|
||||||
import sys
|
|
||||||
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 = []
|
|
||||||
|
|
||||||
class SConscriptReturn(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
launch_dir = os.path.abspath(os.curdir)
|
|
||||||
|
|
||||||
GlobalDict = None
|
|
||||||
|
|
||||||
# global exports set by Export():
|
|
||||||
global_exports = {}
|
|
||||||
|
|
||||||
# chdir flag
|
|
||||||
sconscript_chdir = 1
|
|
||||||
|
|
||||||
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:
|
|
||||||
# Don't start iterating with the current stack-frame to
|
|
||||||
# prevent creating reference cycles (f_back is safe).
|
|
||||||
frame = sys.exc_info()[2].tb_frame.f_back
|
|
||||||
|
|
||||||
# Find the first frame that *isn't* from this file. This means
|
|
||||||
# that we expect all of the SCons frames that implement an Export()
|
|
||||||
# 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
|
|
||||||
|
|
||||||
|
|
||||||
def compute_exports(exports):
|
|
||||||
"""Compute a dictionary of exports given one of the parameters
|
|
||||||
to the Export() function or the exports argument to SConscript()."""
|
|
||||||
|
|
||||||
loc, glob = get_calling_namespaces()
|
|
||||||
|
|
||||||
retval = {}
|
|
||||||
try:
|
|
||||||
for export in exports:
|
|
||||||
if SCons.Util.is_Dict(export):
|
|
||||||
retval.update(export)
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
retval[export] = loc[export]
|
|
||||||
except KeyError:
|
|
||||||
retval[export] = glob[export]
|
|
||||||
except KeyError, x:
|
|
||||||
raise SCons.Errors.UserError, "Export of non-existent variable '%s'"%x
|
|
||||||
|
|
||||||
return retval
|
|
||||||
|
|
||||||
class Frame:
|
|
||||||
"""A frame on the SConstruct/SConscript call stack"""
|
|
||||||
def __init__(self, fs, exports, sconscript):
|
|
||||||
self.globals = BuildDefaultGlobals()
|
|
||||||
self.retval = None
|
|
||||||
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
|
|
||||||
elif sconscript == '-':
|
|
||||||
self.sconscript = None
|
|
||||||
else:
|
|
||||||
self.sconscript = fs.File(str(sconscript))
|
|
||||||
|
|
||||||
# the SConstruct/SConscript call stack:
|
|
||||||
call_stack = []
|
|
||||||
|
|
||||||
# For documentation on the methods in this file, see the scons man-page
|
|
||||||
|
|
||||||
def Return(*vars, **kw):
|
|
||||||
retval = []
|
|
||||||
try:
|
|
||||||
fvars = SCons.Util.flatten(vars)
|
|
||||||
for var in fvars:
|
|
||||||
for v in string.split(var):
|
|
||||||
retval.append(call_stack[-1].globals[v])
|
|
||||||
except KeyError, x:
|
|
||||||
raise SCons.Errors.UserError, "Return of non-existent variable '%s'"%x
|
|
||||||
|
|
||||||
if len(retval) == 1:
|
|
||||||
call_stack[-1].retval = retval[0]
|
|
||||||
else:
|
|
||||||
call_stack[-1].retval = tuple(retval)
|
|
||||||
|
|
||||||
stop = kw.get('stop', True)
|
|
||||||
|
|
||||||
if stop:
|
|
||||||
raise SConscriptReturn
|
|
||||||
|
|
||||||
|
|
||||||
stack_bottom = '% Stack boTTom %' # hard to define a variable w/this name :)
|
|
||||||
|
|
||||||
def _SConscript(fs, *files, **kw):
|
|
||||||
top = fs.Top
|
|
||||||
sd = fs.SConstruct_dir.rdir()
|
|
||||||
exports = kw.get('exports', [])
|
|
||||||
|
|
||||||
# evaluate each SConscript file
|
|
||||||
results = []
|
|
||||||
for fn in files:
|
|
||||||
call_stack.append(Frame(fs, exports, fn))
|
|
||||||
old_sys_path = sys.path
|
|
||||||
try:
|
|
||||||
SCons.Script.sconscript_reading = SCons.Script.sconscript_reading + 1
|
|
||||||
if fn == "-":
|
|
||||||
exec sys.stdin in call_stack[-1].globals
|
|
||||||
else:
|
|
||||||
if isinstance(fn, SCons.Node.Node):
|
|
||||||
f = fn
|
|
||||||
else:
|
|
||||||
f = fs.File(str(fn))
|
|
||||||
_file_ = None
|
|
||||||
|
|
||||||
# Change directory to the top of the source
|
|
||||||
# tree to make sure the os's cwd and the cwd of
|
|
||||||
# fs match so we can open the SConscript.
|
|
||||||
fs.chdir(top, change_os_dir=1)
|
|
||||||
if f.rexists():
|
|
||||||
_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)
|
|
||||||
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
|
|
||||||
# we're using the -f option, we're essentially
|
|
||||||
# creating a parallel SConscript directory structure
|
|
||||||
# in our local directory tree.
|
|
||||||
#
|
|
||||||
# XXX This is broken for multiple-repository cases
|
|
||||||
# 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)
|
|
||||||
except OSError:
|
|
||||||
# There was no local directory, so we should be
|
|
||||||
# able to chdir to the Repository directory.
|
|
||||||
# Note that we do this directly, not through
|
|
||||||
# fs.chdir(), because we still need to
|
|
||||||
# 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
|
|
||||||
# of sys.path so Python modules in the SConscript
|
|
||||||
# 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.
|
|
||||||
# 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:
|
|
||||||
try:
|
|
||||||
exec _file_ in call_stack[-1].globals
|
|
||||||
except SConscriptReturn:
|
|
||||||
pass
|
|
||||||
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:
|
|
||||||
SCons.Script.sconscript_reading = SCons.Script.sconscript_reading - 1
|
|
||||||
sys.path = old_sys_path
|
|
||||||
frame = call_stack.pop()
|
|
||||||
try:
|
|
||||||
fs.chdir(frame.prev_dir, change_os_dir=sconscript_chdir)
|
|
||||||
except OSError:
|
|
||||||
# There was no local directory, so chdir to the
|
|
||||||
# Repository directory. Like above, we do this
|
|
||||||
# directly.
|
|
||||||
fs.chdir(frame.prev_dir, change_os_dir=0)
|
|
||||||
rdir = frame.prev_dir.rdir()
|
|
||||||
rdir._create() # Make sure there's a directory there.
|
|
||||||
try:
|
|
||||||
os.chdir(rdir.get_abspath())
|
|
||||||
except OSError, e:
|
|
||||||
# We still couldn't chdir there, so raise the error,
|
|
||||||
# but only if actions are being executed.
|
|
||||||
#
|
|
||||||
# If the -n option was used, the directory would *not*
|
|
||||||
# have been created and we should just carry on and
|
|
||||||
# let things muddle through. This isn't guaranteed
|
|
||||||
# to work if the SConscript files are reading things
|
|
||||||
# from disk (for example), but it should work well
|
|
||||||
# enough for most configurations.
|
|
||||||
if SCons.Action.execute_actions:
|
|
||||||
raise e
|
|
||||||
|
|
||||||
results.append(frame.retval)
|
|
||||||
|
|
||||||
# if we only have one script, don't return a tuple
|
|
||||||
if len(results) == 1:
|
|
||||||
return results[0]
|
|
||||||
else:
|
|
||||||
return tuple(results)
|
|
||||||
|
|
||||||
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()
|
|
||||||
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.
|
|
||||||
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:
|
|
||||||
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."""
|
|
||||||
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
|
|
||||||
# leave this disabled until we find a more efficient mechanism.
|
|
||||||
#SCons.Node.Annotate = annotate
|
|
||||||
|
|
||||||
class SConsEnvironment(SCons.Environment.Base):
|
|
||||||
"""An Environment subclass that contains all of the methods that
|
|
||||||
are particular to the wrapper SCons interface and which aren't
|
|
||||||
(or shouldn't be) part of the build engine itself.
|
|
||||||
|
|
||||||
Note that not all of the methods of this class have corresponding
|
|
||||||
global functions, there are some private methods.
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Private methods of an SConsEnvironment.
|
|
||||||
#
|
|
||||||
def _exceeds_version(self, major, minor, v_major, v_minor):
|
|
||||||
"""Return 1 if 'major' and 'minor' are greater than the version
|
|
||||||
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_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())
|
|
||||||
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):
|
|
||||||
"""
|
|
||||||
Convert the parameters passed to # SConscript() calls into a list
|
|
||||||
of files and export variables. If the parameters are invalid,
|
|
||||||
throws SCons.Errors.UserError. Returns a tuple (l, e) where l
|
|
||||||
is a list of SConscript filenames and e is a list of exports.
|
|
||||||
"""
|
|
||||||
exports = []
|
|
||||||
|
|
||||||
if len(ls) == 0:
|
|
||||||
try:
|
|
||||||
dirs = kw["dirs"]
|
|
||||||
except KeyError:
|
|
||||||
raise SCons.Errors.UserError, \
|
|
||||||
"Invalid SConscript usage - no parameters"
|
|
||||||
|
|
||||||
if not SCons.Util.is_List(dirs):
|
|
||||||
dirs = [ dirs ]
|
|
||||||
dirs = map(str, dirs)
|
|
||||||
|
|
||||||
name = kw.get('name', 'SConscript')
|
|
||||||
|
|
||||||
files = map(lambda n, name = name: os.path.join(n, name), dirs)
|
|
||||||
|
|
||||||
elif len(ls) == 1:
|
|
||||||
|
|
||||||
files = ls[0]
|
|
||||||
|
|
||||||
elif len(ls) == 2:
|
|
||||||
|
|
||||||
files = ls[0]
|
|
||||||
exports = self.Split(ls[1])
|
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
raise SCons.Errors.UserError, \
|
|
||||||
"Invalid SConscript() usage - too many arguments"
|
|
||||||
|
|
||||||
if not SCons.Util.is_List(files):
|
|
||||||
files = [ files ]
|
|
||||||
|
|
||||||
if kw.get('exports'):
|
|
||||||
exports.extend(self.Split(kw['exports']))
|
|
||||||
|
|
||||||
variant_dir = kw.get('variant_dir') or kw.get('build_dir')
|
|
||||||
if variant_dir:
|
|
||||||
if len(files) != 1:
|
|
||||||
raise SCons.Errors.UserError, \
|
|
||||||
"Invalid SConscript() usage - can only specify one SConscript with a variant_dir"
|
|
||||||
duplicate = kw.get('duplicate', 1)
|
|
||||||
src_dir = kw.get('src_dir')
|
|
||||||
if not src_dir:
|
|
||||||
src_dir, fname = os.path.split(str(files[0]))
|
|
||||||
files = [os.path.join(str(variant_dir), fname)]
|
|
||||||
else:
|
|
||||||
if not isinstance(src_dir, SCons.Node.Node):
|
|
||||||
src_dir = self.fs.Dir(src_dir)
|
|
||||||
fn = files[0]
|
|
||||||
if not isinstance(fn, SCons.Node.Node):
|
|
||||||
fn = self.fs.File(fn)
|
|
||||||
if fn.is_under(src_dir):
|
|
||||||
# Get path relative to the source directory.
|
|
||||||
fname = fn.get_path(src_dir)
|
|
||||||
files = [os.path.join(str(variant_dir), fname)]
|
|
||||||
else:
|
|
||||||
files = [fn.abspath]
|
|
||||||
kw['src_dir'] = variant_dir
|
|
||||||
self.fs.VariantDir(variant_dir, src_dir, duplicate)
|
|
||||||
|
|
||||||
return (files, exports)
|
|
||||||
|
|
||||||
#
|
|
||||||
# Public methods of an SConsEnvironment. These get
|
|
||||||
# entry points in the global name space so they can be called
|
|
||||||
# as global functions.
|
|
||||||
#
|
|
||||||
|
|
||||||
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 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."""
|
|
||||||
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:
|
|
||||||
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)
|
|
||||||
|
|
||||||
def Exit(self, value=0):
|
|
||||||
sys.exit(value)
|
|
||||||
|
|
||||||
def Export(self, *vars):
|
|
||||||
for var in vars:
|
|
||||||
global_exports.update(compute_exports(self.Split(var)))
|
|
||||||
|
|
||||||
def GetLaunchDir(self):
|
|
||||||
global launch_dir
|
|
||||||
return launch_dir
|
|
||||||
|
|
||||||
def GetOption(self, name):
|
|
||||||
name = self.subst(name)
|
|
||||||
return SCons.Script.Main.GetOption(name)
|
|
||||||
|
|
||||||
def Help(self, text):
|
|
||||||
text = self.subst(text, raw=1)
|
|
||||||
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 == '*':
|
|
||||||
globals.update(global_exports)
|
|
||||||
globals.update(exports)
|
|
||||||
else:
|
|
||||||
if exports.has_key(v):
|
|
||||||
globals[v] = exports[v]
|
|
||||||
else:
|
|
||||||
globals[v] = global_exports[v]
|
|
||||||
except KeyError,x:
|
|
||||||
raise SCons.Errors.UserError, "Import of non-existent variable '%s'"%x
|
|
||||||
|
|
||||||
def SConscript(self, *ls, **kw):
|
|
||||||
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):
|
|
||||||
val = self.subst(val)
|
|
||||||
elif SCons.Util.is_List(val):
|
|
||||||
result = []
|
|
||||||
for v in val:
|
|
||||||
if SCons.Util.is_String(v):
|
|
||||||
v = self.subst(v)
|
|
||||||
result.append(v)
|
|
||||||
val = result
|
|
||||||
subst_kw[key] = val
|
|
||||||
|
|
||||||
files, exports = self._get_SConscript_filenames(ls, subst_kw)
|
|
||||||
subst_kw['exports'] = exports
|
|
||||||
return apply(_SConscript, [self.fs,] + files, subst_kw)
|
|
||||||
|
|
||||||
def SConscriptChdir(self, flag):
|
|
||||||
global sconscript_chdir
|
|
||||||
sconscript_chdir = flag
|
|
||||||
|
|
||||||
def SetOption(self, name, value):
|
|
||||||
name = self.subst(name)
|
|
||||||
SCons.Script.Main.SetOption(name, value)
|
|
||||||
|
|
||||||
#
|
|
||||||
#
|
|
||||||
#
|
|
||||||
SCons.Environment.Environment = SConsEnvironment
|
|
||||||
|
|
||||||
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():
|
|
||||||
global _DefaultEnvironmentProxy
|
|
||||||
if not _DefaultEnvironmentProxy:
|
|
||||||
default_env = SCons.Defaults.DefaultEnvironment()
|
|
||||||
_DefaultEnvironmentProxy = SCons.Environment.NoSubstitutionProxy(default_env)
|
|
||||||
return _DefaultEnvironmentProxy
|
|
||||||
|
|
||||||
class DefaultEnvironmentCall:
|
|
||||||
"""A class that implements "global function" calls of
|
|
||||||
Environment methods by fetching the specified method from the
|
|
||||||
DefaultEnvironment's class. Note that this uses an intermediate
|
|
||||||
proxy class instead of calling the DefaultEnvironment method
|
|
||||||
directly so that the proxy can override the subst() method and
|
|
||||||
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, subst=0):
|
|
||||||
self.method_name = method_name
|
|
||||||
if subst:
|
|
||||||
self.factory = SCons.Defaults.DefaultEnvironment
|
|
||||||
else:
|
|
||||||
self.factory = get_DefaultEnvironmentProxy
|
|
||||||
def __call__(self, *args, **kw):
|
|
||||||
env = self.factory()
|
|
||||||
method = getattr(env, self.method_name)
|
|
||||||
return apply(method, args, kw)
|
|
||||||
|
|
||||||
|
|
||||||
def BuildDefaultGlobals():
|
|
||||||
"""
|
|
||||||
Create a dictionary containing all the default globals for
|
|
||||||
SConstruct and SConscript files.
|
|
||||||
"""
|
|
||||||
|
|
||||||
global GlobalDict
|
|
||||||
if GlobalDict is None:
|
|
||||||
GlobalDict = {}
|
|
||||||
|
|
||||||
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]
|
|
||||||
|
|
||||||
return GlobalDict.copy()
|
|
|
@ -1,408 +0,0 @@
|
||||||
"""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, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Script/__init__.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
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.Variables
|
|
||||||
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
|
|
||||||
#SConscriptSettableOptions = Main.SConscriptSettableOptions
|
|
||||||
|
|
||||||
AddOption = Main.AddOption
|
|
||||||
GetOption = Main.GetOption
|
|
||||||
SetOption = Main.SetOption
|
|
||||||
Progress = Main.Progress
|
|
||||||
GetBuildFailures = Main.GetBuildFailures
|
|
||||||
|
|
||||||
#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
|
|
||||||
AddMethod = SCons.Util.AddMethod
|
|
||||||
AllowSubstExceptions = SCons.Subst.SetAllowableExceptions
|
|
||||||
Builder = SCons.Builder.Builder
|
|
||||||
Configure = _SConscript.Configure
|
|
||||||
Environment = SCons.Environment.Environment
|
|
||||||
#OptParser = SCons.SConsOptions.OptParser
|
|
||||||
FindPathDirs = SCons.Scanner.FindPathDirs
|
|
||||||
Platform = SCons.Platform.Platform
|
|
||||||
Return = _SConscript.Return
|
|
||||||
Scanner = SCons.Scanner.Base
|
|
||||||
Tool = SCons.Tool.Tool
|
|
||||||
WhereIs = SCons.Util.WhereIs
|
|
||||||
|
|
||||||
#
|
|
||||||
BoolVariable = SCons.Variables.BoolVariable
|
|
||||||
EnumVariable = SCons.Variables.EnumVariable
|
|
||||||
ListVariable = SCons.Variables.ListVariable
|
|
||||||
PackageVariable = SCons.Variables.PackageVariable
|
|
||||||
PathVariable = SCons.Variables.PathVariable
|
|
||||||
|
|
||||||
# Deprecated names that will go away some day.
|
|
||||||
BoolOption = SCons.Options.BoolOption
|
|
||||||
EnumOption = SCons.Options.EnumOption
|
|
||||||
ListOption = SCons.Options.ListOption
|
|
||||||
PackageOption = SCons.Options.PackageOption
|
|
||||||
PathOption = SCons.Options.PathOption
|
|
||||||
|
|
||||||
# Action factories.
|
|
||||||
Chmod = SCons.Defaults.Chmod
|
|
||||||
Copy = SCons.Defaults.Copy
|
|
||||||
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 Variables(files=[], args=ARGUMENTS):
|
|
||||||
return SCons.Variables.Variables(files, args)
|
|
||||||
|
|
||||||
def Options(files=[], 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',
|
|
||||||
'Help',
|
|
||||||
'Import',
|
|
||||||
#'SConscript', is handled separately, below.
|
|
||||||
'SConscriptChdir',
|
|
||||||
|
|
||||||
# Methods from the Environment.Base class.
|
|
||||||
'AddPostAction',
|
|
||||||
'AddPreAction',
|
|
||||||
'Alias',
|
|
||||||
'AlwaysBuild',
|
|
||||||
'BuildDir',
|
|
||||||
'CacheDir',
|
|
||||||
'Clean',
|
|
||||||
#The Command() method is handled separately, below.
|
|
||||||
'Decider',
|
|
||||||
'Depends',
|
|
||||||
'Dir',
|
|
||||||
'NoClean',
|
|
||||||
'NoCache',
|
|
||||||
'Entry',
|
|
||||||
'Execute',
|
|
||||||
'File',
|
|
||||||
'FindFile',
|
|
||||||
'FindInstalledFiles',
|
|
||||||
'FindSourceFiles',
|
|
||||||
'Flatten',
|
|
||||||
'GetBuildPath',
|
|
||||||
'Glob',
|
|
||||||
'Ignore',
|
|
||||||
'Install',
|
|
||||||
'InstallAs',
|
|
||||||
'Literal',
|
|
||||||
'Local',
|
|
||||||
'ParseDepends',
|
|
||||||
'Precious',
|
|
||||||
'Repository',
|
|
||||||
'Requires',
|
|
||||||
'SConsignFile',
|
|
||||||
'SideEffect',
|
|
||||||
'SourceCode',
|
|
||||||
'SourceSignatures',
|
|
||||||
'Split',
|
|
||||||
'Tag',
|
|
||||||
'TargetSignatures',
|
|
||||||
'Value',
|
|
||||||
'VariantDir',
|
|
||||||
]
|
|
||||||
|
|
||||||
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',
|
|
||||||
'Package',
|
|
||||||
]
|
|
||||||
|
|
||||||
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)
|
|
|
@ -1,57 +0,0 @@
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Sig.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
__doc__ = """Place-holder for the old SCons.Sig module hierarchy
|
|
||||||
|
|
||||||
This is no longer used, but code out there (such as the NSIS module on
|
|
||||||
the SCons wiki) may try to import SCons.Sig. If so, we generate a warning
|
|
||||||
that points them to the line that caused the import, and don't die.
|
|
||||||
|
|
||||||
If someone actually tried to use the sub-modules or functions within
|
|
||||||
the package (for example, SCons.Sig.MD5.signature()), then they'll still
|
|
||||||
get an AttributeError, but at least they'll know where to start looking.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import SCons.Util
|
|
||||||
import SCons.Warnings
|
|
||||||
|
|
||||||
msg = 'The SCons.Sig module no longer exists.\n' \
|
|
||||||
' Remove the following "import SCons.Sig" line to eliminate this warning:'
|
|
||||||
|
|
||||||
SCons.Warnings.warn(SCons.Warnings.DeprecatedWarning, msg)
|
|
||||||
|
|
||||||
default_calc = None
|
|
||||||
default_module = None
|
|
||||||
|
|
||||||
class MD5Null(SCons.Util.Null):
|
|
||||||
def __repr__(self):
|
|
||||||
return "MD5Null()"
|
|
||||||
|
|
||||||
class TimeStampNull(SCons.Util.Null):
|
|
||||||
def __repr__(self):
|
|
||||||
return "TimeStampNull()"
|
|
||||||
|
|
||||||
MD5 = MD5Null()
|
|
||||||
TimeStamp = TimeStampNull()
|
|
|
@ -1,884 +0,0 @@
|
||||||
"""SCons.Subst
|
|
||||||
|
|
||||||
SCons string substitution.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Subst.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import re
|
|
||||||
import string
|
|
||||||
import types
|
|
||||||
import UserList
|
|
||||||
import UserString
|
|
||||||
|
|
||||||
import SCons.Errors
|
|
||||||
|
|
||||||
from SCons.Util import is_String, is_Sequence
|
|
||||||
|
|
||||||
# Indexed by the SUBST_* constants below.
|
|
||||||
_strconv = [SCons.Util.to_String_for_subst,
|
|
||||||
SCons.Util.to_String_for_subst,
|
|
||||||
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_Sequence(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_Sequence() function will identify an object of this class as
|
|
||||||
a list during variable expansion. We're not really using any
|
|
||||||
UserList.UserList methods in practice.
|
|
||||||
"""
|
|
||||||
def __init__(self, nl):
|
|
||||||
self.nl = nl
|
|
||||||
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:
|
|
||||||
def get_tgt_subst_proxy(thing):
|
|
||||||
try:
|
|
||||||
subst_proxy = thing.get_subst_proxy()
|
|
||||||
except AttributeError:
|
|
||||||
subst_proxy = thing # probably a string, just return it
|
|
||||||
return subst_proxy
|
|
||||||
tnl = NLWrapper(target, get_tgt_subst_proxy)
|
|
||||||
dict['TARGETS'] = Targets_or_Sources(tnl)
|
|
||||||
dict['TARGET'] = Target_or_Source(tnl)
|
|
||||||
else:
|
|
||||||
dict['TARGETS'] = None
|
|
||||||
dict['TARGET'] = None
|
|
||||||
|
|
||||||
if source:
|
|
||||||
def get_src_subst_proxy(node):
|
|
||||||
try:
|
|
||||||
rfile = node.rfile
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
node = rfile()
|
|
||||||
try:
|
|
||||||
return node.get_subst_proxy()
|
|
||||||
except AttributeError:
|
|
||||||
return node # probably a String, just return it
|
|
||||||
snl = NLWrapper(source, get_src_subst_proxy)
|
|
||||||
dict['SOURCES'] = Targets_or_Sources(snl)
|
|
||||||
dict['SOURCE'] = Target_or_Source(snl)
|
|
||||||
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 ]
|
|
||||||
|
|
||||||
def _rm_list(list):
|
|
||||||
#return [ l for l in list if not l in ('$(', '$)') ]
|
|
||||||
return filter(lambda l: not l in ('$(', '$)'), list)
|
|
||||||
|
|
||||||
def _remove_list(list):
|
|
||||||
result = []
|
|
||||||
do_append = result.append
|
|
||||||
for l in list:
|
|
||||||
if l == '$(':
|
|
||||||
do_append = lambda x: None
|
|
||||||
elif l == '$)':
|
|
||||||
do_append = result.append
|
|
||||||
else:
|
|
||||||
do_append(l)
|
|
||||||
return result
|
|
||||||
|
|
||||||
# Indexed by the SUBST_* constants above.
|
|
||||||
_list_remove = [ _rm_list, None, _remove_list ]
|
|
||||||
|
|
||||||
# Regular expressions for splitting strings and handling substitutions,
|
|
||||||
# for use by the scons_subst() and scons_subst_list() functions:
|
|
||||||
#
|
|
||||||
# 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 or list containing construction variable
|
|
||||||
substitutions.
|
|
||||||
|
|
||||||
This is the work-horse function for substitutions in file names
|
|
||||||
and the like. The companion scons_subst_list() function (below)
|
|
||||||
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_Sequence(s):
|
|
||||||
def func(l, conv=self.conv, substitute=self.substitute, lvars=lvars):
|
|
||||||
return conv(substitute(l, lvars))
|
|
||||||
return map(func, s)
|
|
||||||
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):
|
|
||||||
args = str(args) # In case it's a UserString.
|
|
||||||
try:
|
|
||||||
def sub_match(match, conv=self.conv, expand=self.expand, lvars=lvars):
|
|
||||||
return conv(expand(match.group(1), lvars))
|
|
||||||
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)))
|
|
||||||
if len(result) == 1:
|
|
||||||
result = result[0]
|
|
||||||
else:
|
|
||||||
result = string.join(map(str, result), '')
|
|
||||||
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))
|
|
||||||
elif is_Sequence(result):
|
|
||||||
remove = _list_remove[mode]
|
|
||||||
if remove:
|
|
||||||
result = remove(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_trace(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_Sequence(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 = str(args) # In case it's a UserString.
|
|
||||||
args = _separate_args.findall(args)
|
|
||||||
for a in args:
|
|
||||||
if a[0] in ' \t\n\r\f\v':
|
|
||||||
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_Sequence(a):
|
|
||||||
return string.join(map(str, a))
|
|
||||||
else:
|
|
||||||
return str(a)
|
|
||||||
|
|
||||||
if is_Sequence(strSubst):
|
|
||||||
result = []
|
|
||||||
for arg in strSubst:
|
|
||||||
if is_String(arg):
|
|
||||||
if arg in matchlist:
|
|
||||||
arg = val
|
|
||||||
if is_Sequence(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
|
|
|
@ -1,985 +0,0 @@
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__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__ = "src/engine/SCons/Taskmaster.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
from itertools import chain
|
|
||||||
import operator
|
|
||||||
import string
|
|
||||||
import sys
|
|
||||||
import traceback
|
|
||||||
|
|
||||||
import SCons.Errors
|
|
||||||
import SCons.Node
|
|
||||||
|
|
||||||
StateString = SCons.Node.StateString
|
|
||||||
NODE_NO_STATE = SCons.Node.no_state
|
|
||||||
NODE_PENDING = SCons.Node.pending
|
|
||||||
NODE_EXECUTING = SCons.Node.executing
|
|
||||||
NODE_UP_TO_DATE = SCons.Node.up_to_date
|
|
||||||
NODE_EXECUTED = SCons.Node.executed
|
|
||||||
NODE_FAILED = SCons.Node.failed
|
|
||||||
|
|
||||||
|
|
||||||
# A subsystem for recording stats about how different Nodes are handled by
|
|
||||||
# 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 trace_message(self, method, node, description='node'):
|
|
||||||
fmt = '%-20s %s %s\n'
|
|
||||||
return fmt % (method + ':', description, self.tm.trace_node(node))
|
|
||||||
|
|
||||||
def display(self, message):
|
|
||||||
"""
|
|
||||||
Hook to allow the calling interface to display a message.
|
|
||||||
|
|
||||||
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.
|
|
||||||
"""
|
|
||||||
T = self.tm.trace
|
|
||||||
if T: T.write(self.trace_message('Task.prepare()', self.node))
|
|
||||||
|
|
||||||
# Now that it's the appropriate time, give the TaskMaster a
|
|
||||||
# chance to raise any exceptions it encountered while preparing
|
|
||||||
# this task.
|
|
||||||
self.exception_raise()
|
|
||||||
|
|
||||||
if self.tm.message:
|
|
||||||
self.display(self.tm.message)
|
|
||||||
self.tm.message = None
|
|
||||||
|
|
||||||
# Let the targets take care of any necessary preparations.
|
|
||||||
# This includes verifying that all of the necessary sources
|
|
||||||
# and dependencies exist, removing the target file(s), etc.
|
|
||||||
#
|
|
||||||
# As of April 2008, the get_executor().prepare() method makes
|
|
||||||
# sure that all of the aggregate sources necessary to build this
|
|
||||||
# Task's target(s) exist in one up-front check. The individual
|
|
||||||
# target t.prepare() methods check that each target's explicit
|
|
||||||
# or implicit dependencies exists, and also initialize the
|
|
||||||
# .sconsign info.
|
|
||||||
self.targets[0].get_executor().prepare()
|
|
||||||
for t in self.targets:
|
|
||||||
t.prepare()
|
|
||||||
for s in t.side_effects:
|
|
||||||
s.prepare()
|
|
||||||
|
|
||||||
def get_target(self):
|
|
||||||
"""Fetch the target being built or updated by this task.
|
|
||||||
"""
|
|
||||||
return self.node
|
|
||||||
|
|
||||||
def needs_execute(self):
|
|
||||||
"""
|
|
||||||
Called to determine whether the task's execute() method should
|
|
||||||
be run.
|
|
||||||
|
|
||||||
This method allows one to skip the somethat costly execution
|
|
||||||
of the execute() method in a seperate thread. For example,
|
|
||||||
that would be unnecessary for up-to-date targets.
|
|
||||||
"""
|
|
||||||
return True
|
|
||||||
|
|
||||||
def execute(self):
|
|
||||||
"""
|
|
||||||
Called to execute the task.
|
|
||||||
|
|
||||||
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().
|
|
||||||
"""
|
|
||||||
T = self.tm.trace
|
|
||||||
if T: T.write(self.trace_message('Task.execute()', self.node))
|
|
||||||
|
|
||||||
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 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 Exception, e:
|
|
||||||
buildError = SCons.Errors.convert_to_BuildError(e)
|
|
||||||
buildError.node = self.targets[0]
|
|
||||||
buildError.exc_info = sys.exc_info()
|
|
||||||
raise buildError
|
|
||||||
|
|
||||||
def executed_without_callbacks(self):
|
|
||||||
"""
|
|
||||||
Called when the task has been successfully executed
|
|
||||||
and the Taskmaster instance doesn't want to call
|
|
||||||
the Node's callback methods.
|
|
||||||
"""
|
|
||||||
T = self.tm.trace
|
|
||||||
if T: T.write(self.trace_message('Task.executed_without_callbacks()',
|
|
||||||
self.node))
|
|
||||||
|
|
||||||
for t in self.targets:
|
|
||||||
if t.get_state() == NODE_EXECUTING:
|
|
||||||
for side_effect in t.side_effects:
|
|
||||||
side_effect.set_state(NODE_NO_STATE)
|
|
||||||
t.set_state(NODE_EXECUTED)
|
|
||||||
|
|
||||||
def executed_with_callbacks(self):
|
|
||||||
"""
|
|
||||||
Called when the task has been successfully executed and
|
|
||||||
the Taskmaster instance wants to call the Node's callback
|
|
||||||
methods.
|
|
||||||
|
|
||||||
This may have been a do-nothing operation (to preserve build
|
|
||||||
order), so we must check the node's state before deciding whether
|
|
||||||
it was "built", in which case we call the appropriate Node method.
|
|
||||||
In any event, we always call "visited()", which will handle any
|
|
||||||
post-visit actions that must take place regardless of whether
|
|
||||||
or not the target was an actual built target or a source Node.
|
|
||||||
"""
|
|
||||||
T = self.tm.trace
|
|
||||||
if T: T.write(self.trace_message('Task.executed_with_callbacks()',
|
|
||||||
self.node))
|
|
||||||
|
|
||||||
for t in self.targets:
|
|
||||||
if t.get_state() == NODE_EXECUTING:
|
|
||||||
for side_effect in t.side_effects:
|
|
||||||
side_effect.set_state(NODE_NO_STATE)
|
|
||||||
t.set_state(NODE_EXECUTED)
|
|
||||||
t.built()
|
|
||||||
t.visited()
|
|
||||||
|
|
||||||
executed = executed_with_callbacks
|
|
||||||
|
|
||||||
def failed(self):
|
|
||||||
"""
|
|
||||||
Default action when a task fails: stop the build.
|
|
||||||
|
|
||||||
Note: Although this function is normally invoked on nodes in
|
|
||||||
the executing state, it might also be invoked on up-to-date
|
|
||||||
nodes when using Configure().
|
|
||||||
"""
|
|
||||||
self.fail_stop()
|
|
||||||
|
|
||||||
def fail_stop(self):
|
|
||||||
"""
|
|
||||||
Explicit stop-the-build failure.
|
|
||||||
|
|
||||||
This sets failure status on the target nodes and all of
|
|
||||||
their dependent parent nodes.
|
|
||||||
|
|
||||||
Note: Although this function is normally invoked on nodes in
|
|
||||||
the executing state, it might also be invoked on up-to-date
|
|
||||||
nodes when using Configure().
|
|
||||||
"""
|
|
||||||
T = self.tm.trace
|
|
||||||
if T: T.write(self.trace_message('Task.failed_stop()', self.node))
|
|
||||||
|
|
||||||
# Invoke will_not_build() to clean-up the pending children
|
|
||||||
# list.
|
|
||||||
self.tm.will_not_build(self.targets, lambda n: n.set_state(NODE_FAILED))
|
|
||||||
|
|
||||||
# Tell the taskmaster to not start any new tasks
|
|
||||||
self.tm.stop()
|
|
||||||
|
|
||||||
# We're stopping because of a build failure, but give the
|
|
||||||
# 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.
|
|
||||||
|
|
||||||
Note: Although this function is normally invoked on nodes in
|
|
||||||
the executing state, it might also be invoked on up-to-date
|
|
||||||
nodes when using Configure().
|
|
||||||
"""
|
|
||||||
T = self.tm.trace
|
|
||||||
if T: T.write(self.trace_message('Task.failed_continue()', self.node))
|
|
||||||
|
|
||||||
self.tm.will_not_build(self.targets, lambda n: n.set_state(NODE_FAILED))
|
|
||||||
|
|
||||||
def make_ready_all(self):
|
|
||||||
"""
|
|
||||||
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.
|
|
||||||
"""
|
|
||||||
T = self.tm.trace
|
|
||||||
if T: T.write(self.trace_message('Task.make_ready_all()', self.node))
|
|
||||||
|
|
||||||
self.out_of_date = self.targets[:]
|
|
||||||
for t in self.targets:
|
|
||||||
t.disambiguate().set_state(NODE_EXECUTING)
|
|
||||||
for s in t.side_effects:
|
|
||||||
s.set_state(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.
|
|
||||||
"""
|
|
||||||
T = self.tm.trace
|
|
||||||
if T: T.write(self.trace_message('Task.make_ready_current()',
|
|
||||||
self.node))
|
|
||||||
|
|
||||||
self.out_of_date = []
|
|
||||||
needs_executing = False
|
|
||||||
for t in self.targets:
|
|
||||||
try:
|
|
||||||
t.disambiguate().make_ready()
|
|
||||||
is_up_to_date = not t.has_builder() or \
|
|
||||||
(not t.always_build and t.is_up_to_date())
|
|
||||||
except EnvironmentError, e:
|
|
||||||
raise SCons.Errors.BuildError(node=t, errstr=e.strerror, filename=e.filename)
|
|
||||||
|
|
||||||
if not is_up_to_date:
|
|
||||||
self.out_of_date.append(t)
|
|
||||||
needs_executing = True
|
|
||||||
|
|
||||||
if needs_executing:
|
|
||||||
for t in self.targets:
|
|
||||||
t.set_state(NODE_EXECUTING)
|
|
||||||
for s in t.side_effects:
|
|
||||||
s.set_state(NODE_EXECUTING)
|
|
||||||
else:
|
|
||||||
for t in self.targets:
|
|
||||||
# We must invoke visited() to ensure that the node
|
|
||||||
# information has been computed before allowing the
|
|
||||||
# parent nodes to execute. (That could occur in a
|
|
||||||
# parallel build...)
|
|
||||||
t.visited()
|
|
||||||
t.set_state(NODE_UP_TO_DATE)
|
|
||||||
|
|
||||||
make_ready = make_ready_current
|
|
||||||
|
|
||||||
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.
|
|
||||||
"""
|
|
||||||
T = self.tm.trace
|
|
||||||
if T: T.write(self.trace_message('Task.postprocess()', self.node))
|
|
||||||
|
|
||||||
# We may have built multiple targets, some of which may have
|
|
||||||
# common parents waiting for this build. Count up how many
|
|
||||||
# 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.
|
|
||||||
|
|
||||||
targets = set(self.targets)
|
|
||||||
|
|
||||||
pending_children = self.tm.pending_children
|
|
||||||
parents = {}
|
|
||||||
for t in targets:
|
|
||||||
# A node can only be in the pending_children set if it has
|
|
||||||
# some waiting_parents.
|
|
||||||
if t.waiting_parents:
|
|
||||||
if T: T.write(self.trace_message('Task.postprocess()',
|
|
||||||
t,
|
|
||||||
'removing'))
|
|
||||||
pending_children.discard(t)
|
|
||||||
for p in t.waiting_parents:
|
|
||||||
parents[p] = parents.get(p, 0) + 1
|
|
||||||
|
|
||||||
for t in targets:
|
|
||||||
for s in t.side_effects:
|
|
||||||
if s.get_state() == NODE_EXECUTING:
|
|
||||||
s.set_state(NODE_NO_STATE)
|
|
||||||
for p in s.waiting_parents:
|
|
||||||
parents[p] = parents.get(p, 0) + 1
|
|
||||||
for p in s.waiting_s_e:
|
|
||||||
if p.ref_count == 0:
|
|
||||||
self.tm.candidates.append(p)
|
|
||||||
|
|
||||||
for p, subtract in parents.items():
|
|
||||||
p.ref_count = p.ref_count - subtract
|
|
||||||
if T: T.write(self.trace_message('Task.postprocess()',
|
|
||||||
p,
|
|
||||||
'adjusted parent ref count'))
|
|
||||||
if p.ref_count == 0:
|
|
||||||
self.tm.candidates.append(p)
|
|
||||||
|
|
||||||
for t in 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, visited):
|
|
||||||
if stack[-1] in visited:
|
|
||||||
return None
|
|
||||||
visited.add(stack[-1])
|
|
||||||
for n in stack[-1].waiting_parents:
|
|
||||||
stack.append(n)
|
|
||||||
if stack[0] == stack[-1]:
|
|
||||||
return stack
|
|
||||||
if find_cycle(stack, visited):
|
|
||||||
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.original_top = targets
|
|
||||||
self.top_targets_left = targets[:]
|
|
||||||
self.top_targets_left.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
|
|
||||||
self.pending_children = set()
|
|
||||||
|
|
||||||
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_left.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.
|
|
||||||
|
|
||||||
Note that we have to clean-up the Taskmaster candidate list
|
|
||||||
because the cycle detection depends on the fact all nodes have
|
|
||||||
been processed somehow.
|
|
||||||
"""
|
|
||||||
while self.candidates:
|
|
||||||
candidates = self.candidates
|
|
||||||
self.candidates = []
|
|
||||||
self.will_not_build(candidates)
|
|
||||||
return None
|
|
||||||
|
|
||||||
def _validate_pending_children(self):
|
|
||||||
"""
|
|
||||||
Validate the content of the pending_children set. Assert if an
|
|
||||||
internal error is found.
|
|
||||||
|
|
||||||
This function is used strictly for debugging the taskmaster by
|
|
||||||
checking that no invariants are violated. It is not used in
|
|
||||||
normal operation.
|
|
||||||
|
|
||||||
The pending_children set is used to detect cycles in the
|
|
||||||
dependency graph. We call a "pending child" a child that is
|
|
||||||
found in the "pending" state when checking the dependencies of
|
|
||||||
its parent node.
|
|
||||||
|
|
||||||
A pending child can occur when the Taskmaster completes a loop
|
|
||||||
through a cycle. For example, lets imagine a graph made of
|
|
||||||
three node (A, B and C) making a cycle. The evaluation starts
|
|
||||||
at node A. The taskmaster first consider whether node A's
|
|
||||||
child B is up-to-date. Then, recursively, node B needs to
|
|
||||||
check whether node C is up-to-date. This leaves us with a
|
|
||||||
dependency graph looking like:
|
|
||||||
|
|
||||||
Next candidate \
|
|
||||||
\
|
|
||||||
Node A (Pending) --> Node B(Pending) --> Node C (NoState)
|
|
||||||
^ |
|
|
||||||
| |
|
|
||||||
+-------------------------------------+
|
|
||||||
|
|
||||||
Now, when the Taskmaster examines the Node C's child Node A,
|
|
||||||
it finds that Node A is in the "pending" state. Therefore,
|
|
||||||
Node A is a pending child of node C.
|
|
||||||
|
|
||||||
Pending children indicate that the Taskmaster has potentially
|
|
||||||
loop back through a cycle. We say potentially because it could
|
|
||||||
also occur when a DAG is evaluated in parallel. For example,
|
|
||||||
consider the following graph:
|
|
||||||
|
|
||||||
|
|
||||||
Node A (Pending) --> Node B(Pending) --> Node C (Pending) --> ...
|
|
||||||
| ^
|
|
||||||
| |
|
|
||||||
+----------> Node D (NoState) --------+
|
|
||||||
/
|
|
||||||
Next candidate /
|
|
||||||
|
|
||||||
The Taskmaster first evaluates the nodes A, B, and C and
|
|
||||||
starts building some children of node C. Assuming, that the
|
|
||||||
maximum parallel level has not been reached, the Taskmaster
|
|
||||||
will examine Node D. It will find that Node C is a pending
|
|
||||||
child of Node D.
|
|
||||||
|
|
||||||
In summary, evaluating a graph with a cycle will always
|
|
||||||
involve a pending child at one point. A pending child might
|
|
||||||
indicate either a cycle or a diamond-shaped DAG. Only a
|
|
||||||
fraction of the nodes ends-up being a "pending child" of
|
|
||||||
another node. This keeps the pending_children set small in
|
|
||||||
practice.
|
|
||||||
|
|
||||||
We can differentiate between the two cases if we wait until
|
|
||||||
the end of the build. At this point, all the pending children
|
|
||||||
nodes due to a diamond-shaped DAG will have been properly
|
|
||||||
built (or will have failed to build). But, the pending
|
|
||||||
children involved in a cycle will still be in the pending
|
|
||||||
state.
|
|
||||||
|
|
||||||
The taskmaster removes nodes from the pending_children set as
|
|
||||||
soon as a pending_children node moves out of the pending
|
|
||||||
state. This also helps to keep the pending_children set small.
|
|
||||||
"""
|
|
||||||
|
|
||||||
for n in self.pending_children:
|
|
||||||
assert n.state in (NODE_PENDING, NODE_EXECUTING), \
|
|
||||||
(str(n), StateString[n.state])
|
|
||||||
assert len(n.waiting_parents) != 0, (str(n), len(n.waiting_parents))
|
|
||||||
for p in n.waiting_parents:
|
|
||||||
assert p.ref_count > 0, (str(n), str(p), p.ref_count)
|
|
||||||
|
|
||||||
|
|
||||||
def trace_message(self, message):
|
|
||||||
return 'Taskmaster: %s\n' % message
|
|
||||||
|
|
||||||
def trace_node(self, node):
|
|
||||||
return '<%-10s %-3s %s>' % (StateString[node.get_state()],
|
|
||||||
node.ref_count,
|
|
||||||
repr(str(node)))
|
|
||||||
|
|
||||||
def _find_next_ready_node(self):
|
|
||||||
"""
|
|
||||||
Finds the next node that is ready to be built.
|
|
||||||
|
|
||||||
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
|
|
||||||
if T: T.write('\n' + self.trace_message('Looking for a node to evaluate'))
|
|
||||||
|
|
||||||
while 1:
|
|
||||||
node = self.next_candidate()
|
|
||||||
if node is None:
|
|
||||||
if T: T.write(self.trace_message('No candidate anymore.') + '\n')
|
|
||||||
return None
|
|
||||||
|
|
||||||
node = node.disambiguate()
|
|
||||||
state = node.get_state()
|
|
||||||
|
|
||||||
# For debugging only:
|
|
||||||
#
|
|
||||||
# try:
|
|
||||||
# self._validate_pending_children()
|
|
||||||
# except:
|
|
||||||
# self.ready_exc = sys.exc_info()
|
|
||||||
# return node
|
|
||||||
|
|
||||||
if CollectStats:
|
|
||||||
if not hasattr(node, 'stats'):
|
|
||||||
node.stats = Stats()
|
|
||||||
StatsNodes.append(node)
|
|
||||||
S = node.stats
|
|
||||||
S.considered = S.considered + 1
|
|
||||||
else:
|
|
||||||
S = None
|
|
||||||
|
|
||||||
if T: T.write(self.trace_message(' Considering node %s and its children:' % self.trace_node(node)))
|
|
||||||
|
|
||||||
if state == NODE_NO_STATE:
|
|
||||||
# Mark this node as being on the execution stack:
|
|
||||||
node.set_state(NODE_PENDING)
|
|
||||||
elif state > NODE_PENDING:
|
|
||||||
# Skip this node if it has already been evaluated:
|
|
||||||
if S: S.already_handled = S.already_handled + 1
|
|
||||||
if T: T.write(self.trace_message(' already handled (executed)'))
|
|
||||||
continue
|
|
||||||
|
|
||||||
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(self.trace_message(' SystemExit'))
|
|
||||||
return node
|
|
||||||
except Exception, e:
|
|
||||||
# We had a problem just trying to figure out the
|
|
||||||
# children (like a child couldn't be linked in to a
|
|
||||||
# VariantDir, or a Scanner threw something). Arrange to
|
|
||||||
# raise the exception when the Task is "executed."
|
|
||||||
self.ready_exc = sys.exc_info()
|
|
||||||
if S: S.problem = S.problem + 1
|
|
||||||
if T: T.write(self.trace_message(' exception %s while scanning children.\n' % e))
|
|
||||||
return node
|
|
||||||
|
|
||||||
children_not_visited = []
|
|
||||||
children_pending = set()
|
|
||||||
children_not_ready = []
|
|
||||||
children_failed = False
|
|
||||||
|
|
||||||
for child in chain(children,node.prerequisites):
|
|
||||||
childstate = child.get_state()
|
|
||||||
|
|
||||||
if T: T.write(self.trace_message(' ' + self.trace_node(child)))
|
|
||||||
|
|
||||||
if childstate == NODE_NO_STATE:
|
|
||||||
children_not_visited.append(child)
|
|
||||||
elif childstate == NODE_PENDING:
|
|
||||||
children_pending.add(child)
|
|
||||||
elif childstate == NODE_FAILED:
|
|
||||||
children_failed = True
|
|
||||||
|
|
||||||
if childstate <= NODE_EXECUTING:
|
|
||||||
children_not_ready.append(child)
|
|
||||||
|
|
||||||
|
|
||||||
# These nodes have not even been visited yet. Add
|
|
||||||
# them to the list so that on some next pass we can
|
|
||||||
# take a stab at evaluating them (or their children).
|
|
||||||
children_not_visited.reverse()
|
|
||||||
self.candidates.extend(self.order(children_not_visited))
|
|
||||||
#if T and children_not_visited:
|
|
||||||
# T.write(self.trace_message(' adding to candidates: %s' % map(str, children_not_visited)))
|
|
||||||
# T.write(self.trace_message(' candidates now: %s\n' % map(str, self.candidates)))
|
|
||||||
|
|
||||||
# Skip this node if any of its children have failed.
|
|
||||||
#
|
|
||||||
# This catches the case where we're descending a top-level
|
|
||||||
# target and one of our children failed while trying to be
|
|
||||||
# built by a *previous* descent of an earlier top-level
|
|
||||||
# target.
|
|
||||||
#
|
|
||||||
# It can also occur if a node is reused in multiple
|
|
||||||
# targets. One first descends though the one of the
|
|
||||||
# target, the next time occurs through the other target.
|
|
||||||
#
|
|
||||||
# Note that we can only have failed_children if the
|
|
||||||
# --keep-going flag was used, because without it the build
|
|
||||||
# will stop before diving in the other branch.
|
|
||||||
#
|
|
||||||
# Note that even if one of the children fails, we still
|
|
||||||
# added the other children to the list of candidate nodes
|
|
||||||
# to keep on building (--keep-going).
|
|
||||||
if children_failed:
|
|
||||||
node.set_state(NODE_FAILED)
|
|
||||||
|
|
||||||
if S: S.child_failed = S.child_failed + 1
|
|
||||||
if T: T.write(self.trace_message('****** %s\n' % self.trace_node(node)))
|
|
||||||
continue
|
|
||||||
|
|
||||||
if children_not_ready:
|
|
||||||
for child in children_not_ready:
|
|
||||||
# We're waiting on one or more derived targets
|
|
||||||
# that have not yet finished building.
|
|
||||||
if S: S.not_built = S.not_built + 1
|
|
||||||
|
|
||||||
# Add this node to the waiting parents lists of
|
|
||||||
# anything we're waiting on, with a reference
|
|
||||||
# count so we can be put back on the list for
|
|
||||||
# re-evaluation when they've all finished.
|
|
||||||
node.ref_count = node.ref_count + child.add_to_waiting_parents(node)
|
|
||||||
if T: T.write(self.trace_message(' adjusted ref count: %s, child %s' %
|
|
||||||
(self.trace_node(node), repr(str(child)))))
|
|
||||||
|
|
||||||
if T:
|
|
||||||
for pc in children_pending:
|
|
||||||
T.write(self.trace_message(' adding %s to the pending children set\n' %
|
|
||||||
self.trace_node(pc)))
|
|
||||||
self.pending_children = self.pending_children | children_pending
|
|
||||||
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Skip this node if it has side-effects that are
|
|
||||||
# currently being built:
|
|
||||||
wait_side_effects = False
|
|
||||||
for se in node.side_effects:
|
|
||||||
if se.get_state() == NODE_EXECUTING:
|
|
||||||
se.add_to_waiting_s_e(node)
|
|
||||||
wait_side_effects = True
|
|
||||||
|
|
||||||
if wait_side_effects:
|
|
||||||
if S: S.side_effects = S.side_effects + 1
|
|
||||||
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(self.trace_message('Evaluating %s\n' %
|
|
||||||
self.trace_node(node)))
|
|
||||||
|
|
||||||
# For debugging only:
|
|
||||||
#
|
|
||||||
# try:
|
|
||||||
# self._validate_pending_children()
|
|
||||||
# except:
|
|
||||||
# self.ready_exc = sys.exc_info()
|
|
||||||
# return node
|
|
||||||
|
|
||||||
return node
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
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 in self.original_top, node)
|
|
||||||
try:
|
|
||||||
task.make_ready()
|
|
||||||
except:
|
|
||||||
# We had a problem just trying to get this task ready (like
|
|
||||||
# a child couldn't be linked in to a VariantDir when deciding
|
|
||||||
# whether this node is current). Arrange to raise the
|
|
||||||
# exception when the Task is "executed."
|
|
||||||
self.ready_exc = sys.exc_info()
|
|
||||||
|
|
||||||
if self.ready_exc:
|
|
||||||
task.exception_set(self.ready_exc)
|
|
||||||
|
|
||||||
self.ready_exc = None
|
|
||||||
|
|
||||||
return task
|
|
||||||
|
|
||||||
def will_not_build(self, nodes, node_func=lambda n: None):
|
|
||||||
"""
|
|
||||||
Perform clean-up about nodes that will never be built. Invokes
|
|
||||||
a user defined function on all of these nodes (including all
|
|
||||||
of their parents).
|
|
||||||
"""
|
|
||||||
|
|
||||||
T = self.trace
|
|
||||||
|
|
||||||
pending_children = self.pending_children
|
|
||||||
|
|
||||||
to_visit = set(nodes)
|
|
||||||
pending_children = pending_children - to_visit
|
|
||||||
|
|
||||||
if T:
|
|
||||||
for n in nodes:
|
|
||||||
T.write(self.trace_message(' removing node %s from the pending children set\n' %
|
|
||||||
self.trace_node(n)))
|
|
||||||
try:
|
|
||||||
while 1:
|
|
||||||
try:
|
|
||||||
node = to_visit.pop()
|
|
||||||
except AttributeError:
|
|
||||||
# Python 1.5.2
|
|
||||||
if len(to_visit):
|
|
||||||
node = to_visit[0]
|
|
||||||
to_visit.remove(node)
|
|
||||||
else:
|
|
||||||
break
|
|
||||||
|
|
||||||
node_func(node)
|
|
||||||
|
|
||||||
# Prune recursion by flushing the waiting children
|
|
||||||
# list immediately.
|
|
||||||
parents = node.waiting_parents
|
|
||||||
node.waiting_parents = set()
|
|
||||||
|
|
||||||
to_visit = to_visit | parents
|
|
||||||
pending_children = pending_children - parents
|
|
||||||
|
|
||||||
for p in parents:
|
|
||||||
p.ref_count = p.ref_count - 1
|
|
||||||
if T: T.write(self.trace_message(' removing parent %s from the pending children set\n' %
|
|
||||||
self.trace_node(p)))
|
|
||||||
except KeyError:
|
|
||||||
# The container to_visit has been emptied.
|
|
||||||
pass
|
|
||||||
|
|
||||||
# We have the stick back the pending_children list into the
|
|
||||||
# task master because the python 1.5.2 compatibility does not
|
|
||||||
# allow us to use in-place updates
|
|
||||||
self.pending_children = pending_children
|
|
||||||
|
|
||||||
def stop(self):
|
|
||||||
"""
|
|
||||||
Stops the current build completely.
|
|
||||||
"""
|
|
||||||
self.next_candidate = self.no_next_candidate
|
|
||||||
|
|
||||||
def cleanup(self):
|
|
||||||
"""
|
|
||||||
Check for dependency cycles.
|
|
||||||
"""
|
|
||||||
if not self.pending_children:
|
|
||||||
return
|
|
||||||
|
|
||||||
# TODO(1.5)
|
|
||||||
#nclist = [ (n, find_cycle([n], set())) for n in self.pending_children ]
|
|
||||||
nclist = map(lambda n: (n, find_cycle([n], set())), self.pending_children)
|
|
||||||
|
|
||||||
# TODO(1.5)
|
|
||||||
#genuine_cycles = [
|
|
||||||
# node for node, cycle in nclist
|
|
||||||
# if cycle or node.get_state() != NODE_EXECUTED
|
|
||||||
#]
|
|
||||||
genuine_cycles = filter(lambda t: t[1] or t[0].get_state() != NODE_EXECUTED, nclist)
|
|
||||||
if not genuine_cycles:
|
|
||||||
# All of the "cycles" found were single nodes in EXECUTED state,
|
|
||||||
# which is to say, they really weren't cycles. Just return.
|
|
||||||
return
|
|
||||||
|
|
||||||
desc = 'Found dependency cycle(s):\n'
|
|
||||||
for node, cycle in nclist:
|
|
||||||
if cycle:
|
|
||||||
desc = desc + " " + string.join(map(str, cycle), " -> ") + "\n"
|
|
||||||
else:
|
|
||||||
desc = desc + \
|
|
||||||
" Internal Error: no cycle found for node %s (%s) in state %s\n" % \
|
|
||||||
(node, repr(node), StateString[node.get_state()])
|
|
||||||
|
|
||||||
raise SCons.Errors.UserError, desc
|
|
|
@ -1,55 +0,0 @@
|
||||||
"""SCons.Tool.386asm
|
|
||||||
|
|
||||||
Tool specification for the 386ASM assembler for the Phar Lap ETS embedded
|
|
||||||
operating system.
|
|
||||||
|
|
||||||
There normally shouldn't be any need to import this module directly.
|
|
||||||
It will usually be imported through the generic SCons.Tool.Tool()
|
|
||||||
selection method.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Tool/386asm.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
from SCons.Tool.PharLapCommon import addPharLapPaths
|
|
||||||
import SCons.Util
|
|
||||||
|
|
||||||
as_module = __import__('as', globals(), locals(), [])
|
|
||||||
|
|
||||||
def generate(env):
|
|
||||||
"""Add Builders and construction variables for ar to an Environment."""
|
|
||||||
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 $ASPPFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS $SOURCES -o $TARGET'
|
|
||||||
|
|
||||||
addPharLapPaths(env)
|
|
||||||
|
|
||||||
def exists(env):
|
|
||||||
return env.Detect('386asm')
|
|
|
@ -1,59 +0,0 @@
|
||||||
"""SCons.Tool.BitKeeper.py
|
|
||||||
|
|
||||||
Tool-specific initialization for the BitKeeper source code control
|
|
||||||
system.
|
|
||||||
|
|
||||||
There normally shouldn't be any need to import this module directly.
|
|
||||||
It will usually be imported through the generic SCons.Tool.Tool()
|
|
||||||
selection method.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Tool/BitKeeper.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import SCons.Action
|
|
||||||
import SCons.Builder
|
|
||||||
import SCons.Util
|
|
||||||
|
|
||||||
def generate(env):
|
|
||||||
"""Add a Builder factory function and construction variables for
|
|
||||||
BitKeeper to an Environment."""
|
|
||||||
|
|
||||||
def BitKeeperFactory(env=env):
|
|
||||||
""" """
|
|
||||||
act = SCons.Action.Action("$BITKEEPERCOM", "$BITKEEPERCOMSTR")
|
|
||||||
return SCons.Builder.Builder(action = act, env = env)
|
|
||||||
|
|
||||||
#setattr(env, 'BitKeeper', BitKeeperFactory)
|
|
||||||
env.BitKeeper = BitKeeperFactory
|
|
||||||
|
|
||||||
env['BITKEEPER'] = 'bk'
|
|
||||||
env['BITKEEPERGET'] = '$BITKEEPER get'
|
|
||||||
env['BITKEEPERGETFLAGS'] = SCons.Util.CLVar('')
|
|
||||||
env['BITKEEPERCOM'] = '$BITKEEPERGET $BITKEEPERGETFLAGS $TARGET'
|
|
||||||
|
|
||||||
def exists(env):
|
|
||||||
return env.Detect('bk')
|
|
|
@ -1,67 +0,0 @@
|
||||||
"""SCons.Tool.CVS.py
|
|
||||||
|
|
||||||
Tool-specific initialization for CVS.
|
|
||||||
|
|
||||||
There normally shouldn't be any need to import this module directly.
|
|
||||||
It will usually be imported through the generic SCons.Tool.Tool()
|
|
||||||
selection method.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Tool/CVS.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import SCons.Action
|
|
||||||
import SCons.Builder
|
|
||||||
import SCons.Util
|
|
||||||
|
|
||||||
def generate(env):
|
|
||||||
"""Add a Builder factory function and construction variables for
|
|
||||||
CVS to an Environment."""
|
|
||||||
|
|
||||||
def CVSFactory(repos, module='', env=env):
|
|
||||||
""" """
|
|
||||||
# fail if repos is not an absolute path name?
|
|
||||||
if module != '':
|
|
||||||
# Don't use os.path.join() because the name we fetch might
|
|
||||||
# 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}'
|
|
||||||
act = SCons.Action.Action('$CVSCOM', '$CVSCOMSTR')
|
|
||||||
return SCons.Builder.Builder(action = act,
|
|
||||||
env = env,
|
|
||||||
CVSREPOSITORY = repos,
|
|
||||||
CVSMODULE = module)
|
|
||||||
|
|
||||||
#setattr(env, 'CVS', CVSFactory)
|
|
||||||
env.CVS = CVSFactory
|
|
||||||
|
|
||||||
env['CVS'] = 'cvs'
|
|
||||||
env['CVSFLAGS'] = SCons.Util.CLVar('-d $CVSREPOSITORY')
|
|
||||||
env['CVSCOFLAGS'] = SCons.Util.CLVar('')
|
|
||||||
env['CVSCOM'] = '$CVS $CVSFLAGS co $CVSCOFLAGS ${TARGET.posix}'
|
|
||||||
|
|
||||||
def exists(env):
|
|
||||||
return env.Detect('cvs')
|
|
|
@ -1,241 +0,0 @@
|
||||||
"""SCons.Tool.FortranCommon
|
|
||||||
|
|
||||||
Stuff for processing Fortran, common to all fortran dialects.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Tool/FortranCommon.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import re
|
|
||||||
import string
|
|
||||||
import os.path
|
|
||||||
|
|
||||||
import SCons.Action
|
|
||||||
import SCons.Defaults
|
|
||||||
import SCons.Scanner.Fortran
|
|
||||||
import SCons.Tool
|
|
||||||
import SCons.Util
|
|
||||||
|
|
||||||
def isfortran(env, source):
|
|
||||||
"""Return 1 if any of code in source has fortran files in it, 0
|
|
||||||
otherwise."""
|
|
||||||
try:
|
|
||||||
fsuffixes = env['FORTRANSUFFIXES']
|
|
||||||
except KeyError:
|
|
||||||
# If no FORTRANSUFFIXES, no fortran tool, so there is no need to look
|
|
||||||
# for fortran sources.
|
|
||||||
return 0
|
|
||||||
|
|
||||||
if not source:
|
|
||||||
# Source might be None for unusual cases like SConf.
|
|
||||||
return 0
|
|
||||||
for s in source:
|
|
||||||
if s.sources:
|
|
||||||
ext = os.path.splitext(str(s.sources[0]))[1]
|
|
||||||
if ext in fsuffixes:
|
|
||||||
return 1
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def _fortranEmitter(target, source, env):
|
|
||||||
node = source[0].rfile()
|
|
||||||
if not node.exists() and not node.is_derived():
|
|
||||||
print "Could not locate " + str(node.name)
|
|
||||||
return ([], [])
|
|
||||||
mod_regex = """(?i)^\s*MODULE\s+(?!PROCEDURE)(\w+)"""
|
|
||||||
cre = re.compile(mod_regex,re.M)
|
|
||||||
# Retrieve all USE'd module names
|
|
||||||
modules = cre.findall(node.get_contents())
|
|
||||||
# Remove unique items from the list
|
|
||||||
modules = SCons.Util.unique(modules)
|
|
||||||
# Convert module name to a .mod filename
|
|
||||||
suffix = env.subst('$FORTRANMODSUFFIX', target=target, source=source)
|
|
||||||
moddir = env.subst('$FORTRANMODDIR', target=target, source=source)
|
|
||||||
modules = map(lambda x, s=suffix: string.lower(x) + s, modules)
|
|
||||||
for m in modules:
|
|
||||||
target.append(env.fs.File(m, moddir))
|
|
||||||
return (target, source)
|
|
||||||
|
|
||||||
def FortranEmitter(target, source, env):
|
|
||||||
target, source = _fortranEmitter(target, source, env)
|
|
||||||
return SCons.Defaults.StaticObjectEmitter(target, source, env)
|
|
||||||
|
|
||||||
def ShFortranEmitter(target, source, env):
|
|
||||||
target, source = _fortranEmitter(target, source, env)
|
|
||||||
return SCons.Defaults.SharedObjectEmitter(target, source, env)
|
|
||||||
|
|
||||||
def ComputeFortranSuffixes(suffixes, ppsuffixes):
|
|
||||||
"""suffixes are fortran source files, and ppsuffixes the ones to be
|
|
||||||
pre-processed. Both should be sequences, not strings."""
|
|
||||||
assert len(suffixes) > 0
|
|
||||||
s = suffixes[0]
|
|
||||||
sup = string.upper(s)
|
|
||||||
upper_suffixes = map(string.upper, suffixes)
|
|
||||||
if SCons.Util.case_sensitive_suffixes(s, sup):
|
|
||||||
ppsuffixes.extend(upper_suffixes)
|
|
||||||
else:
|
|
||||||
suffixes.extend(upper_suffixes)
|
|
||||||
|
|
||||||
def CreateDialectActions(dialect):
|
|
||||||
"""Create dialect specific actions."""
|
|
||||||
CompAction = SCons.Action.Action('$%sCOM ' % dialect, '$%sCOMSTR' % dialect)
|
|
||||||
CompPPAction = SCons.Action.Action('$%sPPCOM ' % dialect, '$%sPPCOMSTR' % dialect)
|
|
||||||
ShCompAction = SCons.Action.Action('$SH%sCOM ' % dialect, '$SH%sCOMSTR' % dialect)
|
|
||||||
ShCompPPAction = SCons.Action.Action('$SH%sPPCOM ' % dialect, '$SH%sPPCOMSTR' % dialect)
|
|
||||||
|
|
||||||
return CompAction, CompPPAction, ShCompAction, ShCompPPAction
|
|
||||||
|
|
||||||
def DialectAddToEnv(env, dialect, suffixes, ppsuffixes, support_module = 0):
|
|
||||||
"""Add dialect specific construction variables."""
|
|
||||||
ComputeFortranSuffixes(suffixes, ppsuffixes)
|
|
||||||
|
|
||||||
fscan = SCons.Scanner.Fortran.FortranScan("%sPATH" % dialect)
|
|
||||||
|
|
||||||
for suffix in suffixes + ppsuffixes:
|
|
||||||
SCons.Tool.SourceFileScanner.add_scanner(suffix, fscan)
|
|
||||||
|
|
||||||
env.AppendUnique(FORTRANSUFFIXES = suffixes + ppsuffixes)
|
|
||||||
|
|
||||||
compaction, compppaction, shcompaction, shcompppaction = \
|
|
||||||
CreateDialectActions(dialect)
|
|
||||||
|
|
||||||
static_obj, shared_obj = SCons.Tool.createObjBuilders(env)
|
|
||||||
|
|
||||||
for suffix in suffixes:
|
|
||||||
static_obj.add_action(suffix, compaction)
|
|
||||||
shared_obj.add_action(suffix, shcompaction)
|
|
||||||
static_obj.add_emitter(suffix, FortranEmitter)
|
|
||||||
shared_obj.add_emitter(suffix, ShFortranEmitter)
|
|
||||||
|
|
||||||
for suffix in ppsuffixes:
|
|
||||||
static_obj.add_action(suffix, compppaction)
|
|
||||||
shared_obj.add_action(suffix, shcompppaction)
|
|
||||||
static_obj.add_emitter(suffix, FortranEmitter)
|
|
||||||
shared_obj.add_emitter(suffix, ShFortranEmitter)
|
|
||||||
|
|
||||||
if not env.has_key('%sFLAGS' % dialect):
|
|
||||||
env['%sFLAGS' % dialect] = SCons.Util.CLVar('')
|
|
||||||
|
|
||||||
if not env.has_key('SH%sFLAGS' % dialect):
|
|
||||||
env['SH%sFLAGS' % dialect] = SCons.Util.CLVar('$%sFLAGS' % dialect)
|
|
||||||
|
|
||||||
# If a tool does not define fortran prefix/suffix for include path, use C ones
|
|
||||||
if not env.has_key('INC%sPREFIX' % dialect):
|
|
||||||
env['INC%sPREFIX' % dialect] = '$INCPREFIX'
|
|
||||||
|
|
||||||
if not env.has_key('INC%sSUFFIX' % dialect):
|
|
||||||
env['INC%sSUFFIX' % dialect] = '$INCSUFFIX'
|
|
||||||
|
|
||||||
env['_%sINCFLAGS' % dialect] = '$( ${_concat(INC%sPREFIX, %sPATH, INC%sSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)' % (dialect, dialect, dialect)
|
|
||||||
|
|
||||||
if support_module == 1:
|
|
||||||
env['%sCOM' % dialect] = '$%s -o $TARGET -c $%sFLAGS $_%sINCFLAGS $_FORTRANMODFLAG $SOURCES' % (dialect, dialect, dialect)
|
|
||||||
env['%sPPCOM' % dialect] = '$%s -o $TARGET -c $%sFLAGS $CPPFLAGS $_CPPDEFFLAGS $_%sINCFLAGS $_FORTRANMODFLAG $SOURCES' % (dialect, dialect, dialect)
|
|
||||||
env['SH%sCOM' % dialect] = '$SH%s -o $TARGET -c $SH%sFLAGS $_%sINCFLAGS $_FORTRANMODFLAG $SOURCES' % (dialect, dialect, dialect)
|
|
||||||
env['SH%sPPCOM' % dialect] = '$SH%s -o $TARGET -c $SH%sFLAGS $CPPFLAGS $_CPPDEFFLAGS $_%sINCFLAGS $_FORTRANMODFLAG $SOURCES' % (dialect, dialect, dialect)
|
|
||||||
else:
|
|
||||||
env['%sCOM' % dialect] = '$%s -o $TARGET -c $%sFLAGS $_%sINCFLAGS $SOURCES' % (dialect, dialect, dialect)
|
|
||||||
env['%sPPCOM' % dialect] = '$%s -o $TARGET -c $%sFLAGS $CPPFLAGS $_CPPDEFFLAGS $_%sINCFLAGS $SOURCES' % (dialect, dialect, dialect)
|
|
||||||
env['SH%sCOM' % dialect] = '$SH%s -o $TARGET -c $SH%sFLAGS $_%sINCFLAGS $SOURCES' % (dialect, dialect, dialect)
|
|
||||||
env['SH%sPPCOM' % dialect] = '$SH%s -o $TARGET -c $SH%sFLAGS $CPPFLAGS $_CPPDEFFLAGS $_%sINCFLAGS $SOURCES' % (dialect, dialect, dialect)
|
|
||||||
|
|
||||||
def add_fortran_to_env(env):
|
|
||||||
"""Add Builders and construction variables for Fortran to an Environment."""
|
|
||||||
try:
|
|
||||||
FortranSuffixes = env['FORTRANFILESUFFIXES']
|
|
||||||
except KeyError:
|
|
||||||
FortranSuffixes = ['.f', '.for', '.ftn']
|
|
||||||
|
|
||||||
#print "Adding %s to fortran suffixes" % FortranSuffixes
|
|
||||||
try:
|
|
||||||
FortranPPSuffixes = env['FORTRANPPFILESUFFIXES']
|
|
||||||
except KeyError:
|
|
||||||
FortranPPSuffixes = ['.fpp', '.FPP']
|
|
||||||
|
|
||||||
DialectAddToEnv(env, "FORTRAN", FortranSuffixes,
|
|
||||||
FortranPPSuffixes, support_module = 1)
|
|
||||||
|
|
||||||
env['FORTRANMODPREFIX'] = '' # like $LIBPREFIX
|
|
||||||
env['FORTRANMODSUFFIX'] = '.mod' # like $LIBSUFFIX
|
|
||||||
|
|
||||||
env['FORTRANMODDIR'] = '' # where the compiler should place .mod files
|
|
||||||
env['FORTRANMODDIRPREFIX'] = '' # some prefix to $FORTRANMODDIR - similar to $INCPREFIX
|
|
||||||
env['FORTRANMODDIRSUFFIX'] = '' # some suffix to $FORTRANMODDIR - similar to $INCSUFFIX
|
|
||||||
env['_FORTRANMODFLAG'] = '$( ${_concat(FORTRANMODDIRPREFIX, FORTRANMODDIR, FORTRANMODDIRSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)'
|
|
||||||
|
|
||||||
def add_f77_to_env(env):
|
|
||||||
"""Add Builders and construction variables for f77 to an Environment."""
|
|
||||||
try:
|
|
||||||
F77Suffixes = env['F77FILESUFFIXES']
|
|
||||||
except KeyError:
|
|
||||||
F77Suffixes = ['.f77']
|
|
||||||
|
|
||||||
#print "Adding %s to f77 suffixes" % F77Suffixes
|
|
||||||
try:
|
|
||||||
F77PPSuffixes = env['F77PPFILESUFFIXES']
|
|
||||||
except KeyError:
|
|
||||||
F77PPSuffixes = []
|
|
||||||
|
|
||||||
DialectAddToEnv(env, "F77", F77Suffixes, F77PPSuffixes)
|
|
||||||
|
|
||||||
def add_f90_to_env(env):
|
|
||||||
"""Add Builders and construction variables for f90 to an Environment."""
|
|
||||||
try:
|
|
||||||
F90Suffixes = env['F90FILESUFFIXES']
|
|
||||||
except KeyError:
|
|
||||||
F90Suffixes = ['.f90']
|
|
||||||
|
|
||||||
#print "Adding %s to f90 suffixes" % F90Suffixes
|
|
||||||
try:
|
|
||||||
F90PPSuffixes = env['F90PPFILESUFFIXES']
|
|
||||||
except KeyError:
|
|
||||||
F90PPSuffixes = []
|
|
||||||
|
|
||||||
DialectAddToEnv(env, "F90", F90Suffixes, F90PPSuffixes,
|
|
||||||
support_module = 1)
|
|
||||||
|
|
||||||
def add_f95_to_env(env):
|
|
||||||
"""Add Builders and construction variables for f95 to an Environment."""
|
|
||||||
try:
|
|
||||||
F95Suffixes = env['F95FILESUFFIXES']
|
|
||||||
except KeyError:
|
|
||||||
F95Suffixes = ['.f95']
|
|
||||||
|
|
||||||
#print "Adding %s to f95 suffixes" % F95Suffixes
|
|
||||||
try:
|
|
||||||
F95PPSuffixes = env['F95PPFILESUFFIXES']
|
|
||||||
except KeyError:
|
|
||||||
F95PPSuffixes = []
|
|
||||||
|
|
||||||
DialectAddToEnv(env, "F95", F95Suffixes, F95PPSuffixes,
|
|
||||||
support_module = 1)
|
|
||||||
|
|
||||||
def add_all_to_env(env):
|
|
||||||
"""Add builders and construction variables for all supported fortran
|
|
||||||
dialects."""
|
|
||||||
add_fortran_to_env(env)
|
|
||||||
add_f77_to_env(env)
|
|
||||||
add_f90_to_env(env)
|
|
||||||
add_f95_to_env(env)
|
|
|
@ -1,317 +0,0 @@
|
||||||
"""SCons.Tool.JavaCommon
|
|
||||||
|
|
||||||
Stuff for processing Java.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Tool/JavaCommon.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import os
|
|
||||||
import os.path
|
|
||||||
import re
|
|
||||||
import string
|
|
||||||
|
|
||||||
java_parsing = 1
|
|
||||||
|
|
||||||
default_java_version = '1.4'
|
|
||||||
|
|
||||||
if java_parsing:
|
|
||||||
# Parse Java files for class names.
|
|
||||||
#
|
|
||||||
# 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;
|
|
||||||
# double-backslashes;
|
|
||||||
# a single-line comment "//";
|
|
||||||
# single or double quotes preceeded by a backslash;
|
|
||||||
# single quotes, double quotes, open or close braces, semi-colons,
|
|
||||||
# periods, open or close parentheses;
|
|
||||||
# floating-point numbers;
|
|
||||||
# any alphanumeric token (keyword, class name, specifier);
|
|
||||||
# any alphanumeric token surrounded by angle brackets (generics);
|
|
||||||
# the multi-line comment begin and end tokens /* and */;
|
|
||||||
# array declarations "[]".
|
|
||||||
_reToken = re.compile(r'(\n|\\\\|//|\\[\'"]|[\'"\{\}\;\.\(\)]|' +
|
|
||||||
r'\d*\.\d*|[A-Za-z_][\w\$\.]*|<[A-Za-z_]\w+>|' +
|
|
||||||
r'/\*|\*/|\[\])')
|
|
||||||
|
|
||||||
class OuterState:
|
|
||||||
"""The initial state for parsing a Java file for classes,
|
|
||||||
interfaces, and anonymous inner classes."""
|
|
||||||
def __init__(self, version=default_java_version):
|
|
||||||
|
|
||||||
if not version in ('1.1', '1.2', '1.3','1.4', '1.5', '1.6'):
|
|
||||||
msg = "Java version %s not supported" % version
|
|
||||||
raise NotImplementedError, msg
|
|
||||||
|
|
||||||
self.version = version
|
|
||||||
self.listClasses = []
|
|
||||||
self.listOutputs = []
|
|
||||||
self.stackBrackets = []
|
|
||||||
self.brackets = 0
|
|
||||||
self.nextAnon = 1
|
|
||||||
self.localClasses = []
|
|
||||||
self.stackAnonClassBrackets = []
|
|
||||||
self.anonStacksStack = [[0]]
|
|
||||||
self.package = None
|
|
||||||
|
|
||||||
def trace(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def __getClassState(self):
|
|
||||||
try:
|
|
||||||
return self.classState
|
|
||||||
except AttributeError:
|
|
||||||
ret = ClassState(self)
|
|
||||||
self.classState = ret
|
|
||||||
return ret
|
|
||||||
|
|
||||||
def __getPackageState(self):
|
|
||||||
try:
|
|
||||||
return self.packageState
|
|
||||||
except AttributeError:
|
|
||||||
ret = PackageState(self)
|
|
||||||
self.packageState = ret
|
|
||||||
return ret
|
|
||||||
|
|
||||||
def __getAnonClassState(self):
|
|
||||||
try:
|
|
||||||
return self.anonState
|
|
||||||
except AttributeError:
|
|
||||||
self.outer_state = self
|
|
||||||
ret = SkipState(1, AnonClassState(self))
|
|
||||||
self.anonState = ret
|
|
||||||
return ret
|
|
||||||
|
|
||||||
def __getSkipState(self):
|
|
||||||
try:
|
|
||||||
return self.skipState
|
|
||||||
except AttributeError:
|
|
||||||
ret = SkipState(1, self)
|
|
||||||
self.skipState = ret
|
|
||||||
return ret
|
|
||||||
|
|
||||||
def __getAnonStack(self):
|
|
||||||
return self.anonStacksStack[-1]
|
|
||||||
|
|
||||||
def openBracket(self):
|
|
||||||
self.brackets = self.brackets + 1
|
|
||||||
|
|
||||||
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.localClasses.pop()
|
|
||||||
self.listClasses.pop()
|
|
||||||
self.anonStacksStack.pop()
|
|
||||||
self.stackBrackets.pop()
|
|
||||||
if len(self.stackAnonClassBrackets) and \
|
|
||||||
self.brackets == self.stackAnonClassBrackets[-1]:
|
|
||||||
self.__getAnonStack().pop()
|
|
||||||
self.stackAnonClassBrackets.pop()
|
|
||||||
|
|
||||||
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 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"""
|
|
||||||
if self.version in ('1.1', '1.2', '1.3', '1.4'):
|
|
||||||
clazz = self.listClasses[0]
|
|
||||||
self.listOutputs.append('%s$%d' % (clazz, self.nextAnon))
|
|
||||||
elif self.version in ('1.5', '1.6'):
|
|
||||||
self.stackAnonClassBrackets.append(self.brackets)
|
|
||||||
className = []
|
|
||||||
className.extend(self.listClasses)
|
|
||||||
self.__getAnonStack()[-1] = self.__getAnonStack()[-1] + 1
|
|
||||||
for anon in self.__getAnonStack():
|
|
||||||
className.append(str(anon))
|
|
||||||
self.listOutputs.append(string.join(className, '$'))
|
|
||||||
|
|
||||||
self.nextAnon = self.nextAnon + 1
|
|
||||||
self.__getAnonStack().append(0)
|
|
||||||
|
|
||||||
def setPackage(self, package):
|
|
||||||
self.package = package
|
|
||||||
|
|
||||||
class AnonClassState:
|
|
||||||
"""A state that looks for anonymous inner classes."""
|
|
||||||
def __init__(self, old_state):
|
|
||||||
# outer_state is always an instance of OuterState
|
|
||||||
self.outer_state = old_state.outer_state
|
|
||||||
self.old_state = old_state
|
|
||||||
self.brace_level = 0
|
|
||||||
def parseToken(self, token):
|
|
||||||
# This is an anonymous class if and only if the next
|
|
||||||
# non-whitespace token is a bracket. Everything between
|
|
||||||
# braces should be parsed as normal java code.
|
|
||||||
if token[:2] == '//':
|
|
||||||
return IgnoreState('\n', self)
|
|
||||||
elif token == '/*':
|
|
||||||
return IgnoreState('*/', self)
|
|
||||||
elif token == '\n':
|
|
||||||
return self
|
|
||||||
elif token[0] == '<' and token[-1] == '>':
|
|
||||||
return self
|
|
||||||
elif token == '(':
|
|
||||||
self.brace_level = self.brace_level + 1
|
|
||||||
return self
|
|
||||||
if self.brace_level > 0:
|
|
||||||
if token == 'new':
|
|
||||||
# look further for anonymous inner class
|
|
||||||
return SkipState(1, AnonClassState(self))
|
|
||||||
elif token in [ '"', "'" ]:
|
|
||||||
return IgnoreState(token, self)
|
|
||||||
elif token == ')':
|
|
||||||
self.brace_level = self.brace_level - 1
|
|
||||||
return self
|
|
||||||
if token == '{':
|
|
||||||
self.outer_state.addAnonClass()
|
|
||||||
return self.old_state.parseToken(token)
|
|
||||||
|
|
||||||
class SkipState:
|
|
||||||
"""A state that will skip a specified number of tokens before
|
|
||||||
reverting to the previous state."""
|
|
||||||
def __init__(self, tokens_to_skip, old_state):
|
|
||||||
self.tokens_to_skip = tokens_to_skip
|
|
||||||
self.old_state = old_state
|
|
||||||
def parseToken(self, token):
|
|
||||||
self.tokens_to_skip = self.tokens_to_skip - 1
|
|
||||||
if self.tokens_to_skip < 1:
|
|
||||||
return self.old_state
|
|
||||||
return self
|
|
||||||
|
|
||||||
class ClassState:
|
|
||||||
"""A state we go into when we hit a class or interface keyword."""
|
|
||||||
def __init__(self, outer_state):
|
|
||||||
# outer_state is always an instance of OuterState
|
|
||||||
self.outer_state = outer_state
|
|
||||||
def parseToken(self, token):
|
|
||||||
# the next non-whitespace token should be the name of the class
|
|
||||||
if token == '\n':
|
|
||||||
return self
|
|
||||||
# If that's an inner class which is declared in a method, it
|
|
||||||
# requires an index prepended to the class-name, e.g.
|
|
||||||
# 'Foo$1Inner' (Tigris Issue 2087)
|
|
||||||
if self.outer_state.localClasses and \
|
|
||||||
self.outer_state.stackBrackets[-1] > \
|
|
||||||
self.outer_state.stackBrackets[-2]+1:
|
|
||||||
locals = self.outer_state.localClasses[-1]
|
|
||||||
try:
|
|
||||||
idx = locals[token]
|
|
||||||
locals[token] = locals[token]+1
|
|
||||||
except KeyError:
|
|
||||||
locals[token] = 1
|
|
||||||
token = str(locals[token]) + token
|
|
||||||
self.outer_state.localClasses.append({})
|
|
||||||
self.outer_state.listClasses.append(token)
|
|
||||||
self.outer_state.anonStacksStack.append([0])
|
|
||||||
return self.outer_state
|
|
||||||
|
|
||||||
class IgnoreState:
|
|
||||||
"""A state that will ignore all tokens until it gets to a
|
|
||||||
specified token."""
|
|
||||||
def __init__(self, ignore_until, old_state):
|
|
||||||
self.ignore_until = ignore_until
|
|
||||||
self.old_state = old_state
|
|
||||||
def parseToken(self, token):
|
|
||||||
if self.ignore_until == token:
|
|
||||||
return self.old_state
|
|
||||||
return self
|
|
||||||
|
|
||||||
class PackageState:
|
|
||||||
"""The state we enter when we encounter the package keyword.
|
|
||||||
We assume the next token will be the package name."""
|
|
||||||
def __init__(self, outer_state):
|
|
||||||
# outer_state is always an instance of OuterState
|
|
||||||
self.outer_state = outer_state
|
|
||||||
def parseToken(self, token):
|
|
||||||
self.outer_state.setPackage(token)
|
|
||||||
return self.outer_state
|
|
||||||
|
|
||||||
def parse_java_file(fn, version=default_java_version):
|
|
||||||
return parse_java(open(fn, 'r').read(), version)
|
|
||||||
|
|
||||||
def parse_java(contents, version=default_java_version, 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"""
|
|
||||||
package = None
|
|
||||||
initial = OuterState(version)
|
|
||||||
currstate = initial
|
|
||||||
for token in _reToken.findall(contents):
|
|
||||||
# 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)
|
|
||||||
|
|
||||||
else:
|
|
||||||
# Don't actually parse Java files for class names.
|
|
||||||
#
|
|
||||||
# We might make this a configurable option in the future if
|
|
||||||
# Java-file parsing takes too long (although it shouldn't relative
|
|
||||||
# to how long the Java compiler itself seems to take...).
|
|
||||||
|
|
||||||
def parse_java_file(fn):
|
|
||||||
""" "Parse" a .java file.
|
|
||||||
|
|
||||||
This actually just splits the file name, so the assumption here
|
|
||||||
is that the file name matches the public class name, and that
|
|
||||||
the path to the file is the same as the package name.
|
|
||||||
"""
|
|
||||||
return os.path.split(file)
|
|
|
@ -1,98 +0,0 @@
|
||||||
"""SCons.Tool.Perforce.py
|
|
||||||
|
|
||||||
Tool-specific initialization for Perforce Source Code Management system.
|
|
||||||
|
|
||||||
There normally shouldn't be any need to import this module directly.
|
|
||||||
It will usually be imported through the generic SCons.Tool.Tool()
|
|
||||||
selection method.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Tool/Perforce.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import os
|
|
||||||
|
|
||||||
import SCons.Action
|
|
||||||
import SCons.Builder
|
|
||||||
import SCons.Node.FS
|
|
||||||
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 = PerforceAction, env = env)
|
|
||||||
|
|
||||||
#setattr(env, 'Perforce', PerforceFactory)
|
|
||||||
env.Perforce = PerforceFactory
|
|
||||||
|
|
||||||
env['P4'] = 'p4'
|
|
||||||
env['P4FLAGS'] = SCons.Util.CLVar('')
|
|
||||||
env['P4COM'] = '$P4 $P4FLAGS sync $TARGET'
|
|
||||||
try:
|
|
||||||
environ = env['ENV']
|
|
||||||
except KeyError:
|
|
||||||
environ = {}
|
|
||||||
env['ENV'] = environ
|
|
||||||
|
|
||||||
# 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' Windows's tilde-mangling for long file names.
|
|
||||||
environ['PWD'] = env.Dir('#').get_abspath()
|
|
||||||
|
|
||||||
for var in _import_env:
|
|
||||||
v = os.environ.get(var)
|
|
||||||
if v:
|
|
||||||
environ[var] = v
|
|
||||||
|
|
||||||
if SCons.Util.can_read_reg:
|
|
||||||
# If we can read the registry, add the path to Perforce to our environment.
|
|
||||||
try:
|
|
||||||
k=SCons.Util.RegOpenKeyEx(SCons.Util.hkey_mod.HKEY_LOCAL_MACHINE,
|
|
||||||
'Software\\Perforce\\environment')
|
|
||||||
val, tok = SCons.Util.RegQueryValueEx(k, 'P4INSTROOT')
|
|
||||||
addPathIfNotExists(environ, 'PATH', val)
|
|
||||||
except SCons.Util.RegError:
|
|
||||||
# Can't detect where Perforce is, hope the user has it set in the
|
|
||||||
# PATH.
|
|
||||||
pass
|
|
||||||
|
|
||||||
def exists(env):
|
|
||||||
return env.Detect('p4')
|
|
|
@ -1,132 +0,0 @@
|
||||||
"""SCons.Tool.PharLapCommon
|
|
||||||
|
|
||||||
This module contains common code used by all Tools for the
|
|
||||||
Phar Lap ETS tool chain. Right now, this is linkloc and
|
|
||||||
386asm.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Tool/PharLapCommon.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import os
|
|
||||||
import os.path
|
|
||||||
import SCons.Errors
|
|
||||||
import SCons.Util
|
|
||||||
import re
|
|
||||||
import string
|
|
||||||
|
|
||||||
def getPharLapPath():
|
|
||||||
"""Reads the registry to find the installed path of the Phar Lap ETS
|
|
||||||
development kit.
|
|
||||||
|
|
||||||
Raises UserError if no installed version of Phar Lap can
|
|
||||||
be found."""
|
|
||||||
|
|
||||||
if not SCons.Util.can_read_reg:
|
|
||||||
raise SCons.Errors.InternalError, "No Windows registry module was found"
|
|
||||||
try:
|
|
||||||
k=SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE,
|
|
||||||
'SOFTWARE\\Pharlap\\ETS')
|
|
||||||
val, type = SCons.Util.RegQueryValueEx(k, 'BaseDir')
|
|
||||||
|
|
||||||
# The following is a hack...there is (not surprisingly)
|
|
||||||
# an odd issue in the Phar Lap plug in that inserts
|
|
||||||
# a bunch of junk data after the phar lap path in the
|
|
||||||
# registry. We must trim it.
|
|
||||||
idx=val.find('\0')
|
|
||||||
if idx >= 0:
|
|
||||||
val = val[:idx]
|
|
||||||
|
|
||||||
return os.path.normpath(val)
|
|
||||||
except SCons.Util.RegError:
|
|
||||||
raise SCons.Errors.UserError, "Cannot find Phar Lap ETS path in the registry. Is it installed properly?"
|
|
||||||
|
|
||||||
REGEX_ETS_VER = re.compile(r'#define\s+ETS_VER\s+([0-9]+)')
|
|
||||||
|
|
||||||
def getPharLapVersion():
|
|
||||||
"""Returns the version of the installed ETS Tool Suite as a
|
|
||||||
decimal number. This version comes from the ETS_VER #define in
|
|
||||||
the embkern.h header. For example, '#define ETS_VER 1010' (which
|
|
||||||
is what Phar Lap 10.1 defines) would cause this method to return
|
|
||||||
1010. Phar Lap 9.1 does not have such a #define, but this method
|
|
||||||
will return 910 as a default.
|
|
||||||
|
|
||||||
Raises UserError if no installed version of Phar Lap can
|
|
||||||
be found."""
|
|
||||||
|
|
||||||
include_path = os.path.join(getPharLapPath(), os.path.normpath("include/embkern.h"))
|
|
||||||
if not os.path.exists(include_path):
|
|
||||||
raise SCons.Errors.UserError, "Cannot find embkern.h in ETS include directory.\nIs Phar Lap ETS installed properly?"
|
|
||||||
mo = REGEX_ETS_VER.search(open(include_path, 'r').read())
|
|
||||||
if mo:
|
|
||||||
return int(mo.group(1))
|
|
||||||
# Default return for Phar Lap 9.1
|
|
||||||
return 910
|
|
||||||
|
|
||||||
def addPathIfNotExists(env_dict, key, path, sep=os.pathsep):
|
|
||||||
"""This function will take 'key' out of the dictionary
|
|
||||||
'env_dict', then add the path 'path' to that key if it is not
|
|
||||||
already there. This treats the value of env_dict[key] as if it
|
|
||||||
has a similar format to the PATH variable...a list of paths
|
|
||||||
separated by tokens. The 'path' will get added to the list if it
|
|
||||||
is not already there."""
|
|
||||||
try:
|
|
||||||
is_list = 1
|
|
||||||
paths = env_dict[key]
|
|
||||||
if not SCons.Util.is_List(env_dict[key]):
|
|
||||||
paths = string.split(paths, sep)
|
|
||||||
is_list = 0
|
|
||||||
if not os.path.normcase(path) in map(os.path.normcase, paths):
|
|
||||||
paths = [ path ] + paths
|
|
||||||
if is_list:
|
|
||||||
env_dict[key] = paths
|
|
||||||
else:
|
|
||||||
env_dict[key] = string.join(paths, sep)
|
|
||||||
except KeyError:
|
|
||||||
env_dict[key] = path
|
|
||||||
|
|
||||||
def addPharLapPaths(env):
|
|
||||||
"""This function adds the path to the Phar Lap binaries, includes,
|
|
||||||
and libraries, if they are not already there."""
|
|
||||||
ph_path = getPharLapPath()
|
|
||||||
|
|
||||||
try:
|
|
||||||
env_dict = env['ENV']
|
|
||||||
except KeyError:
|
|
||||||
env_dict = {}
|
|
||||||
env['ENV'] = env_dict
|
|
||||||
addPathIfNotExists(env_dict, 'PATH',
|
|
||||||
os.path.join(ph_path, 'bin'))
|
|
||||||
addPathIfNotExists(env_dict, 'INCLUDE',
|
|
||||||
os.path.join(ph_path, 'include'))
|
|
||||||
addPathIfNotExists(env_dict, 'LIB',
|
|
||||||
os.path.join(ph_path, 'lib'))
|
|
||||||
addPathIfNotExists(env_dict, 'LIB',
|
|
||||||
os.path.join(ph_path, os.path.normpath('lib/vclib')))
|
|
||||||
|
|
||||||
env['PHARLAP_PATH'] = getPharLapPath()
|
|
||||||
env['PHARLAP_VERSION'] = str(getPharLapVersion())
|
|
||||||
|
|
|
@ -1,58 +0,0 @@
|
||||||
"""SCons.Tool.RCS.py
|
|
||||||
|
|
||||||
Tool-specific initialization for RCS.
|
|
||||||
|
|
||||||
There normally shouldn't be any need to import this module directly.
|
|
||||||
It will usually be imported through the generic SCons.Tool.Tool()
|
|
||||||
selection method.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Tool/RCS.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import SCons.Action
|
|
||||||
import SCons.Builder
|
|
||||||
import SCons.Util
|
|
||||||
|
|
||||||
def generate(env):
|
|
||||||
"""Add a Builder factory function and construction variables for
|
|
||||||
RCS to an Environment."""
|
|
||||||
|
|
||||||
def RCSFactory(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
|
|
||||||
|
|
||||||
env['RCS'] = 'rcs'
|
|
||||||
env['RCS_CO'] = 'co'
|
|
||||||
env['RCS_COFLAGS'] = SCons.Util.CLVar('')
|
|
||||||
env['RCS_COCOM'] = '$RCS_CO $RCS_COFLAGS $TARGET'
|
|
||||||
|
|
||||||
def exists(env):
|
|
||||||
return env.Detect('rcs')
|
|
|
@ -1,58 +0,0 @@
|
||||||
"""SCons.Tool.SCCS.py
|
|
||||||
|
|
||||||
Tool-specific initialization for SCCS.
|
|
||||||
|
|
||||||
There normally shouldn't be any need to import this module directly.
|
|
||||||
It will usually be imported through the generic SCons.Tool.Tool()
|
|
||||||
selection method.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Tool/SCCS.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import SCons.Action
|
|
||||||
import SCons.Builder
|
|
||||||
import SCons.Util
|
|
||||||
|
|
||||||
def generate(env):
|
|
||||||
"""Add a Builder factory function and construction variables for
|
|
||||||
SCCS to an Environment."""
|
|
||||||
|
|
||||||
def SCCSFactory(env=env):
|
|
||||||
""" """
|
|
||||||
act = SCons.Action.Action('$SCCSCOM', '$SCCSCOMSTR')
|
|
||||||
return SCons.Builder.Builder(action = act, env = env)
|
|
||||||
|
|
||||||
#setattr(env, 'SCCS', SCCSFactory)
|
|
||||||
env.SCCS = SCCSFactory
|
|
||||||
|
|
||||||
env['SCCS'] = 'sccs'
|
|
||||||
env['SCCSFLAGS'] = SCons.Util.CLVar('')
|
|
||||||
env['SCCSGETFLAGS'] = SCons.Util.CLVar('')
|
|
||||||
env['SCCSCOM'] = '$SCCS $SCCSFLAGS get $SCCSGETFLAGS $TARGET'
|
|
||||||
|
|
||||||
def exists(env):
|
|
||||||
return env.Detect('sccs')
|
|
|
@ -1,65 +0,0 @@
|
||||||
"""SCons.Tool.Subversion.py
|
|
||||||
|
|
||||||
Tool-specific initialization for Subversion.
|
|
||||||
|
|
||||||
There normally shouldn't be any need to import this module directly.
|
|
||||||
It will usually be imported through the generic SCons.Tool.Tool()
|
|
||||||
selection method.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Tool/Subversion.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import os.path
|
|
||||||
|
|
||||||
import SCons.Action
|
|
||||||
import SCons.Builder
|
|
||||||
import SCons.Util
|
|
||||||
|
|
||||||
def generate(env):
|
|
||||||
"""Add a Builder factory function and construction variables for
|
|
||||||
Subversion to an Environment."""
|
|
||||||
|
|
||||||
def SubversionFactory(repos, module='', env=env):
|
|
||||||
""" """
|
|
||||||
# fail if repos is not an absolute path name?
|
|
||||||
if module != '':
|
|
||||||
module = os.path.join(module, '')
|
|
||||||
act = SCons.Action.Action('$SVNCOM', '$SVNCOMSTR')
|
|
||||||
return SCons.Builder.Builder(action = act,
|
|
||||||
env = env,
|
|
||||||
SVNREPOSITORY = repos,
|
|
||||||
SVNMODULE = module)
|
|
||||||
|
|
||||||
#setattr(env, 'Subversion', SubversionFactory)
|
|
||||||
env.Subversion = SubversionFactory
|
|
||||||
|
|
||||||
env['SVN'] = 'svn'
|
|
||||||
env['SVNFLAGS'] = SCons.Util.CLVar('')
|
|
||||||
env['SVNCOM'] = '$SVN $SVNFLAGS cat $SVNREPOSITORY/$SVNMODULE$TARGET > $TARGET'
|
|
||||||
|
|
||||||
def exists(env):
|
|
||||||
return env.Detect('svn')
|
|
|
@ -1,667 +0,0 @@
|
||||||
"""SCons.Tool
|
|
||||||
|
|
||||||
SCons tool selection.
|
|
||||||
|
|
||||||
This looks for modules that define a callable object that can modify
|
|
||||||
a construction environment as appropriate for a given tool (or tool
|
|
||||||
chain).
|
|
||||||
|
|
||||||
Note that because this subsystem just *selects* a callable that can
|
|
||||||
modify a construction environment, it's possible for people to define
|
|
||||||
their own "tool specification" in an arbitrary callable function. No
|
|
||||||
one needs to use or tie in to this subsystem in order to roll their own
|
|
||||||
tool definition.
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Tool/__init__.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import imp
|
|
||||||
import sys
|
|
||||||
|
|
||||||
import SCons.Builder
|
|
||||||
import SCons.Errors
|
|
||||||
import SCons.Node.FS
|
|
||||||
import SCons.Scanner
|
|
||||||
import SCons.Scanner.C
|
|
||||||
import SCons.Scanner.D
|
|
||||||
import SCons.Scanner.LaTeX
|
|
||||||
import SCons.Scanner.Prog
|
|
||||||
|
|
||||||
DefaultToolpath=[]
|
|
||||||
|
|
||||||
CScanner = SCons.Scanner.C.CScanner()
|
|
||||||
DScanner = SCons.Scanner.D.DScanner()
|
|
||||||
LaTeXScanner = SCons.Scanner.LaTeX.LaTeXScanner()
|
|
||||||
PDFLaTeXScanner = SCons.Scanner.LaTeX.PDFLaTeXScanner()
|
|
||||||
ProgramScanner = SCons.Scanner.Prog.ProgramScanner()
|
|
||||||
SourceFileScanner = SCons.Scanner.Base({}, name='SourceFileScanner')
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
# FIXME: what should be done here? Two scanners scan the same extensions,
|
|
||||||
# but look for different files, e.g., "picture.eps" vs. "picture.pdf".
|
|
||||||
# The builders for DVI and PDF explicitly reference their scanners
|
|
||||||
# I think that means this is not needed???
|
|
||||||
for suffix in LaTeXSuffixes:
|
|
||||||
SourceFileScanner.add_scanner(suffix, LaTeXScanner)
|
|
||||||
SourceFileScanner.add_scanner(suffix, PDFLaTeXScanner)
|
|
||||||
|
|
||||||
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
|
|
||||||
if hasattr(module, 'options'):
|
|
||||||
self.options = module.options
|
|
||||||
|
|
||||||
def _tool_module(self):
|
|
||||||
# TODO: Interchange zipimport with normal initilization for better error reporting
|
|
||||||
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:
|
|
||||||
if str(e)!="No module named %s"%self.name:
|
|
||||||
raise SCons.Errors.EnvironmentError, 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:
|
|
||||||
if str(e)!="No module named %s"%self.name:
|
|
||||||
raise SCons.Errors.EnvironmentError, 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.EnvironmentError, m
|
|
||||||
except ImportError, e:
|
|
||||||
m = "No tool named '%s': %s" % (self.name, e)
|
|
||||||
raise SCons.Errors.EnvironmentError, 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 ])
|
|
||||||
if hasattr(self, 'options'):
|
|
||||||
import SCons.Variables
|
|
||||||
if not env.has_key('options'):
|
|
||||||
from SCons.Script import ARGUMENTS
|
|
||||||
env['options']=SCons.Variables.Variables(args=ARGUMENTS)
|
|
||||||
opts=env['options']
|
|
||||||
|
|
||||||
self.options(opts)
|
|
||||||
opts.Update(env)
|
|
||||||
|
|
||||||
apply(self.generate, ( env, ) + args, kw)
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return self.name
|
|
||||||
|
|
||||||
##########################################################################
|
|
||||||
# Create common executable program / library / object builders
|
|
||||||
|
|
||||||
def createProgBuilder(env):
|
|
||||||
"""This is a utility function that creates the Program
|
|
||||||
Builder in an Environment if it is not there already.
|
|
||||||
|
|
||||||
If it is already there, we return the existing one.
|
|
||||||
"""
|
|
||||||
|
|
||||||
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 = ProgramScanner)
|
|
||||||
env['BUILDERS']['Program'] = program
|
|
||||||
|
|
||||||
return program
|
|
||||||
|
|
||||||
def createStaticLibBuilder(env):
|
|
||||||
"""This is a utility function that creates the StaticLibrary
|
|
||||||
Builder in an Environment if it is not there already.
|
|
||||||
|
|
||||||
If it is already there, we return the existing one.
|
|
||||||
"""
|
|
||||||
|
|
||||||
try:
|
|
||||||
static_lib = env['BUILDERS']['StaticLibrary']
|
|
||||||
except KeyError:
|
|
||||||
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',
|
|
||||||
src_suffix = '$OBJSUFFIX',
|
|
||||||
src_builder = 'StaticObject')
|
|
||||||
env['BUILDERS']['StaticLibrary'] = static_lib
|
|
||||||
env['BUILDERS']['Library'] = static_lib
|
|
||||||
|
|
||||||
return static_lib
|
|
||||||
|
|
||||||
def createSharedLibBuilder(env):
|
|
||||||
"""This is a utility function that creates the SharedLibrary
|
|
||||||
Builder in an Environment if it is not there already.
|
|
||||||
|
|
||||||
If it is already there, we return the existing one.
|
|
||||||
"""
|
|
||||||
|
|
||||||
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 = 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
|
|
||||||
are not there already.
|
|
||||||
|
|
||||||
If they are there already, we return the existing ones.
|
|
||||||
|
|
||||||
This is a separate function because soooo many Tools
|
|
||||||
use this functionality.
|
|
||||||
|
|
||||||
The return is a 2-tuple of (StaticObject, SharedObject)
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
try:
|
|
||||||
static_obj = env['BUILDERS']['StaticObject']
|
|
||||||
except KeyError:
|
|
||||||
static_obj = SCons.Builder.Builder(action = {},
|
|
||||||
emitter = {},
|
|
||||||
prefix = '$OBJPREFIX',
|
|
||||||
suffix = '$OBJSUFFIX',
|
|
||||||
src_builder = ['CFile', 'CXXFile'],
|
|
||||||
source_scanner = SourceFileScanner,
|
|
||||||
single_source = 1)
|
|
||||||
env['BUILDERS']['StaticObject'] = static_obj
|
|
||||||
env['BUILDERS']['Object'] = static_obj
|
|
||||||
|
|
||||||
try:
|
|
||||||
shared_obj = env['BUILDERS']['SharedObject']
|
|
||||||
except KeyError:
|
|
||||||
shared_obj = SCons.Builder.Builder(action = {},
|
|
||||||
emitter = {},
|
|
||||||
prefix = '$SHOBJPREFIX',
|
|
||||||
suffix = '$SHOBJSUFFIX',
|
|
||||||
src_builder = ['CFile', 'CXXFile'],
|
|
||||||
source_scanner = SourceFileScanner,
|
|
||||||
single_source = 1)
|
|
||||||
env['BUILDERS']['SharedObject'] = shared_obj
|
|
||||||
|
|
||||||
return (static_obj, shared_obj)
|
|
||||||
|
|
||||||
def createCFileBuilders(env):
|
|
||||||
"""This is a utility function that creates the CFile/CXXFile
|
|
||||||
Builders in an Environment if they
|
|
||||||
are not there already.
|
|
||||||
|
|
||||||
If they are there already, we return the existing ones.
|
|
||||||
|
|
||||||
This is a separate function because soooo many Tools
|
|
||||||
use this functionality.
|
|
||||||
|
|
||||||
The return is a 2-tuple of (CFile, CXXFile)
|
|
||||||
"""
|
|
||||||
|
|
||||||
try:
|
|
||||||
c_file = env['BUILDERS']['CFile']
|
|
||||||
except KeyError:
|
|
||||||
c_file = SCons.Builder.Builder(action = {},
|
|
||||||
emitter = {},
|
|
||||||
suffix = {None:'$CFILESUFFIX'})
|
|
||||||
env['BUILDERS']['CFile'] = c_file
|
|
||||||
|
|
||||||
env.SetDefault(CFILESUFFIX = '.c')
|
|
||||||
|
|
||||||
try:
|
|
||||||
cxx_file = env['BUILDERS']['CXXFile']
|
|
||||||
except KeyError:
|
|
||||||
cxx_file = SCons.Builder.Builder(action = {},
|
|
||||||
emitter = {},
|
|
||||||
suffix = {None:'$CXXFILESUFFIX'})
|
|
||||||
env['BUILDERS']['CXXFile'] = cxx_file
|
|
||||||
env.SetDefault(CXXFILESUFFIX = '.cc')
|
|
||||||
|
|
||||||
return (c_file, cxx_file)
|
|
||||||
|
|
||||||
##########################################################################
|
|
||||||
# Create common Java builders
|
|
||||||
|
|
||||||
def CreateJarBuilder(env):
|
|
||||||
try:
|
|
||||||
java_jar = env['BUILDERS']['Jar']
|
|
||||||
except KeyError:
|
|
||||||
fs = SCons.Node.FS.get_default_fs()
|
|
||||||
jar_com = SCons.Action.Action('$JARCOM', '$JARCOMSTR')
|
|
||||||
java_jar = SCons.Builder.Builder(action = jar_com,
|
|
||||||
suffix = '$JARSUFFIX',
|
|
||||||
src_suffix = '$JAVACLASSSUFIX',
|
|
||||||
src_builder = 'JavaClassFile',
|
|
||||||
source_factory = fs.Entry)
|
|
||||||
env['BUILDERS']['Jar'] = java_jar
|
|
||||||
return java_jar
|
|
||||||
|
|
||||||
def CreateJavaHBuilder(env):
|
|
||||||
try:
|
|
||||||
java_javah = env['BUILDERS']['JavaH']
|
|
||||||
except KeyError:
|
|
||||||
fs = SCons.Node.FS.get_default_fs()
|
|
||||||
java_javah_com = SCons.Action.Action('$JAVAHCOM', '$JAVAHCOMSTR')
|
|
||||||
java_javah = SCons.Builder.Builder(action = java_javah_com,
|
|
||||||
src_suffix = '$JAVACLASSSUFFIX',
|
|
||||||
target_factory = fs.Entry,
|
|
||||||
source_factory = fs.File,
|
|
||||||
src_builder = 'JavaClassFile')
|
|
||||||
env['BUILDERS']['JavaH'] = java_javah
|
|
||||||
return java_javah
|
|
||||||
|
|
||||||
def CreateJavaClassFileBuilder(env):
|
|
||||||
try:
|
|
||||||
java_class_file = env['BUILDERS']['JavaClassFile']
|
|
||||||
except KeyError:
|
|
||||||
fs = SCons.Node.FS.get_default_fs()
|
|
||||||
javac_com = SCons.Action.Action('$JAVACCOM', '$JAVACCOMSTR')
|
|
||||||
java_class_file = SCons.Builder.Builder(action = javac_com,
|
|
||||||
emitter = {},
|
|
||||||
#suffix = '$JAVACLASSSUFFIX',
|
|
||||||
src_suffix = '$JAVASUFFIX',
|
|
||||||
src_builder = ['JavaFile'],
|
|
||||||
target_factory = fs.Entry,
|
|
||||||
source_factory = fs.File)
|
|
||||||
env['BUILDERS']['JavaClassFile'] = java_class_file
|
|
||||||
return java_class_file
|
|
||||||
|
|
||||||
def CreateJavaClassDirBuilder(env):
|
|
||||||
try:
|
|
||||||
java_class_dir = env['BUILDERS']['JavaClassDir']
|
|
||||||
except KeyError:
|
|
||||||
fs = SCons.Node.FS.get_default_fs()
|
|
||||||
javac_com = SCons.Action.Action('$JAVACCOM', '$JAVACCOMSTR')
|
|
||||||
java_class_dir = SCons.Builder.Builder(action = javac_com,
|
|
||||||
emitter = {},
|
|
||||||
target_factory = fs.Dir,
|
|
||||||
source_factory = fs.Dir)
|
|
||||||
env['BUILDERS']['JavaClassDir'] = java_class_dir
|
|
||||||
return java_class_dir
|
|
||||||
|
|
||||||
def CreateJavaFileBuilder(env):
|
|
||||||
try:
|
|
||||||
java_file = env['BUILDERS']['JavaFile']
|
|
||||||
except KeyError:
|
|
||||||
java_file = SCons.Builder.Builder(action = {},
|
|
||||||
emitter = {},
|
|
||||||
suffix = {None:'$JAVASUFFIX'})
|
|
||||||
env['BUILDERS']['JavaFile'] = java_file
|
|
||||||
env['JAVASUFFIX'] = '.java'
|
|
||||||
return java_file
|
|
||||||
|
|
||||||
class ToolInitializerMethod:
|
|
||||||
"""
|
|
||||||
This is added to a construction environment in place of a
|
|
||||||
method(s) normally called for a Builder (env.Object, env.StaticObject,
|
|
||||||
etc.). When called, it has its associated ToolInitializer
|
|
||||||
object search the specified list of tools and apply the first
|
|
||||||
one that exists to the construction environment. It then calls
|
|
||||||
whatever builder was (presumably) added to the construction
|
|
||||||
environment in place of this particular instance.
|
|
||||||
"""
|
|
||||||
def __init__(self, name, initializer):
|
|
||||||
"""
|
|
||||||
Note: we store the tool name as __name__ so it can be used by
|
|
||||||
the class that attaches this to a construction environment.
|
|
||||||
"""
|
|
||||||
self.__name__ = name
|
|
||||||
self.initializer = initializer
|
|
||||||
|
|
||||||
def get_builder(self, env):
|
|
||||||
"""
|
|
||||||
Returns the appropriate real Builder for this method name
|
|
||||||
after having the associated ToolInitializer object apply
|
|
||||||
the appropriate Tool module.
|
|
||||||
"""
|
|
||||||
builder = getattr(env, self.__name__)
|
|
||||||
|
|
||||||
self.initializer.apply_tools(env)
|
|
||||||
|
|
||||||
builder = getattr(env, self.__name__)
|
|
||||||
if builder is self:
|
|
||||||
# There was no Builder added, which means no valid Tool
|
|
||||||
# for this name was found (or possibly there's a mismatch
|
|
||||||
# between the name we were called by and the Builder name
|
|
||||||
# added by the Tool module).
|
|
||||||
return None
|
|
||||||
|
|
||||||
self.initializer.remove_methods(env)
|
|
||||||
|
|
||||||
return builder
|
|
||||||
|
|
||||||
def __call__(self, env, *args, **kw):
|
|
||||||
"""
|
|
||||||
"""
|
|
||||||
builder = self.get_builder(env)
|
|
||||||
if builder is None:
|
|
||||||
return [], []
|
|
||||||
return apply(builder, args, kw)
|
|
||||||
|
|
||||||
class ToolInitializer:
|
|
||||||
"""
|
|
||||||
A class for delayed initialization of Tools modules.
|
|
||||||
|
|
||||||
Instances of this class associate a list of Tool modules with
|
|
||||||
a list of Builder method names that will be added by those Tool
|
|
||||||
modules. As part of instantiating this object for a particular
|
|
||||||
construction environment, we also add the appropriate
|
|
||||||
ToolInitializerMethod objects for the various Builder methods
|
|
||||||
that we want to use to delay Tool searches until necessary.
|
|
||||||
"""
|
|
||||||
def __init__(self, env, tools, names):
|
|
||||||
if not SCons.Util.is_List(tools):
|
|
||||||
tools = [tools]
|
|
||||||
if not SCons.Util.is_List(names):
|
|
||||||
names = [names]
|
|
||||||
self.env = env
|
|
||||||
self.tools = tools
|
|
||||||
self.names = names
|
|
||||||
self.methods = {}
|
|
||||||
for name in names:
|
|
||||||
method = ToolInitializerMethod(name, self)
|
|
||||||
self.methods[name] = method
|
|
||||||
env.AddMethod(method)
|
|
||||||
|
|
||||||
def remove_methods(self, env):
|
|
||||||
"""
|
|
||||||
Removes the methods that were added by the tool initialization
|
|
||||||
so we no longer copy and re-bind them when the construction
|
|
||||||
environment gets cloned.
|
|
||||||
"""
|
|
||||||
for method in self.methods.values():
|
|
||||||
env.RemoveMethod(method)
|
|
||||||
|
|
||||||
def apply_tools(self, env):
|
|
||||||
"""
|
|
||||||
Searches the list of associated Tool modules for one that
|
|
||||||
exists, and applies that to the construction environment.
|
|
||||||
"""
|
|
||||||
for t in self.tools:
|
|
||||||
tool = SCons.Tool.Tool(t)
|
|
||||||
if tool.exists(env):
|
|
||||||
env.Tool(tool)
|
|
||||||
return
|
|
||||||
|
|
||||||
# If we fall through here, there was no tool module found.
|
|
||||||
# This is where we can put an informative error message
|
|
||||||
# about the inability to find the tool. We'll start doing
|
|
||||||
# this as we cut over more pre-defined Builder+Tools to use
|
|
||||||
# the ToolInitializer class.
|
|
||||||
|
|
||||||
def Initializers(env):
|
|
||||||
ToolInitializer(env, ['install'], ['_InternalInstall', '_InternalInstallAs'])
|
|
||||||
def Install(self, *args, **kw):
|
|
||||||
return apply(self._InternalInstall, args, kw)
|
|
||||||
def InstallAs(self, *args, **kw):
|
|
||||||
return apply(self._InternalInstallAs, args, kw)
|
|
||||||
env.AddMethod(Install)
|
|
||||||
env.AddMethod(InstallAs)
|
|
||||||
|
|
||||||
def FindTool(tools, env):
|
|
||||||
for tool in tools:
|
|
||||||
t = Tool(tool)
|
|
||||||
if t.exists(env):
|
|
||||||
return tool
|
|
||||||
return None
|
|
||||||
|
|
||||||
def FindAllTools(tools, env):
|
|
||||||
def ToolExists(tool, env=env):
|
|
||||||
return Tool(tool).exists(env)
|
|
||||||
return filter (ToolExists, tools)
|
|
||||||
|
|
||||||
def tool_list(platform, env):
|
|
||||||
|
|
||||||
# XXX this logic about what tool to prefer on which platform
|
|
||||||
# should be moved into either the platform files or
|
|
||||||
# the tool files themselves.
|
|
||||||
# The search orders here are described in the man page. If you
|
|
||||||
# change these search orders, update the man page as well.
|
|
||||||
if str(platform) == 'win32':
|
|
||||||
"prefer Microsoft tools on Windows"
|
|
||||||
linkers = ['mslink', 'gnulink', 'ilink', 'linkloc', 'ilink32' ]
|
|
||||||
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 = ['gfortran', 'g77', 'ifl', 'cvf', 'f95', 'f90', 'fortran']
|
|
||||||
ars = ['mslib', 'ar', 'tlib']
|
|
||||||
elif str(platform) == 'os2':
|
|
||||||
"prefer IBM tools on OS/2"
|
|
||||||
linkers = ['ilink', 'gnulink', 'mslink']
|
|
||||||
c_compilers = ['icc', 'gcc', 'msvc', 'cc']
|
|
||||||
cxx_compilers = ['icc', 'g++', 'msvc', 'c++']
|
|
||||||
assemblers = ['nasm', 'masm', 'gas']
|
|
||||||
fortran_compilers = ['ifl', 'g77']
|
|
||||||
ars = ['ar', 'mslib']
|
|
||||||
elif str(platform) == 'irix':
|
|
||||||
"prefer MIPSPro on IRIX"
|
|
||||||
linkers = ['sgilink', 'gnulink']
|
|
||||||
c_compilers = ['sgicc', 'gcc', 'cc']
|
|
||||||
cxx_compilers = ['sgic++', 'g++', 'c++']
|
|
||||||
assemblers = ['as', 'gas']
|
|
||||||
fortran_compilers = ['f95', 'f90', 'f77', 'g77', 'fortran']
|
|
||||||
ars = ['sgiar']
|
|
||||||
elif str(platform) == 'sunos':
|
|
||||||
"prefer Forte tools on SunOS"
|
|
||||||
linkers = ['gnulink','sunlink']
|
|
||||||
c_compilers = ['gcc','suncc', 'cc']
|
|
||||||
cxx_compilers = ['g++','sunc++', 'c++']
|
|
||||||
assemblers = ['as', 'gas']
|
|
||||||
fortran_compilers = ['sunf95', 'sunf90', 'sunf77', 'f95', 'f90', 'f77',
|
|
||||||
'gfortran', 'g77', 'fortran']
|
|
||||||
ars = ['sunar']
|
|
||||||
elif str(platform) == 'hpux':
|
|
||||||
"prefer aCC tools on HP-UX"
|
|
||||||
linkers = ['hplink', 'gnulink']
|
|
||||||
c_compilers = ['hpcc', 'gcc', 'cc']
|
|
||||||
cxx_compilers = ['hpc++', 'g++', 'c++']
|
|
||||||
assemblers = ['as', 'gas']
|
|
||||||
fortran_compilers = ['f95', 'f90', 'f77', 'g77', 'fortran']
|
|
||||||
ars = ['ar']
|
|
||||||
elif str(platform) == 'aix':
|
|
||||||
"prefer AIX Visual Age tools on AIX"
|
|
||||||
linkers = ['aixlink', 'gnulink']
|
|
||||||
c_compilers = ['aixcc', 'gcc', 'cc']
|
|
||||||
cxx_compilers = ['aixc++', 'g++', 'c++']
|
|
||||||
assemblers = ['as', 'gas']
|
|
||||||
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 = ['gfortran', 'f95', 'f90', 'g77']
|
|
||||||
ars = ['ar']
|
|
||||||
else:
|
|
||||||
"prefer GNU tools on all other platforms"
|
|
||||||
linkers = ['gnulink', 'mslink', 'ilink']
|
|
||||||
c_compilers = ['gcc', 'msvc', 'intelc', 'icc', 'cc']
|
|
||||||
cxx_compilers = ['g++', 'msvc', 'intelc', 'icc', 'c++']
|
|
||||||
assemblers = ['gas', 'nasm', 'masm']
|
|
||||||
fortran_compilers = ['gfortran', 'g77', 'ifort', 'ifl', 'f95', 'f90', 'f77']
|
|
||||||
ars = ['ar', 'mslib']
|
|
||||||
|
|
||||||
c_compiler = FindTool(c_compilers, env) or c_compilers[0]
|
|
||||||
|
|
||||||
# XXX this logic about what tool provides what should somehow be
|
|
||||||
# moved into the tool files themselves.
|
|
||||||
if c_compiler and c_compiler == 'mingw':
|
|
||||||
# MinGW contains a linker, C compiler, C++ compiler,
|
|
||||||
# Fortran compiler, archiver and assembler:
|
|
||||||
cxx_compiler = None
|
|
||||||
linker = None
|
|
||||||
assembler = None
|
|
||||||
fortran_compiler = None
|
|
||||||
ar = None
|
|
||||||
else:
|
|
||||||
# Don't use g++ if the C compiler has built-in C++ support:
|
|
||||||
if c_compiler in ('msvc', 'intelc', 'icc'):
|
|
||||||
cxx_compiler = None
|
|
||||||
else:
|
|
||||||
cxx_compiler = FindTool(cxx_compilers, env) or cxx_compilers[0]
|
|
||||||
linker = FindTool(linkers, env) or linkers[0]
|
|
||||||
assembler = FindTool(assemblers, env) or assemblers[0]
|
|
||||||
fortran_compiler = FindTool(fortran_compilers, env) or fortran_compilers[0]
|
|
||||||
ar = FindTool(ars, env) or ars[0]
|
|
||||||
|
|
||||||
other_tools = FindAllTools(['BitKeeper', 'CVS',
|
|
||||||
'dmd',
|
|
||||||
'filesystem',
|
|
||||||
'dvipdf', 'dvips', 'gs',
|
|
||||||
'jar', 'javac', 'javah',
|
|
||||||
'latex', 'lex',
|
|
||||||
'm4', 'midl', 'msvs',
|
|
||||||
'pdflatex', 'pdftex', 'Perforce',
|
|
||||||
'RCS', 'rmic', 'rpcgen',
|
|
||||||
'SCCS',
|
|
||||||
# 'Subversion',
|
|
||||||
'swig',
|
|
||||||
'tar', 'tex',
|
|
||||||
'yacc', 'zip', 'rpm', 'wix'],
|
|
||||||
env)
|
|
||||||
|
|
||||||
tools = ([linker, c_compiler, cxx_compiler,
|
|
||||||
fortran_compiler, assembler, ar]
|
|
||||||
+ other_tools)
|
|
||||||
|
|
||||||
return filter(lambda x: x, tools)
|
|
|
@ -1,76 +0,0 @@
|
||||||
"""SCons.Tool.aixc++
|
|
||||||
|
|
||||||
Tool-specific initialization for IBM xlC / Visual Age 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, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Tool/aixc++.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import os.path
|
|
||||||
|
|
||||||
import SCons.Platform.aix
|
|
||||||
|
|
||||||
cplusplus = __import__('c++', globals(), locals(), [])
|
|
||||||
|
|
||||||
packages = ['vacpp.cmp.core', 'vacpp.cmp.batch', 'vacpp.cmp.C', 'ibmcxx.cmp']
|
|
||||||
|
|
||||||
def get_xlc(env):
|
|
||||||
xlc = env.get('CXX', 'xlC')
|
|
||||||
xlc_r = env.get('SHCXX', 'xlC_r')
|
|
||||||
return SCons.Platform.aix.get_xlc(env, xlc, xlc_r, packages)
|
|
||||||
|
|
||||||
def smart_cxxflags(source, target, env, for_signature):
|
|
||||||
build_dir = env.GetBuildPath()
|
|
||||||
if build_dir:
|
|
||||||
return '-qtempinc=' + os.path.join(build_dir, 'tempinc')
|
|
||||||
return ''
|
|
||||||
|
|
||||||
def generate(env):
|
|
||||||
"""Add Builders and construction variables for xlC / Visual Age
|
|
||||||
suite to an Environment."""
|
|
||||||
path, _cxx, _shcxx, version = get_xlc(env)
|
|
||||||
if path:
|
|
||||||
_cxx = os.path.join(path, _cxx)
|
|
||||||
_shcxx = os.path.join(path, _shcxx)
|
|
||||||
|
|
||||||
cplusplus.generate(env)
|
|
||||||
|
|
||||||
env['CXX'] = _cxx
|
|
||||||
env['SHCXX'] = _shcxx
|
|
||||||
env['CXXVERSION'] = version
|
|
||||||
env['SHOBJSUFFIX'] = '.pic.o'
|
|
||||||
|
|
||||||
def exists(env):
|
|
||||||
path, _cxx, _shcxx, version = get_xlc(env)
|
|
||||||
if path and _cxx:
|
|
||||||
xlc = os.path.join(path, _cxx)
|
|
||||||
if os.path.exists(xlc):
|
|
||||||
return xlc
|
|
||||||
return None
|
|
|
@ -1,68 +0,0 @@
|
||||||
"""SCons.Tool.aixcc
|
|
||||||
|
|
||||||
Tool-specific initialization for IBM xlc / Visual Age 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, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Tool/aixcc.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import os.path
|
|
||||||
|
|
||||||
import SCons.Platform.aix
|
|
||||||
|
|
||||||
import cc
|
|
||||||
|
|
||||||
packages = ['vac.C', 'ibmcxx.cmp']
|
|
||||||
|
|
||||||
def get_xlc(env):
|
|
||||||
xlc = env.get('CC', 'xlc')
|
|
||||||
xlc_r = env.get('SHCC', 'xlc_r')
|
|
||||||
return SCons.Platform.aix.get_xlc(env, xlc, xlc_r, packages)
|
|
||||||
|
|
||||||
def generate(env):
|
|
||||||
"""Add Builders and construction variables for xlc / Visual Age
|
|
||||||
suite to an Environment."""
|
|
||||||
path, _cc, _shcc, version = get_xlc(env)
|
|
||||||
if path:
|
|
||||||
_cc = os.path.join(path, _cc)
|
|
||||||
_shcc = os.path.join(path, _shcc)
|
|
||||||
|
|
||||||
cc.generate(env)
|
|
||||||
|
|
||||||
env['CC'] = _cc
|
|
||||||
env['SHCC'] = _shcc
|
|
||||||
env['CCVERSION'] = version
|
|
||||||
|
|
||||||
def exists(env):
|
|
||||||
path, _cc, _shcc, version = get_xlc(env)
|
|
||||||
if path and _cc:
|
|
||||||
xlc = os.path.join(path, _cc)
|
|
||||||
if os.path.exists(xlc):
|
|
||||||
return xlc
|
|
||||||
return None
|
|
|
@ -1,74 +0,0 @@
|
||||||
"""engine.SCons.Tool.aixf77
|
|
||||||
|
|
||||||
Tool-specific initialization for IBM Visual Age f77 Fortran compiler.
|
|
||||||
|
|
||||||
There normally shouldn't be any need to import this module directly.
|
|
||||||
It will usually be imported through the generic SCons.Tool.Tool()
|
|
||||||
selection method.
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Tool/aixf77.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import os.path
|
|
||||||
|
|
||||||
#import SCons.Platform.aix
|
|
||||||
|
|
||||||
import f77
|
|
||||||
|
|
||||||
# It would be good to look for the AIX F77 package the same way we're now
|
|
||||||
# looking for the C and C++ packages. This should be as easy as supplying
|
|
||||||
# the correct package names in the following list and uncommenting the
|
|
||||||
# SCons.Platform.aix_get_xlc() call the in the function below.
|
|
||||||
packages = []
|
|
||||||
|
|
||||||
def get_xlf77(env):
|
|
||||||
xlf77 = env.get('F77', 'xlf77')
|
|
||||||
xlf77_r = env.get('SHF77', 'xlf77_r')
|
|
||||||
#return SCons.Platform.aix.get_xlc(env, xlf77, xlf77_r, packages)
|
|
||||||
return (None, xlf77, xlf77_r, None)
|
|
||||||
|
|
||||||
def generate(env):
|
|
||||||
"""
|
|
||||||
Add Builders and construction variables for the Visual Age FORTRAN
|
|
||||||
compiler to an Environment.
|
|
||||||
"""
|
|
||||||
path, _f77, _shf77, version = get_xlf77(env)
|
|
||||||
if path:
|
|
||||||
_f77 = os.path.join(path, _f77)
|
|
||||||
_shf77 = os.path.join(path, _shf77)
|
|
||||||
|
|
||||||
f77.generate(env)
|
|
||||||
|
|
||||||
env['F77'] = _f77
|
|
||||||
env['SHF77'] = _shf77
|
|
||||||
|
|
||||||
def exists(env):
|
|
||||||
path, _f77, _shf77, version = get_xlf77(env)
|
|
||||||
if path and _f77:
|
|
||||||
xlf77 = os.path.join(path, _f77)
|
|
||||||
if os.path.exists(xlf77):
|
|
||||||
return xlf77
|
|
||||||
return None
|
|
|
@ -1,70 +0,0 @@
|
||||||
"""SCons.Tool.aixlink
|
|
||||||
|
|
||||||
Tool-specific initialization for the IBM Visual Age linker.
|
|
||||||
|
|
||||||
There normally shouldn't be any need to import this module directly.
|
|
||||||
It will usually be imported through the generic SCons.Tool.Tool()
|
|
||||||
selection method.
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Tool/aixlink.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import os
|
|
||||||
import os.path
|
|
||||||
|
|
||||||
import SCons.Util
|
|
||||||
|
|
||||||
import aixcc
|
|
||||||
import link
|
|
||||||
|
|
||||||
cplusplus = __import__('c++', globals(), locals(), [])
|
|
||||||
|
|
||||||
def smart_linkflags(source, target, env, for_signature):
|
|
||||||
if cplusplus.iscplusplus(source):
|
|
||||||
build_dir = env.subst('$BUILDDIR', target=target, source=source)
|
|
||||||
if build_dir:
|
|
||||||
return '-qtempinc=' + os.path.join(build_dir, 'tempinc')
|
|
||||||
return ''
|
|
||||||
|
|
||||||
def generate(env):
|
|
||||||
"""
|
|
||||||
Add Builders and construction variables for Visual Age linker to
|
|
||||||
an Environment.
|
|
||||||
"""
|
|
||||||
link.generate(env)
|
|
||||||
|
|
||||||
env['SMARTLINKFLAGS'] = smart_linkflags
|
|
||||||
env['LINKFLAGS'] = SCons.Util.CLVar('$SMARTLINKFLAGS')
|
|
||||||
env['SHLINKFLAGS'] = SCons.Util.CLVar('$LINKFLAGS -qmkshrobj -qsuppress=1501-218')
|
|
||||||
env['SHLIBSUFFIX'] = '.a'
|
|
||||||
|
|
||||||
def exists(env):
|
|
||||||
path, _cc, _shcc, version = aixcc.get_xlc(env)
|
|
||||||
if path and _cc:
|
|
||||||
xlc = os.path.join(path, _cc)
|
|
||||||
if os.path.exists(xlc):
|
|
||||||
return xlc
|
|
||||||
return None
|
|
|
@ -1,65 +0,0 @@
|
||||||
"""SCons.Tool.applelink
|
|
||||||
|
|
||||||
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()
|
|
||||||
selection method.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Tool/applelink.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import SCons.Util
|
|
||||||
|
|
||||||
# Even though the Mac is based on the GNU toolchain, it doesn't understand
|
|
||||||
# the -rpath option, so we use the "link" tool instead of "gnulink".
|
|
||||||
import link
|
|
||||||
|
|
||||||
def generate(env):
|
|
||||||
"""Add Builders and construction variables for applelink to an
|
|
||||||
Environment."""
|
|
||||||
link.generate(env)
|
|
||||||
|
|
||||||
env['FRAMEWORKPATHPREFIX'] = '-F'
|
|
||||||
env['_FRAMEWORKPATH'] = '${_concat(FRAMEWORKPATHPREFIX, FRAMEWORKPATH, "", __env__)}'
|
|
||||||
env['_FRAMEWORKS'] = '${_concat("-framework ", FRAMEWORKS, "", __env__)}'
|
|
||||||
env['LINKCOM'] = env['LINKCOM'] + ' $_FRAMEWORKPATH $_FRAMEWORKS $FRAMEWORKSFLAGS'
|
|
||||||
env['SHLINKFLAGS'] = SCons.Util.CLVar('$LINKFLAGS -dynamiclib')
|
|
||||||
env['SHLINKCOM'] = env['SHLINKCOM'] + ' $_FRAMEWORKPATH $_FRAMEWORKS $FRAMEWORKSFLAGS'
|
|
||||||
|
|
||||||
# override the default for loadable modules, which are different
|
|
||||||
# on OS X than dynamic shared libs. echoing what XCode does for
|
|
||||||
# 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'
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def exists(env):
|
|
||||||
return env['PLATFORM'] == 'darwin'
|
|
|
@ -1,57 +0,0 @@
|
||||||
"""SCons.Tool.ar
|
|
||||||
|
|
||||||
Tool-specific initialization for ar (library archive).
|
|
||||||
|
|
||||||
There normally shouldn't be any need to import this module directly.
|
|
||||||
It will usually be imported through the generic SCons.Tool.Tool()
|
|
||||||
selection method.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Tool/ar.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
env['AR'] = 'ar'
|
|
||||||
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')
|
|
|
@ -1,72 +0,0 @@
|
||||||
"""SCons.Tool.as
|
|
||||||
|
|
||||||
Tool-specific initialization for as, the generic Posix assembler.
|
|
||||||
|
|
||||||
There normally shouldn't be any need to import this module directly.
|
|
||||||
It will usually be imported through the generic SCons.Tool.Tool()
|
|
||||||
selection method.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Tool/as.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import SCons.Defaults
|
|
||||||
import SCons.Tool
|
|
||||||
import SCons.Util
|
|
||||||
|
|
||||||
assemblers = ['as']
|
|
||||||
|
|
||||||
ASSuffixes = ['.s', '.asm', '.ASM']
|
|
||||||
ASPPSuffixes = ['.spp', '.SPP', '.sx']
|
|
||||||
if SCons.Util.case_sensitive_suffixes('.s', '.S'):
|
|
||||||
ASPPSuffixes.extend(['.S'])
|
|
||||||
else:
|
|
||||||
ASSuffixes.extend(['.S'])
|
|
||||||
|
|
||||||
def generate(env):
|
|
||||||
"""Add Builders and construction variables for as to an Environment."""
|
|
||||||
static_obj, shared_obj = SCons.Tool.createObjBuilders(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['ASPPFLAGS'] = '$ASFLAGS'
|
|
||||||
env['ASPPCOM'] = '$CC $ASPPFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -c -o $TARGET $SOURCES'
|
|
||||||
|
|
||||||
def exists(env):
|
|
||||||
return env.Detect(assemblers)
|
|
|
@ -1,76 +0,0 @@
|
||||||
"""SCons.Tool.bcc32
|
|
||||||
|
|
||||||
XXX
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Tool/bcc32.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import os
|
|
||||||
import os.path
|
|
||||||
import string
|
|
||||||
|
|
||||||
import SCons.Defaults
|
|
||||||
import SCons.Tool
|
|
||||||
import SCons.Util
|
|
||||||
|
|
||||||
def findIt(program, env):
|
|
||||||
# First search in the SCons path and then the OS path:
|
|
||||||
borwin = env.WhereIs(program) or SCons.Util.WhereIs(program)
|
|
||||||
if borwin:
|
|
||||||
dir = os.path.dirname(borwin)
|
|
||||||
env.PrependENVPath('PATH', dir)
|
|
||||||
return borwin
|
|
||||||
|
|
||||||
def generate(env):
|
|
||||||
findIt('bcc32', env)
|
|
||||||
"""Add Builders and construction variables for bcc to an
|
|
||||||
Environment."""
|
|
||||||
static_obj, shared_obj = SCons.Tool.createObjBuilders(env)
|
|
||||||
for suffix in ['.c', '.cpp']:
|
|
||||||
static_obj.add_action(suffix, SCons.Defaults.CAction)
|
|
||||||
shared_obj.add_action(suffix, SCons.Defaults.ShCAction)
|
|
||||||
static_obj.add_emitter(suffix, SCons.Defaults.StaticObjectEmitter)
|
|
||||||
shared_obj.add_emitter(suffix, SCons.Defaults.SharedObjectEmitter)
|
|
||||||
|
|
||||||
env['CC'] = 'bcc32'
|
|
||||||
env['CCFLAGS'] = SCons.Util.CLVar('')
|
|
||||||
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['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'
|
|
||||||
env['INCSUFFIX'] = ''
|
|
||||||
env['SHOBJSUFFIX'] = '.dll'
|
|
||||||
env['STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME'] = 0
|
|
||||||
env['CFILESUFFIX'] = '.cpp'
|
|
||||||
|
|
||||||
def exists(env):
|
|
||||||
return findIt('bcc32', env)
|
|
|
@ -1,93 +0,0 @@
|
||||||
"""SCons.Tool.c++
|
|
||||||
|
|
||||||
Tool-specific initialization for generic Posix C++ compilers.
|
|
||||||
|
|
||||||
There normally shouldn't be any need to import this module directly.
|
|
||||||
It will usually be imported through the generic SCons.Tool.Tool()
|
|
||||||
selection method.
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Tool/c++.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import os.path
|
|
||||||
|
|
||||||
import SCons.Tool
|
|
||||||
import SCons.Defaults
|
|
||||||
import SCons.Util
|
|
||||||
|
|
||||||
compilers = ['CC', 'c++']
|
|
||||||
|
|
||||||
CXXSuffixes = ['.cpp', '.cc', '.cxx', '.c++', '.C++', '.mm']
|
|
||||||
if SCons.Util.case_sensitive_suffixes('.c', '.C'):
|
|
||||||
CXXSuffixes.append('.C')
|
|
||||||
|
|
||||||
def iscplusplus(source):
|
|
||||||
if not source:
|
|
||||||
# Source might be None for unusual cases like SConf.
|
|
||||||
return 0
|
|
||||||
for s in source:
|
|
||||||
if s.sources:
|
|
||||||
ext = os.path.splitext(str(s.sources[0]))[1]
|
|
||||||
if ext in CXXSuffixes:
|
|
||||||
return 1
|
|
||||||
return 0
|
|
||||||
|
|
||||||
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:
|
|
||||||
static_obj.add_action(suffix, SCons.Defaults.CXXAction)
|
|
||||||
shared_obj.add_action(suffix, SCons.Defaults.ShCXXAction)
|
|
||||||
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('')
|
|
||||||
env['CXXCOM'] = '$CXX -o $TARGET -c $CXXFLAGS $CCFLAGS $_CCCOMCOM $SOURCES'
|
|
||||||
env['SHCXX'] = '$CXX'
|
|
||||||
env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS')
|
|
||||||
env['SHCXXCOM'] = '$SHCXX -o $TARGET -c $SHCXXFLAGS $SHCCFLAGS $_CCCOMCOM $SOURCES'
|
|
||||||
|
|
||||||
env['CPPDEFPREFIX'] = '-D'
|
|
||||||
env['CPPDEFSUFFIX'] = ''
|
|
||||||
env['INCPREFIX'] = '-I'
|
|
||||||
env['INCSUFFIX'] = ''
|
|
||||||
env['SHOBJSUFFIX'] = '.os'
|
|
||||||
env['OBJSUFFIX'] = '.o'
|
|
||||||
env['STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME'] = 0
|
|
||||||
|
|
||||||
env['CXXFILESUFFIX'] = '.cc'
|
|
||||||
|
|
||||||
def exists(env):
|
|
||||||
return env.Detect(compilers)
|
|
|
@ -1,108 +0,0 @@
|
||||||
"""SCons.Tool.cc
|
|
||||||
|
|
||||||
Tool-specific initialization for generic Posix C compilers.
|
|
||||||
|
|
||||||
There normally shouldn't be any need to import this module directly.
|
|
||||||
It will usually be imported through the generic SCons.Tool.Tool()
|
|
||||||
selection method.
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Tool/cc.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import SCons.Tool
|
|
||||||
import SCons.Defaults
|
|
||||||
import SCons.Util
|
|
||||||
|
|
||||||
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.
|
|
||||||
"""
|
|
||||||
static_obj, shared_obj = SCons.Tool.createObjBuilders(env)
|
|
||||||
|
|
||||||
for suffix in CSuffixes:
|
|
||||||
static_obj.add_action(suffix, SCons.Defaults.CAction)
|
|
||||||
shared_obj.add_action(suffix, SCons.Defaults.ShCAction)
|
|
||||||
static_obj.add_emitter(suffix, SCons.Defaults.StaticObjectEmitter)
|
|
||||||
shared_obj.add_emitter(suffix, SCons.Defaults.SharedObjectEmitter)
|
|
||||||
#<<<<<<< .working
|
|
||||||
#
|
|
||||||
# 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'
|
|
||||||
#=======
|
|
||||||
#>>>>>>> .merge-right.r1907
|
|
||||||
|
|
||||||
add_common_cc_variables(env)
|
|
||||||
|
|
||||||
env['CC'] = 'cc'
|
|
||||||
env['CFLAGS'] = SCons.Util.CLVar('')
|
|
||||||
env['CCCOM'] = '$CC -o $TARGET -c $CFLAGS $CCFLAGS $_CCCOMCOM $SOURCES'
|
|
||||||
env['SHCC'] = '$CC'
|
|
||||||
env['SHCFLAGS'] = SCons.Util.CLVar('$CFLAGS')
|
|
||||||
env['SHCCCOM'] = '$SHCC -o $TARGET -c $SHCFLAGS $SHCCFLAGS $_CCCOMCOM $SOURCES'
|
|
||||||
|
|
||||||
env['CPPDEFPREFIX'] = '-D'
|
|
||||||
env['CPPDEFSUFFIX'] = ''
|
|
||||||
env['INCPREFIX'] = '-I'
|
|
||||||
env['INCSUFFIX'] = ''
|
|
||||||
env['SHOBJSUFFIX'] = '.os'
|
|
||||||
env['STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME'] = 0
|
|
||||||
|
|
||||||
env['CFILESUFFIX'] = '.c'
|
|
||||||
|
|
||||||
def exists(env):
|
|
||||||
return env.Detect('cc')
|
|
|
@ -1,52 +0,0 @@
|
||||||
"""engine.SCons.Tool.cvf
|
|
||||||
|
|
||||||
Tool-specific initialization for the Compaq Visual Fortran compiler.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Tool/cvf.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import fortran
|
|
||||||
|
|
||||||
compilers = ['f90']
|
|
||||||
|
|
||||||
def generate(env):
|
|
||||||
"""Add Builders and construction variables for compaq visual fortran to an Environment."""
|
|
||||||
|
|
||||||
fortran.generate(env)
|
|
||||||
|
|
||||||
env['FORTRAN'] = 'f90'
|
|
||||||
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:'
|
|
||||||
env['FORTRANMODDIRSUFFIX'] = ''
|
|
||||||
|
|
||||||
def exists(env):
|
|
||||||
return env.Detect(compilers)
|
|
|
@ -1,44 +0,0 @@
|
||||||
"""SCons.Tool.default
|
|
||||||
|
|
||||||
Initialization with a default tool list.
|
|
||||||
|
|
||||||
There normally shouldn't be any need to import this module directly.
|
|
||||||
It will usually be imported through the generic SCons.Tool.Tool()
|
|
||||||
selection method.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Tool/default.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import SCons.Tool
|
|
||||||
|
|
||||||
def generate(env):
|
|
||||||
"""Add default tools."""
|
|
||||||
for t in SCons.Tool.tool_list(env['PLATFORM'], env):
|
|
||||||
SCons.Tool.Tool(t)(env)
|
|
||||||
|
|
||||||
def exists(env):
|
|
||||||
return 1
|
|
|
@ -1,218 +0,0 @@
|
||||||
"""SCons.Tool.dmd
|
|
||||||
|
|
||||||
Tool-specific initialization for the Digital Mars D compiler.
|
|
||||||
(http://digitalmars.com/d)
|
|
||||||
|
|
||||||
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 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
|
|
||||||
blah.lib from the directory where SConstruct resides.
|
|
||||||
|
|
||||||
Compiler variables:
|
|
||||||
DC - The name of the D compiler to use. Defaults to dmd or gdmd,
|
|
||||||
whichever is found.
|
|
||||||
DPATH - List of paths to search for import modules.
|
|
||||||
DVERSIONS - List of version tags to enable when compiling.
|
|
||||||
DDEBUG - List of debug tags to enable when compiling.
|
|
||||||
|
|
||||||
Linker related variables:
|
|
||||||
LIBS - List of library files to link in.
|
|
||||||
DLINK - Name of the linker to use. Defaults to dmd or gdmd.
|
|
||||||
DLINKFLAGS - List of linker flags.
|
|
||||||
|
|
||||||
Lib tool variables:
|
|
||||||
DLIB - Name of the lib tool to use. Defaults to lib.
|
|
||||||
DLIBFLAGS - List of flags to pass to the lib tool.
|
|
||||||
LIBS - Same as for the linker. (libraries to pull into the .lib)
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Tool/dmd.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import os
|
|
||||||
import string
|
|
||||||
|
|
||||||
import SCons.Action
|
|
||||||
import SCons.Builder
|
|
||||||
import SCons.Defaults
|
|
||||||
import SCons.Scanner.D
|
|
||||||
import SCons.Tool
|
|
||||||
|
|
||||||
# Adapted from c++.py
|
|
||||||
def isD(source):
|
|
||||||
if not source:
|
|
||||||
return 0
|
|
||||||
|
|
||||||
for s in source:
|
|
||||||
if s.sources:
|
|
||||||
ext = os.path.splitext(str(s.sources[0]))[1]
|
|
||||||
if ext == '.d':
|
|
||||||
return 1
|
|
||||||
return 0
|
|
||||||
|
|
||||||
smart_link = {}
|
|
||||||
|
|
||||||
smart_lib = {}
|
|
||||||
|
|
||||||
def generate(env):
|
|
||||||
global smart_link
|
|
||||||
global smart_lib
|
|
||||||
|
|
||||||
static_obj, shared_obj = SCons.Tool.createObjBuilders(env)
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
dc = env.Detect(['dmd', 'gdmd'])
|
|
||||||
env['DC'] = dc
|
|
||||||
env['DCOM'] = '$DC $_DINCFLAGS $_DVERFLAGS $_DDEBUGFLAGS $_DFLAGS -c -of$TARGET $SOURCES'
|
|
||||||
env['_DINCFLAGS'] = '$( ${_concat(DINCPREFIX, DPATH, DINCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)'
|
|
||||||
env['_DVERFLAGS'] = '$( ${_concat(DVERPREFIX, DVERSIONS, DVERSUFFIX, __env__)} $)'
|
|
||||||
env['_DDEBUGFLAGS'] = '$( ${_concat(DDEBUGPREFIX, DDEBUG, DDEBUGSUFFIX, __env__)} $)'
|
|
||||||
env['_DFLAGS'] = '$( ${_concat(DFLAGPREFIX, DFLAGS, DFLAGSUFFIX, __env__)} $)'
|
|
||||||
|
|
||||||
env['DPATH'] = ['#/']
|
|
||||||
env['DFLAGS'] = []
|
|
||||||
env['DVERSIONS'] = []
|
|
||||||
env['DDEBUG'] = []
|
|
||||||
|
|
||||||
if dc:
|
|
||||||
# Add the path to the standard library.
|
|
||||||
# This is merely for the convenience of the dependency scanner.
|
|
||||||
dmd_path = env.WhereIs(dc)
|
|
||||||
if dmd_path:
|
|
||||||
x = string.rindex(dmd_path, dc)
|
|
||||||
phobosDir = dmd_path[:x] + '/../src/phobos'
|
|
||||||
if os.path.isdir(phobosDir):
|
|
||||||
env.Append(DPATH = [phobosDir])
|
|
||||||
|
|
||||||
env['DINCPREFIX'] = '-I'
|
|
||||||
env['DINCSUFFIX'] = ''
|
|
||||||
env['DVERPREFIX'] = '-version='
|
|
||||||
env['DVERSUFFIX'] = ''
|
|
||||||
env['DDEBUGPREFIX'] = '-debug='
|
|
||||||
env['DDEBUGSUFFIX'] = ''
|
|
||||||
env['DFLAGPREFIX'] = '-'
|
|
||||||
env['DFLAGSUFFIX'] = ''
|
|
||||||
env['DFILESUFFIX'] = '.d'
|
|
||||||
|
|
||||||
# Need to use the Digital Mars linker/lib on windows.
|
|
||||||
# *nix can just use GNU link.
|
|
||||||
if env['PLATFORM'] == 'win32':
|
|
||||||
env['DLINK'] = '$DC'
|
|
||||||
env['DLINKCOM'] = '$DLINK -of$TARGET $SOURCES $DFLAGS $DLINKFLAGS $_DLINKLIBFLAGS'
|
|
||||||
env['DLIB'] = 'lib'
|
|
||||||
env['DLIBCOM'] = '$DLIB $_DLIBFLAGS -c $TARGET $SOURCES $_DLINKLIBFLAGS'
|
|
||||||
|
|
||||||
env['_DLINKLIBFLAGS'] = '$( ${_concat(DLIBLINKPREFIX, LIBS, DLIBLINKSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)'
|
|
||||||
env['_DLIBFLAGS'] = '$( ${_concat(DLIBFLAGPREFIX, DLIBFLAGS, DLIBFLAGSUFFIX, __env__)} $)'
|
|
||||||
env['DLINKFLAGS'] = []
|
|
||||||
env['DLIBLINKPREFIX'] = ''
|
|
||||||
env['DLIBLINKSUFFIX'] = '.lib'
|
|
||||||
env['DLIBFLAGPREFIX'] = '-'
|
|
||||||
env['DLIBFLAGSUFFIX'] = ''
|
|
||||||
env['DLINKFLAGPREFIX'] = '-'
|
|
||||||
env['DLINKFLAGSUFFIX'] = ''
|
|
||||||
|
|
||||||
SCons.Tool.createStaticLibBuilder(env)
|
|
||||||
|
|
||||||
# Basically, we hijack the link and ar builders with our own.
|
|
||||||
# these builders check for the presence of D source, and swap out
|
|
||||||
# the system's defaults for the Digital Mars tools. If there's no D
|
|
||||||
# source, then we silently return the previous settings.
|
|
||||||
linkcom = env.get('LINKCOM')
|
|
||||||
try:
|
|
||||||
env['SMART_LINKCOM'] = smart_link[linkcom]
|
|
||||||
except KeyError:
|
|
||||||
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
|
|
||||||
env['SMART_LINKCOM'] = smart_link[linkcom] = _smartLink
|
|
||||||
|
|
||||||
arcom = env.get('ARCOM')
|
|
||||||
try:
|
|
||||||
env['SMART_ARCOM'] = smart_lib[arcom]
|
|
||||||
except KeyError:
|
|
||||||
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
|
|
||||||
env['SMART_ARCOM'] = smart_lib[arcom] = _smartLib
|
|
||||||
|
|
||||||
# It is worth noting that the final space in these strings is
|
|
||||||
# absolutely pivotal. SCons sees these as actions and not generators
|
|
||||||
# if it is not there. (very bad)
|
|
||||||
env['ARCOM'] = '$SMART_ARCOM '
|
|
||||||
env['LINKCOM'] = '$SMART_LINKCOM '
|
|
||||||
else: # assuming linux
|
|
||||||
linkcom = env.get('LINKCOM')
|
|
||||||
try:
|
|
||||||
env['SMART_LINKCOM'] = smart_link[linkcom]
|
|
||||||
except KeyError:
|
|
||||||
def _smartLink(source, target, env, for_signature,
|
|
||||||
defaultLinker=linkcom, dc=dc):
|
|
||||||
if isD(source):
|
|
||||||
try:
|
|
||||||
libs = env['LIBS']
|
|
||||||
except KeyError:
|
|
||||||
libs = []
|
|
||||||
if 'phobos' not in libs:
|
|
||||||
if dc is 'dmd':
|
|
||||||
env.Append(LIBS = ['phobos'])
|
|
||||||
elif dc is 'gdmd':
|
|
||||||
env.Append(LIBS = ['gphobos'])
|
|
||||||
if 'pthread' not in libs:
|
|
||||||
env.Append(LIBS = ['pthread'])
|
|
||||||
if 'm' not in libs:
|
|
||||||
env.Append(LIBS = ['m'])
|
|
||||||
return defaultLinker
|
|
||||||
env['SMART_LINKCOM'] = smart_link[linkcom] = _smartLink
|
|
||||||
|
|
||||||
env['LINKCOM'] = '$SMART_LINKCOM '
|
|
||||||
|
|
||||||
def exists(env):
|
|
||||||
return env.Detect(['dmd', 'gdmd'])
|
|
|
@ -1,58 +0,0 @@
|
||||||
"""SCons.Tool.dvi
|
|
||||||
|
|
||||||
Common DVI Builder definition for various other Tool modules that use it.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Tool/dvi.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
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
|
|
|
@ -1,119 +0,0 @@
|
||||||
"""SCons.Tool.dvipdf
|
|
||||||
|
|
||||||
Tool-specific initialization for dvipdf.
|
|
||||||
|
|
||||||
There normally shouldn't be any need to import this module directly.
|
|
||||||
It will usually be imported through the generic SCons.Tool.Tool()
|
|
||||||
selection method.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Tool/dvipdf.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import SCons.Action
|
|
||||||
import SCons.Defaults
|
|
||||||
import SCons.Tool.pdf
|
|
||||||
import SCons.Tool.tex
|
|
||||||
import SCons.Util
|
|
||||||
|
|
||||||
_null = SCons.Scanner.LaTeX._null
|
|
||||||
|
|
||||||
def DviPdfPsFunction(XXXDviAction, target = None, source= None, env=None):
|
|
||||||
"""A builder for DVI files that sets the TEXPICTS environment
|
|
||||||
variable before running dvi2ps or dvipdf."""
|
|
||||||
|
|
||||||
try:
|
|
||||||
abspath = source[0].attributes.path
|
|
||||||
except AttributeError :
|
|
||||||
abspath = ''
|
|
||||||
|
|
||||||
saved_env = SCons.Scanner.LaTeX.modify_env_var(env, 'TEXPICTS', abspath)
|
|
||||||
|
|
||||||
result = XXXDviAction(target, source, env)
|
|
||||||
|
|
||||||
if saved_env is _null:
|
|
||||||
try:
|
|
||||||
del env['ENV']['TEXPICTS']
|
|
||||||
except KeyError:
|
|
||||||
pass # was never set
|
|
||||||
else:
|
|
||||||
env['ENV']['TEXPICTS'] = saved_env
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
def DviPdfFunction(target = None, source= None, env=None):
|
|
||||||
result = DviPdfPsFunction(PDFAction,target,source,env)
|
|
||||||
return result
|
|
||||||
|
|
||||||
def DviPdfStrFunction(target = None, source= None, env=None):
|
|
||||||
"""A strfunction for dvipdf that returns the appropriate
|
|
||||||
command string for the no_exec options."""
|
|
||||||
if env.GetOption("no_exec"):
|
|
||||||
result = env.subst('$DVIPDFCOM',0,target,source)
|
|
||||||
else:
|
|
||||||
result = ''
|
|
||||||
return result
|
|
||||||
|
|
||||||
PDFAction = None
|
|
||||||
DVIPDFAction = None
|
|
||||||
|
|
||||||
def PDFEmitter(target, source, env):
|
|
||||||
"""Strips any .aux or .log files from the input source list.
|
|
||||||
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."""
|
|
||||||
global PDFAction
|
|
||||||
if PDFAction is None:
|
|
||||||
PDFAction = SCons.Action.Action('$DVIPDFCOM', '$DVIPDFCOMSTR')
|
|
||||||
|
|
||||||
global DVIPDFAction
|
|
||||||
if DVIPDFAction is None:
|
|
||||||
DVIPDFAction = SCons.Action.Action(DviPdfFunction, strfunction = DviPdfStrFunction)
|
|
||||||
|
|
||||||
import pdf
|
|
||||||
pdf.generate(env)
|
|
||||||
|
|
||||||
bld = env['BUILDERS']['PDF']
|
|
||||||
bld.add_action('.dvi', DVIPDFAction)
|
|
||||||
bld.add_emitter('.dvi', PDFEmitter)
|
|
||||||
|
|
||||||
env['DVIPDF'] = 'dvipdf'
|
|
||||||
env['DVIPDFFLAGS'] = SCons.Util.CLVar('')
|
|
||||||
env['DVIPDFCOM'] = 'cd ${TARGET.dir} && $DVIPDF $DVIPDFFLAGS ${SOURCE.file} ${TARGET.file}'
|
|
||||||
|
|
||||||
# Deprecated synonym.
|
|
||||||
env['PDFCOM'] = ['$DVIPDFCOM']
|
|
||||||
|
|
||||||
def exists(env):
|
|
||||||
return env.Detect('dvipdf')
|
|
|
@ -1,88 +0,0 @@
|
||||||
"""SCons.Tool.dvips
|
|
||||||
|
|
||||||
Tool-specific initialization for dvips.
|
|
||||||
|
|
||||||
There normally shouldn't be any need to import this module directly.
|
|
||||||
It will usually be imported through the generic SCons.Tool.Tool()
|
|
||||||
selection method.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Tool/dvips.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import SCons.Action
|
|
||||||
import SCons.Builder
|
|
||||||
import SCons.Tool.dvipdf
|
|
||||||
import SCons.Util
|
|
||||||
|
|
||||||
def DviPsFunction(target = None, source= None, env=None):
|
|
||||||
result = SCons.Tool.dvipdf.DviPdfPsFunction(PSAction,target,source,env)
|
|
||||||
return result
|
|
||||||
|
|
||||||
def DviPsStrFunction(target = None, source= None, env=None):
|
|
||||||
"""A strfunction for dvipdf that returns the appropriate
|
|
||||||
command string for the no_exec options."""
|
|
||||||
if env.GetOption("no_exec"):
|
|
||||||
result = env.subst('$PSCOM',0,target,source)
|
|
||||||
else:
|
|
||||||
result = ''
|
|
||||||
return result
|
|
||||||
|
|
||||||
PSAction = None
|
|
||||||
DVIPSAction = None
|
|
||||||
PSBuilder = None
|
|
||||||
|
|
||||||
def generate(env):
|
|
||||||
"""Add Builders and construction variables for dvips to an Environment."""
|
|
||||||
global PSAction
|
|
||||||
if PSAction is None:
|
|
||||||
PSAction = SCons.Action.Action('$PSCOM', '$PSCOMSTR')
|
|
||||||
|
|
||||||
global DVIPSAction
|
|
||||||
if DVIPSAction is None:
|
|
||||||
DVIPSAction = SCons.Action.Action(DviPsFunction, strfunction = DviPsStrFunction)
|
|
||||||
|
|
||||||
global PSBuilder
|
|
||||||
if PSBuilder is None:
|
|
||||||
PSBuilder = SCons.Builder.Builder(action = PSAction,
|
|
||||||
prefix = '$PSPREFIX',
|
|
||||||
suffix = '$PSSUFFIX',
|
|
||||||
src_suffix = '.dvi',
|
|
||||||
src_builder = 'DVI',
|
|
||||||
single_source=True)
|
|
||||||
|
|
||||||
env['BUILDERS']['PostScript'] = PSBuilder
|
|
||||||
|
|
||||||
env['DVIPS'] = 'dvips'
|
|
||||||
env['DVIPSFLAGS'] = SCons.Util.CLVar('')
|
|
||||||
# I'm not quite sure I got the directories and filenames right for variant_dir
|
|
||||||
# We need to be in the correct directory for the sake of latex \includegraphics eps included files.
|
|
||||||
env['PSCOM'] = 'cd ${TARGET.dir} && $DVIPS $DVIPSFLAGS -o ${TARGET.file} ${SOURCE.file}'
|
|
||||||
env['PSPREFIX'] = ''
|
|
||||||
env['PSSUFFIX'] = '.ps'
|
|
||||||
|
|
||||||
def exists(env):
|
|
||||||
return env.Detect('dvips')
|
|
|
@ -1,56 +0,0 @@
|
||||||
"""engine.SCons.Tool.f77
|
|
||||||
|
|
||||||
Tool-specific initialization for the generic Posix f77 Fortran compiler.
|
|
||||||
|
|
||||||
There normally shouldn't be any need to import this module directly.
|
|
||||||
It will usually be imported through the generic SCons.Tool.Tool()
|
|
||||||
selection method.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Tool/f77.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import SCons.Defaults
|
|
||||||
import SCons.Scanner.Fortran
|
|
||||||
import SCons.Tool
|
|
||||||
import SCons.Util
|
|
||||||
from SCons.Tool.FortranCommon import add_all_to_env, add_f77_to_env
|
|
||||||
|
|
||||||
compilers = ['f77']
|
|
||||||
|
|
||||||
def generate(env):
|
|
||||||
add_all_to_env(env)
|
|
||||||
add_f77_to_env(env)
|
|
||||||
|
|
||||||
fcomp = env.Detect(compilers) or 'f77'
|
|
||||||
env['F77'] = fcomp
|
|
||||||
env['SHF77'] = fcomp
|
|
||||||
|
|
||||||
env['FORTRAN'] = fcomp
|
|
||||||
env['SHFORTRAN'] = fcomp
|
|
||||||
|
|
||||||
def exists(env):
|
|
||||||
return env.Detect(compilers)
|
|
|
@ -1,56 +0,0 @@
|
||||||
"""engine.SCons.Tool.f90
|
|
||||||
|
|
||||||
Tool-specific initialization for the generic Posix f90 Fortran compiler.
|
|
||||||
|
|
||||||
There normally shouldn't be any need to import this module directly.
|
|
||||||
It will usually be imported through the generic SCons.Tool.Tool()
|
|
||||||
selection method.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Tool/f90.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import SCons.Defaults
|
|
||||||
import SCons.Scanner.Fortran
|
|
||||||
import SCons.Tool
|
|
||||||
import SCons.Util
|
|
||||||
from SCons.Tool.FortranCommon import add_all_to_env, add_f90_to_env
|
|
||||||
|
|
||||||
compilers = ['f90']
|
|
||||||
|
|
||||||
def generate(env):
|
|
||||||
add_all_to_env(env)
|
|
||||||
add_f90_to_env(env)
|
|
||||||
|
|
||||||
fc = env.Detect(compilers) or 'f90'
|
|
||||||
env['F90'] = fc
|
|
||||||
env['SHF90'] = fc
|
|
||||||
|
|
||||||
env['FORTRAN'] = fc
|
|
||||||
env['SHFORTRAN'] = fc
|
|
||||||
|
|
||||||
def exists(env):
|
|
||||||
return env.Detect(compilers)
|
|
|
@ -1,57 +0,0 @@
|
||||||
"""engine.SCons.Tool.f95
|
|
||||||
|
|
||||||
Tool-specific initialization for the generic Posix f95 Fortran compiler.
|
|
||||||
|
|
||||||
There normally shouldn't be any need to import this module directly.
|
|
||||||
It will usually be imported through the generic SCons.Tool.Tool()
|
|
||||||
selection method.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Tool/f95.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import SCons.Defaults
|
|
||||||
import SCons.Tool
|
|
||||||
import SCons.Util
|
|
||||||
import fortran
|
|
||||||
from SCons.Tool.FortranCommon import add_all_to_env, add_f95_to_env
|
|
||||||
|
|
||||||
compilers = ['f95']
|
|
||||||
|
|
||||||
def generate(env):
|
|
||||||
add_all_to_env(env)
|
|
||||||
add_f95_to_env(env)
|
|
||||||
|
|
||||||
fcomp = env.Detect(compilers) or 'f95'
|
|
||||||
env['F95'] = fcomp
|
|
||||||
env['SHF95'] = fcomp
|
|
||||||
|
|
||||||
env['FORTRAN'] = fcomp
|
|
||||||
env['SHFORTRAN'] = fcomp
|
|
||||||
|
|
||||||
|
|
||||||
def exists(env):
|
|
||||||
return env.Detect(compilers)
|
|
|
@ -1,92 +0,0 @@
|
||||||
"""SCons.Tool.filesystem
|
|
||||||
|
|
||||||
Tool-specific initialization for the filesystem tools.
|
|
||||||
|
|
||||||
There normally shouldn't be any need to import this module directly.
|
|
||||||
It will usually be imported through the generic SCons.Tool.Tool()
|
|
||||||
selection method.
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Tool/filesystem.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import SCons
|
|
||||||
from SCons.Tool.install import copyFunc
|
|
||||||
|
|
||||||
copyToBuilder, copyAsBuilder = None, None
|
|
||||||
|
|
||||||
def copyto_emitter(target, source, env):
|
|
||||||
""" changes the path of the source to be under the target (which
|
|
||||||
are assumed to be directories.
|
|
||||||
"""
|
|
||||||
n_target = []
|
|
||||||
|
|
||||||
for t in target:
|
|
||||||
n_target = n_target + map( lambda s, t=t: t.File( str( s ) ), source )
|
|
||||||
|
|
||||||
return (n_target, source)
|
|
||||||
|
|
||||||
def copy_action_func(target, source, env):
|
|
||||||
assert( len(target) == len(source) ), "\ntarget: %s\nsource: %s" %(map(str, target),map(str, source))
|
|
||||||
|
|
||||||
for t, s in zip(target, source):
|
|
||||||
if copyFunc(t.get_path(), s.get_path(), env):
|
|
||||||
return 1
|
|
||||||
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def copy_action_str(target, source, env):
|
|
||||||
return env.subst_target_source(env['COPYSTR'], 0, target, source)
|
|
||||||
|
|
||||||
copy_action = SCons.Action.Action( copy_action_func, copy_action_str )
|
|
||||||
|
|
||||||
def generate(env):
|
|
||||||
try:
|
|
||||||
env['BUILDERS']['CopyTo']
|
|
||||||
env['BUILDERS']['CopyAs']
|
|
||||||
except KeyError, e:
|
|
||||||
global copyToBuilder
|
|
||||||
if copyToBuilder is None:
|
|
||||||
copyToBuilder = SCons.Builder.Builder(
|
|
||||||
action = copy_action,
|
|
||||||
target_factory = env.fs.Dir,
|
|
||||||
source_factory = env.fs.Entry,
|
|
||||||
multi = 1,
|
|
||||||
emitter = [ copyto_emitter, ] )
|
|
||||||
|
|
||||||
global copyAsBuilder
|
|
||||||
if copyAsBuilder is None:
|
|
||||||
copyAsBuilder = SCons.Builder.Builder(
|
|
||||||
action = copy_action,
|
|
||||||
target_factory = env.fs.Entry,
|
|
||||||
source_factory = env.fs.Entry )
|
|
||||||
|
|
||||||
env['BUILDERS']['CopyTo'] = copyToBuilder
|
|
||||||
env['BUILDERS']['CopyAs'] = copyAsBuilder
|
|
||||||
|
|
||||||
env['COPYSTR'] = 'Copy file(s): "$SOURCES" to "$TARGETS"'
|
|
||||||
|
|
||||||
def exists(env):
|
|
||||||
return 1
|
|
|
@ -1,57 +0,0 @@
|
||||||
"""SCons.Tool.fortran
|
|
||||||
|
|
||||||
Tool-specific initialization for a generic Posix f77/f90 Fortran compiler.
|
|
||||||
|
|
||||||
There normally shouldn't be any need to import this module directly.
|
|
||||||
It will usually be imported through the generic SCons.Tool.Tool()
|
|
||||||
selection method.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Tool/fortran.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import re
|
|
||||||
import string
|
|
||||||
|
|
||||||
import SCons.Action
|
|
||||||
import SCons.Defaults
|
|
||||||
import SCons.Scanner.Fortran
|
|
||||||
import SCons.Tool
|
|
||||||
import SCons.Util
|
|
||||||
from SCons.Tool.FortranCommon import add_all_to_env, add_fortran_to_env
|
|
||||||
|
|
||||||
compilers = ['f95', 'f90', 'f77']
|
|
||||||
|
|
||||||
def generate(env):
|
|
||||||
add_all_to_env(env)
|
|
||||||
add_fortran_to_env(env)
|
|
||||||
|
|
||||||
fc = env.Detect(compilers) or 'f77'
|
|
||||||
env['SHFORTRAN'] = fc
|
|
||||||
env['FORTRAN'] = fc
|
|
||||||
|
|
||||||
def exists(env):
|
|
||||||
return env.Detect(compilers)
|
|
|
@ -1,84 +0,0 @@
|
||||||
"""SCons.Tool.g++
|
|
||||||
|
|
||||||
Tool-specific initialization for g++.
|
|
||||||
|
|
||||||
There normally shouldn't be any need to import this module directly.
|
|
||||||
It will usually be imported through the generic SCons.Tool.Tool()
|
|
||||||
selection method.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Tool/g++.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import os.path
|
|
||||||
import re
|
|
||||||
import subprocess
|
|
||||||
|
|
||||||
import SCons.Tool
|
|
||||||
import SCons.Util
|
|
||||||
|
|
||||||
cplusplus = __import__('c++', globals(), locals(), [])
|
|
||||||
|
|
||||||
compilers = ['g++']
|
|
||||||
|
|
||||||
def generate(env):
|
|
||||||
"""Add Builders and construction variables for g++ to an Environment."""
|
|
||||||
static_obj, shared_obj = SCons.Tool.createObjBuilders(env)
|
|
||||||
|
|
||||||
cplusplus.generate(env)
|
|
||||||
|
|
||||||
env['CXX'] = env.Detect(compilers)
|
|
||||||
|
|
||||||
# platform specific settings
|
|
||||||
if env['PLATFORM'] == 'aix':
|
|
||||||
env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS -mminimal-toc')
|
|
||||||
env['STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME'] = 1
|
|
||||||
env['SHOBJSUFFIX'] = '$OBJSUFFIX'
|
|
||||||
elif env['PLATFORM'] == 'hpux':
|
|
||||||
env['SHOBJSUFFIX'] = '.pic.o'
|
|
||||||
elif env['PLATFORM'] == 'sunos':
|
|
||||||
env['SHOBJSUFFIX'] = '.pic.o'
|
|
||||||
# determine compiler version
|
|
||||||
if env['CXX']:
|
|
||||||
#pipe = SCons.Action._subproc(env, [env['CXX'], '-dumpversion'],
|
|
||||||
pipe = SCons.Action._subproc(env, [env['CXX'], '--version'],
|
|
||||||
stdin = 'devnull',
|
|
||||||
stderr = 'devnull',
|
|
||||||
stdout = subprocess.PIPE)
|
|
||||||
if pipe.wait() != 0: return
|
|
||||||
# -dumpversion was added in GCC 3.0. As long as we're supporting
|
|
||||||
# GCC versions older than that, we should use --version and a
|
|
||||||
# regular expression.
|
|
||||||
#line = pipe.stdout.read().strip()
|
|
||||||
#if line:
|
|
||||||
# env['CXXVERSION'] = line
|
|
||||||
line = pipe.stdout.readline()
|
|
||||||
match = re.search(r'[0-9]+(\.[0-9]+)+', line)
|
|
||||||
if match:
|
|
||||||
env['CXXVERSION'] = match.group(0)
|
|
||||||
|
|
||||||
def exists(env):
|
|
||||||
return env.Detect(compilers)
|
|
|
@ -1,67 +0,0 @@
|
||||||
"""engine.SCons.Tool.g77
|
|
||||||
|
|
||||||
Tool-specific initialization for g77.
|
|
||||||
|
|
||||||
There normally shouldn't be any need to import this module directly.
|
|
||||||
It will usually be imported through the generic SCons.Tool.Tool()
|
|
||||||
selection method.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Tool/g77.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import SCons.Util
|
|
||||||
from SCons.Tool.FortranCommon import add_all_to_env, add_f77_to_env
|
|
||||||
|
|
||||||
compilers = ['g77', 'f77']
|
|
||||||
|
|
||||||
def generate(env):
|
|
||||||
"""Add Builders and construction variables for g77 to an Environment."""
|
|
||||||
add_all_to_env(env)
|
|
||||||
add_f77_to_env(env)
|
|
||||||
|
|
||||||
fcomp = env.Detect(compilers) or 'g77'
|
|
||||||
if env['PLATFORM'] in ['cygwin', 'win32']:
|
|
||||||
env['SHFORTRANFLAGS'] = SCons.Util.CLVar('$FORTRANFLAGS')
|
|
||||||
env['SHF77FLAGS'] = SCons.Util.CLVar('$F77FLAGS')
|
|
||||||
else:
|
|
||||||
env['SHFORTRANFLAGS'] = SCons.Util.CLVar('$FORTRANFLAGS -fPIC')
|
|
||||||
env['SHF77FLAGS'] = SCons.Util.CLVar('$F77FLAGS -fPIC')
|
|
||||||
|
|
||||||
env['FORTRAN'] = fcomp
|
|
||||||
env['SHFORTRAN'] = '$FORTRAN'
|
|
||||||
|
|
||||||
env['F77'] = fcomp
|
|
||||||
env['SHF77'] = '$F77'
|
|
||||||
|
|
||||||
env['INCFORTRANPREFIX'] = "-I"
|
|
||||||
env['INCFORTRANSUFFIX'] = ""
|
|
||||||
|
|
||||||
env['INCF77PREFIX'] = "-I"
|
|
||||||
env['INCF77SUFFIX'] = ""
|
|
||||||
|
|
||||||
def exists(env):
|
|
||||||
return env.Detect(compilers)
|
|
|
@ -1,47 +0,0 @@
|
||||||
"""SCons.Tool.gas
|
|
||||||
|
|
||||||
Tool-specific initialization for as, the Gnu assembler.
|
|
||||||
|
|
||||||
There normally shouldn't be any need to import this module directly.
|
|
||||||
It will usually be imported through the generic SCons.Tool.Tool()
|
|
||||||
selection method.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Tool/gas.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
as_module = __import__('as', globals(), locals(), [])
|
|
||||||
|
|
||||||
assemblers = ['as', 'gas']
|
|
||||||
|
|
||||||
def generate(env):
|
|
||||||
"""Add Builders and construction variables for as to an Environment."""
|
|
||||||
as_module.generate(env)
|
|
||||||
|
|
||||||
env['AS'] = env.Detect(assemblers) or 'as'
|
|
||||||
|
|
||||||
def exists(env):
|
|
||||||
return env.Detect(assemblers)
|
|
|
@ -1,74 +0,0 @@
|
||||||
"""SCons.Tool.gcc
|
|
||||||
|
|
||||||
Tool-specific initialization for gcc.
|
|
||||||
|
|
||||||
There normally shouldn't be any need to import this module directly.
|
|
||||||
It will usually be imported through the generic SCons.Tool.Tool()
|
|
||||||
selection method.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Tool/gcc.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import cc
|
|
||||||
import os
|
|
||||||
import re
|
|
||||||
import subprocess
|
|
||||||
|
|
||||||
import SCons.Util
|
|
||||||
|
|
||||||
compilers = ['gcc', 'cc']
|
|
||||||
|
|
||||||
def generate(env):
|
|
||||||
"""Add Builders and construction variables for gcc to an Environment."""
|
|
||||||
cc.generate(env)
|
|
||||||
|
|
||||||
env['CC'] = env.Detect(compilers) or 'gcc'
|
|
||||||
if env['PLATFORM'] in ['cygwin', 'win32']:
|
|
||||||
env['SHCCFLAGS'] = SCons.Util.CLVar('$CCFLAGS')
|
|
||||||
else:
|
|
||||||
env['SHCCFLAGS'] = SCons.Util.CLVar('$CCFLAGS -fPIC')
|
|
||||||
# determine compiler version
|
|
||||||
if env['CC']:
|
|
||||||
#pipe = SCons.Action._subproc(env, [env['CC'], '-dumpversion'],
|
|
||||||
pipe = SCons.Action._subproc(env, [env['CC'], '--version'],
|
|
||||||
stdin = 'devnull',
|
|
||||||
stderr = 'devnull',
|
|
||||||
stdout = subprocess.PIPE)
|
|
||||||
if pipe.wait() != 0: return
|
|
||||||
# -dumpversion was added in GCC 3.0. As long as we're supporting
|
|
||||||
# GCC versions older than that, we should use --version and a
|
|
||||||
# regular expression.
|
|
||||||
#line = pipe.stdout.read().strip()
|
|
||||||
#if line:
|
|
||||||
# env['CCVERSION'] = line
|
|
||||||
line = pipe.stdout.readline()
|
|
||||||
match = re.search(r'[0-9]+(\.[0-9]+)+', line)
|
|
||||||
if match:
|
|
||||||
env['CCVERSION'] = match.group(0)
|
|
||||||
|
|
||||||
def exists(env):
|
|
||||||
return env.Detect(compilers)
|
|
|
@ -1,58 +0,0 @@
|
||||||
"""SCons.Tool.gfortran
|
|
||||||
|
|
||||||
Tool-specific initialization for gfortran, the GNU Fortran 95/Fortran
|
|
||||||
2003 compiler.
|
|
||||||
|
|
||||||
There normally shouldn't be any need to import this module directly.
|
|
||||||
It will usually be imported through the generic SCons.Tool.Tool()
|
|
||||||
selection method.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Tool/gfortran.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import SCons.Util
|
|
||||||
|
|
||||||
import fortran
|
|
||||||
|
|
||||||
def generate(env):
|
|
||||||
"""Add Builders and construction variables for gfortran to an
|
|
||||||
Environment."""
|
|
||||||
fortran.generate(env)
|
|
||||||
|
|
||||||
for dialect in ['F77', 'F90', 'FORTRAN', 'F95']:
|
|
||||||
env['%s' % dialect] = 'gfortran'
|
|
||||||
env['SH%s' % dialect] = '$%s' % dialect
|
|
||||||
if env['PLATFORM'] in ['cygwin', 'win32']:
|
|
||||||
env['SH%sFLAGS' % dialect] = SCons.Util.CLVar('$%sFLAGS' % dialect)
|
|
||||||
else:
|
|
||||||
env['SH%sFLAGS' % dialect] = SCons.Util.CLVar('$%sFLAGS -fPIC' % dialect)
|
|
||||||
|
|
||||||
env['INC%sPREFIX' % dialect] = "-I"
|
|
||||||
env['INC%sSUFFIX' % dialect] = ""
|
|
||||||
|
|
||||||
def exists(env):
|
|
||||||
return env.Detect('gfortran')
|
|
|
@ -1,57 +0,0 @@
|
||||||
"""SCons.Tool.gnulink
|
|
||||||
|
|
||||||
Tool-specific initialization for the gnu linker.
|
|
||||||
|
|
||||||
There normally shouldn't be any need to import this module directly.
|
|
||||||
It will usually be imported through the generic SCons.Tool.Tool()
|
|
||||||
selection method.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Tool/gnulink.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import SCons.Util
|
|
||||||
|
|
||||||
import link
|
|
||||||
|
|
||||||
linkers = ['g++', 'gcc']
|
|
||||||
|
|
||||||
def generate(env):
|
|
||||||
"""Add Builders and construction variables for gnulink to an Environment."""
|
|
||||||
link.generate(env)
|
|
||||||
|
|
||||||
if env['PLATFORM'] == 'hpux':
|
|
||||||
env['SHLINKFLAGS'] = SCons.Util.CLVar('$LINKFLAGS -shared -fPIC')
|
|
||||||
|
|
||||||
# __RPATH is set to $_RPATH in the platform specification if that
|
|
||||||
# platform supports it.
|
|
||||||
env.Append(LINKFLAGS=['$__RPATH'])
|
|
||||||
env['RPATHPREFIX'] = '-Wl,-rpath='
|
|
||||||
env['RPATHSUFFIX'] = ''
|
|
||||||
env['_RPATH'] = '${_concat(RPATHPREFIX, RPATH, RPATHSUFFIX, __env__)}'
|
|
||||||
|
|
||||||
def exists(env):
|
|
||||||
return env.Detect(linkers)
|
|
|
@ -1,75 +0,0 @@
|
||||||
"""SCons.Tool.gs
|
|
||||||
|
|
||||||
Tool-specific initialization for Ghostscript.
|
|
||||||
|
|
||||||
There normally shouldn't be any need to import this module directly.
|
|
||||||
It will usually be imported through the generic SCons.Tool.Tool()
|
|
||||||
selection method.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Tool/gs.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import SCons.Action
|
|
||||||
import SCons.Platform
|
|
||||||
import SCons.Util
|
|
||||||
|
|
||||||
# Ghostscript goes by different names on different platforms...
|
|
||||||
platform = SCons.Platform.platform_default()
|
|
||||||
|
|
||||||
if platform == 'os2':
|
|
||||||
gs = 'gsos2'
|
|
||||||
elif platform == 'win32':
|
|
||||||
gs = 'gswin32c'
|
|
||||||
else:
|
|
||||||
gs = 'gs'
|
|
||||||
|
|
||||||
GhostscriptAction = None
|
|
||||||
|
|
||||||
def generate(env):
|
|
||||||
"""Add Builders and construction variables for Ghostscript to an
|
|
||||||
Environment."""
|
|
||||||
|
|
||||||
global GhostscriptAction
|
|
||||||
if GhostscriptAction is None:
|
|
||||||
GhostscriptAction = SCons.Action.Action('$GSCOM', '$GSCOMSTR')
|
|
||||||
|
|
||||||
import pdf
|
|
||||||
pdf.generate(env)
|
|
||||||
|
|
||||||
bld = env['BUILDERS']['PDF']
|
|
||||||
bld.add_action('.ps', GhostscriptAction)
|
|
||||||
|
|
||||||
env['GS'] = gs
|
|
||||||
env['GSFLAGS'] = SCons.Util.CLVar('-dNOPAUSE -dBATCH -sDEVICE=pdfwrite')
|
|
||||||
env['GSCOM'] = '$GS $GSFLAGS -sOutputFile=$TARGET $SOURCES'
|
|
||||||
|
|
||||||
|
|
||||||
def exists(env):
|
|
||||||
if env.has_key('PS2PDF'):
|
|
||||||
return env.Detect(env['PS2PDF'])
|
|
||||||
else:
|
|
||||||
return env.Detect(gs) or SCons.Util.WhereIs(gs)
|
|
|
@ -1,79 +0,0 @@
|
||||||
"""SCons.Tool.hpc++
|
|
||||||
|
|
||||||
Tool-specific initialization for c++ on HP/UX.
|
|
||||||
|
|
||||||
There normally shouldn't be any need to import this module directly.
|
|
||||||
It will usually be imported through the generic SCons.Tool.Tool()
|
|
||||||
selection method.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Tool/hpc++.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import os.path
|
|
||||||
import string
|
|
||||||
|
|
||||||
import SCons.Util
|
|
||||||
|
|
||||||
cplusplus = __import__('c++', globals(), locals(), [])
|
|
||||||
|
|
||||||
acc = None
|
|
||||||
|
|
||||||
# search for the acc compiler and linker front end
|
|
||||||
|
|
||||||
try:
|
|
||||||
dirs = os.listdir('/opt')
|
|
||||||
except (IOError, OSError):
|
|
||||||
# Not being able to read the directory because it doesn't exist
|
|
||||||
# (IOError) or isn't readable (OSError) is okay.
|
|
||||||
dirs = []
|
|
||||||
|
|
||||||
for dir in dirs:
|
|
||||||
cc = '/opt/' + dir + '/bin/aCC'
|
|
||||||
if os.path.exists(cc):
|
|
||||||
acc = cc
|
|
||||||
break
|
|
||||||
|
|
||||||
|
|
||||||
def generate(env):
|
|
||||||
"""Add Builders and construction variables for g++ to an Environment."""
|
|
||||||
cplusplus.generate(env)
|
|
||||||
|
|
||||||
if acc:
|
|
||||||
env['CXX'] = acc or 'aCC'
|
|
||||||
env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS +Z')
|
|
||||||
# determine version of aCC
|
|
||||||
line = os.popen(acc + ' -V 2>&1').readline().rstrip()
|
|
||||||
if string.find(line, 'aCC: HP ANSI C++') == 0:
|
|
||||||
env['CXXVERSION'] = string.split(line)[-1]
|
|
||||||
|
|
||||||
if env['PLATFORM'] == 'cygwin':
|
|
||||||
env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS')
|
|
||||||
else:
|
|
||||||
env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS +Z')
|
|
||||||
|
|
||||||
def exists(env):
|
|
||||||
return acc
|
|
|
@ -1,47 +0,0 @@
|
||||||
"""SCons.Tool.hpcc
|
|
||||||
|
|
||||||
Tool-specific initialization for HP aCC and cc.
|
|
||||||
|
|
||||||
There normally shouldn't be any need to import this module directly.
|
|
||||||
It will usually be imported through the generic SCons.Tool.Tool()
|
|
||||||
selection method.
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Tool/hpcc.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import SCons.Util
|
|
||||||
|
|
||||||
import cc
|
|
||||||
|
|
||||||
def generate(env):
|
|
||||||
"""Add Builders and construction variables for aCC & cc to an Environment."""
|
|
||||||
cc.generate(env)
|
|
||||||
|
|
||||||
env['CXX'] = 'aCC'
|
|
||||||
env['SHCCFLAGS'] = SCons.Util.CLVar('$CCFLAGS +Z')
|
|
||||||
|
|
||||||
def exists(env):
|
|
||||||
return env.Detect('aCC')
|
|
|
@ -1,71 +0,0 @@
|
||||||
"""SCons.Tool.hplink
|
|
||||||
|
|
||||||
Tool-specific initialization for the HP linker.
|
|
||||||
|
|
||||||
There normally shouldn't be any need to import this module directly.
|
|
||||||
It will usually be imported through the generic SCons.Tool.Tool()
|
|
||||||
selection method.
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Tool/hplink.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import os
|
|
||||||
import os.path
|
|
||||||
|
|
||||||
import SCons.Util
|
|
||||||
|
|
||||||
import link
|
|
||||||
|
|
||||||
ccLinker = None
|
|
||||||
|
|
||||||
# search for the acc compiler and linker front end
|
|
||||||
|
|
||||||
try:
|
|
||||||
dirs = os.listdir('/opt')
|
|
||||||
except (IOError, OSError):
|
|
||||||
# Not being able to read the directory because it doesn't exist
|
|
||||||
# (IOError) or isn't readable (OSError) is okay.
|
|
||||||
dirs = []
|
|
||||||
|
|
||||||
for dir in dirs:
|
|
||||||
linker = '/opt/' + dir + '/bin/aCC'
|
|
||||||
if os.path.exists(linker):
|
|
||||||
ccLinker = linker
|
|
||||||
break
|
|
||||||
|
|
||||||
def generate(env):
|
|
||||||
"""
|
|
||||||
Add Builders and construction variables for Visual Age linker to
|
|
||||||
an Environment.
|
|
||||||
"""
|
|
||||||
link.generate(env)
|
|
||||||
|
|
||||||
env['LINKFLAGS'] = SCons.Util.CLVar('-Wl,+s -Wl,+vnocompatwarnings')
|
|
||||||
env['SHLINKFLAGS'] = SCons.Util.CLVar('$LINKFLAGS -b')
|
|
||||||
env['SHLIBSUFFIX'] = '.sl'
|
|
||||||
|
|
||||||
def exists(env):
|
|
||||||
return ccLinker
|
|
|
@ -1,53 +0,0 @@
|
||||||
"""engine.SCons.Tool.icc
|
|
||||||
|
|
||||||
Tool-specific initialization for the OS/2 icc compiler.
|
|
||||||
|
|
||||||
There normally shouldn't be any need to import this module directly.
|
|
||||||
It will usually be imported through the generic SCons.Tool.Tool()
|
|
||||||
selection method.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Tool/icc.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import cc
|
|
||||||
|
|
||||||
def generate(env):
|
|
||||||
"""Add Builders and construction variables for the OS/2 to an Environment."""
|
|
||||||
cc.generate(env)
|
|
||||||
|
|
||||||
env['CC'] = 'icc'
|
|
||||||
env['CCCOM'] = '$CC $CFLAGS $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS /c $SOURCES /Fo$TARGET'
|
|
||||||
env['CXXCOM'] = '$CXX $CXXFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS /c $SOURCES /Fo$TARGET'
|
|
||||||
env['CPPDEFPREFIX'] = '/D'
|
|
||||||
env['CPPDEFSUFFIX'] = ''
|
|
||||||
env['INCPREFIX'] = '/I'
|
|
||||||
env['INCSUFFIX'] = ''
|
|
||||||
env['CFILESUFFIX'] = '.c'
|
|
||||||
env['CXXFILESUFFIX'] = '.cc'
|
|
||||||
|
|
||||||
def exists(env):
|
|
||||||
return env.Detect('icc')
|
|
|
@ -1,46 +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, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Tool/icl.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import SCons.Tool.intelc
|
|
||||||
|
|
||||||
# This has been completely superceded by intelc.py, which can
|
|
||||||
# handle both Windows and Linux versions.
|
|
||||||
|
|
||||||
def generate(*args, **kw):
|
|
||||||
"""Add Builders and construction variables for icl to an Environment."""
|
|
||||||
return apply(SCons.Tool.intelc.generate, args, kw)
|
|
||||||
|
|
||||||
def exists(*args, **kw):
|
|
||||||
return apply(SCons.Tool.intelc.exists, args, kw)
|
|
|
@ -1,66 +0,0 @@
|
||||||
"""SCons.Tool.ifl
|
|
||||||
|
|
||||||
Tool-specific initialization for the Intel Fortran compiler.
|
|
||||||
|
|
||||||
There normally shouldn't be any need to import this module directly.
|
|
||||||
It will usually be imported through the generic SCons.Tool.Tool()
|
|
||||||
selection method.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Tool/ifl.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import SCons.Defaults
|
|
||||||
from SCons.Scanner.Fortran import FortranScan
|
|
||||||
from FortranCommon import add_all_to_env
|
|
||||||
|
|
||||||
def generate(env):
|
|
||||||
"""Add Builders and construction variables for ifl to an Environment."""
|
|
||||||
fscan = FortranScan("FORTRANPATH")
|
|
||||||
SCons.Tool.SourceFileScanner.add_scanner('.i', fscan)
|
|
||||||
SCons.Tool.SourceFileScanner.add_scanner('.i90', fscan)
|
|
||||||
|
|
||||||
if not env.has_key('FORTRANFILESUFFIXES'):
|
|
||||||
env['FORTRANFILESUFFIXES'] = ['.i']
|
|
||||||
else:
|
|
||||||
env['FORTRANFILESUFFIXES'].append('.i')
|
|
||||||
|
|
||||||
if not env.has_key('F90FILESUFFIXES'):
|
|
||||||
env['F90FILESUFFIXES'] = ['.i90']
|
|
||||||
else:
|
|
||||||
env['F90FILESUFFIXES'].append('.i90')
|
|
||||||
|
|
||||||
add_all_to_env(env)
|
|
||||||
|
|
||||||
env['FORTRAN'] = 'ifl'
|
|
||||||
env['SHFORTRAN'] = '$FORTRAN'
|
|
||||||
env['FORTRANCOM'] = '$FORTRAN $FORTRANFLAGS $_FORTRANINCFLAGS /c $SOURCES /Fo$TARGET'
|
|
||||||
env['FORTRANPPCOM'] = '$FORTRAN $FORTRANFLAGS $CPPFLAGS $_CPPDEFFLAGS $_FORTRANINCFLAGS /c $SOURCES /Fo$TARGET'
|
|
||||||
env['SHFORTRANCOM'] = '$SHFORTRAN $SHFORTRANFLAGS $_FORTRANINCFLAGS /c $SOURCES /Fo$TARGET'
|
|
||||||
env['SHFORTRANPPCOM'] = '$SHFORTRAN $SHFORTRANFLAGS $CPPFLAGS $_CPPDEFFLAGS $_FORTRANINCFLAGS /c $SOURCES /Fo$TARGET'
|
|
||||||
|
|
||||||
def exists(env):
|
|
||||||
return env.Detect('ifl')
|
|
|
@ -1,83 +0,0 @@
|
||||||
"""SCons.Tool.ifort
|
|
||||||
|
|
||||||
Tool-specific initialization for newer versions of the Intel Fortran Compiler
|
|
||||||
for Linux/Windows (and possibly Mac OS X).
|
|
||||||
|
|
||||||
There normally shouldn't be any need to import this module directly.
|
|
||||||
It will usually be imported through the generic SCons.Tool.Tool()
|
|
||||||
selection method.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Tool/ifort.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import string
|
|
||||||
|
|
||||||
import SCons.Defaults
|
|
||||||
from SCons.Scanner.Fortran import FortranScan
|
|
||||||
from FortranCommon import add_all_to_env
|
|
||||||
|
|
||||||
def generate(env):
|
|
||||||
"""Add Builders and construction variables for ifort to an Environment."""
|
|
||||||
# ifort supports Fortran 90 and Fortran 95
|
|
||||||
# Additionally, ifort recognizes more file extensions.
|
|
||||||
fscan = FortranScan("FORTRANPATH")
|
|
||||||
SCons.Tool.SourceFileScanner.add_scanner('.i', fscan)
|
|
||||||
SCons.Tool.SourceFileScanner.add_scanner('.i90', fscan)
|
|
||||||
|
|
||||||
if not env.has_key('FORTRANFILESUFFIXES'):
|
|
||||||
env['FORTRANFILESUFFIXES'] = ['.i']
|
|
||||||
else:
|
|
||||||
env['FORTRANFILESUFFIXES'].append('.i')
|
|
||||||
|
|
||||||
if not env.has_key('F90FILESUFFIXES'):
|
|
||||||
env['F90FILESUFFIXES'] = ['.i90']
|
|
||||||
else:
|
|
||||||
env['F90FILESUFFIXES'].append('.i90')
|
|
||||||
|
|
||||||
add_all_to_env(env)
|
|
||||||
|
|
||||||
fc = 'ifort'
|
|
||||||
|
|
||||||
for dialect in ['F77', 'F90', 'FORTRAN', 'F95']:
|
|
||||||
env['%s' % dialect] = fc
|
|
||||||
env['SH%s' % dialect] = '$%s' % dialect
|
|
||||||
env['SH%sFLAGS' % dialect] = SCons.Util.CLVar('$%sFLAGS -fPIC' % dialect)
|
|
||||||
|
|
||||||
if env['PLATFORM'] == 'win32':
|
|
||||||
# On Windows, the ifort compiler specifies the object on the
|
|
||||||
# command line with -object:, not -o. Massage the necessary
|
|
||||||
# command-line construction variables.
|
|
||||||
for dialect in ['F77', 'F90', 'FORTRAN', 'F95']:
|
|
||||||
for var in ['%sCOM' % dialect, '%sPPCOM' % dialect,
|
|
||||||
'SH%sCOM' % dialect, 'SH%sPPCOM' % dialect]:
|
|
||||||
env[var] = string.replace(env[var], '-o $TARGET', '-object:$TARGET')
|
|
||||||
env['FORTRANMODDIRPREFIX'] = "/module:"
|
|
||||||
else:
|
|
||||||
env['FORTRANMODDIRPREFIX'] = "-module "
|
|
||||||
|
|
||||||
def exists(env):
|
|
||||||
return env.Detect('ifort')
|
|
|
@ -1,53 +0,0 @@
|
||||||
"""SCons.Tool.ilink
|
|
||||||
|
|
||||||
Tool-specific initialization for the OS/2 ilink linker.
|
|
||||||
|
|
||||||
There normally shouldn't be any need to import this module directly.
|
|
||||||
It will usually be imported through the generic SCons.Tool.Tool()
|
|
||||||
selection method.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files (the
|
|
||||||
# "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
# permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
# the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included
|
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "src/engine/SCons/Tool/ilink.py 3842 2008/12/20 22:59:52 scons"
|
|
||||||
|
|
||||||
import SCons.Defaults
|
|
||||||
import SCons.Tool
|
|
||||||
import SCons.Util
|
|
||||||
|
|
||||||
def generate(env):
|
|
||||||
"""Add Builders and construction variables for ilink to an Environment."""
|
|
||||||
SCons.Tool.createProgBuilder(env)
|
|
||||||
|
|
||||||
env['LINK'] = 'ilink'
|
|
||||||
env['LINKFLAGS'] = SCons.Util.CLVar('')
|
|
||||||
env['LINKCOM'] = '$LINK $LINKFLAGS /O:$TARGET $SOURCES $( $_LIBDIRFLAGS $) $_LIBFLAGS'
|
|
||||||
env['LIBDIRPREFIX']='/LIBPATH:'
|
|
||||||
env['LIBDIRSUFFIX']=''
|
|
||||||
env['LIBLINKPREFIX']=''
|
|
||||||
env['LIBLINKSUFFIX']='$LIBSUFFIX'
|
|
||||||
|
|
||||||
def exists(env):
|
|
||||||
return env.Detect('ilink')
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue