GNU Make是一个控制编译过程的工具。它控制程序的源文件如何生成可执行文件或非源文件,其实就是指定一种方式自动化我们的构建过程。
我们先来了解一下,一个程序是怎么被编译出来的。
在得到一个可执行文件之前,要先编译出目标文件,再把目标文件链接起来。
(注意:编译过程中,会先做预处理,把一些宏展开,include等包含进来等,得到*.i
或*.ii
,接着编译得到汇编程序*.s
,再汇编得到目标文件*.o
,最后把目标文件链接起来得到可执行文件)。
第一步编译出目标文件
如何得到目标文件呢?可以让编译器只编译成目标文件:
g++ main.cpp –c –o main.o
g++ library.cpp –c –o library.o
-c
表示只编译(compile only)
第二步链接目标文件
g++ library.o main.o -o main
如果将上面的步骤用makefile来表达,makefile该如何写呢?
根据上述的信息,我们可以得到以下信息
- main.o要用main.cpp文件生成
- library.o要用library.cpp文件生成
- main可执行文件要用前面生成的目标文件来链接产生
因此makefile文件可以这样写。
main.o: main.cpp
g++ main.cpp -c -o main.o
library.o: library.cpp
g++ library.cpp -c -o library.o
main: main.o library.o
g++ main.o library.o -o main
将上面内容保存到一份名为makefile的文件当中
使用make命令执行makefile的编译过程,通过下面的结果我们会发现,只会执行makefile的第一行,得到main.o。
如果我们用make. main
呢?
我们指定make执行的目标为main,那么它就会把结果所依赖的资源所需要执行的命令也执行了。
我们继续丰富我们这份makefile文件。
main.o: main.cpp
g++ -Wall -g main.cpp -c -o main.o
library.o: library.cpp
g++ -Wall -g library.cpp -c -o library.o
main: main.o library.o
g++ -Wall -g main.o library.o -o main
我们增加了-Wall -g
, 其中 -Wall
表示在编译过程出现警告都打印出来,-g
表示编译出可用gdb调试用的文件。而且我们发现三条命令都有g++ -Wall -g
,我们可以用一个变来存储起来,在后面通过引用变量的方式加到每个命令中:
cxx = g++ -Wall –g
main.o: main.cpp
$(cxx) main.cpp -c -o main.o
library.o: library.cpp
$(cxx) library.cpp -c -o library.o
main: main.o library.o
$(cxx) main.o library.o -o main