Makefile总结

http://www.cnblogs.com/wang_yb/p/3990952.html

1. Makefile 简介

Makefile 是和 make 命令一起配合使用的.

很多大型项目的编译都是通过 Makefile 来组织的, 如果没有 Makefile, 那很多项目中各种库和代码之间的依赖关系不知会多复杂.

Makefile的组织流程的能力如此之强, 不仅可以用来编译项目, 还可以用来组织我们平时的一些日常操作. 这个需要大家发挥自己的想象力.

1.1  Makefile基本格式如下:

 
  1. target ... : prerequisites ...

  2. command

  3. ...

  4. ...

 

其中,

  • target        - 目标文件, 可以是 Object File, 也可以是可执行文件
  • prerequisites - 生成 target 所需要的文件或者目标
  • command       - make需要执行的命令 (任意的shell命令), Makefile中的命令必须以 [tab] 开头

1.2 Makefile 主要的 5个部分 (显示规则, 隐晦规则, 变量定义, 文件指示, 注释)

  1. 显示规则 :: 说明如何生成一个或多个目标文件(包括 生成的文件, 文件的依赖文件, 生成的命令)
  2. 隐晦规则 :: make的自动推导功能所执行的规则
  3. 变量定义 :: Makefile中定义的变量
  4. 文件指示 :: Makefile中引用其他Makefile; 指定Makefile中有效部分; 定义一个多行命令
  5. 注释     :: Makefile只有行注释 "#", 如果要使用或者输出"#"字符, 需要进行转义, "\#"

 1.3 GNU make 的工作方式

  1. 读入主Makefile (主Makefile中可以引用其他Makefile)
  2. 读入被include的其他Makefile
  3. 初始化文件中的变量
  4. 推导隐晦规则, 并分析所有规则
  5. 为所有的目标文件创建依赖关系链
  6. 根据依赖关系, 决定哪些目标要重新生成
  7. 执行生成命令

2. Makefile 初级语法

2.1 Makefile 规则

2.1.1 规则语法

规则主要有2部分: 依赖关系 和 生成目标的方法.

语法有以下2种:

 
  1. target ... : prerequisites ...

  2. command

  3. ...

 
  1. target ... : prerequisites ; command

  2. command

  3. ...

*注* command太长, 可以用 "\" 作为换行符

2.1.2 规则中的通配符

  • *     :: 表示任意一个或多个字符
  • ?     :: 表示任意一个字符
  • [...] :: ex. [abcd] 表示a,b,c,d中任意一个字符, [^abcd]表示除a,b,c,d以外的字符, [0-9]表示 0~9中任意一个数字
  • ~     :: 表示用户的home目录

2.1.3 路径搜索

当一个Makefile中涉及到大量源文件时(这些源文件和Makefile极有可能不在同一个目录中),

这时, 最好将源文件的路径明确在Makefile中, 便于编译时查找. Makefile中有个特殊的变量 VPATH 就是完成这个功能的.

指定了 VPATH 之后, 如果当前目录中没有找到相应文件或依赖的文件, Makefile 回到 VPATH 指定的路径中再去查找..

VPATH 使用方法:

  • vpath <directories>            :: 当前目录中找不到文件时, 就从<directories>中搜索
  • vpath <pattern> <directories>  :: 符合<pattern>格式的文件, 就从<directories>中搜索
  • vpath <pattern>                :: 清除符合<pattern>格式的文件搜索路径
  • vpath                          :: 清除所有已经设置好的文件路径
 
  1. # 示例1 - 当前目录中找不到文件时, 按顺序从 src目录 ../parent-dir目录中查找文件

  2. VPATH src:../parent-dir

  3.  
  4. # 示例2 - .h结尾的文件都从 ./header 目录中查找

  5. VPATH %.h ./header

  6.  
  7. # 示例3 - 清除示例2中设置的规则

  8. VPATH %.h

  9.  
  10. # 示例4 - 清除所有VPATH的设置

  11. VPATH

2.2 Makefile 中的变量

2.2.1 变量定义 ( = or := )

 
  1. OBJS = programA.o programB.o

  2. OBJS-ADD = $(OBJS) programC.o

  3. # 或者

  4. OBJS := programA.o programB.o

  5. OBJS-ADD := $(OBJS) programC.o

其中 = 和 := 的区别在于, := 只能使用前面定义好的变量, = 可以使用后面定义的变量

测试

    测试=

 

 
  1. file1=aaa.c

  2. file2=$(file1) world

  3. ##输出aaa.c world

  4.  
  5.  
  6.  
  7. file2=$(file1) world

  8. file1=aaa.c

  9. ##输出aaa.c world

  10.  

测试:=

 
  1. file1:=$(file1) world

  2. file1=bbvbbb.c

  3.  
  4. text:

  5. echo $(file2)

  6. ##这里输出的是 world

  7.  
  8. #而 file1在这里被认为是空的

2.2.2 变量替换

 
  1. sources=main.c hello.c

  2. objs=$(sources:%.c=%.o)

  3.  
  4. all:

  5. @echo $(sources)

  6. @echo $(objs)

  7. ##在这里输出为main.c hello.c

  8. main.o hello.c

2.2.3 变量追加值 +=      变量的空赋值?=

 
  1. # ?= 变量为空则赋值,不为空则不赋值

  2. # += 原值基础上追加新的值

  3.  
  4. #sources=haha.c

  5. sources?=main.c

  6. sources+=hello.c

  7.  
  8. all:

  9. @echo $(sources)

  10.  
  11. #在这里输出为 main.c hello.c

