summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xCHANGES.txt7
-rwxr-xr-xRELEASE.txt52
-rw-r--r--SCons/Environment.py35
-rw-r--r--SCons/EnvironmentTests.py54
-rw-r--r--SCons/Tool/MSCommon/vs.py2
-rw-r--r--SCons/Tool/docbook/__init__.py27
-rw-r--r--doc/man/scons.xml167
-rw-r--r--doc/man/sconsign.xml139
-rw-r--r--doc/user/MANIFEST1
-rw-r--r--doc/user/caching.xml58
-rw-r--r--doc/user/external.xml158
-rw-r--r--doc/user/main.xml18
-rw-r--r--doc/user/misc.xml65
-rw-r--r--doc/user/sconf.xml24
-rw-r--r--test/Docbook/basedir/slideshtml/image/.exclude_tests1
-rw-r--r--test/Docbook/basedir/slideshtml/image/SConstruct11
-rw-r--r--test/Docbook/basedir/slideshtml/image/SConstruct.cmd11
-rw-r--r--test/Docbook/basedir/slideshtml/image/slides.xsl18
-rw-r--r--test/Docbook/basedir/slideshtml/image/virtns.xml33
-rw-r--r--test/Docbook/basedir/slideshtml/image/xsltver.py20
-rw-r--r--test/Docbook/basedir/slideshtml/slideshtml.py7
-rw-r--r--test/Docbook/basedir/slideshtml/slideshtml_cmd.py7
-rw-r--r--test/Docbook/basic/slideshtml/image/.exclude_tests1
-rw-r--r--test/Docbook/basic/slideshtml/image/SConstruct11
-rw-r--r--test/Docbook/basic/slideshtml/image/SConstruct.cmd11
-rw-r--r--test/Docbook/basic/slideshtml/image/virtns.xml33
-rw-r--r--test/Docbook/basic/slideshtml/image/xsltver.py20
-rw-r--r--test/Docbook/basic/slideshtml/slideshtml.py7
-rw-r--r--test/Docbook/basic/slideshtml/slideshtml_cmd.py7
-rw-r--r--test/Docbook/rootname/slideshtml/image/.exclude_tests1
-rw-r--r--test/Docbook/rootname/slideshtml/image/SConstruct11
-rw-r--r--test/Docbook/rootname/slideshtml/image/slides.xsl18
-rw-r--r--test/Docbook/rootname/slideshtml/image/virtns.xml33
-rw-r--r--test/Docbook/rootname/slideshtml/image/xsltver.py20
-rw-r--r--test/Docbook/rootname/slideshtml/slideshtml.py7
-rw-r--r--test/Interactive/configure.py76
-rw-r--r--test/MSVS/vs-14.0-exec.py1
-rw-r--r--test/MSVS/vs-14.0Exp-exec.py1
-rw-r--r--test/MSVS/vs-14.1-exec.py1
-rw-r--r--test/MSVS/vs-14.2-exec.py1
-rw-r--r--test/fixture/no_msvc/no_msvcs_sconstruct.py2
-rw-r--r--testing/framework/test-framework.rst58
42 files changed, 862 insertions, 373 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index 020e17b91..51a40c834 100755
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -38,6 +38,11 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER
(GH Issue #3699).
- MSVC updates: An MSVC 6.0 installation now appears in the installed versions list
when msvc debug output is enabled (GH Issue #3699).
+ - MSVS test updates: Tests for building a program using generated MSVS project and
+ solution files using MSVS 2015 and later now work as expected on x86 hosts.
+ - Test update: Reduce the number of "false negative" test failures for the interactive
+ configuration test (test/interactive/configure.py).
+ - MSVS update: Fix the development environment path for MSVS 7.0.
From William Deegan:
- Fix broken clang + MSVC 2019 combination by using MSVC configuration logic to
@@ -201,6 +206,8 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER
repository / website (scons-cookbook.readthedocs.io).
- Clean up test harness and tests' use of subdir, file_fixture and
dir_fixture.
+ - SubstitutionEnvironment and OverrideEnvironment now have keys()
+ and values() methods to better emulate a dict (already had items()).
RELEASE 3.1.2 - Mon, 17 Dec 2019 02:06:27 +0000
diff --git a/RELEASE.txt b/RELEASE.txt
index 6729ce8b4..592ed19b5 100755
--- a/RELEASE.txt
+++ b/RELEASE.txt
@@ -20,7 +20,15 @@
- Add CompilationDatabase() builder in compilation_db tool. Contributed by MongoDB.
Setting COMPILATIONDB_USE_ABSPATH to True|False controls whether the files are absolute or relative
paths. Address Issue #3693 and #3694 found during development.
-
+ - Extended `Environment.Dump()` to select a format to serialize construction variables (pretty, json).
+ - New conditional C Scanner (`SCons.Scanner.C.CConditionalScanner()`)
+ which interprets C/C Preprocessor conditional syntax (#ifdef, #if, #else,
+ #elif, #define, etc.)
+ - Experimental New Feature: Enable caching MSVC configuration
+ If SCONS_CACHE_MSVC_CONFIG shell environment variable is set,
+ SCons will cache the results of past calls to vcvarsall.bat to
+ a file; integrates with existing memoizing of such vars.
+ - Preliminary Python 3.9 support.
DEPRECATED FUNCTIONALITY
@@ -51,7 +59,27 @@
and skipping Python 3.8's new pickle protocol 5 whose main advantage is for out-of-band data buffers.
NOTE: If you used Python 3.8 with SCons 3.0.0 or above, you may get a a pickle protocol error. Remove your
.sconsign.dblite. You will end up with a full rebuild.
-
+ - MSVC updates: When there are multiple product installations (e.g, Community and
+ Build Tools) of MSVC 2017 or MSVC 2019, an Enterprise, Professional,
+ or Community installation will be selected before a Build Tools installation when
+ "14.1" or "14.2" is requested, respectively. (GH Issue #3699).
+ - MSVC updates: When there are multiple product installations of MSVC 2017 (e.g.,
+ Community and Express), 2017 Express is no longer returned when "14.1" is
+ requested. Only 2017 Express will be returned when "14.1Exp" is requested.
+ (GH Issue #3699).
+ - MSVC updates: pass on VSCMD_DEBUG and VSCMD_SKIP_SENDTELEMETRY to msvc
+ tool setup if set in environment. Add Powershell to default env
+ (used to call telemetry script).
+ - Renamed as.py to asm.py and left redirecting tool. 'as' is a reserved word and so
+ changing the name was required as we wanted to import symbols for use in compilation_db
+ tool.
+ - Add no_progress (-Q) option as a set-able option. However, setting it in the
+ SConstruct/SConscript will still cause "scons: Reading SConscript files ..." to be
+ printed, since the option is not set when the build scripts first get read.
+ - Docbook builder provides a fallback if lxml fails to generate
+ a document with tostring().
+ - SubstitutionEnvironment and OverrideEnvironment now have keys()
+ and values() methods to better emulate a dict (already had items()).
FIXES
@@ -69,6 +97,13 @@
or
conftest_68b375d16e812c43e6d72d6e93401e7c_0.o
conftest_68b375d16e812c43e6d72d6e93401e7c_0_5713f09fc605f46b2ab2f7950455f187 (for executable)
+ - Updated documentation toolchain to work properly under Python3, also
+ removed libxslt support from the Docbook Tool. (issue #3580)
+ - Fix broken clang + MSVC 2019 combination by using MSVC configuration logic to
+ propagate 'VCINSTALLDIR' and 'VCToolsInstallDir' which clang tools use to locate
+ header files and libraries from MSVC install. (Fixes GH Issue #3480)
+ - Fix Github Issue #2904 - Provide useful error message when more than one Configure Contexts are opened.
+ Only one open is allowed. You must call conf.Finish() to complete the currently open one before creating another
IMPROVEMENTS
@@ -87,13 +122,12 @@
DOCUMENTATION
- - List any significant changes to the documentation (not individual
- typo fixes, even if they're mentioned in src/CHANGES.txt to give
- the contributor credit)
-
- DEVELOPMENT
-
- - List visible changes in the way SCons is developed
+ - Significant rework of documentation: API docs are now generated
+ using Sphinx; manpage and user guide now use more "standard"
+ markup elements (which could facilitate later conversion to a
+ different doc format, should that choice be made); significant
+ rewordings in manpage. Manpage Examples moved to an external
+ repository / website (scons-cookbook.readthedocs.io).
Thanks to CURLY, LARRY, and MOE for their contributions to this release.
Contributors are listed alphabetically by their last name.
diff --git a/SCons/Environment.py b/SCons/Environment.py
index f9af099db..3da726af0 100644
--- a/SCons/Environment.py
+++ b/SCons/Environment.py
@@ -123,7 +123,7 @@ future_reserved_construction_var_names = [
def copy_non_reserved_keywords(dict):
result = semi_deepcopy(dict)
- for k in list(result.keys()):
+ for k in result.copy().keys():
if k in reserved_construction_var_names:
msg = "Ignoring attempt to set reserved variable `$%s'"
SCons.Warnings.warn(SCons.Warnings.ReservedVariableWarning, msg % k)
@@ -142,7 +142,7 @@ def _set_future_reserved(env, key, value):
def _set_BUILDERS(env, key, value):
try:
bd = env._dict[key]
- for k in list(bd.keys()):
+ for k in bd.copy().keys():
del bd[k]
except KeyError:
bd = BuilderDict(bd, env)
@@ -434,13 +434,23 @@ class SubstitutionEnvironment:
return self._dict.get(key, default)
def has_key(self, key):
+ """Emulates the has_key() method of dictionaries."""
return key in self._dict
def __contains__(self, key):
return self._dict.__contains__(key)
+ def keys(self):
+ """Emulates the keys() method of dictionaries."""
+ return self._dict.keys()
+
+ def values(self):
+ """Emulates the values() method of dictionaries."""
+ return self._dict.values()
+
def items(self):
- return list(self._dict.items())
+ """Emulates the items() method of dictionaries."""
+ return self._dict.items()
def arg2nodes(self, args, node_factory=_null, lookup_list=_null, **kw):
if node_factory is _null:
@@ -2338,10 +2348,12 @@ class OverrideEnvironment(Base):
return self.__dict__['overrides'][key]
except KeyError:
return self.__dict__['__subject'].__getitem__(key)
+
def __setitem__(self, key, value):
if not is_valid_construction_var(key):
raise UserError("Illegal construction variable `%s'" % key)
self.__dict__['overrides'][key] = value
+
def __delitem__(self, key):
try:
del self.__dict__['overrides'][key]
@@ -2356,30 +2368,43 @@ class OverrideEnvironment(Base):
raise
result = None
return result
+
def get(self, key, default=None):
"""Emulates the get() method of dictionaries."""
try:
return self.__dict__['overrides'][key]
except KeyError:
return self.__dict__['__subject'].get(key, default)
+
def has_key(self, key):
+ """Emulates the has_key() method of dictionaries."""
try:
self.__dict__['overrides'][key]
return 1
except KeyError:
return key in self.__dict__['__subject']
+
def __contains__(self, key):
if self.__dict__['overrides'].__contains__(key):
return 1
return self.__dict__['__subject'].__contains__(key)
+
def Dictionary(self):
- """Emulates the items() method of dictionaries."""
d = self.__dict__['__subject'].Dictionary().copy()
d.update(self.__dict__['overrides'])
return d
+
def items(self):
"""Emulates the items() method of dictionaries."""
- return list(self.Dictionary().items())
+ return self.Dictionary().items()
+
+ def keys(self):
+ """Emulates the keys() method of dictionaries."""
+ return self.Dictionary().keys()
+
+ def values(self):
+ """Emulates the values() method of dictionaries."""
+ return self.Dictionary().values()
# Overridden private construction environment methods.
def _update(self, dict):
diff --git a/SCons/EnvironmentTests.py b/SCons/EnvironmentTests.py
index 6dcf3c131..f90e39dbf 100644
--- a/SCons/EnvironmentTests.py
+++ b/SCons/EnvironmentTests.py
@@ -174,14 +174,12 @@ class TestEnvironmentFixture:
class SubstitutionTestCase(unittest.TestCase):
def test___init__(self):
- """Test initializing a SubstitutionEnvironment
- """
+ """Test initializing a SubstitutionEnvironment."""
env = SubstitutionEnvironment()
assert '__env__' not in env
def test___cmp__(self):
- """Test comparing SubstitutionEnvironments
- """
+ """Test comparing SubstitutionEnvironments."""
env1 = SubstitutionEnvironment(XXX = 'x')
env2 = SubstitutionEnvironment(XXX = 'x')
@@ -193,16 +191,14 @@ class SubstitutionTestCase(unittest.TestCase):
assert env1 != env4
def test___delitem__(self):
- """Test deleting a variable from a SubstitutionEnvironment
- """
+ """Test deleting a variable from a SubstitutionEnvironment."""
env1 = SubstitutionEnvironment(XXX = 'x', YYY = 'y')
env2 = SubstitutionEnvironment(XXX = 'x')
del env1['YYY']
assert env1 == env2
def test___getitem__(self):
- """Test fetching a variable from a SubstitutionEnvironment
- """
+ """Test fetching a variable from a SubstitutionEnvironment."""
env = SubstitutionEnvironment(XXX = 'x')
assert env['XXX'] == 'x', env['XXX']
@@ -215,38 +211,52 @@ class SubstitutionTestCase(unittest.TestCase):
assert env1 == env2
def test_get(self):
- """Test the SubstitutionEnvironment get() method
- """
+ """Test the SubstitutionEnvironment get() method."""
env = SubstitutionEnvironment(XXX = 'x')
assert env.get('XXX') == 'x', env.get('XXX')
assert env.get('YYY') is None, env.get('YYY')
def test_has_key(self):
- """Test the SubstitutionEnvironment has_key() method
- """
+ """Test the SubstitutionEnvironment has_key() method."""
env = SubstitutionEnvironment(XXX = 'x')
assert 'XXX' in env
assert 'YYY' not in env
def test_contains(self):
- """Test the SubstitutionEnvironment __contains__() method
- """
+ """Test the SubstitutionEnvironment __contains__() method."""
env = SubstitutionEnvironment(XXX = 'x')
assert 'XXX' in env
assert 'YYY' not in env
+ def test_keys(self):
+ """Test the SubstitutionEnvironment keys() method."""
+ testdata = {'XXX': 'x', 'YYY': 'y'}
+ env = SubstitutionEnvironment(**testdata)
+ keys = list(env.keys())
+ assert len(keys) == 2, keys
+ for k in testdata.keys():
+ assert k in keys, keys
+
+ def test_values(self):
+ """Test the SubstitutionEnvironment values() method."""
+ testdata = {'XXX': 'x', 'YYY': 'y'}
+ env = SubstitutionEnvironment(**testdata)
+ values = list(env.values())
+ assert len(values) == 2, values
+ for v in testdata.values():
+ assert v in values, values
+
def test_items(self):
- """Test the SubstitutionEnvironment items() method
- """
- env = SubstitutionEnvironment(XXX = 'x', YYY = 'y')
+ """Test the SubstitutionEnvironment items() method."""
+ testdata = {'XXX': 'x', 'YYY': 'y'}
+ env = SubstitutionEnvironment(**testdata)
items = list(env.items())
- assert len(items) == 2 and ('XXX','x') in items and ('YYY','y') in items, items
- # Was. This fails under py3 as order changes
- # assert items == [('XXX','x'), ('YYY','y')], items
+ assert len(items) == 2, items
+ for k, v in testdata.items():
+ assert (k, v) in items, items
def test_arg2nodes(self):
- """Test the arg2nodes method
- """
+ """Test the arg2nodes method."""
env = SubstitutionEnvironment()
dict = {}
class X(SCons.Node.Node):
diff --git a/SCons/Tool/MSCommon/vs.py b/SCons/Tool/MSCommon/vs.py
index 4eee9b336..0d22e2942 100644
--- a/SCons/Tool/MSCommon/vs.py
+++ b/SCons/Tool/MSCommon/vs.py
@@ -380,7 +380,7 @@ SupportedVSList = [
sdk_version='2003R2',
hkeys=[r'Microsoft\VisualStudio\7.0\Setup\VS\ProductDir'],
common_tools_var='VS70COMNTOOLS',
- executable_path=r'IDE\devenv.com',
+ executable_path=r'Common7\IDE\devenv.com',
batch_file_path=r'Common7\Tools\vsvars32.bat',
default_dirname='Microsoft Visual Studio .NET',
supported_arch=['x86'],
diff --git a/SCons/Tool/docbook/__init__.py b/SCons/Tool/docbook/__init__.py
index c5261a20e..366dff460 100644
--- a/SCons/Tool/docbook/__init__.py
+++ b/SCons/Tool/docbook/__init__.py
@@ -255,7 +255,16 @@ def __generate_xsltproc_action(source, target, env, for_signature):
base_dir = env.subst('$base_dir')
if base_dir:
# Yes, so replace target path by its filename
- return cmd.replace('$TARGET','${TARGET.file}')
+ return cmd.replace('$TARGET', os.path.join(base_dir, '${TARGET.file}'))
+ return cmd
+
+def __generate_xsltproc_nobase_action(source, target, env, for_signature):
+ cmd = env['DOCBOOK_XSLTPROCCOM']
+ # Does the environment have a base_dir defined?
+ base_dir = env.subst('$base_dir')
+ if base_dir:
+ # Yes, so replace target path by its filename
+ return cmd.replace('$TARGET', '${TARGET.file}')
return cmd
@@ -374,6 +383,12 @@ __xsltproc_builder = SCons.Builder.Builder(
src_suffix = '.xml',
source_scanner = docbook_xml_scanner,
emitter = __emit_xsl_basedir)
+__xsltproc_nobase_builder = SCons.Builder.Builder(
+ action = SCons.Action.CommandGeneratorAction(__generate_xsltproc_nobase_action,
+ {'cmdstr' : '$DOCBOOK_XSLTPROCCOMSTR'}),
+ src_suffix = '.xml',
+ source_scanner = docbook_xml_scanner,
+ emitter = __emit_xsl_basedir)
__xmllint_builder = SCons.Builder.Builder(
action = SCons.Action.Action('$DOCBOOK_XMLLINTCOM','$DOCBOOK_XMLLINTCOMSTR'),
suffix = '.xml',
@@ -450,7 +465,7 @@ def DocbookEpub(env, target, source=None, *args, **kw):
__init_xsl_stylesheet(kw, env, '$DOCBOOK_DEFAULT_XSL_EPUB', ['epub','docbook.xsl'])
# Setup builder
- __builder = __select_builder(__lxml_noresult_builder, __xsltproc_builder)
+ __builder = __select_builder(__lxml_noresult_builder, __xsltproc_nobase_builder)
# Create targets
result = []
@@ -519,7 +534,7 @@ def DocbookHtmlChunked(env, target, source=None, *args, **kw):
__init_xsl_stylesheet(kw, env, '$DOCBOOK_DEFAULT_XSL_HTMLCHUNKED', ['html','chunkfast.xsl'])
# Setup builder
- __builder = __select_builder(__lxml_noresult_builder, __xsltproc_builder)
+ __builder = __select_builder(__lxml_noresult_builder, __xsltproc_nobase_builder)
# Detect base dir
base_dir = kw.get('base_dir', '')
@@ -554,7 +569,7 @@ def DocbookHtmlhelp(env, target, source=None, *args, **kw):
__init_xsl_stylesheet(kw, env, '$DOCBOOK_DEFAULT_XSL_HTMLHELP', ['htmlhelp','htmlhelp.xsl'])
# Setup builder
- __builder = __select_builder(__lxml_noresult_builder, __xsltproc_builder)
+ __builder = __select_builder(__lxml_noresult_builder, __xsltproc_nobase_builder)
# Detect base dir
base_dir = kw.get('base_dir', '')
@@ -700,10 +715,10 @@ def DocbookSlidesHtml(env, target, source=None, *args, **kw):
source = [source]
# Init XSL stylesheet
- __init_xsl_stylesheet(kw, env, '$DOCBOOK_DEFAULT_XSL_SLIDESHTML', ['slides','html','plain.xsl'])
+ __init_xsl_stylesheet(kw, env, '$DOCBOOK_DEFAULT_XSL_SLIDESHTML', ['slides','xhtml','plain.xsl'])
# Setup builder
- __builder = __select_builder(__lxml_noresult_builder, __xsltproc_builder)
+ __builder = __select_builder(__lxml_builder, __xsltproc_builder)
# Detect base dir
base_dir = kw.get('base_dir', '')
diff --git a/doc/man/scons.xml b/doc/man/scons.xml
index 18e432186..7b083f05d 100644
--- a/doc/man/scons.xml
+++ b/doc/man/scons.xml
@@ -5335,9 +5335,10 @@ env = Environment(BUILDERS={'MyBuild' : b})
env.MyBuild('sub/dir/foo.out', 'sub/dir/foo.in')
</programlisting>
-<para><emphasis role="bold">WARNING:</emphasis>
+<warning>
+<para>
Python only keeps one current directory
-location for all of the threads.
+location even if there are multiple threads.
This means that use of the
<parameter>chdir</parameter>
argument
@@ -5349,6 +5350,7 @@ option,
because individual worker threads spawned
by SCons interfere with each other
when they start changing directory.</para>
+</warning>
</listitem>
</varlistentry>
</variablelist>
@@ -5387,9 +5389,9 @@ function will turn its
keyword argument into an appropriate
internal Action object.
You can also explicitly create Action objects
-using the &f-link-Action; global function,
-which can then be passed to the
-&f-Builder; function.
+for passing to &f-Builder;, or other functions
+that take actions as arguments,
+by calling the &f-link-Action; factory function.
This can be used to configure
an Action object more flexibly,
or it may simply be more efficient
@@ -5399,31 +5401,26 @@ when multiple
Builder objects need to do the same thing.</para>
<para>The
-&f-link-Action;
-global function
+&Action; factory function
returns an appropriate object for the action
-represented by the type of the first argument:</para>
+represented by the type of the action argument
+(the first positional parmeter):</para>
-<variablelist>
- <varlistentry>
- <term>action</term>
+<itemizedlist>
<listitem>
-<para>If the first argument is already an Action object,
+<para>If the action argument is already an Action object,
the object is simply returned.</para>
</listitem>
- </varlistentry>
- <varlistentry>
- <term>string</term>
<listitem>
-<para>If the first argument is a string,
+<para>If the action argument is a string,
a command-line Action is returned.
If such a string begins with
<emphasis role="bold">@</emphasis>,
it indicates printing of the command line is to be suppressed.
If the string begins with
<emphasis role="bold">-</emphasis> (hyphen),
-it indicated the exit status from the specified command
+it indicates the exit status from the specified command
is to be ignored, allowing execution to continue
even if the command reports failure:</para>
@@ -5436,46 +5433,30 @@ Action('@build $TARGET $SOURCES')
# Ignores return value
Action('-build $TARGET $SOURCES')
</programlisting>
-
-<!-- XXX From Gary Ruben, 23 April 2002: -->
-<!-- What would be useful is a discussion of how you execute command -->
-<!-- shell commands ie. what is the process used to spawn the shell, pass -->
-<!-- environment variables to it etc., whether there is one shell per -->
-<!-- environment or one per command etc. It might help to look at the Gnu -->
-<!-- make documentation to see what they think is important to discuss about -->
-<!-- a build system. I'm sure you can do a better job of organising the -->
-<!-- documentation than they have :\-) -->
</listitem>
- </varlistentry>
- <varlistentry>
- <term>list</term>
<listitem>
-<para>If the first argument is a list,
+<para>If the action argument is a list,
then a list of Action objects is returned.
An Action object is created as necessary
for each element in the list.
If an element
<emphasis>within</emphasis>
the list is itself a list,
-the internal list is the
+the internal list is taken as the
command and arguments to be executed via
the command line.
This allows white space to be enclosed
-in an argument by defining
+in an argument rather than taken as a separator by defining
a command in a list within a list:</para>
<programlisting language="python">
Action([['cc', '-c', '-DWHITE SPACE', '-o', '$TARGET', '$SOURCES']])
</programlisting>
-
</listitem>
- </varlistentry>
- <varlistentry>
- <term>function</term>
<listitem>
-<para>If the first argument is a Python function,
+<para>If the action argument is a Python function,
a function Action is returned.
The Python function must accept three keyword arguments:</para>
@@ -5520,13 +5501,22 @@ def build_it(target=None, source=None, env=None):
a = Action(build_it)
</programlisting>
-
</listitem>
- </varlistentry>
-</variablelist>
-<para>If the action argument is not one of the above,
+ <listitem>
+<para>If the action argument is not one of the above types,
<constant>None</constant> is returned.</para>
+ </listitem>
+</itemizedlist>
+
+<para>As usual the environment method form &f-link-env-Action;
+will expand &consvars; in any argument strings,
+including the action argument, at the time it is called,
+using the construction variables in the &consenv; through which
+it was called. The global function form &f-link-Action;
+<emphasis>delays</emphasis> variable expansion until
+the Action object is actually used.
+</para>
<para>The second argument to &f-Action;
is optional and is used to define the output
@@ -5535,17 +5525,17 @@ In the absence of this parameter,
or if it's an empty string,
a default output depending on the type of the action is used.
For example, a command-line action will print the executed command.
-The argument must be either a Python function or a string.</para>
+The argument must be either a Python function or a string:</para>
-<para>In the first case,
-it's a function that returns a string to be printed
-to describe the action being executed.
-The function may also be specified by the
+<itemizedlist>
+ <listitem>
+<para>If the output argument is a function,
+it must return a string
+describing the action being executed.
+A function may also be specified using the
<parameter>strfunction</parameter>
-keyword argument.
-Like a function to build a file,
-the <parameter>strfunction</parameter> function
-must accept three keyword arguments:</para>
+keyword argument. The function
+must accept these three keyword arguments:</para>
<simplelist type="vert">
<member><parameter>source</parameter> -
@@ -5561,9 +5551,12 @@ and
<parameter>source</parameter>
arguments may be lists of Node objects if there is
more than one target file or source file.</para>
+ </listitem>
-<para>In the second case, you provide the string itself.
-This string may also be specified using the
+ <listitem>
+<para>If the output argument is a string,
+substitution is performed on it before it is printed.
+The output string may also be specified using the
<parameter>cmdstr</parameter>
keyword argument.
The string typically contains variables, notably
@@ -5571,6 +5564,8 @@ The string typically contains variables, notably
or consists of just a single
variable, which is optionally defined somewhere else.
SCons itself heavily uses the latter variant.</para>
+ </listitem>
+</itemizedlist>
<para>Examples:</para>
@@ -5594,14 +5589,14 @@ s = Action(build_it, cmdstr="building '$TARGET' from '$SOURCE'")
l = Action(build_it, '$STRINGIT')
</programlisting>
-<para>The third and succeeding arguments, if present,
-may either be a &consvar; or a list of &consvars;
+<para>Any additional positional arguments, if present,
+may either be &consvars; or lists of &consvars;
whose values will be included in the signature of the Action
when deciding whether a target should be rebuilt because the action changed.
-The variables may also be specified using the
+Such variables may also be specified using the
<parameter>varlist</parameter>
keyword parameter;
-if both are present, they are combined.
+both positional and keyword forms may be present, and will be combined.
This is necessary whenever you want a target to be rebuilt
when a specific &consvar; changes.
This is not often needed for a string action,
@@ -5625,7 +5620,7 @@ a = Action(build_it, varlist=['XXX'])
<para>The
&Action;
-global function
+factory function
can be passed the following
optional keyword arguments
to modify the Action object's behavior:</para>
@@ -5821,14 +5816,10 @@ although the implementation is slightly different.
These functions do not actually
perform the specified action
at the time the function is called,
-but instead return an Action object
+but rather are factory functions which
+return an Action object
that can be executed at the
-appropriate time.
-(In Object-Oriented terminology,
-these are actually
-Action
-<firstterm>Factory functions</firstterm>
-that return Action objects.)</para>
+appropriate time.</para>
<para>In practice,
there are two natural ways
@@ -5918,8 +5909,7 @@ Examples:</para>
<programlisting language="python">
Execute(Copy('foo.output', 'foo.input'))
-env.Command('bar.out', 'bar.in',
- Copy('$TARGET', '$SOURCE'))
+env.Command('bar.out', 'bar.in', Copy('$TARGET', '$SOURCE'))
</programlisting>
</listitem>
@@ -5937,10 +5927,10 @@ the entire directory tree
will be removed.
If the
<parameter>must_exist</parameter>
-flag is set to a True value,
-then a Python error will be thrown
+flag is set to a true value,
+then a Python error will be raised
if the specified entry does not exist;
-the default is False,
+the default is false,
that is, the Action will silently do nothing
if the entry does not exist.
Examples:</para>
@@ -5948,11 +5938,16 @@ Examples:</para>
<programlisting language="python">
Execute(Delete('/tmp/buildroot'))
-env.Command('foo.out', 'foo.in',
- [Delete('${TARGET.dir}'),
- MyBuildAction])
+env.Command(
+ 'foo.out',
+ 'foo.in',
+ action=[
+ Delete('${TARGET.dir}'),
+ MyBuildAction,
+ ],
+)
-Execute(Delete('file_that_must_exist', must_exist=1))
+Execute(Delete('file_that_must_exist', must_exist=True))
</programlisting>
</listitem>
@@ -5970,11 +5965,16 @@ Examples:</para>
<programlisting language="python">
Execute(Mkdir('/tmp/outputdir'))
-env.Command('foo.out', 'foo.in',
- [Mkdir('/tmp/builddir'),
- Copy('/tmp/builddir/foo.in', '$SOURCE'),
- "cd /tmp/builddir &amp;&amp; make",
- Copy('$TARGET', '/tmp/builddir/foo.out')])
+env.Command(
+ 'foo.out',
+ 'foo.in',
+ action=[
+ Mkdir('/tmp/builddir'),
+ Copy('/tmp/builddir/foo.in', '$SOURCE'),
+ "cd /tmp/builddir &amp;&amp; make",
+ Copy('$TARGET', '/tmp/builddir/foo.out'),
+ ],
+)
</programlisting>
</listitem>
@@ -5995,9 +5995,11 @@ Examples:</para>
<programlisting language="python">
Execute(Move('file.destination', 'file.source'))
-env.Command('output_file', 'input_file',
- [MyBuildAction,
- Move('$TARGET', 'file_created_by_MyBuildAction')])
+env.Command(
+ 'output_file',
+ 'input_file',
+ action=[MyBuildAction, Move('$TARGET', 'file_created_by_MyBuildAction')],
+)
</programlisting>
</listitem>
@@ -6015,8 +6017,7 @@ Examples:</para>
<programlisting language="python">
Execute(Touch('file_to_be_touched'))
-env.Command('marker', 'input_file',
- action=[MyBuildAction, Touch('$TARGET')])
+env.Command('marker', 'input_file', action=[MyBuildAction, Touch('$TARGET')])
</programlisting>
</listitem>
diff --git a/doc/man/sconsign.xml b/doc/man/sconsign.xml
index 03b63519c..93842ad43 100644
--- a/doc/man/sconsign.xml
+++ b/doc/man/sconsign.xml
@@ -24,7 +24,6 @@
-->
-<!-- lifted from troff+man by doclifter -->
<refentry id='sconsign1'
xmlns="http://www.scons.org/dbxsd/v1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
@@ -53,14 +52,15 @@
<para>The
<command>sconsign</command>
command
-displays the contents of one or more signature
-("<markup>sconsign</markup>")
-files specified by the user.</para>
+displays the contents of one or more signature database
+(<firstterm>sconsign</firstterm>)
+files used by the <command>scons</command> build tool.
+</para>
<para>By default,
<command>sconsign</command>
dumps the entire contents of the
-specified file(s).
+sconsign file(s).
Without the verbose option,
each entry is printed in the following format:</para>
@@ -74,14 +74,18 @@ file: signature timestamp length
<para><emphasis role="bold">None</emphasis>
is printed
-in place of any missing timestamp, build signature ("bsig"),
-or content signature ("csig")
+in place of any missing timestamp, <firstterm>build signature</firstterm>
+(<emphasis role="bold">bsig</emphasis>),
+or <firstterm>content signature</firstterm>
+(<emphasis role="bold">csig</emphasis>)
values for
any entry
or any of its dependencies.
If the entry has no implicit dependencies,
or no build action,
-the lines are simply omitted.
+the lines are simply omitted.</para>
+
+<para>
The verbose option expands the display into a more human
readable format.
</para>
@@ -89,9 +93,9 @@ readable format.
<para>By default,
<command>sconsign</command>
assumes that any
-<emphasis>file</emphasis>
+<replaceable>file</replaceable>
arguments that end with a
-<markup>.dbm</markup>
+<filename>.dbm</filename>
suffix contains
signature entries for
more than one directory
@@ -100,11 +104,11 @@ was specified by the
<emphasis role="bold">SConsignFile</emphasis>
function).
Any
-<emphasis>file</emphasis>
+<replaceable>file</replaceable>
argument that ends in
-<markup>.dblite</markup>
+<filename>.dblite</filename>
is assumed to be a traditional
-<markup>.sconsign</markup>
+sconsign
file containing the signature entries
for a single directory.
If neither of those is true,
@@ -120,7 +124,7 @@ options.
</para>
<para>
If there are no
-<emphasis>file</emphasis>
+<replaceable>file</replaceable>
arguments, the name
<filename>.sconsign.dblite</filename>
is assumed.
@@ -128,13 +132,18 @@ is assumed.
</refsect1>
-<refsect1 id='options'><title>OPTIONS</title>
+<refsect1 id='options'>
+<title>OPTIONS</title>
<para>Various options control what information is printed
and the format:</para>
<variablelist>
<varlistentry>
- <term>-a, --act, --action</term>
+ <term>
+ <option>-a</option>,
+ <option>--act</option>,
+ <option>--action</option>
+ </term>
<listitem>
<para>Prints the build action information
for all entries or the specified entries.</para>
@@ -142,7 +151,10 @@ for all entries or the specified entries.</para>
</listitem>
</varlistentry>
<varlistentry>
- <term>-c, --csig</term>
+ <term>
+ <option>-c</option>,
+ <option>--csig</option>
+ </term>
<listitem>
<para>Prints the content signature (csig) information
for all entries or the specified entries.</para>
@@ -150,11 +162,14 @@ for all entries or the specified entries.</para>
</listitem>
</varlistentry>
<varlistentry>
- <term>-d DIRECTORY, --dir=DIRECTORY</term>
+ <term>
+ <option>-d <replaceable>DIRECTORY</replaceable></option>,
+ <option>--dir=<replaceable>DIRECTORY</replaceable></option>
+ </term>
<listitem>
<para>When the signatures are being
read from a
-<markup>.dbm</markup>
+<filename>.dbm</filename>
file, or the
<option>-f dbm</option>
or
@@ -163,29 +178,35 @@ options are used,
prints information about
only the signatures
for entries in the specified
-<emphasis>DIRECTORY</emphasis>.</para>
+<replaceable>DIRECTORY</replaceable>.</para>
</listitem>
</varlistentry>
<varlistentry>
- <term>-e ENTRY, --entry=ENTRY</term>
+ <term>
+ <option>-e <replaceable>ENTRY</replaceable></option>,
+ <option>--entry=<replaceable>ENTRY</replaceable></option>
+ </term>
<listitem>
<para>Prints information about only the specified
-<emphasis>ENTRY</emphasis>.
-Multiple -e options may be used,
+<replaceable>ENTRY</replaceable>.
+Multiple <option>-e</option> options may be used,
in which case information about each
-<emphasis>ENTRY</emphasis>
+<replaceable>ENTRY</replaceable>
is printed in the order in which the
options are specified on the command line.</para>
</listitem>
</varlistentry>
<varlistentry>
- <term>-f FORMAT, --format=FORMAT</term>
+ <term>
+ <option>-f <replaceable>FORMAT</replaceable></option>,
+ <option>--format=<replaceable>FORMAT</replaceable></option>
+ </term>
<listitem>
<para>The file(s) to be printed
are in the specified
-<emphasis>FORMAT</emphasis>.
+<replaceable>FORMAT</replaceable>.
Legal values are
<emphasis role="bold">dbm</emphasis>
(the DBM format used
@@ -196,20 +217,26 @@ or
<command>sconsign</command>
(the default format
used for an individual
-<markup>.sconsign</markup>
+<filename>.sconsign</filename>
file in each directory).</para>
</listitem>
</varlistentry>
<varlistentry>
- <term>-h, --help</term>
+ <term>
+ <option>-h</option>,
+ <option>--help</option>
+ </term>
<listitem>
<para>Prints a help message and exits.</para>
</listitem>
</varlistentry>
<varlistentry>
- <term>-i, --implicit</term>
+ <term>
+ <option>-i</option>,
+ <option>--implicit</option>
+ </term>
<listitem>
<para>Prints the list of cached implicit dependencies
for all entries or for the specified entries.</para>
@@ -217,7 +244,7 @@ for all entries or for the specified entries.</para>
</listitem>
</varlistentry>
<varlistentry>
- <term>--raw</term>
+ <term><option>--raw</option></term>
<listitem>
<para>Prints a pretty-printed representation
of the raw Python dictionary that holds
@@ -228,7 +255,10 @@ An entry's build action is still printed in its usual format.</para>
</listitem>
</varlistentry>
<varlistentry>
- <term>-r, --readable</term>
+ <term>
+ <option>-r</option>,
+ <option>--readable</option>
+ </term>
<listitem>
<para>Prints timestamps in a human-readable string,
enclosed in single quotes.</para>
@@ -236,7 +266,10 @@ enclosed in single quotes.</para>
</listitem>
</varlistentry>
<varlistentry>
- <term>-t, --timestamp</term>
+ <term>
+ <option>-t</option>,
+ <option>--timestamp</option>
+ </term>
<listitem>
<para>Prints the timestamp information
for all entries or the specified entries.</para>
@@ -244,7 +277,10 @@ for all entries or the specified entries.</para>
</listitem>
</varlistentry>
<varlistentry>
- <term>-v, --verbose</term>
+ <term>
+ <option>-v</option>,
+ <option>--verbose</option>
+ </term>
<listitem>
<para>Prints labels identifying each field being printed.</para>
@@ -253,34 +289,39 @@ for all entries or the specified entries.</para>
</variablelist>
</refsect1>
-<refsect1 id='environment'><title>ENVIRONMENT</title>
+<refsect1 id='environment'>
+<title>ENVIRONMENT</title>
<variablelist>
<varlistentry>
- <term>SCONS_LIB_DIR</term>
+ <term><envar>SCONS_LIB_DIR</envar></term>
<listitem>
<para>Specifies the directory that contains the SCons Python module directory
(e.g.
-<filename class='directory'>/home/aroach/scons-src-0.01/src/engine</filename>).
-on the command line.</para>
+<filename class='directory'>/home/aroach/scons-src/SCons</filename>).
+</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
-<refsect1 id='see_also'><title>SEE ALSO</title>
-<para><emphasis role="bold">scons</emphasis>,
-<emphasis role="bold">scons</emphasis>
-User Manual,
-<emphasis role="bold">scons</emphasis>
-Design Document,
-<emphasis role="bold">scons</emphasis>
-source code.</para>
-
+<refsect1 id='see_also'>
+<para>
+<title>SEE ALSO</title>
+<command>scons</command>,
+the SCons User Guide at
+<ulink url="https://scons.org/doc/production/HTML/scons-user.html"/>,
+the SCons source code
+<ulink url="https://github.com/SCons/scons">
+on GitHub</ulink>.
+</para>
</refsect1>
-<refsect1 id='authors'><title>AUTHORS</title>
-<para>Steven Knight &lt;knight at baldmt dot com&gt;</para>
+<refsect1 id='authors'>
+<title>AUTHORS</title>
+<para>Originally: Steven Knight <email>knight@baldmt.com</email>
+and Anthony Roach <email>aroach@electriceyeball.com</email>.
+Since 2010: The SCons Development Team <email>scons-dev@scons.org</email>.
+</para>
</refsect1>
</refentry>
-
diff --git a/doc/user/MANIFEST b/doc/user/MANIFEST
index 3110c2a36..10b79f6e0 100644
--- a/doc/user/MANIFEST
+++ b/doc/user/MANIFEST
@@ -18,6 +18,7 @@ depends.xml
environments.xml
errors.xml
example.xml
+external.xml
factories.xml
file-removal.xml
functions.xml
diff --git a/doc/user/caching.xml b/doc/user/caching.xml
index 412b50ab9..790aa93c2 100644
--- a/doc/user/caching.xml
+++ b/doc/user/caching.xml
@@ -2,7 +2,7 @@
<!DOCTYPE sconsdoc [
<!ENTITY % scons SYSTEM "../scons.mod">
%scons;
-
+
<!ENTITY % builders-mod SYSTEM "../generated/builders.mod">
%builders-mod;
<!ENTITY % functions-mod SYSTEM "../generated/functions.mod">
@@ -11,7 +11,7 @@
%tools-mod;
<!ENTITY % variables-mod SYSTEM "../generated/variables.mod">
%variables-mod;
-
+
]>
<chapter id="chap-caching"
@@ -50,7 +50,9 @@
On multi-developer software projects,
you can sometimes speed up every developer's builds a lot by
allowing them to share the derived files that they build.
- &SCons; makes this easy, as well as reliable.
+ After all, it is relatively rare that any in-progress change affects
+ more than a few derived files, most will be unchanged.
+ &SCons; makes this easy and reliable.
</para>
@@ -60,7 +62,7 @@
<para>
To enable sharing of derived files,
- use the &CacheDir; function
+ use the &f-link-CacheDir; function
in any &SConscript; file:
</para>
@@ -83,8 +85,8 @@ CacheDir('/usr/local/build_cache')
<para>
- Note that the directory you specify must already exist
- and be readable and writable by all developers
+ The cache directory you specify must
+ be readable and writable by all developers
who will be sharing derived files.
It should also be in some central location
that all builds will be able to access.
@@ -92,6 +94,10 @@ CacheDir('/usr/local/build_cache')
(like individual workstations) for builds,
this directory would typically be
on a shared or NFS-mounted file system.
+ While &SCons; will create the specified cache directory as needed,
+ in this multi user scenario it is usually best
+ to create it ahead of time so the access rights
+ can be set up correctly.
</para>
@@ -100,23 +106,33 @@ CacheDir('/usr/local/build_cache')
Here's what happens:
When a build has a &CacheDir; specified,
every time a file is built,
- it is stored in the shared cache directory
- along with its MD5 build signature.
- <footnote>
- <para>
- Actually, the MD5 signature is used as the name of the file
- in the shared cache directory in which the contents are stored.
- </para>
- </footnote>
+ it is stored in that cache directory
+ along with its build signature.
On subsequent builds,
before an action is invoked to build a file,
&SCons; will check the shared cache directory
to see if a file with the exact same build
signature already exists.
+ <footnote>
+ <para>
+ A few inner details: &SCons; tracks two main kinds of cryptographic
+ hashes: <emphasis>content signatures</emphasis>,
+ which are a hash of the contents of a file;
+ and <emphasis>build signatures</emphasis>, which are a hash of the
+ elements needed to build a target, such as the exact command line,
+ the contents of the sources, and possibly information about
+ tools used in the build. The hash function produces a unique signature
+ from its inputs, no other set of inputs can produce that same
+ signature. The build signature from building
+ a target is used as the filename of the target file in the
+ shared cache - that way lookups are efficient, just compute
+ a build signature and see if a file exists with that as the name.
+ </para>
+ </footnote>
If so, the derived file will not be built locally,
but will be copied into the local build directory
from the shared cache directory,
- like so:
+ like this:
</para>
@@ -128,12 +144,14 @@ CacheDir('/usr/local/build_cache')
<para>
- Note that the &CacheDir; feature still calculates
- MD5 build sigantures for the shared cache file names
+ Note that the &CacheDir; feature requires that build signatures
+ be calculated,
even if you configure &SCons; to use timestamps
- to decide if files are up to date.
- (See the <xref linkend="chap-depends"></xref>
- chapter for information about the &Decider; function.)
+ to decide if files are up to date
+ (see the <xref linkend="chap-depends"></xref>
+ chapter for information about the &f-link-Decider; function),
+ since the build signature is used to determine if a target file
+ exists in the cache.
Consequently, using &CacheDir; may reduce or eliminate any
potential performance improvements
from using timestamps for up-to-date decisions.
diff --git a/doc/user/external.xml b/doc/user/external.xml
new file mode 100644
index 000000000..a72fa5423
--- /dev/null
+++ b/doc/user/external.xml
@@ -0,0 +1,158 @@
+<?xml version='1.0'?>
+<!DOCTYPE sconsdoc [
+ <!ENTITY % scons SYSTEM "../scons.mod">
+ %scons;
+
+ <!ENTITY % builders-mod SYSTEM "../generated/builders.mod">
+ %builders-mod;
+ <!ENTITY % functions-mod SYSTEM "../generated/functions.mod">
+ %functions-mod;
+ <!ENTITY % tools-mod SYSTEM "../generated/tools.mod">
+ %tools-mod;
+ <!ENTITY % variables-mod SYSTEM "../generated/variables.mod">
+ %variables-mod;
+
+]>
+
+<chapter id="chap-external"
+ xmlns="http://www.scons.org/dbxsd/v1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd">
+<title>Using SCons with other build tools</title>
+
+<!--
+
+ __COPYRIGHT__
+
+ 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.
+
+-->
+
+ <para>
+
+ Sometimes a project needs to interact with other projects
+ in various ways. For example, many open source projects
+ make use of components from other open source projects,
+ and want to use those in their released form, not recode
+ their builds into &SCons;. As another example, sometimes
+ the flexibility and power of &SCons; is useful for managing the
+ overall project, but developers might like faster incremental
+ builds when making small changes by using a different tool.
+
+ </para>
+
+ <para>
+
+ This chapter shows some techniques for interacting with other
+ projects and tools effectively from within &SCons;.
+
+ </para>
+
+ <section>
+ <title>Creating a Compilation Database</title>
+
+ <para>
+
+ Tooling which wants to perform analysis and modification
+ of source code often needs to know not only the source code
+ itself, but also how it will be compiled, as the compilation line
+ affects the behavior of macros, includes, etc. &SCons; has a
+ record of this information once it has run, in the form of
+ Actions associated with the sources, and can emit this information
+ so tools can use it.
+
+ </para>
+
+ <para>
+
+ The Clang project has defined a <firstterm>JSON Compilation Database</firstterm>.
+ This database is in common use as input into Clang tools
+ and many IDEs and editors as well.
+ See
+ <ulink url="https://clang.llvm.org/docs/JSONCompilationDatabase.html">
+ <citetitle>JSON Compilation Database Format Specification</citetitle>
+ </ulink>
+ for complete information. &SCons; can emit a
+ compilation database in this format
+ by enabling the &t-link-compilation_db; tool
+ and calling the &b-link-CompilationDatabase; builder
+ (available since 4.0).
+
+ </para>
+
+ <para>
+
+ The compilation database can be populated with
+ source and target files either with paths relative
+ to the top of the build, or using absolute paths.
+ This is controlled by
+ <envar>COMPILATIONDB_USE_ABSPATH=(True|False)</envar>
+ which defaults to <constant>False</constant>.
+
+ </para>
+
+ <para>
+
+ Example of absolute paths for target and source:
+
+ </para>
+
+ <sconstruct>
+env = Environment(COMPILATIONDB_USE_ABSPATH=True)
+env.Tool('compilation_db')
+env.CompilationDatabase('compile_commands.json')
+ </sconstruct>
+
+ <programlisting language="json">
+[
+ {
+ "command": "gcc -o test_main.o -c test_main.c",
+ "directory": "/home/user/sandbox",
+ "file": "/home/user/sandbox/test_main.c",
+ "target": "/home/user/sandbox/test_main.o"
+ }
+]
+ </programlisting>
+
+ <para>
+
+ Example of relative paths for target and source:
+
+ </para>
+
+ <sconstruct>
+env = Environment()
+env.Tool('compilation_db')
+env.CompilationDatabase('compile_commands.json')
+ </sconstruct>
+ <programlisting language="json">
+[
+ {
+ "command": "gcc -o test_main.o -c test_main.c",
+ "directory": "/home/user/sandbox",
+ "file": "test_main.c",
+ "target": "test_main.o"
+ }
+]
+ </programlisting>
+
+ </section>
+
+</chapter>
diff --git a/doc/user/main.xml b/doc/user/main.xml
index 19d707195..49fef7557 100644
--- a/doc/user/main.xml
+++ b/doc/user/main.xml
@@ -43,23 +43,6 @@
]>
- <!--
-
- XXX Platform()
- XXX Tools()
-
- XXX GetOption('duplicate')
- XXX SetOption('duplicate')
- XXX - - duplicate=
-
- XXX CheckTypeSize()
-
- XXX - - diskcheck=
-
- XXX - - warn=
-
- -->
-
<book xmlns="http://www.scons.org/dbxsd/v1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd">
@@ -158,6 +141,7 @@
-->
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="misc.xml"/>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="external.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="troubleshoot.xml"/>
<!-- Appendix below here -->
diff --git a/doc/user/misc.xml b/doc/user/misc.xml
index 3a2713a02..b093629f5 100644
--- a/doc/user/misc.xml
+++ b/doc/user/misc.xml
@@ -675,69 +675,4 @@ env.Command('directory_build_info',
</section>
- <section>
- <title>Creating LLVM Compilation Database</title>
-
- <para>
-
- LLVM has defined a JSON Compilation Database Format. This file is in common use as input into LLVM tools
- and many IDE's and editors as well.
- </para>
- <para>
- See
- <ulink url="https://clang.llvm.org/docs/JSONCompilationDatabase.html">
- <citetitle>JSON Compilation Database Format Specification</citetitle>
- </ulink>
- for complete information
- </para>
-
- <para>
-
- The compilation database can be populated with source and target files either with paths relative to the
- top of the build, or using absolute paths.
- </para>
- <para>This is controlled by
- <envar>COMPILATIONDB_USE_ABSPATH=(True|False)</envar>
- which defaults to False.
- </para>
-
- <para>Example of absolute paths for target and source</para>
-
- <sconstruct>
-env = Environment(COMPILATIONDB_USE_ABSPATH=True)
-env.Tool('compilation_db')
-env.CompilationDatabase('compile_commands.json')
- </sconstruct>
-
- <programlisting language="json">
-[
- {
- "command": "gcc -o test_main.o -c test_main.c",
- "directory": "/home/user/sandbox",
- "file": "/home/user/sandbox/test_main.c",
- "target": "/home/user/sandbox/test_main.o"
- }
-]
- </programlisting>
-
-
- <para>Example of relative paths for target and source</para>
-
- <sconstruct>
-env = Environment()
-env.Tool('compilation_db')
-env.CompilationDatabase('compile_commands.json')
- </sconstruct>
- <programlisting language="json">
-[
- {
- "command": "gcc -o test_main.o -c test_main.c",
- "directory": "/home/user/sandbox",
- "file": "test_main.c",
- "target": "test_main.o"
- }
-]
- </programlisting>
-
- </section>
</chapter>
diff --git a/doc/user/sconf.xml b/doc/user/sconf.xml
index 8961606b2..5611bbf19 100644
--- a/doc/user/sconf.xml
+++ b/doc/user/sconf.xml
@@ -97,6 +97,30 @@ env = conf.Finish()
<para>
+ There are a few possible strategies for failing
+ configure checks. Some checks may be for features without
+ which you cannot proceed. The simple approach here is
+ just to exit &SCons; at that point - a number of the
+ examples in this chapter are coded that way. If there
+ are multiple hard requirements, however, it may be
+ friendlier to the user to set a flag in case of any
+ fails of hard requirements and accumulate a record of them,
+ so that on the completion of the &configure_context; they can
+ all be listed prior to failing the build - as it can be frustrating
+ to have to iterate through the setup, fixing one new
+ requirement each iteration. Other checks may be for
+ features which you can do without, and here the strategy
+ will usually be to set a construction variable which the
+ rest of the build can examine for its absence/presence,
+ or to set particular compiler flags, library lists, etc.
+ as appropriate for the circumstances, so you can proceed
+ with the build appropriately based on available features.
+
+ </para>
+
+
+ <para>
+
Note that &SCons; uses its own dependency
mechanism to determine when a check
needs to be run--that is,
diff --git a/test/Docbook/basedir/slideshtml/image/.exclude_tests b/test/Docbook/basedir/slideshtml/image/.exclude_tests
new file mode 100644
index 000000000..966db3c5d
--- /dev/null
+++ b/test/Docbook/basedir/slideshtml/image/.exclude_tests
@@ -0,0 +1 @@
+xsltver.py \ No newline at end of file
diff --git a/test/Docbook/basedir/slideshtml/image/SConstruct b/test/Docbook/basedir/slideshtml/image/SConstruct
index 0620efb0e..2bb86f0a6 100644
--- a/test/Docbook/basedir/slideshtml/image/SConstruct
+++ b/test/Docbook/basedir/slideshtml/image/SConstruct
@@ -1,3 +1,12 @@
+import xsltver
+
+v = xsltver.detectXsltVersion('/usr/share/xml/docbook/stylesheet/docbook-xsl')
+
+ns_ext = ''
+if v >= (1, 78, 0):
+ # Use namespace-aware input file
+ ns_ext = 'ns'
+
env = Environment(tools=['docbook'])
-env.DocbookSlidesHtml('virt', xsl='slides.xsl', base_dir='output/')
+env.DocbookSlidesHtml('virt'+ns_ext, xsl='slides.xsl', base_dir='output/')
diff --git a/test/Docbook/basedir/slideshtml/image/SConstruct.cmd b/test/Docbook/basedir/slideshtml/image/SConstruct.cmd
index d5b73f9ed..f82444de7 100644
--- a/test/Docbook/basedir/slideshtml/image/SConstruct.cmd
+++ b/test/Docbook/basedir/slideshtml/image/SConstruct.cmd
@@ -1,4 +1,13 @@
+import xsltver
+
+v = xsltver.detectXsltVersion('/usr/share/xml/docbook/stylesheet/docbook-xsl')
+
+ns_ext = ''
+if v >= (1, 78, 0):
+ # Use namespace-aware input file
+ ns_ext = 'ns'
+
env = Environment(DOCBOOK_PREFER_XSLTPROC=1, tools=['docbook'])
env.Append(DOCBOOK_XSLTPROCFLAGS=['--novalid', '--nonet'])
-env.DocbookSlidesHtml('virt', xsl='slides.xsl', base_dir='output/')
+env.DocbookSlidesHtml('virt'+ns_ext, xsl='slides.xsl', base_dir='output/')
diff --git a/test/Docbook/basedir/slideshtml/image/slides.xsl b/test/Docbook/basedir/slideshtml/image/slides.xsl
index 24e076dc9..a94e54f98 100644
--- a/test/Docbook/basedir/slideshtml/image/slides.xsl
+++ b/test/Docbook/basedir/slideshtml/image/slides.xsl
@@ -26,6 +26,7 @@
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
+ xmlns:dbs="http://docbook.org/ns/docbook-slides"
version="1.0">
<xsl:import href="file:///usr/share/xml/docbook/stylesheet/docbook-xsl/slides/xhtml/plain.xsl"/>
@@ -34,22 +35,5 @@
<xsl:param name="section.autolabel" select="1"/>
<xsl:param name="base.dir" select="'output/'"/>
<xsl:param name="html.stylesheet" select="'scons.css'"/>
-<xsl:param name="generate.toc">
-/appendix toc,title
-article/appendix nop
-/article toc,title
-book toc,title,figure,table,example,equation
-/chapter toc,title
-part toc,title
-/preface toc,title
-reference toc,title
-/sect1 toc
-/sect2 toc
-/sect3 toc
-/sect4 toc
-/sect5 toc
-/section toc
-set toc,title
-</xsl:param>
</xsl:stylesheet>
diff --git a/test/Docbook/basedir/slideshtml/image/virtns.xml b/test/Docbook/basedir/slideshtml/image/virtns.xml
new file mode 100644
index 000000000..f64c624cf
--- /dev/null
+++ b/test/Docbook/basedir/slideshtml/image/virtns.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<dbs:slides xmlns="http://docbook.org/ns/docbook"
+ xmlns:dbs="http://docbook.org/ns/docbook-slides"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <info>
+ <title>Virtuelles Kopieren</title>
+
+ <titleabbrev>Virtuelles Kopieren</titleabbrev>
+
+ <copyright>
+ <year>2007</year>
+
+ <holder>Femutec GmbH</holder>
+ </copyright>
+
+ <author>
+ <firstname>Dirk</firstname>
+
+ <surname>Baechle</surname>
+ </author>
+
+ <pubdate>09.07.2007</pubdate>
+ </info>
+
+<dbs:foilgroup>
+<title>Group</title>
+ <dbs:foil>
+ <title>sfForming</title>
+
+ </dbs:foil>
+</dbs:foilgroup>
+</dbs:slides>
+
diff --git a/test/Docbook/basedir/slideshtml/image/xsltver.py b/test/Docbook/basedir/slideshtml/image/xsltver.py
new file mode 100644
index 000000000..c8453249e
--- /dev/null
+++ b/test/Docbook/basedir/slideshtml/image/xsltver.py
@@ -0,0 +1,20 @@
+import os
+import re
+
+def detectXsltVersion(fpath):
+ """ Return a tuple with the version of the Docbook XSLT stylesheets,
+ or (0, 0, 0) if no stylesheets are installed or the VERSION
+ file couldn't be found/parsed correctly.
+ """
+ with open(os.path.join(fpath, 'VERSION'), 'rb') as fin:
+ re_version = re.compile("<fm:Version>([^<]+)</fm:Version>".encode('utf-8'))
+ m = re_version.search(fin.read())
+ if m:
+ try:
+ return tuple(map(int, m.group(1).split(b'.')))
+ except Exception:
+ return (0, 0, 0)
+
+ return (0, 0, 0)
+
+ return (0, 0, 0)
diff --git a/test/Docbook/basedir/slideshtml/slideshtml.py b/test/Docbook/basedir/slideshtml/slideshtml.py
index b4bdec36d..674138d94 100644
--- a/test/Docbook/basedir/slideshtml/slideshtml.py
+++ b/test/Docbook/basedir/slideshtml/slideshtml.py
@@ -46,16 +46,11 @@ test.dir_fixture('image')
# Normal invocation
test.run(stderr=None)
test.must_not_be_empty(test.workpath('output/index.html'))
-test.must_not_be_empty(test.workpath('output/toc.html'))
-test.must_not_be_empty(test.workpath('output/foil01.html'))
-test.must_not_be_empty(test.workpath('output/foilgroup01.html'))
+test.must_contain(test.workpath('output/index.html'), 'sfForming')
# Cleanup
test.run(arguments='-c')
test.must_not_exist(test.workpath('output/index.html'))
-test.must_not_exist(test.workpath('output/toc.html'))
-test.must_not_exist(test.workpath('output/foil01.html'))
-test.must_not_exist(test.workpath('output/foilgroup01.html'))
test.pass_test()
diff --git a/test/Docbook/basedir/slideshtml/slideshtml_cmd.py b/test/Docbook/basedir/slideshtml/slideshtml_cmd.py
index 5d2556d1e..901d94e2a 100644
--- a/test/Docbook/basedir/slideshtml/slideshtml_cmd.py
+++ b/test/Docbook/basedir/slideshtml/slideshtml_cmd.py
@@ -43,16 +43,11 @@ test.dir_fixture('image')
# Normal invocation
test.run(arguments=['-f','SConstruct.cmd'], stderr=None)
test.must_not_be_empty(test.workpath('output/index.html'))
-test.must_not_be_empty(test.workpath('output/toc.html'))
-test.must_not_be_empty(test.workpath('output/foil01.html'))
-test.must_not_be_empty(test.workpath('output/foilgroup01.html'))
+test.must_contain(test.workpath('output/index.html'), 'sfForming')
# Cleanup
test.run(arguments=['-f','SConstruct.cmd','-c'], stderr=None)
test.must_not_exist(test.workpath('output/index.html'))
-test.must_not_exist(test.workpath('output/toc.html'))
-test.must_not_exist(test.workpath('output/foil01.html'))
-test.must_not_exist(test.workpath('output/foilgroup01.html'))
test.pass_test()
diff --git a/test/Docbook/basic/slideshtml/image/.exclude_tests b/test/Docbook/basic/slideshtml/image/.exclude_tests
new file mode 100644
index 000000000..966db3c5d
--- /dev/null
+++ b/test/Docbook/basic/slideshtml/image/.exclude_tests
@@ -0,0 +1 @@
+xsltver.py \ No newline at end of file
diff --git a/test/Docbook/basic/slideshtml/image/SConstruct b/test/Docbook/basic/slideshtml/image/SConstruct
index 034a3c7c8..e1437daaa 100644
--- a/test/Docbook/basic/slideshtml/image/SConstruct
+++ b/test/Docbook/basic/slideshtml/image/SConstruct
@@ -1,3 +1,12 @@
+import xsltver
+
+v = xsltver.detectXsltVersion('/usr/share/xml/docbook/stylesheet/docbook-xsl')
+
+ns_ext = ''
+if v >= (1, 78, 0):
+ # Use namespace-aware input file
+ ns_ext = 'ns'
+
env = Environment(tools=['docbook'])
-env.DocbookSlidesHtml('virt')
+env.DocbookSlidesHtml('virt'+ns_ext, xsl='/usr/share/xml/docbook/stylesheet/docbook-xsl/slides/xhtml/plain.xsl')
diff --git a/test/Docbook/basic/slideshtml/image/SConstruct.cmd b/test/Docbook/basic/slideshtml/image/SConstruct.cmd
index ad5668ce2..08cbc3181 100644
--- a/test/Docbook/basic/slideshtml/image/SConstruct.cmd
+++ b/test/Docbook/basic/slideshtml/image/SConstruct.cmd
@@ -1,4 +1,13 @@
+import xsltver
+
+v = xsltver.detectXsltVersion('/usr/share/xml/docbook/stylesheet/docbook-xsl')
+
+ns_ext = ''
+if v >= (1, 78, 0):
+ # Use namespace-aware input file
+ ns_ext = 'ns'
+
env = Environment(DOCBOOK_PREFER_XSLTPROC=1, tools=['docbook'])
env.Append(DOCBOOK_XSLTPROCFLAGS=['--novalid', '--nonet'])
-env.DocbookSlidesHtml('virt')
+env.DocbookSlidesHtml('virt'+ns_ext, xsl='/usr/share/xml/docbook/stylesheet/docbook-xsl/slides/xhtml/plain.xsl')
diff --git a/test/Docbook/basic/slideshtml/image/virtns.xml b/test/Docbook/basic/slideshtml/image/virtns.xml
new file mode 100644
index 000000000..f64c624cf
--- /dev/null
+++ b/test/Docbook/basic/slideshtml/image/virtns.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<dbs:slides xmlns="http://docbook.org/ns/docbook"
+ xmlns:dbs="http://docbook.org/ns/docbook-slides"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <info>
+ <title>Virtuelles Kopieren</title>
+
+ <titleabbrev>Virtuelles Kopieren</titleabbrev>
+
+ <copyright>
+ <year>2007</year>
+
+ <holder>Femutec GmbH</holder>
+ </copyright>
+
+ <author>
+ <firstname>Dirk</firstname>
+
+ <surname>Baechle</surname>
+ </author>
+
+ <pubdate>09.07.2007</pubdate>
+ </info>
+
+<dbs:foilgroup>
+<title>Group</title>
+ <dbs:foil>
+ <title>sfForming</title>
+
+ </dbs:foil>
+</dbs:foilgroup>
+</dbs:slides>
+
diff --git a/test/Docbook/basic/slideshtml/image/xsltver.py b/test/Docbook/basic/slideshtml/image/xsltver.py
new file mode 100644
index 000000000..c8453249e
--- /dev/null
+++ b/test/Docbook/basic/slideshtml/image/xsltver.py
@@ -0,0 +1,20 @@
+import os
+import re
+
+def detectXsltVersion(fpath):
+ """ Return a tuple with the version of the Docbook XSLT stylesheets,
+ or (0, 0, 0) if no stylesheets are installed or the VERSION
+ file couldn't be found/parsed correctly.
+ """
+ with open(os.path.join(fpath, 'VERSION'), 'rb') as fin:
+ re_version = re.compile("<fm:Version>([^<]+)</fm:Version>".encode('utf-8'))
+ m = re_version.search(fin.read())
+ if m:
+ try:
+ return tuple(map(int, m.group(1).split(b'.')))
+ except Exception:
+ return (0, 0, 0)
+
+ return (0, 0, 0)
+
+ return (0, 0, 0)
diff --git a/test/Docbook/basic/slideshtml/slideshtml.py b/test/Docbook/basic/slideshtml/slideshtml.py
index 2cfe3e8cc..93592106f 100644
--- a/test/Docbook/basic/slideshtml/slideshtml.py
+++ b/test/Docbook/basic/slideshtml/slideshtml.py
@@ -46,16 +46,11 @@ test.dir_fixture('image')
# Normal invocation
test.run(stderr=None)
test.must_not_be_empty(test.workpath('index.html'))
-test.must_not_be_empty(test.workpath('toc.html'))
-test.must_not_be_empty(test.workpath('foil01.html'))
-test.must_not_be_empty(test.workpath('foilgroup01.html'))
+test.must_contain(test.workpath('index.html'), 'sfForming')
# Cleanup
test.run(arguments='-c')
test.must_not_exist(test.workpath('index.html'))
-test.must_not_exist(test.workpath('toc.html'))
-test.must_not_exist(test.workpath('foil01.html'))
-test.must_not_exist(test.workpath('foilgroup01.html'))
test.pass_test()
diff --git a/test/Docbook/basic/slideshtml/slideshtml_cmd.py b/test/Docbook/basic/slideshtml/slideshtml_cmd.py
index c51f83139..7ebc8d48c 100644
--- a/test/Docbook/basic/slideshtml/slideshtml_cmd.py
+++ b/test/Docbook/basic/slideshtml/slideshtml_cmd.py
@@ -43,16 +43,11 @@ test.dir_fixture('image')
# Normal invocation
test.run(arguments=['-f','SConstruct.cmd'], stderr=None)
test.must_not_be_empty(test.workpath('index.html'))
-test.must_not_be_empty(test.workpath('toc.html'))
-test.must_not_be_empty(test.workpath('foil01.html'))
-test.must_not_be_empty(test.workpath('foilgroup01.html'))
+test.must_contain(test.workpath('index.html'), 'sfForming')
# Cleanup
test.run(arguments=['-f','SConstruct.cmd','-c'], stderr=None)
test.must_not_exist(test.workpath('index.html'))
-test.must_not_exist(test.workpath('toc.html'))
-test.must_not_exist(test.workpath('foil01.html'))
-test.must_not_exist(test.workpath('foilgroup01.html'))
test.pass_test()
diff --git a/test/Docbook/rootname/slideshtml/image/.exclude_tests b/test/Docbook/rootname/slideshtml/image/.exclude_tests
new file mode 100644
index 000000000..966db3c5d
--- /dev/null
+++ b/test/Docbook/rootname/slideshtml/image/.exclude_tests
@@ -0,0 +1 @@
+xsltver.py \ No newline at end of file
diff --git a/test/Docbook/rootname/slideshtml/image/SConstruct b/test/Docbook/rootname/slideshtml/image/SConstruct
index 769314c7d..4f1079e6f 100644
--- a/test/Docbook/rootname/slideshtml/image/SConstruct
+++ b/test/Docbook/rootname/slideshtml/image/SConstruct
@@ -1,3 +1,12 @@
+import xsltver
+
+v = xsltver.detectXsltVersion('/usr/share/xml/docbook/stylesheet/docbook-xsl')
+
+ns_ext = ''
+if v >= (1, 78, 0):
+ # Use namespace-aware input file
+ ns_ext = 'ns'
+
env = Environment(tools=['docbook'])
-env.DocbookSlidesHtml('manual.html', 'virt', xsl='slides.xsl')
+env.DocbookSlidesHtml('manual.html', 'virt'+ns_ext, xsl='slides.xsl')
diff --git a/test/Docbook/rootname/slideshtml/image/slides.xsl b/test/Docbook/rootname/slideshtml/image/slides.xsl
index 29058f111..a490b0a34 100644
--- a/test/Docbook/rootname/slideshtml/image/slides.xsl
+++ b/test/Docbook/rootname/slideshtml/image/slides.xsl
@@ -26,6 +26,7 @@
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
+ xmlns:dbs="http://docbook.org/ns/docbook-slides"
version="1.0">
<xsl:import href="file:///usr/share/xml/docbook/stylesheet/docbook-xsl/slides/xhtml/plain.xsl"/>
@@ -34,22 +35,5 @@
<xsl:param name="section.autolabel" select="1"/>
<xsl:param name="titlefoil.html" select="'manual.html'"/>
<xsl:param name="html.stylesheet" select="'scons.css'"/>
-<xsl:param name="generate.toc">
-/appendix toc,title
-article/appendix nop
-/article toc,title
-book toc,title,figure,table,example,equation
-/chapter toc,title
-part toc,title
-/preface toc,title
-reference toc,title
-/sect1 toc
-/sect2 toc
-/sect3 toc
-/sect4 toc
-/sect5 toc
-/section toc
-set toc,title
-</xsl:param>
</xsl:stylesheet>
diff --git a/test/Docbook/rootname/slideshtml/image/virtns.xml b/test/Docbook/rootname/slideshtml/image/virtns.xml
new file mode 100644
index 000000000..f64c624cf
--- /dev/null
+++ b/test/Docbook/rootname/slideshtml/image/virtns.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<dbs:slides xmlns="http://docbook.org/ns/docbook"
+ xmlns:dbs="http://docbook.org/ns/docbook-slides"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <info>
+ <title>Virtuelles Kopieren</title>
+
+ <titleabbrev>Virtuelles Kopieren</titleabbrev>
+
+ <copyright>
+ <year>2007</year>
+
+ <holder>Femutec GmbH</holder>
+ </copyright>
+
+ <author>
+ <firstname>Dirk</firstname>
+
+ <surname>Baechle</surname>
+ </author>
+
+ <pubdate>09.07.2007</pubdate>
+ </info>
+
+<dbs:foilgroup>
+<title>Group</title>
+ <dbs:foil>
+ <title>sfForming</title>
+
+ </dbs:foil>
+</dbs:foilgroup>
+</dbs:slides>
+
diff --git a/test/Docbook/rootname/slideshtml/image/xsltver.py b/test/Docbook/rootname/slideshtml/image/xsltver.py
new file mode 100644
index 000000000..c8453249e
--- /dev/null
+++ b/test/Docbook/rootname/slideshtml/image/xsltver.py
@@ -0,0 +1,20 @@
+import os
+import re
+
+def detectXsltVersion(fpath):
+ """ Return a tuple with the version of the Docbook XSLT stylesheets,
+ or (0, 0, 0) if no stylesheets are installed or the VERSION
+ file couldn't be found/parsed correctly.
+ """
+ with open(os.path.join(fpath, 'VERSION'), 'rb') as fin:
+ re_version = re.compile("<fm:Version>([^<]+)</fm:Version>".encode('utf-8'))
+ m = re_version.search(fin.read())
+ if m:
+ try:
+ return tuple(map(int, m.group(1).split(b'.')))
+ except Exception:
+ return (0, 0, 0)
+
+ return (0, 0, 0)
+
+ return (0, 0, 0)
diff --git a/test/Docbook/rootname/slideshtml/slideshtml.py b/test/Docbook/rootname/slideshtml/slideshtml.py
index 2d8500e63..daa5d8d33 100644
--- a/test/Docbook/rootname/slideshtml/slideshtml.py
+++ b/test/Docbook/rootname/slideshtml/slideshtml.py
@@ -46,16 +46,11 @@ test.dir_fixture('image')
# Normal invocation
test.run(stderr=None)
test.must_not_be_empty(test.workpath('manual.html'))
-test.must_not_be_empty(test.workpath('toc.html'))
-test.must_not_be_empty(test.workpath('foil01.html'))
-test.must_not_be_empty(test.workpath('foilgroup01.html'))
+test.must_contain(test.workpath('manual.html'), 'sfForming')
# Cleanup
test.run(arguments='-c')
test.must_not_exist(test.workpath('manual.html'))
-test.must_not_exist(test.workpath('toc.html'))
-test.must_not_exist(test.workpath('foil01.html'))
-test.must_not_exist(test.workpath('foilgroup01.html'))
test.pass_test()
diff --git a/test/Interactive/configure.py b/test/Interactive/configure.py
index 44a53eb70..dfe1c7f6d 100644
--- a/test/Interactive/configure.py
+++ b/test/Interactive/configure.py
@@ -32,6 +32,73 @@ Also tests that "b" can be used as a synonym for "build".
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import TestSCons
+import TestCmd
+import re
+
+# The order of the statements in the expected stdout is unreliable.
+
+# case 1
+# scons>>> .*foo\.cpp.*
+# scons>>> scons: `foo.obj' is up to date.
+# scons>>> .*foo\.cpp.*
+# scons>>> scons: `foo.obj' is up to date.
+# scons>>>\s*
+
+# case 2
+# scons>>> .*foo\.cpp.*
+# scons>>> .*foo\.cpp.*
+# scons>>> scons: `foo.obj' is up to date.
+# scons>>> scons: `foo.obj' is up to date.
+# scons>>>\s*
+
+# The order of this list is related to the order of the counts below
+expected_patterns = [
+ re.compile("^scons>>> .*foo\.cpp.*$"),
+ re.compile("^scons>>> scons: `foo.obj' is up to date\.$"),
+ re.compile("^scons>>>\s*$"),
+]
+
+# The order of this list is related to the order of the regular expressions above
+expected_counts = [
+ [2,2,1], # case 1 and 2
+]
+
+# This is used for the diff output when the test fails and to distinguish between
+# stdout and stderr in the match function below.
+expect_stdout = r"""scons>>> .*foo\.cpp.*
+scons>>> .*foo\.cpp.*
+scons>>> scons: `foo.obj' is up to date.
+scons>>> scons: `foo.obj' is up to date.
+scons>>>\s*
+"""
+
+def match_custom(lines, expect):
+
+ if expect != expect_stdout:
+ # stderr
+ if lines == expect:
+ return 1
+ return None
+
+ # taken directly from TestCmd
+ if not TestCmd.is_List(lines):
+ # CRs mess up matching (Windows) so split carefully
+ lines = re.split('\r?\n', lines)
+
+ # record number of matches for each regex
+ n_actual = [0] * len(expected_patterns)
+ for line in lines:
+ for i, regex in enumerate(expected_patterns):
+ if regex.search(line):
+ n_actual[i] += 1
+ break
+
+ # compare actual counts to expected counts
+ for n_expect in expected_counts:
+ if n_actual == n_expect:
+ return 1
+
+ return None
_python_ = TestSCons._python_
@@ -108,14 +175,7 @@ scons.send("b foo.obj\n")
scons.send("build foo.obj\n")
-expect_stdout = r"""scons>>> .*foo\.cpp.*
-scons>>> .*foo\.cpp.*
-scons>>> scons: `foo.obj' is up to date.
-scons>>> scons: `foo.obj' is up to date.
-scons>>>\s*
-"""
-
-test.finish(scons, stdout = expect_stdout, match=TestSCons.match_re)
+test.finish(scons, stdout = expect_stdout, stderr = '', match = match_custom)
test.pass_test()
diff --git a/test/MSVS/vs-14.0-exec.py b/test/MSVS/vs-14.0-exec.py
index 1d5b9bc89..7e919ba83 100644
--- a/test/MSVS/vs-14.0-exec.py
+++ b/test/MSVS/vs-14.0-exec.py
@@ -81,6 +81,7 @@ env.Program('foo.c')
""" % locals())
test.write(['sub dir', 'foo.c'], r"""
+#include <stdio.h>
int
main(int argc, char *argv)
{
diff --git a/test/MSVS/vs-14.0Exp-exec.py b/test/MSVS/vs-14.0Exp-exec.py
index cb4aaf315..5d2a5859c 100644
--- a/test/MSVS/vs-14.0Exp-exec.py
+++ b/test/MSVS/vs-14.0Exp-exec.py
@@ -77,6 +77,7 @@ env.Program('foo.c')
""" % locals())
test.write(['sub dir', 'foo.c'], r"""
+#include <stdio.h>
int
main(int argc, char *argv)
{
diff --git a/test/MSVS/vs-14.1-exec.py b/test/MSVS/vs-14.1-exec.py
index bcf4fbe1f..2accaafab 100644
--- a/test/MSVS/vs-14.1-exec.py
+++ b/test/MSVS/vs-14.1-exec.py
@@ -81,6 +81,7 @@ env.Program('foo.c')
""" % locals())
test.write(['sub dir', 'foo.c'], r"""
+#include <stdio.h>
int
main(int argc, char *argv)
{
diff --git a/test/MSVS/vs-14.2-exec.py b/test/MSVS/vs-14.2-exec.py
index 1894031dd..5a3079d07 100644
--- a/test/MSVS/vs-14.2-exec.py
+++ b/test/MSVS/vs-14.2-exec.py
@@ -81,6 +81,7 @@ env.Program('foo.c')
""" % locals())
test.write(['sub dir', 'foo.c'], r"""
+#include <stdio.h>
int
main(int argc, char *argv)
{
diff --git a/test/fixture/no_msvc/no_msvcs_sconstruct.py b/test/fixture/no_msvc/no_msvcs_sconstruct.py
index 11a06ac9b..18366d8f3 100644
--- a/test/fixture/no_msvc/no_msvcs_sconstruct.py
+++ b/test/fixture/no_msvc/no_msvcs_sconstruct.py
@@ -1,7 +1,7 @@
import SCons
import SCons.Tool.MSCommon
-def DummyVsWhere(env, msvc_version):
+def DummyVsWhere(msvc_version, env):
# not testing versions with vswhere, so return none
return None
diff --git a/testing/framework/test-framework.rst b/testing/framework/test-framework.rst
index dca468426..265b82e74 100644
--- a/testing/framework/test-framework.rst
+++ b/testing/framework/test-framework.rst
@@ -143,7 +143,7 @@ effects in place.
The ``runtest.py`` script supports additional options to run
tests against unpacked packages in the ``build/test-*/`` subdirectories.
-If you are testing a separate Tool outside of the SCons source tree,
+If you are testing a separate Tool outside of the SCons source tree,
call the ``runtest.py`` script in *external* (stand-alone) mode::
$ python ~/scons/runtest.py -e -a
@@ -431,7 +431,7 @@ For more complex testing scenarios you can use ``file_fixture`` with
the optional second argument (or the keyword arg ``dstfile``) to assign
a name to the file being copied. For example, some tests need to
write multiple ``SConstruct`` files across the full run.
-These files can be given different names in the source (perhaps using a
+These files can be given different names in the source (perhaps using a
sufffix to distinguish them), and then be sucessively copied to the
final name as needed::
@@ -525,11 +525,11 @@ adding debug prints may be more useful.
Test infrastructure
===================
-The main test API in the ``TestSCons.py`` class. ``TestSCons``
+The main test API is defined in the ``TestSCons`` class. ``TestSCons``
is a subclass of ``TestCommon``, which is a subclass of ``TestCmd``.
All those classes are defined in Python files of the same name
-in ``testing/framework``. Start in
-``testing/framework/TestCmd.py`` for the base API definitions, like how
+in ``testing/framework``.
+Start in ``testing/framework/TestCmd.py`` for the base API definitions, like how
to create files (``test.write()``) and run commands (``test.run()``).
Use ``TestSCons`` for the end-to-end tests in ``test``, but use
@@ -548,7 +548,7 @@ The match functions work like this:
``TestSCons.match_re_dotall``
match all the lines against a single RE
-
+
* Joins the lines with newline (unless already a string)
* joins the REs with newline (unless it's a string) and puts ``^..$``
around the whole thing
@@ -571,35 +571,57 @@ proceeding with the test. For example, it's hard to test complilng code with
a C compiler if no C compiler exists. In this case, the test should be
skipped.
-Here's a simple example::
+Here's a simple example for end-to-end tests::
- #!python
intelc = test.detect_tool('intelc', prog='icpc')
if not intelc:
test.skip_test("Could not load 'intelc' Tool; skipping test(s).\n")
-See ``testing/framework/TestSCons.py`` for the ``detect_tool`` method.
+See ``testing/framework/TestSCons.py`` for the ``detect_tool()`` method.
It calls the tool's ``generate()`` method, and then looks for the given
program (tool name by default) in ``env['ENV']['PATH']``.
-The ``where_is`` method can be used to look for programs that
+The ``where_is()`` method can be used to look for programs that
are do not have tool specifications. The existing test code
will have many samples of using either or both of these to detect
if it is worth even proceeding with a test.
+For the unit tests, there are decorators for conditional skipping and
+other actions that will produce the correct output display and statistics
+in abnormal situations.
+
+``@unittest.skip(reason)``
+ Unconditionally skip the decorated test.
+ reason should describe why the test is being skipped.
+
+``@unittest.skipIf(condition, reason)``
+ Skip the decorated test if condition is true.
+
+``@unittest.skipUnless(condition, reason)``
+ Skip the decorated test unless condition is true.
+
+``@unittest.expectedFailure``
+ Mark the test as an expected failure.
+ If the test fails it will be considered a success.
+ If the test passes, it will be considered a failure.
+
+You can also directly call ``testcase.skipTest(reason)``.
+
Note that it is usually possible to test at least part of the operation of
a tool without the underlying program. Tools are responsible for setting up
construction variables and having the right builders, scanners and emitters
plumbed into the environment. These things can be tested by mocking the
behavior of the executable. Many examples of this can be found in the
-``test`` directory. *TODO: point to one example*.
-
-This leads to a suggestion for test organization: keep tool tests which
-don't need the underlying program in separate files from ones which do -
-it is clearer what is going on if we can see in the test results that the
-plumbing tests worked but the ones using the underlying program were skipped
-rather than seeing all the tests for a tool passing or being skipped.
-The framework doesn't have a way to indicate a partial skip - if you executed
+``test`` directory. See for example ``test/subdivide.py``.
+
+This leads to a suggestion for E2E test organization because the framework
+doesn't have a way to indicate a partial skip - if you executed
200 lines of test, then found a condition which caused you to skip the
last 20 lines, the whole test is marked as a skip;
it also doesn't have a way to indicate a partial pass.
+To improve on this, keep tool tests which don't need the
+underlying program in separate files from ones which do -
+that way one can see in the test results that the "plumbing"
+tests worked even if the the ones using the underlying program
+maybe were skipped.
+