嵌入式-Makefile 文件概述

在介绍Makefile文件之前,咱们先来聊聊Shell语言,这可以说是“磨刀不误砍柴工”!对咱们了解Makefile有很大的帮助!



目录

Shell语言:

交叉编译器:

make:

清除工作目录过程文件:

Makefile总述:

Makefile的内容:



Shell语言:

Shell语言是指UNIX操作系统的命令语言,同时又是该命令语言的解释程序的简称。

Shell本身是一个用C语言编写的程序,它是用户使用Unix/Linux 的桥梁,用户的大部分工作都是通过Shell完成的。Shell既是一种命令语言,又是一种程序设计语言。作为命令语言,它交互式地解释和执行用户输入的命令;作为程序设计语言,它定义了各种变量和参数,并提供了许多在高级语言中才具有的控制结构,包括循环和分支。

它虽不是Unix/Linux系统内核的一部分,但它调用了系统核心的大部分功能来执行程序、建立文件并以并行的方式协调各个程序的运行。因此,对于用户来说,shell是最重要的实用程序,深入了解和熟练掌握shell的特性及其使用方法,是用好Unix/Linux系统的关键。

Shell是各个UNIX系统之间通用的功能,并且经过了POSIX的标准化。因此,shell脚本只要“用心写”一次,即可应用到很多系统上。同时,它运行于高于系统内核的环境,能够简单地执行一些文件系统级的高级操作。因此,之所以要使用Shell脚本主要有一下几点:

  •  简单性:Shell是一个高级语言,处于内核外层环境;通过shell可以简洁地表达复杂的操作。
  •  可移植性:使用POSIX所定义的功能,可以做到脚本无需修改就可以在不同的系统上执行。
  •  开发容易:可以在短时间内完成一个功能强大又适用的脚本。


交叉编译器:

一般来说arm-linux-gcc是arm-none-linux-gnueabi-gcc的一个软链接。(可用ls -l命令,查看连接对象;用la -i命令,查看inode数值)。

arm-none-linux-gnueabi-gcc只是告诉你支持eabi功能,可以替换为arm-linux-gcc执行;但arm-linux-gcc不能直接改为arm-none-linux-gnueabi-gcc,因为不了解arm-linux-gcc的形式。(现在的arm-linux-toolchain大多数是arm-none-linux-gnueabi-gcc类型的,为了方便,就软链接成arm-linux-gcc).



make:

make 是一个命令工具,它解释Makefile中的指令(应该说是规则),在Makefile文件中描述了整个工程所有文件的编译顺序、编译规则、Makefile有自己的书写格式、关键字、函数、像C 语言有自己的格式、关键字一样。而且在Makefile中可以利用系统shell所提供的任何命令来完成想要的工作。Makefile(在其他的系统上可能是另外的文件名)在绝大多数的IDE开发环境中都在使用,已经成为一种工程的编译方法。

编译:把高级语言编写的代码转换成机器可以识别的机器指令,编译高级语言后生成的指令虽然可被机器识别,但是还不能被执行。编译时,编译器检查和高级语言的语法、函数与变量的声明是否正确.只有所有的语法正确、相关变量定义正确 编译器就可以编译出中间目标文件。通常一个高级语言的源文件都可以对应一个目标文件、目标文件在Linux中默认后缀为“.o”(如:“foo.c”的目标文件为“foo.o”)。[为了和规则的目标文件相区别。这里将编译高级语言后生成的目标文件成为.o文件]

链接:将多.o文件,或者.o文件和库文件链接成为可被操作系统执行的可执行程序(Linux环境下,可执行文件的格式为“ELF”格式)。连接器不检查函数所在的源文件,只检查所有.o文件中的定义的符号。将.o文件中使用的函数和其他 .o或者库文件中的相关符号进行合并,对所有文件中的符号进行重新安排(重定位),并链接系统相关文件(程序启动文件等)最终生成可执行程序。链接过程使用GNU的“ld”工具。

静态库:又称为文档文件(Archive File),它是多个 .o文件的集合。Linux中静态库文件的后缀为“.a”。静态库中的各个成员(.o文件)没有特殊的存在格式,仅仅是一个.o文件的集合。使用“ar”工具维护和管理静态库。

