4
votes

I am trying to generate an error in a Makefile when a string is not found in the output of a shell command. The shell command depends on a parameter, therefore the whole thing is in a defined function. Here is a minimalist example:

define check_in_abcdefg
$(eval TMP := $(shell echo abcdefg))
$(if $(findstring $(1),$(TMP)),,$(error $(1) not in $(TMP)))
endef

$(call check_in_abcdefg,def)

all:
    @echo Hello, world!

I would like this Makefile to output Hello, world! in this case, but I'd like it to output xyz not in abcdefg if I replace the call line with this one:

$(call check_in_abcdefg,xyz)

The problem is that with the def check I have this output:

Makefile:6: *** missing separator. Stop.

Where line 6 is $(call check_in_abcdefg,def)

Why does the syntax check fail when the $(if ...) condition is true since it's actually empty ?

Note that the echo command in the dummy target all is correctly preceded by a tab, not four spaces. I am running GNU make 4.1.90 built for Windows32, and it seems not to happen for newer version of GNU make. I am looking for any answer that could help me make it work with GNU make 4.1.90

2
I can't reproduce your problem (GNU Make 4.2.1 on x86_64-pc-msys).user2371524
@FelixPalmen Thanks for trying, actually I just tried with GNU make 4.2 and it seems to work. I have no idea why this would fail with the version 4.1.90 and unfortunately it's this one which is globally deployed in my context.Tim
I use GNU Make 4.1 x86_64-pc-linux-gnu, i have the same error when line 3 evaluates to true. That problem seems to get fixed if something is specified, for exemple : $(if $(findstring $(1), $(TMP), $(errror $(1) is in $(TMP)), $(error $(1) is not in $(TMP))) works. Hope this can helpHollyol
@Hollyol Thanks for trying, however this doesn't really work for me since the issue happens right after. In your case it doesn't happen because make stops at the error, but if you put an info instead if fails : $(if $(findstring $(1),$(TMP)),$(info OK),$(error $(1) not in $(TMP))). This displays OK followed by *** missing separator. Stop.Tim
4.1.90 is an internal release version (that's what the "90" means; all "9x" versions are internal). It's really bad that anyone is using it for production use. There's no possible way to know why you're seeing this behavior, because there's no way to know what actual code you're using. There can be all sorts of bugs introduced then fixed within the same version before the next release, all with version "4.1.90", and most of them not explicitly called out in NEWS, etc.MadScientist

2 Answers

2
votes

I'm not sure why older make versions choke here, but you can make it work with one big $(eval ) like this:

define check_in_abcdefg
$(eval
  TMP := $$(shell echo abcdefg)
  ifeq ($$(findstring $$(1),$$(TMP)),)
      $$(error $$(1) not in $$(TMP))
  endif
)
endef

$(call check_in_abcdefg,def)

all:
        @echo Hello, world!
2
votes

To answer the question about why GNU make 4.1 is throwing this error: that version of GNU make is mishandling the newline. In your example:

define check_in_abcdefg
$(eval TMP := $(shell echo abcdefg))
$(if $(findstring $(1),$(TMP)),,$(error $(1) not in $(TMP)))
endef

$(call check_in_abcdefg,def)

The first line of the defined macro (the eval) expands to the empty string, and so does the second line (the if). So, the call expands to a single newline character.

That version of GNU make is not correctly ignoring this newline character and instead throws an error. You can change your makefile to work in those older versions by removing the newline:

define check_in_abcdefg
$(eval TMP := $(shell echo abcdefg))$(if $(findstring $(1),$(TMP)),,$(error $(1) not in $(TMP)))
endef

$(call check_in_abcdefg,def)