超出树内核模块:多个模块,单个Makefile,相同的源文件,不同的构建选项

时间:2013-08-22 16:33:02

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

我正在使用共享源代码构建一组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

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

据我所知,Linux中使用的Makefile系统隐含地推断出对于名为“code.o”的目标文件,源文件称为“code.c”,那么我该如何实现呢?有可能吗?有更好的方法吗?

2 个答案:

答案 0 :(得分:5)

这里有一个问题,因为在定义code.c时你显然会对-DPREPROCEFFOR_FLAG=1进行不同的编译,但是一旦编译成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,感觉不对。

答案 1 :(得分: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等所发生的情况,其中realmode文件只包含:

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

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

这似乎比复制源文件更好,因为如果你想在内核版本中使用O=...选项来保持一个干净的源代码树并构建一个单独的对象树,你就会陷入混乱。