make编译笔记(一)

实在是太多太长了,分。

Makefile关系到整个工程的编译规则。规定了一些列的规则,来指定哪些文件需要先编译,那些文件需要后编译,那些文件需要重新编译。

为了完成对工程文件的编译,并生成执行文件,可以这样编译这些源文件。

gcc xxx.c ccc.c cccc.c -o main

但这样效率低下,修改了某个就需要全部重新编。

给每个文件编译,再拿这些编译好的编译就会快很多,但这样又容易出错。

需要一个能够按照一定规则对源文件编译的文件,就是Makefile文件。 

编写一个Makefile的文件并与源代码放在同一个目录下。

目标...:条件集合...
    命令1
    命令2

注:行首的空白不能用空白格,必须是tab

对于Makefile中的每个以Tab开头的命令,make会创建一个Shell进程去执行

clean是用来清除make执行过程中产生的临时文件。当使用make命令时,clean下的命令不会被执行,需要以make clean方式单独执行。

clean:
    rm *.o
    rm xxx

make是如何工作的

  1. make会在当前目录下找到名为Makefile或makefile的文件
  2. 如果找到,他会找到文件中的第一个目标文件
  3. 如果目标文件不存在,或者目标文件所依赖的.o文件修改时间比目标文件晚,那么他就会执行后面定义的命令来生成目标文件
  4. 如果目标文件依赖的.o文件存在。make会在当前文件中查找目标为.o的依赖性;如果找到,再根据那个规则生成.o文件
  5. 如果c文件和头文件存在,make会生成.o文件,然后再用.o文件生成make的目标文件

Makefile中使用变量

为了Makefile的易维护性,Makefile可以使用变量

objects=main.o xxx.o xxxx.o
main:$(objects)
    gcc -o main$(object)
...

让Makefile自动推导

只要make看到一个.o文件就会自动把.c文件加到依赖关系中

清空目标文件的规则

clean要放在文件的最后

.PHONY表示clean是一个"伪目标",可以在rm命令前加一个减号(也许某些文件会出问题,但不管,继续做后面的事情)

make概述

makefile内容:

主要包含了5个内容:显式规则、隐式规则、变量定义、文件指示和注释

  1. 显式规则:说明了如何生成一个或多个目标文件。书写Makefile时需要明确指定目标文件、目标的依赖文件以及更新目标文件需要的命令
  2. 隐式规则:有一些规则不需要明确说明
  3. 变量定义:在Makefile中要定义一系列的变量,变量一般都是字符串
  4. 文件指示:有3个部分,一个部分是一个Makefile中引用另一个Makefile,另一个是根据情况指定Makefile中的有效部分,还有一种情况定义一个多行的命令
  5. 注释:只有行注释#

makefile的文件名

默认情况下,make命令会在当前目下按顺序寻找名为GUNmakefile、makefile、Makefile的文件。最好使用Makefile文件名,最好不要使用GUNmakefile文件名,这个文件是GUN的make识别的。

如果要指定特定的Makefile,可以使用make的-f或--file参数。

包含其他的makefile文件

关键字是include

include指示符告诉make暂停读取当前的Makefile,赚取读取include指定的一个或多个文件,完成后再返回继续当前Makefile的读取

include XXXXX

XXXXX事故shell所支持的文件名(可以使用通配符) 

指示符include所在的行可以一个或者多个空格(make程序在处理时将忽略这些空格)开始,不能以Tab字符开始。使用指示符包含进来的Makefile中,如果存在变量或者函数的引用,他们将会在包含他们的Makefile中展开。

make指示符有以下场合

  • 有多个不同程序,由不同目录下的几个独立Makefile来描述其创建或者更新规则
  • 当根据原文件自动产生依赖文件时,可以将自动产生的依赖关系保存在另一个文件中,主Makefile使用指示符include包含这些文件

如果include指示符指定的文件不是以斜线开始(绝对路径),且当前目录下也不存在此文件,make将根据文件名试图在以下几个目录下查找:首先,查找使用命令行选项-l或者--include-dir指定的目录,如果找到指定的文件,则使用这个文件;否则依次搜索(如果存在)/usr/gun/include、/usr/include

