您的位置:首页 > 其它

深入学习Make命令和Makefile

2010-08-05 19:13 253 查看
make是Linux

下的一款程序自动维护工具,配合makefile的使用,就能够根据程序中模块的修改情况,自动判断应该对那些模块重新编译,从而保证软件是由最新的模块构成。本文分为上下两部分,我们将紧紧围绕make在软件开发中的应用展开详细的介绍。
一、都是源文件太多惹得祸



当我们在开发的程序中涉及众多源文件时,常常会引起一些问题。首先,如果程序只有两三个源文件,那么修改代码后直接重新编译全部源文件就行了,但是如果程序的源文件较多,这种简单的处理方式就有问题了。


设想一下,如果我们只修改了一个源文件,却要重新编译所有源文件,那么这显然是在浪费时间。其次,要是只重新编译那些受影响的文件的话,我们又该如
何确定这些文件呢?比如我们使用了多个头文件,那么它们会被包含在各个源文件中,修改了某些头文件后,那些源文件受影响,哪些与此无关呢?如果采取拉网式
大检查的话,可就费劲了。

由此可以看出,源文件多了可真是件让人头疼的事。幸运的是,实用程序make可以帮我们解决这两个问题——当程序的源文件改变后,它能保证所有受影响的文件都将重新编译,而不受影响的文件则不予编译,这真是太好了。

二、Make程序的命令行选项和参数



我们知道,make程序能够根据程序中各模块的修改情况,自动判断应对哪些模块重新编译,保证软件是由最新的模块构建的。至于检查哪些模块,以及如何构建软件由makefile文件来决定。


虽然make可以在makefile中进行配置,除此之外我们还可以利用make程序的命令行选项对它进行即时配置。Make命令参数的典型序列如下所示:

make [-f makefile文件名][选项][宏定义][目标]



这里用[]括起来的表示是可选的。命令行选项由破折号“–”指明,后面跟选项,如

make –e
如果需要多个选项,可以只使用一个破折号,如

make –kr
也可以每个选项使用一个破折号,如


make –k –r
甚至混合使用也行,如

make –e –kr
Make命令本身的命令行选项较多,这里只介绍在开发程序时最为常用的三个,它们是:

–k:

如果使用该选项,即使make程序遇到错误也会继续向下运行;如果没有该选项,在遇到第一个错误时make程序马上就会停止,那么后面的错误情况就不得而知了。我们可以利用这个选项来查出所有有编译问题的源文件。


–n:

该选项使make程序进入非执行模式,也就是说将原来应该执行的命令输出,而不是执行。

网管下载dl.bitscn.com
–f :

指定作为makefile的文件的名称。
如果不用该选项,那么make程序首先在当前目录查找名为makefile的文件,如果没有找到,它就会转而查找名为Makefile的文件。如果您在
Linux下使用GNU Make的话,它会首先查找GNUmakefile,之后再搜索makefile和Makefile。按照惯例,许多Linux

程序员使用Makefile,因为这样能使Makefile出现在目录中所有以小写字母命名的文件的前面。所以,最好不要使用GNUmakefile这一名称,因为它只适用于make程序的GNU版本。 中国网管联盟bitsCN.com



当我们想构建指定目标的时候,比如要生成某个可执行文件,那么就可以在make命令行中给出该目标的名称;如果命令行中没有给出目标的话,make
命令会设法构建makefile中的第一个目标。我们可以利用这一特点,将all作为makefile中的第一个目标,然后将让目标作为all所依赖的目
标,这样,当命令行中没有给出目标时,也能确保它会被构建。



管u家u.bitscn@com

make是Linux
下的一款程序自动维护工具,配合makefile的使用,就能够根据程序中模块的修改情况,自动判断应该对那些模块重新编译,从而保证软件是由最新的模块构成。

本文分为上下两部分,我们在上一篇文章中分别介绍了make和makefile的一些基本用法,在本文中,我们会对make和makefile的功能做进一步的介绍。



一、构建多个目标


