Among the myriad of other improvement in the 2.6 series Linux kernel, a new
infrastructure, "kbuild", has been developed to create a highly configurable
and versatile build system. The full scope of this change is not the focus of
this document. Of importance is the new recommended method for compiling
external kernel modules against a 2.6 kernel tree. From
Compiling modules outside the official kernel --------------------------------------------- Often modules are developed outside the official kernel. To keep up with changes in the build system the most portable way to compile a module outside the kernel is to use the following command-line: make -C path/to/kernel/src SUBDIRS=$PWD modules
By overriding the SUBDIRS variable, the latest kbuild infrastructure can easily
be used to compile external modules. This in itself is a
Having configured and compiled a 2.6 series kernel residing in
Modules being built within the portage system suffer from this exact same problem, dying with sandbox violations when such updates are attempted. The added features of kbuild have also added complexity, of a sort which is very problematic for those wishing to follow safe practices of least privilege.
Searching Gentoo's bugzilla will find many bugs opened because of this very
problem and many forums posts have arisen suggesting sandbox disabling as the
only solution. Indeed, with the current state of affairs, it seemed inevitable
that some writing or updating to
One solution exists for this problem which does not require much change to the
current way modules are handled. By creating a build directory in the sandbox
and symlinking the important files from
The cleaner solution has arisen out of a realization that fighting the new features of kbuild would only result and further and further problems in the future. In fact, kbuild's new ability to send all output files to a separate directory would prove to be the solution. Keeping the kernel source tree completely clean and allowing external modules to build against a clean source tree while they themselves sent their output files to a temporary directory is the key.
The details of how these elements interplay is somewhat complex. Hopefully the following section will break the concepts into more easily digestable pieces, such that developers and users wishing to enhance or use this new system will have the knowledge needed to do so.
kbuild provides two variables for dictating where the kernel should output its files.
Variable | Usage |
---|---|
The combination of these two variables is the key to successfully using kbuild and portage to install kernel modules.
To make use of the kernel output features, the new
Once this variable is set, all make commands issued in the kernel source tree send their outputs to this new directory. No further work is required on the users part and the change is most (see the next section for exceptions) seamless. Once a kernel is installed, a user can still just do:
# make menuconfig
and they will be able to configure their kernel and then build it.
As all generated files are now placed in a separate directory, a few key files
will end up in a place unexpected by the user. In particular, a users
Now that kernels are outputting their files to a different location, writing
ebuilds that adhere to the new system is the next step. Updating ebuilds to
look for certain generated files and headers in the proper location and
getting them using the correct
The general idea is to patch
Changes have been added to the
The new koutput setup adds certain necessities to the
All kernel module ebuilds should now use the
Variable | Usage |
---|---|
kernel-mod_src_unpack() works very hard to figure out how the driver being built
should be handled. In particular, it handles the two different 2.6 build methods
very well. In particular, if the old style of building modules is detected, the
directory
Variable | Meaning |
---|---|
Most ebuilds will generally need one patch to the makefiles to enabled outputing to a different directory, and then do some sedding based on what is found in KV_OUTPUT and KV_BUILD after kernel-mod_src_unpack() is called. The example ebuild below will show how that is handled.
The following is a real world example of how the hostap-driver package was
fixed to create a fully functioning ebuild for both 2.4 and 2.6 series kernels.
It uses a patch to the hostap-driver's top level
Below are some excerpts from the original
include $(KERNEL_PATH)/.config
Below is the fixed version which lets KERNEL_OUTPUT_PATH be set if not already
(for 2.4 backwards compatibility) and looks for the
ifndef KERNEL_OUTPUT_PATH KERNEL_OUTPUT_PATH=$(KERNEL_PATH) endif include $(KERNEL_OUTPUT_PATH)/.config
Since we now have a KERNEL_OUTPUT_PATH variable at our disposal, fixing
the following variable declaration involving the generated
VERFILE := $(KERNEL_PATH)/include/linux/version.h
And now the edited fixed version:
VERFILE := $(KERNEL_OUTPUT_PATH)/include/linux/version.h
Finally, our patch fixes the line which invokes the 2.6 kbuild system to
include the use of the O variable, setting the system to output to a directory
Here is the original:
$(MAKE) -C $(KERNEL_PATH) SUBDIRS=$(PWD)/driver/modules \ MODVERDIR=$(PWD)/driver/modules modules
And here is the edited version:
mkdir -p $(PWD)/tmp -cp $(KERNEL_OUTPUT_PATH)/.config $(PWD)/tmp $(MAKE) -C $(KERNEL_PATH) O=$(PWD)/tmp \ SUBDIRS=$(PWD)/driver/modules \ MODVERDIR=$(PWD)/driver/modules modules
The changes to the ebuild are relatively straightforward. Things are made particularly easy by the kernel-mod eclass. Here are the important pieces of the src_unpack section and some variables we set in the ebuild:
KERNEL_MOD_SOURCES="${P}.tar.gz" KERNEL_MOD_KOUTPUT_PATCH="${PN}-koutput.diff.gz" src_unpack() { # Unpack and set some variables kernel-mod_src_unpack ## unpack the pcmcia-cs sources if needed pcmcia_src_unpack epatch "${FILESDIR}/${P}.firmware.diff.bz2" # Handle two possible 2.6 kernel build methods if [ "${KV_MINOR}" -gt "4" ] then # If outputting to the source directory, use KV_BUILD as the kernel # else we've patched for koutput and we can set the variable we added # in the patch if [ "${KV_OUTPUT}" = "/usr/src/linux" ]; then sed -i -e s:^KERNEL_PATH=.*:KERNEL_PATH=${KV_BUILD}:" \ ${S}/Makefile else sed -i -e \ "s:^# KERNEL_OUTPUT_PATH=.*:KERNEL_OUTPUT_PATH=${KV_OUTPUT}:" \ ${S}/Makefile fi fi }
Notice the use of the two variables,
src_compile() { # Configure the pcmcia-cs sources as needed. pcmcia_configure einfo "Building hostap-driver for kernel version: ${KV}" case ${KV_MINOR} in [34]) local mydrivers use pcmcia && mydrivers="${mydrivers} pccard" use hostap-nopci || mydrivers="${mydrivers} pci" use hostap-noplx || mydrivers="${mydrivers} plx" einfo "Building the following drivers: ${mydrivers}" emake EXTRA_CFLAGS="-DPRISM2_DOWNLOAD_SUPPORT" ${mydrivers} || die "make failed" ;; [56]) unset ARCH emake EXTRA_CFLAGS="-DPRISM2_DOWNLOAD_SUPPORT" all || die "make failed" ;; *) eerror "Unsupported kernel version: ${KV}" die ;; esac }
Notice in particular that the
This ebuild's src_install() function will not be shown, as it basically just
installs all the modules into