当在这些目录都没有找到include指定的文件时,马克将会提示一个包含文件未找到的警告提示,但不会立刻推出,而是继续处理Makefile的内容。当完成读取所有的Makefile文件后,make将试图使用规则来创建通过指示符include指定的但未找到的文件,当不能创建它时,make将提示致命错误并推出。

可以使用-include来代替include,忽略由于文件不存在或者无法创建时的错误提示。

为了和其他的make程序进行兼容,也可以使用sinclude来到代替-include(GUN所支持的方式)

变量MAKEFILES

如果当前环境定义了一个MAKEFILES的环境变量,make执行时就会首先将此变量的值作为需要读入的Makefile文件,并且多个文件之间使用空格分开。

区别:

  • 环境变量指定的Makefile文件中的目标不会被作为make执行的终极目标。如果在make的工作目录下没有名为Makefile、makefile或GUNmakefile文件,make会提示mak:xxx没有规则可以创建目标;存在,那么make执行的终极目标就是当前目录下这个文件中定义的终极目标。
  • 环境变量所定义的文件列表在执行make时,即使不能找到其中某一个文件(不存在或者无法创建)make不会提示错误也不会退出
  • make在执行时,首先读取的是环境变量MAKEFILES所指定的文件列表,之后才是工作目录下的Makefile文件,include所指定的文件是在make发现此关键字时才会暂停正在读取的文件而转去读取include所指定的文件。

环境变量MAKEFILES主要用在make的递归调用过程中的通信。

推荐的做法是在需要包含其他Makefile文件时使用指示符include来实现。

变量MAKEFILE_LIST

make程序在读取多个Makefile文件时,在对这些文件进行解析执行之前,make读取的文件名时会被自动地追加到变量MAKEFILE_LIST的定义域中。

例:

name1:=$(word$(words$(MAKEFILE_LIST)),$(MAKEFILE_LIST))
include inc.mk
name2:=$(word$(words$(MAKEFILE_LIST)),$(MAKEFILE_LIST))
all:
    @echo name1=$(name1)
    @echo name2=$(name2)

执行make,结果如下:

name1=Makefile

name2=inc.mk

words返回单词个数

word返回列表中的第i个单词

整体函数的功能时返回MAKRFILE_LIST中最后一个单词 

其他特殊变量

GUN make支持一个特殊的变量,且不能通过任何途径给它赋值。此变量展开以后是一个特定的值。这个重要的特殊的变量是.VARIABLES。他被展开以后是此引用点之前Makefile文件中所定义的所有全局变量列表。包括空变量和make的内嵌变量,但不包括目标指定的变量,目标指定变量只在特定目标的上下文有效。

Makefile文件的重建

Makefile可又其他文件生成。如果Makefile由其他文件重建,那么在make开始解析Makefile时,需要读取的是更新后的Makefile。

重载另外一个Makefile

某些情况下,会存在两个比较类似于Makefile文件,其中一个需要使用另外一个文件中所定义的变量和规则,可以使用include来包含另一个文件。如果两个文件中存在相同目标,而其描述规则中使用了不同的命名,这是不允许的。遇到这种情况不能使用include来解决。GUN make提供了另一种途径。

在需要包含的Makefile文件中那个,可以使用一个称之为所有匹配模式的规则来描述在A中没有定义的目标,make将会在给定的Makefile文件中寻找没有在当前Makefile中给出的目标更新规则。

make如何解析Makefile文件

分为两个阶段

第一阶段:读取所有Makefile文件,内建所有变量,明确规则和隐含规则,并建立所有目标与依赖之间的依赖关系结构链表

第二阶段:根据第一阶段已经建立的依赖关系结构链表决定哪些目标需要更新,并使用对应的规则来重建这些目标。

总结

执行过程:

  1. 依次读取变量MAKEFILES定义的Makefile文件列表
  2. 读取工作目录下的Makefile文件
  3. 依次读取工作目录Makefile文件中使用指示符include包含的文件
  4. 查找重建所有已读的Makefile文件的规则
  5. 初始化变量,展开那些需要立即展开的变量和函数,并根据预设条件确定执行分支
  6. 根据终极目标及其他目标的依赖关系建立依赖关系链表
  7. 执行除终极目标外的所有目标的规则
  8. 执行终极目标的规则

你可能感兴趣的:(linux,笔记)