Allow add_dist_script() in subprojects

Fixes: #8440.
pull/8555/head
Xavier Claessens 4 years ago committed by Xavier Claessens
parent 848e360450
commit 3990754bf5
  1. 21
      docs/markdown/Reference-manual.md
  2. 14
      docs/markdown/snippets/dist_script.md
  3. 3
      mesonbuild/interpreter.py
  4. 16
      mesonbuild/mdist.py
  5. 4
      run_unittests.py
  6. 2
      test cases/unit/35 dist script/meson.build
  7. 12
      test cases/unit/35 dist script/subprojects/sub/dist-script.py
  8. 11
      test cases/unit/35 dist script/subprojects/sub/meson.build
  9. 1
      test cases/unit/35 dist script/subprojects/sub/meson_options.txt
  10. 1
      test cases/unit/35 dist script/subprojects/sub/prog.c

@ -1907,16 +1907,25 @@ the following methods.
archived. Note that this runs the script file that is in the
_staging_ directory, not the one in the source directory. If the
script file can not be found in the staging directory, it is a hard
error. This command can only invoked from the main project, calling
it from a subproject is a hard error. *(since 0.49.0)* Accepts multiple arguments
for the script. *(since 0.54.0)* The `MESON_SOURCE_ROOT` and `MESON_BUILD_ROOT`
environment variables are set when dist scripts are run.
error. The `MESON_DIST_ROOT` environment variables is set when dist scripts is
run.
*(since 0.49.0)* Accepts multiple arguments for the script.
*(since 0.54.0)* The `MESON_SOURCE_ROOT` and `MESON_BUILD_ROOT`
environment variables are set when dist scripts are run. They are path to the
root source and build directory of the main project, even when the script
comes from a subproject.
*(since 0.55.0)* The output of `configure_file`, `files`, and `find_program`
as well as strings.
*(since 0.57.0)* `file` objects and the output of `configure_file` may be
used as the `script_name` parameter.
*(since 0.58.0)* This command can be invoked from a subproject, it was a hard
error in earlier versions. Subproject dist scripts will only be executed
when running `meson dist --include-subprojects`. `MESON_PROJECT_SOURCE_ROOT`,
`MESON_PROJECT_BUILD_ROOT` and `MESON_PROJECT_DIST_ROOT` environment
variables are set when dist scripts are run. They are identical to
`MESON_SOURCE_ROOT`, `MESON_BUILD_ROOT` and `MESON_DIST_ROOT` for main project
scripts, but for subproject scripts they have the path to the root of the
subproject appended, usually `subprojects/<subproject-name>`.
- `add_install_script(script_name, arg1, arg2, ...)`: causes the script
given as an argument to be run during the install step, this script

@ -0,0 +1,14 @@
## `meson.add_dist_script()` allowd in subprojects
`meson.add_dist_script()` can now be invoked from a subproject, it was a hard
error in earlier versions. Subproject dist scripts will only be executed
when running `meson dist --include-subprojects`. `MESON_PROJECT_SOURCE_ROOT`,
`MESON_PROJECT_BUILD_ROOT` and `MESON_PROJECT_DIST_ROOT` environment variables
are set when dist scripts are run. They are identical to `MESON_SOURCE_ROOT`,
`MESON_BUILD_ROOT` and `MESON_DIST_ROOT` for main project scripts, but for
subproject scripts they have the path to the root of the subproject appended,
usually `subprojects/<subproject-name>`.
Note that existing dist scripts likely need to be modified to use those new
environment variables instead of `MESON_DIST_ROOT` to work properly when used
from a subproject.

@ -2028,7 +2028,8 @@ class MesonMain(InterpreterObject):
FeatureNew.single_use('Passing file object to script parameter of add_dist_script',
'0.57.0', self.interpreter.subproject)
if self.interpreter.subproject != '':
raise InterpreterException('add_dist_script may not be used in a subproject.')
FeatureNew.single_use('Calling "add_dist_script" in a subproject',
'0.58.0', self.interpreter.subproject)
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)

