1.1 makefile helloworld
Makefile的规则如下:
target ... : prerequisites ...
command ... ...
target可以是一个目标文件,也可以是Object File(例如helloworld.obj),也可以是执行文件和标签。
prerequisites就是生成target所需要的文件或是目标。
command也就是要达到target这个目标所需要执行的命令。这里没有说“使用生成target所需要执行的命令”,是因为target可能是标签。需要注意的是command前面必须是TAB键,而不是空格,因此喜欢在编辑器里面将TAB键用空格替换的人需要特别小心了。
我们写程序一般喜欢写helloworld,当我们写了一个c的helloworld之后,我们该如何写helloworld来编译helloworld.c呢?
下面就是编译helloworld的makefile。
helloworld : helloworld.o cc -o helloworld helloworld .o helloworld.o : helloworld.c cc -c main.c clean: rm helloworld helloworl.o |
之后我们执行make就可以编译helloworld.c了,执行make clean就可以清除编译结果了(其实就是删除helloworld helloworl.o)。
可能有人问为什么执行make就会生成helloworld呢?这得从make的默认处理说起:make将makefile的第一个target作为作为最终的
target,凡是这个规则依赖的规则都将被执行,否则就不会执行。所以在执行make的时候,clean这个规则就没有被执行。
上面的是最简单的makefile,复杂点makefile就开始使用高级点的技巧了,例如使用变量,使用隐式规则,执行负责点shell命令(常见的是字符串处理和文件处理等),这里不打算介绍这些规则,后面在分析android的makefile时会结合具体代码进行具体分析,大家可以先看看陈皓的《跟我一起写makefile》来了解了解。
makefile的大体的结构是程序树形的,如下:
这样写起makefile也简单,我们将要达到的目标作为第一个规则,然后将目标分解成子目标,然后一个个写规则,依次类推,直到最下面的规则很容易实现为止。这其实和算法里面的分治法很像,将一个复杂的问题分而治之。
说到树,我想到了编译原理里面的语法分析,语法分析里面有自顶而下的分析方法和自底而下的分析方法。当然makefile并不是要做语法分析,而是要做与语法分析分析相反的事。(语法分析要做的是一个句子是不是根据语法可以推出来,而makefile要做的是根据规则生成一个command 执行队列。)不过makefile的规则和词法分析还是很像的。下面出一道编译原理上面的一个例子,大家可以理解一下makefile和词法分析的不同点和相同点:
<标识符> -> <字母><字母数字串>
<字母数字串> -> <字母><字母数字串>|<数字><字母数字串>|<下划线><字母数字串>|ε
<无符号整数> -> <数字><数字串>
<数字串> -> <数字><数字串>|ε
<加法运算符> -> &#43;
<减法运算符> -> -
<大于关系运算符> -> >
<大于等于关系运算符> -> >&#61;
最后&#xff0c;介绍一下autoconfautomake&#xff0c;使用这两个工具可以自动生成makefile。
从上面的图可以看出&#xff0c;通过autoscan&#xff0c;我们可以根据代码生成一个叫做configure.scan的文件&#xff0c;然后我们编辑这个文件&#xff0c;参数一个configure.in的文件。接着我们写一个makefile.am的文件&#xff0c;然后就可以用automake生成makefile.in&#xff0c;最后&#xff0c;根据makefile.in和configure就可以生成makefile了。在很多开源的工程里面&#xff0c;我们都可以看到makefile.am,configure.in,makefine.in,configure文件&#xff0c;还有可能看到一个十分复杂的makefile文件&#xff0c;许多人学习makefile的时候想通过看这个文件来学习&#xff0c;最终却发现太复杂了。如果我们知道这个文件是自动生成的&#xff0c;就理解这个makefile文件为什么这个复杂了。
欲更加详细的理解automake等工具&#xff0c;可以参考http://www.ibm.com/developerworks/cn/linux/l-makefile/。