Comment inclure des files d'en-tête locaux dans le module du kernel Linux

Disons que j'ai un module mymod avec les files source comme suit:

src / mod / mymod.c
src / inc / mymod.h

J'essaie d'inclure mymod.h comme suit

 #include <mymod.h> 

Mon makefile contient EXTRA_CFLAGS= -I$(shell pwd)/../inc/ mais quand le kernel est fait, j'obtiens une erreur indiquant:

mymod.h introuvable

La raison semble être que lorsque les modules du kernel sont faits, cette command est exécutée à partir du makefile: (using make V1):

 make -C <path/to/linux/src> M=<path/to/mymod> modules 

Dans d'autres travaux, mon $(shell pwd) été étendu à <path/to/linux> . Ce n'est pas ce que je veux. Comment puis-je spécifier le paramètre -I pour pointer vers src/inc de mon mymod source mymod ?

Les makefiles du kernel Linux utilisent le framework Kbuild. Bien que ceux-ci soient interprétés par GNU make, Kbuild se compose d'un grand nombre de macros avec des conventions d'utilisation particulières, de sorte que les directives typiques de makefile ne s'appliquent pas. La bonne chose à propos de Kbuild est que vous avez besoin de très peu boilerplate count tenu de la complexité de la tâche.

Kbuild est documenté dans la source du kernel, dans Documentation/kbuild . En tant que rédacteur de module, vous devriez surtout lire modules.txt (et au less parcourir les autres).

Ce que vous faites maintenant ne fonctionne pas car $(shell pwd) est développé lorsque la variable EXTRA_CFLAGS est utilisée. Comme le makefile s'exécute à partir de l'arborescence source du kernel plutôt que du directory de votre module (c'est l'un des nombreux aspects non évidents de Kbuild), il récupère le mauvais directory.

L'idiome officiel pour spécifier des directorys d'inclusion dans un module hors tree est au § 5.3 de modules.txt . La variable src est définie sur le directory toplevel de votre module. Donc:

 EXTRA_CFLAGS := -I$(src)/src/inc 

Notez que cette déclaration doit être dans un file appelé Kbuild à la racine de votre arborescence de modules. (Vous voudrez peut-être considérer que le directory src est la racine de votre arborescence de modules, si c'est le cas, mettez Kbuild y Kbuild et remplacez la valeur ci-dessus par -I$(src)/inc ). Il est également possible de les mettre dans un Makefile , mais attention à ce que cette définition (aussi longtime que tout ce qui s'applique uniquement lors de la construction d'un module kernel) soit dans une directive conditionnelle ifeq ($(KERNELRELEASE),) . Voir §4.1 de modules.txt .

Si vous ne disposez pas déjà d'un file Kbuild et souhaitez en avoir un, lisez le § 4.1 de modules.txt . Avoir un file Kbuild séparé est légèrement plus clair. Ne mettez rien qui s'applique au kernel de votre makefile principal, à part une règle pour appeler make -C $(KERNELDIR) M=$(pwd) . Dans Kbuild , le minimum dont vous avez besoin est la list des modules que vous construisez (souvent la seule) et une list de files à inclure dans votre module, ainsi qu'une déclaration de dépendance:

 EXTRA_CFLAGS := -I$(src)/inc obj-m := mymod.o mymod-y := $(src)/mod/mymod.o $(src)/mod/mymod.o: $(src)/inc/mymod.h 

Traditionnellement, le moyen de #include files avec des paths relatifs au directory du code source actuel est d'utiliser des guillemets plutôt que des chevrons:

 #include <stdio.h> #include "mygreatfunctions.h" 

Dans ce cas, le premier #include fera reference au path de search include du compilateur (qui, dans le cas de gcc, est contrôlé par le commutateur de command line -I ), tandis que le second cherchera dans le directory contenant le file source #include

De tels paths peuvent aussi être relatifs. Donc, dans src / mod / mymod.c, vous pouvez dire:

 #include "../inc/mymod.h" 

et cela devrait "marcher".

Je ne sais pas si c'est une pratique courante dans l'arborescence du kernel Linux, mais il vaut sûrement mieux que de contourner le path d'inclusion, qui pourrait avoir un certain nombre d'effets secondaires inattendus.