Makefile快速学习上手

Makefile快速学习上手

一、Makefile介绍

1、Makefile规则

 

target ... : prerequisites ...

command

...

 

(1)command一定要以Tab开头

(2)prerequisites中若有一个文件比target新,或target不存在,command命令就会执行。

 

2、make是如何工作的

(1)在当前目录下找Makefile或makefile

(2)找第一个target,作为最终的目标文件

(3)若target不存在或依赖的修改时间比它新,就执行后面定义的命令

(4)依次以依赖循环下去,直到生成最终目标

 

3、变量

定义:OBJ = main.o test.o

使用:$(OBJ)

 

4、自动推导

make找到*.o那么*.c就是其依赖文件。

 

二、Makefile总述

1、Makefile组成

(1)显式规则:如何生成目标文件

(2)隐晦规则:自动推导

(3)变量定义:变量一般是字符串

(4)文件指示:①引用另一个Makefile ②指定有效部分

(5)注释:#

(6)命令必须tab开头

 

2、Makefile文件名

make默认寻找GNUmakefile、makefile、Makefile,也可使用-f或--file指定

 

3、引用其他Makefile

include ...

(1)前面可以有空格,但不能是tab。

(2)默认在当前目录寻找,然后/usr/local/bin或/usr/include

(3)-I 或 --include-dir指定目录

(4)未找到文件生成警告消息,继续执行,再次寻找时会产生致命信息

(5)-include <filename>加横杆忽略错误

 

4、工作方式

(1)读Makefile

(2)include

(3)初始化变量

(4)推导隐晦规则

(5)创建依赖关系链

(6)根据依赖关系,决定哪些目标重新生成

(7)执行命令

 

三、书写规则

1、通配符

*, ?, [...]

 

2、伪目标

.PHONY : clean

避免和文件重名

 

3、多目标

$@所有目标集合

 

4、静态模式

<targets ...>:<target-pattern>:<prereq-patterns ...>

<commands>

...

targets 定义了一系列目标文件

target-parrtern 指明模式

prereq-patterns 目标的依赖模式

 

objects = foo.o bar.o

all: $(objects)

$(objects): %.o: %.c

$(CC) -c $(CFLAGS) $< -o $@

 

5、自动生成依赖

-M 自动寻找源文件中包含的头文件,并生成依赖关系

-MM 避免包含标准库头文件

 

%d: %.c

@set -e; rm -rf $@; \

$(CC) -M $(CPPFLAGS) $< > $@.$$$$; \

sed `s, \($*\)\.o[ :]*,\1.o $@ : ,g` < $@.$$$$ > $@; \

rm -f $@.$$$$

 

四、书写命令

1、显式命令

① @在命令前,不显示执行的命令

② make -n 或 --just-print只显式不执行

 

2、命令执行

① 后一条命令依赖前一条命令的结果,需写在一行用";"分开

 

3、命令出错

① 命令出错终止执行

② 加横杆-,忽略错误

③ make -i 或者 --ignore-errors,忽略所有命令的错误

 

4、嵌套执行

subsystem:

cd subdir && $(MAKE)

subsystem:

$(MAKE) -C subdir

 

① Makefile变量可以传递到下级,但不会覆盖,除非指定-e参数

② export <variable ...> 传递到下级,后面不跟变量表示传递所有变量

③ unexport <variable ...> 不传递到下级

 

5、定义命令包

define run-yacc

yacc $(firstwword $^)

mv y.tab.c $@

endef

 

foo.c: foo.y

$(run-yacc)

 

五、变量

由字符、数字、下划线组成,大小写敏感

1、声明时赋初值,使用$引用,最好加()或{}

使用$字符,$$

 

2、使用时赋值

foo = $(bar)

bar = 123

 

3、立即赋值

x := foo

y := $$(x)

x := later

 

4、判断赋值,未赋值才赋值

FOO ?= 456

 

5、追加变量赋值

x = test.c

x += main.c

 

6、参数变量

make CC=gcc

 

7、override覆盖参数变量值

