C++ makefile的正确使用

C++ makefile的正确使用,c++,compilation,makefile,C++,Compilation,Makefile,所以,我试图理解makefile。现在我有一个项目,其中包含一些模块,它们或多或少互不依赖 我的目录树如下所示: root/ - Source/ <-- referenced as $(INPUTPATH) - Build/ <-- referenced as $(BUILDPATH) - Release/ <-- referenced as $(OUTPUTPATH) - Makefile all: maps auxiliars methods @echo "lin

所以,我试图理解makefile。现在我有一个项目,其中包含一些模块,它们或多或少互不依赖

我的目录树如下所示:

root/
- Source/ <-- referenced as $(INPUTPATH)
- Build/ <-- referenced as $(BUILDPATH)
- Release/ <-- referenced as $(OUTPUTPATH)
- Makefile
all: maps auxiliars methods
    @echo "linking...";\
    $(CC) $(CFLAGS) $(OBJS) $(CLIBS) -o ${OUTPUTPATH}/MainProgram

dependency1: $(INPUTPATH)/foo.cpp
    @echo "compiling ArbPrecision...";\
    cd ${BUILDPATH};\
    $(CC) $(CFLAGS) $(CINCLUDE) -c ../$?

dependency2: dependency1 $(INPUTPATH)/bar.cpp
    @echo "compiling saddleConstructor...";\
    cd ${BUILDPATH};\
    $(CC) $(CFLAGS) $(CINCLUDE) -c ../$(INPUTPATH)/bar.cpp

maps: dependency2 $(INPUTPATH)/*Map.cpp
    @echo "compiling maps...";\
    cd ${BUILDPATH};\
    $(CC) $(CFLAGS) $(CINCLUDE) -c ../$(INPUTPATH)/*Map.cpp
... (auxiliars and methods)
$CINCLUDE和cflag只是编译器的东西,比如头文件和外部lib

一切工作都几乎完美:在每个目标上,它要求其他目标的依赖项,以及源上的*cpp。如果不存在,则调用目标并编译*cpp。创建的可执行文件没有错误

但是,如果我调用“make”两次,编译第一次和第二次所需的时间是相同的,即使我没有对源代码进行任何更改。显然,我没有纠正依赖关系

有人能告诉我执行此编译的正确方向吗?我做错了什么,我不明白它是什么

谢谢,
Jorge

Make希望在文件之外进行操作。对于每个规则,它检查由该规则命名的目标文件(1)是否存在,以及(2)是否是最新的(即,在其任何依赖项之后进行了修改)。如果文件不是最新的,那么它将执行规则使其成为最新的

因此,在当前编写makefile时,当您运行
make
时,make执行以下操作:

OBJS := foo.o bar.o Map.o

all: $(OUTPUTPATH)/MainProgram

$(OUTPUTPATH)/MainProgram: $(OBJS)
    $(CC) $(CFLAGS) $(OBJS) $(CLIBS) -o $(OUTPUTPATH)/MainProgram

%.o: %.cpp
    $(CC) $(CFLAGS) $(CINCLUDE) $< -c $@

.PHONY: all
  • all
    是第一条规则,因此如果不指定任何参数,请使用
    all
    规则进行处理
  • 不存在名为
    all
    的文件,因此需要执行
    all
    规则
  • all
    取决于
    dependency1
    规则。不存在名为
    dependency1
    的文件,因此需要执行
    dependency1
    规则
  • dependency1
    取决于
    dependency2
    规则。不存在名为
    dependency2
    的文件,因此需要执行
    dependency2
    规则
相反,您想要的是类似于以下内容的内容:

OBJS := foo.o bar.o Map.o

all: $(OUTPUTPATH)/MainProgram

$(OUTPUTPATH)/MainProgram: $(OBJS)
    $(CC) $(CFLAGS) $(OBJS) $(CLIBS) -o $(OUTPUTPATH)/MainProgram

%.o: %.cpp
    $(CC) $(CFLAGS) $(CINCLUDE) $< -c $@

.PHONY: all
OBJS:=foo.o bar.o Map.o
全部:$(输出路径)/main程序
$(OUTPUTPATH)/Main程序:$(OBJS)
$(CC)$(CFLAGS)$(OBJS)$(CLIBS)-o$(OUTPUTPATH)/main程序
%.o:%.cpp
$(CC)$(CFLAGS)$(c包括)$<-c$@
冒牌货:全部
注意以下几点:

OBJS := foo.o bar.o Map.o

all: $(OUTPUTPATH)/MainProgram

$(OUTPUTPATH)/MainProgram: $(OBJS)
    $(CC) $(CFLAGS) $(OBJS) $(CLIBS) -o $(OUTPUTPATH)/MainProgram

%.o: %.cpp
    $(CC) $(CFLAGS) $(CINCLUDE) $< -c $@

.PHONY: all
  • 由于Make操作文件,所以规则的目标和依赖项尽可能按文件名列出

  • 不是单独列出.cpp文件,而是使用来构建每个.o文件。在模式规则中,编译输入时的
    $是源文件(即.cpp文件),输出是目标文件(通常是.o或.obj文件)。这就是你应该去的地方。您应该说bar.o依赖于bar.cpp等。类似地,链接步骤,您的程序依赖于一组对象文件,因此它们应该列在
    所有
    的dependemcies中。模式规则必须包括目录名:
    $(BUILDPATH)/%.o:$(INPUTPATH)/%.cpp
    @anatolyg-谢谢。我过分简化了路径,一部分是为了关注概念,另一部分是因为我懒惰。:-)好的,这是一个很大的区别…:p为什么用-o编译对象,用-o编译可执行文件?-c不是用于编译,而-o不是用于链接吗?@J.c.Leitão-Oops。固定的。谢谢。好的,谢谢你的解释,我想错了。现在我想我理解了makefile的基本思想。