summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorWilliam Deegan <bill@baddogconsulting.com>2019-12-10 16:24:13 (GMT)
committerGitHub <noreply@github.com>2019-12-10 16:24:13 (GMT)
commit00c82b641c13ede400982f51b75f01938c99353b (patch)
tree2a217fa865d49438b730b4f2472f168719d726ac /src
parentdc8aaebf2271cbd78edeeda923ce2c8acd67f946 (diff)
parent392d323e36bf8c80c7a6d43160148359cfae8ff6 (diff)
downloadSCons-00c82b641c13ede400982f51b75f01938c99353b.zip
SCons-00c82b641c13ede400982f51b75f01938c99353b.tar.gz
SCons-00c82b641c13ede400982f51b75f01938c99353b.tar.bz2
Merge branch 'master' into py3-doctasks
Diffstat (limited to 'src')
-rwxr-xr-xsrc/CHANGES.txt11
-rw-r--r--src/engine/SCons/ActionTests.py4
-rw-r--r--src/engine/SCons/Environment.py41
-rw-r--r--src/engine/SCons/Environment.xml22
-rw-r--r--src/engine/SCons/Platform/win32.py58
-rw-r--r--src/engine/SCons/SConfTests.py28
-rw-r--r--src/engine/SCons/Script/Main.py7
-rw-r--r--src/engine/SCons/Script/Main.xml37
-rw-r--r--src/engine/SCons/Script/SConsOptions.py2
-rw-r--r--src/engine/SCons/Tool/MSCommon/vc.py9
10 files changed, 154 insertions, 65 deletions
diff --git a/src/CHANGES.txt b/src/CHANGES.txt
index e24555d..47b63ee 100755
--- a/src/CHANGES.txt
+++ b/src/CHANGES.txt
@@ -4,6 +4,8 @@
Change Log
+NOTE: Please add your name below (and your changes) alphabetically by last name.
+
RELEASE VERSION/DATE TO BE FILLED IN LATER
From Edoardo Bezzeccheri
@@ -16,6 +18,15 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER
From Tim Gates
- Resolved a typo in engine.SCons.Tool
+ From Adam Gross:
+ - Resolved a race condition in multithreaded Windows builds with Python 2
+ in the case where a child process is spawned while a Python action has a
+ file open. Original author: Ryan Beasley.
+
+ From Jason Kenny
+ - Update Command() function to accept target_scanner, source_factory, and target_factory arguments.
+ This makes Command act more like a one-off builder.
+
From Ivan Kravets
- Added support for "-imacros" to ParseFlags
diff --git a/src/engine/SCons/ActionTests.py b/src/engine/SCons/ActionTests.py
index 3054368..3303750 100644
--- a/src/engine/SCons/ActionTests.py
+++ b/src/engine/SCons/ActionTests.py
@@ -1208,10 +1208,6 @@ class CommandActionTestCase(unittest.TestCase):
# Newer cygwin seems to return 126 for following
expect_nonexecutable_file = 126
expect_nonexecutable_dir = 127
- elif sys.platform.find('sunos') != -1:
- expect_nonexistent = 1
- expect_nonexecutable_file = 1
- expect_nonexecutable_dir = 1
else:
expect_nonexistent = 127
expect_nonexecutable_file = 126
diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py
index 1296f54..916ebc4 100644
--- a/src/engine/SCons/Environment.py
+++ b/src/engine/SCons/Environment.py
@@ -1983,13 +1983,42 @@ class Base(SubstitutionEnvironment):
be any type that the Builder constructor will accept
for an action."""
bkw = {
- 'action' : action,
- 'target_factory' : self.fs.Entry,
- 'source_factory' : self.fs.Entry,
+ 'action': action,
+ 'target_factory': self.fs.Entry,
+ 'source_factory': self.fs.Entry,
}
- try: bkw['source_scanner'] = kw['source_scanner']
- except KeyError: pass
- else: del kw['source_scanner']
+ # source scanner
+ try:
+ bkw['source_scanner'] = kw['source_scanner']
+ except KeyError:
+ pass
+ else:
+ del kw['source_scanner']
+
+ # target scanner
+ try:
+ bkw['target_scanner'] = kw['target_scanner']
+ except KeyError:
+ pass
+ else:
+ del kw['target_scanner']
+
+ # source factory
+ try:
+ bkw['source_factory'] = kw['source_factory']
+ except KeyError:
+ pass
+ else:
+ del kw['source_factory']
+
+ # target factory
+ try:
+ bkw['target_factory'] = kw['target_factory']
+ except KeyError:
+ pass
+ else:
+ del kw['target_factory']
+
bld = SCons.Builder.Builder(**bkw)
return bld(self, target, source, **kw)
diff --git a/src/engine/SCons/Environment.xml b/src/engine/SCons/Environment.xml
index 0963fd2..73c347e 100644
--- a/src/engine/SCons/Environment.xml
+++ b/src/engine/SCons/Environment.xml
@@ -937,19 +937,29 @@ for a single special-case build.
</para>
<para>
-As a special case, the
-<varname>source_scanner</varname>
-keyword argument can
+&b-Command; builder accepts
+<varname>source_scanner</varname>,
+<varname>target_scanner</varname>,
+<varname>source_factory</varname>, and
+<varname>target_factory</varname>
+keyword arguments. The *_scanner args can
be used to specify
a Scanner object
-that will be used to scan the sources.
-(The global
+that will be used to apply a custom
+scanner for a source or target.
+For example, the global
<literal>DirScanner</literal>
object can be used
if any of the sources will be directories
that must be scanned on-disk for
changes to files that aren't
-already specified in other Builder of function calls.)
+already specified in other Builder of function calls.
+The *_factory args take a factory function that the
+Command will use to turn any sources or targets
+specified as strings into SCons Nodes.
+See the sections "Builder Objects"
+below, for more information about how these
+args work in a Builder.
</para>
<para>
diff --git a/src/engine/SCons/Platform/win32.py b/src/engine/SCons/Platform/win32.py
index 0a3b199..77c048e 100644
--- a/src/engine/SCons/Platform/win32.py
+++ b/src/engine/SCons/Platform/win32.py
@@ -51,10 +51,6 @@ 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" + \
@@ -66,28 +62,44 @@ except AttributeError:
else:
parallel_msg = None
- _builtin_open = open
+ if sys.version_info.major == 2:
+ import __builtin__
+
+ _builtin_file = __builtin__.file
+ _builtin_open = __builtin__.open
+
+ def _scons_fixup_mode(mode):
+ """Adjust 'mode' to mark handle as non-inheritable.
+
+ SCons is multithreaded, so allowing handles to be inherited by
+ children opens us up to races, where (e.g.) processes spawned by
+ the Taskmaster may inherit and retain references to files opened
+ by other threads. This may lead to sharing violations and,
+ ultimately, build failures.
+
+ By including 'N' as part of fopen's 'mode' parameter, all file
+ handles returned from these functions are atomically marked as
+ non-inheritable.
+ """
+ if not mode:
+ # Python's default is 'r'.
+ # https://docs.python.org/2/library/functions.html#open
+ mode = 'rN'
+ elif 'N' not in mode:
+ mode += 'N'
+ return mode
- def _scons_open(*args, **kw):
- fp = _builtin_open(*args, **kw)
- win32api.SetHandleInformation(msvcrt.get_osfhandle(fp.fileno()),
- win32con.HANDLE_FLAG_INHERIT,
- 0)
- return fp
+ class _scons_file(_builtin_file):
+ def __init__(self, name, mode=None, *args, **kwargs):
+ _builtin_file.__init__(self, name, _scons_fixup_mode(mode),
+ *args, **kwargs)
- open = _scons_open
+ def _scons_open(name, mode=None, *args, **kwargs):
+ return _builtin_open(name, _scons_fixup_mode(mode),
+ *args, **kwargs)
- if sys.version_info.major == 2:
- _builtin_file = file
- class _scons_file(_builtin_file):
- def __init__(self, *args, **kw):
- _builtin_file.__init__(self, *args, **kw)
- win32api.SetHandleInformation(msvcrt.get_osfhandle(self.fileno()),
- win32con.HANDLE_FLAG_INHERIT, 0)
- file = _scons_file
- else:
- # No longer needed for python 3.4 and above. Files are opened non sharable
- pass
+ __builtin__.file = _scons_file
+ __builtin__.open = _scons_open
diff --git a/src/engine/SCons/SConfTests.py b/src/engine/SCons/SConfTests.py
index f770450..787138e 100644
--- a/src/engine/SCons/SConfTests.py
+++ b/src/engine/SCons/SConfTests.py
@@ -56,6 +56,18 @@ class SConfTestCase(unittest.TestCase):
os.chdir(self.save_cwd)
def _resetSConfState(self):
+ if sys.platform in ['cygwin', 'win32'] and sys.version_info.major == 2:
+ # On Windows with Python2, SCons.Platform.win32 redefines the
+ # built-in file() and open() functions to disable handle
+ # inheritance. Because we are unloading all SCons modules other
+ # than SCons.Compat, SCons.Platform.win32 will lose the variables
+ # it needs. As a result, we should reset the file() and open()
+ # functions to their original built-in versions.
+ import __builtin__
+ import SCons.Platform.win32
+ __builtin__.file = SCons.Platform.win32._builtin_file
+ __builtin__.open = SCons.Platform.win32._builtin_open
+
# Ok, this is tricky, and i do not know, if everything is sane.
# We try to reset scons' state (including all global variables)
import SCons.SConsign
@@ -90,22 +102,6 @@ class SConfTestCase(unittest.TestCase):
global existing_lib
existing_lib = 'm'
- if sys.platform in ['cygwin', 'win32']:
- # On Windows, SCons.Platform.win32 redefines the builtin
- # file() and open() functions to close the file handles.
- # This interferes with the unittest.py infrastructure in
- # some way. Just sidestep the issue by restoring the
- # original builtin functions whenever we have to reset
- # all of our global state.
-
- import SCons.Platform.win32
-
- try:
- file = SCons.Platform.win32._builtin_file
- open = SCons.Platform.win32._builtin_open
- except AttributeError:
- pass
-
def _baseTryXXX(self, TryFunc):
# TryCompile and TryLink are much the same, so we can test them
# in one method, we pass the function as a string ('TryCompile',
diff --git a/src/engine/SCons/Script/Main.py b/src/engine/SCons/Script/Main.py
index 58dbf64..238a828 100644
--- a/src/engine/SCons/Script/Main.py
+++ b/src/engine/SCons/Script/Main.py
@@ -211,10 +211,9 @@ class BuildTask(SCons.Taskmaster.OutOfDateTask):
last_command_end = finish_time
cumulative_command_time = cumulative_command_time+finish_time-start_time
if print_action_timestamps:
- sys.stdout.write("Command execution start time: %s: %f seconds\n"%(str(self.node), start_time))
+ sys.stdout.write("Command execution start timestamp: %s: %f\n"%(str(self.node), start_time))
+ sys.stdout.write("Command execution end timestamp: %s: %f\n"%(str(self.node), finish_time))
sys.stdout.write("Command execution time: %s: %f seconds\n"%(str(self.node), finish_time-start_time))
- if print_action_timestamps:
- sys.stdout.write("Command execution stop time: %s: %f seconds\n"%(str(self.node), finish_time))
def do_failed(self, status=2):
_BuildFailures.append(self.exception[1])
@@ -679,7 +678,7 @@ def _set_debug_values(options):
options.tree_printers.append(TreePrinter(status=True))
if "time" in debug_values:
print_time = 1
- if "action_timestamps" in debug_values:
+ if "action-timestamps" in debug_values:
print_time = 1
print_action_timestamps = 1
if "tree" in debug_values:
diff --git a/src/engine/SCons/Script/Main.xml b/src/engine/SCons/Script/Main.xml
index 83d9605..5c68dee 100644
--- a/src/engine/SCons/Script/Main.xml
+++ b/src/engine/SCons/Script/Main.xml
@@ -33,11 +33,11 @@ See its __doc__ string for a discussion of the format.
This function adds a new command-line option to be recognized.
The specified
<varname>arguments</varname>
-are the same as supported by the standard Python
-<function>optparse.add_option</function>()
-method (with a few additional capabilities noted below);
+are the same as supported by the <function>add_option</function>
+method in the standard Python library module <emphasis>optparse</emphasis>,
+with a few additional capabilities noted below;
see the documentation for
-<literal>optparse</literal>
+<emphasis>optparse</emphasis>
for a thorough discussion of its option-processing capabities.
</para>
@@ -78,12 +78,22 @@ the option will have a default value of
</para>
<para>
+Unlike regular <emphasis>optparse</emphasis>, option names
+added via <function>AddOption</function> must be matched
+exactly, the automatic matching of abbreviations on the
+command line for long options is not supported.
+To allow specific abbreviations,
+include them in the &f-AddOption; call.
+</para>
+
+<para>
Once a new command-line option has been added with
&f-AddOption;,
the option value may be accessed using
&f-GetOption;
or
<function>env.GetOption</function>().
+<!--
The value may also be set, using
&f-SetOption;
or
@@ -95,6 +105,9 @@ Note, however, that a
value specified on the command line will
<emphasis>always</emphasis>
override a value set by any SConscript file.
+-->
+&f-SetOption; is not currently supported for
+options added with &f-AddOption;.
</para>
<para>
@@ -133,6 +146,22 @@ AddOption('--prefix',
help='installation prefix')
env = Environment(PREFIX = GetOption('prefix'))
</example_commands>
+
+<note>
+<para>
+While &AddOption; behaves like
+<function>add_option</function>,
+from the <emphasis>optparse</emphasis> module,
+the behavior of options added by &AddOption;
+which take arguments is underfined in
+<command>scons</command> if whitespace
+(rather than an <literal>=</literal> sign) is used as
+the separator on the command line when
+the option is invoked.
+Such usage should be avoided.
+</para>
+</note>
+
</summary>
</scons_function>
diff --git a/src/engine/SCons/Script/SConsOptions.py b/src/engine/SCons/Script/SConsOptions.py
index 7b5d523..66c7239 100644
--- a/src/engine/SCons/Script/SConsOptions.py
+++ b/src/engine/SCons/Script/SConsOptions.py
@@ -622,7 +622,7 @@ def Parser(version):
debug_options = ["count", "duplicate", "explain", "findlibs",
"includes", "memoizer", "memory", "objects",
"pdb", "prepare", "presub", "stacktrace",
- "time", "action_timestamps"]
+ "time", "action-timestamps"]
def opt_debug(option, opt, value__, parser,
debug_options=debug_options,
diff --git a/src/engine/SCons/Tool/MSCommon/vc.py b/src/engine/SCons/Tool/MSCommon/vc.py
index 4f6048d..86bdbe0 100644
--- a/src/engine/SCons/Tool/MSCommon/vc.py
+++ b/src/engine/SCons/Tool/MSCommon/vc.py
@@ -161,11 +161,18 @@ def get_host_target(env):
if not host_platform:
host_platform = platform.machine()
+ # Solaris returns i86pc for both 32 and 64 bit architectures
+ if host_platform == "i86pc":
+ if platform.architecture()[0] == "64bit":
+ host_platform = "amd64"
+ else:
+ host_platform = "x86"
+
# Retain user requested TARGET_ARCH
req_target_platform = env.get('TARGET_ARCH')
debug('get_host_target() req_target_platform:%s'%req_target_platform)
- if req_target_platform:
+ if req_target_platform:
# If user requested a specific platform then only try that one.
target_platform = req_target_platform
else: