关于make及makefile的工作笔记
之前一直是用java的,最近工作中需要在Linux中写一个C++程序,之前的写法很不规范,只有一个CPP。记录一下关于makefile的相关知识
想要完整的了解相关内容,推荐看这本书《程序员的自我修养--链接、装载与库》
想要快速的了解可以看这个大神写的博客https://seisman.github.io/how-to-write-makefile/overview.html
写的比较早了,可以挑着看
为什么使用make和makefile
在linux系统中make是一个非常重要的编译命令,不管是自己进行项目开发还是安装应用软件,我们都经常要用到make或makeinstall。利用make工具,我们可以将大型的开发项目分解成为多个更易于管理的模块,一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为makefile就像一个Shell脚本一样,其中也可以执行操作系统的命令。makefile 带来的好处就是“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
make
1.make的工作原理
当make 命令被执行时,它会扫描当前目录下Makefile或makefile文件找到目标以及其依赖。如果这些依赖自身也是目标,继续为这些依赖扫描Makefile 建立其依赖关系,然后编译它们。一旦主依赖编译之后,然后就编译主目标,假设你对某个源文件进行了修改,你再次执行make 命令,它将只编译与该源文件相关的目标文件,因此,编译完最终的可执行文件节省了大量的时间。
## 2.make命令的参数
-f:指定“makefile”文件;
-i:忽略命令执行返回的出错信息;
-s:沉默模式,在执行之前不输出相应的命令行信息;
-r:禁止使用build-in规则;
-n:非执行模式,输出所有执行命令,但并不执行;
-t:更新目标文件;
-q:make操作将根据目标文件是否已经更新返回"0"或非"0"的状态信息;
-p:输出所有宏定义和目标文件描述;
-d:Debug模式,输出有关文件和检测时间的详细信息。
-C dir:在读取makefile 之前改变到指定的目录dir;
-I dir:当包含其他makefile文件时,利用该选项指定搜索目录;
-h:help文挡,显示所有的make选项;
-w:在处理makefile之前和之后,都显示工作目录。
3.make命令的隐藏过程
这部分在上面那本书里有很详细的解释,但是有好几百页,想了解的话自己看吧。
1.预编译
预编译过程相当于执行
gcc -E hello_world.c -o hello_world.i
预编译过程主要处理以#开头的预处理指令,#include #define等,处理过程如下:
1 将所有#define删除,并展开所有宏定义
2 处理所有条件预编译指令#if #ifdef #elif #else #endif等
3 处理#include 预编译指令,将包含的文件插入到预编译指令的位置(递归进行,所包含的文件可能包含其他文件)
4 删除所有注释// /* */
5 添加行号和文件名标识,如:#2 hello_kitty.c 2 ,用于编译时编译器产生调试信息和编译时产生的错误和警告时能显示行号。
6 保留说有的#pragma编译器指令
经过预编译的.i文件,不包含任何宏定义,并且所包含的文件也被插入进来。
make命令的隐藏过程
1.预编译
预编译过程相当于执行
gcc -E hello_world.c -o hello_world.i
预编译过程主要处理以#开头的预处理指令,#include #define等,处理过程如下:
1 将所有#define删除,并展开所有宏定义
2 处理所有条件预编译指令#if #ifdef #elif #else #endif等
3 处理#include 预编译指令,将包含的文件插入到预编译指令的位置(递归进行,所包含的文件可能包含其他文件)
4 删除所有注释// /* */
5 添加行号和文件名标识,如:#2 hello_kitty.c 2 ,用于编译时编译器产生调试信息和编译时产生的错误和警告时能显示行号。
6 保留说有的#pragma编译器指令
经过预编译的.i文件,不包含任何宏定义,并且所包含的文件也被插入进来。
2.编译
编译过程就是将预编译产生的.i文件经过一系列的词法分析,语法分析,语义分析,中间代码生成,目标代码生成与优化。
编译原理
3.汇编
汇编器将汇编代码转换成成机器指令,每一条汇编语句对应一条或几条机器指令,生成目标文件。
4.链接(模块拼装)
将库文件与目标文件链接成可执行文件的过程。
概念
动态链接库:是一种不可执行的二进制程序文件,它允许程序共享执行特殊任务所必需的代码和其他资源。Windows平台上动态链接库的后缀名是”.dll”,Linux平台上的后缀名是“.so”。Linux上动态库一般是libxxx.so;相对于静态函数库,动态函数库在编译的时候并没有被编译进目标代码中,你的程序执行到相关函数时才调用该函数库里的相应函数,因此动态函数库所产生的可执行文件比较小。由于函数库没有被整合进你的程序,而是程序运行时动态的申请并调用,所以程序的运行环境中必须提供相应的库。动态函数库的改变并不影响你的程序,所以动态函数库的升级比较方便。
静态链接库:这类库的名字一般是libxxx.a;利用静态函数库编译成的文件比较大,因为整个函数库的所有数据都会被整合进目标代码中,他的优点就显而易见了,即编译后的执行程序不需要外部的函数库支持,因为所有使用的函数都已经被编译进去了。当然这也会成为他的缺点,因为如果静态函数库改变了,那么你的程序必须重新编译。
人们将每个源代码模块独立的编译,然后按照需要将它们组装起来,这个组装模块的过程就是链接
连接过程主要包括了地址空间分配、符号决议和重定位等
步骤:
1、 合并段表:将多个二进制可重定位文件中的段信息整合放到一个文件中
2、 调整段偏移:段表经过合并之后大小发生了变化,所以地址需要适当的偏移
3、 合并符号表:将多个二进制可重定位文件中的符号整合到一个文件中
4、 完成符号的重定位:连接器把每个符号定义与一个虚拟地址联系起来,然后修改所有对这些符号的引用,使得它们指向这个存储位置,从而重定位这些节。
makefile
包含内容:
显式规则。显式规则说明了,如何生成一个或多的的目标文件。这是由Makefile的书写者明显指出,要生成的文件,文件的依赖文件,生成的命令。
隐晦规则。由于我们的make有自动推导的功能,所以隐晦的规则可以让我们比较粗糙地简略地书写Makefile,这是由make所支持的。
变量的定义。在Makefile中我们要定义一系列的变量,变量一般都是字符串,这个有点你C语言中的宏,当Makefile被执行时,其中的变量都会被扩展到相应的引用位置上。
文件指示。其包括了三个部分,一个是在一个Makefile中引用另一个Makefile,就像C语言中的include一样;另一个是指根据某些情况指定Makefile中的有效部分,就像C语言中的预编译#if一样;还有就是定义一个多行的命令。有关这一部分的内容,我会在后续的部分中讲述。
注释。Makefile中只有行注释,和UNIX的Shell脚本一样,其注释是用“#”字符,这个就像C/C++中的“//”一样。如果你要在你的Makefile中使用“#”字符,可以用反斜框进行转义,如:“/#”。
还有模式规则、自动化变量、检查规则等等很多的内容,由于不是每次都要用,就不再写了。
大概流程:
- 执行make指令,在当前目录下找到makefile文件
- 进入makefile文件找到最终目标
- 逐层查找最终目标的依赖
- 编译文件
- 链接可执行文件及库文件生成一个最终的可执行文件
- 删除中间生成的那些可执行文件
写的文件不能放出来,可以参考一下这个:https://blog.csdn.net/X_BoLuoPi/article/details/106246779
还有一个常用模板
https://www.cnblogs.com/cyyljw/p/8137015.html
关于make及makefile的工作笔记的更多相关文章
- Makefile的学习笔记
Makefile的学习笔记 标签: makefilewildcard扩展includeshellfile 2012-01-03 00:07 9586人阅读 评论(2) 收藏 举报 分类: Linux ...
- Makefile速查笔记
Makefile速查笔记 Makefile中的几个调试方法 一. 使用 info/warning/error 增加调试信息 a. $(info "some text")打印 &qu ...
- 2016年第2周读书笔记与工作笔记 scrollIntoView()与datalist元素
这一周主要是看了html5网页开发实例与javascript 高级程序设计,供以后翻阅查找. html5网页开发实例第1章与第二章的2.1部分: 第1章内容: html5在w3c的发展史. 浏览器的 ...
- javascript - 工作笔记 (事件四)
在javascript - 工作笔记 (事件绑定二)篇中,我将事件的方法做了简单的包装, JavaScript Code 12345 yx.bind(item, "click&quo ...
- 工作笔记3.手把手教你搭建SSH(struts2+hibernate+spring)环境
上文中我们介绍<工作笔记2.软件开发经常使用工具> 从今天開始本文将教大家怎样进行开发?本文以搭建SSH(struts2+hibernate+spring)框架为例,共分为3步: 1)3个 ...
- Sencha Touch2 工作笔记
Sencha Touch2 工作笔记 Ext.dataview.List activate( this, newActiveItem, oldActiveItem, eOpts ) Fires whe ...
- 工作笔记5.JAVA图片验证码
本文主要内容为:利用JAVA图片制作验证码. 设计思路: 1.拷贝AuthImageServlet.class图片验证码 2.配置web.xml 3.JSP中,调用封装好的AuthImageServl ...
- 读书笔记——《MySQL DBA 工作笔记》
关于前言 作者在前言中提出的一些观点很具有参考价值, 梳理完整的知识体系 这是每一个技术流都应该追逐的,完整的知识体系能够使我们对知识的掌握更加全面,而不仅仅局限于点 建立技术连接的思维,面对需求,永 ...
- 《工作笔记:移动web页面前端开发总结》
工作笔记:移动web页面前端开发总结 移动web在当今的发展速度是一日千里,作为移动领域的门外汉,在这段时间的接触后,发现前端开发这一块做一个小小的总结. 1.四大浏览器内核 1.Trident (I ...
随机推荐
- 前端学习(九):CSS基础
进击のpython ***** 前端学习--CSS基础 CSS的样式可以写在哪呢?其实CSS的样式插入式十分灵活的 按照插入的形势来看,可以分为三种情况 而接下来就对这三种情况进行简单的讨论 内嵌式 ...
- 缓存利器、Lua模块下的共享内存
上一节讲到了worker进程的共享内存,它利用丰富的指令使数据的缓存操作变得非常简单,但它也存在一些缺点. 1.worker进程之间会有锁竞争,在高并发的情况下会增加性能开销.2.只支持Lua布尔值. ...
- python迭代器和装饰器
一.迭代器 1.迭代器协议:对象必须提供一个__next__()方法,执行该方法要么返回迭代中的下一个对象,要么引起一个StopIteration异常以终止迭代,迭代只能向后进行不能往前回退 2.可迭 ...
- 21天速成python电子书pdf|超级厉害的书内附百度云链接可直接下载|
python的学习书籍小编看过很多,但是这本<21天学通python>真的是堪称极品!本书的作者团队成员为一线开发工程师.资深编程专家或专业培训师,在编程开发方面有着丰富的经验,并已出版过 ...
- 如何使用k3OS和Argo进行自动化边缘部署?
本文转自边缘计算k3s社区 前 言 随着Kubernetes生态系统的发展,新的技术正在被开发出来,以实现更广泛的应用和用例.边缘计算的发展推动了对其中一些技术的需求,以实现将Kubernetes部署 ...
- JS中Math.random()的使用和扩展
Math.random()方法返回大于等于 0 小于 1 的一个随机数.对于某些站点来说,这个方法非常实用,因为可以利用它来随机显示一些名人名言和新闻事件. 在连续整数中取得一个随机数 值 = Mat ...
- PHP libxml_clear_errors() 函数
定义和用法 libxml_clear_errors() 函数清空 libxml 错误缓冲. 语法 libxml_clear_errors() 实例 <?phplibxml_clear_error ...
- PHP zip_entry_read() 函数
定义和用法 zip_entry_read() 函数从打开的 zip 档案中获取内容.高佣联盟 www.cgewang.com 如果成功,该函数则返回项目的内容.如果失败,则返回 FALSE. 语法 z ...
- luogu P2607 [ZJOI2008]骑士 tarjan dp
LINK:骑士 本来是不打算写的 发现这道题在tarjan的时候有一个坑点 所以写出来记录一下. 可以发现图可能是不连通的 且一个连通块中是一个奇环树. 做法:类似tarjan找割点 然后把环给拉出来 ...
- 服务没有报告任何错误。 请键入 NET HELPMSG 3534 以获得更多的帮助。
解决: 删除data文件夹 然后按顺序执行: sc delete mysql mysqld --initialize-insecure mysqld -install mysql net start ...