Linux C - Makefile (一)

本文为Makefile学习笔记,知识点根据个人需要摘取、总结,来自 http://c.biancheng.net/makefile/。

Makefile

1. Makefile 文件是什么?

Makefile 可以简单的认为是一个工程文件的编译规则,描述了整个工程的编译和链接等规则。Makefile 可以使得我们的项目工程的编译变得自动化,不需要每次都手动输入一堆源文件和参数。

  • 编译的时候 gcc 只会默认链接一些基本的C语言标准库,很多源文件依赖的标准库都需要我们手动链接。在编译的时候命令会很长,并且在编译的时候我们可能会涉及到文件链接的顺序问题,所以手动编译会很麻烦。—— Makefile 就不一样了,它会彻底简化编译的操作。把要链接的库文件放在 Makefile 中,制定相应的规则和对应的链接顺序。这样只需要执行 make 命令,工程就会自动编译。每次想要编译工程的时候就执行 make ,省略掉手动编译中的参数选项和命令,非常的方便。
  • Makefile 支持多线程并发操作,会极大的缩短我们的编译时间,并且当我们修改了源文件之后,编译整个工程的时候,make 命令只会编译我们修改过的文件,没有修改的文件不用重新编译,也极大的解决了我们耗费时间的问题。

2. Makefile 文件规则

Makefile 规则包含两部分:
分别是依赖的关系和执行的命令,其结构如下所示:

targets : prerequisites
    command

或者是

targets : prerequisites; command
    command

相关说明如下:

  • targets:规则的目标,可以是 Object File(一般称它为中间文件),也可以是可执行文件,还可以是一个标签;
  • prerequisites:是我们的依赖文件,要生成 targets 需要的文件或者是目标。可以是多个,也可以是没有;
  • command:make 需要执行的命令(任意的 shell 命令)。可以有多条命令,每一条命令占一行。
  • 目标和依赖文件之间要使用冒号分隔开,命令的开始一定要使用Tab键。
  • 注释: Makefile 中只有行注释,和 UNIX 的 Shell 脚本一样,其注释是用“#”字符,这个就像 C/C++ 中的“//”一样。如果你要在你的 Makefile 中使用“#”字符,可以用反斜框进行转义,如:“#”。

3. Makefile 工作流程

Makefile 的具体工作流程可以通过例子来看一下:创建一个包含有多个源文件和 Makefile 的目录文件,源文件之间相互关联。在 Makefile 中添加下面的代码:

main:main.o test1.o test2.o
gcc main.o test1.o test2.o -o main
main.o:main.c test.h
gcc -c main.c -o main.o
test1.o:test1.c test.h
gcc -c test1.c -o test1.o
test2.o:test2.c test.h
gcc -c test2.c -o test2.o

默认情况下,make 执行的是 Makefile 中的第一规则(Makefile 中出现的第一个依赖关系),此规则的第一目标称之为“最终目标”或者是“终极目标”。

它的具体工作顺序是:当在 shell 提示符下输入 make 命令以后。 make 读取当前目录下的 Makefile 文件,并将 Makefile 文件中的第一个目标作为其执行的“终极目标”,开始处理第一个规则(终极目标所在的规则)。在我们的例子中,第一个规则就是目标 “main” 所在的规则。规则描述了 “main” 的依赖关系,并定义了链接 “.o” 文件生成目标 “main” 的命令;make 在执行这个规则所定义的命令之前,首先处理目标 “main” 的所有的依赖文件(例子中的那些 “.o” 文件)的更新规则(以这些 “.o” 文件为目标的规则)。

对这些 “.o” 文件为目标的规则处理有下列三种情况:

  • 目标 “.o” 文件不存在,使用其描述规则创建它;
  • 目标 “.o” 文件存在,目标 “.o” 文件所依赖的 “.c” 源文件 “.h” 文件中的任何一个比目标 “.o” 文件“更新”(在上一次 make 之后被修改)。则根据规则重新编译生成它;
  • 目标 “.o” 文件存在,目标 “.o” 文件比它的任何一个依赖文件(".c" 源文件、".h" 文件)“更新”(它的依赖文件在上一次 make 之后没有被修改),则什么也不做。

当然 make 命令能否顺利的执行,还在于我们是否制定了正确的的依赖规则,当前目录下是不是存在需要的依赖文件,只要任意一点不满足,我们在执行 make 的时候就会出错。

清除工作目录中的过程文件
我们在使用的时候会产生中间文件会让整个文件看起来很乱,所以在编写 Makefile 文件的时候会在末尾加上这样的规则语句:

.PHONY:clean
clean:
    rm -rf *.o test

其中 “*.o” 是执行过程中产生的中间文件,“test” 是最终生成的执行文件。我们可以看到 clean 是独立的,不是具体的文件,不会与第一个目标文件相关联,所以在执行 make 的时候也不会执行下面的命令。在shell 中执行 “make clean” 命令,编译时的中间文件和生成的最终目标文件都会被清除,方便我们下次的使用。

4. Makefile通配符的使用

shell 中使用的通配符有:"*","?","[…]":

通配符使用说明
*匹配0个或者是任意个字符
?匹配任意一个字符
[ ]指定匹配的字符放在 “[]” 中

通配符可以出现在模式的规则中,也可以出现在命令中;欲通过引用变量的方式来使用,需调用函数 “wildcard” 将其展开。

OBJ=$(wildcard *.c)
test:$(OBJ)
    gcc -o $@ $^

“%” 可使用在 规则 当中:

test:test.o test1.o
    gcc -o $@ $^
%.o:%.c
    gcc -o $@ $^

“%.o” 把需要的所有的 “.o” 文件组合成为一个列表,从列表中挨个取出的每一个文件,"%" 表示取出来文件的文件名(不包含后缀),然后找到文件中和 "%"名称相同的 “.c” 文件,然后执行下面的命令,直到列表中的文件全部被取出来为止。

5. Makefile变量的定义和使用

Makefile 文件中定义变量的基本语法如下:

变量的名称=值列表
  • 在执行 make 的时候多余的空白符会被自动删除。
  • 调用变量的时候可以用 “$(VALUE_LIST)” 或者是 “${VALUE_LIST}” 来替换,这就是变量的引用。

四种基本赋值方式:

  • 简单赋值 ( := ) 编程语言中常规理解的赋值方式,只对当前语句的变量有效。
  • 递归赋值 ( = ) 赋值语句可能影响多个变量,所有目标变量相关的其他变量都受影响。
  • 条件赋值 ( ?= ) 如果变量未定义,则使用符号中的值定义变量。如果该变量已经赋值,则该赋值语句无效。
  • 追加赋值 ( += ) 原变量用空格隔开的方式追加一个新值。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值