在这一章,我们将会讨论在Linux系统上可用的程序开发工具,其中一些在Unix系统上也可用。除了必须的编译器与调试器以外,Linux提供了一个工具集,其中的每一个工具都完成单独的工作,并且允许开发者以新的方式对这些工具进行组合。这就是Linux所继承的Unix哲学的一部分。在这里,我们将会讨论其中的一些重要工具,并且会讨论使用这些工具解决问题的例子,包括:
make命令以及makefile
使用RCS与CVS进行源代码控制
编写手册页
使用patch与tar发布软件
开发环境
多源代码的问题
当我们编写小程序时,许多人都是简单的在编辑后通过重新编译所有的文件重新构建我们的程序。然而,对于大程序,这种简单构建方法的问题就变得明显了。编辑-编译-测试的循环时间将会变长。即使是最为耐心的程序员也会希望避免当只修改一个文件时而编译所有的文件。
当创建多个头文件并且在不同的源文件中包含多个头文件时就会出现一个更为困难的问题。假设我们有三个头文件a.h,b.h以及c.h,和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被修改了,那么他就应被重新编译。然而,如果b.h被修改了,而程序员忘记重新编译2.c,那么所得到的程序也许就不会正常工作。
make程序通过确保修改所影响的所有文件在需要时进行重新编译来解决所有这些问题。
make命令与Makefile
然而,正如我们所看到的,make命令有许多内建的知识,他本身并不知道如何构建我们的程序。我们必须提供一个文件来告诉make我们的程序是如何组织的。这个文件就是makefile。
makefile文件通常与工程的源文件位于同一个目录中。我们可以同时在我们机子上有多个不同的makefile文件。确实,如果我们有一个非常大的工程,我们也许会选择对于工程的不同部分使用单独的makefile文件进行管理。
make命令以及makefile文件的组合提供了一个强大的工具来进行工程的管理。他通常不仅用于控制源代码的编译,而且也用于准备手册页以及将程序安装到目标目录。
makefile文件的语法
一个makefile文件由一组依赖与规则组成。一个依赖具有一个目标(将要创建的文件)以及他所依赖的源文件集合。规则描述了由依赖文件如何创建目标文件。通常,目标文件是一个可执行文件。
makefile文件由make命令来执行,从而决定目标文件或是要创建的文件,然后比较源文件的日期与时间用于决定调用哪条规则来构建目标。通常,在构建最终的目标之前必须创建一些中间目标。make命令使用makefile文件来确定目标构建的正确顺序以及规则调用的正确顺序。
make选项与参数
make程序本身有多个选项。最常用的三个为:
-k,这个选项会通知make命令,当发现一个错误时会继续执行,而不是在检测到第一个问题时立即退出。例如,我们可以使用这个选项检测出哪个文件编译失败。
-n,这个选项会使得make命令打印出此命令将会做的事情而不会实际执行。
-f <filename>,这个选项会通知make命令使用哪个文件作为makefile文件。如果我们没有使用这个选项,make首先在会当前目录查找名为makefile的文件。如果这个文件不存在,他就会查找Makefile。按约定,Linux程序使用Makefile。这会使用makefile文件在一个满是小写字母名字的目录中第一个出现。
要告诉make来构建一个特定目录,通常是一个可执行文件,我们可以将目标名字作为参数传递给make命令。如果没有这样做,make就会试着构建makefile文件中的第一个目标。许多程序在其makefile文件中将all指定为第一个目标,然后列出其他的all所依赖的目标。这个约定可以很清晰的指出当没有指定目标时makefile应尝试构建的默认目标。我们建议遵守这个约定。
依赖
依赖指出最终程序中的每一个文件如何与源文件相关。在我们本章开始时所显示的例子中,我们指出我们最终的程序依赖于main.o,2.o以及3.o;类似的main.o依赖于main.c与a.h等。所以main.会受到main.c和a.h修改的影响,如果这两个文件中的任何一个发生变化,都需要通过重新编译main.c来重新创建main.o。
在makefile文件中,我们编写规则的格式如下:目标名,冒号,空格或是tab,然后是以空格或是tab分隔的用于创建目标文件的列表。我们例子中的依赖列表如下:
myapp: 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
这表明myapp依赖于main.o,2.o以及3.o,而main.o依赖于main.c以及a.h,等等。
依赖集合指出了一个层次显示了源文件之间如何彼此相关。我们可以很容易的看出,如果b.h发生变化,那么我们需要重新修正2.o以及3.o,而2.o与3.o发生了变化,我们也需要重新构建myapp。
如果我们希望编构建多个文件,那么我们可以使用伪目标all。假设我们的程序由二进制文件myapp与手册页myapp.1构成。我们可以用下面的语句来指定目标:
all: myapp myapp.1
再一次声明,如果我们没有指定all目标,make只是简单的创建他在makefile中查找到的第一个目标。
规则
makefile文件中的第二部分指定了用于描述如何创建一个目标的规则。在我们前面部分的例子中,在make命令之后应该使用哪个命令来重新构建2.o呢?看起来也许只是简单的使用gcc -c 2.c就足够了(而且,正如我们在后面将会看到的,make确实知道许多默认的规则),但是如果我们需要指定一个include目录,或是设置用于以后调试的符号信息选项时应怎么办呢?我们可以通过在makefile文件中显示的指定规则来做到。
注:在这里我们需要提示makefile文件一个非常奇怪的语法:一个空格与一个tab之间有区别。所有规则所在的行必须以一个tab开始;而不能以一个空格开始。因为多个空格与一个tab看起来很相似,而且因为在绝大多数的其他的Linux程序中在空格与tab之间并没有区别,所以如果不加区分就会出现问题。同时,makefile文件中一行结束处的空格也会使得make命令失败。然而,这是一个历史问题,而且已经有许多的makefile文件在尝试改进这个问题,所以我们要小心。幸运的是,当make命令不能工作时,通常一个很明显的问题就是丢失了tab。
试验--一个简单的Makefile
大多数规则由本可以在命令行输入的简单命令组成。对于我们的例子而言,我们可以创建我们的第一个makefile文件,Makefile1:
myapp: main.o 2.o 3.o
gcc -o myapp main.o 2.o 3.o
main.o: main.c a.h
gcc -c main.c
2.o: 2.c a.h b.h
gcc -c 2.c
3.o: 3.c b.h c.h
gcc -c 3.c
我们需要使用-f选项来调用我们的make命令,因为我们的makefile文件并不是通常默认的makefile或是Makefile。如果我们在一个并不包含任何源码的目录中调用这个代码,我们就会得到下面的信息:
$ make -f Makefile1
make: *** No rule to make target ‘main.c’, needed by ‘main.o’.
$
make命令认为makefile文件中的第一个目录myapp是我们希望创建的文件。然后他会查找其他的依赖,并且会确定需要一个名为main.c的文件。因为我们还没有创建这个文件,而makefile也并不知道如何创建这个文件,所以make命令就会报告错误。下面我们创建这些源文件并且再次尝试。因为我们对于结果并不感兴趣,所以这些文件可以非常简单。头文件实际上为空,所以我们使用touch命令来创建这些文件。
$ touch a.h
$ touch b.h
$ touch c.h
main.c包含main函数,并且会调用function_two与function_three。其他的两个文件定义了function_two与function_three。源文件包含#include行来指定头文件,所以他们会依赖所包含的头文件的内容。这并不是一个程序,但是我们在这里列出相应的部分:
/* main.c */
#include <stdlib.h>
#include “a.h”
extern void function_two();
extern void function_three();
int main()
{
function_two();
function_three();
exit (EXIT_SUCCESS);
}
/* 2.c */
#include “a.h”
#include “b.h”
void function_two() {
}
/* 3.c */
#include “b.h”
#include “c.h”
void function_three() {
}
下面我们再试一次:
$ make
gcc -c
gcc -c
gcc -c
gcc -o
$
这就是一次成功的make。
工作原理
make命令处理makefile文件中的依赖部分,并且确定需要创建的文件以及创建的顺序。尽管我们首先列出了如何创建myapp,make可以确定创建文件的正确顺序。然后他会调用我们在这些规则中所指定的创建这些文件的命令。make命令会在执行相应的命令时显示这些命令。现在我们可以测试我们的makefile文件来确定他是否正确的处理了b.h的修改。
$ touch b.h
$ make -f Makefile1
gcc -c 2.c
gcc -c 3.c
gcc -o myapp main.o 2.o 3.o
$
make命令已经读入我们的makefile文件,确定重新构建myapp所需要的最小数量的命令,并且以正确的顺序执行这些命令。下面我们来看一下如果我们删除一个目标文件时会发生什么:
$ rm 2.o
$ make -f Makefile1
gcc -c 2.c
gcc -o myapp main.o 2.o 3.o
$
再一次,make正确的确定了所需要的动作。
分享到:
相关推荐
斯凯开发工具是一款专为MTK(MediaTek)平台设计的软件开发套件,用于MRP(Mobile RunTime Package)应用程序的开发。MRP是一种基于Java的轻量级应用程序格式,广泛应用于早期的智能手机和一些非主流品牌手机,尤其...
微信小程序云开发工具包。借此工具包,你将无需投入服务器、无需接口编程、无需开发后台,将传统开发小程序效率提升百倍微信小程序云开发工具包。借此工具包,你将无需投入服务器、无需接口编程、无需开发后台,将...
【标题】"NES游戏开发工具 NES游戏编程 NES游戏教程"涉及的是8位家用游戏机——Nintendo Entertainment System(NES)的游戏制作技术。NES是1980年代末至1990年代初流行的家用游戏机,它承载了一代人的游戏记忆。这...
"开发工具开发工具开发工具开发工具"这个标题暗示了我们将深入探讨各类开发工具的功能、重要性以及如何选择和使用它们。 描述中的重复性表明了开发工具对于开发者的重要性,因为它们涵盖了编码、调试、版本控制、...
IM安卓开发工具箱imakit是一款专为Android开发者设计的强大工具,尤其在制作和管理刷机包方面具有显著优势。最新版本imakit 9.13带来了更多改进和新功能,进一步提升了开发者的效率和体验。 首先,imakit的核心功能...
组态王图库开发工具是一种专门用于创建和定制工控软件界面的专业软件,它为用户提供了自定义图形界面的能力,使工业自动化应用的可视化设计更加灵活、个性化。在这个“kv图库开发包”中,我们可以预见到包含了一系列...
超简单AIoT物联网与网站假设必学神器:Node-RED视觉化开发工具配套示例代码 超简单AIoT物联网与网站假设必学神器:Node-RED视觉化开发工具配套示例代码 超简单AIoT物联网与网站假设必学神器:Node-RED视觉化开发工具...
微信小程序开发工具是一款专为微信小程序开发者设计的强大平台,它集成了代码编辑、预览、调试和发布等一系列功能,使得开发者能够高效地构建和管理微信小程序应用。在本压缩包中,有两个主要文件:更新日志.txt 和 ...
本资源包“C#开发工具”似乎是一个针对C#初学者的入门套件,包含了必要的文件以帮助开始C#编程之旅。以下是对这些文件的详细解读: 1. **File_id.diz**:这是一个传统的文件标识符,通常包含软件的作者、版本和其他...
开发驱动程序是一项技术性极强的工作,需要用到专业的开发工具。以下是一些常用的驱动开发工具的详细介绍: 1. VXDWriter:VXD(Virtual Device Drivers)是Windows 9x系统中的驱动程序格式。VXDWriter是一款专门...
一种自动生成asp代码的工具(asp开发工具),可用来生成常见的asp添加、删除,修改,查询代码,也可以生成asp类的添加、删除,修改,查询代码,是asp开发人员的超强助手,能迅速生成相应的asp代码,提高写asp代码的...
VBS脚本开发工具是专为编写、调试和优化VBS脚本而设计的软件或平台,它们通常提供代码编辑器、调试器和语法高亮等特性,以提高开发效率和代码质量。 在提供的文件列表中,我们看到几个关键资源: 1. "Microsoft ...
U8二次开发工具包···一些控件调用说明·U8二次开发工具包···一些控件调用说明·
《Linux开发工具箱:项目开发的最有效途径》将系统性地介绍GNU/Linux的开源工具,并通过可以被读者容易修改的简明示例说明如何使用这些工具,以满足读者的实际需求。《Linux开发工具箱:项目开发的最有效途径》首先...
在软件开发过程中,选择合适的开发工具至关重要,而开发语言判断器就是这样一个工具,它能够帮助开发者确定特定软件或代码片段是用哪种编程语言编写的。本文将深入探讨开发语言判断器的功能、工作原理以及在软件开发...
U8快速开发工具是针对客户化开发的特点,基于U8平台而开发的一套简化、快速、高效的U8单据(非UAP表单)开发工具。使用快速开发工具开发的单据与U8标准单据风格一致,可通过数据库脚本的简单调整设置单据上字段格式...
unity开发工具集
书 名:3173 软件开发工具 自考教材 全国高等教育自学考试指定教材 计算机信息管理(独立本科段) 组 编:全国高等教育自学考试指导委员会 出版社:经济科学出版社 版 次:2000年2月第1版 2008年4月第8次印刷 作 者: 陈...