Как правильно связать KBuild Makefiles для создания вложенных папок внутри модуля ядра

#c #makefile #build #linux-kernel #kbuild

#c #makefile #сборка #linux-ядро #kbuild

Вопрос:

У меня есть модуль ядра (часто скомпилированный с использованием CONFIG_MYMODULE=m), который настроен следующим образом:

 mymodule/Makefile
../foo/Makefile
../foo/component1/Makefile
../foo/component2/Makefile
  

В настоящее время используется:

mymodule /Makefile:

 mymodule-y  = mod1file.o mod2file.o mod3file.o #etc
include ../foo/Makefile
mymodule-y  = $(FOO_FILES)
obj-$(CONFIG_MYMODULE)  = mymodule.o
  

../foo/Makefile:

 include component1/Makefile
include component2/Makefile
  

и внутри каждой папки компонента у меня есть:

../foo/component1/Makefile

 FOO_FILES  = foo1file.o foo2file.o foo3file.o #etc
  

Это определенно не кажется правильным способом решения этой проблемы, поскольку все включено непосредственно в mymodule / Makefile и, следовательно, не может устанавливать флаги gcc для конкретной папки.

Каков правильный способ организации этого, сохраняя при этом все в одном модуле ядра? Я прочитал kbuild/modules.txt документация, но я не видел ничего, что имело бы прямое отношение, и я не могу до конца понять, как это сделать или действительно ли это возможно.

Спасибо


Я пробовал следующее, но получаю следующую ошибку:

«ld: не удается найти foo: формат файла не распознан»

mymodule /Makefile:

 mymodule-y  = mod1file.o mod2file.o mod3file.o #etc
mymodule-y  = ../foo/
obj-$(CONFIG_MYMODULE)  = mymodule.o
  

../foo/Makefile

 ccflags-y := -I$(src)/component1/ -I$(src)/component2/
foo-y := foo1file.o foo2file.o foo3file.o
foo-y  = component1
foo-y  = component2
  

../foo/component1/Makefile

 component1-y := component1file.o component1file.o
  

../foo/component2/Makefile

 component2-y := component2file.o component2file.o
  

Если я изменю это, чтобы вместо этого использовать obj-y = ../foo, а не mymodule-y = ../foo, он, по крайней мере, входит в папку, но, похоже, не пытается дополнить, и я хочу, чтобы все это было частью одного модуля ядра.

Комментарии:

1. Вы можете добавлять папки в список объектов. Проверьте любую папку / Makefile в исходных текстах.

2. @AndyShevchenko: Я уже пытался просмотреть их несколько, но, похоже, они не обрабатывают несколько цепочек Make-файлов в один и тот же модуль ядра. Разве это не то, что я пытаюсь сделать внизу с помощью foo-y = ../foo/ ? Если я сделаю что-то вроде «obj-y = ../foo/», работать с компиляцией в модуль ядра mymodule? Я все еще немного в замешательстве. У вас есть хороший пример, на который я могу посмотреть? Спасибо!

3. obj-[ym] это глобальное пространство отдельных блоков. Для этого вам нужно использовать пространство имен модуля.

4. Из моего примера, будет ли это для меня mymodule-y = ../foo/ или это будет что-то вроде foo-y = ../foo ? И что тогда мне делать внутри моего foo / Makefile? Будет ли это mymodule-y = component1 или я должен использовать отдельное пространство имен модуля?

Ответ №1:

Это не кажется слишком сложным.

mymodule /Makefile:

 ...
include ../foo/Makefile
...
# whatever rules use the folder-specific flags:
foo:
    gcc blah blah $(FOLDERFLAGS) blah
  

../foo/component1/Makefile:

 FOLDER_FILES := foo1file.o foo2file.o foo3file.o #etc
$(FOLDER_FILES): FOLDER_FLAGS=folder_1_flag
FOO_FILES  = FOLDER_FILES
  

../foo/component2/Makefile:

 FOLDER_FILES := foo20file.o foo21file.o foo22file.o #etc
$(FOLDER_FILES): FOLDER_FLAGS=folder_2_flag
FOO_FILES  = FOLDER_FILES
  

