在下面的代码中使makefile错误是什么?

时间:2019-11-13 10:21:00

标签: makefile

我在第98行出现错误,我不明白为什么会发生此错误。

makefile:98: *** mixed implicit and normal rules.  Stop.

下面是第98行的代码行

$(SRC_C_OBJS): | $(OBJ_DIR)

下面是使用上述变量的代码:


    OBJ_DIR = .\build

   _C_SRCS = $(PROGRAM)_i.c \
            test_$(PROGRAM).c

  _ASM_SRCS = $(PROGRAM).S

  _REF_C_SRCS = $(PROGRAM)_c.c \
              test_$(PROGRAM).c


REF_OBJS = $(_REF_C_SRCS:%.c=$(REF_OBJ_DIR)\%.o)
SRC_C_OBJS   = $(_C_SRCS:%.c=$(OBJ_DIR)\%.o)
SRC_ASM_OBJS = $(_ASM_SRCS:%.S=$(OBJ_DIR)\%.obj)
SRC_C_OBJS += $(OBJ_DIR)/subsys.o

$(EXEC): $(SRC_C_OBJS) $(SRC_ASM_OBJS)
    $(LD) $(LDFLAGS) -o $@ $(SRC_C_OBJS) $(SRC_ASM_OBJS) $(LLIBS)

2 个答案:

答案 0 :(得分:1)

REF_OBJS = $(_REF_C_SRCS:%.c=$(REF_OBJ_DIR)\%.o)
SRC_C_OBJS   = $(_C_SRCS:%.c=$(OBJ_DIR)\%.o)
SRC_ASM_OBJS = $(_ASM_SRCS:%.S=$(OBJ_DIR)\%.obj)

\%正在转义%,因此它被解释为原义的%,而不是被替换的字符串。 /是UNIX平台上的目录分隔符,而不是\。您想要:

OBJ_DIR = ./build
REF_OBJS = $(_REF_C_SRCS:%.c=$(REF_OBJ_DIR)/%.o)
SRC_C_OBJS   = $(_C_SRCS:%.c=$(OBJ_DIR)/%.o)
SRC_ASM_OBJS = $(_ASM_SRCS:%.S=$(OBJ_DIR)/%.obj)

理论上,如果将\作为分隔符,则可以执行以下操作:

REF_OBJS = $(_REF_C_SRCS:%.c=$(REF_OBJ_DIR)\\%.o)
SRC_C_OBJS   = $(_C_SRCS:%.c=$(OBJ_DIR)\\%.o)
SRC_ASM_OBJS = $(_ASM_SRCS:%.S=$(OBJ_DIR)\\%.obj)\

答案 1 :(得分:1)

Make是在UNIX和POSIX路径上开发并与之一起使用的。 POSIX路径没有驱动器规格(C:等),它们使用正斜杠(/)而不是反斜杠作为目录分隔符。 Make不是为本地Windows路径(驱动器规格和反斜杠)设计的,因此不适用于该路径。

尤其是,make经常将驱动器规范中的:视为规则定义的一部分(请注意,在规则定义中:如何将目标与先决条件区分开)。它还遵循标准的UNIX / POSIX约定,即反斜杠用于转义特殊字符(至少在某些地方)。

所以。首先,当在StackOverflow上提问时,请确保包括以下关键细节,例如(a)您正在使用什么操作系统,以及(b)您正在使用什么版本的工具(在本例中为make)。

第二,上面给出的示例缺少绝对关键的细节:您没有包括对REF_OBJ_DIRPROGRAM变量的分配。没有这一点,我们将无法确定到底是什么问题。

通常,在编写makefile文件时,应避免使用驱动器规格,而应使用正斜杠而非反斜杠作为目录分隔符。大多数Windows程序都接受正斜杠(仅某些旧的command.com程序不接受)。如果必须使用驱动器规格,则需要获取make的版本,该版本可以进行编译以了解Windows路径。

另一件事,只是为了避免另一个常见问题:make不能在包含空格的路径上正常工作...因此请避免使用它们。