【问题标题】:Out of tree kernel modules: Multiple module, single Makefile, same source file, different build optionsOut of tree 内核模块:多个模块、单个 Makefile、相同的源文件、不同的构建选项
【发布时间】:2013-08-23 16:57:46
【问题描述】:

我正在使用共享源代码构建一组 Linux 内核模块。据我了解,Makefile 必须命名为“Makefile”,所以我必须使用相同的 Makefile 来构建两个不同的模块。如何在同一个 Makefile 中使用相同的源代码,但使用两个不同的构建选项构建两个不同的模块?

例如,我的模块被称为 module1 和 module2。所以我有以下行来定义它们:

obj-m := module1.o module2.o

在其他文件中,module1 和 module2 都需要使用相同的源文件code.c,但使用不同的构建选项构建。例如,Makefile 包含以下几行:

module1-objs = module1_code.o other_code.o
module2-objs = module2_code.o other_code.o

我希望 module1_code.omodule2_code.o 从 code.c 构建,但有不同的选项。具体来说,我想要一个 module1_code.o,其中定义了一个宏 -DPREPROCEFFOR_FLAG=1,而 module2_code.o 构建时没有宏。

据我了解,Linux 中使用的 Makefiles 系统隐含地推断,对于名为“code.o”的目标文件,源文件名为“code.c”,那么我该如何实现呢?有可能吗?有没有更好的方法来做到这一点?

【问题讨论】:

  • 你可以随意命名你的makefile。默认情况下,make 只会查找certain filenames。对于任何其他名称,您需要使用 -f 参数。
  • 如果您为您的目标文件制定特定规则,并以相关源文件为先决条件,并且构建目标文件的规则将使用该规则而不是您提到的默认规则。所以module1_code.o: code.c ; <command to build>.
  • 树外构建也可以解决这个问题:stackoverflow.com/questions/5718899/…

标签: makefile linux-kernel linux-device-driver


【解决方案1】:

这里有一个问题,因为在定义 -DPREPROCEFFOR_FLAG=1 时,您显然对 code.c 进行了不同的编译,但是一旦将其编译为 code.o,make 就不会关心预处理器标志或其他任何东西,因为 code.o 会已经是最新的了。

您需要一种将code.c 构建到具有不同C 标志的不同目标文件的方法。可能有一种干净的方法可以做到这一点(对于树外模块,O= 没有机会),但这是我目前不雅但有效的解决方案:

my_modules:
    cp code.c code_noflags.c
    cp code.c code_withflags.c
    make -C $$KDIR M=$$PWD modules
    rm code_noflags.c code_withflags.c

# module objects
obj-m := module1.o module2.o

# module1 specifics
module1-y := code_withflags.o
CFLAGS_code_withflags.o := -DPREPROCEFFOR_FLAG=1

# module2 specifics
module2-y := code_noflags.o

只要打电话:

$ make KDIR=/path/to/kernel

您可以通过以下方式验证预处理器标志是否已传递给正确对象的源文件:

$ make KDIR=/path/to/kernel V=1 | grep PREPRO

如果可能的话,您还可以为每个模块创建两个单独的目录,并在每个目录中都有一个符号链接code.c,指向共同的实数code.c。但是,这仍然是 hackish,感觉不对。

【讨论】:

  • 一种(可能同样不优雅)的解决方案是创建一个指向 code.c 的 sim-link,即 code-link.c,然后使用替代标志编译链接文件。
【解决方案2】:

一个简单的解决方案是,从您的 Makefile 继续

obj-m := module1.o module2.o

module1-objs = module1_code.o other_code.o
module2-objs = module2_code.o other_code.o

再添加两个源文件,module1_code.c 和 module2_code.c。

然后 module1_code.c 看起来像:

#define PREPROCEFFOR_FLAG 1
#include "code.c"

module2_code.c 是:

#include "code.c"

或者,如果您愿意,可以更改 Makefile 和源文件中的名称,这样就不需要没有定义的第二个包含。如果您愿意,您也可以将这两个源文件制作成一个包含并使用CFLAGS_module1_code.o 变量将-D... 选项添加到编译器。

这类似于arch/x86/boot/video-vesa.carch/x86/realmode/rm/video-vesa.c 等上游内核中发生的情况,其中实模式文件仅包含:

#include "../../boot/video-vesa.c"

并且 video-vesa.c 代码最终会使用不同的编译器标志编译两次。

这似乎比复制源文件更可取,因为如果您想在内核构建中使用O=... 选项来保持干净的源树并在单独的对象树中构建,那么您最终会遇到一团糟。

【讨论】:

    猜你喜欢
    • 2012-11-16
    • 1970-01-01
    • 2016-06-12
    • 1970-01-01
    • 2011-03-06
    • 1970-01-01
    • 1970-01-01
    • 2020-01-26
    相关资源
    最近更新 更多