Merge pull request #1874 from rindeal/configure_file-capture

add `capture: true` ability to configure_file()
pull/1918/head
Jussi Pakkanen 8 years ago committed by GitHub
commit 3ced977547
  1. 3
      docs/markdown/Reference-manual.md
  2. 6
      docs/markdown/Release-notes-for-0.41.0.md
  3. 13
      mesonbuild/interpreter.py
  4. 28
      test cases/common/16 configure file/basename.py
  5. 22
      test cases/common/16 configure file/file_contains.py
  6. 17
      test cases/common/16 configure file/meson.build
  7. 16
      test cases/common/16 configure file/touch.py

@ -127,6 +127,7 @@ These are all the supported keyword arguments:
- `output` the output file name (since v0.41.0, may contain `@PLAINNAME@` or `@BASENAME@` substitutions). In configuration mode, the permissions of the input file (if it is specified) are copied to the output file.
- `configuration` as explained above, this is where you pass the configuration data object as returned by `configuration_data()`
- `command` as explained above, if specified, Meson does not create the file itself but rather runs the specified command, which allows you to do fully custom file generation
- `capture` when this argument is set to true, Meson captures `stdout` of the `command` and writes it to the target file specified as `output`. Available since v0.41.0.
- `install_dir` the subdirectory to install the generated file to (e.g. `share/myproject`), if omitted the file is not installed.
### custom_target()
@ -540,7 +541,7 @@ Project supports the following keyword arguments.
- `subproject_dir` specifies the top level directory name that holds Meson subprojects. This is only meant as a compatibility option for existing code bases that house their embedded source code in a custom directory. All new projects should not set this but instead use the default value. It should be noted that this keyword argument is ignored inside subprojects. There can be only one subproject dir and it is set in the top level Meson file.
- `meson_version` takes a string describing which Meson version the project requires. Usually something like `>0.28.0`.
- `license` takes a string or array of strings describing the license(s) the code is under. Usually this would be something like `license : 'GPL2+'`, but if the code has multiple licenses you can specify them as an array like this: `license : ['proprietary', 'GPL3']`. Note that the text is informal and is only written to the dependency manifest. Meson does not do any license validation, you are responsible for verifying that you abide by all licensing terms.
- `default_options` takes an array of strings. The strings are in the form `key=value` and have the same format as options to `mesonconf`. For example to set the default project type you would set this: `default_options : ['buildtype=debugoptimized']`. Note that these settings are only used when running Meson for the first time. Global options such as `buildtype` can only be specified in the master project, settings in subprojects are ignored. Project specific options are used normally even in subprojects.

@ -80,3 +80,9 @@ but actually isn't. For example when:
- `build_machine` is macOS and `host_machine` is the iOS Simulator
- the `build_machine`'s libc is glibc but the `host_machine` libc is uClibc
- code relies on kernel features not available on the `build_machine`
## Support for capturing stdout of a command in configure_file
`configure_file()` now supports a new keyword - `capture`. When this argument
is set to true, Meson captures `stdout` of the `command` and writes it to
the target file specified as `output`.

@ -2319,6 +2319,12 @@ class Interpreter(InterpreterBase):
raise InterpreterException('Must not specify both "configuration" '
'and "command" keyword arguments since '
'they are mutually exclusive.')
if 'capture' in kwargs:
if not isinstance(kwargs['capture'], bool):
raise InterpreterException('"capture" keyword must be a boolean.')
if 'command' not in kwargs:
raise InterpreterException('"capture" keyword requires "command" keyword.')
# Validate input
inputfile = None
ifile_abs = None
@ -2383,6 +2389,13 @@ class Interpreter(InterpreterBase):
if res.returncode != 0:
raise InterpreterException('Running configure command failed.\n%s\n%s' %
(res.stdout, res.stderr))
if 'capture' in kwargs and kwargs['capture']:
dst_tmp = ofile_abs + '~'
with open(dst_tmp, 'w', encoding='utf-8') as f:
f.writelines(res.stdout)
if ifile_abs:
shutil.copymode(ifile_abs, dst_tmp)
mesonlib.replace_if_different(ofile_abs, dst_tmp)
else:
raise InterpreterException('Configure_file must have either "configuration" or "command".')
idir = kwargs.get('install_dir', None)

@ -0,0 +1,28 @@
#!/usr/bin/env python3
import sys
import argparse
import os
def main():
parser = argparse.ArgumentParser()
parser.add_argument('text', nargs='*', type=str)
args = parser.parse_args()
text = args.text if isinstance(args.text, list) else [args.text]
output = ''
for t in text:
t = os.path.basename(t)
if not output:
output += t
else:
output += ' ' + t
output += '\n'
sys.stdout.write(output)
if __name__ == '__main__':
sys.exit(main())

@ -0,0 +1,22 @@
#!/usr/bin/env python3
import sys
import argparse
def main():
parser = argparse.ArgumentParser()
parser.add_argument('file', nargs=1, type=str)
parser.add_argument('text', nargs=1, type=str)
args = parser.parse_args()
text = args.text[0]
with open(args.file[0], 'r', encoding='utf-8') as f:
for line in f:
if line.strip() == text:
return 0
return 1
if __name__ == '__main__':
sys.exit(main())

@ -86,3 +86,20 @@ foreach config_template : config_templates
endforeach
test('Substituted', executable('prog4', 'prog4.c'))
# Test `capture` keyword
basename_py = find_program('basename.py')
file_contains_py = find_program('file_contains.py')
test_string = 'hello world'
test_input_file = join_paths(meson.current_build_dir(), test_string)
run_command(find_program('touch.py'), test_input_file)
configs = [
# no input
configure_file(command: [ basename_py, test_string ], capture: true, output: 'capture test 1'),
# with input
configure_file(input: test_input_file, command: [ basename_py, '@INPUT@' ], capture: true, output: 'capture test 2'),
]
foreach c : configs
test('@0@'.format(c), file_contains_py, args: [ c, test_string ])
endforeach

@ -0,0 +1,16 @@
#!/usr/bin/env python3
import sys
import argparse
from pathlib import Path
def main():
parser = argparse.ArgumentParser()
parser.add_argument('files', nargs='*', type=str)
args = parser.parse_args()
for filepath in args.files:
Path(filepath).touch()
if __name__ == '__main__':
sys.exit(main())
Loading…
Cancel
Save