完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
本帖最后由 michael_llh 于 2016-9-1 19:12 编辑
makefile,这个是一个非常重要的学习内容,当我们的系统非常庞大的时候我们需要一个东西来管理我们的工程。就简单举个例子,在没有IDE的情况下,比如我们只写了一个hello.c然后我们进行编译,那么用gcc工具,只需要键入gcc hello.c就可以了,当然如果有两个文件的话比如说gcc hello.c world.c我们好像也觉得还好,但是如果现在有20个c文件,20个.h文件,这个时候我们就头疼了,这么多文件,假设我还是直接使用gcc的方式来编译的话,那一次就要键入20个文件名,这样的话就非常麻烦。这个时候就体现了make工具的强大之处,当然使用make工具,我们就需要用我们的makefile要定义编译内容了。 首先当我们第一次接触makefile的时候我们要记住一点,makefile的重要组成部分就是是三个,都是围绕着三个东西转。这三个东西分别是: 目标:这个很好理解,就是我们要生成的文件是什么,最终我们要达到的目的是什么。 依赖:这个也比较容易说明,就是说我要达成这个目标,我需要什么东西,我要做一顿可口的饭菜,那么我的依赖就是这些食材。 命令:命令就是我们要完成这个目标所要执行的内容,比如说我们上面的gcc hello.c这个命令。 我们简单举个例子: all:hello.c hello.h gcc hello.c 这里all就是我们的目标,但是这个目标比较特殊,就是当我们不指定生成的目标的时候,这个就是默认目标。目标后面跟着一个冒号,冒号后面就是我们的依赖,这里需要用到hello.c和hello.h这两个文件,下一行,记住,这个有个很重要的点需要注意,就是这里是一个Tab键,一定是一个Tab键,这里的Tab键在我们电脑键盘的左上角第三排第一个按键。不是空格!!不是空格!!不是空格!!是Tab是Tab是Tab,这里需要重点强调,一定要注意这问题。当我们写好这个文件之后保存。这里要注意另外一个东西,就是makefile的文件名,支持两种方式,一种就是全部小写makefile,另外一种就是第一个字母大写Makefile。 之后我们在makefile以及hello.c和hello.h,三个文件的同一个目录下面,使用make命令就可以直接得到我们的执行程序了,这里会生成一个a.out。 使用方法就是make + 目标(如果是第一个目标可以不加) %是makefile的通配符,代表的是一个或者几个字母,例如%.o就是代表所有以.o结尾的文件。 makefile当中有一个自动推导,也就是makefile当中的规则。所谓不以规矩不成方圆,当makefile去执行生成目标的时候我们设定相应的规则来让他执行。当makefile需要一个依赖来生成一个目标的时候,如果找不到这个依赖,那么他会自动去套用规则,看看是否可以通过规则来生成这个文件,然后再返回来去执行生成目标。 makefile当中的变量,可以执行定义,没有变量类型声明的,但是要注意一定变量是要有初始值的,不然会出错的。然后当我们调用这个变量的时候我们需要使用$(变量名)来使用这个变量。 介绍一个另外内容就是: 伪目标:伪目标是没有依赖的,也就是无条件执行。从名字我们也可以明白,伪目标,就是假的目标,之前我们说了目标,目标是我们真正要生成的东西,而伪目标则是用来无条件执行的一种实现方式,为什么我们需要这样的一个命令呢?比如说我们gcc a.c的时候我们会生成一个中间文件a.o,所以当我们一个工程当中,会产生很多的中间文件,那么我们需要一个功能来消除这些文件。那么伪目标就可以完成这一功能。 伪目标可以完成一个功能就是无条件的执行目标下面的命令。所以在命令上面我们就可以按照自己的想法进行书写。 我们常在命令前面加一个.PHONY来声明这个目标是伪目标。 makefile当中的合法文件名有两个,一个是全部小写的makefile或者是第一个字母大写,其余部分小写,也就是Makefile。 另外一个内容就是makefile的引用说明,和我们C语言当中一样,我们是使用#include来包含头文件,那么对于makefile也是一样的,用#include来包含另外一个makefile。在c语言当中我们知道#include的功能就是原地展开的内容,同样的在makefile也是一样的。 makefile当中用#号来表明注释的内容。 makefile默认情况下,makefile执行目标时,会把命令先打印出来,然后再去执行命令。这样很烦人,当我们的命令多的时候,我们只想知道执行结果,并不需要知道这个命令是什么。所以我们就把这个命令打印给他关掉,这个时候我们只需要在命令前面加上一个@就行。这个就叫做静默执行。 我们下面看下几个变量的赋值运算符: ?= :如果变量前面没有赋值过,那么这行就会赋值变量,如果赋值过了,那么这个赋值语句就不执行。变量没有赋值的本质意义就是这个变量没有定义过,因为在makefile当中只要有变量一定就会有定义,不会存在空的变量。makefile当中并不要求赋值预算符两边一定要有空格或者无空格。 += :用来给一个已经赋值过的变量接续赋值,就是在一定定义过的变量中加到这个变量后面,类似strcat(在shell、makefile这些文件当中可以认为所有的变量都是字符串,+=就是对字符串的接续加上新的内容)。有一个细节就是当我们默认使用+=的时候,两个字符串之间会默认加上一个空格。 := 和 = 两个是最简单的赋值方式。这个两个有一定的区别,我们具体看下: 比如说: A = abc B = $(A)def A = gh all : echo $(B) 上面的代码得到最终的结果是:ghdef,这里的“=”有点类似FPGA的编程语言Verilog当中的阻塞性语句,也就是所有的语句阻塞到最后一步执行。所以这里我们最后A = gh,所以最后是ghdef。 A := abc B := $(A)def A := gh all : echo $(B) 上面得到的结果的内容就是abcdef,所以这里我们就可以看出两者的区别。我们再看一个内容: A = abc B := $(A)def A = gh all : echo $(B) 同样这个得到的结果也是abcdef的内容。这里我们可以看出来得到那个结果,就是决定于哪一个的赋值方式。 makefile的环境变量: makefile当中用export导出的就是环境变量,一般我们的书写风格当中用大写来表示环境变量,比如说我们CC = gcc来代表这个编译工具。小写的是普通变量。环境变量就是类似于整个工程中所有的makefile都可以使用的变量,其实和我们c语言当中的全局变量是类似的。而小写的普通变量则只是在当前的makefile这个文件使用。因此当我们定义一个环境变量的时候要注意,不要和其他的makefile中的变量重名。 makefile当中的传参方式: make 参数 = 参数内容 默认的情况下我们传参的优先级是最高的,比如说我们上面定义了CC = gcc,我们可以直接使用make CC=ARM-cross-gcc,类似这样,这个时候CC的内容就是arm-cross-gcc而不是gcc了。 makefile当中使用的通配符: * :表示一个或者多个若干个字符 ?:表示的一个任意字符 [] :将[]中的字符拿出来和其余部分结合进行匹配 % 和 * 两个通配符是和类似,%一般只用于规则描述中,所以又称之为规则通配符。 自动变量: 预定义的特殊意义的符号,类似于C语言编译器中预制的那些宏一样。 为什么使用自动变量? 有些情况下,文件集合中文件非常多,描述的时候很麻烦,就出现了自动变量来解决这个问题。 常用的自动变量: $@:目标 $<:规则的依赖文件名 $^:所有的依赖 |
|
相关推荐
6 个讨论
|
|
|
|
|
|
|
|
讲的很不错啊,新手请多多指教
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
只有小组成员才能发言,加入小组>>
「含关键代码」基于AM3352/AM3354/AM3359的Linux开发案例分享
4868 浏览 0 评论
87358 浏览 0 评论
【高手问答】如何做到精通linux技术?资深工程师带你突破难点
4680 浏览 2 评论
3567 浏览 2 评论
解读Linux :先从创建一个文件夹用来存放jdk压缩文件开始
2453 浏览 0 评论
1952浏览 3评论
这是i.mx6ull的关于usb的宏定义,能解释下这些宏定义的意思
1320浏览 1评论
1231浏览 1评论
求解:aarch64交叉编译工具已经安装成功,环境变量已经配置,怎么将系统架构切换为ARM的架构
1296浏览 0评论
电脑和虚拟机可以互ping,电脑和开发板也可以互ping,但是虚拟机和开发板ping不通是什么原因
1213浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-25 02:49 , Processed in 1.038582 second(s), Total 50, Slave 43 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号