debian: Add docker build helpers

To ease building ACRN with all its requirements, provide a distribution aware,
self-contained docker build environment to build regular Debian packages.

For Debian Buster(10) and Ubuntu Focal Fossa(20.04 LTS) some build tools are
grabbed from their respective backports repositories. This provides a much
easier alignment with the more resent distributions.

There are three packages to be re-packaged to accommodate the build needs as
well as the runtime needs of the ACRN packages:

 * python3-elementpath_2.4.0-1
 * python3-xmlschema_1.9.2-1
 * acpica-tools_20200925-1

These packages are built during docker image build time and provided within
a local APT repository for installation at build time, i.e. when running the
respective docker container.

The multistage Dockerfile separates the required pre-build stages and reduces
the resulting image footprint of the final docker image. There are separate
docker images for each distribution.

To summarize the build steps the script acrn-docker-build.sh is provided. To
control the vendor and the distribution for the build, just set the
environment variables VENDOR and DISTRO before calling the script from the
top directory of the ACRN hypervisor workspace, e.g.:

  VENDOR=debian DISTRO=bullseye debian/docker/acrn-docker-build.sh

or

  VENDOR=ubuntu DISTRO=focal debian/docker/acrn-docker-build.sh

Tracked-On: #6688
Signed-off-by: Helmut Buchsbaum <helmut.buchsbaum@opensource.tttech-industrial.com>
This commit is contained in:
Helmut Buchsbaum 2022-04-04 12:15:05 +02:00 committed by acrnsi-robot
parent 1eadd08bf9
commit 909f6b9219
5 changed files with 347 additions and 0 deletions

244
debian/docker/Dockerfile vendored Normal file
View File

