我在Makefile配方中使用$(shell ...)gnu make函数,它首先在前面的行之前运行。为什么?
一个非常简单的示例:
.PHONY: all
all:
@echo 1
@echo $(eval a=$(shell echo 2a 1>&2))2b
@echo 3 $(a)
输出为:
2a
1
2b
3
首先运行$(shell ...)行(2a),然后运行其他行。当行在配方中按此顺序运行时,如何管理$(shell ...)函数?
1
2a
2b
3
编辑:
没有$(shell ...),它可以正常工作,我期望:
.PHONY: all
all:
@echo 1
$(eval a=a)
@echo 2 $(a)
$(eval a=b)
@echo 3 $(a)
输出:
1
2 a
3 b
编辑2:这是原始Makefile的一部分。粗体显示了我的问题的本质:我想将udisksctl的输出放入一个make变量中,而不是文件$ @。loop中(并使用$ @。mount进行同样的操作)。
$(HDIMG): $(BOOTBLOCK_MBR_BIN) $(BOOTBLOCK_EXT2_BIN) $(LOADER_BIN) | $(DESTDIR)
dd if=/dev/zero [email protected] bs=1 seek=$(PSIZEB) count=0 2>/dev/null
$(MKFSEXT2) -F [email protected] >/dev/null
dd if=$(word 2,$^) [email protected] conv=notrunc 2>/dev/null
cp $< $@
dd if=/dev/zero of=$@ bs=1 seek=$(HDSIZEB) count=0 2>/dev/null
echo $(PFDISK) | $(TR) | $(FDISK) $@ >/dev/null
dd [email protected] of=$@ bs=512 seek=$(PSTART) conv=sparse,notrunc iflag=fullblock 2>/dev/null
**udisksctl loop-setup --file $@ --offset $(PSTARTB) --size $(PSIZEB) >[email protected]**
sed -i -e 's/.* //;s/\.//' [email protected]
cat [email protected]
udisksctl mount --block-device **$$(cat [email protected])** >[email protected]
sed -i -e 's/.* //;s/\.//' [email protected]
cat [email protected]
#
mkdir -p $$(cat [email protected])/boot/
cp $(word 2,$^) $$(cat [email protected])/boot/
#/sbin/filefrag -b512 -e /
#
udisksctl unmount --block-device $$(cat [email protected])
udisksctl loop-delete --block-device $$(cat [email protected])
rm [email protected]
make
运行配方时,它first展开其中的所有变量/功能,而then逐行运行shell命令。
您可以通过使用$(shell ...)
执行every shell命令来解决此问题,或者在您的情况下,使用$(info ...)
而不是echo
:
.PHONY: all
all:
$(info 1)
$(info $(eval a=$(shell echo 2a 1>&2))2b)
$(info 3 $(a))
输出:
1
2a
2b
3
make: Nothing to be done for 'all'.
Nothing to be done for 'all'.
部分是由于以下事实引起的:展开功能后,配方实际上为空(具有0个Shell命令)。向其添加无操作命令(例如@true
)会删除该消息。