在单独的对象目录中构建树外的Linux内核模块

时间:2011-04-19 15:32:35

标签: makefile linux-kernel kbuild

我正在面对Linux内核构建系统(Kbuild,内核≥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.cfoo_linux.o …/checkout/src/linux-driver/foo_linux.c编译{/ 1}}?

6 个答案:

答案 0 :(得分:4)

这是一个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

答案 1 :(得分:3)

我有类似的问题。我修改了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)`

答案 2 :(得分:1)

我不优雅但有效的解决方案是将源文件复制到输出树中。

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)

答案 3 :(得分:0)

虽然你还没有提到你到目前为止所尝试过的内容(或者你是否已经找到了解决方案),但看起来你只需要继续向下继续执行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.

答案 4 :(得分:0)

有点晚了,但看起来O= flag就是你所需要的。

答案 5 :(得分:0)

您可以设置环境变量KBUILD_OUTPUT。此功能类似于O=选项;但是,由于它是一个环境变量,它可以跨越多个makefile,其中O=无法传递或需要构建目录外模块。尝试构建一组compat-wireless模块​​时遇到了同样的问题,我需要使用O=来构建实际的内核映像。