interpreter: Allow install_script to use additional input types

This adds support for Files, CustomTarget, Indexs of CustomTargets,
ConfigureFiles, ExternalPrograms, and Executables.

Fixes: #1234
Fixes: #3552
Fixes: #6175
pull/7060/head
Dylan Baker 5 years ago
parent cd566d2bd5
commit 2c0eaf5c4f
  1. 70
      mesonbuild/interpreter.py
  2. 19
      test cases/common/56 install script/customtarget.py
  3. 26
      test cases/common/56 install script/meson.build
  4. 29
      test cases/common/56 install script/myinstall.py
  5. 0
      test cases/common/56 install script/src/a file.txt
  6. 24
      test cases/common/56 install script/src/exe.c
  7. 4
      test cases/common/56 install script/src/meson.build
  8. 4
      test cases/common/56 install script/src/myinstall.py
  9. 10
      test cases/common/56 install script/test.json
  10. 6
      test cases/common/56 install script/wrap.py

@ -1893,31 +1893,79 @@ class MesonMain(InterpreterObject):
'backend': self.backend_method,
})
def _find_source_script(self, name, args):
def _find_source_script(self, prog: T.Union[str, ExecutableHolder], args):
if isinstance(prog, ExecutableHolder):
prog_path = self.interpreter.backend.get_target_filename(prog.held_object)
return build.RunScript([prog_path], args)
elif isinstance(prog, ExternalProgramHolder):
return build.RunScript(prog.get_command(), args)
# Prefer scripts in the current source directory
search_dir = os.path.join(self.interpreter.environment.source_dir,
self.interpreter.subdir)
key = (name, search_dir)
key = (prog, search_dir)
if key in self._found_source_scripts:
found = self._found_source_scripts[key]
else:
found = dependencies.ExternalProgram(name, search_dir=search_dir)
found = dependencies.ExternalProgram(prog, search_dir=search_dir)
if found.found():
self._found_source_scripts[key] = found
else:
m = 'Script or command {!r} not found or not executable'
raise InterpreterException(m.format(name))
raise InterpreterException(m.format(prog))
return build.RunScript(found.get_command(), args)
@permittedKwargs({})
def add_install_script_method(self, args, kwargs):
def _process_script_args(
self, name: str, args: T.List[T.Union[
str, mesonlib.File, CustomTargetHolder,
CustomTargetIndexHolder, ConfigureFileHolder,
ExternalProgramHolder, ExecutableHolder,
]]) -> T.List[str]:
script_args = [] # T.List[str]
new = False
for a in args:
a = unholder(a)
if isinstance(a, str):
script_args.append(a)
elif isinstance(a, mesonlib.File):
new = True
script_args.append(a.rel_to_builddir(self.interpreter.environment.source_dir))
elif isinstance(a, (build.BuildTarget, build.CustomTarget, build.CustomTargetIndex)):
new = True
script_args.extend([os.path.join(a.get_subdir(), o) for o in a.get_outputs()])
# This feels really hacky, but I'm not sure how else to fix
# this without completely rewriting install script handling.
# This is complicated by the fact that the install target
# depends on all.
if isinstance(a, build.CustomTargetIndex):
a.target.build_by_default = True
else:
a.build_by_default = True
elif isinstance(a, build.ConfigureFile):
new = True
script_args.append(os.path.join(a.subdir, a.targetname))
elif isinstance(a, dependencies.ExternalProgram):
script_args.extend(a.command)
new = True
else:
raise InterpreterException(
'Arguments to {} must be strings, Files, CustomTargets, '
'Indexes of CustomTargets, or ConfigureFiles'.format(name))
if new:
FeatureNew('Calling "{}" with File, CustomTaget, Index of CustomTarget, ConfigureFile, Executable, or ExternalProgram'.format(name), '0.55.0').use(
self.interpreter.subproject)
return script_args
@permittedKwargs(set())
def add_install_script_method(self, args: 'T.Tuple[T.Union[str, ExecutableHolder], T.Union[str, mesonlib.File, CustomTargetHolder, CustomTargetIndexHolder, ConfigureFileHolder], ...]', kwargs):
if len(args) < 1:
raise InterpreterException('add_install_script takes one or more arguments')
check_stringlist(args, 'add_install_script args must be strings')
script = self._find_source_script(args[0], args[1:])
script_args = self._process_script_args('add_install_script', args[1:])
script = self._find_source_script(args[0], script_args)
self.build.install_scripts.append(script)
@permittedKwargs({})
@permittedKwargs(set())
def add_postconf_script_method(self, args, kwargs):
if len(args) < 1:
raise InterpreterException('add_postconf_script takes one or more arguments')
@ -1925,13 +1973,13 @@ class MesonMain(InterpreterObject):
script = self._find_source_script(args[0], args[1:])
self.build.postconf_scripts.append(script)
@permittedKwargs({})
@permittedKwargs(set())
def add_dist_script_method(self, args, kwargs):
if len(args) < 1:
raise InterpreterException('add_dist_script takes one or more arguments')
if len(args) > 1:
FeatureNew('Calling "add_dist_script" with multiple arguments', '0.49.0').use(self.interpreter.subproject)
check_stringlist(args, 'add_dist_script argument must be a string')
check_stringlist(args, 'add_dist_script argumetn must be a string')
if self.interpreter.subproject != '':
raise InterpreterException('add_dist_script may not be used in a subproject.')
script = self._find_source_script(args[0], args[1:])

