summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'BuildTools/scons2ninja.py')
-rwxr-xr-xBuildTools/scons2ninja.py918
1 files changed, 460 insertions, 458 deletions
diff --git a/BuildTools/scons2ninja.py b/BuildTools/scons2ninja.py
index 5d084cd..6c77c88 100755
--- a/BuildTools/scons2ninja.py
+++ b/BuildTools/scons2ninja.py
@@ -24,202 +24,202 @@ SCONS_ARGS = ' '.join(sys.argv[1:])
BINARY_FLAGS = ["-framework", "-arch", "-x", "--output-format", "-isystem", "-include"]
if sys.platform == 'win32' :
- LIB_PREFIX = ""
- LIB_SUFFIX = ""
- EXE_SUFFIX = ".exe"
+ LIB_PREFIX = ""
+ LIB_SUFFIX = ""
+ EXE_SUFFIX = ".exe"
else :
- LIB_PREFIX = "lib"
- LIB_SUFFIX = ".a"
- EXE_SUFFIX = ""
+ LIB_PREFIX = "lib"
+ LIB_SUFFIX = ".a"
+ EXE_SUFFIX = ""
def is_regexp(x) :
- return 'match' in dir(x)
+ return 'match' in dir(x)
def is_list(l) :
- return type(l) is list
+ return type(l) is list
def escape(s) :
- return s.replace(' ', '$ ').replace(':', '$:')
+ return s.replace(' ', '$ ').replace(':', '$:')
def quote_spaces(s) :
- if ' ' in s :
- return '"' + s + '"'
- else :
- return s
+ if ' ' in s :
+ return '"' + s + '"'
+ else :
+ return s
def to_list(l) :
- if not l :
- return []
- if is_list(l) :
- return l
- return [l]
+ if not l :
+ return []
+ if is_list(l) :
+ return l
+ return [l]
def partition(l, f) :
- x = []
- y = []
- for v in l :
- if f(v) :
- x.append(v)
- else :
- y.append(v)
- return (x, y)
+ x = []
+ y = []
+ for v in l :
+ if f(v) :
+ x.append(v)
+ else :
+ y.append(v)
+ return (x, y)
def get_unary_flags(prefix, flags) :
- return [x[len(prefix):] for x in flags if x.lower().startswith(prefix.lower())]
+ return [x[len(prefix):] for x in flags if x.lower().startswith(prefix.lower())]
def extract_unary_flags(prefix, flags) :
- f1, f2 = partition(flags, lambda x : x.lower().startswith(prefix.lower()))
- return ([f[len(prefix):] for f in f1], f2)
+ f1, f2 = partition(flags, lambda x : x.lower().startswith(prefix.lower()))
+ return ([f[len(prefix):] for f in f1], f2)
def extract_unary_flag(prefix, flags) :
- flag, flags = extract_unary_flags(prefix, flags)
- return (flag[0], flags)
+ flag, flags = extract_unary_flags(prefix, flags)
+ return (flag[0], flags)
def extract_binary_flag(prefix, flags) :
- i = flags.index(prefix)
- flag = flags[i + 1]
- del flags[i]
- del flags[i]
- return (flag, flags)
+ i = flags.index(prefix)
+ flag = flags[i + 1]
+ del flags[i]
+ del flags[i]
+ return (flag, flags)
def get_non_flags(flags) :
- skip = False
- result = []
- for f in flags :
- if skip :
- skip = False
- elif f in BINARY_FLAGS :
- skip = True
- elif not f.startswith("/") and not f.startswith("-") :
- result.append(f)
- return result
+ skip = False
+ result = []
+ for f in flags :
+ if skip :
+ skip = False
+ elif f in BINARY_FLAGS :
+ skip = True
+ elif not f.startswith("/") and not f.startswith("-") :
+ result.append(f)
+ return result
def extract_non_flags(flags) :
- non_flags = get_non_flags(flags)
- return (non_flags, filter(lambda x : x not in non_flags, flags))
+ non_flags = get_non_flags(flags)
+ return (non_flags, filter(lambda x : x not in non_flags, flags))
def get_dependencies(target, build_targets) :
- result = []
- queue = list(dependencies.get(target, []))
- while len(queue) > 0 :
- n = queue.pop()
- # Filter out Value() results
- if n in build_targets or os.path.exists(n) :
- result.append(n)
- queue += list(dependencies.get(n, []))
- return result
+ result = []
+ queue = list(dependencies.get(target, []))
+ while len(queue) > 0 :
+ n = queue.pop()
+ # Filter out Value() results
+ if n in build_targets or os.path.exists(n) :
+ result.append(n)
+ queue += list(dependencies.get(n, []))
+ return result
def get_built_libs(libs, libpaths, outputs) :
- canonical_outputs = [os.path.abspath(p) for p in outputs]
- result = []
- for libpath in libpaths :
- for lib in libs :
- lib_libpath = os.path.join(libpath, LIB_PREFIX + lib + LIB_SUFFIX)
- if os.path.abspath(lib_libpath) in canonical_outputs :
- result.append(lib_libpath)
- return result
+ canonical_outputs = [os.path.abspath(p) for p in outputs]
+ result = []
+ for libpath in libpaths :
+ for lib in libs :
+ lib_libpath = os.path.join(libpath, LIB_PREFIX + lib + LIB_SUFFIX)
+ if os.path.abspath(lib_libpath) in canonical_outputs :
+ result.append(lib_libpath)
+ return result
def parse_tool_command(line) :
- command = shlex.split(line, False, False if sys.platform == 'win32' else True)
- flags = command[1:]
- tool = os.path.splitext(os.path.basename(command[0]))[0]
- if tool.startswith('clang++') or tool.startswith('g++') :
- tool = "cxx"
- elif tool.startswith('clang') or tool.startswith('gcc') :
- tool = "cc"
- if tool in ["cc", "cxx"] and not "-c" in flags :
- tool = "glink"
- tool = tool.replace('-qt4', '')
- return tool, command, flags
+ command = shlex.split(line, False, False if sys.platform == 'win32' else True)
+ flags = command[1:]
+ tool = os.path.splitext(os.path.basename(command[0]))[0]
+ if tool.startswith('clang++') or tool.startswith('g++') :
+ tool = "cxx"
+ elif tool.startswith('clang') or tool.startswith('gcc') :
+ tool = "cc"
+ if tool in ["cc", "cxx"] and not "-c" in flags :
+ tool = "glink"
+ tool = tool.replace('-qt4', '')
+ return tool, command, flags
def rglob(pattern, root = '.') :
- return [os.path.join(path, f) for path, dirs, files in os.walk(root) for f in fnmatch.filter(files, pattern)]
+ return [os.path.join(path, f) for path, dirs, files in os.walk(root) for f in fnmatch.filter(files, pattern)]
################################################################################
# Helper for building Ninja files
################################################################################
class NinjaBuilder :
- def __init__(self) :
- self._header = ""
- self.variables = ""
- self.rules = ""
- self._build = ""
- self.pools = ""
- self._flags = {}
- self.targets = []
-
- def header(self, text) :
- self._header += text + "\n"
-
- def rule(self, name, **kwargs) :
- self.rules += "rule " + name + "\n"
- for k, v in kwargs.iteritems() :
- self.rules += " " + str(k) + " = " + str(v) + "\n"
- self.rules += "\n"
-
- def pool(self, name, **kwargs) :
- self.pools += "pool " + name + "\n"
- for k, v in kwargs.iteritems() :
- self.pools += " " + str(k) + " = " + str(v) + "\n"
- self.pools += "\n"
-
- def variable(self, name, value) :
- self.variables += str(name) + " = " + str(value) + "\n"
-
- def build(self, target, rule, sources = None, **kwargs) :
- self._build += "build " + self.to_string(target) + ": " + rule
- if sources :
- self._build += " " + self.to_string(sources)
- if 'deps' in kwargs and kwargs['deps'] :
- self._build += " | " + self.to_string(kwargs["deps"])
- if 'order_deps' in kwargs :
- self._build += " || " + self.to_string(kwargs['order_deps'])
- self._build += "\n"
- for var, value in kwargs.iteritems() :
- if var in ['deps', 'order_deps'] :
- continue
- value = self.to_string(value, quote = True)
- if var.endswith("flags") :
- value = self.get_flags_variable(var, value)
- self._build += " " + var + " = " + value + "\n"
- self.targets += to_list(target)
-
- def header_targets(self) :
- return [x for x in self.targets if x.endswith('.h') or x.endswith('.hh')]
-
- def serialize(self) :
- result = ""
- result += self._header + "\n"
- result += self.variables + "\n"
- for prefix in self._flags.values() :
- for k, v in prefix.iteritems() :
- result += v + " = " + k + "\n"
- result += "\n"
- result += self.pools + "\n"
- result += self.rules + "\n"
- result += self._build + "\n"
- return result
-
- def to_string(self, lst, quote = False) :
- if is_list(lst) :
- if quote :
- return ' '.join([quote_spaces(x) for x in lst])
- else :
- return ' '.join([escape(x) for x in lst])
- if is_regexp(lst) :
- return ' '.join([escape(x) for x in self.targets if lst.match(x)])
- return escape(lst)
-
- def get_flags_variable(self, flags_type, flags) :
- if len(flags) == 0 :
- return ''
- if flags_type not in self._flags :
- self._flags[flags_type] = {}
- type_flags = self._flags[flags_type]
- if flags not in type_flags :
- type_flags[flags] = flags_type + "_" + str(len(type_flags))
- return "$" + type_flags[flags]
+ def __init__(self) :
+ self._header = ""
+ self.variables = ""
+ self.rules = ""
+ self._build = ""
+ self.pools = ""
+ self._flags = {}
+ self.targets = []
+
+ def header(self, text) :
+ self._header += text + "\n"
+
+ def rule(self, name, **kwargs) :
+ self.rules += "rule " + name + "\n"
+ for k, v in kwargs.iteritems() :
+ self.rules += " " + str(k) + " = " + str(v) + "\n"
+ self.rules += "\n"
+
+ def pool(self, name, **kwargs) :
+ self.pools += "pool " + name + "\n"
+ for k, v in kwargs.iteritems() :
+ self.pools += " " + str(k) + " = " + str(v) + "\n"
+ self.pools += "\n"
+
+ def variable(self, name, value) :
+ self.variables += str(name) + " = " + str(value) + "\n"
+
+ def build(self, target, rule, sources = None, **kwargs) :
+ self._build += "build " + self.to_string(target) + ": " + rule
+ if sources :
+ self._build += " " + self.to_string(sources)
+ if 'deps' in kwargs and kwargs['deps'] :
+ self._build += " | " + self.to_string(kwargs["deps"])
+ if 'order_deps' in kwargs :
+ self._build += " || " + self.to_string(kwargs['order_deps'])
+ self._build += "\n"
+ for var, value in kwargs.iteritems() :
+ if var in ['deps', 'order_deps'] :
+ continue
+ value = self.to_string(value, quote = True)
+ if var.endswith("flags") :
+ value = self.get_flags_variable(var, value)
+ self._build += " " + var + " = " + value + "\n"
+ self.targets += to_list(target)
+
+ def header_targets(self) :
+ return [x for x in self.targets if x.endswith('.h') or x.endswith('.hh')]
+
+ def serialize(self) :
+ result = ""
+ result += self._header + "\n"
+ result += self.variables + "\n"
+ for prefix in self._flags.values() :
+ for k, v in prefix.iteritems() :
+ result += v + " = " + k + "\n"
+ result += "\n"
+ result += self.pools + "\n"
+ result += self.rules + "\n"
+ result += self._build + "\n"
+ return result
+
+ def to_string(self, lst, quote = False) :
+ if is_list(lst) :
+ if quote :
+ return ' '.join([quote_spaces(x) for x in lst])
+ else :
+ return ' '.join([escape(x) for x in lst])
+ if is_regexp(lst) :
+ return ' '.join([escape(x) for x in self.targets if lst.match(x)])
+ return escape(lst)
+
+ def get_flags_variable(self, flags_type, flags) :
+ if len(flags) == 0 :
+ return ''
+ if flags_type not in self._flags :
+ self._flags[flags_type] = {}
+ type_flags = self._flags[flags_type]
+ if flags not in type_flags :
+ type_flags[flags] = flags_type + "_" + str(len(type_flags))
+ return "$" + type_flags[flags]
################################################################################
@@ -231,7 +231,7 @@ scons_cmd = "scons"
scons_dependencies = ['SConstruct'] + rglob('SConscript')
def ninja_custom_command(ninja, line) :
- return False
+ return False
CONFIGURATION_FILE = '.scons2ninja.conf'
execfile(CONFIGURATION_FILE)
@@ -248,104 +248,104 @@ ninja = NinjaBuilder()
ninja.pool('scons_pool', depth = 1)
if sys.platform == 'win32' :
- ninja.rule('cl',
- deps = 'msvc',
- command = '$cl /showIncludes $clflags -c $in /Fo$out',
- description = 'CXX $out')
-
- ninja.rule('link',
- command = '$link $in $linkflags $libs /out:$out',
- description = 'LINK $out')
-
- ninja.rule('link_mt',
- command = '$link $in $linkflags $libs /out:$out ; $mt $mtflags',
- description = 'LINK $out')
-
- ninja.rule('lib',
- command = '$lib $libflags /out:$out $in',
- description = 'AR $out')
-
- ninja.rule('rc',
- command = '$rc $rcflags /Fo$out $in',
- description = 'RC $out')
-
- # SCons doesn't touch files if they didn't change, which makes
- # ninja rebuild the file over and over again. There's no touch on Windows :(
- # Could implement it with a script, but for now, delete the file if
- # this problem occurs. I'll fix it if it occurs too much.
- ninja.rule('scons',
- command = scons_cmd + " ${scons_args} $out",
- pool = 'scons_pool',
- description = 'GEN $out')
-
- ninja.rule('install', command = 'cmd /c copy $in $out')
- ninja.rule('run', command = '$in')
+ ninja.rule('cl',
+ deps = 'msvc',
+ command = '$cl /showIncludes $clflags -c $in /Fo$out',
+ description = 'CXX $out')
+
+ ninja.rule('link',
+ command = '$link $in $linkflags $libs /out:$out',
+ description = 'LINK $out')
+
+ ninja.rule('link_mt',
+ command = '$link $in $linkflags $libs /out:$out ; $mt $mtflags',
+ description = 'LINK $out')
+
+ ninja.rule('lib',
+ command = '$lib $libflags /out:$out $in',
+ description = 'AR $out')
+
+ ninja.rule('rc',
+ command = '$rc $rcflags /Fo$out $in',
+ description = 'RC $out')
+
+ # SCons doesn't touch files if they didn't change, which makes
+ # ninja rebuild the file over and over again. There's no touch on Windows :(
+ # Could implement it with a script, but for now, delete the file if
+ # this problem occurs. I'll fix it if it occurs too much.
+ ninja.rule('scons',
+ command = scons_cmd + " ${scons_args} $out",
+ pool = 'scons_pool',
+ description = 'GEN $out')
+
+ ninja.rule('install', command = 'cmd /c copy $in $out')
+ ninja.rule('run', command = '$in')
else :
- ninja.rule('cxx',
- deps = 'gcc',
- depfile = '$out.d',
- command = '$cxx -MMD -MF $out.d $cxxflags -c $in -o $out',
- description = 'CXX $out')
+ ninja.rule('cxx',
+ deps = 'gcc',
+ depfile = '$out.d',
+ command = '$cxx -MMD -MF $out.d $cxxflags -c $in -o $out',
+ description = 'CXX $out')
- ninja.rule('cc',
- deps = 'gcc',
- depfile = '$out.d',
- command = '$cc -MMD -MF $out.d $ccflags -c $in -o $out',
- description = 'CC $out')
+ ninja.rule('cc',
+ deps = 'gcc',
+ depfile = '$out.d',
+ command = '$cc -MMD -MF $out.d $ccflags -c $in -o $out',
+ description = 'CC $out')
- ninja.rule('link',
- command = '$glink -o $out $in $linkflags',
- description = 'LINK $out')
+ ninja.rule('link',
+ command = '$glink -o $out $in $linkflags',
+ description = 'LINK $out')
- ninja.rule('ar',
- command = 'ar $arflags $out $in && ranlib $out',
- description = 'AR $out')
+ ninja.rule('ar',
+ command = 'ar $arflags $out $in && ranlib $out',
+ description = 'AR $out')
- # SCons doesn't touch files if they didn't change, which makes
- # ninja rebuild the file over and over again. Touching solves this.
- ninja.rule('scons',
- command = scons_cmd + " $out && touch $out",
- pool = 'scons_pool',
- description = 'GEN $out')
+ # SCons doesn't touch files if they didn't change, which makes
+ # ninja rebuild the file over and over again. Touching solves this.
+ ninja.rule('scons',
+ command = scons_cmd + " $out && touch $out",
+ pool = 'scons_pool',
+ description = 'GEN $out')
- ninja.rule('install', command = 'install $in $out')
- ninja.rule('run', command = './$in')
+ ninja.rule('install', command = 'install $in $out')
+ ninja.rule('run', command = './$in')
ninja.rule('moc',
- command = '$moc $mocflags -o $out $in',
- description = 'MOC $out')
+ command = '$moc $mocflags -o $out $in',
+ description = 'MOC $out')
ninja.rule('rcc',
- command = '$rcc $rccflags -name $name -o $out $in',
- description = 'RCC $out')
+ command = '$rcc $rccflags -name $name -o $out $in',
+ description = 'RCC $out')
ninja.rule('uic',
- command = '$uic $uicflags -o $out $in',
- description = 'UIC $out')
+ command = '$uic $uicflags -o $out $in',
+ description = 'UIC $out')
ninja.rule('lrelease',
- command = '$lrelease $lreleaseflags $in -qm $out',
- description = 'LRELEASE $out')
+ command = '$lrelease $lreleaseflags $in -qm $out',
+ description = 'LRELEASE $out')
ninja.rule('ibtool',
- command = '$ibtool $ibtoolflags --compile $out $in',
- description = 'IBTOOL $out')
+ command = '$ibtool $ibtoolflags --compile $out $in',
+ description = 'IBTOOL $out')
ninja.rule('dsymutil',
- command = '$dsymutil $dsymutilflags -o $out $in',
- description = 'DSYMUTIL $out')
+ command = '$dsymutil $dsymutilflags -o $out $in',
+ description = 'DSYMUTIL $out')
ninja.rule('generator',
- command = "python " + SCRIPT + " ${scons_args}",
- depfile = ".scons2ninja.deps",
- pool = 'scons_pool',
- generator = '1',
- description = 'Regenerating build.ninja')
+ command = "python " + SCRIPT + " ${scons_args}",
+ depfile = ".scons2ninja.deps",
+ pool = 'scons_pool',
+ generator = '1',
+ description = 'Regenerating build.ninja')
ninja.rule('sdef',
- command = 'sdef $in | sdp -fh --basename $basename -o $outdir',
- description = 'SDEF $out')
+ command = 'sdef $in | sdp -fh --basename $basename -o $outdir',
+ description = 'SDEF $out')
################################################################################
# Build Statements
@@ -365,235 +365,237 @@ stage = 'preamble'
skip_nth_line = -1
stack = ['.']
for line in f.stdout :
- line = line.rstrip()
-
- # Skip lines if requested from previous command
- if skip_nth_line >= 0 :
- skip_nth_line -= 1
- if skip_nth_line == 0 :
- continue
-
- if line.startswith('scons: done building targets') :
- break
-
- if stage == "preamble" :
- # Pass all lines from the SCons configuration step to output
- if re.match("^scons: Building targets ...", line) :
- stage = "build"
- else :
- print line
-
- elif stage == "build" :
- if line.startswith('+-') :
- stage = "dependencies"
- elif re.match("^Using tempfile", line) :
- # Ignore response files from MSVS
- skip_nth_line = 2
- else :
- build_lines.append(line)
-
- # Already detect targets that will need 'mt'
- tool, _, flags = parse_tool_command(line)
- if tool == 'mt' :
- target = get_unary_flags("-outputresource:", flags)[0]
- target = target[0:target.index(';')]
- mtflags[target] = flags
-
- elif stage == "dependencies" :
- if not re.match('^[\s|]+\+\-', line) :
- # Work around bug in SCons that splits output over multiple lines
- continue
-
- level = line.index('+-') / 2
- filename = line[level*2+2:]
- if filename.startswith('[') :
- filename = filename[1:-1]
-
- # Check if we use the 'fixed' format which escapes filenamenames
- if filename.startswith('\'') and filename.endswith('\'') :
- filename = eval(filename)
-
- if level < len(stack) :
- stack = stack[0:level]
- elif level > len(stack) :
- if level != len(stack) + 1 :
- raise Exception("Internal Error" )
- stack.append(previous_filename)
-
- # Skip absolute paths
- if not os.path.isabs(filename) :
- target = stack[-1]
- if target not in dependencies :
- dependencies[target] = []
- dependencies[target].append(filename)
- previous_filename = filename
+ line = line.rstrip()
+
+ # Skip lines if requested from previous command
+ if skip_nth_line >= 0 :
+ skip_nth_line -= 1
+ if skip_nth_line == 0 :
+ continue
+
+ if line.startswith('scons: done building targets') :
+ break
+
+ if stage == "preamble" :
+ # Pass all lines from the SCons configuration step to output
+ if re.match("^scons: Building targets ...", line) :
+ stage = "build"
+ else :
+ print line
+
+ elif stage == "build" :
+ if line.startswith('+-') :
+ stage = "dependencies"
+ elif re.match("^Using tempfile", line) :
+ # Ignore response files from MSVS
+ skip_nth_line = 2
+ else :
+ build_lines.append(line)
+
+ # Already detect targets that will need 'mt'
+ tool, _, flags = parse_tool_command(line)
+ if tool == 'mt' :
+ target = get_unary_flags("-outputresource:", flags)[0]
+ target = target[0:target.index(';')]
+ mtflags[target] = flags
+
+ elif stage == "dependencies" :
+ if not re.match('^[\s|]+\+\-', line) :
+ # Work around bug in SCons that splits output over multiple lines
+ continue
+
+ level = line.index('+-') / 2
+ filename = line[level*2+2:]
+ if filename.startswith('[') :
+ filename = filename[1:-1]
+
+ # Check if we use the 'fixed' format which escapes filenamenames
+ if filename.startswith('\'') and filename.endswith('\'') :
+ filename = eval(filename)
+
+ if level < len(stack) :
+ stack = stack[0:level]
+ elif level > len(stack) :
+ if level != len(stack) + 1 :
+ raise Exception("Internal Error" )
+ stack.append(previous_filename)
+
+ # Skip absolute paths
+ if not os.path.isabs(filename) :
+ target = stack[-1]
+ if target not in dependencies :
+ dependencies[target] = []
+ dependencies[target].append(filename)
+ previous_filename = filename
if f.wait() != 0 :
- print "Error calling '" + scons_generate_cmd + "'"
- print f.stderr.read()
- exit(-1)
+ print "Error calling '" + scons_generate_cmd + "'"
+ print f.stderr.read()
+ exit(-1)
# Pass 2: Parse build rules
tools = {}
for line in build_lines :
- # Custom python function
- m = re.match('^(\w+)\(\[([^\]]*)\]', line)
- if m :
- out = [x[1:-1] for x in m.group(2).split(',')]
- for x in out :
- # 'Note' = To be more correct, deps should also include $scons_dependencies,
- # but this regenerates a bit too often, so leaving it out for now.
- ninja.build(x, 'scons', None, deps = sorted(get_dependencies(x, ninja.targets)))
- continue
-
-
- # TextFile
- m = re.match("^Creating '([^']+)'", line)
- if m :
- out = m.group(1)
- # Note: To be more correct, deps should also include $scons_dependencies,
- # but this regenerates a bit too often, so leaving it out for now.
- ninja.build(out, 'scons', None, deps = sorted(get_dependencies(out, ninja.targets)))
- continue
-
- # Install
- m = re.match('^Install file: "(.*)" as "(.*)"', line)
- if m :
- ninja.build(m.group(2), 'install', m.group(1))
- continue
-
- m = re.match('^Install directory: "(.*)" as "(.*)"', line)
- if m :
- for source in rglob('*', m.group(1)) :
- if os.path.isdir(source) :
- continue
- target = os.path.join(m.group(2), os.path.relpath(source, m.group(1)))
- ninja.build(target, 'install', source)
- continue
-
- # Tools
- tool, command, flags = parse_tool_command(line)
- tools[tool] = command[0]
-
- ############################################################
- # clang/gcc tools
- ############################################################
-
- if tool == 'cc':
- out, flags = extract_binary_flag("-o", flags)
- files, flags = extract_non_flags(flags)
- ninja.build(out, 'cc', files, order_deps = '_generated_headers', ccflags = flags)
-
- elif tool == 'cxx':
- out, flags = extract_binary_flag("-o", flags)
- files, flags = extract_non_flags(flags)
- ninja.build(out, 'cxx', files, order_deps = '_generated_headers', cxxflags = flags)
-
- elif tool == 'glink':
- out, flags = extract_binary_flag("-o", flags)
- files, flags = extract_non_flags(flags)
- libs = get_unary_flags('-l', flags)
- libpaths = get_unary_flags("-L", flags)
- deps = get_built_libs(libs, libpaths, ninja.targets)
- ninja.build(out, 'link', files, deps = sorted(deps), linkflags = flags)
-
- elif tool == 'ar':
- objects, flags = partition(flags, lambda x: x.endswith('.o'))
- libs, flags = partition(flags, lambda x: x.endswith('.a'))
- out = libs[0]
- ninja.build(out, 'ar', objects, arflags = flags)
-
- elif tool == 'ranlib':
- pass
-
-
- ############################################################
- # MSVC tools
- ############################################################
-
- elif tool == 'cl':
- out, flags = extract_unary_flag("/Fo", flags)
- files, flags = extract_non_flags(flags)
- ninja.build(out, 'cl', files, order_deps = '_generated_headers', clflags = flags)
-
- elif tool == 'lib':
- out, flags = extract_unary_flag("/out:", flags)
- files, flags = extract_non_flags(flags)
- ninja.build(out, 'lib', files, libflags = flags)
-
- elif tool == 'link':
- objects, flags = partition(flags, lambda x: x.endswith('.obj') or x.endswith('.res'))
- out, flags = extract_unary_flag("/out:", flags)
- libs, flags = partition(flags, lambda x: not x.startswith("/") and x.endswith(".lib"))
- libpaths = get_unary_flags("/libpath:", flags)
- deps = get_built_libs(libs, libpaths, ninja.targets)
- if out in mtflags :
- ninja.build(out, 'link_mt', objects, deps = sorted(deps),
- libs = libs, linkflags = flags, mtflags = mtflags[out])
- else :
- ninja.build(out, 'link', objects, deps = sorted(deps),
- libs = libs, linkflags = flags)
-
- elif tool == 'rc':
- out, flags = extract_unary_flag("/fo", flags)
- files, flags = extract_non_flags(flags)
- ninja.build(out, 'rc', files[0], order_deps = '_generated_headers', rcflags = flags)
-
- elif tool == 'mt':
- # Already handled
- pass
-
- ############################################################
- # Qt tools
- ############################################################
-
- elif tool == 'moc':
- out, flags = extract_binary_flag("-o", flags)
- files, flags = extract_non_flags(flags)
- ninja.build(out, 'moc', files, mocflags = flags)
-
- elif tool == 'uic':
- out, flags = extract_binary_flag("-o", flags)
- files, flags = extract_non_flags(flags)
- ninja.build(out, 'uic', files, uicflags = flags)
-
- elif tool == 'lrelease':
- out, flags = extract_binary_flag("-qm", flags)
- files, flags = extract_non_flags(flags)
- ninja.build(out, 'lrelease', files, lreleaseflags = flags)
-
- elif tool == 'rcc':
- out, flags = extract_binary_flag("-o", flags)
- name, flags = extract_binary_flag("-name", flags)
- files, flags = extract_non_flags(flags)
- deps = list(set(get_dependencies(out, ninja.targets)) - set(files))
- ninja.build(out, 'rcc', files, deps = sorted(deps), name = name, rccflags = flags)
-
- ############################################################
- # OS X tools
- ############################################################
-
- elif tool == 'ibtool':
- out, flags = extract_binary_flag("--compile", flags)
- files, flags = extract_non_flags(flags)
- ninja.build(out, 'ibtool', files, ibtoolflags = flags)
-
- elif tool == 'dsymutil':
- out, flags = extract_binary_flag("-o", flags)
- files, flags = extract_non_flags(flags)
- ninja.build(out, 'dsymutil', files, dsymutilflags = flags)
-
- elif tool == 'sdef' :
- source = flags[0];
- outdir, flags = extract_binary_flag("-o", flags)
- basename, flags = extract_binary_flag("--basename", flags)
- ninja.build(os.path.join(outdir, basename + ".h"), 'sdef', [source],
- basename = basename,
- outdir = outdir)
-
-
- elif not ninja_custom_command(ninja, line) :
- raise Exception("Unknown tool: '" + line + "'")
+ # Custom python function
+ m = re.match('^(\w+)\(\[([^\]]*)\]', line)
+ if m :
+ out = [x[1:-1] for x in m.group(2).split(',')]
+ for x in out :
+ # 'Note' = To be more correct, deps should also include $scons_dependencies,
+ # but this regenerates a bit too often, so leaving it out for now.
+ ninja.build(x, 'scons', None, deps = sorted(get_dependencies(x, ninja.targets)))
+ continue
+
+
+ # TextFile
+ m = re.match("^Creating '([^']+)'", line)
+ if m :
+ out = m.group(1)
+ # Note: To be more correct, deps should also include $scons_dependencies,
+ # but this regenerates a bit too often, so leaving it out for now.
+ ninja.build(out, 'scons', None, deps = sorted(get_dependencies(out, ninja.targets)))
+ continue
+
+ # Install
+ m = re.match('^Install file: "(.*)" as "(.*)"', line)
+ if m :
+ ninja.build(m.group(2), 'install', m.group(1))
+ continue
+
+ m = re.match('^Install directory: "(.*)" as "(.*)"', line)
+ if m :
+ for source in rglob('*', m.group(1)) :
+ if os.path.isdir(source) :
+ continue
+ target = os.path.join(m.group(2), os.path.relpath(source, m.group(1)))
+ ninja.build(target, 'install', source)
+ continue
+
+ # Tools
+ tool, command, flags = parse_tool_command(line)
+ tools[tool] = command[0]
+
+ ############################################################
+ # clang/gcc tools
+ ############################################################
+
+ if tool == 'cc':
+ out, flags = extract_binary_flag("-o", flags)
+ files, flags = extract_non_flags(flags)
+ ninja.build(out, 'cc', files, order_deps = '_generated_headers', ccflags = flags)
+
+ elif tool == 'cxx':
+ out, flags = extract_binary_flag("-o", flags)
+ files, flags = extract_non_flags(flags)
+ ninja.build(out, 'cxx', files, order_deps = '_generated_headers', cxxflags = flags)
+
+ elif tool == 'glink':
+ out, flags = extract_binary_flag("-o", flags)
+ files, flags = extract_non_flags(flags)
+ libs = get_unary_flags('-l', flags)
+ libpaths = get_unary_flags("-L", flags)
+ deps = get_built_libs(libs, libpaths, ninja.targets)
+ ninja.build(out, 'link', files, deps = sorted(deps), linkflags = flags)
+
+ elif tool == 'ar':
+ objects, flags = partition(flags, lambda x: x.endswith('.o'))
+ libs, flags = partition(flags, lambda x: x.endswith('.a'))
+ out = libs[0]
+ ninja.build(out, 'ar', objects, arflags = flags)
+
+ elif tool == 'ranlib':
+ pass
+
+
+ ############################################################
+ # MSVC tools
+ ############################################################
+
+ elif tool == 'cl':
+ out, flags = extract_unary_flag("/Fo", flags)
+ files, flags = extract_non_flags(flags)
+ ninja.build(out, 'cl', files, order_deps = '_generated_headers', clflags = flags)
+
+ elif tool == 'lib':
+ out, flags = extract_unary_flag("/out:", flags)
+ files, flags = extract_non_flags(flags)
+ ninja.build(out, 'lib', files, libflags = flags)
+
+ elif tool == 'link':
+ objects, flags = partition(flags, lambda x: x.endswith('.obj') or x.endswith('.res'))
+ out, flags = extract_unary_flag("/out:", flags)
+ libs, flags = partition(flags, lambda x: not x.startswith("/") and x.endswith(".lib"))
+ libpaths = get_unary_flags("/libpath:", flags)
+ deps = get_built_libs(libs, libpaths, ninja.targets)
+ if out in mtflags :
+ ninja.build(out, 'link_mt', objects, deps = sorted(deps),
+ libs = libs, linkflags = flags, mtflags = mtflags[out])
+ else :
+ ninja.build(out, 'link', objects, deps = sorted(deps),
+ libs = libs, linkflags = flags)
+
+ elif tool == 'rc':
+ out, flags = extract_unary_flag("/fo", flags)
+ files, flags = extract_non_flags(flags)
+ ninja.build(out, 'rc', files[0], order_deps = '_generated_headers', rcflags = flags)
+
+ elif tool == 'mt':
+ # Already handled
+ pass
+
+ ############################################################
+ # Qt tools
+ ############################################################
+
+ elif tool == 'moc':
+ out, flags = extract_binary_flag("-o", flags)
+ files, flags = extract_non_flags(flags)
+ ninja.build(out, 'moc', files, mocflags = flags)
+
+ elif tool == 'uic':
+ out, flags = extract_binary_flag("-o", flags)
+ files, flags = extract_non_flags(flags)
+ ninja.build(out, 'uic', files, uicflags = flags)
+
+ elif tool == 'lrelease':
+ out, flags = extract_binary_flag("-qm", flags)
+ files, flags = extract_non_flags(flags)
+ ninja.build(out, 'lrelease', files, lreleaseflags = flags)
+
+ elif tool == 'rcc':
+ out, flags = extract_binary_flag("-o", flags)
+ name, flags = extract_binary_flag("-name", flags)
+ compress, flags = extract_binary_flag("--compress", flags)
+ threshold, flags = extract_binary_flag("--threshold", flags)
+ files, flags = extract_non_flags(flags)
+ deps = list(set(get_dependencies(out, ninja.targets)) - set(files))
+ ninja.build(out, 'rcc', files, deps = sorted(deps), name = name, rccflags = ["--compress", compress, "--threshold", threshold])
+
+ ############################################################
+ # OS X tools
+ ############################################################
+
+ elif tool == 'ibtool':
+ out, flags = extract_binary_flag("--compile", flags)
+ files, flags = extract_non_flags(flags)
+ ninja.build(out, 'ibtool', files, ibtoolflags = flags)
+
+ elif tool == 'dsymutil':
+ out, flags = extract_binary_flag("-o", flags)
+ files, flags = extract_non_flags(flags)
+ ninja.build(out, 'dsymutil', files, dsymutilflags = flags)
+
+ elif tool == 'sdef' :
+ source = flags[0];
+ outdir, flags = extract_binary_flag("-o", flags)
+ basename, flags = extract_binary_flag("--basename", flags)
+ ninja.build(os.path.join(outdir, basename + ".h"), 'sdef', [source],
+ basename = basename,
+ outdir = outdir)
+
+
+ elif not ninja_custom_command(ninja, line) :
+ raise Exception("Unknown tool: '" + line + "'")
# Phony target for all generated headers, used as an order-only depency from all C/C++ sources
@@ -607,11 +609,11 @@ ninja.header("# This file is generated by " + SCRIPT)
ninja.variable("ninja_required_version", "1.3")
ninja.variable("scons_args", SCONS_ARGS)
for k, v in tools.iteritems() :
- ninja.variable(k, v)
+ ninja.variable(k, v)
# Extra customizations
if 'ninja_post' in dir() :
- ninja_post(ninja)
+ ninja_post(ninja)
################################################################################