Skip to content

Compilation du noyau Linux

Sommaire

Ce cours présente les grandes étapes pour compiler et installer un noyau Linux personnalisé sur une distribution de type Arch (mais les concepts restent valables ailleurs).

On suit trois grandes phases:

  • Préparation: récupérer les sources, nettoyer.
  • Configuration: générer et modifier le fichier .config.
  • Compilation et installation: compiler, installer modules et noyau, déclarer le nouveau noyau à GRUB. L’objectif n’est pas de devenir mainteneur du noyau, mais de comprendre ce qui se passe derrière les paquets linux fournis par la distribution.

Préparation

Installer les outils nécessaires

Assurez-vous d’avoir les outils de compilation installés (gcc, make, etc.). Sur Arch Linux, installez le groupe de paquets base-devel et quelques utilitaires supplémentaires:

bash
sudo pacman -S base-devel wget bc nano
  • base-devel inclut tous les outils de compilation de base nécessaires.
  • bc est un langage de calcul utilisé dans certains scripts de build du noyau.
  • wget sont utilisés pour télécharger les sources du noyau.

Récupérer les sources du noyau

Plusieurs façons de récupérer le code source du noyau:

  • Depuis le site officiel: https://kernel.org
  • Via wget ou curl (fichier .tar.xz)
  • Via git clone sur le dépôt officiel (git.kernel.org)
  • Depuis une clé USB déjà préparée

Exemple avec wget:

bash
$ mkdir -p ~/src/linux
$ cd ~/src/linux
$ wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.12.58.tar.xz

Décompresser l’archive

On décompresse ensuite l’archive:

Rappel: tar xf sait reconnaître automatiquement plusieurs formats (.tar.gz, .tar.xz, …).

bash
$ tar xf linux-6.12.58.tar.xz
$ cd linux-6.12.58

Se placer dans le bon dossier

Toutes les commandes de compilation doivent être exécutées dans le dossier contenant les sources (celui qui contient le Makefile principal):

bash
$ pwd
# …/src/linux/linux-6.12.58
$ ls
# arch  COPYING  CREDITS  Documentation  Kbuild  Kconfig  Makefile  README  …

Nettoyer l’environnement: make mrproper

Si le répertoire a déjà servi à une compilation précédente, il peut contenir:

  • un ancien fichier .config ;
  • des fichiers d’objets compilés ;
  • des artefacts de build.

Pour repartir sur une base propre:

bash
make mrproper

Cette commande:

  • supprime la configuration précédente ;
  • nettoie les fichiers générés.

Configuration du noyau

Pourquoi configurer le noyau ?

Le but n’est pas juste de "recompiler la même chose", mais de:

  • adapter le noyau à la machine: garder seulement les pilotes nécessaires ;
  • choisir quels pilotes seront:
    • intégrés au noyau (built-in, marqués <*>) ;
    • compilés en modules (<M>) ;
    • complètement désactivés (< >). Tout cela est décrit dans un fichier texte: .config à la racine des sources.

Pilote intégré vs module

Rappel des deux notions importantes:

CaractéristiquePilote intégré (built-in)Module
CompilationCompilé à l'intérieur de l'image du noyauFichier séparé (.ko) stocké dans /lib/modules/<version>/…
Présence en mémoireToujours présent en mémoire après le bootPeut être chargé/déchargé dynamiquement avec modprobe
AvantagesCharge dès le démarrage (utile pour le disque système, le contrôleur SATA/NVMe, etc.)Flexible, permet d'ajouter ou d'enlever des pilotes sans recompiler tout le noyau
InconvénientsAugmente la taille du noyau, nécessite une recompilation pour changerLégère surcharge (indirection, dépendances), et nécessite un mécanisme de chargement

En pratique:

  • Les pilotes indispensables pour booter (disque, système de fichiers racine, etc.) sont souvent intégrés.
  • Le reste (périphériques USB, cartes réseau optionnelles, etc.) est bien mieux en modules.

Générer un .config initial

