Merge pull request #7060 from dcbaker/install-script-targets

Allow meson.add_*_script to take additional types
pull/6524/merge
Jussi Pakkanen 5 years ago committed by GitHub
commit 9a6e79dc68
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 7
      docs/markdown/Reference-manual.md
  2. 24
      docs/markdown/snippets/add_foo_script_type_additions.md
  3. 78
      mesonbuild/interpreter.py
  4. 7
      test cases/common/104 postconf with args/meson.build
  5. 19
      test cases/common/56 install script/customtarget.py
  6. 26
      test cases/common/56 install script/meson.build
  7. 29
      test cases/common/56 install script/myinstall.py
  8. 0
      test cases/common/56 install script/src/a file.txt
  9. 24
      test cases/common/56 install script/src/exe.c
  10. 4
      test cases/common/56 install script/src/meson.build
  11. 4
      test cases/common/56 install script/src/myinstall.py
  12. 10
      test cases/common/56 install script/test.json
  13. 6
      test cases/common/56 install script/wrap.py
  14. 1
      test cases/unit/35 dist script/meson.build

@ -1739,6 +1739,8 @@ the following methods.
0.49.0, the function only accepted a single argument. Since 0.54.0
the `MESON_SOURCE_ROOT` and `MESON_BUILD_ROOT` environment variables
are set when dist scripts are run.
*(Since 0.55.0)* The output of `configure_file`, `files`, and `find_program`
as well as strings.
- `add_install_script(script_name, arg1, arg2, ...)` causes the script
given as an argument to be run during the install step, this script
@ -1746,6 +1748,9 @@ the following methods.
`MESON_BUILD_ROOT`, `MESON_INSTALL_PREFIX`,
`MESON_INSTALL_DESTDIR_PREFIX`, and `MESONINTROSPECT` set.
All positional arguments are passed as parameters.
*(Since 0.55.0)* The output of `configure_file`, `files`, `find_program`,
`custom_target`, indexes of `custom_target`, `executable`, `library`, and
other built targets as well as strings.
*(added 0.54)* If `meson install` is called with the `--quiet` option, the
environment variable `MESON_INSTALL_QUIET` will be set.
@ -1776,6 +1781,8 @@ the following methods.
executable given as an argument after all project files have been
generated. This script will have the environment variables
`MESON_SOURCE_ROOT` and `MESON_BUILD_ROOT` set.
*(Since 0.55.0)* The output of `configure_file`, `files`, and `find_program`
as well as strings.
- `backend()` *(added 0.37.0)* returns a string representing the
current backend: `ninja`, `vs2010`, `vs2015`, `vs2017`, `vs2019`,

@ -0,0 +1,24 @@
## meson.add_*_script methods accept new types
All three (`add_install_script`, `add_dist_script`, and
`add_postconf_script`) now accept ExternalPrograms (as returned by
`find_program`), Files, and the output of `configure_file`. The dist and
postconf methods cannot accept other types because of when they are run.
While dist could, in theory, take other dependencies, it would require more
extensive changes, particularly to the backend.
```meson
meson.add_install_script(find_program('foo'), files('bar'))
meson.add_dist_script(find_program('foo'), files('bar'))
meson.add_postconf_script(find_program('foo'), files('bar'))
```
The install script variant is also able to accept custom_targets,
custom_target indexes, and build targets (executables, libraries), and can
use built executables a the script to run
```meson
installer = executable('installer', ...)
meson.add_install_script(installer, ...)
meson.add_install_script('foo.py', installer)
```

@ -1893,48 +1893,98 @@ 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,
]], allow_built: bool = False) -> 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)):
if not allow_built:
raise InterpreterException('Arguments to {} cannot be built'.format(name))
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:], allow_built=True)
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')
check_stringlist(args, 'add_postconf_script arguments must be strings')
script = self._find_source_script(args[0], args[1:])
script_args = self._process_script_args('add_postconf_script', args[1:], allow_built=True)
script = self._find_source_script(args[0], script_args)
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')
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:])
script_args = self._process_script_args('add_dist_script', args[1:], allow_built=True)
script = self._find_source_script(args[0], script_args)
self.build.dist_scripts.append(script)
@noPosargs

@ -1,5 +1,10 @@
project('postconf script', 'c')
meson.add_postconf_script('postconf.py', '5', '33')
conf = configure_file(
configuration : configuration_data(),
output : 'out'
)
meson.add_postconf_script(find_program('postconf.py'), '5', '33', conf)
test('post', executable('prog', 'prog.c'))

@ -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:])

@ -5,3 +5,4 @@ exe = executable('comparer', 'prog.c')
test('compare', exe)
meson.add_dist_script('replacer.py', '"incorrect"', '"correct"')
meson.add_dist_script(find_program('replacer.py'), '"incorrect"', '"correct"')

Loading…
Cancel
Save