从跨目录的对象构建 .ko 时在 Makefile 中使用通配符的问题
Issues with using wildcard in Makefile while build .ko from objects across directory
我将内核模块组织为不同的子组件,因此我可以轻松地 insert/remove 现有的子模块来尝试或集成东西。
目录结构如下图:
foo --+-- Makefile
|
+-- main.c
|
+-- include --+-- foo1.h
| |
| +-- ... (other headers)
|
|
+-- src ------+-- foo1.c
|
+-- ... (other sources)
这是我的 Makefile,
MODULE_NAME = foo
obj-m += $(MODULE_NAME).o
# [approach 1-1]
# SRCS := main.c src/foo1.c
# [approach 1-2]
SRCS := main.c $(wildcard src/*.c)
$(MODULE_NAME)-objs += main.o $(SRCS:.c=.o)
all:
# [2] echo to check if foo-objs values changes
echo $($(MODULE_NAME)-objs)
KCFLAGS="-I$(PWD)/include" \
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
当我试图在上面的 Makefile 中用 [1-2] 替换方法 [1-1] 时,我收到如下所示的警告。
WARNING: "InitFoo1" [.../foo/foo.ko] undefined!
WARNING: "CleanuptFoo1" [.../foo/foo.ko] undefined!
从控制台输出中,我没有看到 src/foo1.c
已编译,就好像我在 Makefile 中使用方法 [1-1]。
# [2] echo to check if foo-objs values changes
echo main.o main.o src/foo1.o
main.o main.o src/foo1.o
KCFLAGS="-I/home/cyng93/experiment/issues/so_kbuild_wildcard/include" \
make -C /lib/modules/4.4.23-PT-ProbeOn-AuditOn+/build M=/home/cyng93/experiment/issues/so_kbuild_wildcard modules
make[1]: Entering directory '/linux'
CC [M] /home/cyng93/experiment/issues/so_kbuild_wildcard/main.o
LD [M] /home/cyng93/experiment/issues/so_kbuild_wildcard/foo.o
Building modules, stage 2.
MODPOST 1 modules
WARNING: "InitFoo1" [/home/cyng93/experiment/issues/so_kbuild_wildcard/foo.ko] undefined!
WARNING: "CleanupFoo1" [/home/cyng93/experiment/issues/so_kbuild_wildcard/foo.ko] undefined!
CC /home/cyng93/experiment/issues/so_kbuild_wildcard/foo.mod.o
LD [M] /home/cyng93/experiment/issues/so_kbuild_wildcard/foo.ko
make[1]: Leaving directory '/linux'
我尝试回显 foo-objs
(检查 Makefile 中的 [2])并发现方法 [1-1] 和 [1-2] 的值相同。
SO 上有没有人提出类似的问题可以帮助解决一些问题?
(我更喜欢[1-2],因为它可以节省我在添加新子组件时更新Makefile的精力)
下面我也附上了main.c
, foo1.c
& foo1.h
的源码。
您还可以检查 github repo for this issue 以便更轻松地访问这些代码。
main.c
#include <linux/module.h>
#include "foo1.h"
static int myinit(void)
{
printk("Module inserted!\n");
InitFoo1();
return 0;
}
static void myexit(void)
{
CleanupFoo1();
printk("Module removed!\n");
}
module_init(myinit);
module_exit(myexit);
MODULE_LICENSE("GPL v2");
这里,foo1
是一个子组件,在它的初始化和清理过程中简单地打印一些东西:
./include/foo1.h
#ifndef FOO1_H
#define FOO1_H
int InitFoo1(void);
void CleanupFoo1(void);
#endif
./src/foo1.c
#include <linux/module.h>
#include "foo1.h"
int InitFoo1(void)
{
printk("Init Foo1\n");
return 0;
}
void CleanupTest(void)
{
printk("Cleanup Foo1\n");
}
update_2018/01/15
根据下面的 Tsyvarev 回答,可以通过如下修改 Makefile 来更正 Makefile:
MODULE_NAME = foo
obj-m += $(MODULE_NAME).o
# [approach 1-1]
# SRCS := main.c src/foo1.c
# [approach 1-2 (not working)]
# SRCS := main.c $(wildcard src/*.c)
# [approach 1-2 (working)]
MISC := $($(src)/wildcard src/*.c)
SRCS := main.c $(MISC:$(src)%/=%)
$(MODULE_NAME)-objs += main.o $(SRCS:.c=.o)
all:
# [2] echo to check if foo-objs values changes
echo $($(MODULE_NAME)-objs)
KCFLAGS="-I$(PWD)/include" \
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
构建内核模块时,您的 Makefile
被处理 两次 :
- 当您从模块目录中键入
make
时。
- 在 Kbuild 进程中,因为您将
M=$(PWD)
选项传递给它。
第一次处理 Makefile 时,当前目录等于模块的目录。因此通配符按预期工作,这通过从 all
收据打印得到确认。
但是第二次处理 Makefile 时,当前目录等于内核的构建目录(在您的情况下为/lib/modules/4.4.23-PT-ProbeOn-AuditOn+/build
)。在那种模式下
$(wildcard src/*.c)
试图在内核的构建目录中查找文件,显然失败了。
在第二次处理时,可以使用 $(src)
.
引用模块的构建目录
这样可以使用 wildcard()
收集模块的源代码。但请注意,内核构建系统期望源文件的路径(更准确地说,对象 文件)是相对于模块的构建目录。因此,需要从 wildcard()
.
获得的每个文件中剥离 $(src)
组件
我将内核模块组织为不同的子组件,因此我可以轻松地 insert/remove 现有的子模块来尝试或集成东西。
目录结构如下图:
foo --+-- Makefile
|
+-- main.c
|
+-- include --+-- foo1.h
| |
| +-- ... (other headers)
|
|
+-- src ------+-- foo1.c
|
+-- ... (other sources)
这是我的 Makefile,
MODULE_NAME = foo
obj-m += $(MODULE_NAME).o
# [approach 1-1]
# SRCS := main.c src/foo1.c
# [approach 1-2]
SRCS := main.c $(wildcard src/*.c)
$(MODULE_NAME)-objs += main.o $(SRCS:.c=.o)
all:
# [2] echo to check if foo-objs values changes
echo $($(MODULE_NAME)-objs)
KCFLAGS="-I$(PWD)/include" \
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
当我试图在上面的 Makefile 中用 [1-2] 替换方法 [1-1] 时,我收到如下所示的警告。
WARNING: "InitFoo1" [.../foo/foo.ko] undefined!
WARNING: "CleanuptFoo1" [.../foo/foo.ko] undefined!
从控制台输出中,我没有看到 src/foo1.c
已编译,就好像我在 Makefile 中使用方法 [1-1]。
# [2] echo to check if foo-objs values changes
echo main.o main.o src/foo1.o
main.o main.o src/foo1.o
KCFLAGS="-I/home/cyng93/experiment/issues/so_kbuild_wildcard/include" \
make -C /lib/modules/4.4.23-PT-ProbeOn-AuditOn+/build M=/home/cyng93/experiment/issues/so_kbuild_wildcard modules
make[1]: Entering directory '/linux'
CC [M] /home/cyng93/experiment/issues/so_kbuild_wildcard/main.o
LD [M] /home/cyng93/experiment/issues/so_kbuild_wildcard/foo.o
Building modules, stage 2.
MODPOST 1 modules
WARNING: "InitFoo1" [/home/cyng93/experiment/issues/so_kbuild_wildcard/foo.ko] undefined!
WARNING: "CleanupFoo1" [/home/cyng93/experiment/issues/so_kbuild_wildcard/foo.ko] undefined!
CC /home/cyng93/experiment/issues/so_kbuild_wildcard/foo.mod.o
LD [M] /home/cyng93/experiment/issues/so_kbuild_wildcard/foo.ko
make[1]: Leaving directory '/linux'
我尝试回显 foo-objs
(检查 Makefile 中的 [2])并发现方法 [1-1] 和 [1-2] 的值相同。
SO 上有没有人提出类似的问题可以帮助解决一些问题?
(我更喜欢[1-2],因为它可以节省我在添加新子组件时更新Makefile的精力)
下面我也附上了main.c
, foo1.c
& foo1.h
的源码。
您还可以检查 github repo for this issue 以便更轻松地访问这些代码。
main.c
#include <linux/module.h>
#include "foo1.h"
static int myinit(void)
{
printk("Module inserted!\n");
InitFoo1();
return 0;
}
static void myexit(void)
{
CleanupFoo1();
printk("Module removed!\n");
}
module_init(myinit);
module_exit(myexit);
MODULE_LICENSE("GPL v2");
这里,foo1
是一个子组件,在它的初始化和清理过程中简单地打印一些东西:
./include/foo1.h
#ifndef FOO1_H
#define FOO1_H
int InitFoo1(void);
void CleanupFoo1(void);
#endif
./src/foo1.c
#include <linux/module.h>
#include "foo1.h"
int InitFoo1(void)
{
printk("Init Foo1\n");
return 0;
}
void CleanupTest(void)
{
printk("Cleanup Foo1\n");
}
update_2018/01/15
根据下面的 Tsyvarev 回答,可以通过如下修改 Makefile 来更正 Makefile:
MODULE_NAME = foo
obj-m += $(MODULE_NAME).o
# [approach 1-1]
# SRCS := main.c src/foo1.c
# [approach 1-2 (not working)]
# SRCS := main.c $(wildcard src/*.c)
# [approach 1-2 (working)]
MISC := $($(src)/wildcard src/*.c)
SRCS := main.c $(MISC:$(src)%/=%)
$(MODULE_NAME)-objs += main.o $(SRCS:.c=.o)
all:
# [2] echo to check if foo-objs values changes
echo $($(MODULE_NAME)-objs)
KCFLAGS="-I$(PWD)/include" \
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
构建内核模块时,您的 Makefile
被处理 两次 :
- 当您从模块目录中键入
make
时。 - 在 Kbuild 进程中,因为您将
M=$(PWD)
选项传递给它。
第一次处理 Makefile 时,当前目录等于模块的目录。因此通配符按预期工作,这通过从 all
收据打印得到确认。
但是第二次处理 Makefile 时,当前目录等于内核的构建目录(在您的情况下为/lib/modules/4.4.23-PT-ProbeOn-AuditOn+/build
)。在那种模式下
$(wildcard src/*.c)
试图在内核的构建目录中查找文件,显然失败了。
在第二次处理时,可以使用 $(src)
.
这样可以使用 wildcard()
收集模块的源代码。但请注意,内核构建系统期望源文件的路径(更准确地说,对象 文件)是相对于模块的构建目录。因此,需要从 wildcard()
.
$(src)
组件