初始Mkaefile
初识MakefIle
在学习Linux过程中,我越发的觉得Linux系统给了使用者更大的自由,同时也就增加了学习的成本。在gcc下去调试代码,没有了熟悉的VS,没有的人性话的错误提示(当然Makefile是有错误提示和警告的),也没有一键编译。全得自己来,但是在这个过程中,你将会熟悉系统的整个编译过程,以及自己去写编译文件的那种快感。今天我将不去重点介绍编译的过程,重点在GNU的Makefile怎样写,算是自己的一个总结。
在此我先说一下,我的Makefile是在https://blog.csdn.net/haoel/article/details/2886陈皓《跟我一起写Makefile》学到的,里面讲的很是全面有兴趣的话可以认真的去读一遍(内容比较多)。
从认为,Makefile是为生成,编译好的、可执行的文件(make只是一个根据指定的Shell命令进行构建的工具),可以用来调试,也可以直接运行。有人可能要说用gcc自己写命令编译不是更好吗?但是如果一个项目有成百上千个.c .h文件怎么整。
从最简单的说起,一般情况下我们执行Makefile文件直接make就可以了(有些人会进行一些骚操作这就不说了),会生成许多 .o文件最终会有一个或多个可执行文件。
咱们还是直接从例子中去体会吧!
SRC = $(wildcard *.c)
OBJ = $(patsubst %.c,%.o,$(SRC))
target = SendMsg
mode = -g
CC := gcc
$(target):$(OBJ)
$(CC) $(CFLAGS) $^ -o $(target)
.PHONY:
clean:
rm -rf *.o $(target)
上面的代码块就是一个简单的Makefile,我们一句一句的分析他的语法,等到末尾基本上简单的Makefile也就会写了,再去系统的学习Makefile也比较容易(请保持耐心):
整体的看最多的就是赋值符号,细心点会发现有两种复制方式 “=”和“:=”,这两个都是赋值符号,符号左边是变量,右面是所要赋值的内容;
"="是最基本的赋值,如同我们c/c++语言中的赋值一样;
":="表示覆盖赋值,也就是同一个变量在如果用":="赋值,则会覆盖掉之前的内容。
开始看第一句:
SRC = $(wildcard *.c)
之前说过“=”左边是变量,则"SRC"就是变量,想来我不用解释变量是什么意思吧。“=”右边是所要赋值的内容。
$(wildcard *.c)
在这内容里面"$"是函数的调用符,也是变量的调用符。就是说你调用一个变量或一个函数时前面要加上"$"来作为标志,表示这是个函数,或者这是个变量,并且里面的内容需要用括号括起来,括号可以用"{}"也可以用"()"但是最好统一一下不要混用,显得杂乱。(如果对指针比较熟悉的话很快就应该想到“$”跟指针中的“*”用法很类似,为了提取出对方的内容所要加的标志符,如果对指针不熟悉可以忽略这句话)。
因此上面那句话也可以这样写 ${wildcard *.c};
我们分析一下 $(wildcard *.c) 括号里面的内容“*”是通配符的一种,这里表示所有的以".c"结尾的文件,如果是"*.o"那就是所有的以“.o”结尾的文。“wildcard”是Makefile中的函数,Makefile中是有自己内置函数就像我们c/c++中的库函数一样。在这里“wildcard”函数的作用是来获取工作目录下的所有的 “*.c” 文件列表。Makefile中不止这一个函数,还有很多可以自己去看去实践。
现在整体看“SRC = $(wildcard *.c)”这句话的意思就是,取出当前目录下所有的".c"文件并且将此赋给 SRC,那么 SRC 将会代表此目录下的所有 “.c”文件。
第二句
OBJ = $(patsubst %.c,%.o,$(SRC))
同样定义“OBJ”变量,调用“patsubst”函数,函数参数为“%.c”,“%.o”,“$(SRC)”;(函数中有多个参数时,以逗号隔开);
“%”也是一中通配符:非空长度任意的非空字符串。(“%”与“*”是有区别的)
“patsubst”函数的作用是将变量“SRC”中所用“.c”文件用“.o”替代。因此OBJ就是很多将后缀为".c"变成“.o”的文件集合;
第三、四、五句(同类型)
target = SendMsg
mode = -g
CC := gcc
定义target变量名字角SendMsg;
定义“mode”变量且赋值为“-g”;
定义“CC”变量且赋值为"gcc"
第六、七句
$(target):$(OBJ)
$(CC) $(CFLAGS) $^ -o $(target)
这段代码是核心,它符合Makefile 的编译规则如下:
target ... : prerequisites ...
command
...
...
target是目标文件(可以不止一个),prerequisites是目标的依赖文件(可以不止一个),(command)生成目标文件所需要执行的命令。
“目标文件”:即最终生成的可执行的文件;
“目标依赖文件”:即生成目标文件所需要的文件;
“命令”:即处依赖文件到目标文件的过程。注意命令需要以开头必须是table,这是命令的标识。
现在回过头去看我们的程序,五六句:
$(target),表示所要生成的目标文件;
$(OBJ),表示生成目标文件所需的依赖文件;
$(CC) $(mode) $^ -o $(target),处理生成目标的命令;
{命令中"$^"是自动化变量终端的一种,表示所有依赖文件的集合,如果有重复的依赖文件,则去掉重复的依赖文件(自动化变量:会将模式变量一次取出的一种机制变量,自动化变量有好几个,可以去详细解读)};
重点:在Makefile中是以时间戳为参考标准去更新文件的,假若依赖文件中任意一个文件比目标文件的时间戳新,则再次编译目标文件,直到目标文件的时间戳为最新为止。
则五六句代码的理解就是:
以OBJ为依赖文件生成target文件,命令规则是“gcc -g $^ -o target”(假设懂 gcc 的基本语法)。
八、九、十句
.PHONY:
clean:
rm -rf *.o $(target)
这个小模块的目的是为了,清除所有的已经编译后的目标文件;在调试时改变更改程序后需要重新编译,那么将会生成新的编译文件;为了比避免出错,一般先会清除先前的编译文件,在重新生成编译文件。
在这个模块中“clean”时一条伪命令,为什么这样说,是因为它不会再编译的过程中执行,只有使用语句 “make clean”时才会执行此命令。其中“.PHONY”是伪命令的标识,可以选择不写。
最后“rm -rf *.o $(target)”,想来应该也都清楚了,清除所有以“.o”和“target”文件。
至此整个Makefile结束。此段程序虽然简短但是五脏俱全,其中涉及很多Makefile的知识点,可以由此去逐点击破,对Makefile做个详细的了解。
如有问题请指出,我修改……一起进步!
初始Mkaefile的更多相关文章
- 2DToolkit官方文档中文版打地鼠教程(一):初始设置
这是2DToolkit官方文档中 Whack a Mole 打地鼠教程的译文,为了减少文中过多重复操作的翻译,以及一些无必要的句子,这里我假设你有Unity的基础知识(例如了解如何新建Sprite等) ...
- CSharpGL(38)带初始数据创建Vertex Buffer Object的情形汇总
CSharpGL(38)带初始数据创建Vertex Buffer Object的情形汇总 开始 总的来说,OpenGL应用开发者会遇到为如下三种数据创建Vertex Buffer Object的情形: ...
- ArrayList、Vector、HashMap、HashSet的默认初始容量、加载因子、扩容增量
当底层实现涉及到扩容时,容器或重新分配一段更大的连续内存(如果是离散分配则不需要重新分配,离散分配都是插入新元素时动态分配内存),要将容器原来的数据全部复制到新的内存上,这无疑使效率大大降低. 加载因 ...
- linux系统下使用xampp 丢失mysql root密码【xampp的初始密码为空】
如果在ubuntu 下面 使用xampp这个集成开发环境,却忘记mysql密码. 注:刚安装好的xampp的Mysql初始密码是空... 找回密码的步骤如下: 1.停止mysql服务器 sudo /o ...
- python基础之初始python
初始python之基础一 一.Python 介绍 1.python的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,吉多·范罗苏姆为了在阿姆斯特丹打发时间,决心开发 ...
- openfire 初始密码
openfire 初始密码 mssql2014 进入数据库,找到 ofUser 表 ,将密码字段对应的密文替换为下面的内容,则密码就是 admin ecbd03623cd819c48718db1b27 ...
- Bash 什么时候会给 HOME 赋初始值
今天无意发现下面这个表现: $ env -i bash -c cd bash: line 0: cd: HOME not set $ env -i bash -c 'echo $HOME' 这表明了 ...
- Holt-Winters原理和初始值的确定
关于模型 (来自以下PPT,从第4页开始) 关于初始值: 以下文档给出了三个模型的初始值计算的思路. 大致思路如下,建立一个p阶移动平均模型,估计出参数即为初始值,具体的根据三种不同的模型,有 ...
- 关于int,integer初始值问题
随机推荐
- shell 基础(二)变量
1. shell变量的定义 1)Shell 支持以下三种定义变量的方式: variable=value variable='value' variable="value" 特点 1 ...
- GiBbook实用配置以及插件
GitBook可以在您的计算机上用于构建本地书籍,,可以本地预览 安装gitbook 环境要求: 安装GitBook,您的系统需要安装NodeJS(推荐v4.0.0及以上版本) NodeJS下载地址 ...
- 【CH4302】Interval GCD
题目大意:给定一个长度为 N 的序列,M 个操作,支持区间加,区间查询最大公约数. 题解: 先来看一个子问题,若是单点修改,区间最大公约数,则可以发现,每次修改最多改变 \(O(logn)\) 个答案 ...
- 【gdoi2018 day2】第二题 滑稽子图(subgraph)(性质DP+多项式)
题目大意 [gdoi2018 day2]第二题 滑稽子图(subgraph) 给你一颗树\(T\),以及一个常数\(K\),对于\(T\)的点集\(V\)的子集\(S\). 定义\(f(S)\)为点集 ...
- selenium技术博客
1.java+selenium+详细的api说明和seleniumGrid使用,缺点是代码不够好看. http://www.cnblogs.com/yytesting/p/5714175.html
- 利用DOS命令窗口进行Mail通信(二)
一:SMTP协议(对邮件进行发送) <SP>代表空格,<CRLF>代表回车和换行 SMTP命令格式 说明 ehlo<SP><domain><CRL ...
- Mac新手必看教程—让你离熟练操作mac只差十分钟
本文收录于:风云社区(提供各类mac软件资源下载) 本文源自:什么值得买 无论轻薄办公本.还是赶超台式性能的游戏本,关注#笔记本攻略#栏目,解决笔记本电脑从选购到使用的各种问题. 引子 大部分用户接触 ...
- androidstudio上传代码到git上
1.首先通过git --bare init 在服务端创建好了一个git仓库:假设git仓库在服务端的地址为:/user/lyh/project/test.git 2.androidstudio上点击V ...
- HDU 5965(三行扫雷 dp)
题意是在一个 3 行 n 列的图上进行扫雷,中间一行没有雷,且中间一行的每一格都会显示周围的雷数,问根据已知的雷数在上下两行设置地雷的方法数. 分析知每一列所填雷数的和与周围的雷数有关,但每列具体的填 ...
- 新年 flag
在浮躁的年代本不该如此贪多,奈何鸭梨山大...温故知新吧 GO中文社区 深入学习一两门新的编程语言: -Go编程基础 -Go Web基础 -Go名库讲解 rustlang 中文文档 知乎板块 GO 知 ...