【问题标题】:proper usage of makefile正确使用makefile
【发布时间】:2012-10-16 10:23:27
【问题描述】:

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

我的目录树是这样的:

root/
- Source/ <-- referenced as $(INPUTPATH)
- Build/ <-- referenced as $(BUILDPATH)
- Release/ <-- referenced as $(OUTPUTPATH)
- Makefile

我想在 Source/ 上拥有源代码 (.cpp/.h),在 Build/ 上拥有对象,在 Release/* 上拥有可执行文件。

所以,我的想法是有几个不同的目标,并像这样使用它们:

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 和 CFLAGS 只是编译器的东西,比如头文件和外部库。

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

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

谁能指出我执行此编译的正确方向?我做错了什么,我不明白它是什么。

谢谢, 豪尔赫

【问题讨论】:

  • 编译时,输入是源文件(即 .cpp 文件),输出是目标文件(通常是 .o 或 .obj 文件)。那是你应该依赖的地方。你应该说 bar.o 依赖于 bar.cpp 等。同样的链接步骤,你的程序依赖于一堆目标文件,所以它们应该放在 all 的依赖中。

标签: c++ compilation makefile


【解决方案1】:

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

因此,由于当前编写了您的 makefile,当您运行 make 时,Make 会执行以下操作:

  • all 是第一条规则,因此如果您不指定任何参数,make 将处理 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

注意以下几点:

  • 由于 Make 对文件进行操作,规则的目标和依赖项尽可能按文件名列出。
  • 不是单独列出 .cpp 文件,而是使用pattern rule 来构建每个 .o 文件。在模式规则中,$&lt;$@ automatic variables 分别用于指定第一个先决条件(文件)和目标(文件)。
  • 默认回显其命令,因此无需自己echo
  • 对于 GNU Make,all 被列为 phony target,以防止 Make 查找名为 all 的文件。

【讨论】:

  • 模式规则必须包含目录名称:$(BUILDPATH)/%.o: $(INPUTPATH)/%.cpp
  • @anatolyg - 谢谢。我过度简化了路径,部分原因是为了专注于概念,部分原因是我很懒惰。 :-)
  • 好吧,这是一个很大的不同... :p 为什么你用 -o 编译对象而用 -o 编译可执行文件? -c 不是用来编译的,-o 不是用来链接的吗?
  • @J.C.Leitão - 哎呀。固定的。谢谢。
  • 好的,谢谢你的解释,我想错了。现在我想我理解了 makefile 的基本思想。
猜你喜欢
  • 2018-05-29
  • 2017-05-04
  • 1970-01-01
  • 2012-08-21
  • 1970-01-01
  • 2018-07-22
  • 2017-08-30
  • 2023-03-30
  • 2012-05-27
相关资源
最近更新 更多