OK6410 --- Makefile

----------更新日期2019-07-11----------

参考文档:GNU make Version 4.2

GNU make是由Richard Stallman和Roland McGrath实现的,并从3.76版本开始由Paul D. Smith负责开发。make工具自动确定一个大型程序中的哪些部分需要重新编译,并发出命令以重新编译它们。

本系列博文中将使用C语言编写的程序作为示例。当然,你也可以使用make这个工具来编译其他语言,只要它的编译器可以通过shell命令行运行。实际上,make不但可以用于编译程序,还可以用于其它的任务,如当修改一些文件时,会根据修改的文件自动更新或重建与其相关的其他文件。

要使用make工具,首先要创建文件名为Makefile的文件,该文件用于描述程序中文件之间的关系,如该程序中哪些源文件需要编译,如何链接编译后的目标文件,如何生成最终的执行文件等等。一旦Makefile文件中的编译规则编写好,编写的格式正确,在该Makefile文件当前目录下的命令行中输入make命令,make工具就会根据Makefile的数据库和最后修改的时间确定更新哪些文件并如何更新。Makefile数据库中记录着如何处理每个程序文件的规则方法。你还可以通过为make命令添加命令选项来控制那个文件应该被重新编译或如何重新编译。

1 Makefile简介

简单来说,Makefile这个文件就是告诉make该做什么。通常,makefile告诉make如何编译和链接程序。make 通过比较对应文件(规则的目标和依赖,)的最后修改时间,来决定哪些文件需要更新、那些文件不需要更新。对需要更新的文件 make 就执行数据库中所记录的相应命令(在 make 读取 Makefile 以后会建立一个编译过程的描述数据库。此数据库中记录了所有各个文件之间的相互关系,以及它们的关系描述)来重建它,对于不需要重建的文件 make 什么也不做。

1.1 Makefile规则的简单介绍

规则书写的模板:
要生成的目标文件:需要依赖的文件
[tab]生成目标文件所需要执行的命令1(注意:需要在每条命令的开头输入一个制表符,即[tab]键)
[tab]命令2
[tab]命令3
[tab]........

示例1:
如创建一个点亮裸板LED的程序,我们最终需要下载到开发板的程序是一个二进制的文件led.bin。所以,Makefile可以如下:

led.bin:led.elf(规则1)
	arm-linux-objcopy -O binary -S -g $^ $@(命令1.1)

led.elf:led.o(规则2)
	arm-linux-ld -Ttext 0xc000000 -o $@ $^	(命令2.1)

led.o:led.s(规则3)
	arm-linux-gcc -c -g -o $@ $^(命令3.1)

1.2 make是如何工作的

默认的情况下,make执行的是Makefile中的第一个规则,此规则的第一个目标称之为“最终目标”或者“终极目标”(就是一个Makefile最终需要更新或者创建的目标)。示例1中的“led.bin”就是Makefile中的第一个目标,也就是最终目标。它依赖led.elf这个文件,make会作出三种处理情况:

  1. 如果led.elf不存在,则执行规则2中的操作,依赖led.o文件生成led.elf目标文件;
  2. 如果led.elf存在,但源文件led.s的时间比led.elf“更新”,则重新编译程序,更新led.bin文件;
  3. 如果led.elf存在,且led.elf的修改时间比led.o或led.s“更新”,则不做任何操作。

由示例1的规则可知,从源文件led.s到led.bin,需要三步操作,led.s(执行命令3.1,生成)led.o(执行命令2.1,生成)led.elf(执行命令1.1,生成)led.bin。这就像一种递归,首先明确最终目标led.bin,led.bin依赖led.elf,但led.elf不存在,就需要执行以led.elf作为目标的规则来生成led.elf(即执行规则2);而led.elf又依赖led.o,如果led.o也不存在,则执行规则3来生成led.o;当规则3和规则2执行完,就可以顺利得到led.elf文件,再执行规则1就可以得到led.bin文件。

当修改了源文件led.s后,由于led.s文件的时间比led.o“更新”,所以需要重新编译源文件led.s,得到led.o文件;以此类推,最终目标led.bin也将被更新。

在make命令运行过程中,任何一条规则出错,make将报错并退出。整个过程 make 只是负责执行规则,而对具体规则所描述的依赖关系的正确性、规则所定义的命令的正确性不做任何判断。就是说,一个规则的依赖关系是否正确、描述重建目标的规则命令行是否正确,make 不做任何错误检查。因此,需要正确的编译一个工程。需要在提供给 make 程序的 Makefile 中来保证其依赖关系的正确性、和执行命令的正确性。

1.3 清除工作目录中的过程文件

通常,当我在工作目录环境下的命令行中输入make命令后,除了在工作目录里生成最终目标,如示例1中的led.bin,还会生成相关的中间目标文件,如示例1中的led.o,led.elf。这些文件一般是没有什么用途的,因为我们只需要led.bin用于下载到开发板。那么,我们就可以通过输入命令make clean来清理这些在编译过程中产生的临时文件。下面修改一下示例1,如下:

led.bin:led.elf(规则1)
	arm-linux-objcopy -O binary -S -g $^ $@(命令1.1)

led.elf:led.o(规则2)
	arm-linux-ld -Ttext 0xc000000 -o $@ $^	(命令2.1)

led.o:led.s(规则3)
	arm-linux-gcc -c -g -o $@ $^(命令3.1)

.PHONY:clean all_clean
#删除当前目录下的所有.o,.elf后缀的文件
clean:
    rm *.o *.elf
#删除当前目录下的所有.o,.elf,以及.bin后缀的文件
all_clean:
    make clean
    rm *.bin

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章