diff options
author | Jussi Pakkanen <jpakkane@gmail.com> | 2013-06-01 13:19:08 +0300 |
---|---|---|
committer | Jussi Pakkanen <jpakkane@gmail.com> | 2013-06-01 13:19:08 +0300 |
commit | 0d2f34654c09def726e3b1d978c45c41a4f08500 (patch) | |
tree | 26828e65c43b01968b581700d2285e1d5bf23ec3 | |
parent | e453c408da14448d3ac8ffabb8010aafe8ee9ac0 (diff) | |
download | meson-0d2f34654c09def726e3b1d978c45c41a4f08500.zip meson-0d2f34654c09def726e3b1d978c45c41a4f08500.tar.gz meson-0d2f34654c09def726e3b1d978c45c41a4f08500.tar.bz2 |
Generator rules can have more than one output.
-rwxr-xr-x | backends.py | 20 | ||||
-rwxr-xr-x | environment.py | 3 | ||||
-rwxr-xr-x | interpreter.py | 37 | ||||
-rw-r--r-- | test cases/common/29 pipeline/meson.build | 2 | ||||
-rw-r--r-- | test cases/common/30 pipeline/meson.build | 4 | ||||
-rw-r--r-- | test cases/common/31 find program/meson.build | 2 | ||||
-rw-r--r-- | test cases/frameworks/5 protocol buffers/meson.build | 2 |
7 files changed, 43 insertions, 27 deletions
diff --git a/backends.py b/backends.py index 9265ade..6684aea 100755 --- a/backends.py +++ b/backends.py @@ -20,6 +20,7 @@ import environment from meson_install import InstallData from interpreter import InvalidArguments import shutil +from coredata import MesonException if environment.is_windows(): quote_char = '"' @@ -525,22 +526,29 @@ class NinjaBackend(Backend): exe = generator.get_exe() infilelist = genlist.get_infilelist() outfilelist = genlist.get_outfilelist() - if len(infilelist) != len(outfilelist): - raise RuntimeError('Internal data structures broken.') if isinstance(exe, interpreter.BuildTarget): exe_file = os.path.join(self.environment.get_build_dir(), self.get_target_filename(exe)) else: exe_file = exe.get_command() base_args = generator.get_arglist() for i in range(len(infilelist)): - infilename = os.path.join(self.environment.get_source_dir(), infilelist[i]) - outfilename = os.path.join(self.get_target_private_dir(target), outfilelist[i]) - args = [x.replace("@INPUT@", infilename).replace('@OUTPUT@', outfilename)\ + if len(infilelist) == len(outfilelist): + sole_output = os.path.join(self.get_target_private_dir(target), outfilelist[i]) + else: + for x in base_args: + if '@OUTPUT@' in x: + raise MesonException('Tried to use @OUTPUT@ in a rule with more than one output.') + sole_output = '' + curfile = infilelist[i] + infilename = os.path.join(self.environment.get_source_dir(), curfile) + outfiles = genlist.get_outputs_for(curfile) + outfiles = [os.path.join(self.get_target_private_dir(target), of) for of in outfiles] + args = [x.replace("@INPUT@", infilename).replace('@OUTPUT@', sole_output)\ for x in base_args] args = [x.replace("@SOURCE_DIR@", self.environment.get_source_dir()).replace("@BUILD_DIR@", self.get_target_private_dir(target)) for x in args] cmdlist = [exe_file] + args - elem = NinjaBuildElement(outfilename, 'CUSTOM_COMMAND', infilename) + elem = NinjaBuildElement(outfiles, 'CUSTOM_COMMAND', infilename) elem.add_item('DESC', 'Generating $out') if isinstance(exe, interpreter.BuildTarget): elem.add_dep(self.get_target_filename(exe)) diff --git a/environment.py b/environment.py index 301180e..753c8f0 100755 --- a/environment.py +++ b/environment.py @@ -147,13 +147,12 @@ int main(int argc, char **argv) { os.close(fd) ofile = open(srcname, 'w') code = templ % (prefix, element) - print(code) ofile.write(code) ofile.close() commands = self.get_exelist() commands.append(srcname) commands += self.get_output_flags(exename) - p = subprocess.Popen(commands, cwd=os.path.split(srcname)[0])#s, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + p = subprocess.Popen(commands, cwd=os.path.split(srcname)[0], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) p.communicate() os.remove(srcname) if p.returncode != 0: diff --git a/interpreter.py b/interpreter.py index 8b33491..a5a2e7c 100755 --- a/interpreter.py +++ b/interpreter.py @@ -148,21 +148,24 @@ class Generator(InterpreterObject): raise InvalidArguments('A non-string object in "arguments" keyword argument.') self.arglist = args - if 'output_name' not in kwargs: - raise InvalidArguments('Generator must have "output_name" keyword argument.') - rule = kwargs['output_name'] - if not isinstance(rule, str): - raise InvalidArguments('"output_name" keyword argument must be a string.') - if not '@BASENAME@' in rule and not '@PLAINNAME@' in rule: - raise InvalidArguments('"output_name" must contain @BASENAME@ or @PLAINNAME@.') - if '/' in rule: - raise InvalidArguments('"output_name" must not contain a slash.') - self.name_rule = rule - - def get_base_outname(self, inname): + if 'outputs' not in kwargs: + raise InvalidArguments('Generator must have "outputs" keyword argument.') + outputs = kwargs['outputs'] + if not isinstance(outputs, list): + outputs = [outputs] + for rule in outputs: + if not isinstance(rule, str): + raise InvalidArguments('"outputs" may only contain strings.') + if not '@BASENAME@' in rule and not '@PLAINNAME@' in rule: + raise InvalidArguments('"outputs" must contain @BASENAME@ or @PLAINNAME@.') + if '/' in rule or '\\' in rule: + raise InvalidArguments('"outputs" must not contain a directory separator.') + self.outputs = outputs + + def get_base_outnames(self, inname): plainname = os.path.split(inname)[1] basename = plainname.split('.')[0] - return self.name_rule.replace('@BASENAME@', basename).replace('@PLAINNAME@', plainname) + return [x.replace('@BASENAME@', basename).replace('@PLAINNAME@', plainname) for x in self.outputs] def process_method(self, args, kwargs): if len(kwargs) > 0: @@ -187,10 +190,13 @@ class GeneratedList(InterpreterObject): self.generator = generator self.infilelist = [] self.outfilelist = [] + self.outmap = {} def add_file(self, newfile): self.infilelist.append(newfile) - self.outfilelist.append(self.generator.get_base_outname(newfile)) + outfiles = self.generator.get_base_outnames(newfile) + self.outfilelist += outfiles + self.outmap[newfile] = outfiles def get_infilelist(self): return self.infilelist @@ -198,6 +204,9 @@ class GeneratedList(InterpreterObject): def get_outfilelist(self): return self.outfilelist + def get_outputs_for(self, filename): + return self.outmap[filename] + def get_generator(self): return self.generator diff --git a/test cases/common/29 pipeline/meson.build b/test cases/common/29 pipeline/meson.build index 96de345..53be502 100644 --- a/test cases/common/29 pipeline/meson.build +++ b/test cases/common/29 pipeline/meson.build @@ -3,7 +3,7 @@ project('pipeline test', 'c') e1 = executable('srcgen', 'srcgen.c') gen = generator(e1, \ - output_name : '@BASENAME@.c', # Line continuation inside arguments should work without needing a "\". + outputs : '@BASENAME@.c', # Line continuation inside arguments should work without needing a "\". arguments : ['@INPUT@', '@OUTPUT@']) generated = gen.process('input_src.dat') diff --git a/test cases/common/30 pipeline/meson.build b/test cases/common/30 pipeline/meson.build index 1948eeb..f25d4c4 100644 --- a/test cases/common/30 pipeline/meson.build +++ b/test cases/common/30 pipeline/meson.build @@ -2,8 +2,8 @@ project('pipeline test', 'c') e1 = executable('srcgen', 'srcgen.c') -gen = generator(e1, \ - output_name : '@BASENAME@.h', \ +gen = generator(e1, + outputs : '@BASENAME@.h', arguments : ['@INPUT@', '@OUTPUT@']) generated = gen.process('input_src.dat') diff --git a/test cases/common/31 find program/meson.build b/test cases/common/31 find program/meson.build index f466d95..c8a7093 100644 --- a/test cases/common/31 find program/meson.build +++ b/test cases/common/31 find program/meson.build @@ -11,7 +11,7 @@ if host.name() == 'windows' else cp = find_program('cp', required : true) gen = generator(cp, \ - output_name : '@BASENAME@.c', \ + outputs : '@BASENAME@.c', \ arguments : ['@INPUT@', '@OUTPUT@']) generated = gen.process('source.in') diff --git a/test cases/frameworks/5 protocol buffers/meson.build b/test cases/frameworks/5 protocol buffers/meson.build index 37531a1..e0edb4c 100644 --- a/test cases/frameworks/5 protocol buffers/meson.build +++ b/test cases/frameworks/5 protocol buffers/meson.build @@ -4,7 +4,7 @@ protoc = find_program('protoc', required : true) dep = find_dep('protobuf', required : true) gen = generator(protoc, \ - output_name : '@BASENAME@.pb.cc', + outputs : ['@BASENAME@.pb.cc', '@BASENAME@.pb.h'], arguments : ['-I=@SOURCE_DIR@', '--cpp_out=@BUILD_DIR@', '@INPUT@']) generated = gen.process('defs.proto') |