diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index d292cd35e792da3706c1ae7476f487ec68e4b135..12e3b3b8c0b38afabe522591a63c645b66c5be96 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -38,32 +38,28 @@ build:scout:
             apt-get -y --no-install-recommends install \
             bubblewrap \
             libcapsule0 \
-            libcapsule-tools-relocatable \
+            libcapsule-tools-relocatable:amd64 \
+            libcapsule-tools-relocatable:i386 \
             libglib2.0-dev \
             libxau-dev \
             meson \
             ${NULL+}
 
-            meson \
-                --prefix="$(pwd)/_build/relocatable-install" \
-                -Dpython=python3.5 \
-                _build
+            meson --prefix="$(pwd)/_build/prefix" -Dpython=python3.5 _build
             ninja -C _build
-            ninja -C _build install
             meson test --verbose -C _build
+            ninja -C _build install
+            rm -fr _build/relocatable-install
             ./build-relocatable-install.py \
               --srcdir . \
               --builddir _build \
               --libcapsuledir /usr/lib/libcapsule/relocatable \
-              --prefix="$(pwd)/_build/relocatable-install" \
+              --output _build/relocatable-install \
               --archive "$(pwd)/_build" \
               --set-version "$(cat .tarball-version)" \
               ${NULL+}
             prove -v ./tests/relocatable-install.py :: \
-              --srcdir . \
-              --builddir _build \
-              --prefix="$(pwd)/_build/relocatable-install" \
-              ${NULL+}
+              "$(pwd)/_build/relocatable-install"
 
 # Artifacts are currently disabled because uploading them to the
 # coordinator results in HTTP 413 Request Entity Too Large.
diff --git a/README.md b/README.md
index 4e0febbe9ddd0adf782da9a9c4607318df43da65..a5d4e5891d5a666d5a5d457fdae28102ea6325e3 100644
--- a/README.md
+++ b/README.md
@@ -143,25 +143,24 @@ Building a relocatable install for deployment
 To make the built version compatible with older systems, you will need
 a SteamRT 1 'scout' environment.
 
-The most straightforward method is to have prebuilt versions of
-libcapsule-tools-relocatable:amd64, libcapsule-tools-relocatable:i386
-and bubblewrap in your build environment. For example, you could do the
-build in a SteamRT 1 'scout' SDK Docker image that has those packages
-already. Then you can do:
+For this, you need prebuilt versions of libcapsule-tools-relocatable:amd64
+and libcapsule-tools-relocatable:i386 either in your build environment
+or available via apt-get. For example, you could do the build in a
+SteamRT 1 'scout' SDK Docker image that has those packages already.
+Then you can do:
 
-    meson --prefix=$(pwd)/_build/relocatable-install _build
+    meson --prefix="$(pwd)/_build/prefix" _build
     ninja -C _build
-    rm -fr $(pwd)/_build/relocatable-install
     meson test -v -C _build             # optional
     ninja -C _build install
+    rm -fr _build/relocatable-install
     ./build-relocatable-install.py \
         --srcdir . \
         --builddir _build \
         --libcapsuledir /usr/lib/libcapsule/relocatable \
+        --output _build/relocatable-install \
         --archive .
-    ./tests/relocatable-install.py \
-        --srcdir . \
-        --builddir _build               # optional
+    ./tests/relocatable-install.py _build/relocatable-install  # optional
 
 For more convenient use on a development system, if you have a
 SteamRT 1 'scout' SDK tarball or an unpacked sysroot, you can place a
@@ -170,16 +169,15 @@ tarball at `_build/sysroot.tar.gz` or unpack a sysroot into
 `./sysroot/run-in-sysroot.py`:
 
     ./sysroot/run-in-sysroot.py apt-get update
-    ./sysroot/run-in-sysroot.py meson ...
-    rm -fr $(pwd)/_build/relocatable-install
-    ./sysroot/run-in-sysroot.py ninja ...
-    ./sysroot/run-in-sysroot.py ./build-relocatable-install.py ...
+    ./sysroot/run-in-sysroot.py meson --prefix="$(pwd)/_build/prefix" _build
+    ./sysroot/run-in-sysroot.py ninja -C _build
+    (etc.)
 
 (Or put them in different locations and pass the `--sysroot` and
 `--tarball` options to `./sysroot/run-in-sysroot.py`.)
 
