🌽 Compile and install the Linux kernel from source
By OctoSpacc
Caution
The content of this page has been entirely machine-translated into English, from Italiano. Therefore, it might contain any kind of errors.
It's not often that new ideas come to mind, but when they do, they're always just the right amount of bizarre... Without digressing too much, it's precisely because of this development of things that years ago, for the first time, I found myself compiling the Linux kernel from source — on a Raspberry Pi 3 among other things, which in hindsight I wouldn't recommend — and now, precisely yesterday, again another time, after years (this time on the PC, luckily ), for a purpose that I won't spoil.
Why recompile the kernel? 😯️
Linux is based on a monolithic architecture, which would be of little concern to us... if it weren't for the fact that it has an inconvenient implication: any function that works at the kernel level must be compiled into it. Even the mechanism of the so-called modules does not cover all possible situations (at least not on a practical level), and one can therefore find oneself in situations in which the kernel provided by the distribution (or by the hardware manufacturer), even if updated, does not have something that is needed, and therefore must be replaced.
Considering the infinite variety of Linux distributions, repositories that distribute compatible or non-compatible kernels, and combining this with the diversity of individual options that can be enabled in kernel compilation... not only in rare cases is compilation from source the only way, but often it is the most practical one. Luckily, compiling the Linux kernel is very simple — significantly easier than the average Linucs desktop application, with three thousand always conflicting dependencies — but there are perhaps not-so-immediate details in the process, so… here's my note!
0. Departure and prerequisites 📦️
This note is on the more generic recompilation of the Linux kernel, i.e. the official variant (that of Linus Torvalds) on and for an x86_64 (or AMD64) desktop PC. No forks or patched variants, no crappy OEM versions, no installation on embedded or otherwise esoteric devices, no distributed or cross-platform compilation. For more or less borderline cases, the things to do can vary more or less, even if the trend remains the same... you see, come on, the point is that I assume this situation. In my case, there aren't even proprietary kernel modules.
Aside from any favorite tools for obtaining the kernel, unpacking it if necessary, and some distractions to pass the considerable time, the prerequisites are quite minimal. At a minimum you need a C compiler (gcc) for obvious reasons, GNU Make to run the makefiles, some assorted tools with a forgettable name and some super-specific libraries of limited interest. Then, I think other packages may be needed, depending on the Linux distribution in use or the features that need to be compiled.
It's not actually very clear on the web which packages are really necessary, and which ones someone who has done other guides said "well, let's put it in just to be safe"... I'll update here with precise price lists as I check, including excessive planks if necessary (for those who are okay with wasting space but not time). For me it is generally a strategy to install the minimum possible when some requirement is not clear, start the compilation, and install any other dependencies as errors arise in this regard.
Debian and derivatives (apt
):
build-essential
libelf-dev
(required)ncurses-dev
(to use TUI menu configuration)
1. Obtaining the code ⛓️
Linux source code can be taken officially from main Git, from Torvalds GitHub , or from the Kernel.org site. I prefer the last option, which has the latest versions actually needed displayed prominently, up to the oldest supported branch.
There are several versions supported at a given time. Generally, if there's no reason to install an older kernel, a newer one is better; not too new, however, because living on the bleeding edge means losing blood, with occasional even serious problems that can pop up! So, I avoid the mainline
branch, updated daily or almost, like the plague, and generally choose stable
, updated with a little ' more days. Other users might legitimately prefer the more recent longterm
(the one at the top), for even more stability, but I find it useless.
For each version line, apart from the date, what matters is the [tarball] link, so you download that file there. You can then extract it to a convenient folder, among many ways, with the tar xvf
command. All commands to be executed from this point will be inside the prepared folder.
...You should also download the PGP file, when present, which serves to verify that the download is intact and that it comes from legitimate distributors. Realistically, however, not all versions already have it (implying that deep down...), the download is done from the official site with HTTPS (so it will be difficult to alter), it is a compressed archive (so if corrupted it should fail the extraction), and doing the verification is a mind-blowing pain in the ass. Other institutions will have higher security requirements, but for private users it's frankly just boring, I don't do it, I don't care.
2. Kernel configuration 🔩️
Configuring the kernel is the most intricate part... because you can't execute commands by inertia, but you have to choose what you actually need to, well, have the kernel with bone options. There are, as mentioned, infinite configurations, and different ways to use them. The main point is that there is a huge text file, with various options (mostly Boolean), that you can edit.
Tweaking that thing by hand is crazy, though, because there are neat menu-based tools built into the build process to handle the various possibilities. Here too, half a mess, but the choice is mainly between two programs TUI and GUI respectively, which can be invoked respectively with make menuconfig
and make xconfig
. I prefer xconfig
for convenience and, although I have used the curses menu configuration in the past, and it is quite intuitive for me, apparently for many it is not... and the how to use that menu is not today's topic.
menuconfig vs xconfig |
---|
If you do nothing else, the configuration you are going to change is the default one of the kernel as it is being developed. I have never had any problems using that as a base, but, if necessary, in addition to those shared by other users, you can use the one from the current distribution. Depending on how your system exposes the kernel configuration, you can (typically) read it with cat /boot/config-$(uname r)
, cat /boot/config
, or zcat /proc/config.gz
. Just write it (>
) to the ./.config
file to apply it to the current configuration.
In this case I wanted to activate support for the new NTFS driver, so in xconfig I press CTRL+F, search for "ntfs3" and set to (Y)es the option that talks about "NTFS Read/Write something something"; then, I save the configuration, I close, and... I'm done, incredible.
3. Compiling the code 🧑u200d🍳️
With compilation, it's boring time, because you simply have to give the computer time to crunch millions (!) lines of code. It's not good, but at least it's not the end of the world: on any PC that isn't exactly a hack you should do it in less than 4 hours. On the Raspberry Pi 3 it took me a day and a half with the CPU at nuclear temperatures (and also for this reason I advise against it...), but on my PC (Ryzen 3 3200G, 16 GB of RAM of which a few are occupied by compilation, on a low-end SSD) I think it took me just under 3 hours to compile version 6.10.7.
You simply need to run make
, and Linucs will make itself for the current CPU architecture, long live the magic! Better yet, make -j$(nproc)
to use all available CPU cores... The handful of hours, I should point out, are measured against this, otherwise it would be half a day , since my PC has 4 cores; it could do much sooner by having more cores, because it can compile even more files in parallel effectively.
At least in the first few minutes, it's a good idea to keep an eye on the terminal, to see if any errors occur and the compilation stops. Absurd errors have never happened to me, but, as I said, if you don't install all the dependencies, something related to those could come out... in this case, you install what's missing (referring to your distribution), and continue with the previous command.
Depending on your configuration, you will need more or less disk space to complete the compilation. While the kernel itself never weighs more than a few MB (and the modules a few tens of MB), the folder at the end of the day weighed ~22 GB, so it's a good idea to either make sure you have enough space, or check every now and then that this isn't ending. And if it ends during the process, you simply free up space and continue, again, as before. (As long as your file system doesn't get corrupted just by being 100% full, right BTRFS?)
4. Installing kernels and modules 🏗️
You don't need root permissions to compile the kernel, which is handy in case you want to temporarily steal someone else's most powerful computer to do the job... but, to install, you obviously need those on the current system.
Here it is not only simple, but also quite fast (maximum a few minutes): by running (as root) first make install
, and then INSTALL_MOD_STRIP=1 make install_modules
, they will be installed in the appropriate paths, respectively (assuming you have not changed the names): the kernel image (vmlinuz-x.x.x-...
), usually in /boot
and modules, usually in /lib/modules/linux-x.x.x-...
. The modules are files separate from the kernel, because they are loaded by the system when necessary... the point is that some of the many are used to complete the boot, so they must be installed.
You also need to prepare the so-called init file system, or initial ramdisk; normally it also ends up in /boot
, under the name initrd.img-x.x.x-...
. And this step would be quite inconvenient if there were no kernel-install
, script included with systemd, or its alternative installkernel
. Having systemd, at least the first one should already be installed, and in that case (assuming the names from before) just do (as root) kernel-install add x.x.x-... /boot/vmlinuz- x.x.x-...
; alternatively, with the second, installkernel x.x.x-... /boot/vmlinuz-x.x.x-...
.1
Note: those who develop with the kernel (not those who are reading this post, I'm afraid) may want not to set the environment variable INSTALL_MOD_STRIP=1
, because debugging without the debugging, which that flag removes, is difficult... but for ordinary mortal users like me they just waste space (so much so that distributions package them separately). Furthermore, those who do not necessarily develop with the kernel, but have to compile external modules or do other tricks, should realistically also install the corresponding header files on the system: make headers_install
(always as root).
At least on "complete" distributions, make install
and then kernel-install
should have already configured the bootloader too, at least having GRUB. In the case of, so to speak, "more DIY" distributions (which I don't use, btw), as well as more unusual boot configurations... that's not my case, so I know nothing, and I won't say anything. Boot configurations are a beast for another time.
5. Test the core 💥️
If the kernel is installed, and the bootloader has been correctly configured, then simply restart your computer to enjoy. It is good to remember that, if you are using GRUB, some say that the new kernel is not selected as default, and you have to choose it manually from the boot menu... but in my case, on Linux Mint Debian Edition, it seemed to me that instead it had actually been set as default.
Again, if, thanking the penguin, the system finally boots, just use the uname -r
command to check the running kernel version. At this point, it's a good idea to verify that the desired configuration is actually working... but how to do this varies from feature to feature, case by case. To at least confirm that the specified configuration exists, just check the current kernel configuration as in point 2.
At this point, if everything works and no other changes are needed, you can also delete the huge compilation folder, and the kernel will remain. If you also need to uninstall the kernel in the future, just delete the previously installed files normally and reconfigure the bootloader appropriately.
Conclusion 🎊️
Being able to compile the kernel from source code is another of those things that we Linux users can do, and that Windows users frankly don't envy us. But that's because they like to win easy, with their NT, based on a microkernel design... that's right, now that the point of the article is over I can spout nonsense as I like.
Copium aside, compiling Linux can be something fun to do at least once. If you find yourself in uncomfortable situations like me it must be done, there is little that can be done; However, if you just want to have some silly fun, maybe one of the many things you can do is compile an ultra-specific, super-optimized kernel for your machine, or for virtualization purposes. And, sure, it consumes some energy, but never as much as mining cryptocurrencies or rendering nuclear missiles in Blender!
🏷️ Notes and References
The decorative cover image is obtained via Microsoft's generative artificial intelligence.
- The kernel build system: https ://www.kernel.org/doc/html/v6.6/kbuild/index.html
- A Guide to Compiling the Linux Kernel All By Yourself: https:// itsfoss.com/compile-linux-kernel/
- Building and Installing Custom Linux Kernels (Rocky Linux): https://docs.rockylinux.org/guides/custom-linux-kernel/
-
Installkernel and kernel-install (Gentoo Linux): https://wiki. gentoo.org/wiki/Installkernel ↩