`
javasee
  • 浏览: 935125 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

开发工具

阅读更多
在这一章,我们将会讨论在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正确的确定了所需要的动作。
分享到:
评论

相关推荐

    NES游戏开发工具 NES游戏编程 NES游戏教程

    【标题】"NES游戏开发工具 NES游戏编程 NES游戏教程"涉及的是8位家用游戏机——Nintendo Entertainment System(NES)的游戏制作技术。NES是1980年代末至1990年代初流行的家用游戏机,它承载了一代人的游戏记忆。这...

    开发工具 asm-5.1

    开发工具 asm-5.1开发工具 asm-5.1开发工具 asm-5.1开发工具 asm-5.1开发工具 asm-5.1开发工具 asm-5.1开发工具 asm-5.1开发工具 asm-5.1开发工具 asm-5.1开发工具 asm-5.1开发工具 asm-5.1开发工具 asm-5.1开发工具...

    MCGS_脚本驱动开发工具

    《MCGS脚本驱动开发工具详解》 MCGS(Monitor and Control for General System)是一款广泛应用于工业自动化领域的监控组态软件。它的脚本驱动开发工具为用户提供了强大的自定义功能,使得用户可以根据实际需求编写...

    开发工具 customer

    开发工具 customer开发工具 customer开发工具 customer开发工具 customer开发工具 customer开发工具 customer开发工具 customer开发工具 customer开发工具 customer开发工具 customer开发工具 customer开发工具 ...

    U8快速客户化开发工具-基础介绍

    U8快速开发工具是针对客户化开发的特点,基于U8平台而开发的一套简化、快速、高效的U8单据开发工具。使用快速开发工具开发的单据与U8标准单据风格一致,可通过数据库脚本的简单调整设置单据上字段格式(文本、日期、...

    asp开发工具5

    一种自动生成asp代码的工具(asp开发工具),可用来生成常见的asp添加、删除,修改,查询代码,也可以生成asp类的添加、删除,修改,查询代码,是asp开发人员的超强助手,能迅速生成相应的asp代码,提高写asp代码的...

    VBS脚本开发工具

    VBS脚本开发工具是专为编写、调试和优化VBS脚本而设计的软件或平台,它们通常提供代码编辑器、调试器和语法高亮等特性,以提高开发效率和代码质量。 在提供的文件列表中,我们看到几个关键资源: 1. "Microsoft ...

    开发工具 login 开发工具 login

    开发工具 login开发工具 login开发工具 login开发工具 login开发工具 login开发工具 login开发工具 login开发工具 login开发工具 login开发工具 login开发工具 login开发工具 login开发工具 login开发工具 login开发...

    简易C语言开发工具

    简易C语言开发工具是一款简单易用的C语言集成开发环境(IDE),适合于编写符合ANSI C 标准的C程序,用户可以方便的编写、调试、运行C程序。简易C语言开发工具具有以下特点: 一、以解释的方式执行C程序的,可以很...

    Linux开发工具箱--项目开发的最有效途径.pdf

    《Linux开发工具箱:项目开发的最有效途径》将系统性地介绍GNU/Linux的开源工具,并通过可以被读者容易修改的简明示例说明如何使用这些工具,以满足读者的实际需求。《Linux开发工具箱:项目开发的最有效途径》首先...

    IM安卓开发工具箱imakit9.13更新.zip

    IM安卓开发工具箱imakit目前实现的功能: 制作刷机包 1、备份系统img镜像 2、脚本生成 3、刷机包格式转换 img-dat dat-br 等一系列的功能等你发现

    德卡D8开发工具

    德卡D8开发工具是一款专为德卡公司D8读卡器设计的开发包,它提供了全面的开发环境和文档支持,旨在帮助开发者更高效地进行应用开发和系统集成。这款工具集成了必要的驱动程序、API接口、示例代码以及详细的用户手册...

    查看软件开发工具开发语言判断器

    在软件开发过程中,选择合适的开发工具至关重要,而开发语言判断器就是这样一个工具,它能够帮助开发者确定特定软件或代码片段是用哪种编程语言编写的。本文将深入探讨开发语言判断器的功能、工作原理以及在软件开发...

    开发工具 FontAwesome

    开发工具 FontAwesome开发工具 FontAwesome开发工具 FontAwesome开发工具 FontAwesome开发工具 FontAwesome开发工具 FontAwesome开发工具 FontAwesome开发工具 FontAwesome开发工具 FontAwesome开发工具 FontAwesome...

    开发工具 Page 开发工具 Page

    开发工具 Page开发工具 Page开发工具 Page开发工具 Page开发工具 Page开发工具 Page开发工具 Page开发工具 Page开发工具 Page开发工具 Page开发工具 Page开发工具 Page开发工具 Page开发工具 Page开发工具 Page开发...

    开发工具 style 开发工具 style

    开发工具 style开发工具 style开发工具 style开发工具 style开发工具 style开发工具 style开发工具 style开发工具 style开发工具 style开发工具 style开发工具 style开发工具 style开发工具 style开发工具 style开发...

    开发工具包jdk1.7.0

    JDK 1.7.0包含了一系列开发工具,例如: - `javac`:Java源代码编译器。 - `java`:用于执行已编译的Java类。 - `javadoc`:生成API文档。 - `jar`:创建、管理和提取Java归档文件。 - `jdb`:Java调试器。 - `...

    嵌入式Linux C语言开发工具

    《嵌入式Linux C语言应用程序设计》 作者:华清远见嵌入式培训中心 &lt;br&gt;第二章、嵌入式Linux C语言开发工具 &lt;br&gt;任何应用程序的开发都离不开编辑器、编译器及调试器,嵌入式Linux的C语言开发也一样,它也有一...

    OracleEBS-报表开发工具

    OracleEBS-报表开发工具 OracleEBS-报表开发工具

    golang GO语言开发工具

    golang GO语言开发工具golang GO语言开发工具golang GO语言开发工具golang GO语言开发工具golang GO语言开发工具golang GO语言开发工具golang GO语言开发工具golang GO语言开发工具golang GO语言开发工具golang GO...

Global site tag (gtag.js) - Google Analytics