makefile is missing separator
gnu-make, makefile, syntax-error
Solution
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)))> $@
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!
Problem
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.