aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJussi Pakkanen <jpakkane@gmail.com>2013-06-01 13:19:08 +0300
committerJussi Pakkanen <jpakkane@gmail.com>2013-06-01 13:19:08 +0300
commit0d2f34654c09def726e3b1d978c45c41a4f08500 (patch)
tree26828e65c43b01968b581700d2285e1d5bf23ec3
parente453c408da14448d3ac8ffabb8010aafe8ee9ac0 (diff)
downloadmeson-0d2f34654c09def726e3b1d978c45c41a4f08500.zip
meson-0d2f34654c09def726e3b1d978c45c41a4f08500.tar.gz
meson-0d2f34654c09def726e3b1d978c45c41a4f08500.tar.bz2
Generator rules can have more than one output.
-rwxr-xr-xbackends.py20
-rwxr-xr-xenvironment.py3
-rwxr-xr-xinterpreter.py37
-rw-r--r--test cases/common/29 pipeline/meson.build2
-rw-r--r--test cases/common/30 pipeline/meson.build4
-rw-r--r--test cases/common/31 find program/meson.build2
-rw-r--r--test cases/frameworks/5 protocol buffers/meson.build2
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')