makefile:带你了解一种常用语GNU gcc编译的工具语言

LiteOS源码中使用makefile进行文件的批处理编译和连接到生成文件,如果在使用LiteOS来设计工程时使用GNU编译器进行编译,一般会都会使用到makefile进行编译和链接程序,如果使用的Keil或IAR的编译器进行编译则在Keil IDE或IAR IDE中设置编译器信息和文件包换路径就可以了进行编译链接和输出文件。

1、makefile介绍

简单的说makefile就是make执行的文件,将代码变成可行性文件的的过程叫做编译,组成一系列文件的编译叫做构建(build),Make是GNU提供的构建工具,主要用C、C++项目的构建编译过程,要学会使用Make,我们就需要学会使用makefile编写,makefile,该文件描述了如何编译和链接由几个C源文件和几个头文件组成的文本编辑器。当明确要求时,makefile还可以告诉make如何运行其他命令(例如,删除某些文件作为清理操作)。

1.1 makefile 规则


一个简单的makefile由具有以下形状的“规则”组成:

target … : prerequisites …
        recipe
        …
        …

target(目标)通常是由程序生成的文件的名称。目标的示例是可执行文件或目标文件。目标也可以是要执行的操作的名称,例如“clean”;

prerequisites(前置条件)是一个文件,该文件用作创建目标的输入。一个目标通常取决于几个文件;

recipe(命令)是一种要执行的动作。配方可能在同一行上或在自己的行上具有多个命令。请注意:您需要在每个配方行的开头添加一个制表符!这是一个模糊的地方,引起了人们的注意。如果您希望在食谱中使用制表符以外的其他字符作为前缀,则可以将.RECIPEPREFIX变量设置为其他字符"目标"是必需的,不可省略;"前置条件"和"命令"都是可选的,但是两者之中必须至少存在一个;

一条规则说明了如何以及何时重新制作作为特定规则目标的某些文件。 make根据创建或更新目标的先决条件执行方法。规则还可以解释如何以及何时执行某项操作。一个makefile可能包含除规则之外的其他文本,但是一个简单的makefile只需包含规则。规则看起来可能比此样例中显示的要复杂一些,但所有规则或多或少都适合该模式。

1.2Makefile 语法


① # 表示注释

② 通配符用来指定一组符合条件的文件名。Makefile 的通配符与 Bash 一致,主要有星号(*)、问号(?)和 [...] 。比如, *.o 表示所有后缀名为o的文件

③ %模式匹配

如需要编译当前目录下a.c和b.c两个文件,原来的写法是:

a.o: a.c
b.c: b.c

利用%可以简写为:

%.o : %.c

在处理大量同类型文件时既可以利用%简写文件

④ “=” 自定义变量

txt = Hello World
test:
    @echo $(txt)

上面的 txt代替的了“Hello World”

同时基于“=” Makefile提供了(=、:=、?=、+=)四个赋值运算操作。

⑤ 内置变量

Make有自己的操作变量,特指一些自己的功能命令;如:$(CC) 指向当前使用的编译器,$(MAKE) 指向当前使用的Make工具

具体变量规则可参考:https://www.gnu.org/software/make/manual/html_node/Implicit-Variables.html

自动变量(Automatic Variables)

makefile提供一些与规则相关的变量,常用的有:

(1)$@ -----指代当前目标

(2)$<  -----指代第一个前置条件

a.txt: b.txt c.txt
    cp $< $@

上面的代码和下面的代码一致

a.txt: b.txt c.txt
    cp b.txt a.txt

$< 指代第一个前置条件,即“b.txt”;$@ 指代目标值即“a.txt”

(3)$?                      ------ 指代比目标更新的所有前置条件,之间以空格分隔。比如,规则为 t: p1 p2,其中 p2 的时间戳比 t 新,$?就指代p2。

(4)$^                     ------ 指代所有前置条件,之间以空格分隔。比如,规则为 t: p1 p2,那么 $^ 就指代 p1 p2 。

(5)$*                      ------ 指代匹配符 % 匹配的部分, 比如% 匹配 f1.txt 中的f1 ,$* 就表示 f1。

(6)$(@D) 和 $(@F) ------ 分别指向 $@ 的目录名和文件名。比如,$@是 src/input.c,那么$(@D) 的值为 src ,$(@F) 的值为 input.c。

(7)$(<D) 和 $(<F)   ------ 分别指向 $< 的目录名和文件名。

1.3 makefile 循环


Makefile使用 Bash 语法,完成判断和循环。

如ifeq -- else -- endif 使用

ifeq ($(CC),gcc)
  libs=$(libs_for_gcc)
else
  libs=$(normal_libs)
endif

以上代码通过判断编译器是否为gcc决定编译不同的路径。

1.4 makefile 函数


Makefile 提供一些内置函数,使用格式如下:

$(function arguments)
# 或者
${function arguments}

内建函数如下表:具体函数参考路径(https://www.gnu.org/software/make/manual/html_node/Functions.html)

函数说明
Text Functions    通用文本操作功能。
File Name Functions操纵文件名的功能。

Conditional Functions    

实现条件的功能。
Foreach Function重复一些带有受控变化的文本。
File Function    将文本写入文件。
Call Function      展开用户定义的功能。
Value Function    返回变量的未扩展值。
Eval Function    将参数评估为makefile语法。
Origin Function查找变量在何处获得其值。
Flavor Function找出变量的味道。
Make Control Functions控制make运行方式的函数。
Shell Function    替换shell命令的输出。
Guile Function使用GNU Guile嵌入式脚本语言。 

2.mikefile文件编写

如下文件编译一个C语言工程,包含main.c kdb.c display.c 三个源文件及defs.h、command.h、两个头文件。

编译代如下:

edit : main.o kbd.o command.o display.o 
    cc -o edit main.o kbd.o command.o display.o

main.o : main.c defs.h
    cc -c main.c
kbd.o : kbd.c defs.h command.h
    cc -c kbd.c
command.o : command.c defs.h command.h
    cc -c command.c
display.o : display.c defs.h
    cc -c display.c

clean :
     rm edit main.o kbd.o command.o display.o

.PHONY: edit clean

该代码中,清空了输出文件,然后利用gcc编译器编译了三个头文件和两个文件。

--持续更新,请关注。

(完)