configure_file: Add a new action 'copy'
This will copy the file to the build directory without trying to read it or substitute values into it. Also do this optimization if the configuration_data() object passed to the `configuration:` kwarg is empty, and print a warning about it. See also: https://github.com/mesonbuild/meson/issues/1542
This commit is contained in:
parent
b3f74b9c3a
commit
a00433fdbc
|
@ -1665,7 +1665,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', 'install_dir', 'capture', 'install', 'format'},
|
||||
'configure_file': {'input', 'output', 'configuration', 'command', 'copy', 'install_dir', 'capture', 'install', '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'},
|
||||
'declare_dependency': {'include_directories', 'link_with', 'sources', 'dependencies', 'compile_args', 'link_args', 'link_whole', 'version'},
|
||||
|
@ -3126,10 +3126,19 @@ root and issuing %s.
|
|||
raise InterpreterException("configure_file takes only keyword arguments.")
|
||||
if 'output' not in kwargs:
|
||||
raise InterpreterException('Required keyword argument "output" not defined.')
|
||||
if 'configuration' in kwargs and 'command' in kwargs:
|
||||
raise InterpreterException('Must not specify both "configuration" '
|
||||
'and "command" keyword arguments since '
|
||||
'they are mutually exclusive.')
|
||||
actions = set(['configuration', 'command', 'copy']).intersection(kwargs.keys())
|
||||
if len(actions) == 0:
|
||||
raise InterpreterException('Must specify an action with one of these '
|
||||
'keyword arguments: \'configuration\', '
|
||||
'\'command\', or \'copy\'.')
|
||||
elif len(actions) == 2:
|
||||
raise InterpreterException('Must not specify both {!r} and {!r} '
|
||||
'keyword arguments since they are '
|
||||
'mutually exclusive.'.format(*actions))
|
||||
elif len(actions) == 3:
|
||||
raise InterpreterException('Must specify one of {!r}, {!r}, and '
|
||||
'{!r} keyword arguments since they are '
|
||||
'mutually exclusive.'.format(*actions))
|
||||
if 'capture' in kwargs:
|
||||
if not isinstance(kwargs['capture'], bool):
|
||||
raise InterpreterException('"capture" keyword must be a boolean.')
|
||||
|
@ -3177,6 +3186,20 @@ root and issuing %s.
|
|||
raise InterpreterException('Output file name must not contain a subdirectory.')
|
||||
(ofile_path, ofile_fname) = os.path.split(os.path.join(self.subdir, output))
|
||||
ofile_abs = os.path.join(self.environment.build_dir, ofile_path, ofile_fname)
|
||||
# Optimize copies by not doing substitution if there's nothing to
|
||||
# substitute, and warn about this legacy hack
|
||||
if 'configuration' in kwargs:
|
||||
conf = kwargs['configuration']
|
||||
if not isinstance(conf, ConfigurationDataHolder):
|
||||
raise InterpreterException('Argument "configuration" must be of type configuration_data')
|
||||
if ifile_abs and not conf.keys():
|
||||
del kwargs['configuration']
|
||||
kwargs['copy'] = True
|
||||
mlog.warning('Got an empty configuration_data() object: '
|
||||
'optimizing copy automatically; if you want to '
|
||||
'copy a file to the build dir, use the \'copy:\' '
|
||||
'keyword argument added in 0.46.0', location=node)
|
||||
# Perform the appropriate action
|
||||
if 'configuration' in kwargs:
|
||||
conf = kwargs['configuration']
|
||||
if not isinstance(conf, ConfigurationDataHolder):
|
||||
|
@ -3217,8 +3240,13 @@ root and issuing %s.
|
|||
if ifile_abs:
|
||||
shutil.copymode(ifile_abs, dst_tmp)
|
||||
mesonlib.replace_if_different(ofile_abs, dst_tmp)
|
||||
elif 'copy' in kwargs:
|
||||
os.makedirs(os.path.join(self.environment.build_dir, self.subdir), exist_ok=True)
|
||||
shutil.copyfile(ifile_abs, ofile_abs)
|
||||
shutil.copymode(ifile_abs, ofile_abs)
|
||||
else:
|
||||
raise InterpreterException('Configure_file must have either "configuration" or "command".')
|
||||
# Not reachable
|
||||
raise AssertionError
|
||||
# If the input is a source file, add it to the list of files that we
|
||||
# need to reconfigure on when they change. FIXME: Do the same for
|
||||
# files() objects in the command: kwarg.
|
||||
|
|
|
@ -1827,7 +1827,7 @@ int main(int argc, char **argv) {
|
|||
r'meson.build:6: WARNING: a warning of some sort',
|
||||
r'sub' + os.path.sep + r'meson.build:4: WARNING: subdir warning',
|
||||
r'meson.build:7: WARNING: Module unstable-simd has no backwards or forwards compatibility and might not exist in future releases.',
|
||||
r"meson.build:10: WARNING: The variable(s) 'MISSING' in the input file conf.in are not present in the given configuration data.",
|
||||
r"meson.build:11: WARNING: The variable(s) 'MISSING' in the input file conf.in are not present in the given configuration data.",
|
||||
r'meson.build:1: WARNING: Passed invalid keyword argument "invalid".',
|
||||
]:
|
||||
self.assertRegex(out, re.escape(expected))
|
||||
|
|
|
@ -4,8 +4,8 @@ subdir('subdir')
|
|||
|
||||
configure_file(input : 'subdir/someinput.in',
|
||||
output : 'outputhere',
|
||||
configuration : configuration_data())
|
||||
copy: true)
|
||||
|
||||
configure_file(input : cfile1,
|
||||
output : '@BASENAME@',
|
||||
configuration : configuration_data())
|
||||
copy: true)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
configure_file(input : 'someinput.in',
|
||||
output : 'outputsubdir',
|
||||
install : false,
|
||||
configuration : configuration_data())
|
||||
copy: true)
|
||||
|
||||
py3 = import('python3').find_python()
|
||||
|
||||
|
|
|
@ -3,4 +3,12 @@
|
|||
import os
|
||||
import sys
|
||||
|
||||
assert(os.path.exists(sys.argv[1]))
|
||||
if len(sys.argv) == 2:
|
||||
assert(os.path.exists(sys.argv[1]))
|
||||
elif len(sys.argv) == 3:
|
||||
f1 = open(sys.argv[1], 'rb').read()
|
||||
f2 = open(sys.argv[2], 'rb').read()
|
||||
if f1 != f2:
|
||||
raise RuntimeError('{!r} != {!r}'.format(f1, f2))
|
||||
else:
|
||||
raise AssertionError
|
||||
|
|
Binary file not shown.
|
@ -35,21 +35,27 @@ 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',
|
||||
outf = configure_file(input : 'dummy.dat',
|
||||
output : 'config2.h',
|
||||
command : [genprog, scriptfile, ifile, ofile],
|
||||
install_dir : 'share/appdir')
|
||||
run_command(check_file, join_paths(meson.current_build_dir(), 'config2.h'))
|
||||
ret = run_command(check_file, outf)
|
||||
if ret.returncode() != 0
|
||||
error('Error running command: @0@\n@1@'.format(ret.stdout(), ret.stderr()))
|
||||
endif
|
||||
|
||||
# Same again as before, but an input file should not be required in
|
||||
# this case where we use a command/script to generate the output file.
|
||||
genscript2b = '@0@/generator-without-input-file.py'.format(meson.current_source_dir())
|
||||
ofile2b = '@0@/config2b.h'.format(meson.current_build_dir())
|
||||
configure_file(
|
||||
outf = configure_file(
|
||||
output : 'config2b.h',
|
||||
command : [genprog, genscript2b, ofile2b],
|
||||
install_dir : 'share/appdir')
|
||||
run_command(check_file, join_paths(meson.current_build_dir(), 'config2b.h'))
|
||||
ret = run_command(check_file, outf)
|
||||
if ret.returncode() != 0
|
||||
error('Error running command: @0@\n@1@'.format(ret.stdout(), ret.stderr()))
|
||||
endif
|
||||
|
||||
found_script = find_program('generator.py')
|
||||
# More configure_file tests in here
|
||||
|
@ -149,3 +155,22 @@ configure_file(
|
|||
configuration : conf7
|
||||
)
|
||||
test('test7', executable('prog7', 'prog7.c'))
|
||||
|
||||
# Test empty configuration data object on invalid utf8 file
|
||||
inf = 'invalid-utf8.bin.in'
|
||||
outf = configure_file(input : inf,
|
||||
output : 'invalid-utf8.bin',
|
||||
configuration : configuration_data())
|
||||
ret = run_command(check_file, inf, outf)
|
||||
if ret.returncode() != 0
|
||||
error('Error running command: @0@\n@1@'.format(ret.stdout(), ret.stderr()))
|
||||
endif
|
||||
|
||||
# Test copy of a binary file
|
||||
outf = configure_file(input : inf,
|
||||
output : 'somebinary.bin',
|
||||
copy : true)
|
||||
ret = run_command(check_file, inf, outf)
|
||||
if ret.returncode() != 0
|
||||
error('Error running command: @0@\n@1@'.format(ret.stdout(), ret.stderr()))
|
||||
endif
|
||||
|
|
|
@ -3,6 +3,6 @@
|
|||
# because there is no structure in the build dir.
|
||||
genlib = configure_file(input : '../lib.c',
|
||||
output : 'genlib.c',
|
||||
configuration : configuration_data())
|
||||
copy: true)
|
||||
shared_library('genlib', genlib,
|
||||
install : false)
|
||||
|
|
|
@ -12,7 +12,7 @@ endif
|
|||
|
||||
compiler = configure_file(input : 'mycompiler.py',
|
||||
output : 'mycompiler2.py',
|
||||
configuration : configuration_data())
|
||||
copy: true)
|
||||
|
||||
custom_target('thing2',
|
||||
output : 'final2.dat',
|
||||
|
|
|
@ -2,4 +2,4 @@ project('outdir path', 'c')
|
|||
|
||||
configure_file(input : 'foo.in',
|
||||
output : 'subdir/foo',
|
||||
configuration : configuration_data())
|
||||
copy: true)
|
||||
|
|
|
@ -7,4 +7,5 @@ warning('a warning of some sort')
|
|||
import('unstable-simd')
|
||||
|
||||
conf_data = configuration_data()
|
||||
conf_data.set('NOTMISSING', 1)
|
||||
configure_file(input: 'conf.in' , output: 'conf', configuration: conf_data)
|
||||
|
|
Loading…
Reference in New Issue