现在的位置: 首页 > 综合 > 正文

GNU Make手册阅读笔记(1)– 第一章和第二章

2013年08月22日 ⁄ 综合 ⁄ 共 4033字 ⁄ 字号 评论关闭

GNU Make中文手册

http://www.linuxsir.org/main/doc/gnumake/GNUmake_v3.80-zh_CN_html/index.html#content

 

第一章  概述

1.Make介绍

所要完成的
Makefile
文件描述了整个工程的编译、连接等规则。其中包括:工程中的哪些源文件需要编译以及如何编译、需要创建那些库文件以及如何创建这些库文件、如何最后产生我们想要得可执行文件。尽管看起来可能是很复杂的事情,但是为工程编写
Makefile
的好处是能够使用一行命令来完成“自动化编译”,一旦提供一个(通常对于一个工程来说会是多个)正确的
Makefile
。编译整个工程你所要做的唯一的一件事就是在
shell


提示符下输入

make
命令。整个工程完全自动编译,极大提高了效率。


make

是一个命令工具,它解释
Makefile
中的指令(应该说是规则)。在
Makefile
文件中描述了整个工程所有文件的编译顺序、编译规则。
Makefile
有自己的书写格式、关键字、函数。像
C
语言有自己的格式、关键字和函数一样。而且在
Makefile
中可以使用系统
shell
所提供的任何命令来完成想要的工作。
Makefile
(在其它的系统上可能是另外的文件名)在绝大多数的
IDE
开发环境中都在使用,已经成为一种工程的编译方法。

2.相关知识


编译:把高级语言书写的代码转换为机器可识别的机器指令。编译高级语言后生成的指令虽然可被机器识别,但是还不能被执行。编译时,编译器检查高级语言的语
法、函数与变量的声明是否正确。只有所有的语法正确、相关变量定义正确编译器就可以编译出中间目标文件。通常,一个高级语言的源文件都可对应一个目标文
件。目标文件在

Linux
中默认后缀为“
.o
”(如“
foo.c
”的目标文件为“
foo.o
”)。



为了和规则的目标文件相区别。本文将编译高级语言后生成的目标文件成为

.o
文件。


链接:将多

.o
文件,或者
.o
文件和库文件链接成为可被操作系统执行的可执行程序(
Linux
环境下,可执行文件的格式为“
ELF
”格式)。链接器不检查函数所在的源文件,只检查所有
.o
文件中的定义的符号。将
.o
文件中使用的函数和其它
.o
或者库文件中的相关符号进行合并,对所有文件中的符号进行重新安排(重定位),并链接系统相关文件(程序启动文件等)最终生成可执行程序。链接过程使用
GNU


的“

ld
”工具。


静态库:又称为文档文件(

Archive
File

)。它是多个
.o
文件的集合。
Linux
中静态库文件的后缀为“
.a
”。静态库中的各个成员(
.o
文件)没有特殊的存在格式,仅仅是一个
.o
文件的集合。使用“
ar
”工具维护和管理静态库。


共享库:也是多个

.o
文件的集合,但是这些
.o
文件时有编译器按照一种特殊的方式生成(
Linux
中,共享库文件格式通常为“
ELF

格式。共享库已经具备了可执行条件)。模块中各个成员的地址(变量引用和函数调用)都是相对地址。使用此共享库的程序在运行时,共享库被动态加载到内存并
和主程序在内存中进行连接。多个可执行程序可共享库文件的代码段(多个程序可以共享的使用库中的某一个模块,共享代码,不共享数据)。另外共享库的成员对
象可被执行(由

libdl.so
提供支持)。

 

第二章  GNU Make介绍

1.Make的比较方式

        make
通过比较对应文件(规则的目标和依赖,)的最后修改时间,来决定哪些文件需要更新、那些文件不需要更新。对需要更新的文件
make
就执行数据库中所记录的相应命令(在
make
读取
Makefile
以后会建立一个编译过程的描述数据库。此数据库中记录了所有各个文件之间的相互关系,以及它们的关系描述)来重建它,对于不需要重建的文件
make
什么也不做。

2.Make规则介绍


一个简单的

Makefile
描述规则组成:


TARGET... :
PREREQUISITES...



COMMAND


...


...


target

:规则的目标。通常是最后需要生成的文件名或者为了实现这个目的而必需的中间过程文件名。可以是
.o
文件、也可以是最后的可执行程序的文件名等。另外,目标也可以是一个
make
执行的动作的名称,如目标“
clean
”,我们称这样的目标是“伪目标”。


prerequisites

:规则的依赖。生成规则目标所需要的文件名列表。通常一个目标依赖于一个或者多个文件。


command

:规则的命令行。是规则所要执行的动作(任意的
shell
命令或者是可在
shell
下执行的程序)。它限定了
make
执行这条规则时所需要的动作。


一个规则可以有多个命令行,每一条命令占一行。注意:每一个命令行必须以

