Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/ant/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Makefile 在单独的对象目录中构建树外Linux内核模块_Makefile_Linux Kernel_Kbuild - Fatal编程技术网

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

Makefile 在单独的对象目录中构建树外Linux内核模块,makefile,linux-kernel,kbuild,Makefile,Linux Kernel,Kbuild,我面对的是Linux内核构建系统(Kbuild,kernel)≥2.6.28)具有目录结构,并为更大的项目构建系统。我们的项目包含一个树外Linux内核模块,我们的目录结构如下(显然是简化的): 构建过程不得修改签出下的任何内容,构建模块不得修改tmp/linux-2.6.xx下的任何内容。所有输出文件必须在output/linux arm debug下结束(或在构建时选择的任何体系结构和调试变量) 我已经阅读并开始编写我的Kbuild文件: MOD_OUTPUT_DIR = ../../../

我面对的是Linux内核构建系统(Kbuild,kernel)≥2.6.28)具有目录结构,并为更大的项目构建系统。我们的项目包含一个树外Linux内核模块,我们的目录结构如下(显然是简化的):

构建过程不得修改
签出
下的任何内容,构建模块不得修改
tmp/linux-2.6.xx
下的任何内容。所有输出文件必须在
output/linux arm debug
下结束(或在构建时选择的任何体系结构和调试变量)

我已经阅读并开始编写我的
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
进行编译?

尽管您还没有提到您已经尝试了什么(或者是否已经找到了解决方案),看起来您只需要在文件的下一部分继续—到第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.

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

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)
FOO\u SOURCES\u DIR=$(src)/../../../../../checkout/src
FOO_MOD_OUTPUT_DIR=../../../OUTPUT/linux-$(ARCH)-$(调试)
#指定对象文件
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)
#哪里可以找到来源
$(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驱动程序/FOO_linux.c
#复制源的规则
FOO\u复制的\u源=$(patsubst%.o,$(src)/%.c,$(FOO\u模块\u OBJS))
$(FOO\u复制的\u源):
$(Q)mkdir-p$(@D)
cp-f$<$@
清理文件+=$(FOO\u复制的\u源)
清洁目录+=$(FOO_MOD_OUTPUT_DIR)

有点晚了,但看起来这正是您需要的。

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

我也遇到了类似的问题。我修改了
linux\u 2\u 6\u 34/scripts/Makefile.build
,如下所示

ifdef SRCDIR
src := $(SRCDIR)
else
src := $(obj)
endif
SRCDIR
是目录源

要编译模块,请运行

make -c $(KDIR) M=$(Your_output_dir) SRCDIR=$(your source directory)`

这里是一个Makefile,它为内核外树模块(改编自@Mark的注释)进行源代码外树构建

注意:您仍然需要一个Kbuild文件

obj-m += my_driver.o

我读过那部分,我不知道这对我有什么帮助。在该示例中,
complex\u main.c
complex\u main.o
位于同一目录中。在我的构建树中,源代码和构建产品是完全独立的。它看起来确实正确。如果我没有尝试过,我会很惊讶,但是已经有一段时间了,我已经转到了其他项目,所以我不能确定。谢谢你的建议,我会努力寻找机会尝试一下。对我来说不起作用-似乎
O=
KBUILD\u输出
都需要在构建内核时应用,而不仅仅是外部模块。我看到的是在源代码树中查找生成的文件时出错-例如
linux/version.h
-它在O=location.Copy中查找这些文件?至少做一次符号链接,然后离开它@Shahbaz符号链接在构建树中并不总是有效。它们往往作为符号链接包含在归档程序中。我甚至不得不在某个时候进行Samba导出(呃)。在Linux内核构建树中复制少量源文件是微不足道的。如此接近编译的c文件,但它拒绝采取最后一步来生成
.ko
(版本3.14.0)抱歉-pebcak-在我的Kbuild中有一个bug-这就解决了问题-附带条件是它对哪个目录有点困惑,并且在某个阶段要求Kbuild文件位于两个目录中。这是一个很小的代价让它继续运行这似乎是可行的,但出于某种原因,我需要在输出目录中有一个空的Makefile来运行它(linux-4.1.6)我在不修改
Makefile.build
或任何其他文件的情况下使其工作:
make-C/path/to/linux-3.16.1/build M=/path/to/module/build src=/path/to/module
。我不知道这是否适用于任何其他版本的内核,但也许会。我仍然需要在build dir中使用
touch Makefile
。@标记为交叉编译,我可以编写与上面指定相同的
Makefile
。如果是这样,我需要在哪里指定交叉编译器选项。顺便说一句,我想与arm eabi gccI交叉编译。我不明白为什么我们仍然需要一个Kbuild文件
obj-m+=my_driver.o
,这只是一个偏好问题。如果需要,可以将此行添加到Makefile。将它放在Kbuild文件中可以通过删除用于在Makefile中保护此语句的
ifneq($(KERNELRELEASE),)
测试来简化Makefile。请参阅:这与我需要的非常接近,但遗憾的是,它假设模块
Makefile
位于
src
目录中,这对我来说不是这样的(它是由autoconf生成的,所以
Makefile.in
位于源代码中,
Makefile
位于build/M目录中,对于Kbuild文件也是如此)。如果
src=
被记录在
modules.txt
:-(是的,我知道这已经有好几年了,但我觉得
src=
正在做什么是一个重要的问题。
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
obj-m += my_driver.o