学会使用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是如何工作的,在默认的方式下,也就是我们只输入make命令。那么:
对于我们的makefile可能其目的是要生成多个目标文件,但是makefile会默认从上向下扫描文件,并且把识别到的第一个文件识别为终极目标文件,且只会生成这个终极目标文件。
如下:
在此文件中有两个目标文件,我们运行make
MAKE:
如我们所预料,只生成了一个目标文件,如何生成所有目标文件呢,接着往下看
我们可以通过all 指定所需要生成的目标文件
MAKE:
如上图所示,存在回显问题,如果想要取消回显,可在makefile文件中在指令前面加@
MAKE:
对于我们多次运行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 变量。
$@ #表示目标文件
$^ #表示依赖文件列表
&< #表示依次取依赖文件列表文件生成对应目标文件
$符号表示取变量的值,当变量名多于一个字符时,使用"( )"
伪目标是一个特殊的目标,它不代表一个真实的文件。形象的来讲它只是一个标签,用于执行与该目标关联的命令。因为伪目标不代表任何文件,所以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中,执行
make -C 路径
两个子makefile文件内容如下(两个子makefile内容相同):
MAKE:
MAKE CLEAN:
本章到此结束,感谢阅读!
文章浏览阅读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不成功
文章浏览阅读190次。前言事情还要从一个故事讲起:对于上面那只可爱的小狗狗不会,本篇即为该教程,首先,我要告诉这只可爱的小狗狗,这种问题你要使用的数据结构为优先队列,每次操作的时间复杂度为O(logn),而整个过程的时间复杂度为O(nlogn).对于本片的设计与实现和堆排序可能有些相似,因为他们都借助堆来实现算法和数据结构,下面详细介绍优先队列的设计与实现。堆而堆就是一类特殊的数据结构的统称。堆通常是一个可以被看做一棵..._mysql 的堆排序
文章浏览阅读231次。C# 序列化与反序列化, 读文件和写到文件_c++json序列化与反序列化
文章浏览阅读446次,点赞14次,收藏14次。1.背景介绍智能制造控制是现代制造业中的一个重要领域,它涉及到制造过程中的自动化、智能化和优化。随着计算能力的提高和数据技术的发展,人工智能(AI)技术在智能制造控制中的应用也逐渐成为主流。本文将从背景、核心概念、算法原理、代码实例、未来趋势等多个方面进行深入探讨,以帮助读者更好地理解AI在智能制造控制中的应用和研究进展。1.1 背景介绍智能制造控制是制造业中的一个重要领域,涉及到制造...
文章浏览阅读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美亚杯个人赛
文章浏览阅读6.2k次。公司要求使用ECS框架经行开发,没办法只能自己学习了。记录一下学习过程。框架的含义可以去其他地方查看,我这里写一点我的理解(新人,不对请谅解)。ECS即Entity-Component-System(实体-组件-系统) 的缩写。它做到了行为、数据分开,Component存数据。Entity用来就是由各个Component组成。System用来经行他们中间的通信。对于网上或者官方说速度更快、更容..._ecs框架 entitas
文章浏览阅读1k次。从行业趋势看,Serverless 是云计算必经的一场革命2019 年,Serverless 被 Gartner 称为最有潜力的云计算技术发展方向,并被赋予是必然性的发展趋势。Serverless 从底层开始变革计算资源的形态,为软件架构设计与应用服务部署带来了新的设计思路。为此,我们策划了Serverless 技术专栏,从基础概念入门,到前后台架构设计、应用拓展、最佳实践等多维度,揭开 Serverless 的面纱,带你走进无服务器的世界。什么是 Serverless?Serverl.._seveless 百度
文章浏览阅读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
文章浏览阅读9.2k次,点赞4次,收藏28次。手册里使用的词汇是 regexp 优点: 方便地完成字符串的一些处理操作,例如验证、查找、替换和分割等。类名称为QRegExp类,是基于Perl的正则表达式语言,支持Unicode。头文件:#include < QRegExp >//(尖括号中的空格是为了适应markdown而添加的,编程时不使用多余的空格)qmake:QT += core帮助文档中指出:All functions in_qt regex
文章浏览阅读151次。一、根据订旅馆建模文档,Asg-RH.pdf:1. 绘制用例图模型(到子用例)给出 make reservation 用例的活动图2、根据课程练习“投递员使用投递箱给收件人快递包裹”的业务场景分别用多泳道图建模三个场景的业务过程场景一x科技公司发明了投递柜,它们自建了投递柜以及远程控制系统。注册的投递员在推广期免费使用投递柜。由于缺乏资源,仅能使用y移动平台向客户发送短信通知。..._sdlc的第一阶段是分析。写一个简单的报告,包括: 分析新系统需要解决的问题 l可行
文章浏览阅读8k次,点赞2次,收藏18次。 以前没有做网页开发不知道的内容太多了,现在开始做了这一块,发现内容真多。 星期五接到一个资产核查的任务,时间紧,我对网页这一块的内容还不是很熟练,有些着急,在网上一搜,LayUI的模板,有很多好评和讲解,拿来一用,感觉很不错。 这个后台系统可以很快上手,界面部分不用操心太多,很多页面有实例,略微改动就可以直接使用。 写程序界面是个大问题,这下省事多了,虽然后期项目使用LayUI比较少,但做一些中小型的项目真的是很好的选择,最主要的就是快。..._layui后端模板
文章浏览阅读90次。常见数组_常见的数组