[Tab]
字符开始,
[Tab]
字符告诉
make
此行是一个命令行。
make
按照命令完成相应的动作。这也是书写
Makefile
中容易产生,而且比较隐蔽的错误。


命令就是在任何一个目标的依赖文件发生变化后重建目标的动作描述。一个目标可以没有依赖而只有动作(指定的命令)。比如

Makefile
中的目标“
clean
”,此目标没有依赖,只有命令。它所定义的命令用来删除
make
过程产生的中间文件(进行清理工作)。



Makefile
中“规则”就是描述在什么情况下、如何重建规则的目标文件,通常规则中包括了目标的依赖关系(目标的依赖文件)和重建目标的命令。
make
执行重建目标的命令,来创建或者重建规则的目标(此目标文件也可以是触发这个规则的上一个规则中的依赖文件)。
规则包含了文件之间的依赖关系和更新此规则目标所需要的命令。


一个

Makefile
文件中通常还包含了除规则以外的很多东西(后续我们会一步一步的展开)。一个最简单的
Makefile
可能只包含规则。规则在有些
Makefile
中可能看起来非常复杂,但是无论规则的书写是多么的复杂,它都符合规则的基本格式。


make

程序根据规则的依赖关系,决定是否执行规则所定义的命令的过程我们称之为执行规则

3.Makefile示例


#sample
Makefile



edit :
main.o kbd.o command.o display.o /



insert.o
search.o files.o utils.o



cc -o edit
main.o kbd.o command.o display.o /



insert.o
search.o files.o utils.o



main.o :
main.c defs.h



cc -c
main.c   



kbd.o :
kbd.c defs.h command.h



cc -c kbd.c


command.o :
command.c defs.h command.h



cc -c
command.c



display.o :
display.c defs.h buffer.h



cc -c
display.c



insert.o :
insert.c defs.h buffer.h



cc -c
insert.c



search.o :
search.c defs.h buffer.h



cc -c
search.c



files.o :
files.c defs.h buffer.h command.h



cc -c
files.c



utils.o :
utils.c defs.h



cc -c
utils.c



clean :


rm edit
main.o kbd.o command.o display.o /



insert.o
search.o files.o utils.o


1.

反斜线之后不能有空格(这也是大家最容易犯的错误,错误比较隐蔽)

2.

所有的命令行必需以

[Tab]


字符开始,但并不是所有的以

[Tab]
键出现行都是命令行。但
make
程序会把出现在第一条规则之后的所有以
[Tab]
字符开始的行都作为命令行来处理

3.

Makefile
中把那些没有任何依赖只有执行动作的目标称为“伪目标”(
phony
targets


4.Make工作过程

    对于一个
Makefile
文件,“
make
”首先解析终极目标所在的规则,根据其依赖文件,
依次(按照依赖文件列表从左到右的顺序)寻找创建这些依赖文件的规则。首先为第一个依赖文件
寻找创建规则,如果第一个依赖文件依赖于其它文件
,则同样为这个依赖文件寻找创建规则
……,直到为所有的依赖文件找到合适的创建规则。之后
make
从最后一个规则
回退开始执行,最终完成终极目标的第一个依赖文件的创建和更新。之后对第二个、第三个、第四个……终极目标的依赖文件执行同样的过程

5.变量


objects =
main.o kbd.o command.o display.o /



insert.o
search.o files.o utils.o



edit :
$(objects)



cc -o edit
$(objects)



…….


…….


clean :


rm edit
$(objects)


6.make的隐含规则

    在使用
make
编译
.c
源文件时,编译
.c
源文件规则的命令可以不用明确给出。这是因为
make
本身存在一个默认的规则,能够自动完成对
.c
文件的编译并生成对应的
.o
文件。它执行命令“
cc
-c

”来编译
.c
源文件。在
Makefile
中我们只需要给出需要重建的目标文件名(一个
.o
文件),
make
会自动为这个
.o
文件寻找合适的依赖文件(对应的
.c
文件。对应是指:文件名除后缀外,其余都相同的两个文件),而且使用正确的命令来重建这个目标文件。

    书写规则建议的方式是:单目标,多依赖。就是说尽量要做到一个规则中只存在一个目标文件,可有多个依赖文件。尽量避免多目标,单依赖的方式。

 

7.清理过程文件


在实际应用时,我们把这个规则写成如下稍微复杂一些的样子。以防止出现始料未及的情况。


.PHONY :
clean



clean :


-rm edit
$(objects)



 


这两个实现有两点不同:


1.


通过“

.PHONY
”特殊目标将“
clean
”目标声明为伪目标。避免当磁盘上存在一个名为“
clean
”文件时,目标“
clean
”所在规则的命令无法执行(因为clean文件无依赖文件,其始终是最新的)。
2.


在命令行之前使用“

-
”,意思是忽略命令“
rm
”的执行错误。

抱歉!评论已关闭.