Exploration approfondie du Makefile principal du noyau Linux

Première approche de la compilation du noyau

Avant d'entamer la compilation, il convient d'installer la bibliothèque de compression nécessaire sur le système Debian/Ubuntu :

sudo apt-get install lzop

La séquence de compilation pour une plateforme ARM s'enchaîne ensuite ainsi :

export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabihf-
make distclean
make imx_v7_defconfig
make menuconfig
make all -j$(nproc)

La configuraton par défaut imx_v7_defconfig s'applique via l'outil conf du système Kconfig :

scripts/kconfig/conf --defconfig=arch/arm/configs/imx_v7_defconfig Kconfig

L'interface graphique de configuration permet d'ajuster les options du noyau. Une fois les modifications terminées, la sortie de menuconfig déclenche automatiquement la compilation complète.

Nettoyage et préparation de l'environnement

La cible distclean effectue un nettoyage exhaustif. En mode verbeux (V=1), on observe l'invocation récursive de scripts/Makefile.clean sur chaque sous-répertoire du projet :

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean V=1

Le processus parcourt l'ensemble de l'arborescence — des pilotes matériels aux systèmes de fichiers, en passant par les couches réseau et le sous-système son — pour éliminer les artefacts de compilation précédents. Les fichiers nettoyés incluent les tables de symboles, les images intermédiaires compressées, et les fichiers objet générés.

Génération de la configuration

L'étape defconfig construit les outils nécessaires puis génère le fichier .config final :

make -f ./scripts/Makefile.build obj=scripts/basic
make -f ./scripts/Makefile.build obj=scripts/kconfig imx_v7_defconfig

Les outils fixdep et conf sont compilés à la volée. Le script conf parse ensuite l'ensemble des Kconfig pour produire la configuration définitive du noyau.

Déroulement de la compilation complète

La phase all débute par la génération des en-têtes et des fichiers d'offsets d'architecture. Les étapes clés se succèdent :

  • Génération des wrappers d'en-têtes ARM dans arch/arm/include/generated/asm/
  • Construction des outils de traitement du Device Tree (dtc)
  • Compilation du code d'initialisation (init/)
  • Assemblage du code d'entrée du noyau et des routines VFP
  • Construction du VDSO (Virtual Dynamic Shared Object)
  • Compilation du code spécifique à la machine (arch/arm/mach-imx/)

Le système de construction continue avec les sous-systèmes fondamentaux : gestion mémoire (mm/), systèmes de fichiers (fs/), pilotes de périphériques (drivers/), et pile réseau (net/).

Structure de l'arborescence du noyau

Répertoire Contenu fonctionnel
arch/ Code dépendant de l'architecture (ARM, x86, etc.)
block/ Gestion des périphériques à blocs
crypto/ Algorithmes cryptographiques
Documentation/ Documentation technique
drivers/ Pilotes de périphériques organisés par catégorie
firmware/ Images de micro-logiciel
fs/ Implémentations des systèmes de fichiers
include/ En-têtes du noyau
init/ Code d'initialisation du noyau
ipc/ Mécanismes de communication inter-processus
kernel/ Code principal du noyau
lib/ Routines utilitaires
mm/ Gestion de la mémoire virtuelle
net/ Pile réseau
samples/ Exemples de code
scripts/ Scripts et outils de construction
security/ Modules de sécurité
sound/ Sous-système audio
tools/ Outils utilitaires
usr/ Génération de l'initramfs
virt/ Virtualisation (KVM)

Configuration de l'environnement VSCode

Pour faciliter la navigation dans les sources, un fichier .vscode/settings.json filtre les éléments superflus :

{
    "search.exclude": {
        "**/*.o": true,
        "**/*.su": true,
        "**/*.cmd": true,
        "arch/alpha": true,
        "arch/arc": true,
        "arch/arm64": true,
        "arch/avr32": true,
        "arch/[b-z]*": true,
        "arch/arm/plat*": true,
        "arch/arm/mach-[a-h]*": true,
        "arch/arm/mach-[n-z]*": true,
        "arch/arm/mach-i[n-z]*": true,
        "arch/arm/mach-m[e-v]*": true,
        "arch/arm/mach-k*": true,
        "arch/arm/mach-l*": true
    },
    "files.exclude": {
        "**/.git": true,
        "**/*.o": true,
        "**/*.su": true,
        "**/*.cmd": true
    }
}

Analyse du Makefile principal

Identification de la version

