add json output format to configure file

pull/12170/head
Charles Brunet 2 years ago committed by Eli Schwartz
parent cd30d1889f
commit cf5adf0c64
  1. 5
      docs/markdown/snippets/json_output_format.md
  2. 2
      docs/yaml/functions/configure_file.yaml
  3. 4
      mesonbuild/interpreter/interpreter.py
  4. 2
      mesonbuild/interpreter/kwargs.py
  5. 50
      mesonbuild/utils/universal.py
  6. 5
      test cases/common/269 configure file output format/compare.py
  7. 21
      test cases/common/269 configure file output format/expected/config.h
  8. 1
      test cases/common/269 configure file output format/expected/config.json
  9. 17
      test cases/common/269 configure file output format/expected/config.nasm
  10. 38
      test cases/common/269 configure file output format/meson.build

@ -0,0 +1,5 @@
## Added 'json' output_format to configure_file()
When no input file is specified, [[configure_file]] can now
generate a `json` file from given [[@cfg_data]].
Field descriptions are not preserved in the json file.

@ -134,7 +134,7 @@ kwargs:
The format of the output to generate when no input
was specified. It defaults to `c`, in which case preprocessor directives
will be prefixed with `#`, you can also use `nasm`, in which case the
prefix will be `%`.
prefix will be `%`. *(since 1.3.0)* `json` format can also be used.
encoding:
type: str

@ -2594,8 +2594,8 @@ class Interpreter(InterpreterBase, HoldableObject):
KwargInfo('install_dir', (str, bool), default='',
validator=lambda x: 'must be `false` if boolean' if x is True else None),
OUTPUT_KW,
KwargInfo('output_format', str, default='c', since='0.47.0',
validator=in_set_validator({'c', 'nasm'})),
KwargInfo('output_format', str, default='c', since='0.47.0', since_values={'json': '1.3.0'},
validator=in_set_validator({'c', 'json', 'nasm'})),
)
def func_configure_file(self, node: mparser.BaseNode, args: T.List[TYPE_var],
kwargs: kwtypes.ConfigureFile):

@ -286,7 +286,7 @@ class ConfigureFile(TypedDict):
output: str
capture: bool
format: T.Literal['meson', 'cmake', 'cmake@']
output_format: T.Literal['c', 'nasm']
output_format: T.Literal['c', 'json', 'nasm']
depfile: T.Optional[str]
install: T.Optional[bool]
install_dir: T.Union[str, T.Literal[False]]

@ -32,6 +32,7 @@ import textwrap
import copy
import pickle
import errno
import json
from mesonbuild import mlog
from .core import MesonException, HoldableObject
@ -1361,34 +1362,43 @@ CONF_NASM_PRELUDE = '''; Autogenerated by the Meson build system.
'''
def dump_conf_header(ofilename: str, cdata: 'ConfigurationData', output_format: Literal['c', 'nasm']) -> None:
def _dump_c_header(ofile: T.TextIO, cdata: ConfigurationData, output_format: Literal['c', 'nasm']) -> None:
format_desc: T.Callable[[str], str]
if output_format == 'c':
prelude = CONF_C_PRELUDE
prefix = '#'
else:
format_desc = lambda desc: f'/* {desc} */\n'
else: # nasm
prelude = CONF_NASM_PRELUDE
prefix = '%'
format_desc = lambda desc: '; ' + '\n; '.join(desc.splitlines()) + '\n'
ofile.write(prelude)
for k in sorted(cdata.keys()):
(v, desc) = cdata.get(k)
if desc:
ofile.write(format_desc(desc))
if isinstance(v, bool):
if v:
ofile.write(f'{prefix}define {k}\n\n')
else:
ofile.write(f'{prefix}undef {k}\n\n')
elif isinstance(v, (int, str)):
ofile.write(f'{prefix}define {k} {v}\n\n')
else:
raise MesonException('Unknown data type in configuration file entry: ' + k)
def dump_conf_header(ofilename: str, cdata: ConfigurationData,
output_format: Literal['c', 'nasm', 'json']) -> None:
ofilename_tmp = ofilename + '~'
with open(ofilename_tmp, 'w', encoding='utf-8') as ofile:
ofile.write(prelude)
for k in sorted(cdata.keys()):
(v, desc) = cdata.get(k)
if desc:
if output_format == 'c':
ofile.write('/* %s */\n' % desc)
elif output_format == 'nasm':
for line in desc.split('\n'):
ofile.write('; %s\n' % line)
if isinstance(v, bool):
if v:
ofile.write(f'{prefix}define {k}\n\n')
else:
ofile.write(f'{prefix}undef {k}\n\n')
elif isinstance(v, (int, str)):
ofile.write(f'{prefix}define {k} {v}\n\n')
else:
raise MesonException('Unknown data type in configuration file entry: ' + k)
if output_format == 'json':
data = {k: v[0] for k, v in cdata.values.items()}
json.dump(data, ofile, sort_keys=True)
else: # c, nasm
_dump_c_header(ofile, cdata, output_format)
replace_if_different(ofilename, ofilename_tmp)

@ -0,0 +1,5 @@
import sys
with open(sys.argv[1], 'r', encoding='utf-8') as f, open(sys.argv[2], 'r', encoding='utf-8') as g:
if f.read() != g.read():
sys.exit('contents are not equal')

@ -0,0 +1,21 @@
/*
* Autogenerated by the Meson build system.
* Do not edit, your changes will be lost.
*/
#pragma once
#define bool
#undef false
/* ultimate question of life, the universe, and everything */
#define int 42
/* This is
a multiline
description */
#define str "hello world!"
#define unquoted float

@ -0,0 +1 @@
{"bool": true, "false": false, "int": 42, "str": "\"hello world!\"", "unquoted": "float"}

@ -0,0 +1,17 @@
; Autogenerated by the Meson build system.
; Do not edit, your changes will be lost.
%define bool
%undef false
; ultimate question of life, the universe, and everything
%define int 42
; This is
; a multiline
; description
%define str "hello world!"
%define unquoted float

@ -0,0 +1,38 @@
project('configure file output format')
data = configuration_data()
data.set_quoted('str', 'hello world!', description: '''This is
a multiline
description''')
data.set('unquoted', 'float')
data.set('int', 42, description: 'ultimate question of life, the universe, and everything')
data.set('bool', true)
data.set('false', false)
config_h = configure_file(
configuration: data,
output_format: 'c',
output: 'config.h'
)
config_nasm = configure_file(
configuration: data,
output_format: 'nasm',
output: 'config.nasm'
)
config_json = configure_file(
configuration: data,
output_format: 'json',
output: 'config.json'
)
py = find_program('python3')
compare_py = files('compare.py')
expected_config_h = files('expected/config.h')
expected_config_nasm = files('expected/config.nasm')
expected_config_json = files('expected/config.json')
test('c_output', py, args: [compare_py, expected_config_h, config_h])
test('nasm_output', py, args: [compare_py, expected_config_nasm, config_nasm])
test('json_output', py, args: [compare_py, expected_config_json, config_json])
Loading…
Cancel
Save