I have the following recipe:
ZS_FPATH := $(filter-out %.awk %.py %.sed, $(wildcard src/*))
compile: ${ZS_FPATH}
mkdir -p ${PACKAGE_NAME}/bin
zsh -c "zcompile -Uz ${PACKAGE_NAME}/bin/${PACKAGE_NAME} ${ZS_FPATH}"
mkdir -p ${PACKAGE_NAME}/etc
:> ${PACKAGE_NAME}/etc/zsfnames.lst
while IFS="" read -r zsfpath || [ -n "${zsfpath}" ]; do
basename $${zsfpath} >> ${PACKAGE_NAME}/etc/zsfnames.lst;
done < "${ZS_FPATH}"
.PHONY: compile
# ------------------------------------------------------------------------------
When I run the target "compile", the following error is returned:
mkdir -p utk/bin
zsh -c "zcompile -Uz utk/bin/utk src/bckpfile src/echopath src/tievalue"
mkdir -p utk/etc
:> utk/etc/zsfnames.lst
while IFS="" read -r zsfpath || [ -n "" ]; do
/bin/sh: -c: line 2: syntax error: unexpected end of file
make: *** [Makefile:63: compile] Error 2
I'm using tabs for spacing with tabstop=2 in neovim. I've also tried vs code without success. Could someone point out the problem with the snippet?
Every logical line in a makefile recipe is invoked in a separate shell. It's not true that the entire recipe is run in a single shell. So:
compile: ${ZS_FPATH}
while IFS="" read -r zsfpath || [ -n "${zsfpath}" ]; do
basename $${zsfpath} >> ${PACKAGE_NAME}/etc/zsfnames.lst;
done < "${ZS_FPATH}"
Will be run by make as:
/bin/sh -c 'while IFS="" read -r zsfpath || [ -n "${zsfpath}" ]; do'
/bin/sh -c 'basename $${zsfpath} >> ${PACKAGE_NAME}/etc/zsfnames.lst;'
/bin/sh -c 'done < "${ZS_FPATH}"'
You can probably see why the shell is complaining now.
If you want to combine multiple physical lines into one logical line you need to add backslashes in your makefile:
compile: ${ZS_FPATH}
while IFS="" read -r zsfpath || [ -n "$${zsfpath}" ]; do \
basename $${zsfpath} >> ${PACKAGE_NAME}/etc/zsfnames.lst; \
done < "${ZS_FPATH}"
which will work. Note you also need to escape the ${zfspath}
else it will be expanded as a shell variable before the recipe is invoked.