80

I want to detect a condition in my makefile where a tool is the wrong version and force the make to fail with an error message indicating the item is not the right version.

Can anyone give an example of doing this?

I tried the following but it is not the right syntax:

ifeq "$(shell svnversion --version | sed s/[^0-9\.]*://)" "1.4"
$error("Bad svnversion v1.4, please install v1.6")
endif

Thanks.

WilliamKF
  • 41,123
  • 68
  • 193
  • 295
  • You might want to check this against 1.4. I have 1.4.4 installed and the `--version` output contains a lot more than the version number. Try something like `ifeq "$(shell svn --version | sed -nE -e '/version/s/^.*([0-9]+\.[0-9]\+)\..*$$/\1/p')" "1.4"` instead – D.Shawley Dec 08 '09 at 04:05
  • My sed does not accept the -E: "sed: invalid option -- E" – WilliamKF Dec 08 '09 at 04:09
  • 1
    Does it have to be make? I tend to write these tests in configure. – Dirk Eddelbuettel Dec 08 '09 at 04:15
  • Ah.. then change the _match_ portion of the expression to `^.*\([0-9][0-9]*\.[0-9][0-9]*\)\..*$$`. The `-E` would enable _extended regular expressions_ which allow for more compact expressions amongst other goodies. – D.Shawley Dec 08 '09 at 12:04
  • I'd recommend quoting the regular expression for the shell too. Just to be safe. I.e., `ifeq ($(shell svnversion --version | sed ''))` Saves you the trouble of worrying about which special characters the shell is going to gobble up and misinterpret (except for single-quotes themselves: replace single-quotes in the quoted-string with `'\''` (`single-quote back-slash single-quote single-quote`) to escape them. – bambams Jan 08 '15 at 05:24

3 Answers3

103

From the manual:

$(error Bad svn version v1.4, please install v1.6)

This will result make to a fatal error:

$ make
Makefile:2: *** Bad svn version v1.4, please install v1.6.  Stop.
LiraNuna
  • 64,916
  • 15
  • 117
  • 140
  • 2
    As a side note, I wanted to output a multiline error message. For that, you can `define err_mesg = your multiline error mesage ... endef`, and then, `$(error $(err_mesg))`. Make will keep and output `err_mesg` as it was written. – Alberto May 19 '16 at 11:08
  • 7
    Minor pitfall: if outside of a recipe, there cannot be whitespace before the `$` – M.M Apr 10 '17 at 14:06
  • 4
    This doesn't seem to work when used with a shell conditional. – CMCDragonkai Feb 22 '19 at 01:32
14

While $(error... works, sometimes its easier to use a rule that fails

test_svn_version:
        @if [ $$(svn --version --quiet | \
                perl -ne '@a=split(/\./); \
                          print $$a[0]*10000 + $$a[1]*100 + $$a[2]') \
              -lt 10600 ]; \
        then \
            echo >&2 "Svn version $$(svn --version --quiet) too old; upgrade to v1.6";
            false; \
        fi

Then you make test_svn_version a prerequisite of your top level target.

Chris Dodd
  • 119,907
  • 13
  • 134
  • 226
  • This isn't working, I get: /bin/sh: -c: line 0: unexpected EOF while looking for matching `)' /bin/sh: -c: line 1: syntax error: unexpected end of file – WilliamKF Dec 08 '09 at 15:40
  • 1
    @WilliamKF -- There's a spurious space after a \ at the end of a line that causes that problem. I also fixed the missing | – Chris Dodd Dec 09 '09 at 03:19
  • 1
    The rule to choose between `$(error)` (parse-time check) and `false` AKA `exit 1` (run-time target) is: use `$(error)` if your build cannot proceed at all; otherwise, if only specific targets cannot be built without this precondition, make them depend on `test_svn_version`. – Victor Sergienko Oct 02 '19 at 16:37
  • Thank you so much for this answer! You helped my quite a lot for a related question: how to implement a 'checking target' – claudio May 23 '21 at 09:44
8

The conditional needs some attention too.

ifeq ($(shell svnversion --version | sed s/[^0-9\.]*://), 1.4) 
    $(error Bad svnversion v1.4, please install v1.6)
endif 
Beta
  • 96,650
  • 16
  • 149
  • 150