我是这个文件夹结构
project
|_src
| |_test
| |_main.cpp
|_Makefile
这是我的makefile(试图改编自this link):
CC = g++
RM = rm
WFLAGS = -c -Wall -W
LDFLAGS =
SRCTESTD = src/test
EXECUTABLE = test
OBJD = .obj
DEPD = .dep
SRCSTEST = $(SRCTESTD)/main.cpp
OBJECTSTEST = $(patsubst %.cpp, $(OBJD)/test/%.o, $(notdir $(SRCSTEST)))
DEPDSTEST = $(patsubst %.cpp, $(DEPD)/test/%.d, $(notdir $(SRCSTEST)))
all: $(SRCSTEST) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTSTEST)
$(CC) $(LDFLAGS) $(OBJECTSTEST) -o $@
.cpp.o:
$(CC) $(WFLAGS) $< -o $@
它不起作用,我发现了这个错误
make: *** No rule to make target `.obj/test/main.o', needed by `test'. Stop.
我做错了什么?对不起琐碎的问题,但我是一个新手。
答案 0 :(得分:2)
错误意味着make无法找到构建目标文件的正确规则。您的树结构缺少一些信息:只有一个文件?其他人在哪里?无论如何,这里有一些提示:
在最后两行中,您使用的是obsolete feature make:后缀规则。我建议您切换到pattern rule,这是功能相当的。 说出类似的话:
%.o: %.cpp
$(CXX) $(CXXFLAGS) $< -o $@
另一件事(这不应该是一个问题):您正在使用内部定义为默认C编译器的变量CC
。没关系,因为你重新定义它,但由于你的源似乎是C ++文件,为什么不使用变量CXX
,即internally defined作为C ++编译器?
最后,为确保正确定义您的文件集,您可以使用虚拟show
目标see here打印它们。
show:
@echo "OBJECTSTEST=$(OBJECTSTEST)"
...
答案 1 :(得分:2)
该链接显示过时的方法,例如suffix rules。在编译过程中也可以通过gcc / g ++来完成依赖关系。
至于其余部分,请注意:
EXE := test
SRCDIR := src
OBJDIR := .obj
SRC := $(shell find $(SRCDIR) -name "*.cpp")
OBJ := $(SRC:$(SRCDIR)/%.cpp=$(OBJDIR)/%.o)
DEP := $(OBJ:.o=.d)
LDLIBS := # -l flags
LDFLAGS := # -L flags
CPPFLAGS := -MMD -MP # -I flags also
CXXFLAGS := -W -Wall # no -c flag here
.PHONY: all clean fclean re
all: $(EXE)
clean:
$(RM) -r $(OBJDIR)
fclean: clean
$(RM) $(EXE)
re: fclean all
-include $(DEP)
$(EXE): $(OBJ)
$(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp
@mkdir -p $(@D)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $@ -c $<
不重新定义内部定义的变量,没有后缀规则,正确的链接步骤和依赖关系生成。
更新:为避免为每个源文件调用mkdir
,应使用order-only prerequisites和特殊目标.SECONDEXPANSION
。
更改此块:
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp
@mkdir -p $(@D)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $@ -c $<
对此:
.SECONDEXPANSION:
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp | $$(@D)/
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $@ -c $<
%/:
mkdir $*