sys-kernel/coreos-modules: Install external mod build files with script

The kernel now includes a script for installing the files needed to
build out-of-tree modules, rendering our existing code obsolete. The
layout is different, but we were following Ubuntu's non-standard layout
when there was no need to. Ubuntu's approach is seemingly designed to
save space by symlinking common files across different platforms, but
Flatcar doesn't need to do this.

More importantly, our previous approach relied on a kernel patch we have
carried for years that no longer applies from v6.13. The patch cannot
simply be reworked as the underlying mechanism has changed.

This clears the last major blocker for the arm64 SDK as the previous
approach also relied on implicit execution by QEMU.

There has been concern that this may break compatibility with some
modules, but I have not seen any issues in practise. I have symlinked
`source` to `build` even though we don't install the full kernel sources
because this is what Fedora does, and it makes the layout resemble
Ubuntu a little more. Should any issues arise, I will gladly work with
upstreams to resolve them or otherwise make adjustments.

Signed-off-by: James Le Cuirot <jlecuirot@microsoft.com>
Signed-off-by: Mathieu Tortuyaux <mtortuyaux@microsoft.com>
This commit is contained in:
Mathieu Tortuyaux 2026-03-18 11:14:11 +01:00
parent 81dcbb38e6
commit 2d3af88164
No known key found for this signature in database
GPG Key ID: AC5CCFB52545D9B8
3 changed files with 15 additions and 102 deletions

View File

@ -0,0 +1 @@
- The way that files for building custom kernel modules are installed has changed from a Ubuntu-inspired method to the standard upstream kernel method. In the unlikely event that this breaks your module builds, please let the Flatcar team know immediately.

View File