@ -0,0 +1,19 @@
#!/usr/bin/env python3
import argparse
import os
def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument('dirname')
args = parser.parse_args()
with open(os.path.join(args.dirname, '1.txt'), 'w') as f:
f.write('')
with open(os.path.join(args.dirname, '2.txt'), 'w') as f:
f.write('')
if __name__ == "__main__":
main()

@ -5,3 +5,29 @@ meson.add_install_script('myinstall.py', 'diiba/daaba', 'file.dat')
meson.add_install_script('myinstall.py', 'this/should', 'also-work.dat')
subdir('src')
meson.add_install_script('myinstall.py', 'dir', afile, '--mode=copy')
data = configuration_data()
data.set10('foo', true)
conf = configure_file(
configuration : data,
output : 'conf.txt'
)
meson.add_install_script('myinstall.py', 'dir', conf, '--mode=copy')
t = custom_target(
'ct',
command : [find_program('customtarget.py'), '@OUTDIR@'],
output : ['1.txt', '2.txt'],
)
meson.add_install_script('myinstall.py', 'customtarget', t, '--mode=copy')
meson.add_install_script('myinstall.py', 'customtargetindex', t[0], '--mode=copy')
meson.add_install_script(exe, 'generated.txt')
wrap = find_program('wrap.py')
# Yes, these are getting silly
meson.add_install_script(wrap, exe, 'wrapped.txt')
meson.add_install_script(wrap, wrap, exe, 'wrapped2.txt')

@ -1,12 +1,31 @@
#!/usr/bin/env python3
import argparse
import os
import sys
import shutil
prefix = os.environ['MESON_INSTALL_DESTDIR_PREFIX']
dirname = os.path.join(prefix, sys.argv[1])
os.makedirs(dirname)
with open(os.path.join(dirname, sys.argv[2]), 'w') as f:
f.write('')
def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument('dirname')
parser.add_argument('files', nargs='+')
parser.add_argument('--mode', action='store', default='create', choices=['create', 'copy'])
args = parser.parse_args()
dirname = os.path.join(prefix, args.dirname)
if not os.path.exists(dirname):
os.makedirs(dirname)
if args.mode == 'create':
for name in args.files:
with open(os.path.join(dirname, name), 'w') as f:
f.write('')
else:
for name in args.files:
shutil.copy(name, dirname)
if __name__ == "__main__":
main()

@ -0,0 +1,24 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char * argv[]) {
if (argc != 2) {
fprintf(stderr, "Takes exactly 2 arguments\n");
return 1;
}
char * dirname = getenv("MESON_INSTALL_DESTDIR_PREFIX");
char * fullname = malloc(strlen(dirname) + 1 + strlen(argv[1]) + 1);
strcpy(fullname, dirname);
strcat(fullname, "/");
strcat(fullname, argv[1]);
FILE * fp = fopen(fullname, "w");
fputs("Some text\n", fp);
fclose(fp);
free(fullname);
return 0;
}

@ -1 +1,5 @@
meson.add_install_script('myinstall.py', 'this/does', 'something-different.dat')
afile = files('a file.txt')
exe = executable('exe', 'exe.c', install : false, native : true)

@ -7,6 +7,8 @@ prefix = os.environ['MESON_INSTALL_DESTDIR_PREFIX']
dirname = os.path.join(prefix, sys.argv[1])
os.makedirs(dirname)
if not os.path.exists(dirname):
os.makedirs(dirname)
with open(os.path.join(dirname, sys.argv[2] + '.in'), 'w') as f:
f.write('')

@ -4,6 +4,14 @@
{"type": "pdb", "file": "usr/bin/prog"},
{"type": "file", "file": "usr/diiba/daaba/file.dat"},
{"type": "file", "file": "usr/this/should/also-work.dat"},
{"type": "file", "file": "usr/this/does/something-different.dat.in"}
{"type": "file", "file": "usr/this/does/something-different.dat.in"},
{"type": "file", "file": "usr/dir/a file.txt"},
{"type": "file", "file": "usr/dir/conf.txt"},
{"type": "file", "file": "usr/customtarget/1.txt"},
{"type": "file", "file": "usr/customtarget/2.txt"},
{"type": "file", "file": "usr/customtargetindex/1.txt"},
{"type": "file", "file": "usr/generated.txt"},
{"type": "file", "file": "usr/wrapped.txt"},
{"type": "file", "file": "usr/wrapped2.txt"}
]
}

@ -0,0 +1,6 @@
#!/usr/bin/env python3
import subprocess
import sys
subprocess.run(sys.argv[1:])
Loading…
Cancel
Save