diff options
-rw-r--r-- | site_scons/site_tools/ninja.py | 64 |
1 files changed, 55 insertions, 9 deletions
diff --git a/site_scons/site_tools/ninja.py b/site_scons/site_tools/ninja.py index feee4f25182..8823121de90 100644 --- a/site_scons/site_tools/ninja.py +++ b/site_scons/site_tools/ninja.py @@ -23,7 +23,8 @@ from threading import Lock from glob import glob import SCons -from SCons.Action import _string_from_cmd_list +from SCons.Action import _string_from_cmd_list, get_default_ENV +from SCons.Util import is_String, is_List from SCons.Script import COMMAND_LINE_TARGETS NINJA_SYNTAX = "NINJA_SYNTAX" @@ -279,17 +280,25 @@ class SConsToNinjaTranslator: if results[0]["rule"] == "CMD": cmdline = "" for cmd in results: - if not cmd["variables"]["cmd"]: - continue - if cmdline: - cmdline += " && " + # Occasionally a command line will expand to a + # whitespace only string (i.e. ' '). Which is not a + # valid command but does not trigger the empty command + # condition if not cmdstr. So here we strip preceding + # and proceeding whitespace to make strings like the + # above become empty strings and so will be skipped. + cmdstr = cmd["variables"]["cmd"].strip() + if not cmdstr: + continue # Skip duplicate commands - if cmd["variables"]["cmd"] in cmdline: + if cmdstr in cmdline: continue - cmdline += cmd["variables"]["cmd"] + if cmdline: + cmdline += " && " + + cmdline += cmdstr # Remove all preceding and proceeding whitespace cmdline = cmdline.strip() @@ -601,8 +610,16 @@ class NinjaState: # DAG walk so we can't rely on action_to_ninja_build to # generate this rule even though SCons should know we're # dependent on SCons files. + # + # TODO: We're working on getting an API into SCons that will + # allow us to query the actual SConscripts used. Right now + # this glob method has deficiencies like skipping + # jstests/SConscript and being specific to the MongoDB + # repository layout. ninja.build( - ninja_file, rule="REGENERATE", implicit=glob("**/SCons*", recursive=True), + ninja_file, + rule="REGENERATE", + implicit=[self.env.File("#SConstruct").get_abspath()] + glob("src/**/SConscript", recursive=True), ) ninja.build( @@ -763,11 +780,40 @@ def get_command(env, node, action): # pylint: disable=too-many-branches # safe to make. outputs = outputs[0:1] + command_env = getattr(node.attributes, "NINJA_ENV_ENV", "") + if not command_env: + ENV = get_default_ENV(sub_env) + + # This is taken wholesale from SCons/Action.py + # + # Ensure that the ENV values are all strings: + for key, value in ENV.items(): + if not is_String(value): + if is_List(value): + # If the value is a list, then we assume it is a + # path list, because that's a pretty common list-like + # value to stick in an environment variable: + value = flatten_sequence(value) + value = os.pathsep.join(map(str, value)) + else: + # If it isn't a string or a list, then we just coerce + # it to a string, which is the proper way to handle + # Dir and File instances and will produce something + # reasonable for just about everything else: + value = str(value) + + if env["PLATFORM"] == "win32": + command_env += "set '{}={}' && ".format(key, value) + else: + command_env += "{}={}; ".format(key, value) + + setattr(node.attributes, "NINJA_ENV_ENV", command_env) + return { "outputs": outputs, "implicit": implicit, "rule": rule, - "variables": {"cmd": cmd}, + "variables": {"cmd": command_env + cmd}, } |