diff options
author | Xavier Claessens <xavier.claessens@collabora.com> | 2019-12-05 13:45:16 -0500 |
---|---|---|
committer | Jussi Pakkanen <jpakkane@gmail.com> | 2019-12-08 20:21:43 +0200 |
commit | 1298f71b1cf48d34627b6483f65b24d81c4d2460 (patch) | |
tree | 3a1b1ac3ec8b4d7376c363dd29a9d85d3580f3d0 | |
parent | f7d54c96c155baae311567e247ae116887d900db (diff) | |
download | meson-1298f71b1cf48d34627b6483f65b24d81c4d2460.zip meson-1298f71b1cf48d34627b6483f65b24d81c4d2460.tar.gz meson-1298f71b1cf48d34627b6483f65b24d81c4d2460.tar.bz2 |
dist: Add --include-subprojects option
-rw-r--r-- | docs/markdown/snippets/dist_subprojects.md | 6 | ||||
-rw-r--r-- | mesonbuild/mdist.py | 44 | ||||
-rwxr-xr-x | run_unittests.py | 39 |
3 files changed, 79 insertions, 10 deletions
diff --git a/docs/markdown/snippets/dist_subprojects.md b/docs/markdown/snippets/dist_subprojects.md new file mode 100644 index 0000000..cdfa070 --- /dev/null +++ b/docs/markdown/snippets/dist_subprojects.md @@ -0,0 +1,6 @@ +## meson dist --include-subprojects + +`meson dist` command line now gained `--include-subprojects` command line option. +When enabled, the source tree of all subprojects used by the current build will +also be included in the final tarball. This is useful to distribute self contained +tarball that can be built offline (i.e. `--wrap-mode=nodownload`). diff --git a/mesonbuild/mdist.py b/mesonbuild/mdist.py index 28e2fce..5a61a6a 100644 --- a/mesonbuild/mdist.py +++ b/mesonbuild/mdist.py @@ -36,6 +36,8 @@ def add_arguments(parser): help='directory to cd into before running') parser.add_argument('--formats', default='xztar', help='Comma separated list of archive types to create.') + parser.add_argument('--include-subprojects', action='store_true', + help='Include source code of subprojects that have been used for the build.') def create_hash(fname): @@ -87,22 +89,37 @@ def run_dist_scripts(dist_root, dist_scripts): print('Failed to run dist script {!r}'.format(name)) sys.exit(1) +def is_git(src_root): + _git = os.path.join(src_root, '.git') + return os.path.isdir(_git) or os.path.isfile(_git) def git_have_dirty_index(src_root): '''Check whether there are uncommitted changes in git''' ret = subprocess.call(['git', '-C', src_root, 'diff-index', '--quiet', 'HEAD']) return ret == 1 -def create_dist_git(dist_name, archives, src_root, bld_root, dist_sub, dist_scripts): +def git_clone(src_root, distdir): if git_have_dirty_index(src_root): mlog.warning('Repository has uncommitted changes that will not be included in the dist tarball') - distdir = os.path.join(dist_sub, dist_name) if os.path.exists(distdir): shutil.rmtree(distdir) os.makedirs(distdir) subprocess.check_call(['git', 'clone', '--shared', src_root, distdir]) process_submodules(distdir) del_gitfiles(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: + sub_src_root = os.path.join(src_root, path) + sub_distdir = os.path.join(distdir, path) + if os.path.exists(sub_distdir): + continue + if is_git(sub_src_root): + git_clone(sub_src_root, sub_distdir) + else: + shutil.copytree(sub_src_root, sub_distdir) run_dist_scripts(distdir, dist_scripts) output_names = [] for a in archives: @@ -112,6 +129,8 @@ def create_dist_git(dist_name, archives, src_root, bld_root, dist_sub, dist_scri shutil.rmtree(distdir) return output_names +def is_hg(src_root): + return os.path.isdir(os.path.join(src_root, '.hg')) def hg_have_dirty_index(src_root): '''Check whether there are uncommitted changes in hg''' @@ -147,7 +166,7 @@ def create_dist_hg(dist_name, archives, src_root, bld_root, dist_sub, dist_scrip return output_names -def check_dist(packagename, meson_command, bld_root, privdir): +def check_dist(packagename, meson_command, extra_meson_args, bld_root, privdir): print('Testing distribution package %s' % packagename) unpackdir = os.path.join(privdir, 'dist-unpack') builddir = os.path.join(privdir, 'dist-build') @@ -165,6 +184,7 @@ def check_dist(packagename, meson_command, bld_root, privdir): with open(os.path.join(bld_root, 'meson-info', 'intro-buildoptions.json')) as boptions: meson_command += ['-D{name}={value}'.format(**o) for o in json.load(boptions) if o['name'] not in ['backend', 'install_umask']] + meson_command += extra_meson_args if subprocess.call(meson_command + ['--backend=ninja', unpacked_src_dir, builddir]) != 0: print('Running Meson on distribution package failed') return 1 @@ -214,10 +234,18 @@ def run(options): archives = determine_archives_to_generate(options) - _git = os.path.join(src_root, '.git') - if os.path.isdir(_git) or os.path.isfile(_git): - names = create_dist_git(dist_name, archives, src_root, bld_root, dist_sub, b.dist_scripts) - elif os.path.isdir(os.path.join(src_root, '.hg')): + subprojects = [] + extra_meson_args = [] + if options.include_subprojects: + subprojects = [os.path.join(b.subproject_dir, sub) for sub in b.subprojects] + extra_meson_args.append('-Dwrap_mode=nodownload') + + if is_git(src_root): + names = create_dist_git(dist_name, archives, src_root, bld_root, dist_sub, b.dist_scripts, subprojects) + elif is_hg(src_root): + if subprojects: + print('--include-subprojects option currently not supported with Mercurial') + return 1 names = create_dist_hg(dist_name, archives, src_root, bld_root, dist_sub, b.dist_scripts) else: print('Dist currently only works with Git or Mercurial repos') @@ -225,7 +253,7 @@ def run(options): if names is None: return 1 # Check only one. - rc = check_dist(names[0], meson_command, bld_root, priv_dir) + rc = check_dist(names[0], meson_command, extra_meson_args, bld_root, priv_dir) if rc == 0: for name in names: create_hash(name) diff --git a/run_unittests.py b/run_unittests.py index 4260256..ec270d7 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -31,6 +31,7 @@ import operator import threading import urllib.error import urllib.request +import zipfile from itertools import chain from unittest import mock from configparser import ConfigParser @@ -2546,7 +2547,7 @@ class AllPlatformTests(BasePlatformTests): subprocess.check_call(['hg', 'commit', '-m', 'I am a project'], cwd=project_dir) try: - self.dist_impl(hg_init) + self.dist_impl(hg_init, include_subprojects=False) except PermissionError: # When run under Windows CI, something (virus scanner?) # holds on to the hg files so cleaning up the dir @@ -2573,7 +2574,14 @@ class AllPlatformTests(BasePlatformTests): # fails sometimes. pass - def dist_impl(self, vcs_init): + def create_dummy_subproject(self, project_dir, name): + path = os.path.join(project_dir, 'subprojects', name) + os.makedirs(path) + with open(os.path.join(path, 'meson.build'), 'w') as ofile: + ofile.write("project('{}')".format(name)) + return path + + def dist_impl(self, vcs_init, include_subprojects=True): # Create this on the fly because having rogue .git directories inside # the source tree leads to all kinds of trouble. with tempfile.TemporaryDirectory() as project_dir: @@ -2581,6 +2589,8 @@ class AllPlatformTests(BasePlatformTests): ofile.write('''project('disttest', 'c', version : '1.4.3') e = executable('distexe', 'distexe.c') test('dist test', e) +subproject('vcssub', required : false) +subproject('tarballsub', required : false) ''') with open(os.path.join(project_dir, 'distexe.c'), 'w') as ofile: ofile.write('''#include<stdio.h> @@ -2595,6 +2605,10 @@ int main(int argc, char **argv) { zip_distfile = os.path.join(self.distdir, 'disttest-1.4.3.zip') zip_checksumfile = zip_distfile + '.sha256sum' vcs_init(project_dir) + if include_subprojects: + vcs_init(self.create_dummy_subproject(project_dir, 'vcssub')) + self.create_dummy_subproject(project_dir, 'tarballsub') + self.create_dummy_subproject(project_dir, 'unusedsub') self.init(project_dir) self.build('dist') self.assertPathExists(xz_distfile) @@ -2606,6 +2620,27 @@ int main(int argc, char **argv) { self.assertPathExists(zip_distfile) self.assertPathExists(zip_checksumfile) + if include_subprojects: + z = zipfile.ZipFile(zip_distfile) + self.assertEqual(sorted(['disttest-1.4.3/', + 'disttest-1.4.3/meson.build', + 'disttest-1.4.3/distexe.c']), + sorted(z.namelist())) + + self._run(self.meson_command + ['dist', '--formats', 'zip', '--include-subprojects'], + workdir=self.builddir) + z = zipfile.ZipFile(zip_distfile) + self.assertEqual(sorted(['disttest-1.4.3/', + 'disttest-1.4.3/subprojects/', + 'disttest-1.4.3/meson.build', + 'disttest-1.4.3/distexe.c', + 'disttest-1.4.3/subprojects/tarballsub/', + 'disttest-1.4.3/subprojects/vcssub/', + 'disttest-1.4.3/subprojects/tarballsub/meson.build', + 'disttest-1.4.3/subprojects/vcssub/meson.build']), + sorted(z.namelist())) + + def test_rpath_uses_ORIGIN(self): ''' Test that built targets use $ORIGIN in rpath, which ensures that they |