@ -0,0 +1,244 @@
# use debian stable as default distribution
ARG DISTRO=stable
ARG VENDOR=debian
###############################################################################
# Prepare apt config and eventually repackage
FROM ${VENDOR}:${DISTRO} AS tool-builder
ARG DISTRO
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get -y update && \
apt-get install -y --no-install-recommends ca-certificates
###############################################################################
# For older distros: Add backports packages needed
# * debhelper dwz libdebhelper-perl: build tool releate update
# * lintian: to keep an acceptable recent version
# * linux-libc-dev: acrn-dm needs >= 4.20 for udmabuf UAPI
RUN REPOBASE=$(cat /etc/apt/sources.list | grep -v -E '^#' | head -1 | awk '{print $3}') && \
eval $(cat /etc/os-release) && \
if [ -n "${VERSION_CODENAME}" ]; then \
DISTRONAME=${VERSION_CODENAME}; \
else \
DISTRONAME=${REPOBASE}; \
fi && \
case ${DISTRONAME} in \
buster) \
echo "deb https://deb.debian.org/debian ${DISTRONAME}-backports main" > /etc/apt/sources.list.d/${DISTRONAME}-backports.list; \
for p in debhelper dwz libdebhelper-perl lintian linux-libc-dev; do \
(echo "Package: $p"; \
echo "Pin: release a=${DISTRONAME}-backports"; \
echo "Pin-Priority: 900"; \
echo "") >> /etc/apt/preferences.d/pin-${DISTRONAME}-backports; \
done; \
;; \
focal) \
for p in debhelper dwz libdebhelper-perl lintian; do \
(echo "Package: $p"; \
echo "Pin: release a=${DISTRONAME}-backports"; \
echo "Pin-Priority: 900"; \
echo "") >> /etc/apt/preferences.d/pin-${DISTRONAME}-backports; \
done; \
;; \
esac
###############################################################################
# Install packages needed for git buildpackage based build
RUN apt-get -y update && \
apt-get install -y --no-install-recommends \
build-essential git-buildpackage devscripts dpkg-dev equivs \
lintian sudo apt-utils pristine-tar
###############################################################################
# Repackage packages
# prepare local apt repo for backported packages
RUN mkdir -p /opt/apt && cd /opt/apt && \
echo "Origin: ACRN Local Build" > .Release.header && \
echo "Label: acrn-local-build" >> .Release.header && \
apt-ftparchive packages . > Packages && \
cp .Release.header Release && apt-ftparchive release . >> Release && \
echo "deb [trusted=yes] file:/opt/apt ./" > /etc/apt/sources.list.d/local-apt.list && \
touch /etc/apt/preferences.d/pin-acrn
# setup git config for temporary use
RUN git config --global user.name "ACRN Debian Package Build" && \
git config --global user.email "acrn-dev@lists.projectacrn.org"
# elementpath 2.4.0
# Attention: 2.4.0 not available at Debian package repos, so
# import the upstream version and repackage
RUN NEEDEDVERSION="2.4.0" && \
srcpkg="elementpath" && \
url="https://salsa.debian.org/debian/${srcpkg}.git" && \
upstream_tag="upstream/2.3.1" && \
debian_tag="debian/2.3.1-1" && \
debian_branch="master" && \
upstream_branch="upstream" && \
mkdir -p /usr/src/${srcpkg} && cd /usr/src/${srcpkg} && \
git init && git remote add origin ${url} && \
git fetch origin --depth 1 refs/tags/${upstream_tag}:refs/tags/${upstream_tag} && \
git fetch origin --depth 1 refs/tags/${debian_tag}:refs/tags/${debian_tag} && \
if git show ${debian_tag}:debian | grep -qw gbp.conf; then \
pristine_tar=$(git show ${debian_tag}:debian/gbp.conf | awk -F "=" '/pristine-tar/ {print $2}' | tr '[:upper:]' '[:lower:]' | xargs); \
if [ "${pristine_tar}" = "true" ]; then \
git fetch origin pristine-tar; git branch -t pristine-tar origin/pristine-tar; \
fi; \
debian_branch=$(git show ${debian_tag}:debian/gbp.conf | awk -F "=" '/debian-branch/ {print $2}' | xargs) && \
if [ -z "${debian_branch}" ]; then \
debian_branch="master"; \
fi; \
upstream_branch=$(git show ${debian_tag}:debian/gbp.conf | awk -F "=" '/upstream-branch/ {print $2}' | xargs) && \
if [ -z "${upstream_branch}" ]; then \
upstream_branch="upstream"; \
fi; \
fi && \
git checkout -b ${upstream_branch} ${upstream_tag} && \
git checkout -b ${debian_branch} ${debian_tag} && \
sed -i 's#/latest##g' debian/watch && git add -u && git commit -m "d/watch: Fix watch url to get arbitrary versions" && \
gbp import-orig --uscan --upstream-version ${NEEDEDVERSION} && \
EDITOR=true DEBEMAIL=$(git config user.email) DEBFULLNAME=$(git config user.name) gbp dch -R -N ${NEEDEDVERSION}-1 --commit && \
mk-build-deps --tool='apt-get -o Debug::pkgProblemResolver=yes --no-install-recommends --yes' --install debian/control --remove && \
rm -f $(dpkg-parsechangelog -Ssource)-build-deps_$(dpkg-parsechangelog -Sversion)_*.* && \
DEB_BUILD_OPTIONS="nocheck" gbp buildpackage -b -us -uc && \
for p in $(grep -E '^Package:' debian/control | awk '{print $2}'); do \
echo "Package: $p" >> /etc/apt/preferences.d/pin-acrn; \
echo "Pin: release l=acrn-local-build" >> /etc/apt/preferences.d/pin-acrn; \
echo "Pin-Priority: 900" >> /etc/apt/preferences.d/pin-acrn; \
echo "" >> /etc/apt/preferences.d/pin-acrn; \
done && \
cd /usr/src && mv *.deb /opt/apt && \
cd /opt/apt && apt-ftparchive packages . > Packages && cp .Release.header Release && apt-ftparchive release . >> Release && \
ls -al /opt/apt && \
cat /etc/apt/preferences.d/pin-acrn && \
apt-get update -y
# xmlschema 1.9.2
# Again we need to repackage. This the upstream version is already available, but no debian version.
# Use 1.4.2-1 as base
RUN NEEDEDVERSION="1.9.2"; \
srcpkg="xmlschema" && \
url="https://salsa.debian.org/python-team/packages/python-xmlschema.git" && \
upstream_tag="upstream/${NEEDEDVERSION}" && \
debian_tag="debian/1.4.2-1" && \
debian_branch="master" && \
upstream_branch="upstream" && \
mkdir -p /usr/src/${srcpkg} && cd /usr/src/${srcpkg} && \
git init && git remote add origin ${url} && \
git fetch origin refs/tags/${upstream_tag}:refs/tags/${upstream_tag} && \
git fetch origin refs/tags/${debian_tag}:refs/tags/${debian_tag} && \
if git show ${debian_tag}:debian | grep -qw gbp.conf; then \
pristine_tar=$(git show ${debian_tag}:debian/gbp.conf | awk -F "=" '/pristine-tar/ {print $2}' | tr '[:upper:]' '[:lower:]' | xargs); \
if [ "${pristine_tar}" = "true" ]; then \
git fetch origin pristine-tar; git branch -t pristine-tar origin/pristine-tar; \
fi; \
debian_branch=$(git show ${debian_tag}:debian/gbp.conf | awk -F "=" '/debian-branch/ {print $2}' | xargs) && \
if [ -z "${debian_branch}" ]; then \
debian_branch="master"; \
fi; \
upstream_branch=$(git show ${debian_tag}:debian/gbp.conf | awk -F "=" '/upstream-branch/ {print $2}' | xargs) && \
if [ -z "${upstream_branch}" ]; then \
upstream_branch="upstream"; \
fi; \
fi && \
git checkout -b ${upstream_branch} ${upstream_tag} && \
git checkout -b ${debian_branch} ${debian_tag} && \
git merge --no-edit ${upstream_tag} && \
EDITOR=true DEBEMAIL=$(git config user.email) DEBFULLNAME=$(git config user.name) gbp dch -R -N ${NEEDEDVERSION}-1 --commit && \
mk-build-deps --tool='apt-get -o Debug::pkgProblemResolver=yes --no-install-recommends --yes' --install debian/control --remove && \
rm -f $(dpkg-parsechangelog -Ssource)-build-deps_$(dpkg-parsechangelog -Sversion)_*.* && \
DEB_BUILD_OPTIONS="nocheck" gbp buildpackage -b -us -uc && \
for p in $(grep -E '^Package:' debian/control | awk '{print $2}'); do \
echo "Package: $p" >> /etc/apt/preferences.d/pin-acrn; \
echo "Pin: release l=acrn-local-build" >> /etc/apt/preferences.d/pin-acrn; \
echo "Pin-Priority: 900" >> /etc/apt/preferences.d/pin-acrn; \
echo "" >> /etc/apt/preferences.d/pin-acrn; \
done && \
cd /usr/src && mv *.deb /opt/apt && \
cd /opt/apt && apt-ftparchive packages . > Packages && cp .Release.header Release && apt-ftparchive release . >> Release && \
apt-get update
# acpica-unix >= 20200925
RUN NEEDEDVERSION="20200925"; \
PKGVERSION=$(apt-cache policy acpica-tools | grep "Candidate:" | awk '{ print $2}'); \
if [ -z "${PKGVERSION}" -o "${NEEDEDVERSION}" != "$(echo ${NEEDEDVERSION}\\n${PKGVERSION} | sort -V | head -n1)" ]; then \
srcpkg="acpica-unix" && \
url="https://github.com/ahs3/acpica-tools" && \
upstream_tag="upstream/${NEEDEDVERSION}" && \
debian_tag="debian/${NEEDEDVERSION}-1" && \
debian_branch="master" && \
upstream_branch="upstream" && \
mkdir -p /usr/src/${srcpkg} && cd /usr/src/${srcpkg} && \
git init && git remote add origin ${url} && \
git fetch origin --depth 1 refs/tags/${upstream_tag}:refs/tags/${upstream_tag} && \
git fetch origin --depth 1 refs/tags/${debian_tag}:refs/tags/${debian_tag} && \
if git show ${debian_tag}:debian | grep -qw gbp.conf; then \
pristine_tar=$(git show ${debian_tag}:debian/gbp.conf | awk -F "=" '/pristine-tar/ {print $2}' | tr '[:upper:]' '[:lower:]' | xargs); \
if [ "${pristine_tar}" = "true" ]; then \
git fetch origin pristine-tar; git branch -t pristine-tar origin/pristine-tar; \
fi; \
debian_branch=$(git show ${debian_tag}:debian/gbp.conf | awk -F "=" '/debian-branch/ {print $2}' | xargs) && \
if [ -z "${debian_branch}" ]; then \
debian_branch="master"; \
fi; \
upstream_branch=$(git show ${debian_tag}:debian/gbp.conf | awk -F "=" '/upstream-branch/ {print $2}' | xargs) && \
if [ -z "${upstream_branch}" ]; then \
upstream_branch="upstream"; \
fi; \
fi && \
git checkout -b ${upstream_branch} ${upstream_tag} && \
git checkout -b ${debian_branch} ${debian_tag} && \
mk-build-deps --tool='apt-get -o Debug::pkgProblemResolver=yes --no-install-recommends --yes' --install debian/control --remove && \
rm -f $(dpkg-parsechangelog -Ssource)-build-deps_$(dpkg-parsechangelog -Sversion)_*.* && \
DEB_BUILD_OPTIONS="nocheck" gbp buildpackage -b -us -uc && \
for p in $(grep -E '^Package:' debian/control | awk '{print $2}'); do \
echo "Package: $p" >> /etc/apt/preferences.d/pin-acrn; \
echo "Pin: release l=acrn-local-build" >> /etc/apt/preferences.d/pin-acrn; \
echo "Pin-Priority: 900" >> /etc/apt/preferences.d/pin-acrn; \
echo "" >> /etc/apt/preferences.d/pin-acrn; \
done && \
cd /usr/src && mv *.deb /opt/apt && \
cd /opt/apt && apt-ftparchive packages . > Packages && cp .Release.header Release && apt-ftparchive release . >> Release && \
apt-get update -y; \
fi
###############################################################################
# the final image
FROM ${VENDOR}:${DISTRO}
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get -y update && \
apt-get install -y --no-install-recommends ca-certificates
COPY --from=tool-builder /etc/apt/sources.list.d/* /etc/apt/sources.list.d/
COPY --from=tool-builder /etc/apt/preferences.d/* /etc/apt/preferences.d/
COPY --from=tool-builder /opt/apt /opt/apt
###############################################################################
# Install build script requirements
RUN apt-get -y update && apt-get install -y --no-install-recommends \
devscripts \
equivs \
git-buildpackage \
lintian \
sudo
###############################################################################
# Mount the topdir of the Debian git repository at /source
VOLUME /source/
WORKDIR /source/
###############################################################################
# Get default settings and helper scripts
ADD gbp.conf /etc/git-buildpackage/
ADD debian-pkg-build.sh /usr/local/bin/debian-pkg-build.sh
ADD lintian.sh /usr/local/bin/lintian.sh
###############################################################################
# build Debian packages
ENTRYPOINT ["/usr/local/bin/debian-pkg-build.sh"]

44
debian/docker/acrn-docker-build.sh vendored Executable file
View File

@ -0,0 +1,44 @@
#!/bin/bash
# Helper script to build ACRN with docker
# This also includes building packages required for ACRN build or runtime
VENDOR=${VENDOR:-debian}
DISTRO=${DISTRO:-stable}
TOPDIR=$(git rev-parse --show-toplevel)
DOCKER=$(which docker)
if [ -z "${TOPDIR}" ]; then
echo "Run $0 from inside git repository!"
exit 1
fi
if [ -z "${DOCKER}" ]; then
echo "Cannot find docker binary, please install!"
exit 1
fi
pushd ${TOPDIR} >/dev/null
if [ ! -f debian/docker/Dockerfile ]; then
echo "No Dockerfile available!"
exit 1
fi
set -e
# create docker image for Debian package build
${DOCKER} build \
-f debian/docker/Dockerfile \
--build-arg DISTRO=${DISTRO} \
--build-arg VENDOR=${VENDOR} \
-t acrn-pkg-builder:${DISTRO} debian/docker
# build ACRN packages
${DOCKER} run \
--rm \
-e UID=$(id -u) \
-e GID=$(id -g) \
-v $(pwd):/source acrn-pkg-builder:${DISTRO} -F --no-sign --git-export-dir=build/${DISTRO} "$@"
popd >/dev/null

26
debian/docker/debian-pkg-build.sh vendored Executable file
View File

@ -0,0 +1,26 @@
#!/bin/bash -e
if [ ! -f debian/control ]; then
echo "Cannot find debian/control" >&2
exit 1
fi
if [[ -n ${UID} && -n ${GID} ]]; then
addgroup --gid ${GID} docker-build
adduser --uid=${UID} --gid=${GID} --disabled-password --gecos '' docker-build
else
echo "UID/GID not set. Use docker run -e UID=$(id -u) -e GID=$(id -g)" >&2
exit 1
fi
# install build dependencies using tmpdir to not interfer with parallel builds
topdir=$(pwd)
tmpdir=$(mktemp -d)
pushd ${tmpdir} >/dev/null
mk-build-deps --tool='apt-get -o Debug::pkgProblemResolver=yes --no-install-recommends --yes' --install ${topdir}/debian/control
popd >/dev/null
rm -rf ${tmpdir}
# start build
export HOME=$(echo ~docker-build)
sudo -E -u docker-build gbp buildpackage "$@"

5
debian/docker/gbp.conf vendored Normal file
View File

@ -0,0 +1,5 @@
[DEFAULT]
[buildpackage]
# To make build fail on lintian errors
builder = debuild --no-lintian -i -I --check-command=/usr/local/bin/lintian.sh

28
debian/docker/lintian.sh vendored Executable file
View File

@ -0,0 +1,28 @@
#!/bin/sh
# helper to compare version
verlte() {
[ "$1" = "$(echo -e "$1\n$2" | sort -V | head -n1)" ]
}
lintian_version=$(lintian --version | awk '{print $2}')
# Explicitly use --fail-on error if available (since 2.77.0)
# This circumvents a problem in bullseye lintian, where failing on error
# is not the default action any more
# Always use debian profile for lintian
if $(verlte 2.77.0 ${lintian_version}); then
LINTIAN_ARGS="--profile debian --fail-on error"
else
LINTIAN_ARGS="--profile debian"
fi
echo "lintian ${LINTIAN_ARGS} $1"
lintian ${LINTIAN_ARGS} $1
status=$?
if [ $status -ne 0 ]; then
echo "+++ LINTIAN ERRORS DETECTED +++" >&2
fi
exit $status