首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

Makefile文件:Makefile介绍

  • 23-09-22 01:23
  • 2965
  • 5624
blog.csdn.net

本文介绍Makefile的一些基本概念以及简单的用法。本文所用的编译器是Hightec tricore v4.9.1.0。

文章目录

  • 1 Makefile的作用
  • 2 Makefile的规则
  • 3 一个简单的Makefile
    • 3.1 帮助文档中的例子
    • 3.2 例1:一个简单的Makefile
  • 4 make是如何执行Makefile的
    • 4.1 默认目标
    • 4.2 例2:使用默认目标
  • 5 使用变量让Makefile更简洁
    • 5.1 变量的简单用法
    • 5.2 例3:在Makefile中使用变量
  • 6 通过make推导规则
    • 6.1 隐式规则
    • 6.2 例4:省略源文件
  • 7 另一种风格的Makefile
  • 8 清空路径的规则
  • 9 总结

1 Makefile的作用

简单来说,Makefile的作用是告诉make如何编译和链接程序。我们在Eclipse界面中写好代码后,会点击一下rebuild按钮来将工程重新编译和链接,这背后就是通过Makefile来实现的。本文会结合编译器的帮助文档make.pdf,并且自己编写Makefile,来学习Makefile的基本概念和用法。

2 Makefile的规则

Makefile的规则如下所示:
在这里插入图片描述
其中的含义如下:

  1. target是生成的文件的名称,可以是编译器生成的目标文件,或者链接器生成的可执行文件。另外也可以是执行的动作,例如clean;
  2. prerequisite是用于生成文件的输入,例如生成目标文件的输入是C文件和头文件,生成可执行文件的输入是目标文件;
  3. recipe是需要执行的动作,可以理解成命令。recipe前面要加上一个Tab制表符。

知道了以上规则,就可以写一个简单的Makefile了。

3 一个简单的Makefile

3.1 帮助文档中的例子

Hightec的帮助文档中举了个例子来演示Makefile,如下图所示。
在这里插入图片描述
该Makefile主要做了一下几件事:

  • 将8个源文件编译成目标文件;
  • 将8个目标文件链接成一个可执行文件edit;
  • 用clean清除掉目标文件和可执行文件。

3.2 例1:一个简单的Makefile

帮助文档中只是个演示,并没有附带源文件供我们练习。因此博主自己写了简单的源文件头文件和Makefile,研究Makefile的执行过程和结果。另外,由于链接过程需要编写复杂的链接脚本,所以在下面的例子中只尝试编译的过程。

1)首先在同一个路径下建立三个文件:hello.c,hello.h,Makefile。
在这里插入图片描述
2)在hello.c中写入简单的变量和函数定义,如下所示。

/* hello.c */
#include "hello.h"

int a = 10;

int main(void)
{
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

在hello.h中写入对应的变量和函数声明,如下所示。

/* hello.h */
extern int a;
extern int main(void);
  • 1
  • 2
  • 3

根据上文提到的规则,在Makefile中尝试写入编译hello.c的命令语句,如下所示。

hello.o : hello.c hello.h
	tricore-gcc -c hello.c
	
clean : 
	rm hello.o
  • 1
  • 2
  • 3
  • 4
  • 5

Makefile中包含了两个功能:调用tricore-gcc把hello.c编译成hello.o,以及移除hello.o。

3)打开命令提示符,切换到这三个文件所在的路径。然后输入make并回车,如下图所示。
在这里插入图片描述
命令窗口会显示tricore-gcc -c hello.c这一行命令语句。然后回到文件夹路径下,看到成功生成了hello.o文件。
在这里插入图片描述
4)在窗口中输入make clean并回车,就会执行Makefile中的clean命令,如下图所示。
在这里插入图片描述
命令窗口会显示rm hello.o这一行命令语句。然后回到文件夹路径下,之前的hello.o文件就被移除了。clean的功能在软件编译的过程中很常用。在这里,clean不是一个目标文件,而是一个动作。clean的冒号后面没有跟其他的文件,因而被称为伪目标。

5)当路径下已经有了hello.o文件的时候,再去执行make命令会发生什么呢?尝试执行两次make命令,如下图所示。
在这里插入图片描述
第二次执行make命令的时候,编译器返回了"make: ‘hello.o’ is up to date"这句话,表示hello.o文件已经是最新的了。这里就要提到一个Makefile的机制,就是如果target文件(冒号前的文件)的时间晚于prerequisite文件(冒号后的文件)的时间,就表示输入文件没有被更新过,所以不会进行重新编译。
在这里插入图片描述

