]>
Commit | Line | Data |
---|---|---|
7629744a | 1 | #!/bin/sh |
8f5bcd61 | 2 | # SPDX-License-Identifier: LGPL-2.1-or-later |
1394a3ec | 3 | set -e |
1b0ff615 | 4 | |
1b0ff615 LP |
5 | # This is a build script for OS image generation using mkosi (https://github.com/systemd/mkosi). |
6 | # Simply invoke "mkosi" in the project directory to build an OS image. | |
7 | ||
69d638e6 DDM |
8 | ASAN_OPTIONS=strict_string_checks=1:detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1:disable_coredump=0:use_madv_dontdump=1 |
9 | UBSAN_OPTIONS=print_stacktrace=1:print_summary=1:halt_on_error=1 | |
10 | ||
7211773a LP |
11 | # On Fedora "ld" is (unfortunately — if you ask me) managed via |
12 | # "alternatives". Since we'd like to support building images in environments | |
13 | # with only /usr/ around (e.g. mkosi's UsrOnly=1 option), we have the problem | |
14 | # that /usr/bin/ld is a symlink that points to a non-existing file in | |
15 | # /etc/alternative/ in this mode. Let's work around this for now by manually | |
16 | # redirect "ld" to "ld.bfd", i.e. circumventing the /usr/bin/ld symlink. | |
068d1338 | 17 | if [ ! -x /usr/bin/ld ] && [ -x /usr/bin/ld.bfd ]; then |
7211773a LP |
18 | mkdir -p "$HOME"/bin |
19 | ln -s /usr/bin/ld.bfd "$HOME"/bin/ld | |
20 | PATH="$HOME/bin:$PATH" | |
21 | fi | |
22 | ||
70e760e3 LP |
23 | # If mkosi.builddir/ exists mkosi will set $BUILDDIR to it, let's then use it |
24 | # as out-of-tree build dir. Otherwise, let's make up our own builddir. | |
84a4af2c DDM |
25 | [ -z "$BUILDDIR" ] && BUILDDIR="$PWD"/build |
26 | ||
27 | # Let's make sure we're using stuff from the build directory first if available there. | |
28 | PATH="$BUILDDIR:$PATH" | |
29 | export PATH | |
70e760e3 | 30 | |
2ea09665 FB |
31 | # Meson uses Python 3 and requires a locale with an UTF-8 character map. |
32 | # Not running under UTF-8 makes the `ninja test` step break with a CodecError. | |
33 | # So let's ensure we're running under UTF-8. | |
34 | # | |
35 | # If our current locale already is UTF-8, then we don't need to do anything: | |
068d1338 | 36 | if [ "$(locale charmap 2>/dev/null)" != "UTF-8" ] ; then |
2ea09665 FB |
37 | # Try using C.UTF-8 locale, if available. This locale is not shipped |
38 | # by upstream glibc, so it's not available in all distros. | |
39 | # (In particular, it's not available in Arch Linux.) | |
5e577e17 DDM |
40 | if locale -a | grep -q -E "C.UTF-8|C.utf8"; then |
41 | export LC_CTYPE=C.UTF-8 | |
42 | # Finally, try something like en_US.UTF-8, which should be | |
43 | # available in Arch Linux, but is not present in Debian's | |
44 | # minimal image in our mkosi config. | |
45 | elif locale -a | grep -q en_US.utf8; then | |
2ea09665 | 46 | export LC_CTYPE=en_US.UTF-8 |
5e577e17 DDM |
47 | else |
48 | # If nothing works, fail early. | |
49 | echo "*** Could not find a valid locale that supports UTF-8. ***" >&2 | |
50 | exit 1 | |
2ea09665 FB |
51 | fi |
52 | fi | |
9400405b | 53 | |
37d35150 DDM |
54 | # The bpftool script shipped by Ubuntu tries to find the actual program to run via querying `uname -r` and |
55 | # using the current kernel version. This obviously doesn't work in containers. As a workaround, we override | |
56 | # the ubuntu script with a symlink to the first bpftool program we can find. | |
57 | for bpftool in /usr/lib/linux-tools/*/bpftool; do | |
58 | [ -x "$bpftool" ] || continue | |
84a4af2c | 59 | ln -sf "$bpftool" "$BUILDDIR"/bpftool |
37d35150 DDM |
60 | break |
61 | done | |
62 | ||
6afeac1d DDM |
63 | # CentOS Stream 8 includes bpftool 4.18.0 which is lower than what we need. However, they've backported the |
64 | # specific feature we need ("gen skeleton") to this version, so we replace bpftool with a script that reports | |
65 | # version 5.6.0 to satisfy meson which makes bpf work on CentOS Stream 8 as well. | |
66 | if [ "$(grep '^ID=' /etc/os-release)" = "ID=\"centos\"" ] && [ "$(grep '^VERSION=' /etc/os-release)" = "VERSION=\"8\"" ]; then | |
84a4af2c | 67 | cat >"$BUILDDIR"/bpftool <<EOF |
6afeac1d DDM |
68 | #!/bin/sh |
69 | if [ "\$1" = --version ]; then | |
70 | echo 5.6.0 | |
71 | else | |
84a4af2c | 72 | exec /usr/sbin/bpftool \$@ |
6afeac1d DDM |
73 | fi |
74 | EOF | |
84a4af2c | 75 | chmod +x "$BUILDDIR"/bpftool |
6afeac1d DDM |
76 | fi |
77 | ||
c81a2569 | 78 | if [ ! -f "$BUILDDIR"/build.ninja ] ; then |
068d1338 | 79 | sysvinit_path=$(realpath /etc/init.d) |
8da0592c | 80 | |
068d1338 | 81 | init_path=$(realpath /sbin/init 2>/dev/null) |
bac567a5 | 82 | if [ -z "$init_path" ] ; then |
2401c9ac | 83 | rootprefix="" |
bac567a5 | 84 | else |
2401c9ac DDM |
85 | rootprefix=${init_path%/lib/systemd/systemd} |
86 | rootprefix=/${rootprefix#/} | |
bac567a5 MK |
87 | fi |
88 | ||
bbb40c4e LB |
89 | # On debian-like systems the library directory is not /usr/lib64 but /usr/lib/<arch-triplet>/. |
90 | # It is important to use the right one especially for cryptsetup plugins, otherwise they will be | |
91 | # installed in the wrong directory and not be found by cryptsetup. Assume native build. | |
92 | if grep -q -e "ID=debian" -e "ID_LIKE=debian" /etc/os-release && command -v dpkg 2>/dev/null; then | |
93 | LIBDIR="-Drootlibdir=/usr/lib/$(dpkg-architecture -qDEB_HOST_MULTIARCH)" | |
94 | PAMDIR="-Dpamlibdir=/usr/lib/$(dpkg-architecture -qDEB_HOST_MULTIARCH)/security" | |
95 | fi | |
96 | ||
97 | # Cannot quote $LIBDIR and $PAMDIR, because they may be empty, and meson will fail. | |
98 | # shellcheck disable=SC2086 | |
8c21a0c9 | 99 | meson setup "$BUILDDIR" \ |
bbb40c4e LB |
100 | ${LIBDIR:-} \ |
101 | ${PAMDIR:-} \ | |
db52af5a DDM |
102 | -D "sysvinit-path=$sysvinit_path" \ |
103 | -D "rootprefix=$rootprefix" \ | |
104 | -D man=false \ | |
ef1bd234 | 105 | -D translations=false \ |
c0daae3a | 106 | -D version-tag="${VERSION_TAG}" \ |
69d638e6 | 107 | -D mode=developer \ |
819a2502 | 108 | -D b_sanitize="${SANITIZERS:-none}" \ |
37d35150 DDM |
109 | -D install-tests=true \ |
110 | -D tests=unsafe \ | |
111 | -D slow-tests=true \ | |
112 | -D utmp=true \ | |
113 | -D hibernate=true \ | |
114 | -D ldconfig=true \ | |
115 | -D resolve=true \ | |
116 | -D efi=true \ | |
117 | -D tpm=true \ | |
118 | -D environment-d=true \ | |
119 | -D binfmt=true \ | |
120 | -D repart=true \ | |
121 | -D sysupdate=true \ | |
122 | -D coredump=true \ | |
123 | -D pstore=true \ | |
124 | -D oomd=true \ | |
125 | -D logind=true \ | |
126 | -D hostnamed=true \ | |
127 | -D localed=true \ | |
128 | -D machined=true \ | |
129 | -D portabled=true \ | |
130 | -D sysext=true \ | |
131 | -D userdb=true \ | |
132 | -D homed=true \ | |
133 | -D networkd=true \ | |
134 | -D timedated=true \ | |
135 | -D timesyncd=true \ | |
136 | -D remote=true \ | |
137 | -D nss-myhostname=true \ | |
138 | -D nss-mymachines=true \ | |
139 | -D nss-resolve=true \ | |
140 | -D nss-systemd=true \ | |
141 | -D firstboot=true \ | |
142 | -D randomseed=true \ | |
143 | -D backlight=true \ | |
144 | -D vconsole=true \ | |
145 | -D quotacheck=true \ | |
146 | -D sysusers=true \ | |
147 | -D tmpfiles=true \ | |
148 | -D importd=true \ | |
149 | -D hwdb=true \ | |
150 | -D rfkill=true \ | |
151 | -D xdg-autostart=true \ | |
152 | -D translations=true \ | |
153 | -D polkit=true \ | |
154 | -D acl=true \ | |
155 | -D audit=true \ | |
156 | -D blkid=true \ | |
157 | -D fdisk=true \ | |
158 | -D kmod=true \ | |
159 | -D pam=true \ | |
160 | -D pwquality=true \ | |
161 | -D microhttpd=true \ | |
162 | -D libcryptsetup=true \ | |
163 | -D libcurl=true \ | |
164 | -D idn=true \ | |
165 | -D libidn2=true \ | |
166 | -D qrencode=true \ | |
167 | -D gcrypt=true \ | |
168 | -D gnutls=true \ | |
169 | -D openssl=true \ | |
170 | -D cryptolib=openssl \ | |
171 | -D p11kit=true \ | |
172 | -D libfido2=true \ | |
173 | -D tpm2=true \ | |
174 | -D elfutils=true \ | |
175 | -D zstd=true \ | |
176 | -D xkbcommon=true \ | |
177 | -D pcre2=true \ | |
178 | -D glib=true \ | |
179 | -D dbus=true \ | |
180 | -D gnu-efi=true \ | |
181 | -D kernel-install=true \ | |
182 | -D analyze=true \ | |
c8943ce8 DDM |
183 | -D bpf-framework=true \ |
184 | -D ukify=true | |
c82ce4f2 LP |
185 | fi |
186 | ||
c3e2dc71 | 187 | cd "$BUILDDIR" |
44bc7f4f | 188 | ninja "$@" |
ff549982 | 189 | if [ "$WITH_TESTS" = 1 ] ; then |
69d638e6 DDM |
190 | if [ -n "$SANITIZERS" ]; then |
191 | export ASAN_OPTIONS="$ASAN_OPTIONS" | |
192 | export UBSAN_OPTIONS="$UBSAN_OPTIONS" | |
193 | TIMEOUT_MULTIPLIER=3 | |
194 | else | |
195 | TIMEOUT_MULTIPLIER=1 | |
196 | fi | |
197 | ||
de9b57a1 | 198 | meson test --print-errorlogs --timeout-multiplier=$TIMEOUT_MULTIPLIER |
ff549982 | 199 | fi |
c3e2dc71 | 200 | cd "$SRCDIR" |
fe2b7631 | 201 | |
fc4b61d0 | 202 | meson install -C "$BUILDDIR" --quiet --no-rebuild --only-changed |
6344a7eb | 203 | |
70e760e3 | 204 | mkdir -p "$DESTDIR"/etc |
6344a7eb | 205 | |
068d1338 | 206 | cat >"$DESTDIR"/etc/issue <<EOF |
6344a7eb LP |
207 | \S (built from systemd tree) |
208 | Kernel \r on an \m (\l) | |
209 | ||
210 | EOF | |
d10ba83a | 211 | |
f533cda5 | 212 | if [ -n "$IMAGE_ID" ] ; then |
2401c9ac DDM |
213 | mkdir -p "$DESTDIR"/usr/lib |
214 | sed -n \ | |
215 | -e '/^IMAGE_ID=/!p' \ | |
216 | -e "\$aIMAGE_ID=$IMAGE_ID" <"/usr/lib/os-release" >"${DESTDIR}/usr/lib/os-release" | |
f533cda5 | 217 | |
2401c9ac | 218 | OSRELEASEFILE="$DESTDIR"/usr/lib/os-release |
f533cda5 | 219 | else |
2401c9ac | 220 | OSRELEASEFILE=/usr/lib/os-release |
f533cda5 LP |
221 | fi |
222 | ||
223 | ||
224 | if [ -n "$IMAGE_VERSION" ] ; then | |
2401c9ac DDM |
225 | mkdir -p "$DESTDIR"/usr/lib |
226 | sed -n \ | |
227 | -e '/^IMAGE_VERSION=/!p' \ | |
228 | -e "\$aIMAGE_VERSION=$IMAGE_VERSION" <$OSRELEASEFILE >"/tmp/os-release.tmp" | |
f533cda5 | 229 | |
f7ad9650 | 230 | cat /tmp/os-release.tmp >"$DESTDIR"/usr/lib/os-release |
2401c9ac | 231 | rm /tmp/os-release.tmp |
f533cda5 | 232 | fi |
24acd406 FS |
233 | |
234 | # If $CI_BUILD is set, copy over the CI service which executes a service check | |
235 | # after boot and then shuts down the machine | |
236 | if [ -n "$CI_BUILD" ]; then | |
2401c9ac DDM |
237 | mkdir -p "$DESTDIR/usr/lib/systemd/system" |
238 | cp -v "$SRCDIR/test/mkosi-check-and-shutdown.service" "$DESTDIR/usr/lib/systemd/system/mkosi-check-and-shutdown.service" | |
239 | cp -v "$SRCDIR/test/mkosi-check-and-shutdown.sh" "$DESTDIR/usr/lib/systemd/mkosi-check-and-shutdown.sh" | |
240 | chmod +x "$DESTDIR/usr/lib/systemd/mkosi-check-and-shutdown.sh" | |
24acd406 | 241 | fi |
69d638e6 DDM |
242 | |
243 | if [ -n "$SANITIZERS" ]; then | |
ac3326df | 244 | LD_PRELOAD=$(ldd "$BUILDDIR"/systemd | grep libasan.so | awk '{print $3}') |
69d638e6 DDM |
245 | |
246 | mkdir -p "$DESTDIR/etc/systemd/system.conf.d" | |
247 | ||
f7ad9650 | 248 | cat >"$DESTDIR/etc/systemd/system.conf.d/10-asan.conf" <<EOF |
69d638e6 DDM |
249 | [Manager] |
250 | ManagerEnvironment=ASAN_OPTIONS=$ASAN_OPTIONS\\ | |
251 | UBSAN_OPTIONS=$UBSAN_OPTIONS\\ | |
252 | LD_PRELOAD=$LD_PRELOAD | |
253 | DefaultEnvironment=ASAN_OPTIONS=$ASAN_OPTIONS\\ | |
254 | UBSAN_OPTIONS=$UBSAN_OPTIONS\\ | |
255 | LD_PRELOAD=$LD_PRELOAD | |
256 | EOF | |
257 | ||
258 | # ASAN logs to stderr by default. However, journald's stderr is connected to /dev/null, so we lose | |
259 | # all the ASAN logs. To rectify that, let's connect journald's stdout to the console so that any | |
260 | # sanitizer failures appear directly on the user's console. | |
261 | mkdir -p "$DESTDIR/etc/systemd/system/systemd-journald.service.d" | |
262 | ||
f7ad9650 | 263 | cat >"$DESTDIR/etc/systemd/system/systemd-journald.service.d/10-stdout-tty.conf" <<EOF |
69d638e6 DDM |
264 | [Service] |
265 | StandardOutput=tty | |
266 | EOF | |
267 | ||
268 | # Both systemd and util-linux's login call vhangup() on /dev/console which disconnects all users. | |
269 | # This means systemd-journald can't log to /dev/console even if we configure `StandardOutput=tty`. As | |
270 | # a workaround, we modify console-getty.service to disable systemd's vhangup() and disallow login | |
271 | # from calling vhangup() so that journald's ASAN logs correctly end up in the console. | |
272 | ||
273 | mkdir -p "$DESTDIR/etc/systemd/system/console-getty.service.d" | |
274 | ||
f7ad9650 | 275 | cat >"$DESTDIR/etc/systemd/system/console-getty.service.d/10-no-vhangup.conf" <<EOF |
69d638e6 DDM |
276 | [Service] |
277 | TTYVHangup=no | |
278 | CapabilityBoundingSet=~CAP_SYS_TTY_CONFIG | |
279 | EOF | |
280 | fi | |
37d35150 DDM |
281 | |
282 | # Make sure services aren't enabled by default on Debian/Ubuntu. | |
283 | mkdir -p "$DESTDIR/etc/systemd/system-preset" | |
f7ad9650 | 284 | echo "disable *" >"$DESTDIR/etc/systemd/system-preset/99-mkosi.preset" |
d12e9bdc DDM |
285 | |
286 | if [ -d mkosi.kernel/ ]; then | |
287 | cd "$SRCDIR/mkosi.kernel" | |
288 | mkdir -p "$BUILDDIR/mkosi.kernel" | |
289 | ||
6c2ff4a0 DDM |
290 | # Ensure fast incremental builds by fixating these values which usually change for each build. |
291 | export KBUILD_BUILD_TIMESTAMP="Fri Jun 5 15:58:00 CEST 2015" | |
292 | export KBUILD_BUILD_HOST="mkosi" | |
293 | ||
37b56a79 DDM |
294 | scripts/kconfig/merge_config.sh -O "$BUILDDIR/mkosi.kernel" \ |
295 | ../mkosi.kernel.config \ | |
296 | tools/testing/selftests/bpf/config.x86_64 \ | |
297 | tools/testing/selftests/bpf/config | |
d12e9bdc DDM |
298 | |
299 | make O="$BUILDDIR/mkosi.kernel" -j "$(nproc)" | |
300 | ||
ac3326df | 301 | KERNEL_RELEASE=$(make O="$BUILDDIR"/mkosi.kernel -s kernelrelease) |
d12e9bdc DDM |
302 | mkdir -p "$DESTDIR/usr/lib/modules/$KERNEL_RELEASE" |
303 | make O="$BUILDDIR/mkosi.kernel" INSTALL_MOD_PATH="$DESTDIR/usr" modules_install | |
304 | make O="$BUILDDIR/mkosi.kernel" INSTALL_PATH="$DESTDIR/usr/lib/modules/$KERNEL_RELEASE" install | |
6c2ff4a0 DDM |
305 | mkdir -p "$DESTDIR/usr/lib/kernel/selftests" |
306 | make -C tools/testing/selftests -j "$(nproc)" O="$BUILDDIR/mkosi.kernel" KSFT_INSTALL_PATH="$DESTDIR/usr/lib/kernel/selftests" SKIP_TARGETS="" install | |
31aba196 DDM |
307 | |
308 | ln -sf /usr/lib/kernel/selftests/bpf/bpftool "$DESTDIR/usr/bin/bpftool" | |
d12e9bdc | 309 | fi |