-The relocatable install goes into`_build/relocatable-install` (or
-whatever you used as the `--prefix`), and a compressed version ends
+The relocatable install goes into `relocatable-install` (or
+whatever you used as the `--output`), and a compressed version ends
 up in the directory passed as an argument to `--archive`.
 
 Instructions for testing
diff --git a/build-relocatable-install.py b/build-relocatable-install.py
index 55fba701c50cbc62cbbc2de186dae2fcec9ac890..1c3a434f96c0c423fa58eb85e71fd6be3d26b5ef 100755
--- a/build-relocatable-install.py
+++ b/build-relocatable-install.py
@@ -30,6 +30,7 @@ import os
 import re
 import shutil
 import subprocess
+import tempfile
 
 try:
     import typing
@@ -141,6 +142,7 @@ def main():
     parser.add_argument(
         '--builddir', default=os.getenv('MESON_BUILD_ROOT', '_build'))
     parser.add_argument('--prefix', default=None)
+    parser.add_argument('--output', '-o', default=None)
     parser.add_argument('--archive', default=None)
     parser.add_argument('--libcapsuledir', default='')
     parser.add_argument('--set-version', dest='version', default='unknown')
@@ -171,389 +173,423 @@ def main():
                 'please specify --prefix'
             )
 
-    os.chdir(args.builddir)
-
-    destdir_prefix = args.destdir + args.prefix
+    with tempfile.TemporaryDirectory(prefix='pressure-vessel-') as tmpdir:
+        if args.output is None:
+            installation = os.path.join(tmpdir, 'installation')
+        else:
+            installation = args.output
 
-    os.makedirs(os.path.join(destdir_prefix, 'bin'), exist_ok=True)
-    os.makedirs(os.path.join(destdir_prefix, 'metadata'), exist_ok=True)
+        if os.path.exists(installation):
+            raise RuntimeError('--output directory must not already exist')
 
-    for arch in ARCHS:
-        os.makedirs(
-            os.path.join(destdir_prefix, 'lib', arch.multiarch),
-            exist_ok=True,
-        )
+        destdir_prefix = args.destdir + args.prefix
 
-    for script in SCRIPTS:
-        install_exe(
-            os.path.join(args.srcdir, script),
-            os.path.join(destdir_prefix, 'bin'),
-        )
+        os.makedirs(os.path.join(installation, 'bin'), exist_ok=True)
+        os.makedirs(os.path.join(installation, 'metadata'), exist_ok=True)
 
-    for exe in EXECUTABLES:
-        install_exe(
-            os.path.join(args.builddir, exe),
-            os.path.join(destdir_prefix, 'bin'),
-        )
+        for arch in ARCHS:
+            os.makedirs(
+                os.path.join(installation, 'lib', arch.multiarch),
+                exist_ok=True,
+            )
 
-    install(
-        os.path.join(args.srcdir, 'THIRD-PARTY.md'),
-        os.path.join(destdir_prefix, 'metadata', 'README.txt'),
-        0o644,
-    )
+        for script in SCRIPTS:
+            install_exe(
+                os.path.join(destdir_prefix, 'bin', script),
+                os.path.join(installation, 'bin'),
+            )
 
-    if args.libcapsuledir:
-        for arch in ARCHS:
-            for tool in TOOLS:
-                install_exe(
-                    os.path.join(
-                        args.libcapsuledir,
-                        '{}-{}'.format(arch.multiarch, tool),
-                    ),
-                    os.path.join(destdir_prefix, 'bin'),
-                )
+        for exe in EXECUTABLES:
+            install_exe(
+                os.path.join(destdir_prefix, 'bin', exe),
+                os.path.join(installation, 'bin'),
+            )
 
         install(
-            '/usr/share/doc/libcapsule-tools-relocatable/copyright',
-            os.path.join(destdir_prefix, 'metadata', 'libcapsule.txt'),
+            os.path.join(args.srcdir, 'THIRD-PARTY.md'),
+            os.path.join(installation, 'metadata', 'README.txt'),
+            0o644,
         )