VERSION = 4
PATCHLEVEL = 1
SUBLEVEL = 15
EXTRAVERSION =

Options de contrôle du make

MAKEFLAGS += -rR --include-dir=$(CURDIR)

L'option -rR désactive les règles implicites et les variables intégrées, garantissant un environnnement de construction prévisible.

Gestion de la verbosité

Le comportement silencieux s'active via make -s ou la variable silent, supprimant l'affichage des commandes exécutées.

Variables d'inclusion des en-têtes

USERINCLUDE := \
    -I$(srctree)/arch/$(hdr-arch)/include/uapi \
    -I$(srctree)/arch/$(hdr-arch)/include/generated/uapi \
    -I$(srctree)/include/uapi \
    -I$(objtree)/include/generated/uapi \
    -include $(srctree)/include/linux/kconfig.h

LINUXINCLUDE := \
    -I$(srctree)/arch/$(SRCARCH)/include \
    -I$(objtree)/arch/$(SRCARCH)/include/generated \
    $(USERINCLUDE)

Export des symboles de construction

export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION
export ARCH SRCARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE
export AS LD CC CPP AR NM STRIP OBJCOPY OBJDUMP
export MAKE AWK GENKSYMS INSTALLKERNEL PERL PYTHON UTS_MACHINE
export KBUILD_CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS
export KBUILD_CFLAGS CFLAGS_KERNEL CFLAGS_MODULE CFLAGS_GCOV
export KBUILD_AFLAGS AFLAGS_KERNEL AFLAGS_MODULE

Mécanisme de configuration defconfig

L'invocation make imx_v7_defconfig déclenche la chaîne suivante :

  1. Détermination des cibles de configuration (config-targets=1)
  2. Construction des outils de base (scripts_basic)
  3. Exécution via scripts/Makefile.build

Cible scripts_basic

scripts_basic:
    $(Q)$(MAKE) $(build)=scripts/basic
    $(Q)rm -f .tmp_quiet_recordmcount

Qui s'expanse en :

make -f ./scripts/Makefile.build obj=scripts/basic

Logique de construction générique

Le fichier scripts/Makefile.build constitue le cœur du système de compilation. Pour un objet donné, il détermine :

  • kbuild-dir : le répertoire source réel
  • kbuild-file : le Makefile spécifique du module
  • Les cibles à construire (builtin-target, lib-target, extra-y, etc.)

Génération finale du fichier .config

La règle finale s'exprime comme :

%_defconfig: scripts/kconfig/conf
    $(Q)$< --defconfig=arch/$(SRCARCH)/configs/$@ Kconfig

L'outil conf lit la configuration par défaut spécifiée et matérialise toutes les options dans le fichier .config à la racine des sources.

Options de compilation modulaires

Flags locaux au Makefile courant

ccflags-y   # Options du compilateur C
asflags-y   # Options de l'assembleur
ldflags-y   # Options de l'éditeur de liens

Ces variables n'affectent que le Makefile où elles sont définies, sans propagation aux sous-répertoires.

Flags propagés dans la hiérarchie

subdir-ccflags-y  # Options GCC pour le répertoire et ses descendants
subdir-asflags-y  # Options assembleur pour le répertoire et ses descendants

Flags spécifiques par module objet

CFLAGS_module.o = -DCONFIG_FEATURE_X  # Définit un symbole pour module.o uniquement
AFLAGS_entry.o  = -march=armv7-a       # Options d'assemblage spécifiques

Production des artefacts finaux

La compilation aboutit à plusieurs livrables essentiels :

Artefact Description
vmlinux Image ELF non compressée du noyau
arch/arm/boot/Image Image binaire brute
arch/arm/boot/zImage Image auto-extractible compressée
arch/arm/boot/dts/*.dtb Binaires de description matérielle
*.ko Modules chargeables

Le processus final d'assemblage de l'image compressée implique la chaîne :

OBJCOPY arch/arm/boot/Image
LZO     arch/arm/boot/compressed/piggy.lzo
AS      arch/arm/boot/compressed/piggy.lzo.o
LD      arch/arm/boot/compressed/vmlinux
OBJCOPY arch/arm/boot/zImage

Les modules sont ensuite traités en deux phases : compilation des sources, puis construction des fichiers .ko via MODPOST et ld -r pour la résolution des symboles.

Étiquettes: linux-kernel Makefile embedded-linux cross-compilation kbuild

Publié le 4 septembre à 10h25