diff --git a/CHANGES.txt b/CHANGES.txt
index 17dfb07d05..ee1139a9e8 100755
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -135,6 +135,9 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER
Note that these are called for every build command run by SCons. It could have considerable
performance impact if not used carefully.
to connect to the server during start up.
+ - Ninja: Added command line variable NINJA_CMD_ARGS that allows to pass through ninja command line args.
+ This can also be set in your Environment().
+
From Mats Wichmann:
- Tweak the way default site_scons paths on Windows are expressed to
diff --git a/RELEASE.txt b/RELEASE.txt
index aa60c8be94..c2bd2b4e42 100755
--- a/RELEASE.txt
+++ b/RELEASE.txt
@@ -14,7 +14,8 @@ NOTE: If you build with Python 3.10.0 and then rebuild with 3.10.1 (or higher),
NEW FUNCTIONALITY
-----------------
-- Added MSVC_USE_SCRIPT_ARGS variable to pass arguments to MSVC_USE_SCRIPT.
+- Added MSVC_USE_SCRIPT_ARGS Environment variable which specifies command line arguments
+ to pass to the script specified by MSVC_USE_SCRIPT.
- Added Configure.CheckMember() checker to check if struct/class has the specified member.
- Added SHELL_ENV_GENERATORS construction variable. This variable should be set to a list
(or an iterable) which contains functions to be called in order
@@ -24,6 +25,8 @@ NEW FUNCTIONALITY
performance impact if not used carefully.
- Added MSVC_USE_SETTINGS variable to pass a dictionary to configure the msvc compiler
system environment as an alternative to bypassing Visual Studio autodetection entirely.
+- Ninja: Added command line variable NINJA_CMD_ARGS that allows to pass through ninja command line args.
+ This can also be set in your Environment().
- Added a global policy setting and an environment policy variable for specifying the action to
be taken when an msvc request cannot be satisfied. The available options are "error",
"exception", "warning", "warn", "ignore", and "suppress". The global policy variable may be
diff --git a/SCons/Tool/ninja/__init__.py b/SCons/Tool/ninja/__init__.py
index 04a7abbe74..ca659dccfc 100644
--- a/SCons/Tool/ninja/__init__.py
+++ b/SCons/Tool/ninja/__init__.py
@@ -87,7 +87,7 @@ def ninja_builder(env, target, source):
if str(env.get("NINJA_DISABLE_AUTO_RUN")).lower() not in ['1', 'true']:
num_jobs = env.get('NINJA_MAX_JOBS', env.GetOption("num_jobs"))
- cmd += ['-j' + str(num_jobs)] + NINJA_CMDLINE_TARGETS
+ cmd += ['-j' + str(num_jobs)] + env.get('NINJA_CMD_ARGS', '').split() + NINJA_CMDLINE_TARGETS
print(f"ninja will be run with command line targets: {' '.join(NINJA_CMDLINE_TARGETS)}")
print("Executing:", str(' '.join(cmd)))
@@ -125,6 +125,14 @@ def execute_ninja():
sys.stdout.write("\n")
+def options(opts):
+ """
+ Add command line Variables for Ninja builder.
+ """
+ opts.AddVariables(
+ ("NINJA_CMD_ARGS", "Arguments to pass to ninja"),
+ )
+
def exists(env):
"""Enable if called."""
@@ -197,7 +205,7 @@ def generate(env):
env["NINJA_SCONS_DAEMON_PORT"] = env.get('NINJA_SCONS_DAEMON_PORT', random.randint(10000, 60000))
if GetOption("disable_ninja"):
- env.SConsignFile(os.path.join(str(env['NINJA_DIR']),'.ninja.sconsign'))
+ env.SConsignFile(os.path.join(str(env['NINJA_DIR']), '.ninja.sconsign'))
# here we allow multiple environments to construct rules and builds
# into the same ninja file
diff --git a/SCons/Tool/ninja/ninja.xml b/SCons/Tool/ninja/ninja.xml
index 6b247d0c0a..664d521780 100644
--- a/SCons/Tool/ninja/ninja.xml
+++ b/SCons/Tool/ninja/ninja.xml
@@ -77,7 +77,7 @@ See its __doc__ string for a discussion of the format.
- IMPLICIT_COMMAND_DEPENDENCIES
- NINJA_SCONS_DAEMON_KEEP_ALIVE
- NINJA_SCONS_DAEMON_PORT
-
+ - NINJA_CMD_ARGS
@@ -395,5 +395,22 @@ python -m pip install ninja
+
+
+
+ A string which will pass arguments through SCons to the ninja command when scons executes ninja.
+ Has no effect if &cv-NINJA_DISABLE_AUTO_RUN; is set.
+
+
+ This value can also be passed on the command line:
+
+
+scons NINJA_CMD_ARGS=-v
+or
+scons NINJA_CMD_ARGS="-v -j 3"
+
+
+
+
diff --git a/SCons/Tool/packaging/__init__.py b/SCons/Tool/packaging/__init__.py
index 68cedeb12a..6fe01c190f 100644
--- a/SCons/Tool/packaging/__init__.py
+++ b/SCons/Tool/packaging/__init__.py
@@ -217,10 +217,11 @@ def generate(env):
env['BUILDERS']['Package'] = Package
env['BUILDERS']['Tag'] = Tag
+
def exists(env):
return 1
-# XXX
+
def options(opts):
opts.AddVariables(
EnumVariable('PACKAGETYPE',
diff --git a/test/ninja/generate_and_build.py b/test/ninja/generate_and_build.py
index 91be108176..e1c26d4bb0 100644
--- a/test/ninja/generate_and_build.py
+++ b/test/ninja/generate_and_build.py
@@ -49,12 +49,17 @@
test.file_fixture('ninja_test_sconscripts/sconstruct_generate_and_build', 'SConstruct')
# generate simple build
-test.run(stdout=None)
+test.run(stdout=None, arguments='NINJA_CMD_ARGS=-v')
test.must_contain_all_lines(test.stdout(), ['Generating: build.ninja'])
test.must_contain_all(test.stdout(), 'Executing:')
test.must_contain_all(test.stdout(), 'ninja%(_exe)s -f' % locals())
+test.must_contain_all(test.stdout(), ' -j1 -v')
test.run(program=test.workpath('foo' + _exe), stdout="foo.c")
+# Test multiple args for NINJA_CMD_ARGS
+test.run(stdout=None, arguments={'NINJA_CMD_ARGS':"-v -j3"})
+test.must_contain_all(test.stdout(), ' -v -j3')
+
# clean build and ninja files
test.run(arguments='-c', stdout=None)
test.must_contain_all_lines(test.stdout(), [
diff --git a/testing/framework/TestCmd.py b/testing/framework/TestCmd.py
index 575912146a..a70df0fe7f 100644
--- a/testing/framework/TestCmd.py
+++ b/testing/framework/TestCmd.py
@@ -1125,6 +1125,9 @@ def command_args(self, program=None, interpreter=None, arguments=None):
interpreter = [interpreter]
cmd = list(interpreter) + cmd
if arguments:
+ if isinstance(arguments, dict):
+ cmd.extend(["%s=%s" % (k, v) for k, v in arguments.items()])
+ return cmd
if isinstance(arguments, str):
arguments = arguments.split()
cmd.extend(arguments)
@@ -1569,6 +1572,9 @@ def run(self, program=None,
The specified program will have the original directory
prepended unless it is enclosed in a [list].
+
+ argument: If this is a dict() then will create arguments with KEY+VALUE for
+ each entry in the dict.
"""
if self.external:
if not program:
diff --git a/testing/framework/TestCmdTests.py b/testing/framework/TestCmdTests.py
index 3b29091f72..8e5ecda29f 100644
--- a/testing/framework/TestCmdTests.py
+++ b/testing/framework/TestCmdTests.py
@@ -2261,6 +2261,12 @@ def test_command_args(self):
expect = ['PYTHON', default_prog, 'arg3', 'arg4']
assert r == expect, (expect, r)
+ # Test arguments = dict
+ r = test.command_args(interpreter='PYTHON', arguments={'VAR1':'1'})
+ expect = ['PYTHON', default_prog, 'VAR1=1']
+ assert r == expect, (expect, r)
+
+
test.interpreter_set('default_python')
r = test.command_args()
@@ -2585,7 +2591,7 @@ def test_send(self):
with open(t.recv_out_path, 'rb') as f:
result = to_str(f.read())
expect = 'script_recv: ' + input
- assert result == expect, repr(result)
+ assert result == expect, "Result:[%s] should match\nExpected:[%s]" % (result, expect)
p = test.start(stdin=1)
input = 'send() input to the receive script\n'
@@ -3103,7 +3109,7 @@ def test_workpath(self):
assert wpath == os.path.join(test.workdir, 'foo', 'bar')
-
+@unittest.skipIf(sys.platform == 'win32', "Don't run on win32")
class readable_TestCase(TestCmdTestCase):
def test_readable(self):
"""Test readable()"""
@@ -3183,7 +3189,7 @@ def test_writable(self):
assert not _is_writable(test.workpath('file1'))
-
+@unittest.skipIf(sys.platform == 'win32', "Don't run on win32")
class executable_TestCase(TestCmdTestCase):
def test_executable(self):
"""Test executable()"""
@@ -3331,70 +3337,8 @@ def test_variables(self):
assert stderr == "", stderr
-
if __name__ == "__main__":
- tclasses = [
- __init__TestCase,
- basename_TestCase,
- cleanup_TestCase,
- chmod_TestCase,
- combine_TestCase,
- command_args_TestCase,
- description_TestCase,
- diff_TestCase,
- diff_stderr_TestCase,
- diff_stdout_TestCase,
- exit_TestCase,
- fail_test_TestCase,
- interpreter_TestCase,
- match_TestCase,
- match_exact_TestCase,
- match_re_dotall_TestCase,
- match_re_TestCase,
- match_stderr_TestCase,
- match_stdout_TestCase,
- no_result_TestCase,
- pass_test_TestCase,
- preserve_TestCase,
- program_TestCase,
- read_TestCase,
- rmdir_TestCase,
- run_TestCase,
- run_verbose_TestCase,
- set_diff_function_TestCase,
- set_match_function_TestCase,
- sleep_TestCase,
- start_TestCase,
- stderr_TestCase,
- stdin_TestCase,
- stdout_TestCase,
- subdir_TestCase,
- symlink_TestCase,
- tempdir_TestCase,
- timeout_TestCase,
- unlink_TestCase,
- touch_TestCase,
- verbose_TestCase,
- workdir_TestCase,
- workdirs_TestCase,
- workpath_TestCase,
- writable_TestCase,
- write_TestCase,
- variables_TestCase,
- ]
- if sys.platform != 'win32':
- tclasses.extend([
- executable_TestCase,
- readable_TestCase,
- ])
- suite = unittest.TestSuite()
- for tclass in tclasses:
- loader = unittest.TestLoader()
- loader.testMethodPrefix = 'test_'
- names = loader.getTestCaseNames(tclass)
- suite.addTests([tclass(n) for n in names])
- if not unittest.TextTestRunner().run(suite).wasSuccessful():
- sys.exit(1)
+ unittest.main()
# Local Variables:
# tab-width:4