我有一个 Makefile 规则,需要将 shell 命令的结果存储到变量中以备后用。出于某种原因,似乎$(shell)
call 在我的规则匹配后立即执行,而不是在执行期间遇到它。
该文件如下:
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
直到合适的行?
最佳答案
不可能像这样延迟扩张。 Make 总是首先扩展整个配方中的所有变量,然后再将配方的任何部分发送到 shell。没有办法“推迟”到以后。
一般来说,使用 $(shell ...)
并不典型。在配方中,因为配方已经在 shell 中运行。并通过 $(eval ...)
在配方中设置 make 变量也是极不寻常的。
我建议你重写这个秘籍以使用 shell 变量,而不是 make 变量;它会更容易理解:
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
关于Makefile 变量赋值提前执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22999306/