configure_file: Add output_format kwarg (#3636)

* configure_file: Add output_format kwarg

* docs: Reference-manual.md output_format was added in 0.47 [skip ci]
pull/3668/head
Mathieu Duponchelle 7 years ago committed by Nirbheek Chauhan
parent 17cb364046
commit 14750b50ea
  1. 4
      docs/markdown/Reference-manual.md
  2. 14
      docs/markdown/snippets/configure_file_output_format.md
  3. 14
      mesonbuild/interpreter.py
  4. 36
      mesonbuild/mesonlib.py
  5. 1
      run_project_tests.py
  6. 27
      test cases/nasm/1 configure file/hello.asm
  7. 44
      test cases/nasm/1 configure file/meson.build

@ -208,6 +208,10 @@ the `@variable@` syntax.
`@PLAINNAME@` or `@BASENAME@` substitutions). In configuration mode,
the permissions of the input file (if it is specified) are copied to
the output file.
- `output_format` *(added 0.47.0)* 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 `%`.
### custom_target()

@ -0,0 +1,14 @@
## New keyword argument `output_format` for configure_file()
When called without an input file, `configure_file` generates a
C header file by default. A keyword argument was added to allow
specifying the output format, for example for use with nasm or yasm:
```
conf = configuration_data()
conf.set('FOO', 1)
configure_file('config.asm',
configuration: conf,
output_format: 'nasm')
```

@ -1697,7 +1697,7 @@ permitted_kwargs = {'add_global_arguments': {'language'},
'add_test_setup': {'exe_wrapper', 'gdb', 'timeout_multiplier', 'env'},
'benchmark': {'args', 'env', 'should_fail', 'timeout', 'workdir', 'suite'},
'build_target': known_build_target_kwargs,
'configure_file': {'input', 'output', 'configuration', 'command', 'copy', 'install_dir', 'capture', 'install', 'format'},
'configure_file': {'input', 'output', 'configuration', 'command', 'copy', 'install_dir', 'capture', 'install', 'format', 'output_format'},
'custom_target': {'input', 'output', 'command', 'install', 'install_dir', 'build_always', 'capture', 'depends', 'depend_files', 'depfile', 'build_by_default'},
'dependency': {'default_options', 'fallback', 'language', 'main', 'method', 'modules', 'optional_modules', 'native', 'required', 'static', 'version', 'private_headers'},
'declare_dependency': {'include_directories', 'link_with', 'sources', 'dependencies', 'compile_args', 'link_args', 'link_whole', 'version'},
@ -3196,6 +3196,16 @@ root and issuing %s.
if fmt not in ('meson', 'cmake', 'cmake@'):
raise InterpreterException('"format" possible values are "meson", "cmake" or "cmake@".')
if 'output_format' in kwargs:
output_format = kwargs['output_format']
if not isinstance(output_format, str):
raise InterpreterException('"output_format" keyword must be a string.')
else:
output_format = 'c'
if output_format not in ('c', 'nasm'):
raise InterpreterException('"format" possible values are "c" or "nasm".')
# Validate input
inputfile = None
ifile_abs = None
@ -3258,7 +3268,7 @@ root and issuing %s.
"present in the given configuration data." % (
var_list, inputfile), location=node)
else:
mesonlib.dump_conf_header(ofile_abs, conf.held_object)
mesonlib.dump_conf_header(ofile_abs, conf.held_object, output_format)
conf.mark_used()
elif 'command' in kwargs:
# We use absolute paths for input and output here because the cwd

@ -634,28 +634,46 @@ def do_conf_file(src, dst, confdata, format):
replace_if_different(dst, dst_tmp)
return missing_variables
def dump_conf_header(ofilename, cdata):
ofilename_tmp = ofilename + '~'
with open(ofilename_tmp, 'w', encoding='utf-8') as ofile:
ofile.write('''/*
CONF_C_PRELUDE = '''/*
* Autogenerated by the Meson build system.
* Do not edit, your changes will be lost.
*/
#pragma once
''')
'''
CONF_NASM_PRELUDE = '''; Autogenerated by the Meson build system.
; Do not edit, your changes will be lost.
'''
def dump_conf_header(ofilename, cdata, output_format):
if output_format == 'c':
prelude = CONF_C_PRELUDE
prefix = '#'
elif output_format == 'nasm':
prelude = CONF_NASM_PRELUDE
prefix = '%'
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:
ofile.write('/* %s */\n' % 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('#define %s\n\n' % k)
ofile.write('%sdefine %s\n\n' % (prefix, k))
else:
ofile.write('#undef %s\n\n' % k)
ofile.write('%sundef %s\n\n' % (prefix, k))
elif isinstance(v, (int, str)):
ofile.write('#define %s %s\n\n' % (k, v))
ofile.write('%sdefine %s %s\n\n' % (prefix, k, v))
else:
raise MesonException('Unknown data type in configuration file entry: ' + k)
replace_if_different(ofilename, ofilename_tmp)

@ -523,6 +523,7 @@ def detect_tests_to_run():
('python3', 'python3', backend is not Backend.ninja),
('fpga', 'fpga', shutil.which('yosys') is None),
('frameworks', 'frameworks', False),
('nasm', 'nasm', False),
]
gathered_tests = [(name, gather_tests(Path('test cases', subdir)), skip) for name, subdir, skip in all_tests]
return gathered_tests

@ -0,0 +1,27 @@
; hello.asm a first program for nasm for Linux, Intel, gcc
;
; assemble: nasm -f elf -l hello.lst hello.asm
; link: gcc -o hello hello.o
; run: hello
; output is: Hello World
%include "config.asm"
SECTION .data ; data section
msg: db "Hello World",10 ; the string to print, 10=cr
len: equ $-msg ; "$" means "here"
; len is a value, not an address
SECTION .text ; code section
global main ; make label available to linker
main: ; standard gcc entry point
mov edx,len ; arg3, length of string to print
mov ecx,msg ; arg2, pointer to string
mov ebx,1 ; arg1, where to write, screen
mov eax,4 ; write sysout command to int 80 hex
int 0x80 ; interrupt 80 hex, call kernel
mov ebx,HELLO ; exit code, 0=normal
mov eax,1 ; exit command to kernel
int 0x80 ; interrupt 80 hex, call kernel

@ -0,0 +1,44 @@
project('nasm config file', 'c')
if host_machine.cpu_family() == 'x86' and host_machine.system() == 'windows'
asm_format = 'win32'
elif host_machine.cpu_family() == 'x86_64' and host_machine.system() == 'windows'
asm_format = 'win64'
elif host_machine.cpu_family() == 'x86' and host_machine.system() == 'linux'
asm_format = 'elf32'
elif host_machine.cpu_family() == 'x86_64' and host_machine.system() == 'linux'
asm_format = 'elf64'
else
error('MESON_SKIP_TEST: skipping test on this platform')
endif
nasm = find_program('nasm', required: false)
if not nasm.found()
error('MESON_SKIP_TEST: nasm not available')
endif
conf = configuration_data()
conf.set('HELLO', 0)
asm_gen = generator(nasm,
output : '@BASENAME@.o',
arguments : [
'-f', asm_format,
'-i', meson.current_source_dir() + '/',
'-i', join_paths(meson.current_source_dir(), ''),
'-P', join_paths(meson.current_build_dir(), 'config.asm'),
'@INPUT@',
'-o', '@OUTPUT@'])
config_file = configure_file(
output: 'config.asm',
configuration: conf,
output_format: 'nasm',
)
exe = executable('hello', asm_gen.process('hello.asm'))
test('test-nasm-configure-file', exe)
Loading…
Cancel
Save