我正试图为我的项目创建一个makefile,但在测试新事物时,我似乎遇到了一些错误。我的文件结构如下:
~/main #root project folder
~/main/include #header files (mostly class headers)
~/main/src #source files
~/main/src/obj #object files
Makefile
(Makefile在根项目文件夹中)
生成文件:
CC=g++
IDIR=include
SDIR=src
ODIR=src/obj
DEPS=$(IDIR)/%.h
OBJS=$(ODIR)/%.o
SRCS=$(SDIR)/%.cpp
CFLAGS=-Wall -std=c++11 -I$(IDIR)
$(OBJS): $(SRCS) $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS)
all: $(OBJS)
gcc -o run $^ $(CFLAGS)
.PHONY: clean
clean:
rm -f $(OBJS)
出于测试目的,我在src
文件夹中有一个main.cpp
,在include
文件夹中有个随机头文件。运行简单的make
命令时,我得到的错误如下:
make: *** No rule to make target `src/obj/%.o', needed by `all'. Stop.
编辑:在下面的人的帮助下,我想出了的解决方案
CC=g++
IDIR=include
SDIR=src
ODIR=src/obj
CFLAGS=-Wall -std=c++11 -I$(IDIR)
_DEPS = yo.h
DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))
_OBJ = main.o
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
_SRC = main.cpp
SRC = $(patsubst %,$(SDIR)/%,$(_SRC))
$(ODIR)/%.o: $(SRC) $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS)
all: $(OBJ)
$(CC) -o run $^ $(CFLAGS) $(LIBS)
.PHONY: clean
clean:
rm -f $(OBJS)
在两种情况下使用%
是有区别的。当你写:
$(ODIR)/%.o : $(SDIR)/%.cpp $(IDIR)/%.h
这将进行模式替换,并创建一组规则,如:
$(ODIR)/foo.o : $(SDIR)/foo.cpp $(SDIR)/foo.h
所以它在那里很好,尽管您应该在那里显式地使用%
,这样就可以清楚地看到规则在做什么。
但当你在这里使用它时:
all : $(ODIR)/%.o
这实际上是在寻找没有规则的目标$(ODIR)/%.o
。没有替代品。而且你没有一条规则来达到这个目标——因此出现了错误。您想要做的是让all
依赖于所有实际的对象,为此您需要使用wildcard
函数:
SOURCES = $(wildcard $(SDIR)/*.cpp)
OBJECTS = $(SOURCES:$(SDIR)/%.cpp=$(ODIR)/%.o)
all : $(OBJECTS)
gcc -o run $^ $(CFLAGS)
使用时
OBJS=$(ODIR)/%.o
%.o
部分没有扩展到任何有意义的内容。它只是保留为文字值%.o
。DEPS
和SRCS
也存在同样的问题。
您需要使用wildcard
和patsub
函数。代替
DEPS=$(IDIR)/%.h
OBJS=$(ODIR)/%.o
SRCS=$(SDIR)/%.cpp
使用
DEPS=$(wildcard $(IDIR)/*.h)
SRCS=$(wildcard $(SDIR)/*.cpp)
OBJS=$(patsub %.cpp,%.o,$(SRCS))