By default, `tar` copies file ownership UID/GID. This works fine when
the build is running in a rootless container, since the source UID/GID
numbers are mapped to 0/0 inside the container. In other scenarios,
though, such as building in a microvm with the source directory on a
shared filesystem, the original numbers are preserved. We need to
explicitly state that the files must be owned by root.
When running inside a QEMU microvm with the source directory shared
via 9pfs, the kernel build process fails
> Error: Could not mmap file: vmlinux
Thus, we need to run the build in a path on a local filesystem. To
support this, the Makefile now supports an `O` option, and all the build
scripts have been adjusted to make use of it as needed.
Since building in a local filesystem would ultimately discard the final
artifacts when the VM terminates, we need yet a different location for
the files we want to keep. The `IMAGESDIR` option can be used to
specify this path. This path can be on a shared filesystem, thus
saving the artifacts outside the microvm.
Several packages end up with circular dependencies, depending on which
Portage profile is selected. The default profiles have a circular
dependency between *sys-libs/pam* and *sys-libs/libcap*. Systemd and
SELinux profiles have even more issues.
We can break the circular dependencies by explicitly building *libcap*
with`USE=-pam` first, which happens to be the default configuration
generated by `crossdev`. Then, we need to switch to a more complete
profile in order to build *glibc* and *util-linux*. At this point, the
build root should be complete enough to build anything without circular
dependencies.
There's really no sense in creating a writable copy of the whole `/etc`
hierarchy at `/run/etc/rw`. Instead, let's just mount overlays at the
paths we want to make writable (which for now is only `/etc/ssh`).
In a "merged-usr" system, `/lib` is a symlink to `/usr/lib`. When
installing *sys-apps/systemd*, Portage checks to ensure this is the
case. If this happens after `make modules_install` is run, `/lib` is
a directory, which causes the installation to fail. To avoid this, we
need to explicitly install the modules into `/usr/lib` so that the
symlink can be created later.
Building the OS is now as simple as running `make` on a Gentoo system.
Interestingly, when `make` is executed as a (grand)child process of
another `make` process, it always prints an `Entering directory ...`
message. This breaks the `make kernelversion` command, by adding
extraneous text to the output.
The *ldconfig.service* fails because `/etc` is not writable and thus
`/etc/ld.so.cache` cannot be generated.
The files specified in the `provision.d` *tmpfiles.d(5)* configuration
are unnecessary, and many of them cannot be created at runtime because
the root filesystem is immutable.
When running inside a rootless Podman container on a SELinux-enabled
host, the `patch` command fails because it cannot copy SELinux labels
from the original file to the patched file. This only happens patching
files that are located in a bind mount.