什么是makefile?

或许很多 的程序员都不知道这个东西,因为那些 的 都为你做了这个工作,但是一个好的和 的程序员, 还是要懂。这就好像现在有这么多的 的编辑器,但如果你想成为一个专业人士,你还是要了解 的标识的含义。特别在 下的软件编译,你就不能不自己写 了,「会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力」。因为 关系到了整个工程的编译规则。

上期「用GCC写个库给你玩」已经详细介绍了GCC编译链接的过程,那么接下来就聊聊makefile艺术。

makefile介绍

命令执行时,需要一个 文件,以告诉 命令需要怎么样的去编译和链接程序。

的规则是:

1.如果这个工程没有编译过,那么我们的所有 C 文件都要编译并被链接。

2.如果这个工程的某几个 C 文件被修改,那么我们只编译被修改的 C 文件,并链接目标程序。

3.如果这个工程的头文件被改变了,那么我们需要编译引用了这几个头文件的C文件,并链接目标程序。

只要我们的 写得够好,所有的这一切,我们只用一个 命令就可以完成, 命令会自动智能地根据当前的文件修改的情况来确定哪些文件需要重编译,从而自己编译所需要的文件和链接目标程序。

makefile的规则

在讲述这个makefile之前,还是让我们先来粗略地看一看makefile的规则。

「target」

可以是一个(目标文件),也可以是一个执行文件。

「prerequisites」

生成该所依赖的文件和/或

「command」

该要执行的命令(任意的命令)

一个示例

首先还是使用上期「编译链接,你还不会用GCC生成标准库」的测试代码

那么我们需要通过 将示例代码编译生成目标文件.

第一个版本

执行命令看一下效果,很

思考:为什么写这么复杂,先生成再生成

直接说答案:「方便编译链接」

小实验:修改里面的内容,随便按一个空格,然后保存退出再执行命令

结果很明显:只对进行了编译,省略了没有必要的编译步骤

为什么会这样?那就要说说 是如何工作的

make是如何工作的

在默认的方式下,也就是我们只输入 命令。那么,

make会在当前目录下找名字叫的文件。

如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到“app”这个文件,并把这个文件作为最终的目标文件。

如果app文件不存在,或是app所依赖的后面的 文件的文件修改时间要比 这个文件新,那么,他就会执行后面所定义的命令来生成 这个文件,节省了没有必要的编译步骤。

如果 所依赖的 文件也不存在,那么make会在当前文件中找目标为 文件的依赖性,如果找到则再根据那一个规则生成 文件。(这有点像一个堆栈的过程)

当然,你的C文件和H文件是存在的啦,于是make会生成 文件,然后再用 文件生成make的终极任务,也就是执行文件 了。

这就是整个的依赖性,会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。

上述还只是简单的,属于「显式规则」,那么为了优化我们介绍「隐式规则」

makefile中使用变量

在中我们要定义一系列的变量,变量一般都是字符串,这个有点「类似C语言中的宏」,当被执行时,其中的变量都会被扩展到相应的引用位置上,可以直接把变量当成C语言中的宏理解。

Makefile中变量有四种定义(赋值)方式:

1,简单赋值( := ) 编程语言中常规理解的赋值方式,只对当前语句的变量有效(推荐使用)

2,递归赋值( = )赋值语句可能影响多个变量,所有目标变量相关的其他变量都受影响

3,条件赋值( ?= )如果变量未定义,则使用符号中的值定义变量。如果该变量已经赋值,则该赋值语句无效。

4,追加赋值( += )原变量用空格隔开的方式追加一个新值

使用变量非常简单,变量在声明时需要给予初值,而在使用时,需要给在变量名前加上 符号,但最好用小括号 或是大括号 把变量给包括起来。

在隐含规则中的命令中,基本上都是使用了一些预先设置的变量。你可以在你的makefile中改变这些变量的值,或是在make的命令行中传入这些值,或是在你的环境变量中设置这些值

命令的变量命令参数的变量隐晦规则

如果我们想定义一系列比较类似的文件,我们很自然地就想起使用通配符。

通配符

GNU的make很强大,它可以自动推导文件以及文件依赖关系后面的命令

例如:

只要make看到一个 文件,它就会自动的把 文件加在依赖关系中,如果make找到一个 ,那么 main.cmain.o` 的依赖文件。

有.o文件没有.c文件,makefile会自动推导生成.o文件

除了通配符,makefile还提供了自动推导的自动变量

自动变量

由此第二个版本出来了

第二个版本

已经很精简了是不是

伪指令

在第一第二个版本的makefile里面我都有写这个规则,并且在make的时候并没有执行这个规则。其实 表示 是一个“伪目标”,并不在make的执行命令中,只有指定才会执行例如:

比较健壮的伪指令写法是:

在 命令前面加了一个小减号的意思就是,也许某些文件出现问题,但不要管,继续做后面的事.

函数

在中可以使用函数来处理变量,从而让我们的命令或是规则更为的灵活和具有智能。下面介绍三个最常用的函数

文本处理函数

「wildcard」

功能:该函数被展开为已经存在的、使用空格分开的、匹配此模式的所有文件列表。

「举例」

获取工作目录下的所有文件列表

字符串替换函数

「patsubst」

功能:查找 中的单词(单词以“空格”、“Tab”或“回车”“换行”分隔)是否符合模式 ,如果匹配的话,则以 替换。

「举例」

shell函数

shell函数也不像其它的函数。顾名思义,它的参数应该就是操作系统Shell的命令。

「举例」

将当前目录及其子目录下所有文件后缀为「.c」的文件以空格为限赋值给 SRC

最终版本

先总结一下前面都讲了些什么

Makefile里主要包含了五个东西:「显式规则」、「隐晦规则」、「变量定义」、「函数」、「注释」。

显式规则。显式规则说明了如何生成一个或多个目标文件。这是由Makefile的书写者明显指出要生成的文件、文件的依赖文件和生成的命令。

隐晦规则。由于我们的make有自动推导的功能,所以隐晦的规则可以让我们比较简略地书写 Makefile,这是由make所支持的。

变量的定义。在Makefile中我们要定义一系列的变量,变量一般都是字符串,这个有点像你C语言中的宏,当Makefile被执行时,其中的变量都会被扩展到相应的引用位置上。

函数。其包主要介绍了三个函数,一个是提取工作目录下的所有.c文件列表,另外一个就是将提取的.c列表转换成.o列表,最后就是shell函数,可以执行任何shell操作.

注释。Makefile中只有行注释,和UNIX的Shell脚本一样,其注释是用 字符,这个就像C/C++中的 一样。如果你要在你的Makefile中使用 字符,可以用反斜杠进行转义,如: 。

然后「最终版本确定」,可以作为「模板」使用

多目录makefile

作为一个健壮的makefile怎么能将所有代码放在一个文件夹下面呢?优秀的工程师都是分模块标准放置

先看一下目录树形结构

示例程序的Makefile分为3类:

顶层目录的Makefile

顶层目录的Makefile.build

各级子目录的Makefile

「各级子目录的Makefile」

这个是最简单的,只需要将所有.o文件或者子级目录添加即可,例如

sub文件夹下的 makefile

「顶层目录的Makefile」

它除了定义obj-y来指定根目录下要编进程序去的文件、子目录外,主要是定义工具链、编译参数

「顶层目录的Makefile.build」

这是最复杂的部分,它的功能就是把某个目录及它的所有子目录中、需要编进程序去的文件都编译出来,打包为.o文件.

这个也不好演示,但都是模板,改一些参数就可以直接用,后台发送关键字获取「测试源码」和「makefile文件」

关键字【俄罗斯方块】

End

作者:梦凡

梦想在,终不凡~

你们的在看就是对我最大的肯定,

点个在看好吗~

编程学习基地

常回基地看看

makefile传字符串给c语言,makefile终极奥义相关推荐

  1. C语言makefile文件详解,makefile讲解

    仅供自己学习使用 一.Makefile介绍 Makefile 或 makefile: 告诉make维护一个大型程序, 该做什么.Makefile说明了组成程序的各模块间的相互 关系及更新模块时必须进行 ...

  2. Makefile编写及一个简单的Makefile架构实现

    Makefile编写及一个简单的Makefile架构实现 Makefile常用命令 GCC/G++常用编译参数 简单Makefile框架实现 使用CMake构建项目 Makefile常用命令 make ...

  3. c语言数据库的连接字符串函数,C语言strcat()函数:连接字符串

    头文件:#include strcat() 函数用来连接字符串,其原型为: char *strcat(char *dest, const char *src); [参数]dest 为目的字符串指针,s ...

  4. 华为机考HJ4字符串分隔C语言题解

    华为机考HJ4字符串分隔C语言题解 好家伙,今天的while循环检测文件末尾又好使了. 把白给打在公屏上. 主要思路就是求余的花样使用. 首先把字符串数组里的内容全部放入新的数组. 新的数组每满八个就 ...

  5. java语言中json转换,JSON字符串和JAVA语言对象的相互转换教程

    本文主要向大家介绍了JSON字符串和JAVA语言对象的相互转换教程,通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助. 一:字符串转换为对象:使用JSON.parse()方法 var st ...

  6. 飞鸽传书2007程序语言的面向对象最后会成自然语言吗?

    飞鸽传书2007程序语言的面向对象最后会成自然语言吗?程序语言的向自然语言靠拢,自底向上还是自顶向下? 飞鸽传书2007绿色版: http://www.freeeim.com/ipmsg/ipmsg_ ...

  7. linux内核makefile详解,linux kernel编译Makefile和Kconfig,make menuconfig详解

    Sam需要看看2.6 kernel中USB Mouse的代码.顺便谈谈Kernel中Makefile和Kconfig文件的关系以及配合使用. 背景知识: 背景知识一:Kconfig介绍: 在#make ...

  8. c 字符串数组_C语言探索之旅 | 第二部分第四课:字符串

    内容简介 前言 字符类型 显示字符 字符串其实就是字符的数组 字符串的创建和初始化 从 scanf 函数取得一个字符串 操纵字符串的一些常用函数 总结 第二部分第五课预告 1. 前言 上一课 C语言探 ...

  9. 【数据结构、字符串、C语言】统计字符串中不同字符出现的频度

    [数据结构.字符串.C语言]统计字符串中不同字符出现的频度 问题描述 完整代码 问题描述 写一个算法统计在输入字符串中各个不同字符出现的频度并打印(字符串中的合法字符为A-Z这26个字母和0-9这10 ...

最新文章

  1. INDEX FULL SCAN和INDEX FAST FULL SCAN区别
  2. java for循环_愉快地学Java语言:第五章 循环
  3. For the king:出色的冒险,失败的角色扮演
  4. django(7)modelform操作及验证、ajax操作普通表单数据提交、文件上传、富文本框基本使用...
  5. 王道操作系统考研笔记——2.1.8 调度算法的评价指标
  6. 【剑指offer】面试题03:数组中重复的数字(java)
  7. pip 换清华源 更新所有库 windows
  8. 【最短路】Floyd算法:2020蓝桥最短路
  9. Julia: Dates =DateFormat, format,parse.......
  10. 《概率论与数理统计》之常见概率分布
  11. 经济周期的定义、阶段及特点-宏观经济指标和政策
  12. 低通滤波器转带通滤波器公式由来_无源滤波器应用或电路中的带通滤波器原理...
  13. Linux系统怎么复制文件夹下的全部文件到另外文件夹?...
  14. 内网渗透篇-信息收集
  15. vue第三天笔记05——使用vue-cli脚手架工具创建一个项目
  16. VPS与云服务器应该如何选择?
  17. 移动磁盘已用空间0字节要如何办啊
  18. 自己写的wow菜鸟指南
  19. Python实践4-守护线程
  20. 富途韦莱韬悦脉脉《2022年股权激励研究报告》全文解读

热门文章

  1. java联机_Java实现简易联网坦克对战小游戏
  2. 8个好玩又实用的神奇网站,帮你打开新世界大门!
  3. tuned-adm性能优化的配置文件详解
  4. 软件相关技术及其在国内的应用
  5. 调用函数计算器的代码
  6. 基于pyspark的个性化电商广告推荐系统
  7. Java 如何模拟真正的并发请求?
  8. request java获取参数body_@RequestBody参数已经被读取,究竟是何原因?
  9. 赛门铁克公司的极限之旅
  10. 助力智慧医疗,解析i.MX8MM在麻醉系统中的应用方案