如何在make下编译多个文件

时间:2012-10-18 10:27:17

标签: c++ compiler-construction linker makefile g++

我有几个.cpp和.hpp文件。我想编译并使用make将它们放在一边。我怎么能这样做?

    sample.cpp sample.hpp
    sample_2.cpp sample_2.hpp
    sample_3.cpp sample_3.hpp
    ...
    and 
    main.cpp

    I have done :

    default:

             g++ -c sample sample.cpp
             g++ -c sample_2 sample_2.cpp
             g++ -c sample_3 sample_3.cpp

             g++ -o main main.cpp sample sample_2 sample_3

当我在终端上键入make时,它会出错:

 /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 0 has invalid symbol index 10

1 个答案:

答案 0 :(得分:3)

不是让一个default目标执行所有操作,而是每个单独的输出应该是一个make目标。这允许make正常工作,以正确的顺序一次构建一个东西(或者如果依赖图允许的话,并行构建)并在每个步骤正确地报告错误。此外,非常重要的是,通过告诉make每个单独的目标以及它们依赖的内容,您确保在依赖项更改时,确切地知道由于更改的依赖项需要重建哪些目标。这是Make的最佳功能。

在您的情况下,最终目标是main,因此您希望default目标构建该目标,您可以通过说mainmain的先决条件来执行此操作:< / p>

default: main

现在你需要说明如何构建main,它取决于各种目标文件,所以我们告诉make:

main: main.o sample.o sample_2.o sample_3.o

这说明它取决于那些目标文件(它们是它们的先决条件),因此它们将首先构建。每个对象都是另一个将单独构建的make目标。

当构建了所有先决条件后,将使用配方将它们链接到main,因此我们需要为上述目标添加配方:

main: main.o sample.o sample_2.o sample_3.o
        g++ main.o sample.o sample_2.o sample_3.o -o main

Make有很多缩写来简化事情,例如$(CXX)是C ++编译器,$@表示当前目标,$^表示当前目标的先决条件,因此您可以将该规则简化为:

main: main.o sample.o sample_2.o sample_3.o
        $(CXX) $^ -o $@

这实际上就是你所需要的,Make已经知道如何使用其内置规则构建.o先决条件,因此它将看到一个名为main.cpp的文件并且知道它可以编译它来创建{{1}并查看main.o并将其编译为sample.cpp等。它将从makefile创建一个依赖图,以确定构建sample.o所需的目标(这意味着它决定了它需要default,并且需要mainmain.o等等,并且它们需要已经存在的sample.omain.cpp等,因此它可以开始构建先决条件,直到它拥有链接sample.cpp所需的一切,然后它可以做到并完成。)

现在,如果您更改main并再次运行sample_2.cpp,则会看到make已过期,需要重新编译,但其他sample_2.o文件仍然存在好的(它们比它们所依赖的.o文件更新),因此它将重新编译.cpp并重新链接sample_2.o 而不是重建其他所有文件

事实上,通过使用默认配方将对象链接到可执行文件中,您可以进一步简化它:

main

这就是你所需要的!但是,对于初学者来说,使用更详细的版本通常更清晰,因为当您不熟悉Make的所有自动规则和变量时,它更容易定制。

告诉make有关头文件的依赖关系也很有帮助,这样当标题更改时会重建内容。这可以使用编译器自动完成,以生成先决条件,但对于简单的情况,您可以直接将其添加到makefile中,例如。

LINK.o = $(CXX)

default: main

main: main.o sample.o sample_2.o sample_3.o