从跨目录的对象构建 .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 被处理 两次 :

  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) 组件