[Linux]Makefile入门


Linux项目自动化构建工具-make/Makefile

  学会使用Makefile可以极大的提高了软件开发的效率,makefile的特色“自动化编译”,使得我们一旦写好makefile,只需要一个make命令,整个工程完全自动编译。同时是否会写makefile,也从一个侧面说明了一个人是否具备完成大型工程的能力。
  通过make命令,与makefile文件,两个搭配使用,完成项目自动化构建。
  讲是这么讲,makefile到底怎么就提高了我们软件开发的效率呢?
  先来看一看如果没有makefile我们编写程序到底会多麻烦
  我们有两个简单的文件,其实现如下图所示

在这里插入图片描述  现在我们要制作一个属于自己的MyMath库,并将其发布,如果没有makefile我们要怎么做?

    gcc -c my_add.c my_sub.c                      //生成可重定位二进制文件
    ar -rc libMyMath.a my_add.o my_sub.o         //生成库文件
    mkdir -p mylib/include                      //创建目录结构
    mkdir -p mylib/lib                         //创建目录结构
    cp -rf *.h mylib/include/                 //拷贝文件到对应目录
    cp -rf *.a mylib/lib/                    //拷贝文件到对应目录
    tar czf mylib.tgz mylib                 //打包

最终结果如下:
在这里插入图片描述  现在我们有了makefile就可以大大提高工作效率
在这里插入图片描述  我们在命令行运行makefile生成目标文件,make output发布我们自己的库,make clean清理文件。
在这里插入图片描述
  现在知道为什么说makefile可以极大提高开发效率了吧。
  现在我们就来正式学习如何使用makefile吧。


语法规则

目标文件:依赖文件列表  
	依赖方法    #注意依赖方法前面要有一个TAB键

  1.目标文件:我们要生成的文件。
  2.依赖文件列表:简单来讲就是目标文件需要哪些文件用来生成目标文件。
  3.依赖方法:就是目标文件如何用依赖文件列表中的文件来生成目标文件。


make/Makefile工作原理

  make是如何工作的,在默认的方式下,也就是我们只输入make命令。那么:

  1. make会在当前目录下找名字叫“Makefile”或“makefile”的文件。
  2. 如果找到,它会找文件中的第一个目标文件(target),并把这个文件识别为 终极目标
  3. 根据目标文件是否存在以及目标文件所依赖文件ACM时间来决定是否会生成目标文件。
  4. 如果目标文件的依赖文件同时也依赖其他文件生成,make就会解决目标文件依赖文件的依赖关系,这就是整个make的依赖性,make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。
  5. 在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错,而对于所定义的命令的错误,或是编译不成功,make根本不理。
  6. make只管文件的依赖性即,如果在我找了依赖关系之后,冒号后面的文件还是不在,那么对不起,我就挂掉了。

目标文件生成规则

终极目标

  对于我们的makefile可能其目的是要生成多个目标文件,但是makefile会默认从上向下扫描文件,并且把识别到的第一个文件识别为终极目标文件,且只会生成这个终极目标文件。
  如下:
 在此文件中有两个目标文件,我们运行make
在这里插入图片描述MAKE:
 如我们所预料,只生成了一个目标文件,如何生成所有目标文件呢,接着往下看
在这里插入图片描述  我们可以通过all 指定所需要生成的目标文件

在这里插入图片描述

MAKE:
在这里插入图片描述  如上图所示,存在回显问题,如果想要取消回显,可在makefile文件中在指令前面加@
在这里插入图片描述

MAKE:
在这里插入图片描述

ACM时间

  对于我们多次运行make生成目标文件,会发生什么?
  它会告知我们目标文件已经存在。
在这里插入图片描述
  如果我们touch更新目标文件时间呢?
  文件重新生成。
在这里插入图片描述  结论:当我们已经存在该目标文件时,make后目标文件是否会重新生成取决于该目标文件所依赖文件的ACM时间(严格来讲是M时间)
  那到底什么是ACM时间呢?
  1.A(access时间):即文件最后一次访问时间,对于我们频繁访问某一文件,并不是每一次访问都会更新该文件的A时间,在我们访问该文件后短时间内再次访问并不会更新A时间。
  2.C(change时间):即文件最后一次属性修改时间(一个文件由内容与属性所构成)
  3.M(modify时间):即文件最后一次内容修改时间。(修改文件内容必定引起AC时间改变)
  我们可以通过stat指令查看文件的ACM时间。
在这里插入图片描述


变量赋值

以下用A B C代指某些文件例如main.c文件或指令例如gcc main.c

直接赋值

  直接赋值是最简单的方式,只需要使用 = 符号。这种方式定义的变量被称为递归扩展变量,其值为整个Makefile中最后被指定的值。

VARIABLE_A=A
VARIABLE_B=$(VARIABLE_A) B   #$(VARIABLE_A)表示取VARIABLE_A值
VARIABLE_A=AA

  最后VARIABLE_B的值为AA B

立即赋值

  使用 := 符号进行赋值会立即扩展变量的值,这种方式定义的变量被称为简单扩展变量.

SIMPLE_VARIABLE := $(ANOTHER_VARIABLE)

  在这个例子中,SIMPLE_VARIABLE 会立即被赋值为 ANOTHER_VARIABLE 的值。如果 ANOTHER_VARIABLE 在后面被改变,SIMPLE_VARIABLE 的值不会受到影响。

条件赋值

  你可以使用条件语句来为变量赋值,例如:

ifeq ($(DEBUG),1)  #ifeq 是条件指令,用于比较两个参数是否相等
    DEBUG_FLAGS = A

else  

    DEBUG_FLAGS = B

endif

  在这个例子中,DEBUG_FLAGS 会根据 DEBUG 变量的值被赋予不同的值。
  ?=赋值

MY_VARIABLE?=default_value

  在这个例子中,如果 MY_VARIABLE 在这个 Makefile 或任何包含它的 Makefile 中之前没有被设置过值,那么它就会被设置为 default_value。但是,如果 MY_VARIABLE 在这之前已经被设置过了,那么它就不会被 default_value 覆盖。

追加赋值

  使用 += 符号可以将值追加到变量的现有值上。

OBJECTS = A B  

OBJECTS += C

  在这个例子中,OBJECTS 变量最初包含 A 和B,然后C被追加到它的值上。

使用环境变量

  Makefile 中的变量也可以从环境变量中继承。如果你想在 Makefile 中使用环境变量的值,你可以直接引用它。

CC = $(CC_ENV)

  在这个例子中,如果环境变量 CC_ENV 存在,它将被赋值给 CC 变量。


特殊变量

$@ #表示目标文件
$^ #表示依赖文件列表
&< #表示依次取依赖文件列表文件生成对应目标文件

使用变量

$符号表示取变量的值,当变量名多于一个字符时,使用"( )"


伪目标 .PHONY

  伪目标是一个特殊的目标,它不代表一个真实的文件。形象的来讲它只是一个标签,用于执行与该目标关联的命令。因为伪目标不代表任何文件,所以make工具不会检查文件系统来确定该目标是否已经是最新的。这意味着,无论何时你尝试构建这个伪目标,与其关联的命令都会被执行。
  假设当前目录下存在一个名为clean的文件和一个Makefile文件,Makefile文件内容如下:

clean:
	rm temp

  当我们执行make clean命令后,目标clean并不会被执行,因为make会首先查找名为clean的文件,而不是将clean作为目标来执行,又因为我们不会生成新的clean文件,所以使得clean文件的ACM时间一直被判定为最新时间,导致不会执行clean,为了解决这个问题,可以在Makefile文件中将clean声明为伪目标,修改后的Makefile文件内容如下:

.PHONY: clean
clean:
	rm temp

  再次执行make clean命令后,伪目标clean就会被执行,从而删除temp文件或目录(如果存在的话)。
  伪目标用途:伪目标在Makefile中的作用主要是用来定义一些不代表实际文件的目标,这些目标通常用于执行一些额外的操作,比如清理临时文件、生成文档、运行测试等。使用伪目标可以将这些操作集中到一个目标中,方便管理。同时,伪目标还可以用来定义一些常用的操作,比如编译、运行、安装等,以及定义依赖关系,确保目标的正确顺序。


嵌套执行Makefile

  嵌套 Makefile 是指在一个 Makefile 中包含另一个 Makefile。这种技术常用于大型项目中,将项目划分为多个子目录或子模块,每个子目录或子模块都有自己的 Makefile,然后在主 Makefile 中包含这些子 Makefile。
  现在有以下结构:
在这里插入图片描述  主makefile文件内容如下:
嵌套执行makefile语法规则:
在主makefile中,执行

make -C  路径

在这里插入图片描述

  两个子makefile文件内容如下(两个子makefile内容相同):
在这里插入图片描述

MAKE:
在这里插入图片描述
MAKE CLEAN:
在这里插入图片描述


本章到此结束,感谢阅读!

  • 29
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 22
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 22
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值