custom_target: Recursively flatten `command:`

Without this, files() in the arguments give an error because it's a list
of mesonlib.File objects:

  Array as argument 1 contains a non-string.

It also breaks in nested lists. Includes a test for this.
pull/1382/merge
Nirbheek Chauhan 8 years ago committed by Jussi Pakkanen
parent 16adedf6bc
commit 15b6915954
  1. 50
      mesonbuild/build.py
  2. 4
      test cases/common/56 custom target/meson.build
  3. 15
      test cases/common/56 custom target/my_compiler.py

@ -1298,6 +1298,29 @@ class CustomTarget(Target):
deps.append(c)
return deps
def flatten_command(self, cmd):
if not isinstance(cmd, list):
cmd = [cmd]
final_cmd = []
for c in cmd:
if hasattr(c, 'held_object'):
c = c.held_object
if isinstance(c, (str, File)):
final_cmd.append(c)
elif isinstance(c, dependencies.ExternalProgram):
if not c.found():
m = 'Tried to use not-found external program {!r} in "command"'
raise InvalidArguments(m.format(c.name))
final_cmd += c.get_command()
elif isinstance(c, (BuildTarget, CustomTarget)):
self.dependencies.append(c)
final_cmd.append(c)
elif isinstance(c, list):
final_cmd += self.flatten_command(c)
else:
raise InvalidArguments('Argument {!r} in "command" is invalid'.format(c))
return final_cmd
def process_kwargs(self, kwargs):
super().process_kwargs(kwargs)
self.sources = kwargs.get('input', [])
@ -1325,32 +1348,7 @@ class CustomTarget(Target):
if os.path.split(depfile)[1] != depfile:
raise InvalidArguments('Depfile must be a plain filename without a subdirectory.')
self.depfile = depfile
cmd = kwargs['command']
if not(isinstance(cmd, list)):
cmd = [cmd]
final_cmd = []
for i, c in enumerate(cmd):
if hasattr(c, 'held_object'):
c = c.held_object
if isinstance(c, (str, File)):
final_cmd.append(c)
elif isinstance(c, dependencies.ExternalProgram):
if not c.found():
raise InvalidArguments('Tried to use not found external program {!r} in a build rule.'.format(c.name))
final_cmd += c.get_command()
elif isinstance(c, (BuildTarget, CustomTarget)):
self.dependencies.append(c)
final_cmd.append(c)
elif isinstance(c, list):
# Hackety hack, only supports one level of flattening. Should really
# work to arbtrary depth.
for s in c:
if not isinstance(s, str):
raise InvalidArguments('Array as argument %d contains a non-string.' % i)
final_cmd.append(s)
else:
raise InvalidArguments('Argument %s in "command" is invalid.' % i)
self.command = final_cmd
self.command = self.flatten_command(kwargs['command'])
if self.capture:
for c in self.command:
if isinstance(c, str) and '@OUTPUT@' in c:

@ -8,11 +8,13 @@ endif
# Note that this will not add a dependency to the compiler executable.
# Code will not be rebuilt if it changes.
comp = '@0@/@1@'.format(meson.current_source_dir(), 'my_compiler.py')
# Test that files() in command: works. The compiler just discards it.
useless = files('installed_files.txt')
mytarget = custom_target('bindat',
output : 'data.dat',
input : 'data_source.txt',
command : [python, comp, '--input=@INPUT@', '--output=@OUTPUT@'],
command : [python, comp, '--input=@INPUT@', '--output=@OUTPUT@', useless],
install : true,
install_dir : 'subdir'
)

@ -1,16 +1,21 @@
#!/usr/bin/env python3
import os
import sys
assert(os.path.exists(sys.argv[3]))
args = sys.argv[:-1]
if __name__ == '__main__':
if len(sys.argv) != 3 or not sys.argv[1].startswith('--input') or \
not sys.argv[2].startswith('--output'):
print(sys.argv[0], '--input=input_file --output=output_file')
if len(args) != 3 or not args[1].startswith('--input') or \
not args[2].startswith('--output'):
print(args[0], '--input=input_file --output=output_file')
sys.exit(1)
with open(sys.argv[1].split('=')[1]) as f:
with open(args[1].split('=')[1]) as f:
ifile = f.read()
if ifile != 'This is a text only input file.\n':
print('Malformed input')
sys.exit(1)
with open(sys.argv[2].split('=')[1], 'w') as ofile:
with open(args[2].split('=')[1], 'w') as ofile:
ofile.write('This is a binary output file.\n')

Loading…
Cancel
Save