Сборка модуля ядра Linux из дерева в отдельном объектном каталоге
Я сопоставляю систему сборки ядра Linux (Kbuild, kernel ≥2.6.28) со структурой каталогов и системой сборки для более крупного проекта. Наш проект содержит модуль ядра Linux из дерева, и наша структура каталогов выглядит так (очевидно, упрощенно):
checkout/src/common/*.c source files (common to Linux and other platforms)
checkout/src/linux-driver/*.c source files (for the Linux kernel driver)
checkout/build/linux/Kbuild Kbuild
tmp/linux-2.6.xx/ where the Linux kernel is unpacked and configured
output/linux-arm-debug/ where object files must end up
Процесс сборки не должен ничего менять под checkout
и сборка модуля не должна ничего менять под tmp/linux-2.6.xx
, Все выходные файлы должны быть в output/linux-arm-debug
(или любой другой вариант архитектуры и отладки, выбранный во время сборки).
я прочел kbuild/modules.txt
и начал писать мой Kbuild
файл:
MOD_OUTPUT_DIR = ../../../output/linux-$(ARCH)-$(DEBUG)
obj-m += $(MOD_OUTPUT_DIR)/foo_mod.o
$(MOD_OUTPUT_DIR)/our_module-objs := $(MOD_OUTPUT_DIR)/foo_common.o $(MOD_OUTPUT_DIR)/foo_linux.o
Это обрабатывает хранение объектных файлов в другом каталоге, где Kbuild
жизни. Теперь, как я могу указать, что foo_common.o
должен быть скомпилирован из …/checkout/src/common/foo_common.c
а также foo_linux.o
от …/checkout/src/linux-driver/foo_linux.c
?
6 ответов
Вот Makefile, который делает сборки из дерева исходников для модулей дерева ядра (адаптировано из комментария @Mark)...
KDIR ?= /lib/modules/$(shell uname -r)/build
BUILD_DIR ?= $(PWD)/build
BUILD_DIR_MAKEFILE ?= $(PWD)/build/Makefile
default: $(BUILD_DIR_MAKEFILE)
make -C $(KDIR) M=$(BUILD_DIR) src=$(PWD) modules
$(BUILD_DIR):
mkdir -p "$@"
$(BUILD_DIR_MAKEFILE): $(BUILD_DIR)
touch "$@"
clean:
make -C $(KDIR) M=$(BUILD_DIR) src=$(PWD) clean
Примечание: вам все еще нужен файл Kbuild...
obj-m += my_driver.o
У меня была похожая проблема. Я модифицировал linux_2_6_34/scripts/Makefile.build
следующее.
ifdef SRCDIR
src := $(SRCDIR)
else
src := $(obj)
endif
SRCDIR
является источником каталога.
Чтобы скомпилировать модуль, запустите
make -c $(KDIR) M=$(Your_output_dir) SRCDIR=$(your source directory)`
Мое не элегантное, но эффективное решение - скопировать исходные файлы в дерево вывода.
FOO_SOURCES_DIR = $(src)/../../../checkout/src
FOO_MOD_OUTPUT_DIR = ../../../output/linux-$(ARCH)-$(DEBUG)
# Specify the object files
obj-m += $(FOO_MOD_OUTPUT_DIR)/foo_mod.o
FOO_MODULE_OBJS := $(FOO_MOD_OUTPUT_DIR)/foo_common.o $(FOO_MOD_OUTPUT_DIR)/foo_linux.o
$(FOO_MOD_OUTPUT_DIR)/foo_mod-objs := $(FOO_MODULE_OBJS)
# Where to find the sources
$(src)/$(FOO_MOD_OUTPUT_DIR)/foo_common.c: $(FOO_SOURCES_DIR)/common/foo_common.c
$(src)/$(FOO_MOD_OUTPUT_DIR)/foo_linux.c: $(FOO_SOURCES_DIR)/linux-driver/foo_linux.c
# Rules to copy the sources
FOO_COPIED_SOURCES = $(patsubst %.o,$(src)/%.c,$(FOO_MODULE_OBJS))
$(FOO_COPIED_SOURCES):
$(Q)mkdir -p $(@D)
cp -f $< $@
clean-files += $(FOO_COPIED_SOURCES)
clean-dirs += $(FOO_MOD_OUTPUT_DIR)
Хотя вы еще не упомянули то, что пытались до сих пор (или уже нашли решение), похоже, вам просто нужно немного продвинуться дальше по файлу modules.txt - до Раздела 4.3:
--- 4.3 Several Subdirectories
kbuild can handle files that are spread over several directories.
Consider the following example:
.
|__ src
| |__ complex_main.c
| |__ hal
| |__ hardwareif.c
| |__ include
| |__ hardwareif.h
|__ include
|__ complex.h
To build the module complex.ko, we then need the following
kbuild file:
--> filename: Kbuild
obj-m := complex.o
complex-y := src/complex_main.o
complex-y += src/hal/hardwareif.o
ccflags-y := -I$(src)/include
ccflags-y += -I$(src)/src/hal/include
As you can see, kbuild knows how to handle object files located
in other directories. The trick is to specify the directory
relative to the kbuild file's location. That being said, this
is NOT recommended practice.
For the header files, kbuild must be explicitly told where to
look. When kbuild executes, the current directory is always the
root of the kernel tree (the argument to "-C") and therefore an
absolute path is needed. $(src) provides the absolute path by
pointing to the directory where the currently executing kbuild
file is located.
Немного поздно, но похоже, что O= flag - это то, что вам нужно.
Вы можете установить переменную среды KBUILD_OUTPUT
, Эта функция похожа на O=
вариант; однако, поскольку это переменная окружения, она может охватывать несколько make-файлов, где O=
не могут быть переданы или модуль вне каталога должен быть собран. У меня возникла такая же проблема при попытке собрать набор беспроводных модулей, и мне нужно было использовать O=
для фактической сборки образа ядра.