Linux应用开发·Makefile菜鸟教程
目录
1. 概述
2. 准备工作
2.1 安装工具包
2.2 创建Helloworld程序
3. 编写 Makefile 文件
4. 拓展一:clean的使用
5. 拓展二:变量的引入
6. 拓展三:自动推导
1. 概述
Makefile是一种用于管理和自动化软件编译过程的文本文件。它通常包含了一系列规则,这些规则描述了如何根据源代码文件生成可执行文件或者其他目标文件。Makefile的核心概念是规则和依赖关系,规则定义了如何生成一个或多个目标文件,而依赖关系则指定了生成目标文件所需要的源文件或其他依赖文件。
简单点来说,Makefile 就是用来管理项目的,makefile 定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译。
2. 准备工作
2.1 安装工具包
要想使用 Makefile,需要要确保我们安装好的Linux上又相关的工具,输入命令:
sudo apt install -y build-essential
这是一个工具包,其中包含gcc/g++等开发工具,make-doc就是我们需要的 Makefile:
2.2 创建Helloworld程序
为了方便观看具体流程,创建三个文件第一个hello.c:
#include<stdio.h>
#include"hello.h"void Hello_World(void)
{printf("Hello World!!!\n");
}
第二个hello.h:
#ifndef __HELLO_H__
#define __HELLO_H__void Hello_World(void);#endif
第三个main.c:
#include"hello.h"
#include <stdio.h>#define num 3//这是一个注释
int main()
{int a = 10;if(a<num){Hello_World();}else{printf("This is gcc !!!\n");}return 0;
}
为了方便查看代码,我们可以在Linux上下载一个VScode进行查看,但是最终编译代码还是回到终端上进行编译,因为我们如果要在开发板上进行开发,开发板可不会提供给我们VScode,有的只有终端进行编译,VScode在这里只是辅助我们观看代码,当然如果你还是想使用 vi 也是可以的,对编译没有任何影响。
对于VScode的安装,可以参考如下链接:
Linux应用开发·如何在Linux上安装VScode、gcc编译流程以及如何进行静态/动态链接的打包使用·详细步骤演示-CSDN博客
只看VScode安装部分即可,如果不了解gcc的编译流程最好看一下。
在创建一个 Makefile 的文件,可以直接在终端使用命令:
也可以来到VScode直接右键:
注意:我们平常遇见的xxx.mk 文件或者 Makefile 都统称为 Makefile 脚本文件。
命名只能为 makefile 或者是 Makefile,因为只有这两种命名方式才能被 make 命令识别。
在VScode上创建 Makefile 文件的时候,如果之前没有安装过相关扩展,第一次创建右下角会提示需要安装扩展,安装即可:
这里的安装扩展,和上面的工具包是两码事,一个是在终端,一个是在VScode,安装完成后:
3. 编写 Makefile 文件
在编写前,我们先了解一下 Makefile 内容都是由那三部分组成,其格式如下:
# Makefile内容组成部分
# <目标名称>:<前置依赖>
# \t<需要执行的命令># 注意\t制表符是一个Tab键,在键盘上,最好自己敲上去,复制有时候会识别为空格# 举个例子main:hello.o main.ogcc hello.o main.o -o main
在VScode上编写:
或者通过命令在 vi 上编写:
而这个hello.o和main.o文件是怎么来的呢?这就需要我们通过gcc进行编译:
此时输入make就会运行:
不过此时我们会发现,我们在输入make前还需要输入这么多的前置命令非常不方便,那么我们为什么不让make帮我们输入呢:
# Makefile内容组成部分
# <目标名称>:<前置依赖>
# \t<需要执行的命令># 注意\t制表符是一个Tab键,在键盘上,最好自己敲上去,复制有时候会识别为空格# 举个例子
# 放在第一个是默认目标
# 目标是编译出main文件,依赖hello.o和main.o文件
# 编译的命令是gcc hello.o main.o -o main
main:hello.o main.ogcc hello.o main.o -o main# 目标是main.o 依赖main.c和hello.h
# 编译的命令是gcc -c main.c
main.o:main.c hello.hgcc -c main.c# 目标是hello.o 依赖hello.c和hello.h
# 编译的命令是gcc -c hello.c
hello.o:hello.c hello.hgcc -c hello.c
我们将前置的文件全部删除掉:
运行一下看一下:
到这里其实已经能进行Makefile的一个简单的使用了,下面我们在做一些拓展。
4. 拓展一:clean的使用
在我们上面使用完 Makefile 后会发现出现一堆.o文件,此时因为这个只是一个简单的hello world程序,不是很明显,若是一个大型项目,一堆.o文件会影响我们的阅读,若是一个一个删除又比较麻烦:
这里我们将 Makefile 的代码简单的更改一下,在尾部添加clean程序:
# Makefile内容组成部分
# <目标名称>:<前置依赖>
# \t<需要执行的命令># 注意\t制表符是一个Tab键,在键盘上,最好自己敲上去,复制有时候会识别为空格# 举个例子
# 放在第一个是默认目标
# 目标是编译出main文件,依赖hello.o和main.o文件
# 编译的命令是gcc hello.o main.o -o main
main:hello.o main.ogcc hello.o main.o -o main# 目标是main.o 依赖main.c和hello.h
# 编译的命令是gcc -c main.c
main.o:main.c hello.hgcc -c main.c# 目标是hello.o 依赖hello.c和hello.h
# 编译的命令是gcc -c hello.c
hello.o:hello.c hello.hgcc -c hello.cclean:rm -f main.o hello.o
我们可以通过make clean命令将.o文件删除:
5. 拓展二:变量的引入
对于 Makefile 有四种变量赋值方式:
:= # 即时变量
= # 延时变量
?= # 延时变量,如果是第 1 次定义才起效,如果在前面该变量已定义则忽略这句
+= # 附加,他是即时变量还是延时变量取决于前面的定义
我们更改一下代码:
# Makefile内容组成部分
# <目标名称>:<前置依赖>
# \t<需要执行的命令># 注意\t制表符是一个Tab键,在键盘上,最好自己敲上去,复制有时候会识别为空格# 举个例子
# 定义变量 example_sum
example_sum := hello.o main.o # 放在第一个是默认目标
# 目标是编译出main文件,依赖hello.o和main.o文件
# 编译的命令是gcc hello.o main.o -o main
main:$(example_sum)gcc $(example_sum) -o main# 目标是main.o 依赖main.c和hello.h
# 编译的命令是gcc -c main.c
main.o:main.c hello.hgcc -c main.c# 目标是hello.o 依赖hello.c和hello.h
# 编译的命令是gcc -c hello.c
hello.o:hello.c hello.hgcc -c hello.cclean:rm -f $(example_sum)
可以看到能够正常运行:
6. 拓展三:自动推导
Makefile 有一个强大特性,可以大大简化编译规则的编写,那就是自动推导,我们上面可以看到 Makefile 里面写了非常多的东西,其实又许多的 Makefile 是可以自动推导出来的,可以直接简写为:
main: main.o hello.o
可以看到也能正常运行:
但是对于clean还是需要自己编写,为了后续方便我们还是先加上:
还需要注意一点的是,他对于hello.h的更改是识别不到的,我来可以来看一下,首先是对main.c进行更改,找一行代码回车一下就行,我们先不进行更改,其显示未更新,因此不会执行别的命令:
我们随便一行敲一下回车,更改一下main.c保存一下,可以检测到更改,重新执行了main.c的命令,但是对于hello.c未做回应:
同样的方法,我们更改一下hello.c来看看:
但是如果我们对hello.h进行更改,可以发现识别不到更新:
这是因为自动推导不能自动检测头文件依赖,那么如何解决呢?就是将不能推导的给写上去,明确写出头文件依赖:
main: main.o hello.omain.o:hello.h
hello.o:hello.hclean:rm -f main.o hello.o
此时就可以检测到跟改:
嵌入式Linux·应用开发_时光の尘的博客-CSDN博客