linux程序设计——多个源文件的问题,makefile的语法(第九章)

第九章 开发工具

本章介绍一些linux系统中的程序开发工具,其中一些工具也可以在UNIX系统中使用.linux系统除提供开发人员必须的编译器和调试器外,还提供一组工具,其中每个都可以完成一件独立的任务,并且允许开发人员将它们创造性地组合在一起,而这种组合能力也是linux从UNIX的哲学体系中继承而来的.

9.1 多个源文件带来的问题

在编写小程序时,许多人都会在编辑完源文件后重新编译所有文件来重组应用程序.但是对大型程序来说,使用这种简单的处理方式会带来一些很明显的问题.编辑--编译--测试这一循环的周期将变长.如果仅改动了一个源文件,可能需要重新编译所有的源文件.
如果在程序中创建了多个头文件,并在不同的源文件中包含它们,这种处理方式会带来一个潜在的,更严重的问题.比如说,有3个头文件a.h,b.h,c.h,3个C源文件main.c,2.c和3.c,具体情况如下所示:
/* main.c */
#include "a.h"
...
/* 2.c */
#include "a.h"
#include "b.h"
...
/* 3.c */
#include "b.h"
#include "c.h"
...
如果程序员只修改了头文件c.h,则源文件main.c和2.c无需重新编译,因为它们并不依赖于这个头文件,而对于源文件3.c来说,因为它包含了头文件c.h,所以在头文件c.h改动后,就必须编译它.如果忘记重新编译,则最终的程序很可能无法正常工作的.
make工具可以解决这个问题,它会在必要时重新编译所有受影响的源文件.
make命令不仅用于编译程序,无论何时,当需要通过多个输入文件来生成输出文件时,可以利用它来完成任务,它的其他用法还包括文档处理(例如针对troff或者TeX文档)

9.2 make命令和makefile文件

虽然make命令内置了很多智能机制,但是光凭自身是无法了解如何建立应用程序的.必须为其提供一个文件,告诉它应用程序应该如何构造,这个文件称为makefile.
makefile文件一般都会和项目的其他源文件放在同一目录下.事实上,如果管理的是一个大项目,可以用多个不同的makefile文件来分别管理项目的不同部分.
make命令和makefile文件的结合提供了一个在项目管理领域非常强大的工具.它不仅常被用于控制源代码的编译,而且还用于手册页的编写以及将应用程序安装到目标目录.

9.2.1 makefile的语法

makefile文件由一组依赖关系和规则构成.每个依赖关系由一个目标(即要创建的文件)和一组该目标所依赖的源文件组成.而规则描述了如何通过这些依赖文件创建目标.一般来说,目标是一个单独的可执行文件.
make命令会读取makefile文件的内容,它先确定目标文件或要创建的文件,然后比较目标所依赖的源文件的日期和时间以决定该采用哪条规则来构造目标.通常在创建最终的目标文件之前,它需要先创建一些中间目标.make命令会根据makefile文件来确定目标文件的创建顺序以及正确规则调用顺序.

9.2.2 make命令的选项和参数

make程序本身有许多选项,其中 最常用的3个选项如下所示:
-k:它的作用是让make命令在发现错误时仍然继续执行,而不是在检测到第一个错误时就停下来.可以利用这个选项 在一次操作中发现所有未编译成功的源文件.(如下图所示)
-n:它的作用是让make命令输出将要执行的操作步骤,而不是真正执行这些操作.
-f :它的作用是告诉make命令将哪个文件作为makefile文件.如果未使用这个选项,标准版本的make命令将首先在当前目录下查找名为makefile的文件.如果该文件不存在,它就会查找名为Makefile的文件.按照惯例许多linux程序员使用文件名Makefile,因为如果一个目录下都是以小写字母为名称的文件,则Makefile文件将在目录的文件列表中第一个出现.

linux程序设计——多个源文件的问题,makefile的语法(第九章)_第1张图片

为了指示make命令创建一个特定的目标(通常是可执行文件),可以把该目标的名字作为make命令的一个参数.

1.依赖关系

依赖关系定义了最终应用程序里的每个文件与源文件之间的关系.可以把之前的依赖关系定义为最终应用程序依赖于文件main.o,2.o和3.o,同样main.o依赖于main.c和a.h,2.o依赖于2.c,a.h,b.h,3.o依赖于3.c,b.h,c.h.因此,main.o受文件main.c和a.h修改的影响,如果这两个文件有所变化,就需要重新编译main.c来重建main.o.
在makefile文件中,这些规则的写法是:先写目标的名称,然后紧跟一个冒号,接着是空格或者制表符tab,最后用空格或者制表符tab隔开的文件列表.如下所示:
myapp: main.o 2.o 3.o
main.o: main.c 2.h
2.o: 2.c a.h b.h
3.o: 3.c b.h c.h
这组依赖关系形成了一个层次结构,它显示了源文件之间的关系.
如果想一次创建多个文件,可以利用伪目标all.假设应用程序由二进制文件myapp和使用手册myapp.1组成.可以用下面的这行语句进行定义:
all: myapp myapp.1
再次强调, 如果未指定一个all目标,则make命令将只创建它在文件makefile中找到的第一个目标.

2.规则

makefile文件的第二部分内容是规则, 规则定义了目标的创建方式.如之前所述,当make命令确定需要重建2.o时,它具体应该使用哪条命令呢?看上去只需要使用gcc 2.c -c即可(make命令内置了很多默认规则),但如果需要指定头文件目录,或者为了今后的调试需要设置符号信息选项应该怎样做的?这就需要在makefile文件>中明确定义一些规则.
注意:makefile文件中空格和制表符是有区别的.规则所在行必须以制表符tab开头,而用空格是不行的.由于连续几个空格和一个制表符tab看上去很类似,而且几乎在linux编程的所有领域中,空格和制表符tab之间几乎没有差别,所以这样的语法规定会带来问题(如make出现遗漏分隔符错误).此外,如果makefile文件中的某行以空格结尾,它也可能导致make命令执行失败.但这些都是历史遗留问题,而且因为已有太多的makefile文件存在,企图将其全部改正是不现实的,所以需要小心编写makefile文件.
创建一个简单的makefile1文件                                                                                                                 
编写之后,在 调用make命令时加上-f选项,这是因为makefile文件并未使用常见的默认文件名makefile或者Makefile(而是使用Makefile1).如下所示:
make -f Makefile1
make命令假设在makefile文件中的第一个目标myapp是想创建的目标文件.然后它会检查其他的依赖关系,并确定需要有一个名为main.c的文件.如果并未创建该文件,makefile文件里并未说明如何创建该文件,则make命令报告一个错误.
                                                                  
 

你可能感兴趣的:(C,linux,linux程序设计)