@ -117,10 +117,10 @@ kmake() {
if gcc-specs-pie; then
kernel_cflags="-nopie -fstack-check=no ${kernel_cflags}"
fi
emake "--directory=${S}/source" \
emake "--directory=${KERNEL_DIR}" \
ARCH="${kernel_arch}" \
CROSS_COMPILE="${CHOST}-" \
KBUILD_OUTPUT="../build" \
KBUILD_OUTPUT="${S}/build" \
KCFLAGS="${kernel_cflags}" \
LDFLAGS="" \
"V=1" \
@ -184,85 +184,6 @@ shred_keys() {
cp certs/modules.pub.pem "${sig_key}" || die
}
# Populate /lib/modules/$(uname -r)/{build,source}
install_build_source() {
local kernel_arch=$(tc-arch-kernel)
local host_kernel_arch=$(tc-ninja_magic_to_arch kern "${CBUILD}")
# NOTE: We have to get ${archabspaths} before removing symlinks under
# /usr/lib/modules. However, do not exclude "dt-bindings" for now,
# as it looks architecture-independent.
local archabspaths=($(ls -1d ${D}/usr/lib/modules/${KV_FULL}/source/scripts/dtc/include-prefixes/* \
| grep -v dt-bindings ))
# remove the broken symlinks referencing $ROOT
rm "${D}/usr/lib/modules/${KV_FULL}/build" || die
# Compose list of architectures to be excluded from the kernel modules
# tree in the final image. It is an array to be used as a pattern for
# grep command below at the end of "find source/scripts" command for
# fetching kernel modules list, e.g.:
# find source/scripts -follow -print \
# | grep -E -v -w "include-prefixes/arc|include-prefixes/xtensa"
declare -a excarchlist
local excarchstr
for apath in "${archabspaths[@]}"; do
local arch
arch=$(basename "${apath}")
if [[ "${arch}" != "${kernel_arch}" ]]; then
excarchlist+=("include-prefixes/${arch}")
# Do not append delimiter '|' in case of the last element.
if [[ "${apath}" != "${archabspaths[-1]}" ]]; then
excarchlist+=("|")
fi
fi
done
# Remove every whitespace from the grep pattern string, to make pattern
# matching work well.
excarchstr=$(echo "${excarchlist[@]}" | sed -e 's/[[:space:]]*//g')
# Install a stripped source for out-of-tree module builds (Debian-derived)
#
# NOTE: we need to exclude unsupported architectures from source/scripts,
# to prevent the final image from having unnecessary directories under
# /usr/lib/modules/${KV_FULL}/source/scripts/dtc/include-prefixes.
# The grep must run with "-w" to exclude exact patterns like either arm
# or arm64.
{
echo source/Makefile
find source/arch/${host_kernel_arch} -follow -maxdepth 1 -name 'Makefile*' -print
find source/arch/${kernel_arch} -follow -maxdepth 1 -name 'Makefile*' -print
find source/arch/${kernel_arch} -follow \( -name 'module.lds' -o -name 'Kbuild.platforms' -o -name 'Platform' \) -print
find $(find source/arch/${kernel_arch} -follow \( -name include -o -name scripts \) -follow -type d -print) -print
find source/include -follow -print
find source/scripts -follow -print | grep -E -v -w "${excarchstr}"
find build/ -print
} | cpio -pd \
--preserve-modification-time \
--owner=root:root \
--dereference \
"${D}/usr/lib/modules/${KV_FULL}" || die
# ./build/source is a symbolic link so cpio ends up creating an empty dir.
# Restore the symlink.
pushd "${D}/usr/lib/modules/${KV_FULL}"
rmdir build/source || die
ln -sr source build || die
# Symlink includes into the build directory to resemble Ubuntu's /lib/modules
# layout. This lets the Nvidia driver build when passing SYSSRC=/lib/modules/../build
# instead of requiring SYSOUT/SYSSRC.
{
find source/include -mindepth 1 -maxdepth 1 -type d
find source/arch/${kernel_arch}/include -mindepth 1 -maxdepth 1 -type d
} | while read src; do
dst="${src/source/build}"
ln -sr "${src}" "${dst}" || die
done || die
popd
}
coreos-kernel_pkg_pretend() {
[[ "${MERGE_TYPE}" == binary ]] && return
@ -280,10 +201,7 @@ coreos-kernel_pkg_setup() {
}
coreos-kernel_src_unpack() {
# we more or less reproduce the layout in /lib/modules/$(uname -r)/
mkdir -p "${S}/build" || die
mkdir -p "${S}/source" || die
ln -s "${KERNEL_DIR}"/* "${S}/source/" || die
}
coreos-kernel_src_configure() {

View File

@ -35,34 +35,28 @@ src_compile() {
}
src_install() {
local build="lib/modules/${KV_FULL}/build"
# Install modules to /usr, assuming USE=symlink-usr
# Install firmware to a temporary (bogus) location.
# The linux-firmware package will be used instead.
# Stripping must be done here, not portage, to preserve sigs.
kmake INSTALL_MOD_PATH="${D}/usr" \
kmake INSTALL_MOD_PATH="${ED}/usr" \
INSTALL_MOD_STRIP="--strip-debug" \
INSTALL_FW_PATH="${T}/fw" \
modules_install
# Install to /usr/lib/debug with debug symbols intact
kmake INSTALL_MOD_PATH="${D}/usr/lib/debug/usr" \
INSTALL_FW_PATH="${T}/fw" \
kmake INSTALL_MOD_PATH="${ED}/usr/lib/debug/usr" \
modules_install
rm "${D}/usr/lib/debug/usr/lib/modules/${KV_FULL}/"modules.* || die
rm "${D}/usr/lib/debug/usr/lib/modules/${KV_FULL}/build" || die
rm "${ED}/usr/lib/debug/usr/lib/modules/${KV_FULL}"/{build,modules.*} || die
# Clean up the build tree
shred_keys
kmake clean
find "build/" -type d -empty -delete || die
rm "build/.config.old" || die
# Install /lib/modules/${KV_FULL}/{build,source}
install_build_source
# Replace the broken /lib/modules/${KV_FULL}/build symlink with a copy of
# the files needed to build out-of-tree modules.
rm "${ED}/usr/${build}" || die
kmake run-command KBUILD_RUN_COMMAND="${KERNEL_DIR}/scripts/package/install-extmod-build ${ED}/usr/${build}"
# Not strictly required but this is where we used to install the config.
dodir "/usr/boot"
local build="lib/modules/${KV_FULL}/build"
dosym "../${build}/.config" "/usr/boot/config-${KV_FULL}"
dosym "../${build}/.config" "/usr/boot/config"
# Symlink "source" to "build" for compatibility. Fedora does this.
dosym build "/usr/${build}/../source"
}