override CC = g++

override CC := g++

 

8、多行变量

define two-lines

echo foo # 可以是函数、命令、文字、其他变量

echo $(bar)

endef

 

9、环境变量

① Makefile中可使用环境变量,make参数和里面定义的变量会覆盖环境变量

② 若make -e则环境变量覆盖他们

③ 上层Makefile中变量可使用export声明传递到下层

 

10、目标变量

<target ...>: <variable-assignment>

<target ...>: override <variable-assignment>

 

11、模式变量

<pattern ...>: <variable-assignment>

<pattern ...>: override <variable-assignment>

%.o: CFLAGS = -O

 

六、条件判断

条件表达式可以是比较变量的值、变量、常量

 

1、ifeq ($(CC), gcc)

@echo ""

else

@echo ""

endif

 

2、语法

<conditional-directive>

<text-if-true>

endif

 

<conditional-directive>

<text-if-true>

else

<text-if-true>

endif

 

ifeq (<arg1>, <arg2>)

ifeq '<arg1>' '<arg2>'

ifeq "<arg1>" "<arg2>"

ifeq "<arg1>" '<arg2>'

ifeq '<arg1>' "<arg2>"

 

ifdef foo #测试变量是否有值

 

七、函数

1、函数调用

$(<function> <arguments>)

${<function> <arguments>}

 

bar := $(subst $(sub), $(value), $(main))

 

2、字符串处理函数

$(subst <from>, <to>, <text>) # 替换子字符串

$(patsubst <pattern>, <replacement>, <text>) # 模式替换字符串

$(strip <string>) # 去除首位的空格

$(findstring <find>, <in>) # 查找字符串是否存在

$(filter <pattern...>, <text>) # 模式过滤字符串

$(filter-out <pattern...>, <text>) # 反过滤字符串

$(sort <list>) # 给字符串中的单词升序排序

$(word <n>, <text>) # 取text中第n个单词

$(wordlist <s>, <e>, <text>) # 取text中第s到e中的单词

$(words <text>) # 统计单词个数

$(firstword <text>) # 取第一个单词

 

3、文件名操作函数

$(dir <names...>) # 取目录

$(suffix <names...>) # 取后缀

$(basename <names...>) # 取前缀

$(addsuffix <suffix>, <names...>) # 加后缀

$(addprefix <prefix>, <names...>) # 加前缀

$(join <list1>, <list2>) # 单词连接

 

4、foreach

$(foreach <var>, <list>, <text>) # 逐个参数值处理

names := a b c d

files := $(foreach n,$(names),$(n).o)

 

5、if函数

$(if <condition>, <then-part>) 或

$(if <condition>, <then-part>, <else-part>)

 

6、call函数

$(call <expression>, <parm1>, <parm2>, <parm3>...)

 

reverse = $(1) $(2)

foo = $(call reverse, a, b)

 

7、shell函数

files := $(shell echo *.c)

生成shell程序来执行命令,注意性能问题

 

八、make的运行

1、make退出码

0 成功,1 错误,2 make -q,使得一些目标不需要更新

2、指定文件-f或--file

 

3、指定目标

① make install,make clean

② "="或"-"开头时会被解析成参数或变量

③ MAKECMDGOALS环境变量指定目标

④ 常用功能

all :编译所有目标

clean:删除创建的文件

print:列出改变过的源文件

tar:打包源程序

dist:创建压缩文件

TAGS:更新所有目标,以备完整地重编译使用

check和test:测试Makefile的流程

4、检查规则

参数:-n、--just-print、--dry-run,--recon

5、参数

① -b和-m忽略和其他make版本的兼容性

② -B和--always-make重编译

③ -C和--directory=<dir>指定读取Makefile的目录

④ -e和--environment-overrides指明环境变量的值覆盖makefile中值

⑤ -f、--file、--makefile指定文件

⑥ -h和--help显式帮助信息

⑦ -i和--ignore-errors忽略执行错误

⑧ -I 和--include-dir=指定包含makefile的搜索目标

