diff options
author | Dylan Baker <dylan@pnwbakers.com> | 2020-04-16 21:42:38 -0700 |
---|---|---|
committer | Dylan Baker <dylan@pnwbakers.com> | 2020-04-30 10:01:14 -0700 |
commit | 2c0eaf5c4f4493146355eeb8521c17a3c2ef5acd (patch) | |
tree | d77467eafcd7ff4432cd65fa204369809a29476b | |
parent | cd566d2bd5f2f1faa3576b51b6b47c74a7ed0392 (diff) | |
download | meson-2c0eaf5c4f4493146355eeb8521c17a3c2ef5acd.zip meson-2c0eaf5c4f4493146355eeb8521c17a3c2ef5acd.tar.gz meson-2c0eaf5c4f4493146355eeb8521c17a3c2ef5acd.tar.bz2 |
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
-rw-r--r-- | mesonbuild/interpreter.py | 70 | ||||
-rwxr-xr-x | test cases/common/56 install script/customtarget.py | 19 | ||||
-rw-r--r-- | test cases/common/56 install script/meson.build | 26 | ||||
-rw-r--r-- | test cases/common/56 install script/myinstall.py | 29 | ||||
-rw-r--r-- | test cases/common/56 install script/src/a file.txt | 0 | ||||
-rw-r--r-- | test cases/common/56 install script/src/exe.c | 24 | ||||
-rw-r--r-- | test cases/common/56 install script/src/meson.build | 4 | ||||
-rw-r--r-- | test cases/common/56 install script/src/myinstall.py | 4 | ||||
-rw-r--r-- | test cases/common/56 install script/test.json | 10 | ||||
-rwxr-xr-x | test cases/common/56 install script/wrap.py | 6 |
10 files changed, 174 insertions, 18 deletions
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index dd1e57b..2b699f8 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.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:]) diff --git a/test cases/common/56 install script/customtarget.py b/test cases/common/56 install script/customtarget.py new file mode 100755 index 0000000..e28373a --- /dev/null +++ b/test cases/common/56 install script/customtarget.py @@ -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() diff --git a/test cases/common/56 install script/meson.build b/test cases/common/56 install script/meson.build index 6351518..e80e666 100644 --- a/test cases/common/56 install script/meson.build +++ b/test cases/common/56 install script/meson.build @@ -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') diff --git a/test cases/common/56 install script/myinstall.py b/test cases/common/56 install script/myinstall.py index 812561e..a573342 100644 --- a/test cases/common/56 install script/myinstall.py +++ b/test cases/common/56 install script/myinstall.py @@ -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() diff --git a/test cases/common/56 install script/src/a file.txt b/test cases/common/56 install script/src/a file.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test cases/common/56 install script/src/a file.txt diff --git a/test cases/common/56 install script/src/exe.c b/test cases/common/56 install script/src/exe.c new file mode 100644 index 0000000..b573b91 --- /dev/null +++ b/test cases/common/56 install script/src/exe.c @@ -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; +} diff --git a/test cases/common/56 install script/src/meson.build b/test cases/common/56 install script/src/meson.build index b23574a..1db424f 100644 --- a/test cases/common/56 install script/src/meson.build +++ b/test cases/common/56 install script/src/meson.build @@ -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) diff --git a/test cases/common/56 install script/src/myinstall.py b/test cases/common/56 install script/src/myinstall.py index 3b7ce37..3a9d89b 100644 --- a/test cases/common/56 install script/src/myinstall.py +++ b/test cases/common/56 install script/src/myinstall.py @@ -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('') diff --git a/test cases/common/56 install script/test.json b/test cases/common/56 install script/test.json index d17625f..b2a5971 100644 --- a/test cases/common/56 install script/test.json +++ b/test cases/common/56 install script/test.json @@ -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"} ] } diff --git a/test cases/common/56 install script/wrap.py b/test cases/common/56 install script/wrap.py new file mode 100755 index 0000000..87508e0 --- /dev/null +++ b/test cases/common/56 install script/wrap.py @@ -0,0 +1,6 @@ +#!/usr/bin/env python3 + +import subprocess +import sys + +subprocess.run(sys.argv[1:]) |