即使在声明中使用 :=,Makefile 变量替换显然也没有完成

发布于 2024-12-25 08:28:12 字数 1335 浏览 1 评论 0原文

我有一个主内核模块,其他内核模块可以与它进行通信。我已经像这样构建了模块(概念上):

main module/
           |
            \drivers/
                    |
                    |\driver1
                    |\driver2
                     \driver3

由于这些是内核模块,我需要像这样编译它们:

make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules

但是,由于可以从以前的目录调用驱动程序的 Makefile,所以我需要执行 $(shell pwd) 在调用其他 make(linux 的 make)之前。所以 Makefile 现在看起来像这样:

CURRENT_DIR := $(shell pwd)

.PHONY: all
all:
    $(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(CURRENT_DIR) modules

到目前为止,一切都很好并且工作完美。问题是这样的:我有一个驱动程序需要包含的文件,所以我必须给出要生成的包含路径。我第一次尝试

EXTRA_CFLAGS += -I../..

并立即理解为什么它不起作用(相对路径是 /lib/module/... 而不是当前目录)。所以我把它改成了:

MAIN_MODULE_HOME := $(CURRENT_DIR)/../..
EXTRA_CFLAGS += -I$(MAIN_MODULE_HOME)

奇怪的是,这不起作用!如果我手动编写

EXTRA_CFLAGS += -Ipath/I/get/from/pwd/../..

,它会编译!有人可以解释我做错了什么吗?在调用 make 之前,我 echoed $(CURRENT_DIR)$(MAIN_MODULE_HOME) 并且这些变量是有意义的。

我知道 EXTRA_CFLAGS 不会立即评估,但由于 CURRENT_DIRMAIN_MODULE_HOME 是用 := 声明的,我不知道不明白事情是如何变得一团糟的。

(如果有人能更好地表达问题标题,请这样做!)

I have a main kernel module with which other kernel modules communicate. I have structured the modules like this (conceptually):

main module/
           |
            \drivers/
                    |
                    |\driver1
                    |\driver2
                     \driver3

Since these are kernel modules, I need to compile them like this:

make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules

However, since the Makefile of drivers can be called from previous directories, I need to do the $(shell pwd) before calling the other make (linux's make). So the Makefile now looks like this:

CURRENT_DIR := $(shell pwd)

.PHONY: all
all:
    $(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(CURRENT_DIR) modules

So far it is fine and it works perfectly. The problem is this: I have a file that the drivers need to include, so I have to give the include path to make. I first tried

EXTRA_CFLAGS += -I../..

and immediately understood why it doesn't work (relative path would be to /lib/module/... not to current directory). So I changed it to:

MAIN_MODULE_HOME := $(CURRENT_DIR)/../..
EXTRA_CFLAGS += -I$(MAIN_MODULE_HOME)

Oddly enough, this doesn't work! If I write

EXTRA_CFLAGS += -Ipath/I/get/from/pwd/../..

manually, it compiles! Can someone explain what I am doing wrong? Before calling make, I echoed $(CURRENT_DIR) and $(MAIN_MODULE_HOME) and the variables are meaningful.

I know that EXTRA_CFLAGS is not immediately evaluated, but since CURRENT_DIR and MAIN_MODULE_HOME are declared with := I don't understand how things are getting messed up.

(If anyone can phrase the question title better, please do!)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

月亮坠入山谷 2025-01-01 08:28:12

您应该像这样传递 EXTRA_CFLAGS 来 make:

$(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(CURRENT_DIR) \
           EXTRA_CFLAGS="$(EXTRA_CFLAGS)" modules

更新:

driver1/Makefile 的内容被读取两次:第一次 - 当您在 driver1 目录中运行 make 时,第二次 - 由 Kbuild 系统读取。

首先,CURRENT_DIR := $(shell pwd) 被评估为类似 /home/users/.../main module/drivers/driver1 的内容。其次,Kbuild 将 CURRENT_DIR := $(shell pwd) 评估为类似 /usr/src/linux-headers-2.6.32-33-generic/

中描述的情况LDD3、ch2、p24

技巧是按如下方式编写 makefile:

# If KERNELRELEASE is defined, we've been invoked from the
# kernel build system and can use its language.
ifneq ($(KERNELRELEASE),)
    obj-m := hello.o
# Otherwise we were called directly from the command
# line; invoke the kernel build system.
else
    KERNELDIR ?= /lib/modules/$(shell uname -r)/build
    PWD  := $(shell pwd)
default:
    $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
#endif

You should pass EXTRA_CFLAGS to make like this:

$(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(CURRENT_DIR) \
           EXTRA_CFLAGS="$(EXTRA_CFLAGS)" modules

Update:

The content of driver1/Makefile is read twice: first - when you run make inside driver1 directory, second - by Kbuild system.

First, CURRENT_DIR := $(shell pwd) is evaluated to something like /home/users/.../main module/drivers/driver1. Second, Kbuild evaluates CURRENT_DIR := $(shell pwd) to something like /usr/src/linux-headers-2.6.32-33-generic/

That situation described in LDD3, ch2, p24

The trick is to write your makefile as follows:

# If KERNELRELEASE is defined, we've been invoked from the
# kernel build system and can use its language.
ifneq ($(KERNELRELEASE),)
    obj-m := hello.o
# Otherwise we were called directly from the command
# line; invoke the kernel build system.
else
    KERNELDIR ?= /lib/modules/$(shell uname -r)/build
    PWD  := $(shell pwd)
default:
    $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
#endif
美男兮 2025-01-01 08:28:12

这很可能是因为 EXTRA_CFLAGS 的递归风格,它实际上是在子 make 中扩展的,而子 make 无法访问从中引用的 MAIN_MODULE_HOME

首先,尝试导出 MAIN_MODULE_HOME

export MAIN_MODULE_HOME

在使用它之前,我还尝试展平 EXTRA_CFLAGS(但是,我不确定这是否是一个Kbuild 的良好实践):

EXTRA_CFLAGS := $(EXTRA_CFLAGS)

It most likely because of recursive flavor of EXTRA_CFLAGS, which gets actually expanded in a sub-make, which doesn't have an access to MAIN_MODULE_HOME referred from it.

First, try to export MAIN_MODULE_HOME:

export MAIN_MODULE_HOME

I would also tried to flatten EXTRA_CFLAGS before using it (however, I'm not sure whether this is a good practice for Kbuild):

EXTRA_CFLAGS := $(EXTRA_CFLAGS)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文