makefile介绍 通俗易懂

2021-08-30 11:01:09 浏览数 (1)

Make 概述

在学习Makefile之前,首先介绍一下make命令,make命令是GNU的工程化编译工具,它用于编译大量互相关联的源代码,使用它可以实现项目的工程化管理,提高开发效率。

Make 可自动决定一个大程序中哪些文件需要重新编译,并发布重新编译它们的命令。Make的使用不仅限于程序,它可以适用于任何如果一些文件变化导致另外一些文件必须更新的任务。

当然,我们要想使用Make命令,必须先写一个称为Makefile的文件,该文件描述程序中各个文件之间的相互关系,并且提供每一个文件的更新命令。

关于编译和链接

编译:生成目标文件(编译时,编译器需要的是语法的正确,函数与变量的声明的正确)

链接:生成可执行文件(链接时,主要是链接函数和全局变量,把目标文件链接成应用文件)

Windows程序开发一般包括:编辑、编译链接、执行三大步骤。

嵌入式程序开发一般包括:

1、编辑

2、指定链接地址

3、指定连接顺序

4、编译链接

5、执行(烧写到单板再启动)

Linux程序开发一般包括:

1、编辑

2、链接脚本

3、用命令行链接文件顺序

4、运行命令行

5、执行(烧写到单板再启动)

通常我们把上述的2、3、4条内容写入到Makefile文件中,然后执行Make完成编译。

Makefile文件介绍

Make程序需要一个所谓的Makefile文件来告诉它干什么。通常情况下,Makefile文件告诉Make源代码文件之间的链接关系、依赖关系等从而准确编译和链接成一个应用程序。

这里举一个简单的例子,假设我们把5个C源程序文件和3个头文件编译和连接成为一个FY的目标程序。我们需要写一个Makefile文件来告诉Make怎样运行所需要的杂乱无章的命令。

如果这个工程从没被编译过(没有编译后生成的目标文件),那么所有的.c源文件都要被编译并链接。

如果有编译后的目标文件,但此工程的某几个.c源文件被修改了,那么我们只编译被修改的.c文件,并链接目标程序。

如果有编译后的目标文件,但此工程的头文件被改变了,那么需要编译引用了这几个头文件的.c文件,并链接目标程序。

通过上面的这些规则,避免了每次Make都去重新编译或者链接。只要写好Makefile,无论怎么修改源程序,只要运行下Make命令就自动完成编译和链接,大大提高了项目运行开发的效率。

Understanding Makefile With Examples

Makefile的规则

一个简单的Makefile文件包含一系列的“规则”,其样式如下:

目标: 依赖1 依赖2…

<‘tab>命令

目标:通常是要产生的文件的名称,它可以是可执行文件(OBJ文件),也可是一个执行的动作名称,如‘clean’。

依赖:用来输入从而产生目标的文件,一个目标经常有几个依赖。

命令:Make执行的动作,一个规则可以含有几个命令,每个命令占一行。

注意:每个命令行前面必须是一个Tab字符,即命令行第一个字符是Tab。这是不小心容易出错的地方。

以下是写好的Makefile文件,他告诉Make把源程序编译链接成一个FY的目标文件。

使用Makefile文件创建可执行的称为‘FY’的文件,键入:make

使用Makefile文件从目录中删除可执行文件和目标,键入:make clean

在这个Makefile文件例子中:

目标包括可执行文件‘FY’和OBJ文件‘main.o’、‘kdb.o’等。

依赖是C语言源文件和C语言头文件如‘main.c’和‘defs.h’等。事实上,每一个OBJ文件既是目标也是依赖。

命令行包括‘gcc -c main.c’和‘cc -c kbd.c’等(缩进一定要以一个Tab键作为开头)。

make是如何工作的

在编译过程中,我们通常只是输入一个make命令,那它到底是怎么运行工作呢?

首先make会在当前目录下查找名称为“Makefile”或者“makefile”的文件。

找到文件之后,它会继续找文件中注明的第一个目标文件(即上文的FY)。

如果目标文件(FY)不存在,或者目标文件后的依赖文件(.o文件)的修改时间要比目标文件(FY)新,那么,它继续寻找后面定义的命令。

如果目标文件FY依赖的.o文件存在,那么make会在当前文件中寻找目标为.o文件的依赖性。若找到则根据规则继续生成一个头文件。

make会根据文件夹内的.c或者.h生成.o文件,然后再用.o文件生成FY可执行的程序。

注:make只会检查文件依赖,不会对命令进行检查。所以命令写错了是不会报错的。

使用变量简化makefile文件

在例子中,我们在‘FY’的生成规则中把所有的OBJ文件列举了两次

如果我们在FY项目中又新加入了一个.c文件,那么Makefile需要好几处都做改动。而且如果项目大的话Makefile也会写的很混乱,不方便阅读,出错的概率也更大。因此,我们需要一个变量来代替我们写的这些文件。

比如声明一个变量objects(其它名字也可以)来表示这一大串.o文件,然后,在每一个需要列举OBJ文件的地方,我们使用写为`$(objects)'形式的变量代替。

使用变量后的完整的makefile文件:

这样如果有新的文件,只用修改一下objects,给它添加一个文件即可。

让make自动推导命令

make具有识别并且自动推导命令的能力,它识别出一个.o文件,就会自动将其对应的.c文件加在依赖关系中。并且也会自动推导出相关的编译命令。所以我们可在依赖中省略C语言源程序,进而可以省略命令,实现Makefile文件编写更加简洁。

这种方式称为make的隐晦规则。.PHONY表示clean是一个伪目标文件。

另一种风格的makefile文件

make可以自动推导命令,这很方便。但是Makefile的每个.o文件都依赖于很多的.h文件,能不能把这些.h文件综合到一起呢?

看一下这种书写方式:

这里的defs.h是所有OBJ文件的共同的一个依赖;command.h和bufffer.h是具体列出的OBJ文件的共同依赖。

目录中删除文件的规则

对于编写习惯的养成而言,我们最好在每个Makefile中都写一个清空目标文件的clean命令,这样有利用重新编译。例如:

在实际应用中,应该编写较为复杂的规则以防不能预料的情况发生。更接近实用的规则样式如下:这样可以防止make因为存在名为’clean’的文件而发生混乱,并且导致它在执行rm命令时发生错误

注意,后者的-表示忽略问题,强制执行。而且不要将clean放在文件的开头,因为Makefile默认执行的就是文件开头的target。因此,对于clean,最好将它放在文件最后。

————————————————

Understanding Makefile With Examples

0 人点赞