-    else:
-        for arch in ARCHS:
-            for tool in TOOLS:
-                install_exe(
-                    os.path.join(
-                        'build-relocatable',
-                        arch.name,
-                        'libcapsule',
-                        tool,
-                    ),
-                    os.path.join(
-                        'build-relocatable',
-                        '{}-{}'.format(arch.multiarch, tool),
-                    ),
-                )
-                v_check_call([
-                    'chrpath', '-r',
-                    '${ORIGIN}/../lib/' + arch.multiarch,
-                    os.path.join(
-                        'build-relocatable',
-                        '{}-{}'.format(arch.multiarch, tool),
-                    ),
-                ])
-                install_exe(
-                    os.path.join(
-                        'build-relocatable',
-                        '{}-{}'.format(arch.multiarch, tool),
-                    ),
-                    os.path.join(destdir_prefix, 'bin'),
-                )
+
+        if args.libcapsuledir:
+            for arch in ARCHS:
+                for tool in TOOLS:
+                    install_exe(
+                        os.path.join(
+                            args.libcapsuledir,
+                            '{}-{}'.format(arch.multiarch, tool),
+                        ),
+                        os.path.join(installation, 'bin'),
+                    )
 
             install(
-                os.path.join(
-                    args.builddir,
-                    'libcapsule',
-                    'debian',
-                    'copyright',
-                ),
-                os.path.join(destdir_prefix, 'metadata', 'libcapsule.txt'),
+                '/usr/share/doc/libcapsule-tools-relocatable/copyright',
+                os.path.join(installation, 'metadata', 'libcapsule.txt'),
             )
+        else:
+            for arch in ARCHS:
+                for tool in TOOLS:
+                    install_exe(
+                        os.path.join(
+                            args.builddir,
+                            'build-relocatable',
+                            arch.name,
+                            'libcapsule',
+                            tool,
+                        ),
+                        os.path.join(
+                            tmpdir,
+                            'build-relocatable',
+                            '{}-{}'.format(arch.multiarch, tool),
+                        ),
+                    )
+                    v_check_call([
+                        'chrpath', '-r',
+                        '${ORIGIN}/../lib/' + arch.multiarch,
+                        os.path.join(
+                            tmpdir,
+                            'build-relocatable',
+                            '{}-{}'.format(arch.multiarch, tool),
+                        ),
+                    ])
+                    install_exe(
+                        os.path.join(
+                            tmpdir,
+                            'build-relocatable',
+                            '{}-{}'.format(arch.multiarch, tool),
+                        ),
+                        os.path.join(installation, 'bin'),
+                    )
 
-    primary_architecture = subprocess.check_output([
-        'dpkg', '--print-architecture',
-    ]).decode('utf-8').strip()
+                install(
+                    os.path.join(
+                        args.builddir,
+                        'libcapsule',
+                        'debian',
+                        'copyright',
+                    ),
+                    os.path.join(installation, 'metadata', 'libcapsule.txt'),
+                )
 
-    for arch in ARCHS:
-        os.makedirs(
-            os.path.join('build-relocatable', arch.name, 'lib'),
-            exist_ok=True,
-        )
+        primary_architecture = subprocess.check_output([
+            'dpkg', '--print-architecture',
+        ]).decode('utf-8').strip()
 
-        v_check_call([
-            '{}/bin/{}-capsule-capture-libs'.format(
-                destdir_prefix,
-                arch.multiarch,
-            ),
-            '--dest=build-relocatable/{}/lib'.format(arch.name),
-            '--no-glibc',
-            'soname:libelf.so.1',
-            'soname:libz.so.1',
-        ])
+        for arch in ARCHS:
+            os.makedirs(
+                os.path.join(tmpdir, 'build-relocatable', arch.name, 'lib'),
+                exist_ok=True,
+            )
 
-        if arch.name == primary_architecture:
             v_check_call([
                 '{}/bin/{}-capsule-capture-libs'.format(
-                    destdir_prefix,
+                    installation,
                     arch.multiarch,
                 ),
-                '--dest=build-relocatable/{}/lib'.format(arch.name),
+                '--dest={}/build-relocatable/{}/lib'.format(
+                    tmpdir,
+                    arch.name,
+                ),
                 '--no-glibc',
-                'soname:libXau.so.6',
-                'soname:libcap.so.2',
-                'soname:libgio-2.0.so.0',
-                'soname:libpcre.so.3',
-                'soname:libselinux.so.1',
+                'soname:libelf.so.1',
+                'soname:libz.so.1',
             ])
 
