我在第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)
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)\
Make是在UNIX和POSIX路径上开发并与之配合使用的。 POSIX路径没有驱动器规格(C:
等),它们使用正斜杠(/
)而不是反斜杠作为目录分隔符。 Make不是为本地Windows路径(驱动器规格和反斜杠)设计的,因此无法很好地工作。
尤其是,make经常将驱动器规范中的:
视为规则定义的一部分(请注意,在规则定义中:
如何将目标与先决条件区分开)。它还遵循标准的UNIX / POSIX约定,即反斜杠用于转义特殊字符(至少在某些地方)。
所以首先,当在StackOverflow上提问时,请确保包括以下关键细节,例如(a)您正在使用什么操作系统,以及(b)您正在使用什么版本的工具(在本例中为make)。
第二,您在上面给出的示例缺少绝对关键的细节:您没有包括对REF_OBJ_DIR
或PROGRAM
变量的分配。没有这一点,我们将无法确定到底是什么问题。
通常,在编写makefile文件时,应避免使用驱动器规格,而应将正斜杠而非反斜杠用作目录分隔符。大多数Windows程序都接受正斜杠(仅某些旧的command.com
程序不接受)。如果必须使用驱动器规格,则需要获取make的版本,该版本将被编译以了解Windows路径。
另一件事,只是为了避免另一个常见问题:make不能在包含空格的路径下正常工作,因此请避免使用它们。