Search code examples
makefilegnu-make

[MAKEFILE]: *** missing separator issue


Hi am trying following code snippet in makefile where it enters both if block and else block :-

 MAINSUFFIX := -ktest
define install_shared_library
  ifneq $$(filter hello hello1,$(1),)
    LIBNAME := $(1)$$(MAINSUFFIX).lib
    $$(info in if $(LIBNAME))
  else
    $$(info in else)
  endif
endef

$(eval $(call install_shared_library,lvvm))

Output is:- test1.mk:12: *** invalid syntax in conditional. Stop.

What is the issue in above code snippet?

To workaround i am trying below code snippet:-

MAINSUFFIX := -ktest

define install_shared_library
   if [ "$(1)" = "hello" -o "$(1)" = "hello1" ]; then \
          LIBNAME="$(1)$(MAINSUFFIX).lib"; \
          echo "test1"; \
   else \
          echo "test else"; \
   fi
endef

$(eval $(call install_shared_library,lvvm))

I hit into issue:- k.mk:13: *** missing separator. Stop.


Solution

  • To answer your second question first: that is shell script syntax. Make is not the shell. Make can invoke the shell to parse a shell script, but only in either a recipe or in a $(shell ...) function, and you are using neither here.

    To answer the first question, it's a matter of expansion order. In the statement:

    $(eval $(call install_shared_library,lvvm))
    

    make first expands the variable install_shared_library due to the inner call function. The call function just expands its argument as text, it has no idea that the argument is a makefile script. So when it expands, both the $(info ...) functions are expanded (it's just text, it doesn't know that there's an if statement there) and you see both outputs.

    It's only after that first expansion, where the results are passed to eval, that the if statement is parsed.

    If you want to defer the expansion until the eval you have to escape the function from the call like this:

    define install_shared_library
     ifneq ($$(filter hello hello1,$(1)),)
       LIBNAME := $(1)$$(MAINSUFFIX).lib
       $$(info test1)
     else
       $$(info test else)
     endif
    endef
    

    basically any variable or function that is not referring to the call arguments, should be escaped.