Software written in C++ typically depends on `libstdc++.so.6` and
`libgcc_s.so.1`. These library dependencies are implicit, as Gentoo
expects GCC to be installed as part of the _@system_ set. Since that
set does not get installed in the target root, anything that depends on
those libraries will not function.
Rather than install _sys-devel/gcc_ in the target environment to get
those libraries, we can copy ones built by `crossdev` manually. This
way, we do not end up with a full C compiler and development toolchain
in the target environment, while still making the libraries available
for applications that need them.
Since installing _sys-libs/glibc_ in the crossdev root overwrites the
libraries built by crossdev, Portage records the latter as needing to be
protected. This results in _everything_ being pulled in to
@preserved-rebuild, which ultimately does nothing since the preserved
library is never replaced. To avoid this pointlessness, we need to
disable the _preserve-libs_ feature when reinstalling _glibc_.
We also disable _protect-owned_ to avoid spam from Portage when
initially overwriting the libraries and headers in the crossdev root.
`ldconfig` has started complaining that it needs a configuration file
when using the `-r` argument:
> /mnt/gentoo/usr/sbin/ldconfig: need absolute file name for
> configuration file when using -r
_crossdev_ sets `ACCEPT_KEYWORDS="${ARCH} ~${ARCH}" by default, even
when run with `--stable`. This can cause conflicts when the host system
does not accept ~arch, and may not be desirable anyway. Projects that
want to use ~arch can set it in their own `make.conf`.
The _u-boot_ package does not have any stable keywords, so we have to
explicitly accept it.
This will silence warnings from `mount` about `/etc/fstab` having
changed since the last time the `systemd-fstab-generator` was run. It's
not true, since it's immutable, but the warning comes up on Raspberry
Pis without an RTC.
For whatever reason, _systemd-networkd_ does not resepect the DNS domain
search list sent by the DHCP server by default. This means single-label
name lookups will fail in most cases.
We don't want to reinstall _baselayout_ when its USE flags change.
Indeed, USE flag changes are expected, because we first install it with
USE=build, but only temporarily. Once the initial symlinks for
merged-usr are in place, it can be reinstalled without that flag. We
don't need to keep reinstalling and toggling between states, so we
ignore USE flag changes for the first pass.
Projects can now include a `customize.sh` script. If present, this
script will be run after the root filesystem hierarchy has been created,
but before the image is captured. This allows projects to apply
additional customizations beyond adding or removing files.
The project configuration file can now contain an optional `rootflags`
variable. If specified, this variable will be used to set the GRUB
environment variable of the same name. The value will be appended to
the kernel command line.
The _app-alternatives/awk_ package installs a symlink to `busybox` for
for `awk`. Using this package instead of `busybox.symlinks` allows
it to satisfy other packages that depend on a generic `awk`
implementation.
Using the host's `ldconfig` doesn't work, as it only considers libraries
for the same machine type as itself. THus, we have to execute the
target's copy, which means running it via QEMU userspace emulation.
The `-o` argument to `xargs` tells it to reopen a TTY to pass to the
spawned process's standard input. If there is no controlling TTY, this
will fail. There's no reason to do this anyway, so let's avoid it.
_sys-apps/util-linux_ first must be built (in the prepare stage) with
`USE=build` and then reinstalled later without that flag. We can save
time in the second step by using binary packages if they are already
available (i.e. from a previous build).
The _sys-apps/baselayout_ package handles initializing a new filesystem
hierarchy. With `USE=build`, it will create the appropriate symlinks in
`/` for a merged-usr tree.
Instead of requiring every Aimee OS project to carry around a full
Portage configuration tree, including patches, saved configurations,
etc., we now support a "layered" configuration system. Aimee OS core
provides a base configuration that includes all settings, patches, etc.
common for all Aimee OS projects. At build time, this base
configuration is combined with the project's configuration, which need
only specify USE flags, etc. for that specific project. This should
make maintenance across multiple projects easier, and make getting a new
project started _significantly_ less cumbersome.
GRUB is needed for all machines that run Aimee OS. The Raspberry Pi
firmware, of course, is only needed to run Aimee OS on a Raspberry Pi.
Thus, the former should be listed in the global `build.packages` file,
while the latter should be built only for projects targeting Raspberry
Pis.
The 17.0 profiles are deprecated. Let's use the project's configured
profile at this stage, so as not to have to rebuild stuff because we
change USE flages, etc. once we set it later.
The modern profiles are all "merged-usr" by default now, so we do not
need that explicit step anymore.
Since this is the last vestige of the "host" Portage configuration
directory, we can remove it entirely by setting `USE=symlink` as an
environment variable. This should be safe, since there are not many
other packages besides kernel sources that use this USE flag, and
they're not likely to be pulled in with this `emerge` invocation.
`build.packages`, `installonly.packages`, and `busybox.symlinks` are now
optional in the `$CONFIGDIR`. If they do exist, they are combined with
the same files in the Aimee OS source.
None of these are necessary anymore. They do not apply cleanly to
current versions of ebuilds in Gentoo's repository, causing builds to
fail.
Going forward, I think it will be better to maintain patched ebuilds in
the Aimee OS repository, rather than patching them at build time.
Instead of building host tools along with the target packages, we now
rely on the build container to contain everything we need to build Aimee
OS. The _aimee-os.org/build/build-{target}_ image (tentative name)
includes a cross-compilation toolchain and all of the tools that were
originally listed in `host-tools.packages`.
Projects can now set a `buildvm` variable in their `config` file to
specify a unique name for their build VMs. This allows multiple
projects to have running VMs simultaneously.
If a project does not provide a name, the build VM will be called
`aimeebuild`.
The default SELinux policy does not allow passing generic USB devices
and unallocated TTYs to containers. This prevents the Zigbee and ZWave
USB dongles from being usable by their respective container processes.
`systemd-network-generator`, which parses network configuration from the
kernel command line and generates configuration for *systemd-networkd*,
creates a configuration file with priority 90. This conflicts with our
default network configuration at the same priority, so the configuration
from the kernel command line never gets used. By reducing our default
priority to 95, we ensure that the generated configuration file is read
first and thus overrides the defaults.
The `semanage.sh` script starts an interactive shell in an alternate
mount namespace where `/etc/selinux` and `/var/lib/selinux` are
bind-mounted from the target filesystem. This allows SELinux management
commands like `setsebool`, `semodule, `semanage`, etc. to work on the
target policy, since not all of them directly support working on an
alternate policy.
Very large packages cannot be built with `PORTAGE_TMPDIR` on a tmpfs
mount, unless the VM has a tremendous amount of RAM. The performance
improvement is negligible anyway, so let's not bother.
It turns out that QEMU microvms have a very limited number of I/O ports
available for e.g. attached disks and shared filesystems. To conserve
ports, we'll use a single volume for both distfiles and binpkgs cache
directories.
The `ocivm.sh` script mounts the source directory at `/tmp/src`, since
we use `/tmp/build` as the output directory. For consistency, the
`start-container.sh` script, although it's mostly unused anymore, now
does the same.
`genimage` does not align partitions appropriately by default, but
simply packs them one-after-another based on their size. This is easy
enough to fix by setting the `align` property in the `hdimage` block.
These SELinux policy rules allow containers to log directly to
syslog/the systemd journal via the `/dev/log` socket. To enable this,
simply mount the socket into a container's mount namespace, e.g. `-v
/dev/log:/dev/log`.
When creating writable paths in the `/etc` subvolume, the `setup_etc`
function needs to create intermediate directories before copying
existing files from the root filesystem. Without this step, `cp` will
fail with a "no such file or directory" error, referring to the
destination path.