我正在为一个业余爱好OS项目制作一个make脚本。在使用脚本时,我注意到(几乎)相同变量的两个不同的变量扩展会产生不同的结果(即使它们直接放置在彼此之后)。我将提供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
输出线当然来自两条回声线'在内核配方中。值得一提的是,此代码片段中使用的所有变量都使用此处,仅在此处用于更大的make脚本。两个常规后缀规则用于构建 KERNEL_OBJS ,但它们不应该改变输出。除了后缀规则之外,此片段及其变量与脚本的其余部分完全分开。
为什么两个变量扩展有何不同?你的,Mikael。
答案 0 :(得分:0)
两个上下文之间的最大区别在于,在解析makefile时,先决条件列表会立即扩展 ,但是当make即将构建该目标时,配方仅在稍后扩展。
当make首先解析你的makefile时,它会找到这一行:
kernel: $(KERNEL_OBJS)
它会立即扩展此变量。当变量被展开时,DRIVER_OBJS
变量尚未设置,所以它是空字符串,你得到这个:
kernel: kernel/kmain.o kernel/boot.o
然后make完成解析所有makefile并作为其中的一部分设置DRIVER_OBJS
变量......但这对上面的行并不重要,因为它已经被扩展了。
现在决定要构建kernel
目标,为了做到这一点,必须扩展配方:
@echo $^
@echo $(KERNEL_OBJS)
此处$^
是先决条件列表:kernel/kmain.o kernel/boot.o
。现在KERNEL_OBJS
已展开,现在已设置DRIVER_OBJS
,因此您可以获得完整列表。
有关扩展何时发生的详细信息,请参阅How make Reads a Makefile。
答案 1 :(得分:0)
您可以激活第二次扩展,然后在依赖项中使用它:
let title = ["title1","title2","title3","title4","title5"]
override func viewWillAppear(_ animated: Bool) {
self.viewModel.index.value = 0
self.viewModel.index
.asObservable()
.map( {self.periodText[$0]
})
.bind(to: self.titleLabel.rx.text)
.addDisposableTo(self.disposeBag)
}