In one of my Makefile recipes, I want to create a temporary file, pass the name of that file to a shell command and assign the output of that command to a make variable so that I can use that subsequently. For the life of me, I cannot get it to work.
For the purpose of debugging I have tried to boil down the problem to the most simple target I could come up with:
.PHONY: foo
foo:
$(eval TMPFILE = $(shell mktemp -p ./))
dd if=/dev/random of=${TMPFILE} bs=1 count=512
$(eval FOO = $(shell wc -c ${TMPFILE}))
@echo FOO: ${FOO}
Here is what happens:
❯ make foo
dd if=/dev/random of=./tmp.K1au4WrZ76 bs=1 count=512
512 0 records in
512 0 records out
512 bytes copied, 0.00287818 s, 178 kB/s
FOO: 0 ./tmp.K1au4WrZ76
So somehow, wc
thinks the file is empty. But when I check the TMPFILE it has 512 bytes, as expected:
❯ wc -c tmp.K1au4WrZ76
512 tmp.K1au4WrZ76
Can someone, please enlighten me what is going on here and how to do that correctly?
Thanks Phil
Update: Based on the answer I put together this target which works as desired:
.PHONEY: foo
.ONESHELL:
foo:
set -e
TMPFILE=`mktemp -p ./`
dd if=/dev/random of=$$TMPFILE bs=1 count=512
FOO=`wc -c $$TMPFILE`
@echo FOO: $$FOO
Thanks!
CodePudding user response:
Make always expands the entire recipe (all lines of the recipe) first, before it starts any shell commands. So all your eval
, etc. operations are invoked before any shell command, such as dd
, is run.