├── Dockerfile-Debian-bookworm-12 ├── Dockerfile-Debian-bullseye-11 ├── Dockerfile-Debian-buster-10 ├── Dockerfile-Debian-sid-unstable ├── Dockerfile-ubuntu-18.04 ├── Dockerfile-ubuntu-20.04 ├── Dockerfile-ubuntu-22.04 ├── Dockerfile-ubuntu-23.04 ├── LICENSE ├── README.md ├── build └── build-helper.sh /Dockerfile-Debian-bookworm-12: -------------------------------------------------------------------------------- 1 | FROM debian:bookworm 2 | 3 | RUN sed -i -- 's/Types: deb/Types: deb deb-src/g' /etc/apt/sources.list.d/debian.sources 4 | RUN echo 'man-db man-db/auto-update boolean false' | debconf-set-selections 5 | RUN set -ex \ 6 | && apt-get update \ 7 | && apt-get upgrade -y --no-install-recommends \ 8 | && apt-get install -y --no-install-recommends \ 9 | build-essential \ 10 | cdbs \ 11 | devscripts \ 12 | equivs \ 13 | fakeroot \ 14 | && apt-mark minimize-manual -y \ 15 | && apt-get autopurge -y \ 16 | && apt-get clean 17 | RUN rm /etc/apt/apt.conf.d/docker-clean 18 | RUN rm -rf /tmp/* /var/tmp/ 19 | RUN ln -s /tmp /var/tmp 20 | -------------------------------------------------------------------------------- /Dockerfile-Debian-bullseye-11: -------------------------------------------------------------------------------- 1 | FROM debian:bullseye 2 | 3 | RUN sed -i -- 's/# deb-src/deb-src/g' /etc/apt/sources.list 4 | RUN echo 'man-db man-db/auto-update boolean false' | debconf-set-selections 5 | RUN set -ex \ 6 | && apt-get update \ 7 | && apt-get upgrade -y --no-install-recommends \ 8 | && apt-get install -y --no-install-recommends \ 9 | build-essential \ 10 | cdbs \ 11 | devscripts \ 12 | equivs \ 13 | fakeroot \ 14 | && apt-mark minimize-manual -y \ 15 | && apt-get autopurge -y \ 16 | && apt-get clean 17 | RUN rm /etc/apt/apt.conf.d/docker-clean 18 | RUN rm -rf /tmp/* /var/tmp/ 19 | RUN ln -s /tmp /var/tmp 20 | -------------------------------------------------------------------------------- /Dockerfile-Debian-buster-10: -------------------------------------------------------------------------------- 1 | FROM debian:buster 2 | 3 | RUN sed -i -- 's/# deb-src/deb-src/g' /etc/apt/sources.list 4 | RUN echo 'man-db man-db/auto-update boolean false' | debconf-set-selections 5 | RUN set -ex \ 6 | && apt-get update \ 7 | && apt-get upgrade -y --no-install-recommends \ 8 | && apt-get install -y --no-install-recommends \ 9 | build-essential \ 10 | cdbs \ 11 | devscripts \ 12 | equivs \ 13 | fakeroot \ 14 | && apt-mark minimize-manual -y \ 15 | && apt-get autopurge -y \ 16 | && apt-get clean 17 | RUN rm /etc/apt/apt.conf.d/docker-clean 18 | RUN rm -rf /tmp/* /var/tmp/ 19 | RUN ln -s /tmp /var/tmp 20 | -------------------------------------------------------------------------------- /Dockerfile-Debian-sid-unstable: -------------------------------------------------------------------------------- 1 | FROM debian:sid 2 | 3 | RUN sed -i -- 's/Types: deb/Types: deb deb-src/g' /etc/apt/sources.list.d/debian.sources 4 | RUN echo 'man-db man-db/auto-update boolean false' | debconf-set-selections 5 | RUN set -ex \ 6 | && apt-get update \ 7 | && apt-get upgrade -y --no-install-recommends --purge \ 8 | && apt-get dist-upgrade -y --no-install-recommends --purge \ 9 | && apt-get install -y --no-install-recommends --purge \ 10 | build-essential \ 11 | cdbs \ 12 | devscripts \ 13 | equivs \ 14 | fakeroot \ 15 | && apt-mark minimize-manual -y \ 16 | && apt-get autopurge -y \ 17 | && apt-get clean 18 | RUN rm /etc/apt/apt.conf.d/docker-clean 19 | RUN rm -rf /tmp/* /var/tmp/ 20 | RUN ln -s /tmp /var/tmp 21 | -------------------------------------------------------------------------------- /Dockerfile-ubuntu-18.04: -------------------------------------------------------------------------------- 1 | FROM ubuntu:18.04 2 | 3 | RUN sed -i -- 's/# deb-src/deb-src/g' /etc/apt/sources.list 4 | RUN echo 'man-db man-db/auto-update boolean false' | debconf-set-selections 5 | RUN set -ex \ 6 | && apt-get update \ 7 | && apt-get upgrade -y --no-install-recommends \ 8 | && apt-get install -y --no-install-recommends \ 9 | build-essential \ 10 | cdbs \ 11 | devscripts \ 12 | equivs \ 13 | fakeroot \ 14 | && apt-get clean 15 | RUN rm /etc/apt/apt.conf.d/docker-clean 16 | RUN rm -rf /tmp/* /var/tmp/ 17 | RUN ln -s /tmp /var/tmp 18 | -------------------------------------------------------------------------------- /Dockerfile-ubuntu-20.04: -------------------------------------------------------------------------------- 1 | FROM ubuntu:20.04 2 | 3 | ARG DEBIAN_FRONTEND=noninteractive 4 | 5 | RUN sed -i -- 's/# deb-src/deb-src/g' /etc/apt/sources.list 6 | RUN echo 'man-db man-db/auto-update boolean false' | debconf-set-selections 7 | RUN set -ex \ 8 | && apt-get update \ 9 | && apt-get upgrade -y --no-install-recommends \ 10 | && apt-get install -y --no-install-recommends \ 11 | build-essential \ 12 | cdbs \ 13 | devscripts \ 14 | equivs \ 15 | fakeroot \ 16 | && apt-mark minimize-manual -y \ 17 | && apt-get autopurge -y \ 18 | && apt-get clean 19 | RUN rm /etc/apt/apt.conf.d/docker-clean 20 | RUN rm -rf /tmp/* /var/tmp/ 21 | RUN ln -s /tmp /var/tmp 22 | -------------------------------------------------------------------------------- /Dockerfile-ubuntu-22.04: -------------------------------------------------------------------------------- 1 | FROM ubuntu:22.04 2 | 3 | ARG DEBIAN_FRONTEND=noninteractive 4 | 5 | RUN sed -i -- 's/# deb-src/deb-src/g' /etc/apt/sources.list 6 | RUN echo 'man-db man-db/auto-update boolean false' | debconf-set-selections 7 | RUN set -ex \ 8 | && apt-get update \ 9 | && apt-get upgrade -y --no-install-recommends \ 10 | && apt-get install -y --no-install-recommends \ 11 | build-essential \ 12 | cdbs \ 13 | devscripts \ 14 | equivs \ 15 | fakeroot \ 16 | && apt-mark minimize-manual -y \ 17 | && apt-get autopurge -y \ 18 | && apt-get clean 19 | RUN rm /etc/apt/apt.conf.d/docker-clean 20 | RUN rm -rf /tmp/* /var/tmp/ 21 | RUN ln -s /tmp /var/tmp 22 | -------------------------------------------------------------------------------- /Dockerfile-ubuntu-23.04: -------------------------------------------------------------------------------- 1 | FROM ubuntu:23.04 2 | 3 | ARG DEBIAN_FRONTEND=noninteractive 4 | 5 | RUN sed -i -- 's/# deb-src/deb-src/g' /etc/apt/sources.list 6 | RUN echo 'man-db man-db/auto-update boolean false' | debconf-set-selections 7 | RUN set -ex \ 8 | && apt-get update \ 9 | && apt-get upgrade -y --no-install-recommends \ 10 | && apt-get install -y --no-install-recommends \ 11 | build-essential \ 12 | cdbs \ 13 | devscripts \ 14 | equivs \ 15 | fakeroot \ 16 | && apt-mark minimize-manual -y \ 17 | && apt-get autopurge -y \ 18 | && apt-get clean 19 | RUN rm /etc/apt/apt.conf.d/docker-clean 20 | RUN rm -rf /tmp/* /var/tmp/ 21 | RUN ln -s /tmp /var/tmp 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Tero Saarni 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Creating Debian packages in container 2 | 3 | ## Overview 4 | 5 | Container engines, in particular docker and podman, can be used for Debian 6 | packaging. Building inside a container avoids installing build dependencies on 7 | the host, ensures a clean and reproducible environment, and in case of podman 8 | allows to perform the build as unprivileged user. 9 | 10 | Fork of [docker-deb-builder](https://github.com/tsaarni/docker-deb-builder), 11 | created by Tero Saarni. 12 | 13 | ## Create build environment 14 | 15 | The build environment is setup in advance by creating a container image to 16 | speed up builds. It only contains essential build dependencies, like gcc, thus 17 | one can be used to build different Debian packages. For each distribution a 18 | separate build environment needs to be created. 19 | 20 | In this example the target is Ubuntu 22.04 and Debian sid, other distributions 21 | can be created by their respective Dockerfile: 22 | 23 | docker build -t container-deb-builder:22.04 -f Dockerfile-ubuntu-22.04 . 24 | podman build -t container-deb-builder:sid -f Dockerfile-Debian-sid-unstable . 25 | 26 | The image name (`container-deb-builder:22.04`) is later used while building a 27 | Debian package. 28 | 29 | ## Building packages 30 | 31 | First download or git clone the source code of the package to build: 32 | 33 | git clone ... ~/my-package-source 34 | 35 | The source code should contain subdirectory called `debian` with at 36 | least a minimum set of packaging files: `control`, `copyright`, 37 | `changelog` and `rules`. 38 | 39 | Run the build script to see its usage: 40 | 41 | $ ./build -h 42 | usage: build [options...] SOURCEDIR 43 | Options: 44 | -i IMAGE Name of the docker image (including tag) to use as package build environment. 45 | -c PROGRAM Use a custom container engine. 46 | -o DIR Destination directory to store packages to. 47 | -d DIR Directory that contains other deb packages that need to be installed before build. 48 | -p profiles Specify the profiles to build (e.g. nocheck). Takes a comma separated list. 49 | -C Use ccache to cache compiled objects. 50 | -L Run Lintian after a successful build. 51 | -B Run blhc after a successful build. 52 | -t Reset file modification timestamps to changelog entry. 53 | 54 | To build Debian packages run following commands: 55 | 56 | # create destination directory to store the build results 57 | mkdir output 58 | 59 | # build package from source directory 60 | ./build -i container-deb-builder:22.04 -o output ~/my-package-source 61 | 62 | After a successful build the build results will be copied from the container 63 | into the `output` directory. The container itself is discarded. 64 | 65 | Sometimes builds might require dependencies that cannot be installed with 66 | `apt-get build-dep`, e.g. when the required version of the dependency is not 67 | yet available. Those can be installed into the build environment by passing 68 | the option `-d DIR`, where *DIR* is a directory with `*.deb` files in it. 69 | 70 | ./build -i container-deb-builder:22.04 -o output -d dependencies ~/my-package-source 71 | 72 | ### Native builds for foreign architectures 73 | 74 | By default all packages are build for the architecture the host is running on. 75 | Docker and Podman however support running containers under a foreign 76 | architecture via QEMU. This emulation is quite slower than standard cross- 77 | compiling but enables native builds, which for example includes running tests. 78 | 79 | First install the required system packages: 80 | 81 | apt install binfmt-support qemu-user-static 82 | 83 | Distinct images needs to be build for each architecture via the flag 84 | `--platform`, e.g. for arm64: 85 | 86 | podman build -t container-deb-builder-arm64:sid -f Dockerfile-Debian-bookworm-12 --platform arm64 . 87 | 88 | --- 89 | **Note**: 90 | 91 | Podman remembers the last architecture used for a local image, so be sure to 92 | specify the correct platform for further usage (especially if the name of the 93 | image is used multiple times). 94 | 95 | --- 96 | 97 | Building packages then works just by using the particular images. 98 | 99 | ## Maintenance 100 | 101 | The data for apt archives and ccache is stored in volumes. These volumes have 102 | the naming scheme `cdebb__${ImageName}__(apt|ccache)` and can be removed if 103 | the respective image does no longer exists or the disk space is needed. 104 | -------------------------------------------------------------------------------- /build: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eo pipefail 4 | 5 | PROG=$(basename "$0") 6 | PROG_DIR=$(dirname "$0") 7 | 8 | CDEBB_DIR='/opt/cdebb' 9 | 10 | if [ -t 0 ] && [ -t 1 ]; then 11 | Red='\033[0;31m' 12 | Cyan='\033[0;36m' 13 | UnderlineON='\033[4m' 14 | UnderlineOFF='\033[24m' 15 | Bold='\033[1m' 16 | Reset='\033[0m' 17 | else 18 | Red= 19 | Cyan= 20 | UnderlineON='`' 21 | UnderlineOFF='`' 22 | Bold= 23 | Reset= 24 | fi 25 | 26 | function log { 27 | echo -e "${Cyan}[+] $1${Reset}" 28 | } 29 | 30 | function usage { 31 | cat <&2 32 | usage: $PROG [options...] SOURCEDIR 33 | Options: 34 | -i IMAGE Name of the docker image (including tag) to use as package build environment. 35 | -c PROGRAM Use a custom container engine. 36 | -o DIR Destination directory to store packages to. 37 | -d DIR Directory that contains other deb packages that need to be installed before build. 38 | -p profiles Specify the profiles to build (e.g. nocheck). Takes a comma separated list. 39 | -C Use ccache to cache compiled objects. 40 | -L Run Lintian after a successful build. 41 | -B Run blhc after a successful build. 42 | -t Reset file modification timestamps to changelog entry. 43 | EOF 44 | exit 1 45 | } 46 | 47 | function fatal { 48 | echo -e "${Red}[!]${Reset} ${Bold}$PROG${Reset}: ${Red}${1:-"Unknown Error"}${Reset}" 1>&2 49 | exit 1 50 | } 51 | 52 | function abspath { 53 | cd "$1" && pwd 54 | } 55 | 56 | function sanitize_string { 57 | local str=${1//_/} 58 | str=${str// /_} 59 | echo "${str//[^a-zA-Z0-9_]/-}" 60 | } 61 | 62 | 63 | ########################################################################### 64 | 65 | [[ $# -eq 0 ]] && usage 66 | 67 | while getopts "c:i:o:p:d:htBCL" opt; do 68 | case $opt in 69 | c) 70 | [[ "$tool" ]] && fatal "Container engine specified multiple times" 71 | tool="$OPTARG" 72 | ;; 73 | i) 74 | [[ "$image" ]] && fatal "Build image specified multiple times" 75 | image="$OPTARG" 76 | ;; 77 | o) 78 | [[ "$outdir" ]] && fatal "Destination directory specified multiple times" 79 | outdir="$OPTARG" 80 | ;; 81 | p) 82 | [[ "$profiles" ]] && fatal "Build profiles specified multiple times" 83 | profiles="$OPTARG" 84 | ;; 85 | d) 86 | [[ "$depdir" ]] && fatal "Dependency directory specified multiple times" 87 | depdir="$OPTARG" 88 | ;; 89 | t) 90 | [[ "$reset_timestamps" ]] && fatal "Timestamp reset option specified multiple times" 91 | reset_timestamps=1 92 | ;; 93 | B) 94 | [[ "$run_blhc" ]] && fatal "blhc option specified multiple times" 95 | run_blhc=1 96 | ;; 97 | C) 98 | [[ "$use_ccache" ]] && fatal "ccache option specified multiple times" 99 | use_ccache=1 100 | ;; 101 | L) 102 | [[ "$run_lintian" ]] && fatal "Lintian option specified multiple times" 103 | run_lintian=1 104 | ;; 105 | h) 106 | usage 107 | ;; 108 | *) 109 | usage 110 | ;; 111 | esac 112 | done 113 | 114 | shift $((OPTIND - 1)) 115 | [[ $# -eq 0 ]] && fatal "source directory not specified" 116 | srcdir=$1 117 | shift 118 | extra_args=("$@") 119 | [[ $# -ne 0 ]] && fatal "invalid trailing command line argument(s): ${extra_args[*]}" 120 | 121 | if [[ ! "$tool" ]]; then 122 | if command -v podman >/dev/null 2>&1; then 123 | tool='podman' 124 | elif command -v docker >/dev/null 2>&1; then 125 | tool='docker' 126 | elif command -v distrobox-host-exec >/dev/null 2>&1; then 127 | if distrobox-host-exec podman --version >/dev/null 2>&1; then 128 | tool='distrobox-host-exec podman' 129 | elif distrobox-host-exec docker --version >/dev/null 2>&1; then 130 | tool='distrobox-host-exec docker' 131 | fi 132 | elif command -v flatpak-spawn >/dev/null 2>&1; then 133 | if flatpak-spawn --host podman --version >/dev/null 2>&1; then 134 | tool='flatpak-spawn --host podman' 135 | elif flatpak-spawn --host docker --version >/dev/null 2>&1; then 136 | tool='flatpak-spawn --host docker' 137 | fi 138 | fi 139 | fi 140 | 141 | [[ ! "$tool" ]] && fatal "neither podman nor docker found" 142 | tool_version=$($tool --version) 143 | 144 | tool_args="--interactive --tty " 145 | 146 | # Check that mandatory parameters are valid 147 | [[ ! "$outdir" ]] && fatal "output directory was not given (-o DIR)" 148 | [[ ! -d "$outdir" ]] && fatal "output directory ${UnderlineON}${outdir}${UnderlineOFF} does not exist" 149 | [[ ! "$srcdir" ]] && fatal "source directory not given" 150 | [[ ! -r "$srcdir/debian" ]] && fatal "source directory ${UnderlineON}${srcdir}${UnderlineOFF} does not contain debian sub directory" 151 | [[ ! "$image" ]] && fatal "docker image name not given (-i IMAGE)" 152 | 153 | # Check that optional parameters are valid 154 | if [[ "$depdir" ]]; then 155 | [[ ! -e "$depdir" ]] && fatal "dependency directory ${UnderlineON}${depdir}${UnderlineOFF} given but does not exist" 156 | [[ ! -d "$depdir" ]] && fatal "dependency directory ${UnderlineON}${depdir}${UnderlineOFF} given but is not a directory" 157 | tool_args+="--volume $(abspath "$depdir"):${CDEBB_DIR}/dependencies:ro " 158 | fi 159 | 160 | tool_args+="--volume $(abspath "$srcdir"):${CDEBB_DIR}/source-ro:ro " 161 | tool_args+="--volume $(abspath "$outdir"):${CDEBB_DIR}/output " 162 | tool_args+="--volume $(abspath "$PROG_DIR")/build-helper.sh:${CDEBB_DIR}/build-helper.sh:ro " 163 | tool_args+="--mount type=tmpfs,destination=/tmp " 164 | 165 | # Pass current UID and GID to container, so that it can change the 166 | # ownership of output files which are otherwise written to outdir as 167 | # root 168 | CURR_UID=$(id -u) 169 | CURR_GID=$(id -g) 170 | [[ "$tool_version" =~ "Docker" ]] && tool_args+="--env USER=${CURR_UID} --env GROUP=${CURR_GID} " 171 | 172 | # Comment following out if you want to keep container after execution 173 | # for debugging 174 | tool_args+="--rm " 175 | 176 | # pass build profiles to use 177 | if [[ "$profiles" ]]; then 178 | tool_args+="--env DEB_BUILD_PROFILES=$profiles --env DEB_BUILD_OPTIONS=$profiles " 179 | fi 180 | 181 | sanitized_image_name=$(sanitize_string "$image") 182 | 183 | # share apt package cache 184 | tool_args+="--volume cdebb__${sanitized_image_name}__apt:/var/cache/apt/archives " 185 | 186 | # pass whether to use ccache 187 | if [[ "$use_ccache" ]]; then 188 | tool_args+="--env USE_CCACHE=1 --volume cdebb__${sanitized_image_name}__ccache:${CDEBB_DIR}/ccache_dir " 189 | fi 190 | 191 | # pass whether to run Lintian 192 | if [[ "$run_lintian" ]]; then 193 | tool_args+="--env RUN_LINTIAN=1 " 194 | fi 195 | 196 | # pass whether to run blhc 197 | if [[ "$run_blhc" ]]; then 198 | tool_args+="--env RUN_BLHC=1 " 199 | fi 200 | 201 | # pass whether to reset timestamps 202 | if [[ "$reset_timestamps" ]]; then 203 | tool_args+="--env RESET_TIMESTAMPS=1 " 204 | fi 205 | 206 | # disable any selinux stuff while using rh and derivates with podman 207 | [[ "$tool_version" =~ "podman" ]] && tool_args+="--security-opt label=disable " 208 | 209 | # run in RAM 210 | [[ "$tool_version" =~ "podman" ]] && tool_args+="--image-volume=tmpfs " 211 | 212 | cmd="$tool run $tool_args $image /bin/bash ${CDEBB_DIR}/build-helper.sh" 213 | 214 | log "Running '$tool':" 215 | log "$cmd" 216 | 217 | exec $cmd 218 | -------------------------------------------------------------------------------- /build-helper.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -euo pipefail 4 | 5 | # This script is executed within the container as root. It assumes 6 | # that source code with debian packaging files can be found at 7 | # /source-ro and that resulting packages are written to /output after 8 | # successful build. These directories are mounted as docker volumes to 9 | # allow files to be exchanged between the host and the container. 10 | 11 | CDEBB_DIR='/opt/cdebb' 12 | CDEBB_BUILD_DIR="${CDEBB_DIR}/build" 13 | 14 | if [ -t 0 ] && [ -t 1 ]; then 15 | Blue='\033[0;34m' 16 | Reset='\033[0m' 17 | else 18 | Blue= 19 | Reset= 20 | fi 21 | 22 | function log { 23 | echo -e "${Blue}[*] $1${Reset}" 24 | } 25 | 26 | CONTAINER_START_TIME="$EPOCHSECONDS" 27 | 28 | # Remove directory owned by _apt 29 | trap "rm -rf /var/cache/apt/archives/partial" EXIT 30 | 31 | # force colors from dh and dpkg 32 | export DH_COLORS="always" 33 | export DPKG_COLORS="always" 34 | 35 | log "Updating container" 36 | apt-get update 37 | apt-get upgrade -y --no-install-recommends 38 | 39 | log "Checking for obsolete packages" 40 | apt-mark minimize-manual -y 41 | apt-get autoremove -y 42 | 43 | log "Cleaning apt package cache" 44 | apt-get autoclean 45 | 46 | # Install extra dependencies that were provided for the build (if any) 47 | # Note: dpkg can fail due to dependencies, ignore errors, and use 48 | # apt-get to install those afterwards 49 | if [ -d "${CDEBB_DIR}/dependencies" ]; then 50 | log "Installing extra dependencies" 51 | dpkg -i "${CDEBB_DIR}/dependencies"/*.deb || true 52 | apt-get -f install -y --no-install-recommends 53 | fi 54 | 55 | useradd --system --user-group --no-create-home --shell /usr/sbin/nologin build-runner 56 | 57 | # Install ccache 58 | if [ -n "${USE_CCACHE+x}" ]; then 59 | log "Setting up ccache" 60 | apt-get install -y --no-install-recommends ccache 61 | export CCACHE_DIR="${CDEBB_DIR}/ccache_dir" 62 | ccache --zero-stats 63 | chown -R --preserve-root build-runner: "${CDEBB_DIR}/ccache_dir" 64 | fi 65 | 66 | # Make read-write copy of source code 67 | log "Copying source directory" 68 | mkdir "${CDEBB_BUILD_DIR}" 69 | cp -a "${CDEBB_DIR}/source-ro" "${CDEBB_BUILD_DIR}/source" 70 | chown -R --preserve-root build-runner: "${CDEBB_BUILD_DIR}" 71 | 72 | # Reset timestamps 73 | if [ -n "${RESET_TIMESTAMPS+x}" ]; then 74 | log "Resetting timestamps" 75 | SOURCE_DATE_RFC2822=$(dpkg-parsechangelog --file "${CDEBB_BUILD_DIR}/source/debian/changelog" --show-field Date) 76 | find "${CDEBB_BUILD_DIR}/source" -exec touch -m --no-dereference --date="${SOURCE_DATE_RFC2822}" {} +; 77 | fi 78 | 79 | cd "${CDEBB_BUILD_DIR}/source" 80 | 81 | # Install build dependencies 82 | log "Installing build dependencies" 83 | mk-build-deps -ir -t "apt-get -o Debug::pkgProblemResolver=yes -y --no-install-recommends" 84 | 85 | # Build packages 86 | log "Building package with DEB_BUILD_OPTIONS set to '${DEB_BUILD_OPTIONS:-}'" 87 | debuild_args= 88 | # supported since Debian 11 (bullseye) 89 | if dpkg-buildpackage --sanitize-env --help &> /dev/null; then 90 | debuild_args+=' --sanitize-env' 91 | fi 92 | 93 | BUILD_START_TIME="$EPOCHSECONDS" 94 | # supported since Debian 12 (bookworm) 95 | if unshare --map-users 1,1,1000 --help &> /dev/null; then 96 | # shellcheck disable=SC2086 97 | unshare --user --map-root-user --net --map-users 1,1,1000 --map-users 65534,65534,1 --map-groups 1,1,1000 --map-groups 65534,65534,1 --setuid "$(id -u build-runner)" --setgid "$(id -g build-runner)" -- env PATH="/usr/lib/ccache:$PATH" dpkg-buildpackage -rfakeroot -b --no-sign -sa ${debuild_args} 2>&1 | tee "${CDEBB_BUILD_DIR}/build.log" 98 | else 99 | log "unshare(1) does not support --map-users, falling back to runuser(1); build has network access" 100 | # shellcheck disable=SC2086 101 | runuser -u build-runner -- env PATH="/usr/lib/ccache:$PATH" dpkg-buildpackage -rfakeroot -b --no-sign -sa ${debuild_args} 2>&1 | tee "${CDEBB_BUILD_DIR}/build.log" 102 | fi 103 | log "Build completed in $((EPOCHSECONDS - BUILD_START_TIME)) seconds" 104 | 105 | cd / 106 | 107 | if [ -n "${USE_CCACHE+x}" ]; then 108 | log "ccache statistics" 109 | # supported since Debian 12 (bookworm) 110 | if ccache --verbose --help &> /dev/null; then 111 | ccache --show-stats --verbose 112 | else 113 | ccache --show-stats 114 | fi 115 | fi 116 | 117 | # Run Lintian 118 | if [ -n "${RUN_LINTIAN+x}" ]; then 119 | log "Installing Lintian" 120 | apt-get install -y --no-install-recommends lintian 121 | useradd --system --user-group --no-create-home --shell /usr/sbin/nologin lintian-runner 122 | log "+++ Lintian Report Start +++" 123 | # supported since Debian 11 (bullseye) 124 | if lintian --help | grep -w -- '--fail-on\b' &> /dev/null; then 125 | runuser -u lintian-runner -- lintian --display-experimental --info --display-info --pedantic --tag-display-limit 0 --color always --verbose --fail-on none "${CDEBB_BUILD_DIR}"/*.changes 2>&1 | tee "${CDEBB_BUILD_DIR}/lintian.log" 126 | else 127 | runuser -u lintian-runner -- lintian --display-experimental --info --display-info --pedantic --tag-display-limit 0 --color always --verbose "${CDEBB_BUILD_DIR}"/*.changes 2>&1 | tee "${CDEBB_BUILD_DIR}/lintian.log" 128 | fi 129 | log "+++ Lintian Report End +++" 130 | fi 131 | 132 | # Drop color escape sequences from logs 133 | cd "${CDEBB_BUILD_DIR}" 134 | sed -E -e 's/\x1b\[[0-9;]+[mK]//g' --in-place=.color -- *.log 135 | 136 | # Run blhc 137 | if [ -n "${RUN_BLHC+x}" ]; then 138 | log "Installing blhc" 139 | apt-get install -y --no-install-recommends blhc 140 | log "+++ blhc Report Start +++" 141 | blhc --all --color "${CDEBB_BUILD_DIR}/build.log" 2>&1 | tee "${CDEBB_BUILD_DIR}/blhc.log" || true 142 | log "+++ blhc Report End +++" 143 | sed -E -e 's/\x1b\[[0-9;]+[mK]//g' --in-place=.color "${CDEBB_BUILD_DIR}/blhc.log" 144 | fi 145 | 146 | # Copy packages to output dir with user's permissions 147 | if [ -n "${USER+x}" ] && [ -n "${GROUP+x}" ]; then 148 | chown "${USER}:${GROUP}" -- *.deb *.buildinfo *.changes *.log *.log.color 149 | else 150 | chown root:root -- *.deb *.buildinfo *.changes *.log *.log.color 151 | fi 152 | cp -a -- *.deb *.buildinfo *.changes *.log *.log.color "${CDEBB_DIR}/output/" 153 | 154 | log "Generated files:" 155 | ls -l --almost-all --color=always --human-readable --ignore={*.log,*.log.color} "${CDEBB_DIR}/output" 156 | 157 | log "Finished in $((EPOCHSECONDS - CONTAINER_START_TIME)) seconds" 158 | --------------------------------------------------------------------------------