1、第四章 Linux平台上的软件开发,本章概要程序开发过程代码生成工具多模块软件的编译和链接源代码调试库的开发、调试和使用RCS和CVS的版本控制,2019年7月21日星期日,2,.1 程序开发过程,.1.1 计算机编程语言概述,.1.2 C、C+和Java程序的编译,.1.3 Linux下C编程常识,2019年7月21日星期日,3,通常的Linux/UNIX系统都会支持几种解释型和编译型的高级编程语言。包括C、C+、JAVA、Perl、LISP和FORTRAN。 多数的Linux/UNIX平台下的应用软件是用C语言写的,Linux/UNIX操作系统也是用C写的 。该平台下C语言开发工具比较多。
2、,4.1.1 计算机编程语言概述,2019年7月21日星期日,4,编程语言和编程范式,编程语言 命令型 使用变量,赋值语句,迭代重复等; C、C+、Java、Basic、COBOL、FORTRAN等。 函数/应用型 没有变量、赋值语句,迭代的概念; 运算是将参数传递到函数中完成; LISP、ML、Haskell、Scheme等。,2019年7月21日星期日,5,编程语言和编程范式,逻辑型 通过指定规则,并让语言执行这些规则而完成运算; 最流行的逻辑编程语言是Prolog。 面向对象型 提供对抽象数据类型的支持,即类。 运算是通过对类进行实例化(即产生对象)和对象间的通信产生方法调用来实现。 S
3、malltalk80、Eiffel、Java、C+等。,2019年7月21日星期日,6,编程范式,面向过程 面向对象,2019年7月21日星期日,7,编译过程,图 高级语言转换为可执行代码的过程,高级语言源代码,编译程序,汇编代码,汇编程序,目标代码,链接程序,可执行代码,其他目标模块,库模块,2019年7月21日星期日,8,解释过程,高级语言源代码,解释程序,2019年7月21日星期日,9,4.1.2 C、C+程序的编译,C和C+程序转换为可执行代码的过程,C/C+语言源代码,C/C+ 编译程序,汇编代码,汇编程序,目标代码,链接程序,可执行代码,其他目标模块,库模块,预处理 程序,2019
4、年7月21日星期日,10,预处理程序的工作,插入用#include指令指定的文件; 扩展宏(由#define指令所指定); 处理用#if指令指定的条件编译; 处理连续行连接(只限C)。,2019年7月21日星期日,11,4.1.3 Linux下C编程常识,标准 函数库和系统调用 C语言编程风格 库和头文件的保存位置,2019年7月21日星期日,12,1. 标准,ANSI C:是 ANSI(美国国家标准局)于 1989 年制定的 C 语言标准。 后来被ISO(国际标准化组织)接受为标准,因此也称为 ISO C。 ANSI C 不仅定义了 C 编程语言的语法和语义,而且还定义了一个标准库。,201
5、9年7月21日星期日,13,标准库,这个库可以根据头文件划分为 15 个部分,其中包括: 字符类型 () 错误码 () 浮点常数 () 数学常数 () 标准定义 () 标准 I/O () 工具函数 (),字符串操作 () 时间和日期 ()可变参数表 ()信号 () 非局部跳转 ()本地信息 ()程序断言 () 等等。,2019年7月21日星期日,14,POSIX:该标准最初由 IEEE 开发的标准族,部分已经被 ISO 接受为国际标准。该标准的具体内容 见 1.1.3。POSIX.1 和 POSIX.2 分别定义了 POSIX 兼容操作系统的 C 语言系统接口 以及 shell 和工具标准。这
6、两个标准是通常提到的标准。 SVID:System V 的接口描述。System V 接口描述(SVID)是描述 ATT Unix System V 操作 系统的文档,是对 POSIX 标准的扩展超集。 XPG:X/Open 可移植性指南。X/Open 可移植性指南(由 X/Open Company, Ltd.出版), 是比 POSIX 更为一般的标准。X/Open 拥有 Unix 的版权,而 XPG 则指定成为 Unix 操作系统必须满足的要求。,2019年7月21日星期日,15,2 函数库和系统调用,1)glibc GNU 的 C 函数库,即 glibc,是 Linux 上最重要的函数库,
7、它定义了 ISO C 标准指定的所有的库函数,以及由 POSIX 或其他 UNIX 操作系统统变种指定的附加特色,还包括有与 GNU 系统相关的扩展。目前,流行的 Linux 系统使用 glibc 2.0 以上的版本。 2)其他重要函数库GNU Libtool 、CrackLib 、LibGTop 、 libungif、libtiff、libpng、Imlib 等,2019年7月21日星期日,16,3)系统调用 系统调用是操作系统提供给外部程序的接口。 在 C 语言中,操作系统的系统调用通常通过函数调用的形式完成,这是因为这些函数封装了系统调用的细节,将系统调用的入口、参数以及返回值用 C 语
8、言的函数调用过程实现。 在 Linux 系统中,系统调用函数定义在 glibc 中。,2019年7月21日星期日,17,3 C 语言编程风格K&R缩排风格,在 Linux 内核的源代码中,可以看到 Linux 内核源代码的编码风格说明 (/ Documentation/CodingStyle)。 Linus 为 Linux 内核定义的 C 语言编码风格要点如下: 缩进时,使用长度为 8 个字符宽的 Tab 键。如果程序的缩进超过3级,则应考虑重新设计程序。 大括号的位置。除函数的定义体外,应当将左大括号放在行尾,而将右大括号放在行首。函数的定义体应将左右大括号放在行首。,2019年7月21日星
9、期日,18,应采用简洁的命名方法。对变量名,不赞成使用大小写混写的形式,但鼓励使用描述性的名称;尽可能不使用全局变量;不采用匈牙利命名法表示变量的类型;采用短小精悍的名称表示局部变量;保持函数短小,从而避免使用过多的局部变量。 保持函数短小精悍。 不应过分强调注释的作用,应尽量采用好的编码风格而不是添加过多的注释。,2019年7月21日星期日,19,缩排风格命令,indent选项输入文件 indent选项单个输入文件-o 输出文件 默认的情况下, indent命令按照GNU格式化缩排风格格式化一个程序,并保留用户的所有换行符。,2019年7月21日星期日,20,4 库和头文件的保存位置,1)
10、函数库 /lib:系统必备共享库 /usr/lib:标准共享库和静态库 /usr/i486-linux-libc5/lib:libc5 兼容性函数库 /usr/X11R6/lib:X11R6 的函数库 /usr/local/lib:本地函数库 2) 头文件 /usr/include:系统头文件 /usr/local/include:本地头文件,2019年7月21日星期日,21,3)共享库及其相关配置 /etc/ld.so.conf:包含共享库的搜索位置 ldconfig:共享库管理工具,一般在更新了共享库之后要运行该命令 ldd:可查看可执行文件所使用的共享库,2019年7月21日星期日,22
11、,4.2 代码生成工具C/C+编译程序,2019年7月21日星期日,23,程序开发过程,程序开发过程包括三个阶段:代码生成、静态分析和动态分析。 代码生成阶段:创建源代码、生成源代码的可执行码。 工具:编辑工具、排版工具、编译器、基于模块软件的编译、库创建工具、源代码管理工具、修订控制工具等。,2019年7月21日星期日,24,程序开发过程,静态分析阶段:包括源代码的可移植性、源代码标准测试的验证(如源代码的结构、源代码的大小(以行计算)、功能点的数量等)。 动态分析阶段:包括软件性能的调试、跟踪、测试和监视,根据产品需求进行测试等。,2019年7月21日星期日,25,任何文本编辑器都可以用作
12、创建程序源代码。常用的Linux/UNIX编辑器有: Vi emacs xemacs pico 等。,生成程序源文件,2019年7月21日星期日,26,随 Linux 发行的 GNU C 编译器(GCC)是一个全功能的 ANSI C 兼容编译器。 本节将介绍如何使用 GCC 和一些 GCC 编译器最常用的选项。,C/C+编译程序GCC,2019年7月21日星期日,27,1使用 GCC,通常后跟一些选项和文件名来使用 GCC 编译器. gcc 命令的基本用法如下:gcc option | filename . g+ option | filename . 命令行选项指定的操作将在命令行上每个给出
13、的文件上执行。,2019年7月21日星期日,28,编译器的功能,C 与 C+ 的 compiler 将产生新程序的相关程序整合起来。 产生一个新的程序需要经过四个阶段:预处理、编译、汇编、链接。 这两个编译器都能将输入的文件做不同阶段的处理。,2019年7月21日星期日,29,编译器的功能,gcc 预设经由预处理过(扩展名为.i)的文件为 C 语言,并于程序链接阶段以 C 的链接方式处理。 g+ 预设经由预处理过(扩展名为.ii)的文件为 C+ 语言,并于程序链接阶段以 C+ 的链接方式处理。,2019年7月21日星期日,30,扩展名的含义,原始程序码的扩展名指出所用编写程序所用的语言,以及相
14、对应的处理方法: .c C 原始程序 ; 预处理、编译、汇编 .C C+ 原始程序 ; 预处理、编译、汇编 .cc C+ 原始程序 ; 预处理、编译、汇编 .cxx C+ 原始程序 ; 预处理、编译、汇编 .m Objective-C 原始程序 ; 预处理、编译、汇编 .i 已经过预处理之 C 原始程序 ; 编译、汇编 .ii 已经过预处理之 C+ 原始程序 ; 编译、汇编 .s 组合语言原始程序 ; 汇编 .S 组合语言原始程序 ; 预处理、汇编 .h 预处理文件(标头文件) ; (不常出现在指令行),2019年7月21日星期日,31,连接程序,其他扩展名的文件是由链接程序来处理,通常有:
15、.o Object file .a Archive file 在链接阶段,所有与原始码相对应的.o 文件、程序库、和其他无法自文件名辨明属性的文件(包括不以 .o为扩展名的 object file 以及扩展名为 .a 的 archive file)都会交由链接程序来处理(在指令行将那些文件当作链接程序的参数传给链接程序)。,2019年7月21日星期日,32,2GCC 选项,很多的 GCC 选项包括一个以上的字符。 因此必须为每个选项指定各自的连字符。例如, 下面的两个命令是不同的: gcc -p -g test.c gcc -pg test.c,2019年7月21日星期日,33,gcc tes
16、t.c 当不用任何选项编译一个程序时, GCC 将会建立(假定编译成功)一个名为 a.out 的可执行文件. 用 -o 编译选项来为将产生的可执行文件指定一个文件名来代替 a.out. gcc -o count count.c,当使用-o选项时, -o后面必须跟一个文件名,2019年7月21日星期日,34,-c 选项: 仅把源代码编译为目标代码而跳过汇编和连接的步骤. 缺省时 GCC 建立的目标代码文件有一个 .o 的扩展名. -S 选项: 为 C 代码产生了汇编语言文件后停止编译. GCC 产生的汇编语言文件的缺省扩展名是 .s . -E 选项: 指示编译器仅对输入文件进行预处理. 当这个选
17、项被使用时, 预处理器的输出被送到标准输出而不是储存在文件里.,2019年7月21日星期日,35,3优化选项,-O 选项: 对源代码进行基本优化. 这些优化在大多数情况下都会使程序执行的更快. -O2选项: 产生尽可能小和尽可能快的代码. -O2 选项将使编译的速度比使用 -O 时慢. 但通常产生的代码执行速度会更快. 除了-O和-O2 优化选项外, 还有一些低级选项用于产生更快的代码. 这些选项的详细描述, 请参考 GCC 的指南页, 在命令行上键入 man gcc .,2019年7月21日星期日,36,4调试和剖析选项,-g 选项: 产生能被 GNU 调试器使用的调试信息以便调试程序. -
18、pg 选项: 在程序里加入额外的代码, 执行时, 产生 gprof 用的剖析信息以显示该程序的耗时情况.,2019年7月21日星期日,37,表 gcc 命令的常用选项,-ansi 只支持ANSI标准的C语法。这一选项将禁止GNUC的某些特色,例如asm或typeof关键词。 -c 只编译并生成目标文件。 -E 只运行C预编译器。 -O0 不进行优化处理。,2019年7月21日星期日,38,-O或-O1 优化生成代码。 -O2 进一步优化。 -O3 比-O2更进一步优化,包括inline函数。 -shared 生成共享目标文件。通常用在建立共享库时。 -static 禁止使用共享连接。 -UMA
19、CRO 取消对MACRO宏的定义。 -w 不生成任何警告信息。 -Wall 生成所有警告信息。,2019年7月21日星期日,39,#DEMO#: hello.c,例如,假设有两个源文件 main.c 和 factorial.c ,现在要编译生成一个计算阶乘的程序。 /清单 factorial.c #include #include int factorial (int n) if (n = 1)return 1;elsereturn factorial (n - 1) * n; ,2019年7月21日星期日,40,/清单 main.c #include #include int factori
20、al (int n); int main (int argc, char *argv) int n;if (argc 2) printf (“Usage: %s nn“, argv 0);return -1;else n = atoi (argv1);printf (“Factorial of %d is %d.n“, n, factorial (n); return 0; ,2019年7月21日星期日,41,利用如下的命令可编译生成可执行文件,并执行程序: $ gcc -o factorial main.c factorial.c $ ./factorial 5 Factorial of 5
21、 is 120.,2019年7月21日星期日,42,GCC 可同时用来编译 C 程序和 C+ 程序。 一般来说,C 编译器通过源文件的后缀名来判断是 C 程序还是 C+ 程序。 在 Linux 中,C 源文件的后缀名为 .c,而 C+ 源文件的后缀名为 .C 或 .cc 或.cxx。 但是,gcc 命令只能编译 C+ 源文件,而不能自动和 C+ 程序使用的库连接。因此,通常使用 g+ 命令来完完成 C+ 程序的编译和连接,该程序会自动调用 gcc 实现编译。,gcc与g+,2019年7月21日星期日,43,g+命令,假设我们有一个如下的 C+ 源文件(hello.C): #include vo
22、id main (void) cout “Hello, world!“ endl; 则可以如下调用 g+ 命令编译、连接并生成可执行文件:$ g+ -o hello hello.C $ ./hello Hello, world!,2019年7月21日星期日,44,4.3 多模块软件的编译和链接,2019年7月21日星期日,45,1 Makefile 的作用原理,假设我们有下面这样的一个程序,该程序由三个模块main.c 、mytool1.c和 mytool2.c组成。 在Linux中,我们可以使用下面的命令来编译整个程序: gcc -Wall -o myprogram main.c mytoo
23、l1.c mytool2.c,2019年7月21日星期日,46,/* main.c */ #include “mytool1.h“ #include “mytool2.h“ int main(int argc,char *argv) mytool1_print(“hello“); mytool2_print(“hello“); /* mytool1.h */ #ifndef _MYTOOL_1_H #define _MYTOOL_1_H void mytool1_print(char *print_str); #endif,2019年7月21日星期日,47,/* mytool1.c */ #i
24、nclude “mytool1.h“ void mytool1_print(char *print_str) printf(“This is mytool1 print %s “,print_str); /* mytool2.h */ #ifndef _MYTOOL_2_H #define _MYTOOL_2_H void mytool2_print(char *print_str); #endif /* mytool2.c */ #include “mytool2.h“ void mytool2_print(char *print_str) printf(“This is mytool2 p
25、rint %s “,print_str); ,2019年7月21日星期日,48,编译,由于这个程序很短,我们也可以这样来编译: gcc -c main.c gcc -c mytool1.c gcc -c mytool2.c gcc -o main main.o mytool1.o mytool2.o 如果在mytool1.c文件中改变了一些代码,不需要重新编译main.c 和mytool2.c,只需要重新编译mytool1.c ,并且重新链接: gcc -wall -c mytool1.o mytool1.c gcc -o myprogram main.o mytool1.o mytool2.
26、o,2019年7月21日星期日,49,复杂的情况,但是当事情更复杂一点,如果程序有几百个源程序的时候,难道也要编译器重新一个一个的去编译? 为此,聪明的程序员们想出了一个很好的工具来做这件事情,这就是make。 只要执行一下make,就可以把上面的问题解决掉。 在执行make之前,要先编写一个非常重要的文件Makefile。,2019年7月21日星期日,50,在大型的开发项目中,通常有几十到上百个的源文件,如果每次均手工键入 gcc 命令进行编译的话,则会非常不方便。因此,人们通常利用 make 工具来自动完成编译工作。 这些工作包括:如果仅修改了某几个源文件,则只重新编译这几个源文件;如果某
27、个头文件被修改了,则重新编译所有包含该头文件的源文件。 利用这种自动编译可大大简化开发工作,避免不必要的重新编译。,使用GNU Make,2019年7月21日星期日,51,make,make是一个命令工具,是一个解释makefile中指令的命令工具。 一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C+的nmake,Linux下GNU的make。,2019年7月21日星期日,52,Linux提供了make命令和makefile文件的方式来维护目标程序。Make命令会按照makefile文件中描述的模块依赖关系,根据模块的修改情况重新编译链接目标代码,实现维护工
28、作的自动化。,2019年7月21日星期日,53,makefile 需要按照某种语法进行编写,其中说明了如何编译各个源文件并连接生成可执行文件,并定义了源文件之间的依赖关系。 当修改了其中某个源文件时,如果其他源文件依赖于该文件,则也要重新编译所有依赖该文件的源文件。,2019年7月21日星期日,54,makefile 文件是许多编译器,包括 Windows NT 下的编译器维护编译信息的常用方法,只是在集成开发环境中,用户通过友好的界面修改 makefile 文件而已。 默认情况下,GNU make 工具在当前工作目录中按如下顺序搜索 makefile: GNUmakefile makefil
29、e Makefile,make命令找到了就解释这个文件. 在这三个文件名中,最好使用“Makefile”这个文件名,因为,这个文件名第一个字符为大写,这样有一种显目的感觉。最好不要用“GNUmakefile”,这个文件是GNU的make识别的。有另外一些make只对全小写的 “makefile”文件名敏感,但是基本上来说,大多数的make都支持“makefile”和“Makefile”这两种默认文件名。,2019年7月21日星期日,55,程序编译的一些规范和方法,一般来说,无论是C、C+、还是pas,首先要把源文件编译成中间代码文件,在Windows下也就是 .obj 文件,UNIX下是 .o
30、 文件,即 Object File,这个动作叫做编译(compile)。然后再把大量的Object File合成执行文件,这个动作叫作链接(link)。,2019年7月21日星期日,56,编译,编译器需要的是语法的正确,函数与变量的声明的正确。 对于后者,通常是需要告诉编译器头文件的所在位置(头文件中应该只是声明,而定义应该放在C/C+文件中),只要所有的语法正确,编译器就可以编译出中间目标文件。 一般来说,每个源文件都应该对应于一个中间目标文件(O文件或是OBJ文件)。,2019年7月21日星期日,57,链接,主要是链接函数和全局变量。可以使用这些中间目标文件(O文件或是OBJ文件)来链接应
31、用程序。 链接器并不管函数所在的源文件,只管函数的中间目标文件(Object File),在大多数时候,由于源文件太多,编译生成的中间目标文件太多,而在链接时需要明显地指出中间目标文件名,这对于编译很不方便,所以,要给中间目标文件打个包。 在Windows下这种包叫“库文件”(Library File),也就是 .lib 文件,在UNIX下,是Archive File,也就是 .a 文件。,2019年7月21日星期日,58,小结,源文件首先会生成中间目标文件,再由中间目标文件生成执行文件。 在编译时,编译器只检测程序语法,和函数、变量是否被声明。如果函数未被声明,编译器会给出一个警告,但可以生
32、成Object File。 在链接程序时,链接器会在所有的Object File中找寻函数的实现,如果找不到,那到就会报链接错误码(Linker Error),在VC下,这种错误一般是:Link 2001错误,意思说是说,链接器未能找到函数的实现。你需要指定函数的Object File.,2019年7月21日星期日,59,简单的makefile文件,这是上面那个程序的Makefile文件: main:main.o mytool1.o mytool2.o gcc -o main main.o mytool1.o mytool2.o main.o:main.c mytool1.h mytool2.
33、h gcc -c main.c mytool1.o:mytool1.c mytool1.h gcc -c mytool1.c mytool2.o:mytool2.c mytool2.h gcc -c mytool2.c,有了这个Makefile文件,不论什么时候修改了源程序当中的什么文件,只要执行make命令,编译器都只会去编译和修改文件有关的文件,其它的文件它连理都不去理。,2019年7月21日星期日,60,在Makefile中以#开始的行都是注释行; Makefile中最重要的是描述文件的依赖关系的说明。一般的格式是: target:components TAB rule 第一行表示的是依
34、赖关系。第二行是规则。 比如说上面的那个Makefile文件的第二行。 main:main.o mytool1.o mytool2.o 表示目标(target)main的依赖对象(components)是main.o mytool1.omytool2.o 当依赖的对象在目标修改后修改的话,就要去执行规则一行所指定的命令。就象上面那个Makefile第三行所说的一样要执行 gcc-o main main.o mytool1.o mytool2.o 注意规则一行中的TAB表示那里是一个TAB键,make并不管命令是怎么工作的,只管执行所定义的命令。make会比较target文件和component
35、s文件的修改日期,如果components文件的日期要比target文件的日期要新,或者target不存在的话,那么,make就会执行后续定义的命令。,2019年7月21日星期日,61,三个变量,Makefile有三个非常有用的变量。分别是$,$,$。它们代表的意义分别是: $ 目标文件$ 所有的依赖文件$ 依赖列表中的第 一个依赖文件如果使用上面三个变量,那么可以简化Makefile文件为:,2019年7月21日星期日,62,简化后的Makefile,main:main.o mytool1.o mytool2.o gcc -o $ $ main.o:main.c mytool1.h myto
36、ol2.h gcc -c $ mytool1.o:mytool1.c mytool1.h gcc -c $ mytool2.o:mytool2.c mytool2.h gcc -c $,$ 目标文件 $ 所有的依赖文件 $ 依赖列表中的第 一个依赖文件,2019年7月21日星期日,63,Makefile的缺省规则,.c.o: gcc -c $ 这个规则表示所有的 .o文件都是依赖于相应的.c文件的。例如mytool.o依赖于mytool.c,这样Makefile还可以变为:,$ 目标文件 $ 所有的依赖文件 $ 依赖列表中的第 一个依赖文件,2019年7月21日星期日,64,再一次简化后的Ma
37、kefile,main:main.o mytool1.o mytool2.o gcc -o $ $ .c.o: gcc -c $,$ 目标文件 $ 所有的依赖文件 $ 依赖列表中的第 一个依赖文件,2019年7月21日星期日,65,2 makefile文件的基本语句,makefile文件有如下五种基本语句。 注释语句(Comments) 注释语句是不会真正执行的,它只起注释语句的作用。它的作用范围是从“#”开始,到该行结束为止。 宏(Macros) 一般按如下方式定义宏:NAME=data 在它后面语句中,若出现(NAME),则都被data替代, 如: SRC =main.mgcc(SRC)被
38、解释为main.mgcc。,2019年7月21日星期日,66,默认的宏,AR=ar GET=get MAS=mas AS=as FC=f77 CC=cc LD=ld LEX=lex SHELL=/bin/sh MAKEFLAGS=b 用命令make p可以列出所有默认的宏定义。,2019年7月21日星期日,67,特殊的宏,在Linux中,有几个特殊的宏定义: :扩展成依靠列表中的第一个依靠文件; :代表目标文件名,即写入输出的文件名; * :代表不包含后缀字符串的输入文件名; ? :代表比目标文件更晚的依赖文件名; % :比库文件更晚的库成员文件。$ :所有的依赖文件,2019年7月21日星期
39、日,68,显式规则(Explicit Rules),显式规则具体列出了目标文件的依赖文件以及作用于其上的命令。 其基本格式如下:目标文件:依赖文件 命令 (注意,每个命令前使用Tab键缩进一次) 例: main:main.m list.hgcc o main.m list.h,2019年7月21日星期日,69,隐含规则(Implicit Rules),隐含规则跟显式规则很类似,不过它没有具体列出作用于依赖文件的命令,而是根据目标文件的后缀来决定执行什么样的命令。 如:test.o:test.c io.h 根据这条规则,make会执行 $(CC)$(CFLAGS) c test.c io.h,2
40、019年7月21日星期日,70,类推规则(Inference Rules),情况一: 例 .c.o: gcc c $(CFLAGS)$ 该规则告诉make将.的输入文件编译成.的输出文件。输入文件和输出文件除后缀不同外,有相同的文件名。 情况二:比情况一更一般,它使用%来代表任何字符串, 例 %.:% gcc c o (CFLAGS) 所有原始文件的编译都可用这条语句来完成。,2019年7月21日星期日,71,3 如何创建makefile文件,可以用别人已写好的makefile文件为样本,根据自己的需要作小部分的修改就成了自已的makefile文件,有时甚至可以不作任何修改,完全照搬就行。 若
41、对makefile的语法理解得非常透彻,也可以自己写。 有集成的编译开发工具,由它来自动为开发者生成makefile文件。,2019年7月21日星期日,72,4 几点注意事项,宏的定义不一定用大写,但习惯用大写。 允许增加已经定义过的宏内容,只须用“:=”代替“=”, 例 DRIVERS=drivers/block/block.aIfdef CONFIGSCSIDRIVERS:=$(DRIVERS)dirvers/scsi/scsi.aEndif 在本例中,如果定义了CONFIGSCSI,则DRIVERS的完整定义是: drivers/block/block.adirvers/scsi/scsi.a,2019年7月21日星期日,73,任何shell命令都可以在makefile文件内执行。在命令行中,多句命令用“;”隔开或另起一行。 若宏定义或规则太长,可用“”把下一行作为这行的延续。 执行makefile文件中的命令时,遇到哪条命令执行失败,make终止执行。若在命令前加“-”,则该命令执行失败时make也可跳过这条命令继续执行下一条命令。,