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

17

Disons que j'ai un module mymodavec des fichiers 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 noyau est fait, j'obtiens une erreur indiquant:

mymod.h introuvable

La raison semble être que lorsque les modules du noyau sont créés, cette commande est exécutée à partir du makefile: (en utilisant makeV1):

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

Dans d'autres œuvres, j'ai $(shell pwd)été étendu à <path/to/linux>. Ce n'est pas ce que je veux. Comment puis-je spécifier le -Iparamètre vers lequel pointer src/incde mon mymodarbre source?

Om Narasimhan
la source

Réponses:

19

Les makefiles du noyau Linux utilisent le framework Kbuild. Bien que celles-ci soient interprétées par GNU make, Kbuild se compose d'un large ensemble de macros avec des conventions d'utilisation particulières, donc les directives typiques de makefile ne s'appliquent pas. La bonne chose à propos de Kbuild est que vous avez besoin de très peu de passe-partout compte tenu de la complexité de la tâche.

Kbuild est documenté dans la source du noyau, dans Documentation/kbuild. En tant que rédacteur de module, vous devez particulièrement lire modules.txt(et au moins parcourir les autres).

Ce que vous faites maintenant ne fonctionne pas car il $(shell pwd)est développé lorsque la EXTRA_CFLAGSvariable est utilisée. Étant donné que le makefile s'exécute à partir de l'arborescence des sources du noyau plutôt qu'à partir du répertoire de votre module (c'est l'un des nombreux aspects non évidents de Kbuild), il prend le mauvais répertoire.

L'idiome officiel pour spécifier les répertoires d'inclusion dans un module hors arborescence est au §5.3 de modules.txt. La srcvariable est définie dans le répertoire de niveau supérieur de votre module. Donc:

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

Notez que cette déclaration doit se trouver dans un fichier appelé Kbuildà la racine de votre arborescence de modules. (Vous voudrez peut-être considérer le srcrépertoire comme la racine de votre arborescence de modules; si c'est le cas, placez Kbuild-le et remplacez la valeur ci-dessus par -I$(src)/inc). Il est également possible de les mettre dans un Makefile, mais gardez à l'esprit que cette définition (tant que toute autre chose qui s'applique uniquement lors de la construction d'un module de noyau) devrait être dans une directive conditionnelle ifeq ($(KERNELRELEASE),). Voir §4.1 de modules.txt.

Si vous ne possédez pas déjà un Kbuildfichier et que vous souhaitez en changer, lisez le §4.1 de modules.txt. Avoir un Kbuildfichier séparé est légèrement plus clair. Ne mettez rien qui s'applique au noyau dans votre makefile principal, autre qu'une règle à appeler make -C $(KERNELDIR) M=$(pwd). Dans Kbuild, le minimum dont vous avez besoin est la liste des modules que vous construisez (souvent juste celui-ci) et une liste de fichiers à inclure dans votre module, plus 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
Gilles 'SO- arrête d'être méchant'
la source
Je n'ai pas pu mettre à jour le message car je n'avais pas assez de réputation.
Om Narasimhan
1
@Om Narasimhan: Si cela vous a aidé à trouver la solution, vous devez marquer la réponse comme acceptée.
un CV
1

Traditionnellement, la façon de #includecréer des fichiers avec des chemins relatifs au répertoire du code source actuel consiste à utiliser des guillemets plutôt que des crochets:

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

Dans ce cas, le premier #includeréférencera le chemin de recherche d'inclusion du compilateur (qui, dans le cas de gcc, est contrôlé par le -Icommutateur de ligne de commande), tandis que le second cherchera dans le répertoire qui contient le fichier source avec le #include.

Ces chemins peuvent également être relatifs. Donc, dans src / mod / mymod.c, vous pouvez dire:

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

et cela devrait "simplement fonctionner".

Je ne sais pas si c'est une pratique courante dans l'arborescence du noyau Linux, mais c'est certainement mieux que de contourner le chemin d'inclusion, ce qui pourrait avoir un certain nombre d'effets secondaires involontaires.

un CVn
la source
1
De bons conseils en général, cependant les makefiles du noyau Linux sont très particuliers. Ils font appel à un ensemble de macros assez complexe appelé Kbuild; il est souvent préférable de traiter Kbuild comme un langage qui est presque, mais pas tout à fait, totalement différent de make.
Gilles 'SO- arrête d'être méchant'
1
Effectivement, mais le comportement du compilateur C consistant à rechercher <foo> dans un ensemble de répertoires configuré, et à "bar" en regardant d'abord le répertoire en cours et en retombant ensuite sur le chemin mentionné précédemment ne changera pas par ce que des moyens bizarres appelés le compilateur en premier lieu.
vonbrand