Сборка модуля ядра 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= для фактической сборки образа ядра.

Другие вопросы по тегам