makefile缺少分隔符

时间:2012-06-04 15:13:04

标签: makefile syntax-error gnu-make

好吧我坚持这个,我不知道我做错了什么。在一个更复杂的makefile上工作一切都很顺利,但突然之间,我得到了#34; Missing分离器"错误。我能够将其分解为一个非常简单的场景:

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

简单

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...

我觉得我在这里忽略了一些基本的东西。谢谢你的帮助。

2 个答案:

答案 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)

UPD。: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)))> $@

扩展Make语法

在我们的项目中,我们使用自己的构建系统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 :-)),包括:

  • 面向对象的层,具有动态对象分配,类继承,方法调用等
  • GOLD Parser Builder
  • 生成的解析器的LALR解析器运行时引擎
  • 使用EMF
  • 生成的模型对运行时支持建模库

随意在您自己的项目中使用the code的任何部分!

答案 1 :(得分:0)

我遇到了同样的问题。我插入'标签',删除'标签',重新插入以确保。相同的错误消息。

但是,我在XCodem中完成了所有这些工作,我惊讶地插入了空格,而不是'\ t'。一旦我使用了不同的编辑器,这些“幽灵”错误便消失了。

HTH ......