三个简单的makefile问题

时间:2018-04-11 02:44:18

标签: c++ makefile

我刚刚介绍了makefile(用于c ++程序),我有三个简单的问题。假设我在functions.h中存储了一些类定义,其定义在functions.cpp中定义,并在main.cpp中实现。我的简易makefile是:

CXX=g++

main: functions.o main.o
   ${CXX} -o main student.o main.o

clean: 
   rm -f *.o main

我的想法是,当我调用make时,默认为main并查找.o文件。如果它们不存在,那么makefile会自动创建.o文件,然后执行链接到main。首先,当我们可以简单地做什么时,为什么还要烦恼呢?

${CXX} -o main functions.cpp main.cpp

我开始研究宏,然后找到了重新实现makefile的方法:

main: functions.o main.o
   ${CXX} $^ -o $@

我假设$ ^和$ @自动填写主文件和目标文件?如何获得这些信息?

我的最后一个问题是为什么订单会改变?我的原始makefile的格式为g ++ -o [name] [dependents],而带有宏的那个有g ++ [name] -o [dependents]。我尝试切换顺序,但然后makefile停止工作。切换为什么?

3 个答案:

答案 0 :(得分:3)

你这里有很多问题。我会尝试为你解答。

  

首先,为什么我们只需要做到这一点就烦扰所有这些

     

$ {CXX} -o main functions.cpp main.cpp

是的,你也可以这样做。有时将编译阶段与链接阶段分开会更方便,但您不必这样做。

  

如何知道获取此信息?

$ @扩展为正在调用的规则的名称。在这种情况下,规则的名称为main。 $ ^扩展为所有先决条件的名称(规则行上:之后的所有内容。)在这种情况下,$ ^扩展为functions.o main.o。如果展开规则并展开宏,则会得到:

main: functions.o main.o
    ${CXX} functions.o main.o -o main
  

我的最后一个问题是为什么订单会改变?

如果您将命令编写为:

,则无关紧要
${CXX} functions.o main.o -o main

或作为:

${CXX} -o main functions.o main.o

它们是等价的。现在您可能会发现您误解了宏是如何扩展的。

GNU Make manual解释了所有这些内容,这些内容既繁琐,又非常有用。

答案 1 :(得分:0)

1a上。你的假设是正确的。 GNU make正在执行内置规则以将.c文件转换为.o文件。它运行您的显式规则以将.o文件链接在一起。

1b中。为什么要采取两个步骤(一个用于编译,另一个用于链接)?它们是不同的步骤,恰好得到了g ++编译器的支持。这是g ++提供的便利。但是有很多方法可以创建.o文件。有些可能来自.c文件,有些来自.cpp文件,还有一些可能来自另一种语言,如Fortran。在所有这些情况下,编译步骤是不同的,但链接步骤是类似的。因此,将构建分为两个步骤有助于管理这些差异。

  1. 正确,这些是自动变量:https://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html $ @将替换为规则的目标,$ ^将替换为规则的所有先决条件列表。

  2. 命令略有不同。你的第一个是" g ++ -o main functions.cpp main.cpp"你的第二个是" g ++ functions.o main.o -o main"。第一个命令是两个步骤(编译和链接),第二个命令只是链接。通常,命令行参数的顺序对于像g ++这样的工具并不重要。但是,我认为在这种情况下,链接,.o文件需要在输出文件选项之前。

答案 2 :(得分:0)

在IMO的其他答案中没有充分解决的一个问题是为什么单独编译和链接。对于像这样的小项目来说,真的并不重要。但对于大型项目而言,差异可能非常显着。

请注意

${CXX} -o main functions.cpp main.cpp

将始终编译两个源文件,将它们链接在一起,并丢弃目标文件(.o)。相比之下,

${CXX} -o main functions.o main.o

只会链接目标文件。 Make将检测目标文件何时过期并重新编译。未过期的目标文件不需要重新编译。

编译步骤可能需要很长时间。特别是对于带有大量模板代码的C ++。相比之下,即使对于大型项目,链接通常也非常快。

如果在大型项目中修改了一个源文件,则无需重新编译所有其他源文件。通过在makefile中分离编译和链接,可以确保make只编译您更改的一个源文件,从而在开发周期中节省大量时间。