到目前为止,我有一个运行良好的Makefile。虽然,随着它开始增长,每次重新编译所有来源都开始花费太长时间。以下是工作版本的片段:
CC=$(CROSS_COMPILE)g++
CFLAGS=-Wall -I./include -pg -O2
VPATH=./src:./include
all: dotgazer.cpp dotgazer/Dot.cpp
$(CC) $(CFLAGS) $^ -o dotgazer.out `pkg-config --libs opencv`
有很多依赖项,但这两项足以说明问题所在。我正在尝试将每个cpp
文件的编译阶段移动到单独的目标。当涉及到顶级文件(dotgazer.cpp
)时,这不是问题,一般规则%.o: %.cpp
正常工作。但我不能让第二个依赖工作。以下是它现在的样子:
CC=$(CROSS_COMPILE)g++
CFLAGS=-Wall -I./include -pg -O2
VPATH=./src:./include
all: dotgazer.o dotgazer/Dot.o
$(CC) $(CFLAGS) $^ -o dotgazer.out `pkg-config --libs opencv`
%.o: %.cpp
$(CC) -c $(CFLAGS) $^ -o $@
dotgazer/Dot.o: dotgazer/Dot.cpp
$(CC) -c $(CFLAGS) $^ -o $@
我尝试了Dot.o
规则的不同变体,但它们似乎都没有效果。我从上面得到的错误是:
Fatal error: can't create dotgazer/Dot.o: No such file or directory
我该怎么做?我最希望将.o
个文件放在与其源相同的文件夹中。另外,我会感谢一般规则(如%.o: %.cpp
),因为有很多源文件,我不希望Makefile过于膨胀。谢谢!
答案 0 :(得分:1)
我认为你的Makefile
有点具体,因而容易出错。我建议看看下面的例子,它比你的更通用。
我的例子充分利用了make
隐含规则的措辞。对于cpp
- 文件已存在通用隐式规则。那么为什么不使用它呢?
参考手册描述如下:
编译C ++程序
n.o是从n.cc,n.cpp或n.C自动生成的,其形式为
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c
。
因此,如果您有%.o
个文件作为先决条件,例如规则dotgazer.out: $(OBJS)
make
将隐式规则自动应用于所有这些文件。假设您为CXX
,CPPFLAGS
和/或CXXFLAGS
设置了有效值。
此外,您通常不需要手动将源添加到变量中。大多数情况下,构建可执行文件需要项目目录树中的所有源代码。如果不是这种情况,您应该考虑构建一个反映这一点的适当树。
由于find
负责将来源分配到CPPFILES
,因此我们也不需要设置VPATH
。由于我们使用find
和patsubst
,我们的Makefile
只有一个明确的文件名。这使得在一个真正的项目上工作得更加顺畅。
当然,您不需要all
和clean
规则。我刚刚添加了这些以方便起见。
CXX=$(CROSS_COMPILE)g++
CPPFLAGS=-I./include
CXXFLAGS=-Wall -pg -O2
LDLIBS=`pkg-config --libs opencv`
CPPFILES=$(shell find . -name "*.cpp")
OBJS=$(patsubst %.cpp, %.o, $(CPPFILES))
all: dotgazer.out
@echo $(CPPFILES)
@echo $(OBJS)
dotgazer.out: $(OBJS)
$(CXX) $(CXXFLAGS) -o $@ $^ $(LDLIBS)
clean:
rm -f $(OBJS)