Makefile入门-程序员宅基地

技术标签: Makefile  linux  后端  make  


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:
在这里插入图片描述


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

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/yuehuazyc/article/details/137091015

智能推荐

使用dockerfile文件创建镜像时docker build没有反应-程序员宅基地

文章浏览阅读1.3k次。问题:  先 docker pull centos:7 拉取了一个官方的基础镜像,为后续创建jdk8镜像做准备,在创建如下的dockerfile文件  执行docker build -t jdk_8u191:20190307 . jdk_dockerfile 时都没有反应  jdk_dockerfile文件内容# 以此镜像作为基础镜像构建新的镜像FROM cento..._建立一个dockerfile,docker build -t cetos7/linuxc_env不成功

mysql优先队列排序算法_硬核!手写一个优先队列-程序员宅基地

文章浏览阅读190次。前言事情还要从一个故事讲起:对于上面那只可爱的小狗狗不会,本篇即为该教程,首先,我要告诉这只可爱的小狗狗,这种问题你要使用的数据结构为优先队列,每次操作的时间复杂度为O(logn),而整个过程的时间复杂度为O(nlogn).对于本片的设计与实现和堆排序可能有些相似,因为他们都借助堆来实现算法和数据结构,下面详细介绍优先队列的设计与实现。堆而堆就是一类特殊的数据结构的统称。堆通常是一个可以被看做一棵..._mysql 的堆排序

C# c++ Json序列化与反序列_c++json序列化与反序列化-程序员宅基地

文章浏览阅读231次。C# 序列化与反序列化, 读文件和写到文件_c++json序列化与反序列化

智能制造控制中的AI研究进展-程序员宅基地

文章浏览阅读446次,点赞14次,收藏14次。1.背景介绍智能制造控制是现代制造业中的一个重要领域,它涉及到制造过程中的自动化、智能化和优化。随着计算能力的提高和数据技术的发展,人工智能(AI)技术在智能制造控制中的应用也逐渐成为主流。本文将从背景、核心概念、算法原理、代码实例、未来趋势等多个方面进行深入探讨,以帮助读者更好地理解AI在智能制造控制中的应用和研究进展。1.1 背景介绍智能制造控制是制造业中的一个重要领域,涉及到制造...

2018美亚杯个人赛刷题-程序员宅基地

文章浏览阅读5.4k次,点赞6次,收藏27次。文章目录写在前面题目1.E2.C3.B -D-4.C -E-5.C6. D7.D8. A9.A10.C11.E12.D13.D14.A15.D16.E17.D18.A19. B20.C21.E22.D23.A24.C25.C26.D27.D28.C29.D30.D31.C32.E33.D34.B -C-35. -E-36.A37.A38.D39.D -C-40.B41.C42.E -D-43.C44.B45.A46.C47.E48.B49.D50.CPS写在前面这是美亚杯2018个人赛的个人_2018美亚杯个人赛

ECS框架学习(Entitas)入门_ecs框架 entitas-程序员宅基地

文章浏览阅读6.2k次。公司要求使用ECS框架经行开发,没办法只能自己学习了。记录一下学习过程。框架的含义可以去其他地方查看,我这里写一点我的理解(新人,不对请谅解)。ECS即Entity-Component-System(实体-组件-系统) 的缩写。它做到了行为、数据分开,Component存数据。Entity用来就是由各个Component组成。System用来经行他们中间的通信。对于网上或者官方说速度更快、更容..._ecs框架 entitas

随便推点

Serverless 基本概念入门_seveless 百度-程序员宅基地

文章浏览阅读1k次。从行业趋势看,Serverless 是云计算必经的一场革命2019 年,Serverless 被 Gartner 称为最有潜力的云计算技术发展方向,并被赋予是必然性的发展趋势。Serverless 从底层开始变革计算资源的形态,为软件架构设计与应用服务部署带来了新的设计思路。为此,我们策划了Serverless 技术专栏,从基础概念入门,到前后台架构设计、应用拓展、最佳实践等多维度,揭开 Serverless 的面纱,带你走进无服务器的世界。什么是 Serverless?Serverl.._seveless 百度

ubuntu proxy-程序员宅基地

文章浏览阅读68次。升级到Ubuntu10.04后,发现apt-get的代理设置有改变了,在9.10以前使用“http_proxy”环境变量就可以令apt-get使用代理了export http_proxy=http://127.0.0.1:8000sudo apt-get update然后在Ubuntu10.04下就无效了,看来apt-get已经被改成不使用这个环境变量了。一阵郁闷后,最后..._重装ubuntu proxy address

Qt笔记_正则表达式(regular expression)_qt regex-程序员宅基地

文章浏览阅读9.2k次,点赞4次,收藏28次。手册里使用的词汇是 regexp 优点: 方便地完成字符串的一些处理操作,例如验证、查找、替换和分割等。类名称为QRegExp类,是基于Perl的正则表达式语言,支持Unicode。头文件:#include < QRegExp >//(尖括号中的空格是为了适应markdown而添加的,编程时不使用多余的空格)qmake:QT += core帮助文档中指出:All functions in_qt regex

系统设计与分析homework5_sdlc的第一阶段是分析。写一个简单的报告,包括: 分析新系统需要解决的问题 l可行-程序员宅基地

文章浏览阅读151次。一、根据订旅馆建模文档,Asg-RH.pdf:1. 绘制用例图模型(到子用例)给出 make reservation 用例的活动图2、根据课程练习“投递员使用投递箱给收件人快递包裹”的业务场景分别用多泳道图建模三个场景的业务过程场景一x科技公司发明了投递柜,它们自建了投递柜以及远程控制系统。注册的投递员在推广期免费使用投递柜。由于缺乏资源,仅能使用y移动平台向客户发送短信通知。..._sdlc的第一阶段是分析。写一个简单的报告,包括: 分析新系统需要解决的问题 l可行

LayUI的后台管理模板_layui后端模板-程序员宅基地

文章浏览阅读8k次,点赞2次,收藏18次。  以前没有做网页开发不知道的内容太多了,现在开始做了这一块,发现内容真多。  星期五接到一个资产核查的任务,时间紧,我对网页这一块的内容还不是很熟练,有些着急,在网上一搜,LayUI的模板,有很多好评和讲解,拿来一用,感觉很不错。  这个后台系统可以很快上手,界面部分不用操心太多,很多页面有实例,略微改动就可以直接使用。  写程序界面是个大问题,这下省事多了,虽然后期项目使用LayUI比较少,但做一些中小型的项目真的是很好的选择,最主要的就是快。..._layui后端模板

常见的数组概念-程序员宅基地

文章浏览阅读90次。常见数组_常见的数组