共享库:也是多个.o文件的集合,但是这些.o文件时有编译器按照一种特殊的方式生成(Linux中,共享库文件格式通常为“ELF”格式。共享库已经具备了可执行条件)。模块中各个成员的地址(变量引用和函数调用)都是相对地址。使用此共享库的程序在运行时,共享库被动态加载到内存并和主程序在内存中进行连接。多个可执行程序可共享库文件的代码段(多个程序可以共享的使用库中的某一个模块,共享代码,不共享数据)。另外共享库的成员对象可被执行(由libdl.so提供支持)。

Make在执行时,需要一个命名为Makefile的文件,这个文件告诉make以何种方式编译源代码和连接程序。典型地,可执行文件可由一些.o文件按照一定的顺序生成或者更新。如果在你的工程中已经存在一个或者多个正确的Makefile。当对工程中的若干源文件修改后,需要根据修改来更新可执行文件或者库文件,使用Shell下的make将会十分简单。make会自动根据修改情况完成源文件的对应.o文件的更新、库文件的更新、最终的可执行程序的更新。

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

当使用make工具进行编译时,工程中以下几种文件在执行make时将会被编译(重新编译):

  •  所有的源文件没有被编译过,则对各个C源文件进行编译并进行链接,生成最后的可执行程序;
  •  每一个在上次执行make之后修改过的C源代码文件在本次执行make时将会被重新编译;
  •  头文件在上一次执行make之后被修改,则所有包含此头文件的C源文件在本次执行make时将会被重新编译。

后两种情况是make只将修改过的C源文件重新编译生成.o文件,对于没有修改的文件不进行任何操作。重新编译过程中,任何一个源文件的修改将产生新的对应的.o文件,新的.o文件将和以前的已经存在、此次没有重新编译的.o文件重新连接生成最后的可执行程序。

Makefile规则介绍:

Target:规则的目标。通常是最后需要生成的文件名或者为了实现这个目的而必须的中间过程文件名。可以是.o文件、也可以是最后的可执行程序的文件名等。另外,目标也可以是一个make执行的动作的名称,如目标“clean”,通常称这样的目标是“伪目标”。

Prerequisites:规则的依赖。生成规则目标所需要的文件名列表。通常一个目标依赖于一个或者多个文件。

Command:规则的命令行。是规则所要执行的动作(任意的shell命令或者是可在shell下执行的程序)。它限定了make执行这条规则时所需要的动作。

一个规则可以有多个命令行,每一条命令占一行。注意:每一个命令行必须以[Tab]字符开始,[Tab]字符告诉make此行是一个命令行。Make按照命令完成相应的动作。(易产生隐蔽错误)

命令就是在任何一个目标的依赖文件发生变化后重建目标的动作描述。[一个目标可以没有依赖而只有动作(指定的命令)。比如:Makefile中的目标“clean”,此目标没有依赖,只有命令。它所定义的命令用来删除make过程产生的中间文件(进行清理工作)]。

Make程序根据规则的依赖关系,决定是否执行规则所定义的命令的过程称之为执行规则。

当规则的目标是一个文件,在它的任何一个依赖文件被修改以后,在执行“make”时这个目标文件将会被重新编译或者重新连接。此目标的任何一个依赖文件如果有必要则首先会被重新编译。

在描述依赖关系行之下通常就是规则的命令行(存在一些规则没有命令行),命令行定义了规则的动作(如何根据依赖文件来更新目标文件)。命令行必须以[Tab]字符开始,但并不是所有的以[Tab]键出现行都是命令行。但make程序会把出现在第一条规则之后的所有以[Tab]字符开始的行都作为命令行来处理。

目标“clean”不是一个文件,它仅仅代表执行一个动作的标识。正常情况下,不需要执行这个规则所定义的动作,因此目标“clean”没有出现在其他任何规则的依赖列表中。因此在执行make时,它所指定的动作不会被执行。除非在执行make时明确地指定它。而且目标“clean”没有任何依赖文件,它只有一个目的,就是通过这个目标名来执行它所定义的命令。Makefile中把那些没有任何依赖只有执行动作的目标称为“伪目标”。

