# Simple Makefile to build and run scala program

I wrote this simple Makefile but it ended up like a spaghetti code. I used basename multiple times. I have a special case for first.spec.scala.run and follow.spec.scala.run and maybe more antipattern code that I am not aware of. I am not happy with my code and I appreciate any feedback or review. Thank you.

SPECS=First Follow
EXAMPLES_PATH=../..
ROOT_PATH=../${EXAMPLES_PATH} SCALAV=2.12 APSLIB=${ROOT_PATH}/lib/aps-library-${SCALAV}.jar SCALA_FLAGS=.:${APSLIB}
APS2SCALA=${ROOT_PATH}/bin/aps2scala all:$(addsuffix Spec.compile, $(SPECS))$(addsuffix Spec.run, $(SPECS)) %.generate:${APS2SCALA} -DCOT -p ${EXAMPLES_PATH}:${ROOT_PATH}/base $* %.run: @scala -cp${SCALA_FLAGS} $(basename$@)

GrammarUtil.compile: grammar.generate
scalac -cp ${SCALA_FLAGS} grammar.scala$(basename $@).scala first.compile: scalac -cp${SCALA_FLAGS} $(basename$@).scala

follow.compile:
scalac -cp ${SCALA_FLAGS}$(basename $@).scala Spec.compile: scalac -cp${SCALA_FLAGS} $(basename$@).scala

FirstSpec.compile: Spec.compile grammar.generate GrammarUtil.compile first.generate first.compile
scalac -cp ${SCALA_FLAGS}$(basename $@).scala FollowSpec.compile: Spec.compile grammar.generate GrammarUtil.compile follow.generate follow.compile scalac -cp${SCALA_FLAGS} $(basename$@).scala

clean:
rm -f *.class grammar.scala first.scala follow.scala


I don't know Scala, but I do know Make, so I hope this helps.

Firstly, the makefile is missing .DELETE_ON_ERROR:, which pretty much every makefile needs, to avoid part-written output files appearing up-to-date when a compilation command fails (e.g. is interrupted).

We also want .PHONY: for those targets that don't produce files, such as all and clean. (And clean should use $(RM) rather than rm -f, for increased portability.) I think that we want a straightforward pattern rule that says that we can make a file called foo.compile given an input called foo.scala: %.compile: %.scala scalac -cp${SCALA_FLAGS} $<  It looks to me that -cp is one of the flags to scalac, so that should probably be in ${SCALA_FLAGS} rather than in the command.

I'm not convinced that your rules actually create the files they claim to. For example, GrammarUtil.compile depends on grammar.generate, but then actually uses grammar.scala - should grammar.generate actually be grammar.scala there?

• Thank you so much for the feedback but I am failing. I am getting an error: gist.github.com/amir734jj/645a94412475dfb700f6116dd1c7e1bc Apr 5 at 7:36
• The error I am getting: "make: *** No rule to make target 'grammar.aps'. Stop." Apr 5 at 7:46
• Yes, I do. %.generate and %.class exist and running them individually works. Apr 5 at 7:52
• I've commented at that link (since that's not part of the review) Apr 5 at 8:01