Достаточно ли этого для ваших целей?

Комментарии:

1. Несколько, но он вообще не использует объекты kbuild. Я действительно не хочу вызывать gcc напрямую, и у меня нет других целей в mymodule / Makefile.

2. @Jordan: я не знаком с kbuild; как вы передаете ему флаги gcc?

3. Кажется, вы не делаете это напрямую: lxr.free-electrons.com/source/Documentation/kbuild /…

4. Раздел 3.2 должен объяснить некоторые из них. Я сам не совсем понимаю это.

5. @Jordan: я не собираюсь просматривать этот огромный документ в надежде правильно угадать, как использовать инструмент, с которым мне не нужно экспериментировать. Если ваш реальный вопрос заключается в том, как использовать kbuild, я не могу вам помочь.

Ответ №2:

Вы можете заставить родительские каталоги работать, используя subdir- и extra-y , но это просто накладные расходы, и все равно ccflags для каждого каталога не будут работать. Возможно, правильным способом было бы иметь компоненты в качестве подмодулей с зависимостью от mymodule.

Я бы сохранил сборку модуля в верхнем каталоге mymodule/Makefile , легко создать несколько модулей из одного каталога, но я ничего не нашел об одном модуле из нескольких объектов в подкаталогах (возможно, политика сохранения чистоты или просто так было проще).

obj-m определите список модулей ядра для сборки (только один из приведенных ниже примеров: hello.ko , назван hello.o , но будет выводиться hello.ko )

hello-objs определите список скомпилированных объектов для получения ссылки hello.ko , используя то же имя: hello .

Будучи Makefile, легко связывать объекты условно (см. CONFIG_HELLO_COMPONENT1 )

В конце концов, если на компонент приходится много объектов, и мы хотим сохранить верхний Makefile чистым, мы все равно можем использовать include , но только для условного добавления объектов hello-objs и флагов ccflags-y (или любой другой необходимой переменной, просто нет obj-* ).

CFLAGS_$*.o (см. Ниже) может использоваться для установки cflags для каждого объекта, но он не учитывает путь, поэтому объекты с одинаковыми именами в разных каталогах будут иметь одинаковые флаги.

mymodule/Makefile :

 ifeq ($(CONFIG_HELLO_COMPONENT1), y)
 ccflags-y  = -I$(src)/foo/component1 -DCONFIG_HELLO_COMPONENT1
endif
ccflags-y  = -I$(src)/foo/component2

obj-m  = hello.o

CFLAGS_component2.o  = -DTEST_CFLAGS

hello-objs = hello-1.o
ifeq ($(CONFIG_HELLO_COMPONENT1), y)
 hello-objs  = foo/component1/component1.o
endif
hello-objs  = foo/component2/component2.o

all:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
  

Для полноты описания всех файлов следует выполнить сборку и работу с make помощью or make CONFIG_HELLO_COMPONENT1=y .

mymodule/hello-1.c :

 #include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#ifdef CONFIG_HELLO_COMPONENT1
#include <component1.h>
#endif
#include <component2.h>
static int __init init_hello(void) {
#ifdef CONFIG_HELLO_COMPONENT1
    component1();
#endif
    component2();
    printk(KERN_INFO "Hello world 1.n");
    return 0;
}
static void __exit cleanup_hello(void) {
    printk(KERN_INFO "Goodbye world 1.n");
}
module_init(init_hello);
module_exit(cleanup_hello);
  

mymodule/foo/component2/component2.h :

 #ifndef COMPONENT2_H
#define COMPONENT2_H
void component2(void);
#endif
  

mymodule/foo/component2/component2.c :

 #include <linux/kernel.h>
void component2(void) {
    printk(KERN_INFO "component2n");
}
  

mymodule/foo/component1/component1.h :

 #ifndef COMPONENT1_H
#define COMPONENT1_H
void component1(void);
#endif
  

mymodule/foo/component1/component1.c :

 #include <linux/kernel.h>
void component1(void) {
    printk(KERN_INFO "component1n");
}