#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");
}