有时候,我们想要在一个makefile中生成多个单独的目标文件,或者将多个命令放在一起,比如,在下面的示例mymakefile3中我们将添
加一个clean
选项来清除不需要的目标文件,然后用install选项将生成的应用程序移动到另一个目录中去。这个makefile跟前面的mymakefile较为相
似,不同之处笔者用黑体加以标识:

all: main

# 使用的编译器

CC = gcc

# 安装位置

INSTDIR = /usr/local/bin

# include文件所在位置

INCLUDE = .

# 开发过程中所用的选项

CFLAGS = -g -Wall –ansi

# 发行时用的选项

# CFLAGS = -O -Wall –ansi

main: main.o f1.o f2.o

$(CC) -o main main.o f1.o f2.o

main.o: main.c def1.h

$(CC) -I$(INCLUDE) $(CFLAGS) -c main.c

f1.o: f1.c def1.h def2.h

$(CC) -I$(INCLUDE) $(CFLAGS) -c f1.c

f2.o: f2.c def2.h def3.h

$(CC) -I$(INCLUDE) $(CFLAGS) -c f2.c

clean:

-rm main.o f1.o f2.o

install: main

@if [ -d $(INSTDIR) ]; /

then /

cp main $(INSTDIR);/

chmod a+x $(INSTDIR)/main;/

chmod og-w $(INSTDIR)/main;/

echo “Installed in $(INSTDIR)“;/

else /

echo “Sorry, $(INSTDIR) does not exist”;/

fi

在这个makefile中需要注意的是,虽然这里有一个特殊的目标all,但是最终还是将main作为目标。因此,如果执行make命令时没有在命令行中给出一个特定目标的话,仍然会编译连接main程序。

其次要注意后面的两个目标:clean和install。目标clean没有依赖模块,因为没有时间标记可供比较,所以它总被执行;它的实际意图是
引出后面的rm命令来删除某些目标文件。我们看到rm命令以-开头,这时即使表示make将忽略命令结果,所以即使没有目标供rm命令删除而返回错误
时,make clean依然继续向下执行。

接下来的目标install依赖于main,所以make知道必须在执行安装命令前先建立main。用于安装的指令由一些shell命令组成。


因为make调用shell来执行规则,并且为每条规则生成一个新的shell,所以要用一个shell来执行这些命令的话,必须添加反斜杠,以使所有命令位于同一个逻辑行上。这条命令用@开头,表示在执行规则前不会向标准输出打印命令。

为了安装应用程序,目标install会一条接一条地执行若干命令,并且执行下一个之前,不会检查上一条命令是否成功。若想只有当前面的命令取得成功时,随后的命令才得以执行的话,可以在命令中加入&&,如下所示:



@if [ -d $(INSTDIR) ]; /

then /

cp main $(INSTDIR) &&/

chmod a+x $(INSTDIR)/main && /

chmod og-w $(INSTDIR/main && /

echo “Installed in $(INSTDIR)“ ;/

else /

echo “Sorry, $(INSTDIR) does not exist” ; false ; /

fi
这是shell的“与”指令,只有当在前的命令成功时随后的命令才被执行。这里不必关心前面命令是否取得成功,只需注意这种用法就可以了。

要想在/usr /local/bin目录安装新命令必须具有特权,所以调用make install命令之前,可以让Makefile使用一个不同的安装目录,或者修改该目录的权限,或切换到root用户。如下所示:

$ rm *.o main

$ make -f Mymakefile3

gcc -I. -g -Wall -ansi -c main.c

gcc -I. -g -Wall -ansi -c f1.c

gcc -I. -g -Wall -ansi -c f2.c

gcc -o main main.o f1.o f2.o

$ make -f Mymakefile3

make: Nothing to be done for ‘all’.

$ rm main

$ make -f Mymakefile3 install

gcc -o main main.o f1.o f2.o

Installed in /usr/local/bin

$ make -f Mymakefile3 clean

rm main.o f1.o f2.o



让我们对此作一简单介绍,首先删除main和所有目标文件程序,由于将all作为目标,所以make命令会重新编译main。当我们再次执行
make命令时,由于main是最新的,所以make什么也不做。之后,我们删除main程序文件,并执行make
install,这会重新建立二进制文件main并将其复制到安装目录。最后,运行make clean命令,来删去所有目标程序。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: