gpt4 book ai didi

linux - 从跨目录的对象构建 .ko 时在 Makefile 中使用通配符的问题

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:17:50 25 4
gpt4 key购买 nike

我将内核模块组织为不同的子组件,因此我可以轻松地插入/删除现有的子模块来尝试或集成东西。

目录布局如下图所示:

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.cfoo1.c & foo1.h的源码。您还可以检查 github repo for this issue以便更轻松地访问这些代码。


主.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 被处理两次:

  1. 当您从模块的目录中键入 make 时。
  2. 在 Kbuild 进程中,因为您将 M=$(PWD) 选项传递给它。

第一次处理 Makefile 时,当前目录等于模块的目录。所以通配符按预期工作,这通过打印 all 收据得到确认。

但是第二次处理 Makefile 时,当前目录等于内核的构建目录 (/lib/modules/4.4.23-PT-ProbeOn-AuditOn+/build在你的情况下)。在那种模式下

$(wildcard src/*.c)

试图在内核的构建目录中查找文件,显然失败了。


在第二次处理时,可以使用 $(src) 引用模块的构建目录。

这样可以使用wildcard() 来收集模块的源代码。但请注意,内核构建系统希望源文件路径(更准确地说,对象 文件)相对于模块的构建目录。因此,需要去除使用 wildcard() 获得的每个文件的 $(src) 组件。

关于linux - 从跨目录的对象构建 .ko 时在 Makefile 中使用通配符的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48223341/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com