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 Answer 1

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, 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

This site is temporarily in read-only mode and not accepting new answers.

Not the answer you're looking for? Browse other questions tagged .