Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

makefile is missing separator

Alright I am stuck on this and I have no idea what I am doing wrong. Everything was going great working on a more complicated makefile but then all of a sudden I got the "Missing separator" error. I was able to isolate it down to a very simple scenario:

test.mk

define push_dir
$(info ${1})
endef

define pop_dir
$(info ${1})
endef

define include_submake
$(call push_dir,${1})
$(call pop_dir,${1})
endef

Simple

include test.mk

INITIAL_SUBMAKE:= includeme.mk
$(call include_submake,${INITIAL_SUBMAKE})

process:
    @echo Processed...

And the output:

C:\project>make -f Simple process
includeme.mk
includeme.mk
Simple:4: *** missing separator.  Stop.

includeme.mk does not actually exist. I have no idea what is going wrong here I have tried a multitude of things. If I surround the call to include_submake in info like so:

$(info $(call include_submake,${INITIAL_SUBMAKE}))

The missing separator error goes away. Also If in the include_submake define I only call one of the functions it works fine. Additionally if I directly call the functions instead of calling them include_submake it works as well:

include test.mk

INITIAL_SUBMAKE:= includeme.mk
$(call push_dir,${INITIAL_SUBMAKE})
$(call pop_dir,${INITIAL_SUBMAKE})

process:
    @echo Processed...


C:\project>make -f Simple process
includeme.mk
includeme.mk
Processed...

I feel like I'm overlooking something fundamental here. Thanks for your help.

like image 861
ThePosey Avatar asked Jun 04 '12 15:06

ThePosey


People also ask

What is missing separator in makefile?

Means that the makefile contains spaces instead of Tab's. The make utility is notoriously picky about the use of Space instead of Tab . So it's likely that the makefile contains Space at the beginning of rule stanzas within the file.

Do makefiles need tabs?

Recipes in makefile rules must start with a tab (per definition). If a single tab (interpreted as 8 spaces wide) is not enough to put the recipe clearly indented (meaning at least 4 spaces difference) from the code around it, use additional tabs.

What does $() mean in makefile?

The $@ and $< are called automatic variables. The variable $@ represents the name of the target and $< represents the first prerequisite required to create the output file.

How do I run a makefile in Linux?

Also you can just type make if your file name is makefile/Makefile . Suppose you have two files named makefile and Makefile in the same directory then makefile is executed if make alone is given. You can even pass arguments to makefile.


2 Answers

The missing separator error happens because of a non-empty return value of include_submake, which is a single line feed character in your case. Make only permits whitespace characters (that is, a space or tab) to occur in an expression which is not assumed to be a part of some rule or another directive.

Rewrite your functions using plain-old Make variable assignment and the error should go away:

push_dir = \
    $(info $1)

pop_dir = \
    $(info $1)

include_submake = \
    $(call push_dir,$1) \
    $(call pop_dir,$1)

UPD.: define vs plain old variable assignment

Answering to a question from the first comment. Personally I would prefer using define directive in several cases.

Using with eval function

As the GNU Make manual suggests, define directive is very useful in conjunction with the eval function. Example from the manual (emphasis is mine):

PROGRAMS    = server client

server_OBJS = server.o server_priv.o server_access.o
server_LIBS = priv protocol

client_OBJS = client.o client_api.o client_mem.o
client_LIBS = protocol

# Everything after this is generic

.PHONY: all
all: $(PROGRAMS)

define PROGRAM_template
  $(1): $$($(1)_OBJS) $$($(1)_LIBS:%=-l%)
  ALL_OBJS   += $$($(1)_OBJS)
endef

$(foreach prog,$(PROGRAMS),$(eval $(call PROGRAM_template,$(prog))))

$(PROGRAMS):
    $(LINK.o) $^ $(LDLIBS) -o $@

clean:
    rm -f $(ALL_OBJS) $(PROGRAMS)

Generator templates

Verbatim variables fit perfectly for cases when you want to generate a file from GNU Make. For example, consider generating a header file based on some information from Makefile.

# Args:
#   1. Header identifier.
define header_template
/* This file is generated by GNU Make $(MAKE_VERSION). */

#ifndef $(inclusion_guard)
#define $(inclusion_guard)

$(foreach inc,$($1.includes),
#include <$(inc).h>)

/* Something else... */

#endif /* $(inclusion_guard) */

endef

# 1. Unique header identifier.
inclusion_guard = \
    __GEN_$1_H

# Shell escape.
sh_quote = \
    '$(subst ','"'"',$1)'

foo.includes := bar baz

HEADERS := foo.h

$(HEADERS) : %.h :
    @printf "%s" $(call sh_quote,$(call header_template,$(*F)))&gt $@

Extended Make syntax

In our project we use our own build system called Mybuild, and it is implemented entirely on top of GNU Make. As one of low-level hacks that we used to improve the poor syntax of the builtin language of Make, we have developed a special script which allows one to use extended syntax for function definitions. The script itself is written in Make too, so it is a sort of meta-programming in Make.

In particular, one can use such features as:

  • Defining multiline functions without the need to use backslash
  • Using comments inside functions (in plain-old Make comments can only occur outside variable assignment directives)
  • Defining custom macros like $(assert ...) or $(lambda ...)
  • Inlining simple functions like $(eq s1,s2) (string equality check)

This is an example of how a function can be written using the extended syntax. Note that it becomes a valid Make function and can be called as usual after a call to $(def_all).

# Reverses the specified list.
#   1. The list
# Return:
#   The list with its elements in reverse order.
define reverse
    # Start from the empty list.
    $(fold ,$1,

        # Prepend each new element ($2) to
        # the result of previous computations.
        $(lambda $2 $1))
endef
$(def_all)

Using these new features we were able to implement some really cool things (well, at least for Make :-) ) including:

  • Object-Oriented layer with dynamic object allocation, class inheritance, method invocations and so on
  • LALR parser runtime engine for parsers generated by GOLD Parser Builder
  • Modelling library with runtime support for models generated with EMF

Feel free to use any part of the code in your own projects!

like image 196
Eldar Abusalimov Avatar answered Nov 10 '22 00:11

Eldar Abusalimov


I ran into the same problem. I inserted 'tab', deleted 'tab', reinserted to be sure. Same error message.

But, I did all of this inside of XCodem which to my surprise inserted white spaces, not '\t'. Once I used different editor these 'phantom' errors went away.

HTH...

like image 22
Heikki Avatar answered Nov 10 '22 00:11

Heikki