1
\$\begingroup\$

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
\$\endgroup\$
1
\$\begingroup\$

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?

\$\endgroup\$
4
  • \$\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 at 7:36
  • \$\begingroup\$ The error I am getting: "make: *** No rule to make target 'grammar.aps'. Stop." \$\endgroup\$ – Node.JS Apr 5 at 7:46
  • \$\begingroup\$ Yes, I do. %.generate and %.class exist and running them individually works. \$\endgroup\$ – Node.JS Apr 5 at 7:52
  • \$\begingroup\$ I've commented at that link (since that's not part of the review) \$\endgroup\$ – Toby Speight Apr 5 at 8:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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