Créer un .config entièrement à la main serait interminable. Le noyau propose donc des cibles make pour générer une config de base.

Les plus importantes:

  • make allyesconfig
  • make allmodconfig
  • make allnoconfig
  • make localmodconfig
  • make localyesconfig

allyesconfig, allmodconfig, allnoconfig

  • make allyesconfig:

    • active toutes les options et pilotes (le plus possible en intégré) ;
    • donne un noyau énorme, surtout utile pour des tests.
  • make allmodconfig:

    • active tous les pilotes en tant que modules, autant que possible ;
    • pratique pour des noyaux très génériques.
  • make allnoconfig:

    • désactive tout par défaut ;
    • utile si on veut construire une config hyper-minimale à la main.

localmodconfig et localyesconfig

Ces deux cibles utilisent la configuration actuelle du système (modules chargés) pour générer une config adaptée au matériel réel.

  • make localmodconfig:

    • lit la liste des modules actuellement chargés (lsmod) ;
    • génère une config qui inclut exactement ces pilotes en modules, et désactive le reste.
  • make localyesconfig:

  • même principe, mais les pilotes détectés sont mis en built-in (<*>).

Exemple d’usage typique:

bash
# Copier la config actuelle du noyau fourni par la distrib
$ zcat /proc/config.gz > .config

# Adapter la config à la machine courante
$ make localmodconfig

la commande zcat extrait la config du noyau en cours d’exécution (fournie par la distrib) et la copie dans .config.

Modifier finement la config: make menuconfig

Une fois la base .config générée, on la modifie via une interface en mode texte:

bash
make menuconfig

Menuconfig écran principal

Cet utilitaire en ncurses permet:

  • de parcourir les catégories (Device Drivers, File systems, Networking support, …) ;
  • d’activer/désactiver des options ;
  • de choisir si un driver est intégré (*) ou en module (M).

Navigation:

  • touches flèches pour se déplacer ;
  • Entrée / Select pour entrer dans une catégorie ;
  • Exit pour revenir en arrière ;
  • Space ou Y/M/N pour basculer entre intégré / module / désactivé.
  • / pour chercher une option par mot-clé.

Symboles:

  • <*>: pilote intégré au noyau ;
  • <M>: pilote compilé en module ;
  • < >: pilote non compilé.

N’oubliez pas de sauvegarder la configuration (Save) avant de quitter, ce qui met à jour le fichier .config.

Exemple de modifications

Dans cet exemple, j'ai ajouté le support de la manette Nitendo Switch Pro via le pilote hid-nintendo en tant que module.

Menuconfig Device Drivers

Ainsi le module hid-nintendo sera compilée et pourra être chargée dynamiquement avec modprobe hid-nintendo.

Un appareil "HID Compliant" est un périphérique qui suit les normes HID standardisées. Ces normes garantissent que le périphérique peut communiquer correctement avec les systèmes d'exploitation sans nécessiter de pilote spécialisé (plug-and-play).

Compilation et installation

Une fois .config prêt, on peut lancer la compilation.

Compiler le noyau

Commande principale:

bash
make -jN

Le paramètre -jN indique à make d’utiliser N tâches parallèles

Exemple sur une machine 4 cœurs:

bash
make -j4

Points à noter:

  • la première compilation peut prendre longtemps (minutes à heures selon la machine et le nombre de pilotes activés) ;
  • si la config est énorme (allyesconfig + toutes plateformes), ça explose le temps de build.

Message de fin de compilation du noyau

Compiler et installer les modules

Les modules sont compilés puis installés dans /lib/modules/<version>.

bash
# Compiler les modules
$ make modules

# Installer les modules (en root)
$ sudo make modules_install

On peut ensuite vérifier la présence des modules:

bash
$ ls /lib/modules

Pour l'exemple de la manette Nintendo Switch Pro, on peut vérifier que le module a bien été compilé dans le dossier /lib/modules/6.12.58/kernel/drivers/hid/

Fichier hid-nintendo.ko

