configure_file: Substitute @INPUT@/@OUTPUT@/etc in command

The same substitutions and rules as custom_target().

Also generally fix it to actually work when run in a subdir and with
anything other than absolute paths for input and output files.

We now also log a message when configuring files.

Includes tests for all this.
pull/1403/head
Nirbheek Chauhan 8 years ago
parent 1f0319c288
commit cb0aa6a83a
  1. 33
      mesonbuild/interpreter.py
  2. 6
      test cases/common/16 configure file/check_file.py
  3. 16
      test cases/common/16 configure file/generator.py
  4. 2
      test cases/common/16 configure file/installed_files.txt
  5. 18
      test cases/common/16 configure file/meson.build
  6. 19
      test cases/common/16 configure file/subdir/meson.build

@ -2218,12 +2218,24 @@ requirements use the version keyword argument instead.''')
raise InterpreterException('Must not specify both "configuration" '
'and "command" keyword arguments since '
'they are mutually exclusive.')
inputfile = kwargs.get('input', None)
# Validate input
inputfile = None
if 'input' in kwargs:
inputfile = kwargs['input']
if isinstance(inputfile, list):
if len(inputfile) != 1:
m = "Keyword argument 'input' requires exactly one file"
raise InterpreterException(m)
inputfile = inputfile[0]
if not isinstance(inputfile, (str, mesonlib.File)):
raise InterpreterException('Input must be a string or a file')
ifile_abs = os.path.join(self.environment.source_dir, self.subdir, inputfile)
elif 'command' in kwargs:
raise InterpreterException('Required keyword argument \'input\' missing')
# Validate output
output = kwargs['output']
if inputfile is not None and not isinstance(inputfile, str):
raise InterpreterException('Input must be a string.')
if not isinstance(output, str):
raise InterpreterException('Output must be a string.')
raise InterpreterException('Output file name must be a string')
if os.path.split(output)[0] != '':
raise InterpreterException('Output file name must not contain a subdirectory.')
(ofile_path, ofile_fname) = os.path.split(os.path.join(self.subdir, output))
@ -2232,6 +2244,7 @@ requirements use the version keyword argument instead.''')
conf = kwargs['configuration']
if not isinstance(conf, ConfigurationDataHolder):
raise InterpreterException('Argument "configuration" is not of type configuration_data')
mlog.log('Configuring', mlog.bold(output), 'using configuration')
if inputfile is not None:
# Normalize the path of the conffile to avoid duplicates
# This is especially important to convert '/' to '\' on Windows
@ -2239,15 +2252,19 @@ requirements use the version keyword argument instead.''')
if conffile not in self.build_def_files:
self.build_def_files.append(conffile)
os.makedirs(os.path.join(self.environment.build_dir, self.subdir), exist_ok=True)
ifile_abs = os.path.join(self.environment.source_dir, self.subdir, inputfile)
mesonlib.do_conf_file(ifile_abs, ofile_abs, conf.held_object)
else:
mesonlib.dump_conf_header(ofile_abs, conf.held_object)
conf.mark_used()
elif 'command' in kwargs:
if 'input' not in kwargs:
raise InterpreterException('Required keyword input missing.')
res = self.func_run_command(node, kwargs['command'], {})
# We use absolute paths for input and output here because the cwd
# that the command is run from is 'unspecified', so it could change.
# Currently it's builddir/subdir for in_builddir else srcdir/subdir.
values = mesonlib.get_filenames_templates_dict([ifile_abs], [ofile_abs])
# Substitute @INPUT@, @OUTPUT@, etc here.
cmd = mesonlib.substitute_values(kwargs['command'], values)
mlog.log('Configuring', mlog.bold(output), 'with command')
res = self.func_run_command(node, cmd, {'in_builddir': True})
if res.returncode != 0:
raise InterpreterException('Running configure command failed.\n%s\n%s' %
(res.stdout, res.stderr))

@ -0,0 +1,6 @@
#!/usr/bin/env python3
import os
import sys
assert(os.path.exists(sys.argv[1]))

@ -1,15 +1,17 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# On some platforms "python" points to Python 2
# on others to Python 3. Work with both.
from __future__ import print_function
import sys, os
from pathlib import Path
if len(sys.argv) != 3:
print("Wrong amount of parameters.")
assert(os.path.exists(sys.argv[1]))
build_dir = Path(os.environ['MESON_BUILD_ROOT'])
subdir = Path(os.environ['MESON_SUBDIR'])
inputf = Path(sys.argv[1])
outputf = Path(sys.argv[2])
assert(inputf.exists())
with open(sys.argv[2], 'w') as ofile:
with outputf.open('w') as ofile:
ofile.write("#define ZERO_RESULT 0\n")

@ -1 +1,3 @@
usr/share/appdir/config2.h
usr/share/appdireh/config2-1.h
usr/share/appdirok/config2-2.h

@ -23,18 +23,22 @@ cfile)
test('inctest', e)
# Now generate a header file with an external script.
genprog = find_program('python3', required : false)
if not genprog.found()
genprog = find_program('python')
endif
genprog = import('python3').find_python()
scriptfile = '@0@/generator.py'.format(meson.current_source_dir())
ifile = '@0@/dummy.dat'.format(meson.current_source_dir())
ofile = '@0@/config2.h'.format(meson.current_build_dir())
check_file = find_program('check_file.py')
# Configure in source root with command and absolute paths
configure_file(input : 'dummy.dat',
output : 'config2.h',
command : [genprog, scriptfile, ifile, ofile],
install_dir : 'share/appdir')
output : 'config2.h',
command : [genprog, scriptfile, ifile, ofile],
install_dir : 'share/appdir')
run_command(check_file, join_paths(meson.current_build_dir(), 'config2.h'))
found_script = find_program('generator.py')
# More configure_file tests in here
subdir('subdir')
test('inctest2', executable('prog2', 'prog2.c'))

@ -0,0 +1,19 @@
# Configure in subdir with absolute paths for input and relative for output
configure_file(input : '../dummy.dat',
output : 'config2-1.h',
command : [genprog, scriptfile, ifile, 'config2-1.h'],
install_dir : 'share/appdireh')
run_command(check_file, join_paths(meson.current_build_dir(), 'config2-1.h'))
# Configure in subdir with files() for input and relative for output
configure_file(input : '../dummy.dat',
output : 'config2-2.h',
command : [genprog, scriptfile, files('../dummy.dat'), 'config2-2.h'],
install_dir : 'share/appdirok')
run_command(check_file, join_paths(meson.current_build_dir(), 'config2-2.h'))
# Configure in subdir with string templates for input and output
configure_file(input : '../dummy.dat',
output : 'config2-3.h',
command : [found_script, '@INPUT@', '@OUTPUT@'])
run_command(check_file, join_paths(meson.current_build_dir(), 'config2-3.h'))
Loading…
Cancel
Save