4 make是如何执行Makefile的

4.1 默认目标

默认情况下,make从第一个target开始,这个target被称为默认目标。

例如在3.1中所述的帮助文档中的例子。当我们敲下了make指令的时候,会从第一条规则开始,也就是重链接出edit文件。但是在链接之前,make必须首先处理edit文件所依赖的输入文件,也就是.o文件。所以make会先编译所有需要重新编译的源文件,直到.o文件齐全。这有点像是一个金字塔结构,底层的target完成以后才能做顶层的target。

clean伪目标是个例外,因为它不是edit所依赖的输入,需要使用make clean指令来处理clean。

4.2 例2:使用默认目标

把例1中的Makefile进行修改,在编译hello.c之前做一个默认目标project.elf,依赖于输入文件hello.o文件,如下。

project.elf : hello.o
	tricore-gcc -o project.elf hello.o

hello.o : hello.c hello.h
	tricore-gcc -c hello.c
	
clean : 
	rm project.elf hello.o
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

首先运行make clean,将当前路径的hello.o清除掉,只剩下hello.c,hello.h,Makefile三个文件。
在这里插入图片描述
然后,运行make。
在这里插入图片描述
在路径下就会生成project.elf和hello.o两个文件。
在这里插入图片描述
这个Makefile中就是以开头的project.elf作为默认目标。make先检测到默认目标所依赖的hello.o在当前路径中不存在,所以先去以hello.o为目标进行编译。编译完成后再以project.elf为目标去链接。

注意,这里的链接elf文件只是做一个演示,是为了说明默认目标的概念。实际上,链接过程非常复杂,不要被这个例子中的只言片语所误导。

5 使用变量让Makefile更简洁

5.1 变量的简单用法

在3.1帮助文档中的例子中,edit所依赖的.o文件有很多。如果Makefile中重复出现大量相同的字段,会很容易写错。这时就可以用一个变量来指代这一系列.o文件,如下图所示。
在这里插入图片描述
然后,在后文用到这一系列.o文件的地方,就可以用$(objects)来替换,如下图所示。
在这里插入图片描述

5.2 例3:在Makefile中使用变量

把例1中的Makefile进行修改,将hello.c和hello.h赋值给变量inputfile,然后再后面用到的地方换成$(inputfile),如下。

inputfile = hello.c hello.h
	
hello.o : $(inputfile)
	tricore-gcc -c hello.c
	
clean : 
	rm hello.o
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

然后打开命令行运行make,效果和例1相同,都能生成hello.o文件。

6 通过make推导规则

6.1 隐式规则

在Makefile文件中可以不用把编译的所有规则写出来,因为make中有个概念叫隐式规则,可以自动推导依赖关系。例如,在make看到了一个.o文件的时候,会自动推导它的源文件是同名的.c文件,就不需要把.c文件也写进去了。所以3.1 帮助文档中的例子也可以写成下面这样。
在这里插入图片描述
main.o文件后面就不再写上输入文件main.c了,下面的cc规则也省略了。

6.2 例4:省略源文件

将例1中的Makefile修改,冒号后面的输入文件不带hello.c了,只带一个hello.h,如下。

hello.o : hello.h
	tricore-gcc -c hello.c
	
clean : 
	rm project.elf hello.o
  • 1
  • 2
  • 3
  • 4
  • 5

然后打开命令行,用make执行,效果和例1相同。

7 另一种风格的Makefile

由于有了Makefile的隐式规则,就可以不用把源文件清楚地写出来了。因此,诞生了另一种风格的Makefile,如下。
在这里插入图片描述
在编译规则中,冒号左边的目标是很多个.o文件,右边是头文件。这样的Makefile也是可以正确地执行的,但是依赖关系非常复杂,写的时候很容易出错。

8 清空路径的规则

上面的例子也说到,可以用make clean来清空路径下的文件。实际应用中最好按照以下方式来写clean。
在这里插入图片描述
这里包含了两个要素。首先,.PHONE表示clean是个伪目标,这样就不会把clean和名为clean的文件搞混淆。其次,在rm前面添加一个减号,表示即使rm出现错误也可以使make继续。

注意,诸如clean这样的规则不应放在makefile的开头,因为我们不希望它成为默认目标。

9 总结

本文学习了Makefile的基本概念,并且通过一些实例的操作,熟悉了Makefile的基本用法。

>>返回个人博客总目录

注:本文转载自blog.csdn.net的chhttty的文章"https://blog.csdn.net/u013288925/article/details/110006578"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2024 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top