-        for so in glob.glob(
-            os.path.join('build-relocatable', arch.name, 'lib', '*.so.*'),
-        ):
-            install(so, os.path.join(destdir_prefix, 'lib', arch.multiarch))
-
-    # For bwrap (and possibly other programs in future) we don't have
-    # a relocatable version with a RPATH/RUNPATH, so we wrap a script
-    # around it instead. The script avoids setting LD_LIBRARY_PATH
-    # because that would leak through to the programs invoked by bwrap.
-    for exe, package in WRAPPED_PROGRAMS.items():
-        path = '/usr/bin/{}'.format(exe)
+            if arch.name == primary_architecture:
+                v_check_call([
+                    '{}/bin/{}-capsule-capture-libs'.format(
+                        installation,
+                        arch.multiarch,
+                    ),
+                    '--dest={}/build-relocatable/{}/lib'.format(
+                        tmpdir,
+                        arch.name,
+                    ),
+                    '--no-glibc',
+                    'soname:libXau.so.6',
+                    'soname:libcap.so.2',
+                    'soname:libgio-2.0.so.0',
+                    'soname:libpcre.so.3',
+                    'soname:libselinux.so.1',
+                ])
 
-        if not os.path.exists(path):
-            v_check_call([
-                'apt-get',
-                'download',
-                package,
-            ])
-            v_check_call(
-                'dpkg-deb -x {}_*.deb build-relocatable'.format(
-                    quote(package),
+            for so in glob.glob(
+                os.path.join(
+                    tmpdir,
+                    'build-relocatable',
+                    arch.name,
+                    'lib',
+                    '*.so.*',
                 ),
-                shell=True,
-            )
-            path = 'build-relocatable/usr/bin/{}'.format(exe)
+            ):
+                install(so, os.path.join(installation, 'lib', arch.multiarch))
 
-        for arch in ARCHS:
-            if arch.name != primary_architecture:
-                continue
+        # For bwrap (and possibly other programs in future) we don't have
+        # a relocatable version with a RPATH/RUNPATH, so we wrap a script
+        # around it instead. The script avoids setting LD_LIBRARY_PATH
+        # because that would leak through to the programs invoked by bwrap.
+        for exe, package in WRAPPED_PROGRAMS.items():
+            path = '/usr/bin/{}'.format(exe)
 
-            install_exe(
-                path,
-                os.path.join(destdir_prefix, 'bin', exe + '.bin'),
-            )
+            if not os.path.exists(path):
+                v_check_call([
+                    'apt-get',
+                    'download',
+                    package,
+                ], cwd=tmpdir)
+                v_check_call(
+                    'dpkg-deb -x {}_*.deb build-relocatable'.format(
+                        quote(package),
+                    ),
+                    cwd=tmpdir,
+                    shell=True,
+                )
+                path = '{}/build-relocatable/usr/bin/{}'.format(tmpdir, exe)
+
+            for arch in ARCHS:
+                if arch.name != primary_architecture:
+                    continue
+
+                install_exe(
+                    path,
+                    os.path.join(installation, 'bin', exe + '.bin'),
+                )
 
-            with open(
-                os.path.join('build-relocatable', arch.name, exe),
-                'w',
-            ) as writer:
-                writer.write('#!/bin/sh\n')
-                writer.write('set -eu\n')
-                writer.write('here="$(dirname "$0")"\n')
-                writer.write(
-                    'exec ${{RELOCATABLE_INSTALL_WRAPPER-}} {} '
-                    '--library-path "$here"/../lib/{} '
-                    '"$here"/{}.bin "$@"\n'.format(
-                        quote(arch.ld_so),
-                        quote(arch.multiarch),
-                        quote(exe),
+                with open(
+                    os.path.join(tmpdir, 'build-relocatable', arch.name, exe),
+                    'w',
+                ) as writer:
+                    writer.write('#!/bin/sh\n')
+                    writer.write('set -eu\n')
+                    writer.write('here="$(dirname "$0")"\n')
+                    writer.write(
+                        'exec ${{RELOCATABLE_INSTALL_WRAPPER-}} {} '
+                        '--library-path "$here"/../lib/{} '
+                        '"$here"/{}.bin "$@"\n'.format(
+                            quote(arch.ld_so),
+                            quote(arch.multiarch),
+                            quote(exe),
+                        )
                     )
+
+                install_exe(
+                    os.path.join(tmpdir, 'build-relocatable', arch.name, exe),
+                    os.path.join(installation, 'bin', exe),
                 )
 
-            install_exe(
-                os.path.join('build-relocatable', arch.name, exe),
-                os.path.join(destdir_prefix, 'bin', exe),
-            )
+        source_to_download = set()      # type: typing.Set[str]
+        installed_binaries = set()      # type: typing.Set[str]
 
-    source_to_download = set()      # type: typing.Set[str]
-    installed_binaries = set()      # type: typing.Set[str]
+        for package, source in (
+            list(DEPENDENCIES.items()) + list(PRIMARY_ARCH_DEPENDENCIES.items())
+        ):
+            if not args.libcapsuledir and source == 'libcapsule':
+                continue
 
-    for package, source in (
-        list(DEPENDENCIES.items()) + list(PRIMARY_ARCH_DEPENDENCIES.items())
-    ):
-        if not args.libcapsuledir and source == 'libcapsule':
-            continue
+            if os.path.exists('/usr/share/doc/{}/copyright'.format(package)):
+                installed_binaries.add(package)
 
-        if os.path.exists('/usr/share/doc/{}/copyright'.format(package)):
-            installed_binaries.add(package)
+                install(
+                    '/usr/share/doc/{}/copyright'.format(package),
+                    os.path.join(
+                        installation,
+                        'metadata',
+                        '{}.txt'.format(source),
+                    ),
+                )
 
-            install(
-                '/usr/share/doc/{}/copyright'.format(package),
-                os.path.join(
-                    destdir_prefix,
-                    'metadata',
-                    '{}.txt'.format(source),
-                ),
+                for expr in set(
+                    v_check_output([
+                        'dpkg-query',
+                        '-W',
+                        '-f', '${source:Package}=${source:Version}\n',
+                        package,
+                    ], universal_newlines=True).splitlines()
+                ):
+                    source_to_download.add(re.sub(r'[+]srt[0-9a-z.]+$', '', expr))
+            else:
+                install(
+                    '{}/build-relocatable/usr/share/doc/{}/copyright'.format(
+                        tmpdir,
+                        package,
+                    ),
+                    os.path.join(
+                        installation,
+                        'metadata',
+                        '{}.txt'.format(source),
+                    ),
+                )
+                source_to_download.add(source)
+
+        with open(
+            os.path.join(installation, 'metadata', 'packages.txt'), 'w'
+        ) as writer:
+            writer.write(
+                '#Package[:Architecture]\t#Version\t#Source\t#Installed-Size\n'
             )
+            v_check_call([
+                'dpkg-query',
+                '-W',
+                '-f',
+                r'${binary:Package}\t${Version}\t${Source}\t${Installed-Size}\n',
+            ] + sorted(installed_binaries), stdout=writer)
+
+        with open(
+            os.path.join(installation, 'metadata', 'VERSION.txt'),
+            'w',
+        ) as writer:
+            writer.write('{}\n'.format(args.version))
+
+        shutil.copytree(
+            os.path.join(installation, 'metadata'),
+            os.path.join(installation, 'sources'),
+        )
 
-            for expr in set(
-                v_check_output([
-                    'dpkg-query',
-                    '-W',
-                    '-f', '${source:Package}=${source:Version}\n',
-                    package,
-                ], universal_newlines=True).splitlines()
+        if not args.libcapsuledir:
+            for dsc in glob.glob(
+                os.path.join(args.srcdir, 'libcapsule*.dsc')
             ):
-                source_to_download.add(re.sub(r'[+]srt[0-9a-z.]+$', '', expr))
-        else:
-            install(
-                'build-relocatable/usr/share/doc/{}/copyright'.format(package),
-                os.path.join(
-                    destdir_prefix,
-                    'metadata',
-                    '{}.txt'.format(source),
-                ),
-            )
-            source_to_download.add(source)
+                v_check_call([
+                    'dcmd', 'install', '-m644', dsc,
+                    os.path.join(installation, 'sources'),
+                ])
 
-    with open(
-        os.path.join(destdir_prefix, 'metadata', 'packages.txt'), 'w'
-    ) as writer:
-        writer.write(
-            '#Package[:Architecture]\t#Version\t#Source\t#Installed-Size\n'
+        v_check_call(
+            [
+                'apt-get',
+                '--download-only',
+                '--only-source',
+                'source',
+            ] + list(source_to_download),
+            cwd=os.path.join(installation, 'sources'),
         )
-        v_check_call([
-            'dpkg-query',
-            '-W',
-            '-f',
-            r'${binary:Package}\t${Version}\t${Source}\t${Installed-Size}\n',
-        ] + sorted(installed_binaries), stdout=writer)
-
-    with open(
-        os.path.join(destdir_prefix, 'metadata', 'VERSION.txt'),
-        'w',
-    ) as writer:
-        writer.write('{}\n'.format(args.version))
-
-    shutil.copytree(
-        os.path.join(destdir_prefix, 'metadata'),
-        os.path.join(destdir_prefix, 'sources'),
-    )
-
-    if not args.libcapsuledir:
-        for dsc in glob.glob(
-            os.path.join(args.srcdir, 'libcapsule*.dsc')
-        ):
-            v_check_call([
-                'dcmd', 'install', '-m644', dsc,
-                os.path.join(destdir_prefix, 'sources'),
-            ])
 
-    v_check_call(
-        [
-            'apt-get',
-            '--download-only',
-            '--only-source',
-            'source',
-        ] + list(source_to_download),
-        cwd=os.path.join(destdir_prefix, 'sources'),
-    )
-
-    os.makedirs(
-        os.path.join(destdir_prefix, 'sources', 'pressure-vessel'),
-        exist_ok=True,
-    )
-
-    for src_tar in (
-        os.path.join(
-            args.srcdir,
-            'pressure-vessel-{}.tar.gz'.format(args.version),
-        ),
-        os.path.join(
-            args.srcdir,
-            'pressure-vessel-{}.tar.xz'.format(args.version),
-        ),
-    ):
-        if os.path.exists(src_tar):
-            subprocess.check_call([
-                'tar',
-                '-C', os.path.join(
-                    destdir_prefix,
-                    'sources',
-                    'pressure-vessel',
-                ),
-                '--strip-components=1',
-                '-xvf', src_tar,
-            ])
-            break
-    else:
-        if os.path.exists('/usr/bin/git'):
-            git_archive = subprocess.Popen([
-                'git', 'archive', '--format=tar', 'HEAD',
-            ], cwd=args.srcdir, stdout=subprocess.PIPE)
-            subprocess.check_call([
-                'tar',
-                '-C', os.path.join(
-                    destdir_prefix,
-                    'sources',
-                    'pressure-vessel',
-                ),
-                '-xvf-',
-            ], stdin=git_archive.stdout)
+        os.makedirs(
+            os.path.join(installation, 'sources', 'pressure-vessel'),
+            exist_ok=True,
+        )
 
-            if git_archive.wait() != 0:
-                raise subprocess.CalledProcessError(
-                    returncode=git_archive.returncode,
-                    cmd=git_archive.args,
-                )
-        else:
-            tar = subprocess.Popen([
-                'tar',
-                '-C', args.srcdir,
-                '--exclude=./.git',
-                '--exclude=./_build',
-                '--exclude=./relocatable-install',
-                '--exclude=./.mypy_cache',
-                '--exclude=.*.swp',
-                '-cf-',
-                '.',
-            ], stdout=subprocess.PIPE)
-            subprocess.check_call([
-                'tar',
-                '-C', os.path.join(
-                    destdir_prefix,
-                    'sources',
-                    'pressure-vessel',
+        for src_tar in (
+            os.path.join(
+                args.srcdir,
+                '..',
+                'pressure-vessel_{}.orig.tar.xz'.format(args.version),
+            ),
+            os.path.join(
+                args.builddir,
+                'meson-dist/pressure-vessel-{}.tar.gz'.format(
+                    args.version,
                 ),
-                '-xvf-',
-            ], stdin=tar.stdout)
+            ),
+            os.path.join(
+                args.srcdir,
+                'pressure-vessel-{}.tar.xz'.format(args.version),
+            ),
+        ):
+            if os.path.exists(src_tar):
+                subprocess.check_call([
+                    'tar',
+                    '-C', os.path.join(
+                        installation,
+                        'sources',
+                        'pressure-vessel',
+                    ),
+                    '--strip-components=1',
+                    '-xvf', src_tar,
+                ])
+                break
+        else:
+            if os.path.exists('/usr/bin/git'):
+                git_archive = subprocess.Popen([
+                    'git', 'archive', '--format=tar', 'HEAD',
+                ], cwd=args.srcdir, stdout=subprocess.PIPE)
+                subprocess.check_call([
+                    'tar',
+                    '-C', os.path.join(
+                        installation,
+                        'sources',
+                        'pressure-vessel',
+                    ),
+                    '-xvf-',
+                ], stdin=git_archive.stdout)
 
-            if tar.wait() != 0:
-                raise subprocess.CalledProcessError(
-                    returncode=git_archive.returncode,
-                    cmd=git_archive.args,
-                )
+                if git_archive.wait() != 0:
+                    raise subprocess.CalledProcessError(
+                        returncode=git_archive.returncode,
+                        cmd=git_archive.args,
+                    )
+            else:
+                tar = subprocess.Popen([
+                    'tar',
+                    '-C', args.srcdir,
+                    '--exclude=./.git',
+                    '--exclude=./_build',
+                    '--exclude=./relocatable-install',
+                    '--exclude=./.mypy_cache',
+                    '--exclude=.*.swp',
+                    '-cf-',
+                    '.',
+                ], stdout=subprocess.PIPE)
+                subprocess.check_call([
+                    'tar',
+                    '-C', os.path.join(
+                        installation,
+                        'sources',
+                        'pressure-vessel',
+                    ),
+                    '-xvf-',
+                ], stdin=tar.stdout)
+
+                if tar.wait() != 0:
+                    raise subprocess.CalledProcessError(
+                        returncode=git_archive.returncode,
+                        cmd=git_archive.args,
+                    )
 
-    with open(
-        os.path.join(
-            destdir_prefix,
-            'sources',
-            'pressure-vessel',
-            '.tarball-version',
-        ),
-        'w',
-    ) as writer:
-        writer.write('{}\n'.format(args.version))
-
-    bin_tar = os.path.join(
-        args.archive,
-        'pressure-vessel-{}-bin.tar.gz'.format(args.version),
-    )
-    src_tar = os.path.join(
-        args.archive,
-        'pressure-vessel-{}-bin+src.tar.gz'.format(args.version),
-    )
-
-    subprocess.check_call([
-        'tar',
-        r'--transform=s,^\(\.\(/\|$\)\)\?,pressure-vessel-{}/,'.format(
-            args.version,
-        ),
-        '--exclude=metadata',       # this is all duplicated in sources/
-        '-zcvf', src_tar + '.tmp',
-        '-C', destdir_prefix,
-        '.',
-    ])
-    subprocess.check_call([
-        'tar',
-        r'--transform=s,^\(\.\(/\|$\)\)\?,pressure-vessel-{}/,'.format(
-            args.version,
-        ),
-        '--exclude=sources',
-        '-zcvf', bin_tar + '.tmp',
-        '-C', destdir_prefix,
-        '.',
-    ])
-    os.rename(bin_tar + '.tmp', bin_tar)
-    os.rename(src_tar + '.tmp', src_tar)
-    print('Generated {}'.format(os.path.abspath(bin_tar)))
-    print('Generated {}'.format(os.path.abspath(src_tar)))
+        with open(
+            os.path.join(
+                installation,
+                'sources',
+                'pressure-vessel',
+                '.tarball-version',
+            ),
+            'w',
+        ) as writer:
+            writer.write('{}\n'.format(args.version))
+
+        bin_tar = os.path.join(
+            args.archive,
+            'pressure-vessel-{}-bin.tar.gz'.format(args.version),
+        )
+        src_tar = os.path.join(
+            args.archive,
+            'pressure-vessel-{}-bin+src.tar.gz'.format(args.version),
+        )
+
+        subprocess.check_call([
+            'tar',
+            r'--transform=s,^\(\.\(/\|$\)\)\?,pressure-vessel-{}/,'.format(
+                args.version,
+            ),
+            '--exclude=metadata',       # this is all duplicated in sources/
+            '-zcvf', src_tar + '.tmp',
+            '-C', installation,
+            '.',
+        ])
+        subprocess.check_call([
+            'tar',
+            r'--transform=s,^\(\.\(/\|$\)\)\?,pressure-vessel-{}/,'.format(
+                args.version,
+            ),
+            '--exclude=sources',
+            '-zcvf', bin_tar + '.tmp',
+            '-C', installation,
+            '.',
+        ])
+        os.rename(bin_tar + '.tmp', bin_tar)
+        os.rename(src_tar + '.tmp', src_tar)
+        print('Generated {}'.format(os.path.abspath(bin_tar)))
+        print('Generated {}'.format(os.path.abspath(src_tar)))
 
 
 if __name__ == '__main__':
diff --git a/ci/Jenkinsfile b/ci/Jenkinsfile
index 118390c20b62750ce5be14e8006048f5c5373a22..acb1da2451f857a76922a1721a6aeeda47a5fb2e 100644
--- a/ci/Jenkinsfile
+++ b/ci/Jenkinsfile
@@ -109,23 +109,21 @@ pipeline {
               sh '''
               set -eu
               cd src
-              meson --prefix="${WORKSPACE}/src/_build/relocatable-install" -Dpython=python3.5 _build
+              meson --prefix="$(pwd)/_build/prefix" -Dpython=python3.5 _build
               ninja -C _build
-              ninja -C _build install
               meson test --verbose -C _build
+              ninja -C _build install
+              rm -fr ../relocatable-install
               ./build-relocatable-install.py \
                 --srcdir . \
                 --builddir _build \
                 --libcapsuledir /usr/lib/libcapsule/relocatable \
-                --prefix="${WORKSPACE}/src/_build/relocatable-install" \
+                --output "${WORKSPACE}/relocatable-install" \
                 --archive "${WORKSPACE}" \
                 --set-version "$(cat .tarball-version)" \
                 ${NULL+}
               prove -v ./tests/relocatable-install.py :: \
-                --srcdir . \
-                --builddir _build \
-                --prefix="${WORKSPACE}/src/_build/relocatable-install" \
-                ${NULL+}
+                "${WORKSPACE}/relocatable-install"
               '''
             }
           }
diff --git a/tests/relocatable-install.py b/tests/relocatable-install.py
index 28e202a42ae69e9ef0e718cd723aba0acc8fe3eb..edaaba0282ba45cadc7ed666720019b932845df0 100755
--- a/tests/relocatable-install.py
+++ b/tests/relocatable-install.py
@@ -176,40 +176,10 @@ def main():
     # type: () -> None
 
     parser = argparse.ArgumentParser()
-    parser.add_argument('--destdir', default=os.getenv('DESTDIR', ''))
-    parser.add_argument('--srcdir', default=G_TEST_SRCDIR)
-    parser.add_argument('--builddir', default=G_TEST_BUILDDIR)
-    parser.add_argument('--prefix', default=None)
+    parser.add_argument('path')
     args = parser.parse_args()
 
-    if args.destdir:
-        args.destdir = os.path.abspath(args.destdir)
-
-    args.srcdir = os.path.abspath(args.srcdir)
-    args.builddir = os.path.abspath(args.builddir)
-
-    if args.prefix is None:
-        blob = subprocess.check_output([
-            'meson', 'introspect', args.builddir, '--buildoptions',
-        ], universal_newlines=True)
-        for opt in json.loads(blob):
-            if opt['name'] == 'prefix':
-                args.prefix = opt['value']
-                break
-        else:
-            raise RuntimeError(
-                'Unable to determine installation prefix from Meson, '
-                'please specify --prefix'
-            )
-
-    relocatable_install = args.destdir + args.prefix
-
-    if relocatable_install is None:
-        relocatable_install = os.path.join(args.builddir, 'relocatable-install')
-
-        if not os.path.exists(relocatable_install):
-            print('1..0 # SKIP relocatable-install not in expected location')
-            sys.exit(0)
+    relocatable_install = os.path.abspath(args.path)
 
     test = TapTest()