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

all: $(addsuffix Spec.compile, $(SPECS)) $(addsuffix Spec.run, $(SPECS))


    @scala -cp ${SCALA_FLAGS} $(basename $@)

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

    scalac -cp ${SCALA_FLAGS} $(basename $@).scala

    scalac -cp ${SCALA_FLAGS} $(basename $@).scala

    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

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

1 Answer 1


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?

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.