Makefile 错误未找到规则但存在规则
Makefile error no rule found but rule is present
这个 Makefile
CC = gcc
INC_PATH = -I../common/
SOURCEDIR := ./
SOURCES := $(wildcard $(SOURCEDIR)/*.c)
OBJDIR :=./obj
OBJECTS := $(patsubst $(SOURCEDIR)/%.c,$(OBJDIR)/%.o, $(SOURCES))
DEPENDS := $(patsubst $(SOURCEDIR)/%.c,$(OBJDIR)/%.d, $(SOURCES))
COMMONDIR := ../common
SOURCESCOMMON := $(wildcard $(COMMONDIR)/*.c)
OBJDIRCOMMON := $(COMMONDIR)/obj
OBJECTSCOMMON := $(patsubst $(COMMONDIR)/%.c,$(OBJDIRCOMMON)/%.o, $(SOURCESCOMMON))
DEPENDSCOMMON := $(patsubst $(COMMONDIR)/%.c,$(OBJDIRCOMMON)/%.d, $(SOURCESCOMMON))
# ADD MORE WARNINGS!
WARNING := -Wall -Wextra
# OBJS_LOC is in current working directory,
EXECUTABLE := ../server
# .PHONY means these rules get executed even if
# files of those names exist.
.PHONY: all clean
# The first rule is the default, ie. "make",
# "make all" and "make parking" mean the same
all: $(EXECUTABLE)
clean:
$(RM) $(OBJECTS) $(DEPENDS) $(EXECUTABLE)
# Linking the executable from the object files
# $^ # "src.c src.h" (all prerequisites)
$(EXECUTABLE): $(OBJECTSCOMMON) $(OBJECTS)
$(CC) $(WARNING) $^ -o $@
-include $(DEPENDS) $(DEPENDSCOMMON)
$(OBJDIR):
mkdir -p $(OBJDIR)
$(OBJDIR)/%.o: $(SOURCEDIR)/%.c Makefile | $(OBJDIR)
$(CC) $(WARNING) -MMD -MP -c $(INC_PATH) $< -o $@
$(OBJDIRCOMMON):
mkdir -p $(OBJDIRCOMMON)
$(OBJDIRCOMMON)/%.o: $(SOURCESCOMMON)/%.c | $(OBJDIRCOMMON)
$(CC) $(WARNING) -MMD -MP -c $< -o $@
正在生成错误:
make[1]: *** No rule to make target '../common/obj/utilities.o', needed by '../server'. Stop.
生成规则的主要规则的输入 $(OBJECTSCOMMON)
引用目录 OBJDIRCOMMON
中包含的对象文件 *.o
。生成此对象的规则没有明确的目标,但它是:
$(OBJDIRCOMMON)/%.o: $(SOURCESCOMMON)/%.c | $(OBJDIRCOMMON)
$(CC) $(WARNING) -MMD -MP -c $< -o $@
我认为这是产生错误的原因。我期待定义 OBJECTSCOMMON := $(patsubst $(COMMONDIR)/%.c,$(OBJDIRCOMMON)/%.o, $(SOURCESCOMMON))
制定规则并有效生成 $()
然而,类似的规则用于在同一个 Makefile
中生成 $(OBJECTS)
并且它正在工作:
$(OBJDIR)/%.o: $(SOURCEDIR)/%.c Makefile | $(OBJDIR)
$(CC) $(WARNING) -MMD -MP -c $(INC_PATH) $< -o $@
那么为什么规则之间的行为不同?
$(SOURCESCOMMON)/%.c
扩展为 $(wildcard $(COMMONDIR)/*.c)/%.c
,因此该模式将包含类似 ../common/utilities.c/%.c
的内容(可能具有不同的文件名)。此文件不存在,因此忽略模式规则。
其他规则使用$(SOURCEDIR)
,所以没有这个问题。
这个 Makefile
CC = gcc
INC_PATH = -I../common/
SOURCEDIR := ./
SOURCES := $(wildcard $(SOURCEDIR)/*.c)
OBJDIR :=./obj
OBJECTS := $(patsubst $(SOURCEDIR)/%.c,$(OBJDIR)/%.o, $(SOURCES))
DEPENDS := $(patsubst $(SOURCEDIR)/%.c,$(OBJDIR)/%.d, $(SOURCES))
COMMONDIR := ../common
SOURCESCOMMON := $(wildcard $(COMMONDIR)/*.c)
OBJDIRCOMMON := $(COMMONDIR)/obj
OBJECTSCOMMON := $(patsubst $(COMMONDIR)/%.c,$(OBJDIRCOMMON)/%.o, $(SOURCESCOMMON))
DEPENDSCOMMON := $(patsubst $(COMMONDIR)/%.c,$(OBJDIRCOMMON)/%.d, $(SOURCESCOMMON))
# ADD MORE WARNINGS!
WARNING := -Wall -Wextra
# OBJS_LOC is in current working directory,
EXECUTABLE := ../server
# .PHONY means these rules get executed even if
# files of those names exist.
.PHONY: all clean
# The first rule is the default, ie. "make",
# "make all" and "make parking" mean the same
all: $(EXECUTABLE)
clean:
$(RM) $(OBJECTS) $(DEPENDS) $(EXECUTABLE)
# Linking the executable from the object files
# $^ # "src.c src.h" (all prerequisites)
$(EXECUTABLE): $(OBJECTSCOMMON) $(OBJECTS)
$(CC) $(WARNING) $^ -o $@
-include $(DEPENDS) $(DEPENDSCOMMON)
$(OBJDIR):
mkdir -p $(OBJDIR)
$(OBJDIR)/%.o: $(SOURCEDIR)/%.c Makefile | $(OBJDIR)
$(CC) $(WARNING) -MMD -MP -c $(INC_PATH) $< -o $@
$(OBJDIRCOMMON):
mkdir -p $(OBJDIRCOMMON)
$(OBJDIRCOMMON)/%.o: $(SOURCESCOMMON)/%.c | $(OBJDIRCOMMON)
$(CC) $(WARNING) -MMD -MP -c $< -o $@
正在生成错误:
make[1]: *** No rule to make target '../common/obj/utilities.o', needed by '../server'. Stop.
生成规则的主要规则的输入 $(OBJECTSCOMMON)
引用目录 OBJDIRCOMMON
中包含的对象文件 *.o
。生成此对象的规则没有明确的目标,但它是:
$(OBJDIRCOMMON)/%.o: $(SOURCESCOMMON)/%.c | $(OBJDIRCOMMON)
$(CC) $(WARNING) -MMD -MP -c $< -o $@
我认为这是产生错误的原因。我期待定义 OBJECTSCOMMON := $(patsubst $(COMMONDIR)/%.c,$(OBJDIRCOMMON)/%.o, $(SOURCESCOMMON))
制定规则并有效生成 $()
然而,类似的规则用于在同一个 Makefile
中生成 $(OBJECTS)
并且它正在工作:
$(OBJDIR)/%.o: $(SOURCEDIR)/%.c Makefile | $(OBJDIR)
$(CC) $(WARNING) -MMD -MP -c $(INC_PATH) $< -o $@
那么为什么规则之间的行为不同?
$(SOURCESCOMMON)/%.c
扩展为 $(wildcard $(COMMONDIR)/*.c)/%.c
,因此该模式将包含类似 ../common/utilities.c/%.c
的内容(可能具有不同的文件名)。此文件不存在,因此忽略模式规则。
其他规则使用$(SOURCEDIR)
,所以没有这个问题。