1#!/usr/bin/env bash
2# SPDX-License-Identifier: LGPL-2.1-or-later
3
4set -ex
5
6info() { echo -e "\033[33;1m$1\033[0m"; }
7fatal() { echo >&2 -e "\033[31;1m$1\033[0m"; exit 1; }
8success() { echo >&2 -e "\033[32;1m$1\033[0m"; }
9
10ARGS=(
11    "--optimization=0"
12    "--optimization=s -Dgnu-efi=true -Defi-cflags=-m32 -Defi-libdir=/usr/lib32"
13    "--optimization=3 -Db_lto=true -Ddns-over-tls=false"
14    "--optimization=3 -Db_lto=false"
15    "--optimization=3 -Ddns-over-tls=openssl"
16    "--optimization=3 -Dfexecve=true -Dstandalone-binaries=true -Dstatic-libsystemd=true -Dstatic-libudev=true"
17    "-Db_ndebug=true"
18)
19PACKAGES=(
20    cryptsetup-bin
21    expect
22    fdisk
23    gettext
24    iputils-ping
25    isc-dhcp-client
26    itstool
27    kbd
28    libblkid-dev
29    libbpf-dev
30    libc6-dev-i386
31    libcap-dev
32    libcurl4-gnutls-dev
33    libfdisk-dev
34    libfido2-dev
35    libgpg-error-dev
36    liblz4-dev
37    liblzma-dev
38    libmicrohttpd-dev
39    libmount-dev
40    libp11-kit-dev
41    libpwquality-dev
42    libqrencode-dev
43    libssl-dev
44    libtss2-dev
45    libxkbcommon-dev
46    libxtables-dev
47    libzstd-dev
48    mount
49    net-tools
50    perl
51    python3-evdev
52    python3-jinja2
53    python3-lxml
54    python3-pip
55    python3-pyparsing
56    python3-setuptools
57    quota
58    strace
59    unifont
60    util-linux
61    zstd
62)
63COMPILER="${COMPILER:?}"
64COMPILER_VERSION="${COMPILER_VERSION:?}"
65LINKER="${LINKER:?}"
66CRYPTOLIB="${CRYPTOLIB:?}"
67RELEASE="$(lsb_release -cs)"
68
69bash -c "echo 'deb-src http://archive.ubuntu.com/ubuntu/ $RELEASE main restricted universe multiverse' >>/etc/apt/sources.list"
70
71# Note: As we use postfixed clang/gcc binaries, we need to override $AR
72#       as well, otherwise meson falls back to ar from binutils which
73#       doesn't work with LTO
74if [[ "$COMPILER" == clang ]]; then
75    CC="clang-$COMPILER_VERSION"
76    CXX="clang++-$COMPILER_VERSION"
77    AR="llvm-ar-$COMPILER_VERSION"
78
79    # ATTOW llvm-11 got into focal-updates, which conflicts with llvm-11
80    # provided by the apt.llvm.org repositories. Let's use the system
81    # llvm package if available in such cases to avoid that.
82    if ! apt install --dry-run "llvm-$COMPILER_VERSION" >/dev/null; then
83        # Latest LLVM stack deb packages provided by https://apt.llvm.org/
84        # Following snippet was partly borrowed from https://apt.llvm.org/llvm.sh
85        wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | gpg --yes --dearmor --output /usr/share/keyrings/apt-llvm-org.gpg
86        printf "deb [signed-by=/usr/share/keyrings/apt-llvm-org.gpg] http://apt.llvm.org/%s/   llvm-toolchain-%s-%s  main\n" \
87               "$RELEASE" "$RELEASE" "$COMPILER_VERSION" >/etc/apt/sources.list.d/llvm-toolchain.list
88        PACKAGES+=("clang-$COMPILER_VERSION" "lldb-$COMPILER_VERSION" "lld-$COMPILER_VERSION" "clangd-$COMPILER_VERSION")
89    fi
90elif [[ "$COMPILER" == gcc ]]; then
91    CC="gcc-$COMPILER_VERSION"
92    CXX="g++-$COMPILER_VERSION"
93    AR="gcc-ar-$COMPILER_VERSION"
94    # Latest gcc stack deb packages provided by
95    # https://launchpad.net/~ubuntu-toolchain-r/+archive/ubuntu/test
96    add-apt-repository -y ppa:ubuntu-toolchain-r/test
97    PACKAGES+=("gcc-$COMPILER_VERSION" "gcc-$COMPILER_VERSION-multilib")
98else
99    fatal "Unknown compiler: $COMPILER"
100fi
101
102# PPA with some newer build dependencies (like zstd)
103add-apt-repository -y ppa:upstream-systemd-ci/systemd-ci
104apt-get -y update
105apt-get -y build-dep systemd
106apt-get -y install "${PACKAGES[@]}"
107# Install more or less recent meson and ninja with pip, since the distro versions don't
108# always support all the features we need (like --optimization=). Since the build-dep
109# command above installs the distro versions, let's install the pip ones just
110# locally and add the local bin directory to the $PATH.
111pip3 install --user -r .github/workflows/requirements.txt --require-hashes
112export PATH="$HOME/.local/bin:$PATH"
113
114$CC --version
115meson --version
116ninja --version
117
118for args in "${ARGS[@]}"; do
119    SECONDS=0
120
121    # meson fails with
122    #   src/boot/efi/meson.build:52: WARNING: Not using lld as efi-ld, falling back to bfd
123    #   src/boot/efi/meson.build:52:16: ERROR: Fatal warnings enabled, aborting
124    # when LINKER is set to lld so let's just not turn meson warnings into errors with lld
125    # to make sure that the build systemd can pick up the correct efi-ld linker automatically.
126
127    # The install_tag feature introduced in 0.60 causes meson to fail with fatal-meson-warnings
128    # "Project targeting '>= 0.53.2' but tried to use feature introduced in '0.60.0': install_tag arg in custom_target"
129    # It can be safely removed from the CI since it isn't actually used anywhere to test anything.
130    find . -type f -name meson.build -exec sed -i '/install_tag/d' '{}' '+'
131    if [[ "$LINKER" != lld ]]; then
132        additional_meson_args="--fatal-meson-warnings"
133    fi
134    info "Checking build with $args"
135    # shellcheck disable=SC2086
136    if ! AR="$AR" \
137         CC="$CC" CC_LD="$LINKER" CFLAGS="-Werror" \
138         CXX="$CXX" CXX_LD="$LINKER" CXXFLAGS="-Werror" \
139         meson -Dtests=unsafe -Dslow-tests=true -Dfuzz-tests=true --werror \
140               -Dnobody-group=nogroup $additional_meson_args \
141               -Dcryptolib="${CRYPTOLIB:?}" $args build; then
142
143        cat build/meson-logs/meson-log.txt
144        fatal "meson failed with $args"
145    fi
146
147    if ! meson compile -C build -v; then
148        fatal "'meson compile' failed with $args"
149    fi
150
151    for loader in build/src/boot/efi/*.efi; do
152        if sbverify --list "$loader" |& grep -q "gap in section table"; then
153            fatal "$loader: Gaps found in section table"
154        fi
155    done
156
157    git clean -dxf
158
159    success "Build with $args passed in $SECONDS seconds"
160done
161