The*_*sey 17 makefile syntax-error gnu-make
好吧,我坚持这个,我不知道我做错了什么.在一个更复杂的makefile上,一切都很好,但突然之间我得到了"Missing separator"错误.我能够将它分离到一个非常简单的场景:
define push_dir
$(info ${1})
endef
define pop_dir
$(info ${1})
endef
define include_submake
$(call push_dir,${1})
$(call pop_dir,${1})
endef
Run Code Online (Sandbox Code Playgroud)
include test.mk
INITIAL_SUBMAKE:= includeme.mk
$(call include_submake,${INITIAL_SUBMAKE})
process:
@echo Processed...
Run Code Online (Sandbox Code Playgroud)
并输出:
C:\project>make -f Simple process
includeme.mk
includeme.mk
Simple:4: *** missing separator. Stop.
Run Code Online (Sandbox Code Playgroud)
includeme.mk实际上并不存在.我不知道这里出了什么问题我尝试了很多东西.如果我将include_submake的调用包围在这样的信息中:
$(info $(call include_submake,${INITIAL_SUBMAKE}))
Run Code Online (Sandbox Code Playgroud)
丢失的分隔符错误消失了.另外如果在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...
Run Code Online (Sandbox Code Playgroud)
我觉得我在这里忽略了一些基本的东西.谢谢你的帮助.
Eld*_*mov 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)
Run Code Online (Sandbox Code Playgroud)
define普通的旧变量赋值回答第一条评论中的问题.我个人更喜欢define在几种情况下使用指令.
eval功能正如GNU Make手册所暗示的那样,define指令与eval函数结合使用非常有用.手册中的示例(重点是我的):
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的内置语言的不良语法的低级别黑客之一,我们开发了一个特殊的脚本,允许人们使用扩展语法进行函数定义.脚本本身也是用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 :-)),包括:
随意在您自己的项目中使用代码的任何部分!