⑨ -j和--jobs指定同时运行命令个数

11 -q和--question检查目标是否需要更新

12 -r和--nobuiltin-rules禁止make使用任何隐含规则

 

九、隐含规则

1、make自动推导规则和命令

2、-r和--no-builtin-rules取消隐含规则,有默认后缀列表的还是会生效

3、常用隐含规则

① C语言,<n>.o的目标的依赖会自动推导为<n>.c

② c++,<n>.o的目标的依赖会自动推导为<n>.cc或<n>.C

③ 汇编和汇编预处理,<n>.o的目标的依赖会自动推导为<n>.s

 

4、隐含规则使用变量

① 命令变量

AR :ar 函数库打包

AS :as 汇编语言编译

CXX :g++

CPP :c程序预处理器

RM :rm -rf

 

② 命令参数变量

ARFLAGS :rv 函数库打包程序AR的参数

ASFLAGS :汇编语言编译器参数

CFLAGS :c语言编译器参数

CXXFLAGS:c++语言编译器参数

CPPFLAGS:c预处理器参数

LDFLAGS :链接器参数

 

5、隐含规则链

产生中间文件

 

6、定义模式规则

1、目标中%表示对文件名的匹配,%.c或s.%.c

 

2、示例

%.o : %.c

$(CC) -c $(CFLAGS) $(LDFLAGS) $< -o $@

 

$< 依赖挨个值,$@ 目标挨个值

 

7、自动变量

把模式中所定义的一系列的文件自动地挨个取出。

 

$@ 目标文件集,若有多个目标匹配于目标中模式定义的集合

$% 仅当目标是函数库文件中,表示规则中的目标成员名

$< 依赖目标中的第一个目标名字

$? 所有比目标新的依赖目标的集合

$^ 所有依赖目标的集合,去除重复

$+ 与$^相似,但不去重

$* 表示目标模式中%及其之前的部分。如dir/a.foo.b模式a.%.b, $*为dir/a.foo

$(@D) 表示$@的目录部分

$(@F) 表示$@的文件部分

$(*D)、$(*F) 与前两个相似,但不包含后缀

$(<D)、$(<F) 表示第一个依赖的目录和文件部分

$(^D)、$(^F) 表示所有依赖的目录和文件部分,无相同

$(+D)、$(+F) 表示所有依赖的目录和文件部分,可相同

$(?D)、$(?F) 表示被更新的依赖的目录和文件部分

 

8、模式匹配

① 依赖目标的茎会传给目标

② 有斜杆时会先将目录部分移开,匹配成功后再加回去。

 

十、更新函数库文件

1、隐含规则

%.o会去找bar.o, 没有的话去找bar.c来生成bar.o

cc -c bar.c -o bar.o

ar r foo.a bar.o

rm -rf bar.o

 

2、后缀规则

.c.a:

$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $*.o

$(AR) r $@ $*.o

$(RM) $*.o

等效:

(%.o) : %.c

$(CC) $(CFLAGS) $(CPPFLAGS) -C $< -o $*.o

$(AR) r $@ $*.o

$(RM) $*.o

 

并行机制-j可以损坏函数库

 

十一、实例

#################################################

BIN = main

OBJS = a.o b.o c.o

CFLAGS = -Werror -Iinclude

CC = gcc

 

DEPENDE_FILES := $(patsubst %, .%.d, $(OBJS))

DEPENDE_FILES := $(wildcard $(DEPENDE_FILES))

 

$(BIN): $(OBJS)

$(CC) -o $@ $^

 

ifneq ($(DEPENDE_FILES),)

include $(DEPENDE_FILES)

endif

 

%.o : %.c

$(CC) $(CFLAGS) -c -o $@ $< -MD -MF .$@.d

 

clean:

rm *.o $(BIN)

 

distclean:

rm $(DEPENDE_FILES)

 

.PHONY: clean

#################################################

 

参考《一起来写Makefile》

欢迎转载请注明出处:海漩涡

http://blog.csdn.net/tanhuifang520

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值