我有一个Makefile规则,需要将shell命令的结果存储到变量中供以后使用。出于某种原因,似乎$(shell)
调用在我的规则匹配时执行,而不是在执行期间遇到它。
该文件如下:
TMPDEV=/tmp/disk.img
$(TMPDEV):
fallocate -l 806354944 $(TMPDEV)
sudo parted --script $(TMPDEV) unit s mklabel msdos \
mkpart primary fat16 2048 526335 \
mkpart primary fat32 526336 1050623 \
mkpart primary NTFS 1050624 1574911 \
quit
$(eval TMPDISK := $(shell sudo partx --verbose -a $(TMPDEV) | tail -1 | cut -d':' -f1))
echo $(TMPDISK)
sudo mkfs.fat -F 16 -n FAT16 $(TMPDISK)p1
至少在TMPDISK
电话之后,才能知道fallocate
的价值是什么;这就是$(eval)
语句延迟到磁盘映像分区之后的原因。
我收到的输出是:
$ make
partx: stat failed /tmp/disk.img: No such file or directory
fallocate -l 806354944 /tmp/disk.img || dd if=/dev/zero of=/tmp/disk.img bs=1b count=1574912
sudo parted --script /tmp/disk.img unit s mklabel msdos \
mkpart primary fat16 2048 526335 \
mkpart primary fat32 526336 1050623 \
mkpart primary NTFS 1050624 1574911 \
quit
echo
在执行任何其他命令之前partx
错误(因此TMPDISK
设置为空)的事实让我认为$(shell)
的调用早于预期。无论如何将shell调用和赋值延迟到TMPDISK
直到相应的行?
答案 0 :(得分:4)
不可能像这样延迟扩展。在将配方的任何部分发送到shell之前,Make始终首先展开整个配方中的所有变量。没有办法推迟"直到以后。
通常,在配方中使用$(shell ...)
并不常见,因为配方已经在shell中运行。通过$(eval ...)
在食谱中设置变量也非常不寻常。
我建议您重写此配方以使用shell变量,而不是变量;这将更容易理解:
TMPDEV=/tmp/disk.img
$(TMPDEV):
fallocate -l 806354944 $(TMPDEV)
sudo parted --script $(TMPDEV) unit s mklabel msdos \
mkpart primary fat16 2048 526335 \
mkpart primary fat32 526336 1050623 \
mkpart primary NTFS 1050624 1574911 \
quit
TMPDISK=$$(sudo partx --verbose -a $(TMPDEV) | tail -1 | cut -d':' -f1); \
echo $$TMPDISK; \
sudo mkfs.fat -F 16 -n FAT16 $${TMPDISK}p1
答案 1 :(得分:2)
我遇到了同样的问题。即使在目标命令运行之前,eval命令也会扩展。以下是Simon Gibbons的回答。
makefile variable assignment under a target
解决方案是为" fallocate"添加另一个目标。命令并将其作为依赖项添加到$(TMPDEV)目标。