Generator rules can have more than one output.

pull/15/head
Jussi Pakkanen 12 years ago
parent e453c408da
commit 0d2f34654c
  1. 20
      backends.py
  2. 3
      environment.py
  3. 37
      interpreter.py
  4. 2
      test cases/common/29 pipeline/meson.build
  5. 4
      test cases/common/30 pipeline/meson.build
  6. 2
      test cases/common/31 find program/meson.build
  7. 2
      test cases/frameworks/5 protocol buffers/meson.build

@ -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))

@ -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:

@ -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

@ -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')

@ -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')

@ -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')

@ -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')

Loading…
Cancel
Save