@ -78,13 +78,19 @@ def process_submodules(dirname):
del_gitfiles(os.path.join(dirname, v))
def run_dist_scripts(src_root, bld_root, dist_root, dist_scripts):
def run_dist_scripts(src_root, bld_root, dist_root, dist_scripts, subprojects):
assert(os.path.isabs(dist_root))
env = {}
env['MESON_DIST_ROOT'] = dist_root
env['MESON_SOURCE_ROOT'] = src_root
env['MESON_BUILD_ROOT'] = bld_root
for d in dist_scripts:
if d.subproject and d.subproject not in subprojects:
continue
subdir = subprojects.get(d.subproject, '')
env['MESON_PROJECT_DIST_ROOT'] = os.path.join(dist_root, subdir)
env['MESON_PROJECT_SOURCE_ROOT'] = os.path.join(src_root, subdir)
env['MESON_PROJECT_BUILD_ROOT'] = os.path.join(bld_root, subdir)
name = ' '.join(d.cmd_args)
print(f'Running custom dist script {name!r}')
try:
@ -141,7 +147,7 @@ def git_clone(src_root, distdir):
def create_dist_git(dist_name, archives, src_root, bld_root, dist_sub, dist_scripts, subprojects):
distdir = os.path.join(dist_sub, dist_name)
git_clone(src_root, distdir)
for path in subprojects:
for path in subprojects.values():
sub_src_root = os.path.join(src_root, path)
sub_distdir = os.path.join(distdir, path)
if os.path.exists(sub_distdir):
@ -150,7 +156,7 @@ def create_dist_git(dist_name, archives, src_root, bld_root, dist_sub, dist_scri
git_clone(sub_src_root, sub_distdir)
else:
shutil.copytree(sub_src_root, sub_distdir)
run_dist_scripts(src_root, bld_root, distdir, dist_scripts)
run_dist_scripts(src_root, bld_root, distdir, dist_scripts, subprojects)
output_names = []
for a in archives:
compressed_name = distdir + archive_extension[a]
@ -278,13 +284,13 @@ def run(options):
archives = determine_archives_to_generate(options)
subprojects = []
subprojects = {}
extra_meson_args = []
if options.include_subprojects:
subproject_dir = os.path.join(src_root, b.subproject_dir)
for sub in b.subprojects:
directory = wrap.get_directory(subproject_dir, sub)
subprojects.append(os.path.join(b.subproject_dir, directory))
subprojects[sub] = os.path.join(b.subproject_dir, directory)
extra_meson_args.append('-Dwrap_mode=nodownload')
if is_git(src_root):

@ -3189,6 +3189,10 @@ class AllPlatformTests(BasePlatformTests):
_git_init(project_dir)
self.init(project_dir)
self.build('dist')
self.new_builddir()
self.init(project_dir, extra_args=['-Dsub:broken_dist_script=false'])
self._run(self.meson_command + ['dist', '--include-subprojects'], workdir=self.builddir)
except PermissionError:
# When run under Windows CI, something (virus scanner?)
# holds on to the git files so cleaning up the dir

@ -6,3 +6,5 @@ test('compare', exe)
meson.add_dist_script('replacer.py', '"incorrect"', '"correct"')
meson.add_dist_script(find_program('replacer.py'), '"incorrect"', '"correct"')
subproject('sub')

@ -0,0 +1,12 @@
#!/usr/bin/env python3
import os
import pathlib
import sys
assert sys.argv[1] == 'success'
source_root = pathlib.Path(os.environ['MESON_PROJECT_DIST_ROOT'])
modfile = source_root / 'prog.c'
with modfile.open('w') as f:
f.write('int main(){return 0;}')

@ -0,0 +1,11 @@
project('sub')
if get_option('broken_dist_script')
# Make sure we can add a dist script in a subproject, but it won't be run
# if not using --include-subprojects.
meson.add_dist_script('dist-script.py', 'broken')
else
# The dist script replace prog.c with something that actually build.
meson.add_dist_script('dist-script.py', 'success')
executable('prog', 'prog.c')
endif

@ -0,0 +1 @@
option('broken_dist_script', type: 'boolean', value: true)

@ -0,0 +1 @@
#error This should be replaced by a program during dist
Loading…
Cancel
Save