好吧我坚持这个,我不知道我做错了什么。在一个更复杂的makefile上工作一切都很顺利,但突然之间,我得到了#34; Missing分离器"错误。我能够将其分解为一个非常简单的场景:
define push_dir
$(info ${1})
endef
define pop_dir
$(info ${1})
endef
define include_submake
$(call push_dir,${1})
$(call pop_dir,${1})
endef
include test.mk
INITIAL_SUBMAKE:= includeme.mk
$(call include_submake,${INITIAL_SUBMAKE})
process:
@echo Processed...
输出:
C:\project>make -f Simple process
includeme.mk
includeme.mk
Simple:4: *** missing separator. Stop.
includeme.mk
实际上并不存在。我不知道这里出了什么问题我尝试了很多东西。如果我将include_submake的调用包围在这样的信息中:
$(info $(call include_submake,${INITIAL_SUBMAKE}))
丢失的分隔符错误消失了。另外如果在include_submake
定义中我只调用其中一个函数,它可以正常工作。另外,如果我直接调用函数而不是调用它们include_submake
,它也能正常工作:
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...
我觉得我在这里忽略了一些基本的东西。谢谢你的帮助。
答案 0 :(得分:20)
发生missing separator
错误是因为include_submake
的非空返回值,在您的情况下是单行换行符。 Make只允许空格字符(即空格或制表符)出现在表达式中,该表达式不被认为是某个规则或其他指令的一部分。
使用普通的Make变量赋值重写函数,错误应该消失:
push_dir = \
$(info $1)
pop_dir = \
$(info $1)
include_submake = \
$(call push_dir,$1) \
$(call pop_dir,$1)
define
vs普通旧变量赋值回答第一条评论中的问题。我个人更喜欢在几种情况下使用define
指令。
eval
功能正如GNU Make手册所暗示的那样,define
指令与eval
function结合使用非常有用。手册中的例子(重点是我的):
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)
当您想要从GNU Make生成文件时,Verbatim变量非常适合这种情况。例如,考虑根据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)))> $@
在我们的项目中,我们使用自己的构建系统Mybuild,它完全在GNU Make之上实现。作为我们用来改进Make的内置语言的不良语法的低级别黑客之一,我们开发了一个special script,它允许使用扩展语法进行函数定义。脚本本身也是用Make编写的,因此它是Make中的一种元编程。
特别是,可以使用以下功能:
$(assert ...)
或$(lambda ...)
$(eq s1,s2)
(字符串相等性检查)这是如何使用扩展语法编写函数的示例。请注意,它变为有效的Make函数,并且可以在调用$(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)
使用这些新功能,我们能够实现一些非常酷的东西(好吧,至少对于Make :-)),包括:
随意在您自己的项目中使用the code的任何部分!
答案 1 :(得分:0)
我遇到了同样的问题。我插入'标签',删除'标签',重新插入以确保。相同的错误消息。
但是,我在XCodem中完成了所有这些工作,我惊讶地插入了空格,而不是'\ t'。一旦我使用了不同的编辑器,这些“幽灵”错误便消失了。
HTH ......