snap: confine classically and carry the full packaging toolchain
A devmode snap is a smoke test, not a distribution channel: pkh drives the whole host packaging stack (unshare chroots, overlay mounts, dpkg/quilt/lintian across arbitrary paths), which only classic confinement can express. The snap now bundles every host-side tool pkh execs (git, gnupg, dpkg-dev, quilt, pristine-tar, mmdebstrap, lintian, fakeroot, util-linux, mount, schroot, openssh, tar/xz/bzip2), with apt and dpkg deliberately left to the host: a core24 apt managing a newer host's package database is exactly the skew classic snaps must avoid. Tools running only inside the build chroot stay out; pkh provisions those itself. Release metadata comes from Cargo.toml instead of the git hash, and grade is stable, so a build of any commit packs as the declared version. Classic-mode correctness: noble's mount/umount are staged from the split mount package, fakeroot is exposed via symlink since update-alternatives does not run at staging, and every bundled ELF is patched to the core24 loader with a DT_RPATH resolving the base and $ORIGIN. Without this the host loader would pin the snap to hosts with a matching glibc, and the host ld.so.cache would mix host libraries with base ones.
This commit is contained in:
@@ -1,2 +1,9 @@
|
||||
*.lock
|
||||
target
|
||||
|
||||
# Local snapcraft builds
|
||||
.craft
|
||||
parts
|
||||
prim
|
||||
stage
|
||||
*.snap
|
||||
|
||||
+74
-8
@@ -5,9 +5,13 @@ description: |
|
||||
pkh aims at wrapping the different debian tools and workflows
|
||||
into one tool, that would have the same interface for everything,
|
||||
while being smarter at integrating all workflows.
|
||||
|
||||
This snap uses classic confinement and carries the packaging
|
||||
toolchain it drives (dpkg-dev, git, mmdebstrap, lintian, quilt, ...)
|
||||
so it behaves the same on any Debian/Ubuntu host.
|
||||
adopt-info: pkh-part
|
||||
|
||||
confinement: devmode
|
||||
confinement: classic
|
||||
|
||||
apps:
|
||||
pkh:
|
||||
@@ -19,24 +23,86 @@ parts:
|
||||
source: .
|
||||
override-pull: |
|
||||
craftctl default
|
||||
craftctl set version=$(git rev-parse --short=11 HEAD)
|
||||
craftctl set grade="devel"
|
||||
# Release metadata comes from the crate, not the git state: a build
|
||||
# of any commit must produce the version the crate declares.
|
||||
craftctl set version="$(awk -F'"' '/^version =/{print $2; exit}' Cargo.toml)"
|
||||
craftctl set grade="stable"
|
||||
build-packages:
|
||||
- build-essential
|
||||
- file
|
||||
- patchelf
|
||||
- pkg-config
|
||||
- libssl-dev
|
||||
- libgpg-error-dev
|
||||
- libgpgme-dev
|
||||
# Host-side tools pkh execs directly. Tools that only run *inside*
|
||||
# the build chroot (dose-builddebcheck, dpkg-cross) are provisioned
|
||||
# there by pkh itself and must not be staged; likewise qemu-user-static
|
||||
# is host binfmt configuration, not a bundled file.
|
||||
#
|
||||
# The apt and dpkg state-owning tools are deliberately excluded below:
|
||||
# they must be the host's (classic mode makes them visible), since a
|
||||
# core24 apt/dpkg managing a newer host's package database is exactly
|
||||
# the version skew classic snaps must avoid. The source-package tools
|
||||
# (dpkg-buildpackage, dpkg-source, ...) are bundled instead.
|
||||
stage-packages:
|
||||
- libgpgme11t64
|
||||
- git
|
||||
- curl
|
||||
- gnupg
|
||||
- gpgv
|
||||
- dpkg-dev
|
||||
- quilt
|
||||
- pristine-tar
|
||||
- mmdebstrap
|
||||
- lintian
|
||||
- fakeroot
|
||||
- util-linux
|
||||
- dpkg-dev
|
||||
# mount/umount moved to their own package (split from util-linux)
|
||||
- mount
|
||||
- schroot
|
||||
- openssh-client
|
||||
- tar
|
||||
- xz-utils
|
||||
- bzip2
|
||||
stage:
|
||||
- -usr/lib/x86_64-linux-gnu/libicuio.so.74.2
|
||||
- -usr/lib/x86_64-linux-gnu/libicutest.so.74.2
|
||||
- -usr/lib/x86_64-linux-gnu/libicutu.so.74.2
|
||||
- -usr/lib/x86_64-linux-gnu/libicui18n.so.74.2
|
||||
- -usr/bin/apt
|
||||
- -usr/bin/apt-cache
|
||||
- -usr/bin/apt-cdrom
|
||||
- -usr/bin/apt-config
|
||||
- -usr/bin/apt-get
|
||||
- -usr/bin/apt-key
|
||||
- -usr/bin/apt-mark
|
||||
- -usr/lib/*/libapt-*
|
||||
- -usr/lib/*/libicuio*
|
||||
- -usr/lib/*/libicutest*
|
||||
- -usr/lib/*/libicutu*
|
||||
- -usr/lib/*/libicui18n*
|
||||
# update-alternatives does not run at staging time: expose the sysv
|
||||
# fakeroot under the plain name dpkg-buildpackage and pkh exec.
|
||||
override-prime: |
|
||||
craftctl default
|
||||
ln -sfn fakeroot-sysv "${CRAFT_PRIME}/usr/bin/fakeroot"
|
||||
# Classic-confined ELFs default to the host loader, which pins the
|
||||
# snap to hosts shipping at least the build environment's glibc,
|
||||
# and cannot see the libraries deduplicated against the base.
|
||||
# Point every bundled ELF at the core24 loader and give it an
|
||||
# rpath resolving base libraries from the mounted base and
|
||||
# snap-local libraries from $ORIGIN — the classic linter's
|
||||
# guidance, and what Canonical's own classic snaps do. DT_RPATH
|
||||
# (--force-rpath) is required over the default DT_RUNPATH: the
|
||||
# host ld.so.cache would otherwise resolve sonames to host
|
||||
# libraries first, mixing host libm/libresolv with base libc.
|
||||
# DT_RPATH also propagates transitively, covering dependencies of
|
||||
# dependencies (libgpgme -> libassuan). Host tools spawned later
|
||||
# (host apt-get, ...) run with a pristine environment since no
|
||||
# LD_LIBRARY_PATH is exported.
|
||||
find "${CRAFT_PRIME}" -type f -exec sh -c '
|
||||
for f do
|
||||
[ "$(od -An -N4 -tx1 "$f" | tr -d " \n")" = "7f454c46" ] || continue
|
||||
patchelf --set-interpreter \
|
||||
/snap/core24/current/lib64/ld-linux-x86-64.so.2 "$f" 2>/dev/null || true
|
||||
patchelf --force-rpath --set-rpath \
|
||||
"/snap/core24/current/lib/x86_64-linux-gnu:/snap/core24/current/usr/lib/x86_64-linux-gnu:\$ORIGIN:\$ORIGIN/../lib/x86_64-linux-gnu:\$ORIGIN/../usr/lib/x86_64-linux-gnu" \
|
||||
"$f" 2>/dev/null || true
|
||||
done' sh {} +
|
||||
|
||||
Reference in New Issue
Block a user