2.2.4 自动变量

 
  1. # 自动变量:

  2. #

  3. # 对每一条Makefile规则,Make维护了一些自动变量。

  4. # $< 第一个依赖文件的名称。

  5. # $@ 目标的完整名称。

  6. # $^ 所有的依赖文件,以空格分开,不包含重复的依赖文件。

  7. # $* 不包含扩展名的目标文件名称。

  8. # $+ 所有的依赖文件,以空格分开,并以出现的先后为序,

  9. # 可能包含重复的依赖文件。

  10. # $? 所有的依赖文件,以空格分开,这些依赖文件的修改日期比

  11. # 目标的创建日期晚。

  12. # $% 如果目标是归档成员,则该变量表示目标的归档成员名称。

  13. # 例如,如果目标名称为 mytarget.so(image.o),

  14. # 则 $@ 为 mytarget.so,而 $% 为 image.o。

2.2.5 变量覆盖 override

作用是使 Makefile中定义的变量能够覆盖 make 命令参数中指定的变量

语法:

  • override <variable> = <value>
  • override <variable> := <value>
  • override <variable> += <value>

 

下面通过一个例子体会 override 的作用

 
  1. # Makefile内容 (没有用override)

  2. SRCS := programA.c programB.c programC.c

  3.  
  4. all:

  5. @echo "SRCS: " $(SRCS)

  6.  
  7. # bash中运行make

  8. $ make SRCS=nothing

  9. SRCS: nothing

  10.  
  11. #################################################

  12.  
  13. # Makefile内容 (用override)

  14. override SRCS := programA.c programB.c programC.c

  15.  
  16. all:

  17. @echo "SRCS: " $(SRCS)

  18.  
  19. # bash中运行make

  20. $ make SRCS=nothing

  21. SRCS: programA.c programB.c programC.c

2.2.5 目标变量

作用是使变量的作用域仅限于这个目标(target), 而不像之前例子中定义的变量, 对整个Makefile都有效.

语法:

  • <target ...> :: <variable-assignment>
  • <target ...> :: override <variable-assignment> (override作用参见 变量覆盖的介绍)
 
  1. # Makefile 内容

  2. SRCS := programA.c programB.c programC.c

  3.  
  4. target1: TARGET1-SRCS := programD.c

  5. target1:

  6. @echo "SRCS: " $(SRCS)

  7. @echo "SRCS: " $(TARGET1-SRCS)

  8.  
  9. target2:

  10. @echo "SRCS: " $(SRCS)

  11. @echo "SRCS: " $(TARGET1-SRCS)

  12.  
  13. # bash中执行make

  14. $ make target1

  15. SRCS: programA.c programB.c programC.c

  16. SRCS: programD.c

  17.  
  18. $ make target2 <-- target2中显示不了 $(TARGET1-SRCS)

  19. SRCS: programA.c programB.c programC.c

  20. SRCS:

2.3 Makefile 命令前缀

Makefile 中书写shell命令时可以加2种前缀 @ 和 -, 或者不用前缀.

3种格式的shell命令区别如下:

  • 不用前缀 :: 输出执行的命令以及命令执行的结果, 出错的话停止执行
  • 前缀 @   :: 只输出命令执行的结果, 出错的话停止执行
  • 前缀 -   :: 命令执行有错的话, 忽略错误, 继续执行
 
  1. # Makefile 内容 (不用前缀)

  2. all:

  3. echo "没有前缀"

  4. cat this_file_not_exist

  5. echo "错误之后的命令" <-- 这条命令不会被执行

  6.  
  7. # bash中执行 make

  8. $ make

  9. echo "没有前缀" <-- 命令本身显示出来

  10. 没有前缀 <-- 命令执行结果显示出来

  11. cat this_file_not_exist

  12. cat: this_file_not_exist: No such file or directory

  13. make: *** [all] Error 1

  14.  
  15. ###########################################################

  16.  
  17. # Makefile 内容 (前缀 @)

  18. all:

  19. @echo "没有前缀"

  20. @cat this_file_not_exist

  21. @echo "错误之后的命令" <-- 这条命令不会被执行

  22.  
  23. # bash中执行 make

  24. $ make

  25. 没有前缀 <-- 只有命令执行的结果, 不显示命令本身

  26. cat: this_file_not_exist: No such file or directory

  27. make: *** [all] Error 1

  28.  
  29. ###########################################################

  30.  
  31. # Makefile 内容 (前缀 -)

  32. all:

  33. -echo "没有前缀"

  34. -cat this_file_not_exist

  35. -echo "错误之后的命令" <-- 这条命令会被执行

  36.  
  37. # bash中执行 make

  38. $ make

  39. echo "没有前缀" <-- 命令本身显示出来

  40. 没有前缀 <-- 命令执行结果显示出来

  41. cat this_file_not_exist

  42. cat: this_file_not_exist: No such file or directory

  43. make: [all] Error 1 (ignored)

  44. echo "错误之后的命令" <-- 出错之后的命令也会显示

  45. 错误之后的命令 <-- 出错之后的命令也会执行

2.4 伪目标

伪目标并不是一个"目标(target)", 不像真正的目标那样会生成一个目标文件.

典型的伪目标是 Makefile 中用来清理编译过程中中间文件的 clean 伪目标, 一般格式如下:

 
  1. .PHONY: clean <-- 这句没有也行, 但是最好加上

  2. clean:

  3. -rm -f *.o

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值