__init__.py (SCons-4.3.0) | : | __init__.py (SCons-4.4.0) | ||
---|---|---|---|---|
skipping to change at line 29 | skipping to change at line 29 | |||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | |||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
# | # | |||
"""Generate build.ninja files from SCons aliases.""" | """Generate build.ninja files from SCons aliases.""" | |||
import importlib | import importlib | |||
import os | import os | |||
import traceback | ||||
import subprocess | import subprocess | |||
import sys | import sys | |||
import SCons | import SCons | |||
import SCons.Script | ||||
import SCons.Tool.ninja.Globals | import SCons.Tool.ninja.Globals | |||
from SCons.Script import GetOption | from SCons.Script import GetOption | |||
from .Globals import NINJA_RULES, NINJA_POOLS, NINJA_CUSTOM_HANDLERS | from .Globals import NINJA_RULES, NINJA_POOLS, NINJA_CUSTOM_HANDLERS, NINJA_DEFA ULT_TARGETS, NINJA_CMDLINE_TARGETS | |||
from .Methods import register_custom_handler, register_custom_rule_mapping, regi ster_custom_rule, register_custom_pool, \ | from .Methods import register_custom_handler, register_custom_rule_mapping, regi ster_custom_rule, register_custom_pool, \ | |||
set_build_node_callback, get_generic_shell_command, CheckNinjaCompdbExpand, get_command, \ | set_build_node_callback, get_generic_shell_command, CheckNinjaCompdbExpand, get_command, \ | |||
gen_get_response_file_command | gen_get_response_file_command | |||
from .Overrides import ninja_hack_linkcom, ninja_hack_arcom, NinjaNoResponseFile s, ninja_always_serial, AlwaysExecAction | from .Overrides import ninja_hack_linkcom, ninja_hack_arcom, NinjaNoResponseFile s, ninja_always_serial, AlwaysExecAction | |||
from .Utils import ninja_add_command_line_options, \ | from .Utils import ninja_add_command_line_options, \ | |||
ninja_noop, ninja_print_conf_log, ninja_csig, ninja_contents, ninja_stat, ni nja_whereis | ninja_noop, ninja_print_conf_log, ninja_csig, ninja_contents, ninja_stat, ni nja_whereis, NinjaExperimentalWarning | |||
try: | try: | |||
import ninja | import ninja | |||
NINJA_BINARY = ninja.__file__ | NINJA_BINARY = ninja.__file__ | |||
except ImportError: | except ImportError: | |||
NINJA_BINARY = False | NINJA_BINARY = False | |||
else: | else: | |||
from .NinjaState import NinjaState | from .NinjaState import NinjaState | |||
NINJA_STATE = None | NINJA_STATE = None | |||
skipping to change at line 66 | skipping to change at line 68 | |||
if not isinstance(source, list): | if not isinstance(source, list): | |||
source = [source] | source = [source] | |||
if not isinstance(target, list): | if not isinstance(target, list): | |||
target = [target] | target = [target] | |||
# We have no COMSTR equivalent so print that we're generating | # We have no COMSTR equivalent so print that we're generating | |||
# here. | # here. | |||
print("Generating:", str(target[0])) | print("Generating:", str(target[0])) | |||
generated_build_ninja = target[0].get_abspath() | generated_build_ninja = target[0].get_abspath() | |||
NINJA_STATE.generate() | try: | |||
NINJA_STATE.generate() | ||||
except Exception: | ||||
raise SCons.Errors.BuildError( | ||||
errstr=f"ERROR: an exception occurred while generating the ninja fil | ||||
e:\n{traceback.format_exc()}", | ||||
node=target) | ||||
if env["PLATFORM"] == "win32": | if env["PLATFORM"] == "win32": | |||
# TODO: Is this necessary as you set env variable in the ninja build fil e per target? | # TODO: Is this necessary as you set env variable in the ninja build fil e per target? | |||
# this is not great, its doesn't consider specific | # this is not great, its doesn't consider specific | |||
# node environments, which means on linux the build could | # node environments, which means on linux the build could | |||
# behave differently, because on linux you can set the environment | # behave differently, because on linux you can set the environment | |||
# per command in the ninja file. This is only needed if | # per command in the ninja file. This is only needed if | |||
# running ninja directly from a command line that hasn't | # running ninja directly from a command line that hasn't | |||
# had the environment setup (vcvarsall.bat) | # had the environment setup (vcvarsall.bat) | |||
with open('run_ninja_env.bat', 'w') as f: | with open('run_ninja_env.bat', 'w') as f: | |||
for key in env['ENV']: | for key in env['ENV']: | |||
f.write('set {}={}\n'.format(key, env['ENV'][key])) | f.write('set {}={}\n'.format(key, env['ENV'][key])) | |||
f.write('{} -f {} %*\n'.format(NINJA_STATE.ninja_bin_path, generated _build_ninja)) | f.write('{} -f {} %*\n'.format(NINJA_STATE.ninja_bin_path, generated _build_ninja)) | |||
cmd = ['run_ninja_env.bat'] | cmd = ['run_ninja_env.bat'] | |||
else: | else: | |||
cmd = [NINJA_STATE.ninja_bin_path, '-f', generated_build_ninja] | cmd = [NINJA_STATE.ninja_bin_path, '-f', generated_build_ninja] | |||
if not env.get("NINJA_DISABLE_AUTO_RUN"): | 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)] + env.get('NINJA_CMD_ARGS', '').split() + | ||||
NINJA_CMDLINE_TARGETS | ||||
print(f"ninja will be run with command line targets: {' '.join(NINJA_CMD | ||||
LINE_TARGETS)}") | ||||
print("Executing:", str(' '.join(cmd))) | print("Executing:", str(' '.join(cmd))) | |||
# execute the ninja build at the end of SCons, trying to | # execute the ninja build at the end of SCons, trying to | |||
# reproduce the output like a ninja build would | # reproduce the output like a ninja build would | |||
def execute_ninja(): | def execute_ninja(): | |||
proc = subprocess.Popen(cmd, | proc = subprocess.Popen(cmd, | |||
stderr=sys.stderr, | stderr=sys.stderr, | |||
stdout=subprocess.PIPE, | stdout=subprocess.PIPE, | |||
universal_newlines=True, | universal_newlines=True, | |||
skipping to change at line 119 | skipping to change at line 129 | |||
sys.stdout.write('\x1b[2K') # erase previous line | sys.stdout.write('\x1b[2K') # erase previous line | |||
sys.stdout.write("\r") | sys.stdout.write("\r") | |||
else: | else: | |||
sys.stdout.write(os.linesep) | sys.stdout.write(os.linesep) | |||
sys.stdout.write(output) | sys.stdout.write(output) | |||
sys.stdout.flush() | sys.stdout.flush() | |||
# this will only erase ninjas [#/#] lines | # this will only erase ninjas [#/#] lines | |||
# leaving warnings and other output, seems a bit | # leaving warnings and other output, seems a bit | |||
# prone to failure with such a simple check | # prone to failure with such a simple check | |||
erase_previous = output.startswith('[') | erase_previous = output.startswith('[') | |||
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): | def exists(env): | |||
"""Enable if called.""" | """Enable if called.""" | |||
if 'ninja' not in GetOption('experimental'): | if 'ninja' not in GetOption('experimental'): | |||
return False | return False | |||
# This variable disables the tool when storing the SCons command in the | # This variable disables the tool when storing the SCons command in the | |||
# generated ninja file to ensure that the ninja tool is not loaded when | # generated ninja file to ensure that the ninja tool is not loaded when | |||
# SCons should do actual work as a subprocess of a ninja build. The ninja | # SCons should do actual work as a subprocess of a ninja build. The ninja | |||
skipping to change at line 162 | skipping to change at line 181 | |||
target = [ninja_file, ] | target = [ninja_file, ] | |||
# No source should have been passed. Drop it. | # No source should have been passed. Drop it. | |||
if source: | if source: | |||
source = [] | source = [] | |||
return target, source | return target, source | |||
def generate(env): | def generate(env): | |||
"""Generate the NINJA builders.""" | """Generate the NINJA builders.""" | |||
global NINJA_STATE | global NINJA_STATE, NINJA_CMDLINE_TARGETS | |||
if 'ninja' not in GetOption('experimental'): | if 'ninja' not in GetOption('experimental'): | |||
return | return | |||
if not SCons.Tool.ninja.Globals.ninja_builder_initialized: | if not SCons.Tool.ninja.Globals.ninja_builder_initialized: | |||
SCons.Tool.ninja.Globals.ninja_builder_initialized = True | SCons.Tool.ninja.Globals.ninja_builder_initialized = True | |||
ninja_add_command_line_options() | ninja_add_command_line_options() | |||
if not NINJA_BINARY: | if not NINJA_BINARY: | |||
skipping to change at line 186 | skipping to change at line 205 | |||
env["NINJA_FILE_NAME"] = env.get("NINJA_FILE_NAME", "build.ninja") | env["NINJA_FILE_NAME"] = env.get("NINJA_FILE_NAME", "build.ninja") | |||
# Add the Ninja builder. | # Add the Ninja builder. | |||
always_exec_ninja_action = AlwaysExecAction(ninja_builder, {}) | always_exec_ninja_action = AlwaysExecAction(ninja_builder, {}) | |||
ninja_builder_obj = SCons.Builder.Builder(action=always_exec_ninja_action, | ninja_builder_obj = SCons.Builder.Builder(action=always_exec_ninja_action, | |||
emitter=ninja_emitter) | emitter=ninja_emitter) | |||
env.Append(BUILDERS={"Ninja": ninja_builder_obj}) | env.Append(BUILDERS={"Ninja": ninja_builder_obj}) | |||
env["NINJA_ALIAS_NAME"] = env.get("NINJA_ALIAS_NAME", "generate-ninja") | env["NINJA_ALIAS_NAME"] = env.get("NINJA_ALIAS_NAME", "generate-ninja") | |||
env['NINJA_DIR'] = env.Dir(env.get("NINJA_DIR", '#/.ninja')) | env['NINJA_DIR'] = env.Dir(env.get("NINJA_DIR", '#/.ninja')) | |||
env["NINJA_SCONS_DAEMON_KEEP_ALIVE"] = env.get("NINJA_SCONS_DAEMON_KEEP_ALIV | ||||
E", 180000) | ||||
if GetOption("disable_ninja"): | ||||
env.SConsignFile(os.path.join(str(env['NINJA_DIR']), '.ninja.sconsign')) | ||||
# here we allow multiple environments to construct rules and builds | # here we allow multiple environments to construct rules and builds | |||
# into the same ninja file | # into the same ninja file | |||
if NINJA_STATE is None: | if NINJA_STATE is None: | |||
ninja_file = env.Ninja() | ninja_file = env.Ninja() | |||
env['NINJA_FILE'] = ninja_file[0] | env['NINJA_FILE'] = ninja_file[0] | |||
env.AlwaysBuild(ninja_file) | env.AlwaysBuild(ninja_file) | |||
env.Alias("$NINJA_ALIAS_NAME", ninja_file) | ||||
# We need to force SCons to only build the ninja target when ninja tool | ||||
is loaded. | ||||
# The ninja tool is going to 'rip the guts out' of scons and make it bas | ||||
ically unable | ||||
# to do anything in terms of building, so any targets besides the ninja | ||||
target will | ||||
# end up doing nothing besides causing confusion. We save the targets ho | ||||
wever, so that | ||||
# SCons and invoke ninja to build them in lieu of the user. | ||||
NINJA_CMDLINE_TARGETS = SCons.Script.BUILD_TARGETS | ||||
SCons.Script.BUILD_TARGETS = SCons.Script.TargetList(env.Alias("$NINJA_A | ||||
LIAS_NAME", ninja_file)) | ||||
else: | else: | |||
if str(NINJA_STATE.ninja_file) != env["NINJA_FILE_NAME"]: | if str(NINJA_STATE.ninja_file) != env["NINJA_FILE_NAME"]: | |||
SCons.Warnings.SConsWarning("Generating multiple ninja files not sup ported, set ninja file name before tool initialization.") | SCons.Warnings.SConsWarning("Generating multiple ninja files not sup ported, set ninja file name before tool initialization.") | |||
ninja_file = [NINJA_STATE.ninja_file] | ninja_file = [NINJA_STATE.ninja_file] | |||
def ninja_generate_deps(env): | def ninja_generate_deps(env): | |||
"""Return a list of SConscripts | """Return a list of SConscripts | |||
TODO: Should we also include files loaded from site_scons/*** | TODO: Should we also include files loaded from site_scons/*** | |||
or even all loaded modules? https://stackoverflow.com/questions/485810 0/how-to-list-imported-modules | or even all loaded modules? https://stackoverflow.com/questions/485810 0/how-to-list-imported-modules | |||
TODO: Do we want this to be Nodes? | TODO: Do we want this to be Nodes? | |||
""" | """ | |||
return sorted([str(s) for s in SCons.Node.SConscriptNodes]) | return sorted([str(s) for s in SCons.Node.SConscriptNodes]) | |||
env['_NINJA_REGENERATE_DEPS_FUNC'] = ninja_generate_deps | env['_NINJA_REGENERATE_DEPS_FUNC'] = ninja_generate_deps | |||
env['NINJA_REGENERATE_DEPS'] = env.get('NINJA_REGENERATE_DEPS', '${_NINJA_RE GENERATE_DEPS_FUNC(__env__)}') | env['NINJA_REGENERATE_DEPS'] = env.get('NINJA_REGENERATE_DEPS', '${_NINJA_RE GENERATE_DEPS_FUNC(__env__)}') | |||
# This adds the required flags such that the generated compile | # This adds the required flags such that the generated compile | |||
# commands will create depfiles as appropriate in the Ninja file. | # commands will create depfiles as appropriate in the Ninja file. | |||
if env["PLATFORM"] == "win32": | if 'CCDEPFLAGS' not in env: | |||
env.Append(CCFLAGS=["/showIncludes"]) | # Issue some warning here | |||
pass | ||||
else: | else: | |||
env.Append(CCFLAGS=["-MMD", "-MF", "${TARGET}.d"]) | env.Append(CCFLAGS='$CCDEPFLAGS') | |||
env.AddMethod(CheckNinjaCompdbExpand, "CheckNinjaCompdbExpand") | env.AddMethod(CheckNinjaCompdbExpand, "CheckNinjaCompdbExpand") | |||
# Provide a way for custom rule authors to easily access command | # Provide a way for custom rule authors to easily access command | |||
# generation. | # generation. | |||
env.AddMethod(get_generic_shell_command, "NinjaGetGenericShellCommand") | env.AddMethod(get_generic_shell_command, "NinjaGetGenericShellCommand") | |||
env.AddMethod(get_command, "NinjaGetCommand") | env.AddMethod(get_command, "NinjaGetCommand") | |||
env.AddMethod(gen_get_response_file_command, "NinjaGenResponseFileProvider") | env.AddMethod(gen_get_response_file_command, "NinjaGenResponseFileProvider") | |||
env.AddMethod(set_build_node_callback, "NinjaSetBuildNodeCallback") | env.AddMethod(set_build_node_callback, "NinjaSetBuildNodeCallback") | |||
skipping to change at line 266 | skipping to change at line 297 | |||
# will return "${*COM}" as their pre-subst'd command line. However | # will return "${*COM}" as their pre-subst'd command line. However | |||
# if a user in a SConscript overwrites those values via key access | # if a user in a SConscript overwrites those values via key access | |||
# like env["LINKCOM"] = "$( $ICERUN $)" + env["LINKCOM"] then | # like env["LINKCOM"] = "$( $ICERUN $)" + env["LINKCOM"] then | |||
# those actions no longer return the "bracketted" string and | # those actions no longer return the "bracketted" string and | |||
# instead return something that looks more expanded. So to | # instead return something that looks more expanded. So to | |||
# continue working even if a user has done this we map both the | # continue working even if a user has done this we map both the | |||
# "bracketted" and semi-expanded versions. | # "bracketted" and semi-expanded versions. | |||
def robust_rule_mapping(var, rule, tool): | def robust_rule_mapping(var, rule, tool): | |||
provider = gen_get_response_file_command(env, rule, tool) | provider = gen_get_response_file_command(env, rule, tool) | |||
env.NinjaRuleMapping("${" + var + "}", provider) | env.NinjaRuleMapping("${" + var + "}", provider) | |||
env.NinjaRuleMapping(env.get(var, None), provider) | ||||
# some of these construction vars could be generators, e.g. | ||||
# CommandGeneratorAction, so if the var is not a string, we | ||||
# can't parse the generated string. | ||||
if isinstance(env.get(var), str): | ||||
env.NinjaRuleMapping(env.get(var, None), provider) | ||||
robust_rule_mapping("CCCOM", "CC", "$CC") | robust_rule_mapping("CCCOM", "CC", "$CC") | |||
robust_rule_mapping("SHCCCOM", "CC", "$CC") | robust_rule_mapping("SHCCCOM", "CC", "$CC") | |||
robust_rule_mapping("CXXCOM", "CXX", "$CXX") | robust_rule_mapping("CXXCOM", "CXX", "$CXX") | |||
robust_rule_mapping("SHCXXCOM", "CXX", "$CXX") | robust_rule_mapping("SHCXXCOM", "CXX", "$CXX") | |||
robust_rule_mapping("LINKCOM", "LINK", "$LINK") | robust_rule_mapping("LINKCOM", "LINK", "$LINK") | |||
robust_rule_mapping("SHLINKCOM", "LINK", "$SHLINK") | robust_rule_mapping("SHLINKCOM", "LINK", "$SHLINK") | |||
robust_rule_mapping("ARCOM", "AR", "$AR") | robust_rule_mapping("ARCOM", "AR", "$AR") | |||
# Make SCons node walk faster by preventing unnecessary work | # Make SCons node walk faster by preventing unnecessary work | |||
env.Decider("timestamp-match") | env.Decider("timestamp-match") | |||
# Used to determine if a build generates a source file. Ninja | # Used to determine if a build generates a source file. Ninja | |||
# requires that all generated sources are added as order_only | # requires that all generated sources are added as order_only | |||
# dependencies to any builds that *might* use them. | # dependencies to any builds that *might* use them. | |||
# TODO: switch to using SCons to help determine this (Github Issue #3624) | # TODO: switch to using SCons to help determine this (Github Issue #3624) | |||
env["NINJA_GENERATED_SOURCE_SUFFIXES"] = [".h", ".hpp"] | env["NINJA_GENERATED_SOURCE_SUFFIXES"] = env.get('NINJA_GENERATED_SOURCE_SUF FIXES', [".h", ".hpp"]) | |||
# Force ARCOM so use 's' flag on ar instead of separately running ranlib | # Force ARCOM so use 's' flag on ar instead of separately running ranlib | |||
ninja_hack_arcom(env) | ninja_hack_arcom(env) | |||
if GetOption('disable_ninja'): | if GetOption('disable_ninja'): | |||
return env | return env | |||
SCons.Warnings.SConsWarning("Initializing ninja tool... this feature is expe | print("Initializing ninja tool... this feature is experimental. SCons intern | |||
rimental. SCons internals and all environments will be affected.") | als and all environments will be affected.") | |||
print(f"SCons running in ninja mode. {env['NINJA_FILE']} will be generated." | ||||
) | ||||
# This is the point of no return, anything after this comment | # This is the point of no return, anything after this comment | |||
# makes changes to SCons that are irreversible and incompatible | # makes changes to SCons that are irreversible and incompatible | |||
# with a normal SCons build. We return early if __NINJA_NO=1 has | # with a normal SCons build. We return early if __NINJA_NO=1 has | |||
# been given on the command line (i.e. by us in the generated | # been given on the command line (i.e. by us in the generated | |||
# ninja file) here to prevent these modifications from happening | # ninja file) here to prevent these modifications from happening | |||
# when we want SCons to do work. Everything before this was | # when we want SCons to do work. Everything before this was | |||
# necessary to setup the builder and other functions so that the | # necessary to setup the builder and other functions so that the | |||
# tool can be unconditionally used in the users's SCons files. | # tool can be unconditionally used in the users's SCons files. | |||
if not exists(env): | if not exists(env): | |||
skipping to change at line 431 | skipping to change at line 467 | |||
NINJA_STATE.add_build(target) | NINJA_STATE.add_build(target) | |||
else: | else: | |||
target.build() | target.build() | |||
SCons.Taskmaster.Task.execute = ninja_execute | SCons.Taskmaster.Task.execute = ninja_execute | |||
# Make needs_execute always return true instead of determining out of | # Make needs_execute always return true instead of determining out of | |||
# date-ness. | # date-ness. | |||
SCons.Script.Main.BuildTask.needs_execute = lambda x: True | SCons.Script.Main.BuildTask.needs_execute = lambda x: True | |||
def ninja_Set_Default_Targets(env, tlist): | ||||
""" | ||||
Record the default targets if they were ever set by the user. Ninja | ||||
will need to write the default targets and make sure not to include | ||||
the scons daemon shutdown target. | ||||
""" | ||||
SCons.Script._Get_Default_Targets = SCons.Script._Set_Default_Targets_Ha | ||||
s_Been_Called | ||||
SCons.Script.DEFAULT_TARGETS = ninja_file | ||||
for t in tlist: | ||||
if isinstance(t, SCons.Node.Node): | ||||
NINJA_DEFAULT_TARGETS.append(t) | ||||
else: | ||||
nodes = env.arg2nodes(t, env.fs.Entry) | ||||
NINJA_DEFAULT_TARGETS.extend(nodes) | ||||
SCons.Script._Set_Default_Targets = ninja_Set_Default_Targets | ||||
# We will eventually need to overwrite TempFileMunge to make it | # We will eventually need to overwrite TempFileMunge to make it | |||
# handle persistent tempfiles or get an upstreamed change to add | # handle persistent tempfiles or get an upstreamed change to add | |||
# some configurability to it's behavior in regards to tempfiles. | # some configurability to it's behavior in regards to tempfiles. | |||
# | # | |||
# Set all three environment variables that Python's | # Set all three environment variables that Python's | |||
# tempfile.mkstemp looks at as it behaves differently on different | # tempfile.mkstemp looks at as it behaves differently on different | |||
# platforms and versions of Python. | # platforms and versions of Python. | |||
# build_dir = env.subst("$NINJA_DIR") | # build_dir = env.subst("$NINJA_DIR") | |||
# if build_dir == "": | # if build_dir == "": | |||
# build_dir = "." | # build_dir = "." | |||
# os.environ["TMPDIR"] = env.Dir("{}/.response_files".format(build_dir)).get _abspath() | # os.environ["TMPDIR"] = env.Dir("{}/.response_files".format(build_dir)).get _abspath() | |||
# os.environ["TEMP"] = os.environ["TMPDIR"] | # os.environ["TEMP"] = os.environ["TMPDIR"] | |||
# os.environ["TMP"] = os.environ["TMPDIR"] | # os.environ["TMP"] = os.environ["TMPDIR"] | |||
# if not os.path.isdir(os.environ["TMPDIR"]): | # if not os.path.isdir(os.environ["TMPDIR"]): | |||
# env.Execute(SCons.Defaults.Mkdir(os.environ["TMPDIR"])) | # env.Execute(SCons.Defaults.Mkdir(os.environ["TMPDIR"])) | |||
env['TEMPFILEDIR'] = "$NINJA_DIR/.response_files" | env['TEMPFILEDIR'] = "$NINJA_DIR/.response_files" | |||
env["TEMPFILE"] = NinjaNoResponseFiles | env["TEMPFILE"] = NinjaNoResponseFiles | |||
env.Alias('run-ninja-scons-daemon', 'run_ninja_scons_daemon_phony') | ||||
env.Alias('shutdown-ninja-scons-daemon', 'shutdown_ninja_scons_daemon_phony' | ||||
) | ||||
End of changes. 17 change blocks. | ||||
14 lines changed or deleted | 77 lines changed or added |