Build Makefile-文件夹中的依赖项文件;没有这样的文件或目录;

Build Makefile-文件夹中的依赖项文件;没有这样的文件或目录;,build,makefile,dependencies,Build,Makefile,Dependencies,我有一个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` 还有

我有一个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过于臃肿。谢谢大家!

我认为您的
Makefile
有点过于具体,因此容易出错。我建议看我下面的例子,它比你的例子更一般

我的示例利用了
make
对隐式规则的概括。对于
cpp
-文件已存在通用隐式规则。那么为什么人们不应该使用它呢

参考手册对其描述如下:

<强>编译C++程序>P/> n、 o由n.cc、n.cpp或n.C自动生成,其配方为

$(CXX)$(CPPFLAGS)$(cxflags)-C

因此,如果您有
%.o
文件作为先决条件,如规则
dotgazer.out:$(OBJS)
make
将上述隐式规则自动应用于所有这些文件。假设您已为
CXX
CPPFLAGS
和/或
cxflags
设置了有效值

此外,您通常不需要手动将源添加到变量中。大多数情况下,构建可执行文件需要项目目录树中的所有源。如果不是这样的话,你应该考虑建立一个合适的树来反映这一点。 由于
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)

我可能很傻,但是
%.o:%.cpp
dotgazer/Dot.o:dotgazer/Dot.cpp
规则不是加倍了吗?比如,后一个目标不是已经被前一个处理了吗?@AdamGoodwin我认为它会这样工作(只需要
%.o:%.cpp
规则)。但事实证明——没有。所以我特别为第二个依赖项添加了第二条规则,但它仍然不起作用。只使用
%.o:%.cpp
规则,消息是相同的:
无法创建dotgazer/Dot.o:没有这样的文件或目录
嗯,我刚刚尝试了你的makefile,它对我来说很好。即使只有
%.o
目标,而没有
dotgazer/Dot.o
目标,它也能工作。您在文件名或目录方面没有犯错误,是吗?或者你正在做一些事情,比如从它自己的目录以外的其他地方运行makefile?我很确定没有拼写错误或任何东西。我是从Netbeans运行它的,所以我认为它运行在Makefile文件夹中的
make
。无论如何,这个被接受的答案比我预期的要好得多。非常棒的答案,谢谢!它有我所需要的一切,所有文件都是单独编译的,
.o
文件在各自的文件夹中。但是有一个问题,尽管有
LDLIBS
设置,OpenCV函数还是无法识别。以下是输出:
dotgazer.out
规则应该如下所示:
$(CXX)$^-o$@$(LDLIBS)
。但是,这仍然是一个很好的答案!您是对的,我应该将
$(CXX)$(LDLIBS)$^-o$@
更改为
$(CXX)$(LDLIBS)-o$$^
g++--help
sai表示输入文件应位于选项之后。最好注意这不是问题所在。
-o
可以随时出现。问题是库必须排在最后(库的列出顺序也很重要)。另外,
CPPFLAGS
用于C预处理器标志(
-I
/
-D
);编译器标志如
-Wall-pg-O2
属于
cxflags
(对于C++)。要链接,请使用类似于
$(CXX)$(cxflags)$(LDFLAGS)-o$@$^$(LDLIBS)
@madcasciient:谢谢您的评论。特别是您指出了不同之处。
cxflags
CPPFLAGS
(我将相应地编辑我的答案)。直到现在我才意识到这一点。您的声明有任何参考资料吗
…库必须在最后一个
。直到今天,我的方法从来没有任何问题,但谢谢你在将来为我省去了麻烦。。。