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, `@PLAINNAME@` or `@BASENAME@` substitutions). In configuration mode,
the permissions of the input file (if it is specified) are copied to the permissions of the input file (if it is specified) are copied to
the output file. 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() ### 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'}, 'add_test_setup': {'exe_wrapper', 'gdb', 'timeout_multiplier', 'env'},
'benchmark': {'args', 'env', 'should_fail', 'timeout', 'workdir', 'suite'}, 'benchmark': {'args', 'env', 'should_fail', 'timeout', 'workdir', 'suite'},
'build_target': known_build_target_kwargs, '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'}, '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'}, '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'}, '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@'): if fmt not in ('meson', 'cmake', 'cmake@'):
raise InterpreterException('"format" possible values are "meson", "cmake" or "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 # Validate input
inputfile = None inputfile = None
ifile_abs = None ifile_abs = None
@ -3258,7 +3268,7 @@ root and issuing %s.
"present in the given configuration data." % ( "present in the given configuration data." % (
var_list, inputfile), location=node) var_list, inputfile), location=node)
else: else:
mesonlib.dump_conf_header(ofile_abs, conf.held_object) mesonlib.dump_conf_header(ofile_abs, conf.held_object, output_format)
conf.mark_used() conf.mark_used()
elif 'command' in kwargs: elif 'command' in kwargs:
# We use absolute paths for input and output here because the cwd # 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) replace_if_different(dst, dst_tmp)
return missing_variables return missing_variables
def dump_conf_header(ofilename, cdata): CONF_C_PRELUDE = '''/*
ofilename_tmp = ofilename + '~'
with open(ofilename_tmp, 'w', encoding='utf-8') as ofile:
ofile.write('''/*
* Autogenerated by the Meson build system. * Autogenerated by the Meson build system.
* Do not edit, your changes will be lost. * Do not edit, your changes will be lost.
*/ */
#pragma once #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()): for k in sorted(cdata.keys()):
(v, desc) = cdata.get(k) (v, desc) = cdata.get(k)
if desc: 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 isinstance(v, bool):
if v: if v:
ofile.write('#define %s\n\n' % k) ofile.write('%sdefine %s\n\n' % (prefix, k))
else: else:
ofile.write('#undef %s\n\n' % k) ofile.write('%sundef %s\n\n' % (prefix, k))
elif isinstance(v, (int, str)): 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: else:
raise MesonException('Unknown data type in configuration file entry: ' + k) raise MesonException('Unknown data type in configuration file entry: ' + k)
replace_if_different(ofilename, ofilename_tmp) replace_if_different(ofilename, ofilename_tmp)

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