When I run the makefile
SHELL=/bin/bash
a = False
ifeq ("", "")
a = True
endif
#b = False
#ifeq("","")
# b = True
#endif
#c = False
#if [ "" == "" ] \
#then \
# c = True \
#fi
#d = False
#if [[ "" == "" ]] \
#then \
# d = True \
#fi
all :
@\
echo a = $(a); \
echo b = $(b); \
echo c = $(c); \
echo d = $(d); \
\
c_loc=False; \
if [ "" == "" ]; \
then \
c_loc=True; \
fi; \
\
d_loc=False; \
if [[ "" == "" ]]; \
then \
d_loc=True; \
fi; \
\
echo c_loc = $${c_loc}; \
echo d_loc = $${d_loc}; \
I get the output
a = True
b =
c =
d =
c_loc = True
d_loc = True
Uncommenting if statement c or d leads to the error Makefile:n: *** missing separator. Stop. when using GNU Make 4.2.1 on Ubuntu 20.04. n is the line number of if statement c or d.
On the other hand, if I run the same makefile (with if statement c and d uncommented) on Mac OS Big Sur v11.6.1 with GNU Make3.81 I get the output
a = True
b =
c = False
d = False
c_loc = True
d_loc = True
Uncommenting if statement b leads to a missing separator error in both setups.
My questions:
- Why do I get a missing separator error for if statements c and d on one setup, but not on the other? Is this due to a difference between GNU Make 3 and GNU Make 4 or a difference between Ubuntu and MacOs?
- Why do I not get a True output for if statements c and d on both setups? Where can can I find information on which shell is used in the preamble?
CodePudding user response:
I don't know what you mean by "preamble"; there is no such thing as a "preamble" in a makefile. Makefiles are not shell scripts, although they CONTAIN shell scripts, in recipes. The only place you can have shell script syntax is within recipes. This has been true since make was invented back in the 1970's. Content like if [...]; then; fi is shell script syntax and so it can only appear within recipes.
If you want to have if-statements outside of recipes you have to use makefile syntax for it, not shell syntax.
As for why it "works" in GNU make 3.81 (note, it doesn't really work because it won't reset the value of the c variable regardless of what values you put in the condition), it's because in older versions of GNU make it used to be legal to create variable names consisting of whitespace. So this:
c = False
if [ "" == "" ] \
then \
c = True \
fi
is interpreted as these two lines (after backslash newline is reduced):
c = False
if [ "" == "" ] then c = True fi
In older versions of GNU make where variable names can contain whitespace, this sets the variable named if [ "" == "" ] then c to the value True fi. That's legal syntax, but it obviously doesn't do what you expected.
In newer versions of GNU make we do not allow variable names to contain whitespace, so the above text is invalid syntax and you get make's standard syntax error missing separator.
