Linux---Makefile文件

(一)什么是Makefile文件

最主要包含五个方面:显示规则,隐晦规则,变量定义,文件指示和注释;

(1)显式规则。显式规则说明了,如何生成一个或多的的目标文件。这是由 Makefile 的书写 者明显指出,要生成的文件,文件的依赖文件,生成的命令。 
 
(2)隐晦规则。由于我们的 make 有自动推导的功能,所以隐晦的规则可以让我们比较粗糙 地简略地书写 Makefile,这是由 make 所支持的。 
 
(3)变量的定义。在 Makefile 中我们要定义一系列的变量,变量一般都是字符串,这个有点 你 C 语言中的宏,当 Makefile 被执行时,其中的变量都会被扩展到相应的引用位置上。 
 
(4)文件指示。其包括了三个部分,一个是在一个 Makefile 中引用另一个 Makefile,就像 C 语言中的 include 一样;另一个是指根据某些情况指定 Makefile 中的有效部分,就像 C 语言 中的预编译#if 一样;还有就是定义一个多行的命令。有关这一部分的内容,我会在后续的 部分中讲述。 
 
(5)注释。Makefile 中只有行注释,和 UNIX 的 Shell 脚本一样,其注释是用“#”字符,这 个就像 C/C++中的“//”一样。如果你要在你的 Makefile 中使用“#”字符,可以用反斜框 进行转义,如:“\#”。 
 
后,还值得一提的是,在 Makefile 中的命令,必须要以[Tab]键开始。 

(二)Makefile优势与make命令

Makefile带来的好处就是------“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。

make是一个命令工具,是解释Makefile中指令的命令工具,一般来说,大多数IDE都有这个命令,Visual C++de nmake.linux下的GNU的make。可见,makefile都成为一种在工程方面的编译方法。

make命令执行时,需要一个Makefile文件,已告诉make命令需要怎么样的去编译和链接程序。

(三)Makefile文件示例

现在有5个文件,分别为:main.c  my1.h  my2.h  my1.c  my2.c;现在编写Makefile文件,名称为Makefile过程如下:

main:main.o  my1.o  my2.o

        gcc   -o    main  main.o  my1.o  my2.o

main.o :main.c  my1.h  my2.h

        gcc  -c main.c

my1.o:my1.c  my1.h 

        gcc   -c    my1.c 

my2.o:my2.c  my2.h 

        gcc   -c    my2.c 

clean:

        rm   -f  *.o   main

总结:

target_ _  :prerequisites_ _

            command

            _ _

            _ _

target:也就是一个目标文件,也可以是Objject File,也可以是执行文件。还可以是一个标签(Lable)。

prerequisites:要生成target所需要的文件或是目标。

command:make需要执行的命令

        这是一个文件的依赖关系,也就是说,target 这一个或多个的目标文件依赖于 prerequisites 中的文件,其生成规则定义在 command 中。说白一点就是说,make 会比较 targets 文件和 prerequisites 文件的修改日期,如果 prerequisites 文件的日期要比 targets 文件的日期要新,或者 target 不存在的话,那么,make 就会执行后续定义的命令。 这就是 Makefile 的 规则。也就是 Makefile 中核心的内容。 

在定义好依赖关系后,后续的那一行定义了如何生成目标文件的操作系统命令,一定要以一 个 Tab 键作为开头。

每个 Makefile 中都应该写一个清空目标文件(.o 和执行文件)的规则,这不仅便于重编译, 也很利于保持文件的清洁

(四)make工作原理