Pour charger un module donné (par exemple hid-nintendo, exemple de driver de manette):

bash
sudo modprobe hid-nintendo
lsmod | grep hid-nintendo

Module hid-nintendo chargé

Placer l’image du noyau (bzImage) dans /boot

Après compilation, l’image compressée du noyau se trouve dans arch/<architecture>/boot/bzImage.

bash
$ ls arch/x86/boot/bzImage

Fichier bzImage

On va copier cette image dans /boot avec un nom significatif.

On choisit un nom de noyau, par exemple my-linux.

bash
sudo cp arch/x86/boot/bzImage /boot/vmlinuz-my-linux

Note

Par convention, les images de noyau s’appellent vmlinuz-*, mais ce n’est pas une obligation stricte. C’est toutefois plus simple pour rester cohérent avec le reste du système.


Distributions génériques vs Arch

Les étapes précédentes (make, make modules_install, make bzImage, copie de l’image dans /boot) sont valables sur la plupart des distributions Linux.

À partir d’ici, nous montrons comment Arch Linux gére l’initramfs et l’intégration avec le chargeur de démarrage, en utilisant mkinitcpio et les fichiers .preset dans /etc/mkinitcpio.d/. Sur d’autres distributions, cette partie se fait avec d’autres outils (update-initramfs, dracut, etc.).

Fichier preset mkinitcpio

À propos de l’initramfs

L’initramfs (initial RAM filesystem) est une image de système de fichiers temporaire chargée en mémoire au démarrage, avant de monter le système de fichiers racine réel.

On a besoin d’un initramfs pour que le noyau puisse accéder aux pilotes nécessaires au montage du système de fichiers racine (pilotes de disque, systèmes de fichiers, etc.).

Sur Arch, l’initramfs est géré via mkinitcpio avec des fichiers .preset dans /etc/mkinitcpio.d/.

On part du preset existant (souvent linux.preset) et on en crée une copie pour notre noyau:

bash
$ cd /etc/mkinitcpio.d
$ sudo cp linux.preset my-linux.preset

Ensuite, on édite my-linux.preset et on remplace les occurrences de linux par my-linux pour les noms de fichiers, par exemple:

text
ALL_kver="/boot/vmlinuz-my-linux"

default_image="/boot/initramfs-my-linux.img"

Fichier my-linux.preset

Attention à ne pas casser les chemins de dossiers, seulement les noms de fichiers de noyau / initramfs.

Générer l’initramfs

Une fois le preset prêt, on génère l’initramfs associé:

bash
$ sudo mkinitcpio -p my-linux

Cela crée typiquement /boot/initramfs-my-linux.img (et éventuellement une version fallback).

Résultat de mkinitcpio

Pour résumer

  • le noyau est dans /boot/vmlinuz-my-linux ;
  • initramfs /boot/initramfs-my-linux.img ;
  • le preset /etc/mkinitcpio.d/my-linux.preset décrit comment ils sont reliés via mkinitcpio ;

ls -l /boot

Mettre à jour GRUB

Il faut maintenant informer le chargeur de démarrage (ici GRUB) de l’existence du nouveau noyau.

Sur Arch:

bash
$ sudo grub-mkconfig -o /boot/grub/grub.cfg

Résultat de grub-mkconfig

GRUB va:

  • scanner boot pour trouver les fichiers vmlinuz-* ;
  • générer des entrées de menu correspondantes, souvent accessibles via "Options avancées" au démarrage.

Redémarrer sur le nouveau noyau

On peut maintenant redémarrer:

bash
$ sudo reboot

Au menu GRUB:

  • Aller dans Options avancées.
  • Choisir l’entrée correspondant à my-linux (ou le nom que vous avez donné).
  • Lancer le boot et… espérer que ça fonctionne ! 😀

Écran de GRUB

Écran de GRUB

Une fois connecté, vérifier la version active du noyau:

bash
$ uname -r

Elle devrait correspondre au noyau que vous venez de compiler.

.