对于一个Makefile文件,“make”首先解析终极目标所在的规则,根据其依赖文件依次(按照依赖文件列表从左到右的顺序)寻找创建这些依赖文件的规则、首先为第一个依赖文件(main.o)寻找创建规则,如果第一个依赖文件依赖于其他文件则同样为这个依赖文件寻找创建规则(创建main.c和defs.h的规则,通常源文件和头文件已经存在,也不存在重建它们的规则),直到为所有的依赖文件找到合适的创建规则,之后make从最后一个规则(上例目标为main.o的规则)回退到开始执行,最终完成终极目标的第一个依赖文件的创建和更新,之后对第二个、第三个、第四个…… 终极目标的依赖文件执行同样的过程(商里的顺序是“main.o”、“kbd.o”、“command.o”……)。创建或者更新每一个规则依赖文件的过程都是这样的一个过程(类似于c语言中的递归过程)、对于任意一个规则执行的过程都是按照依赖文件列表顺序,对于规则中的每一个依赖文件,使用同样方式(按照同样的过程)去重建它,在完成对所有依赖文件的重建之后,最后一步才是重建此规则的目标。

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

书写规则建议的方式是:单目标,多依赖,就是说尽量要做到一个规则中只存在一个目标文件,可有多个依赖文件,尽量避免使用多个目标,,单依赖的方式。



清除工作目录过程文件:

规则除了完成源代码编译之外,也可以完成其他任务。例如:前面提到的为了实现清除当前目录中编译过程中产生的临时文件(edit和那些.o文件)的规则:

但在实际应用中,我们把这个规则写成如下稍微复杂的一些例子,以防止出现始料未及的情况。

这两个实现有两点不同:① 通过“.PHONY”特殊目标将“clean”目标声明为伪目标。避免当磁盘上存在一个名为“clean”文件时,目标“clean”所在规则的命令无法执行。② 在命令行之前使用“-”,意思是忽略命令“rm”的执行错误。这样的一个目标在Makefile中,不能将其作为终极目标(Makefile的第一个目标)。因为我们的初衷并不是当你在命令行上输入make以后执行删除动作。而是要创建或者更新程序。在我们上边的例子中,就是输入make以后要需要对目标“edit”进行创建或者重建。 上例中因为目标“clean”没有出现在终极目标“edit”依赖关系中(终极目标的直接依赖或者间接依赖),所以我们执行“make”时。目标“clean”所在的规则将不会被处理。当需要执行此规则,要在make的命令行选项中明确指定这个目标(执行“make clean”)。



Makefile总述:

Makefile的内容:

在一个完整的Makefile中,包含了5个东西:显示规则、隐含规则、变量定义、指示符和注释。

显示规则:它描述了在何种情况下如何更新一个或者多个被称为目标的文件(Makefile的目标文件)。书写Makefile时需要明确地给出目标文件、目标的依赖文件列表以及更新目标文件的所需要的命令(有些规则没有命令,这样的规则只是纯粹的描述了文件之间的依赖关系)。

隐含文件:它是make根据一类目标文件(典型的是根据文件名的后缀)而自动推导出来的规则。Make根据目标文件的名,自动产生目标的依赖文件并使用默认的命令来对目标进行更新(建立一个规则)。

变量定义:使用一个字符或字符串代表一段文本串,当定义了一个变量以后,Makefile后续在需要使用此文本串的地方,通过引用这个变量来实现对文本串的使用。

Makefile指示符:指示符指明在make程序读取makefile文件过程中所要执行的一个动作。其中包括:

 读取一个文件,读取给定文件名的文件,将其内容作为makefile文件的一部分。

 决定(通常是根据一个变量的得值)处理或者忽略makefile中的某一特定部分。

 定义一个多行变量。

注释:Makefile中“#”字符后的内容被作为是注释内容(和shell脚本一样)处理。如果此行的第一个非空字符为“#”,那么此行为注释行、注释行的结尾如果存在反斜线(\),那么下一行也被作为注释行。一般在书写Makefile时推荐将注释行作为一个独立的行,而不要和Makefile的有效行放在一行中书写,当在Makefile中需要使用字符“#”时,可以使用反斜线加“#”(\#)来实现(对特殊字符“#”的转义),其表示将“#”作为一字符而不是注释的开始标志。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值