当我们输入make时:

  • make会首先在当前目录下寻找makefile文件;
  • 如果找到,它会找到文件中的第一个目标文件(target),在上面的例子中,他会找到 “main”这个文件,并把这个文件作为最终的目标文件;
  • 如果main文件不存在,或者main所依赖的后面的.o文件的修改时间要比main这个文件新,那么他就会执行后面所定义的命令来生成main这个文件;
  • 如果main所依赖的.o文件也存在,那么make会在当前文件中找目标为.o文件的依赖性,如果找到在跟就那一个规则生成.o文件;
  • 当.c文件和.h文件都是存在的,那么make会生成.o文件,然后再用.o文件声明make的最终文件,也就是执行文件mian.

       这就是整个 make 的依赖性,make 会一层又一层地去找文件的依赖关系,直到终编译出 第一个目标文件。在找寻的过程中,如果出现错误,比如后被依赖的文件找不到,那么 make 就会直接退出,并报错,而对于所定义的命令的错误,或是编译不成功,make 根本不 理。make 只管文件的依赖性,即,如果在我找了依赖关系之后,冒号后面的文件还是不在, 那么对不起,我就不工作啦。 

(五)makefile文件优化

(1)使用变量

问题导入;

main:main.o  my1.o  my2.o

        gcc   -o    main  main.o  my1.o  my2.o

我们可以看到[.o]文件的字符串被重复了三次(包括clean),如果我们的工程需要加入一个新的[.o]文件, 那么我们需要在三个地方加,虽然不复杂,但是如果文件一旦过多,难免会出错,继而导致编译失败。所以为了makefile的易维护性,引入变量。

比如,我们声明一个变量,叫 objects,只要能够表示 obj 文件就行了。我们在 makefile 一开始就这样定义: 

objects = main.o  my1.o  my2.o          (在 makefile 中以“$(objects)”的方式来使用这个变量了)

改良版

objects = main.o  my1.o  my2.o

main:$(objects)

        gcc   -o    main  $(objects)

main.o :main.c  my1.h  my2.h

        gcc  -c main.c

my1.o:my1.c  my1.h 

        gcc   -c    my1.c 

my2.o:my2.c  my2.h 

        gcc   -c    my2.c 

clean:

        rm   -f  $(objects)  main

(2)自动推导

GNU 的 make 很强大,它可以自动推导文件以及文件依赖关系后面的命令,于是我们就没必要去在每一个[.o]文件后都写上类似的命令,因为我们的 make 会自动识别,并自己推导命令。 只要 make 看到一个[.o]文件,它就会自动的把[.c]文件加在依赖关系中,如果 make 找到一 个 my1.o,那么 my1.c,就会是 my1.o 的依赖文件。并且 cc -c my1.c 也会被推导出来,于是,我们的 makefile 再也不用写得这么复杂。我们的是新的 makefile 又出炉 了。

objects = main.o  my1.o  my2.o

main:$(objects)

        gcc   -o    main  $(objects)

main.o :my1.h  my2.h

my1.o:my1.h 

my2.o:my2.h 

clean:

        rm   -f  $(objects)  main

这种方法,也就是 make 的“隐晦规则”。

(3)另类风格

即然我们的 make 可以自动推导命令,那么我看到那堆[.o]和[.h]的依赖就有点不爽,那么多的重复的[.h],能不能把其收拢起来,好吧,没有问题,这个对于 make 来说很容易,谁叫它提供了自动推导命令和文件的功能呢,来看看新风格的 makefile 吧。 

objects = main.o  my1.o  my2.o

main:$(objects)

        gcc   -o    main  $(objects)

main.o   my1.o:my1.h 

main.o   my2.o:my2.h 

clean:

        rm   -f  $(objects)  main

这种风格,让我们的 makefile 变得很简单,但我们的文件依赖关系就显得有点凌乱了。鱼和 熊掌不可兼得。

(4)环境变量VPATH

在一些大的工程中,有大量的源文件,我们通常的做法是把这许多的源文件分类,并存放在 不同的目录中。所以,当 make 需要去找寻文件的依赖关系时,你可以在文件前加上路径, 但好的方法是把一个路径告诉 make,让 make 在自动去找。 
 
Makefile 文件中的特殊变量“VPATH”就是完成这个功能的,如果没有指明这个变量,make 只会在当前的目录中去找寻依赖文件和目标文件。如果定义了这个变量,那么,make 就会 在当当前目录找不到的情况下,到所指定的目录中去找寻文件了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值