2

Make is one of those technologies where I go back and forth between whether or not I understand it.

This is certainly one instance where I know I must be doing something wrong, since Make was developed to make these tasks less repetitive.

all: 24.1 24.2 24.3

24.1:
    evm install emacs-24.1-bin || true
    emacs --version
    emacs --batch -L . -l ert -l test/tests.el -f ert-run-tests-batch-and-exit
24.2:
    evm install emacs-24.2-bin || true
    emacs --version
    emacs --batch -L . -l ert -l test/tests.el -f ert-run-tests-batch-and-exit
24.3:
    evm install emacs-24.3-bin || true
    emacs --version
    emacs --batch -L . -l ert -l test/tests.el -f ert-run-tests-batch-and-exit

How can I edit this Makefile to only lay out the test sequence once but be able to test against multiple versions?

Sean Allred
  • 3,558
  • 3
  • 32
  • 71

3 Answers3

5

Try this:

VERSIONS = 24.1 24.2 24.3

all :: $(VERSIONS)

$(VERSIONS) ::
    evm install emacs-$@-bin || true
    emacs --version
    emacs --batch -L . -l ert -l test/tests.el -f ert-run-tests-batch-and-exit

The :: is a special kind of rule, that puts the target as phony (and has other properties, too).

Edouard Thiel
  • 5,878
  • 25
  • 33
  • This seems like the cleanest solution, and allows me to have other targets in the Makefile, specifying this recipe for the `VERSIONS` *only*. Good answer :) Do you have a link to the manual page which describes this use of `::`? – Sean Allred Nov 09 '14 at 16:26
  • 1
    Here is a link in the GNU Make Manual: http://www.gnu.org/software/make/manual/make.html#Double_002dColon - but it's not GNU specific, it is "traditional" syntax. – Edouard Thiel Nov 09 '14 at 16:32
  • 1
    I'm not sure what is meant by _`::` stands for phony target_, but no way I read that statement makes it correct :-). Double-colon rules don't create phony targets, although double-colon rules are often also declared phony (separately). – MadScientist Nov 09 '14 at 17:00
2

How about:

all: 24.1 24.2 24.3

%:
        evm install emacs-$@-bin || true
        emacs --version
        emacs --batch -L . -l ert -l test/tests.el -f ert-run-tests-batch-and-exit
MadScientist
  • 92,819
  • 9
  • 109
  • 136
  • Excellent! The manual page, for wanderers: [`Defining Last-Resort Default Rules`](https://www.gnu.org/software/make/manual/html_node/Last-Resort.html). Thank you :) – Sean Allred Nov 08 '14 at 22:20
  • Sorry to take away the tick, but [another answer](http://stackoverflow.com/a/26827668/1443496) has a more precise definition. This still worked in the meantime, though! :) – Sean Allred Nov 09 '14 at 16:27
2

I have to admit that turning to ‘last resort’ strategies always makes me queasy: it feels as if going against the grain of the tool. BSD make on the other hand allows explicit looping constructs, hence getting rid of the repetitive rules is straightforward:

VERSIONS = 24.1 24.2 24.3
all: ${VERSIONS}

.for VERSION in ${VERSIONS}
${VERSION}:
    evm install emacs-${VERSION}-bin || true
    emacs --version
    emacs --batch -L . -l ert -l test/tests.el -f ert-run-tests-batch-and-exit
.endfor

I’m well aware that this solution almost surely won’t help you at all; switching make implementation is almost certainly out of the question. BSD make is sorely underrepresented though, so I thought it might be useful for other people to have an alternative approach documented.

As MadScientist correctly pointed out, GNU make doesn’t support any of the ‘dot constructs’ like .for, which are special to BSD make. However, this question suggests a few other looping techniques that might be applicable to GNU make: How to write loop in a Makefile?

Community
  • 1
  • 1
  • Oh, that's nifty :) GNU Make *may* support this (Emacs highlights the structure, but that doesn't mean anything), but it throws `Makefile:23: *** missing separator. Stop.` at the `.for` line. – Sean Allred Nov 08 '14 at 23:57
  • 2
    GNU make definitely does not support this syntax. In fact none of the BSD "dot commands" (like `.for`) are available in GNU make. – MadScientist Nov 09 '14 at 01:26
  • Yea, I get the missing seperator error also on GNU make. – Leo Ufimtsev Jul 08 '16 at 13:50