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

标签 linux makefile wildcard kernel-module kbuild

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

目录布局如下图所示:

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/

相关文章:

mysql - 全文多字符串搜索

linux - bash - 将 ls 重定向到自定义脚本

c++ - 应用程序因 _Unwind_Resume 中止错误而崩溃

linux - 压缩 Bash 脚本以解析文件

PHP 文件/目录统计相关函数在已安装的 CIFS 上不起作用

python - 一种通过使用通配符更改文件名中的索引来迭代一个规则的方法(在 snakemake 中)

使用外部 makefile 进行正确的语法检查

variables - 如何更改 makefile 变量文件扩展名?

gcc - 编译PJSIP示例

php - WHERE 语句中的 mySql 正则表达式