将内核模块构建到特定目录中

Posted

技术标签:

【中文标题】将内核模块构建到特定目录中【英文标题】:Build kernel module into a specific directory 【发布时间】:2012-08-28 00:30:01 【问题描述】:

有没有办法在我的 makefile 中设置一个输出目录来制作内核模块?

我想从构建文件中保持我的源目录干净。

【问题讨论】:

Building an out-of-tree Linux kernel module in a separate object directory的可能重复 【参考方案1】:

KBUILD_OUTPUTO= 对我不起作用,并且在外部构建时无法找到内核头文件。 我的解决方案是将源文件符号链接到 bin 目录中,并在 bin 目录中动态生成一个新的 MakeFile。这样可以轻松清理所有构建文件,因为动态 Makefile 始终可以重新创建。

INCLUDE=include
SOURCE=src
TARGET=mymodule
OUTPUT=bin
EXPORT=package

SOURCES=$(wildcard $(SOURCE)/*.c)

# Depends on bin/include bin/*.c and bin/Makefile
all: $(OUTPUT)/$(INCLUDE) $(subst $(SOURCE),$(OUTPUT),$(SOURCES)) $(OUTPUT)/Makefile
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD)/$(OUTPUT) modules

# Create a symlink from src to bin
$(OUTPUT)/%: $(SOURCE)/%
    ln -s ../$< $@

# Generate a Makefile with the needed obj-m and mymodule-objs set
$(OUTPUT)/Makefile:
    echo "obj-m += $(TARGET).o\n$(TARGET)-objs := $(subst $(TARGET).o,, $(subst .c,.o,$(subst $(SOURCE)/,,$(SOURCES))))" > $@

clean:
    rm -rf $(OUTPUT)
    mkdir $(OUTPUT)

【讨论】:

这是 linux 内核开发的一个非常可悲的证明。在构成 linux 内核的成千上万个问题中,难道没有一个对一个干净的源目录很感兴趣吗?【参考方案2】:

如果您在内核树中构建,您可以使用O 变量:

make O=/path/to/mydir

如果您在内核树(模块或任何其他类型的程序)之外进行编译,则需要将 Makefile 更改为在不同的目录中输出。这里是一个在MY_DIR 目录中输出的 Makefile 规则的小例子:

$(MY_DIR)/test: test.c
    gcc -o $@ $<

然后写:

$ make MY_DIR=/path/to/build/directory

【讨论】:

不幸的是,它在构建外部(树外)内核模块时似乎没有帮助。在我的系统(OpenSUSE 12.1 x86)上,我有一个目录(~/sample),其中包含一个简单内核模块的源代码以及它的 Kbuild 和 Makefile。我将其设为只读并创建了一个构建目录~/sample_build。从后者,我执行了make -C ~/sample O=$(pwd)。构建失败是因为构建系统仍然试图创建~/sample/.tmp_versions 目录以及~/sample 中的.tmp*.o 文件。或许,还需要其他的东西才能让它发挥作用? 另一方面,make ... O=&lt;build_dir&gt; 似乎适用于 in-tree 内核模块。 感谢您的回答,但您的解决方案不适用于内核模块。因为在您的 kernel-module-makefile 中,您必须使用 /lib/modules//build 中的 makefile 调用 make。所以你没有任何 gcc 调用。到目前为止,我当前的解决方案是在编译后移动 bin-dir 中的所有构建文件。问候汤姆 @Tom,在我们的项目中,我们将内核模块的源代码复制到构建树中,然后以通常的方式在那里构建它们。这行得通,但也许有更好的方法,我还不知道。 @Eugene 我还面临构建模块外源代码的问题,O 标志不能完成这项工作。内核 v5.x 及更高版本是否有更好的解决方案?【参考方案3】:

这里也一样,但我使用了一种对我有用的解决方法:

    为每个架构名称(例如“debug_64”)创建一个子目录。 在“debug_64”下:创建所有 .c 和 .h 文件的符号链接。保持相同的结构。 将 makefile 复制到“debug_64”并为 64 Debug 构建设置正确的标志,例如
ccflags-y := -DCRONO_DEBUG_ENABLED 
ccflags-y += -I$(src)/../../../lib/include 
KBUILD_AFLAGS += -march=x86_64 
    记得将相对目录路径设置为下一层,例如../inc 将是 ../../inc。 对每个拱门/轮廓重复相同的操作。 现在我们有了一个源代码、不同的文件夹和不同的 make 文件。 顺便说一句,在内核模块构建的 make 文件中创建配置文件并不是一件容易的工作,因此,我更喜欢为每个架构创建一个 makefile 的副本。

【讨论】:

以上是关于将内核模块构建到特定目录中的主要内容,如果未能解决你的问题,请参考以下文章

如何使用预构建的内核输出目录构建 linux 内核模块?

静态插入linux内核模块

静态插入linux内核模块

如何从内核源将内核模块安装到 lib/modules/

Linux驱动模块编译进内核中

分析 Linux 内核模块