【问题标题】:Makefile variable yields different resultsMakefile 变量产生不同的结果
【发布时间】:2017-10-20 19:28:26
【问题描述】:

我正在为一个爱好 OS 项目编写脚本。在使用脚本时,我注意到(几乎)同一个变量的两个不同的变量扩展会产生不同的结果(即使它们“直接”放置在彼此之后)。我将提供 makefile 的重要部分以及运行时的结果。

生成文件:

####################
#      KERNEL      #
####################
.PHONY: kernel

KERNEL_OBJS  = $(patsubst %.c,%.o,$(wildcard kernel/*.c))
KERNEL_OBJS += $(patsubst %.asm,%.o,$(wildcard kernel/*.asm))
KERNEL_OBJS += $(DRIVER_OBJS)
KERNEL_NAME  = kernel32.elf

kernel: $(KERNEL_OBJS)
    @echo $^
    @echo $(KERNEL_OBJS)


####################
#     DRIVERS      #
####################
.PHONY: drivers

DRIVER_OBJS := $(patsubst %.c,%.o,$(wildcard drivers/*/*.c))

Makefile 以下列方式通过终端执行(GNU Make 4.2.1):

make kernel

这会产生以下结果:

kernel/kmain.o kernel/boot.o
kernel/kmain.o kernel/boot.o drivers/vga/vga.o

输出线当然来自内核配方中的两条“回声线”。值得一提的是,此代码-sn-p 中使用的所有变量都在here and only here在其他较大的make-script中使用。两个常规后缀规则用于构建KERNEL_OBJS,但无论如何它们都不应该改变这里的输出。除了后缀规则之外,这个 sn-p 及其变量与脚本的其余部分完全分开。

任何想法为什么两个变量扩展不同?你的,米凯尔。

【问题讨论】:

    标签: makefile gnu-make


    【解决方案1】:

    两种上下文之间的最大区别在于,先决条件列表在解析 makefile 时立即扩展,但配方仅在稍后 make 即将构建该目标时扩展。 p>

    当 make 第一次解析你的 makefile 时,它​​会找到这一行:

    kernel: $(KERNEL_OBJS)
    

    它立即扩展这个变量。当变量展开时,DRIVER_OBJS 变量尚未设置,所以它是空字符串,你会得到:

    kernel: kernel/kmain.o kernel/boot.o
    

    然后 make 完成对所有 makefile 的解析,作为其中的一部分,设置了 DRIVER_OBJS 变量...但这与上面的行无关,因为它已经被扩展了。

    现在 make 决定要构建 kernel 目标,为此它必须扩展配方:

    @echo $^
    @echo $(KERNEL_OBJS)
    

    这里$^ 是先决条件列表:kernel/kmain.o kernel/boot.o。现在 KERNEL_OBJS 已展开,现在 DRIVER_OBJS 已设置,因此您将获得完整列表。

    请参阅How make Reads a Makefile 了解有关何时发生扩展的完整详细信息。

    【讨论】:

    • 您如何看待这种将整个全局文件列表作为依赖概念作为先决条件的方法,尤其是在引用的位置不是只读目录的情况下?
    • 谢谢@MadScientist!
    • 我个人从不在我的 makefile 中使用通配符。我总是直接列出所有源文件。源文件列表不会经常更改,以至于这是一个负担,我更愿意确切地知道我正在编译到我的程序中,并且不允许我碰巧创建的一些随机源文件作为测试或类似的进入道路。不过,这只是我的偏好。
    【解决方案2】:

    您可以激活第二个扩展,然后在依赖项中使用它:

    .SECONDEXPANSION:
    kernel: $$(KERNEL_OBJS)
    

    【讨论】:

    • 非常好!感谢您提供新知识!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-08-12
    • 2018-05-23
    • 2017-09-11
    • 2020-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多