diff --git a/backends.py b/backends.py index 574d8f93b..380af9255 100644 --- a/backends.py +++ b/backends.py @@ -85,6 +85,16 @@ def do_conf_file(src, dst, confdata): open(dst_tmp, 'w').writelines(result) replace_if_different(dst, dst_tmp) +class RawFilename(): + def __init__(self, fname): + self.fname = fname + + def split(self, c): + return self.fname.split(c) + + def startswith(self, s): + return self.fname.startswith(s) + class TestSerialisation: def __init__(self, name, fname, is_cross, exe_wrapper, is_parallel, cmd_args, env): self.name = name @@ -121,7 +131,10 @@ class Backend(): def get_target_filename(self, target): targetdir = self.get_target_dir(target) - filename = os.path.join(targetdir, target.get_filename()) + fname = target.get_filename() + if isinstance(fname, list): + fname = fname[0] # HORROR, HORROR! Fix this. + filename = os.path.join(targetdir, fname) return filename def get_target_dir(self, target): @@ -231,8 +244,21 @@ class Backend(): header_deps = gen_other_deps unity_src = [] unity_deps = [] # Generated sources that must be built before compiling a Unity target. - for genlist in target.get_generated_sources(): - for src in genlist.get_outfilelist(): + for gensource in target.get_generated_sources(): + if isinstance(gensource, build.CustomTarget): + for src in gensource.output: + src = os.path.join(gensource.subdir, src) + if self.environment.is_header(src): + header_deps.append(RawFilename(src)) + elif self.environment.is_source(src): + if is_unity: + unity_deps.append(os.path.join(self.environment.get_build_dir(), RawFilename(src))) + else: + obj_list.append(self.generate_single_compile(target, outfile, RawFilename(src), True)) + else: + pass # perhaps print warning about the unknown file? + break # just to cut down on indentation size + for src in gensource.get_outfilelist(): if self.environment.is_object(src): obj_list.append(os.path.join(self.get_target_dir(target), target.get_basename() + '.dir', src)) elif not self.environment.is_header(src): diff --git a/build.py b/build.py index 2b5db29cd..8136d9eb5 100644 --- a/build.py +++ b/build.py @@ -159,9 +159,11 @@ class BuildTarget(): # Holder unpacking. Ugly. if hasattr(s, 'glist'): s = s.glist + if hasattr(s, 'held_object'): + s = s.held_object if isinstance(s, str): self.sources.append(s) - elif isinstance(s, GeneratedList): + elif isinstance(s, GeneratedList) or isinstance(s, CustomTarget): self.generated.append(s) else: raise InvalidArguments('Bad source in target %s.' % self.name) @@ -609,10 +611,13 @@ class CustomTarget: if 'output' not in kwargs: raise InvalidArguments('Missing keyword argument "output".') self.output = kwargs['output'] - if not(isinstance(self.output, str)): - raise InvalidArguments('Output argument not a string.') - if '/' in self.output: - raise InvalidArguments('Output must not contain a path segment.') + if not isinstance(self.output, list): + self.output = [self.output] + for i in self.output: + if not(isinstance(i, str)): + raise InvalidArguments('Output argument not a string.') + if '/' in i: + raise InvalidArguments('Output must not contain a path segment.') if 'command' not in kwargs: raise InvalidArguments('Missing keyword argument "command".') cmd = kwargs['command'] diff --git a/ninjabackend.py b/ninjabackend.py index ef66b2760..7b7056590 100644 --- a/ninjabackend.py +++ b/ninjabackend.py @@ -137,21 +137,21 @@ class NinjaBackend(backends.Backend): os.replace(tempfilename, outfilename) def generate_custom_target(self, target, outfile): - ofilename = os.path.join(target.subdir, target.output) + ofilenames = [os.path.join(target.subdir, i) for i in target.output] deps = [os.path.join(i.get_subdir(), i.get_filename()) for i in target.get_dependencies()] srcs = [os.path.join(self.build_to_src, target.subdir, i) for i in target.sources] deps += srcs - elem = NinjaBuildElement(ofilename, 'CUSTOM_COMMAND', deps) + elem = NinjaBuildElement(ofilenames, 'CUSTOM_COMMAND', deps) cmd = [] for i in target.command: if i == '@INPUT@': cmd += srcs elif i == '@OUTPUT@': - cmd.append(ofilename) + cmd.append += ofilenames else: cmd.append(i) elem.add_item('COMMAND', cmd) - elem.add_item('description', 'Generating %s with a custom command.' % ofilename) + elem.add_item('description', 'Generating %s with a custom command.' % target.name) elem.write(outfile) self.processed_targets[target.name] = True @@ -782,9 +782,10 @@ class NinjaBackend(backends.Backend): newargs.append(arg) return newargs - def generate_custom_generator_rules(self, target, outfile): for genlist in target.get_generated_sources(): + if isinstance(genlist, build.CustomTarget): + continue # Customtarget has already written its output rules generator = genlist.get_generator() exe = generator.get_exe() if self.environment.is_cross_build() and \ @@ -827,7 +828,9 @@ class NinjaBackend(backends.Backend): compiler = self.get_compiler_for_source(src) commands = self.generate_basic_compiler_args(target, compiler) commands.append(compiler.get_include_arg(self.get_target_private_dir(target))) - if is_generated: + if isinstance(src, backends.RawFilename): + rel_src = src.fname + elif is_generated: if '/' in src: rel_src = src else: @@ -838,6 +841,8 @@ class NinjaBackend(backends.Backend): src_filename = os.path.basename(src) else: src_filename = src + if isinstance(src, backends.RawFilename): + src_filename = src.fname obj_basename = src_filename.replace('/', '_').replace('\\', '_') rel_obj = os.path.join(self.get_target_private_dir(target), obj_basename) rel_obj += '.' + self.environment.get_object_suffix() @@ -871,11 +876,15 @@ class NinjaBackend(backends.Backend): element = NinjaBuildElement(rel_obj, compiler_name, rel_src) for d in header_deps: - if not '/' in d: + if isinstance(d, backends.RawFilename): + d = d.fname + elif not '/' in d: d = os.path.join(self.get_target_private_dir(target), d) element.add_dep(d) for d in order_deps: - if not '/' in d: + if isinstance(d, backends.RawFilename): + d = d.fname + elif not '/' in d : d = os.path.join(self.get_target_private_dir(target), d) element.add_orderdep(d) element.add_orderdep(pch_dep)