2017-06-01 27 views
1

我有一个足够大的项目,可以通过目录对文件进行分类。我试图建立一个一个内核模块。如何链接其他目录中的文件?

documentation状态如下:

--- 3.6 Descending down in directories 

A Makefile is only responsible for building objects in its own 
directory. Files in subdirectories should be taken care of by 
Makefiles in these subdirs. The build system will automatically 
invoke make recursively in subdirectories, provided you let it know of 
them. 

To do so, obj-y and obj-m are used. 
ext2 lives in a separate directory, and the Makefile present in fs/ 
tells kbuild to descend down using the following assignment. 

Example: 
    #fs/Makefile 
    obj-$(CONFIG_EXT2_FS) += ext2/ 

If CONFIG_EXT2_FS is set to either 'y' (built-in) or 'm' (modular) 
the corresponding obj- variable will be set, and kbuild will descend 
down in the ext2 directory. 

然而,这似乎是从我需要什么不同。这是两个独立的.ko文件;每个目录中有一个,每个目录文件在其自己的目录中合并。

这是我的项目(简体):

root directory 
| 
+--- Makefile 
| 
+--- foo.c 
| 
+--- subdir 
     | 
     +--- Makefile 
     | 
     +--- bar.c 

我会认为像这样的东西碰得将是合理的:

root directory 
| 
+--- Makefile 
| 
+--- foo.c 
| 
+--- foo.o (containing foo.c's stuff) 
| 
+--- subdir 
|  | 
|  +--- Makefile 
|  | 
|  +--- bar.c 
|  | 
|  +--- bar.o (containing bar.c's stuff) 
| 
+--- kernel-module.ko (containing foo.o and subdir/bar.o) 

我真的结束了是这样的:

root directory 
| 
+--- Makefile 
| 
+--- foo.c 
| 
+--- foo.o (containing foo.c's stuff) 
| 
+--- subdir 
|  | 
|  +--- Makefile 
|  | 
|  +--- bar.c 
|  | 
|  +--- bar.o (containing bar.c's stuff) 
|  | 
|  +--- bar.ko (containing bar.o) 
| 
+--- kernel-module.ko (containing only foo.o) 

我希望每个目录建立一个模块不是K的基本假设构建的设计。运输几个模块听起来像是一团糟,没有收获。

这是我的根Makefile

KERNEL_DIR ?= /lib/modules/$(shell uname -r)/build 

obj-m += kernel-module.o 
obj-m += subdir/ 
kernel-module-objs += foo.o 

all: 
    make -C ${KERNEL_DIR} M=$$PWD 
modules: 
    make -C ${KERNEL_DIR} M=$$PWD [email protected] 
clean: 
    make -C ${KERNEL_DIR} M=$$PWD [email protected] 

这是subdir/Makefile

obj-m += bar.o 

这是foo.c

int external_function(void); 

int test(void) 
{ 
    return external_function(); 
} 

这是subdir/bar.c

int external_function(void) 
{ 
    return 4; 
} 

make(根目录)吐以下警告:

WARNING: "external_function" [(...)/kernel-module.ko] undefined! 

而我试图插入kernel-module.ko被拒绝:

$ sudo insmod kernel-module.ko 
insmod: ERROR: could not insert module kernel-module.ko: Unknown symbol in module 
$ dmesg | tail -1 
[11688.540153] kernel_module: Unknown symbol external_function (err 0) 

我怎么告诉kbuild的是subdir/bar.o应该成为kernel-module.ko的一部分,而不是它自己的模块?

+0

该文档中的建议不好,或者至少不清楚。你的源文件是'foo.c','bar.c'和'bar.h';他们在哪?你想在顶部目录或'subdir /'或'build /'或其他地方使用目标文件'foo.o'和'bar.o'吗?同样,你想在哪里最终产品'outside.ko'? – Beta

+0

@贝塔:感谢您的提问。我在编辑时找到了解决方案。但为了完整起见,以下是您的答案:'foo.c'位于根目录中,'bar.c'属于'subdir /'。生成的文件最终不在这个问题的范围内;我更关心他们的内容。我真的希望他们最终会在'build /'中,但看到我的编辑可以接受的结果。 –

+0

@Beta:另外:关于'bar.h',我最终把它从问题中删除了,因为它是不需要的。关键是,foo可以看到酒吧的声明,但不是它的定义。 –

回答

0

一个解决方案是将bar的目标文件追加到内核模块的目标列表中。这段代码的问题:

obj-m += kernel-module.o 
obj-m += subdir/ 
kernel-module-objs += foo.o 

的是,它告诉kbuild的下降到subdir/,但它不告诉它包括在kernel-module的那个结果。

这将解决这个问题:

obj-m += kernel-module.o 
obj-m += subdir/ 
kernel-module-objs += foo.o subdir/bar.o 

但是,因为它打破了DRY原则,我不喜欢这样的解决方案都:这意味着bar.o已被命名为两次;一个在/Makefile,另一个在/subdir/Makefile

此外,此解决方案不会阻止Kbuild创建冗余subdir/bar.ko模块。

最后,某些documentation指出这是“不推荐的做法”,因为某些完全没有说明的原因。

所以这个解决方案非常糟糕。我不认为我会坚持下去。


另一种解决方案(其与前一个分支)是只删除subdir/Makefile和,根生成文件内,而不是这样的:

obj-m += kernel-module.o 
obj-m += subdir/ 
kernel-module-objs += foo.o 

做到这一点:

obj-m += kernel-module.o 
kernel-module-objs += foo.o subdir/bar.o 

这解决了DRY问题,并防止产生subdir/bar.ko,但仍受到不鼓励的练习。

在此期间我会坚持这个解决方案,但既然他们都不是理想的,我想我会留下一段时间的问题。

+0

我同意不鼓励这种做法。 – 0andriy

+0

@ 0andriy whyyy? –

相关问题