Make, Ant and probably any other build language (and/or toolkit, since Ant is not much in the way of a language) are tricky bastards. I’ve been maintaining a parallel set of build scripts for a Java and C++ project for a few years now, and this has been great practice in getting my Make chops snappier. Just today, I found I needed to build the -Xbootclasspath argument for my makefile. I ended up re-learning an important lesson that applies to bash. Not expectedly so, since Make and bash are not of common ancestry…but that lesson was “spaces.” One needs to put at least one space after Makes conditionals if, ifeq or ifneq. Just like one has to put space after bash’s if, while, and for.
- Bash:
if [ -z "$classpath" ] ; then do classpath="./*jar" done
- Make:
ifeq (,$(classpath)) classpath="./*jar" endif
- Both those statements are checking for zero length strings.
However, I’m going to stop comparing the two. You just look at where I’ve put those spaces, yung’un.
My real goal was to evaluate a series of conditions (is there an JAVA6_HOME defined? Is there a $JAVA_HOME/../jdk6 directory? Is there /usr/local/jdk6 directory? If so create a BOOTCLASSPATH variable:
This is the trick:
4 comma:= , 5 colon:= : 6 empty:= 7 space:= $(empty) $(empty) ... 56 ifneq (,$(JAVA6_HOME)) 57 ifneq (,$(wildcard $(JAVA6_HOME)/.)) 58 JAVA6 = ${JAVA6_HOME} 59 endif 60 endif 61 ifeq (,$(JAVA6)) 62 ifneq (,$(wildcard $(JAVA_HOME)/../jdk6/.)) 63 JAVA6 = $(JAVA_HOME)/../jdk6 64 endif 65 endif 66 ifeq (,$(JAVA6)) 67 ifneq (,$(wildcard /usr/local/jdk6/.)) 68 JAVA6 = "/usr/local/jdk6" 69 endif 70 endif 71 ifneq (,$(JAVA6)) 72 BOOTCLASSPATH := $(wildcard $(JAVA6)/lib/*.jar) 73 JAVATARGET = -target 1.6 \ 74 -source 1.6 \ 75 -Xbootclasspath/p:$(subst $(space),$(colon),$(BOOTCLASSPATH)) 76 $(info BOOTCLASSPATH is $(BOOTCLASSPATH)) 77 $(info JAVATARGET is $(JAVATARGET)) 78 endif
And the quiz for the reader is, why is line 75 important?