Makefile知识点总结:

来源:互联网 发布:cl.4z3.pw index.php 编辑:程序博客网 时间:2024/06/03 20:19
#Makefile知识点总结:
#一、make的参数:
#make -B所有文件都编译
#make -h或者--help帮助文档
#make -t 显示出较新(修改过)的文件
#make -k 即使一个文件编译出错了,不要终止,继续编译其他文件。
#make -n / --just-print运行预览
#make -o指定生成文件
#make -s 不输出运行过程指令,只输出运行结果
#make -v查看make 版本信息
#make -r 取消隐含规则(编译规则都得自己写)

#二、隐含规则
#约定俗成的东西:
#make 时自动搜索Makefile/makefile文件;
#编译.c文件时默认指令:$(CC) -c $(CFLAGS) $(CPPFLAGS) ; .c文件编译时自动加上CFLAGS,CPPFLAGS;CC默认赋值为cc;
#编译.s文件时默认指令:$(AS) -c $(ASFLAGS) ;AS默认赋值为as;
#RM 默认为rm -f (删除)
#最好不要用隐含规则,因为.y文件可能生成.c文件。.c再生成.o文件。而中间的文件将会被RM掉
#模式规则:%表示任意字符(至少一个);比如%.c至少3个字符;s%.c至少4个字符。

#重载隐含规则:
#1、%.o:%.c  目标为模式.o对应模式.c  xx.o依赖于xx.c (akos的Makefile)
# $(CC) $(CFLAGS) -c -o $@ $<
#2、%.o:%.c ;第二行没有规则,同样取消隐含规则,实现重载

#老式风格“后缀”规则(会被模式规则取代,but为了兼容可以存在)
#双后缀规则:
#1、.c.o: #不能有依赖,且必须有规则。#相当于 %.o:%.c
# $(CC) $(CFLAGS) -c -o $@ $<
#
#2、.c.a: #不能有依赖,#相当于 %.o : %.c,最后再打包
# $(CC) $(CFLAGS) -c -o $@ $<
# $(AR) -r $@ $<

#三、自动化变量:
#1、$@目标的集合;(模式规则中逐个取出目标)
#2、$%库文件的成员;foo.a(foo.o),则$%为foo.o;
#3、$<第一个依赖(模式规则中逐个取出依赖)
#4、$?比目标新的依赖集合
#5、$^依赖的集合,依赖以空格分开,重复的依赖只去一个。
#6、$+依赖的集合,依赖以空格分开,重复的依赖都保存
#7、$*模式规则中的前部分; 比如:模式a.%.b ,若目标为dir/a.foo.b,则$*为dir/a.foo  

#老模式拓展
#D表示目录, F表示文件
#$(@D),表示目标文件的路径。与函数dir同
#$(@F),表示目标文件的文件。与函数 nodir 同

#四、Makefile参数
#-I<dir>包含搜索路径 .默认搜索路径/usr/include/
#-D<macro>定义宏;
#-L<path>指定动态链接库路径.默认搜索路径/lib/ /usr/lib/ /usr/local/lib/; ln -s libxxxx-x.x.x.so libxxxx.so
#-l<name>指定动态依赖库的名称,此处省去了[lib]name[.so]中括号的字符串。
#-shared指明生成动态库。比如:gcc -sahred test.c -o libtest.so

#五、模板
#1、伪目标
#.PHONY:all clean
#2、目标
#all:$(COBJS)  
# $(AR) -rsv target.a $(COBJS)
#3、模式编译规则
#$(COBJS):$(patsubst %.o,%.c,$(COBJS)) #第一种
#$(COBJS):$(COBJS:.o=.c) #第二种
#$(COBJS): %.o:%.c #第三种,推荐 #依赖只有c文件,故.h文件修改了需要清除后编译才能生效
#%.o:%.c #第四种,推荐 #所有.o的文件依赖于对应的.c文件
#.c.o: #第五种,#老式风格
# $(CC) $(CFLAGS) -DKUI -c -o $@ $< #规则
#4、清除
#clean:
# -rm -rf *.o *.a *.txt

#六、函数
#字符串操作函数
#1、字符串替换函数:$(subst <from>,<to>,<text>):把text字符串的from符号替换为to符号
# 举例:"$(subst ee,EE,feet)得到fEEt
#2、模式字符串替换函数:$(patsubst <pattern>,<replacement>,<text>) 。特定格式模糊的将text字符串中的pattern替换为replacement
# 举例:$(patsubst %.c,%.o, a.c b.c c.c)得到a.o b.o c.o
#3、去单词首尾多余空格函数:$(strip <string>) 。将字符串string开头结尾的空格去掉。
# 举例"  ab   c  " 得到:ab c 
#4、查找字符串函数:$(findstring <find>,<string>)。在字符串string里查找find字符串,找到则返回find字符串,否则返回空格
# 举例:$(findstring kui,chentengkui)得到kui
#5、过滤函数:$(filter <pattern...>,<text>)。在字符串里面过滤出以pattern模式的字符串。
# 举例:$(filter %.c,$(SOURCES)) 过滤出所有.c的文件
#6、反过滤函数:$(filter <pattern...>,<text>)。在字符串里面过滤出除了以pattern模式的字符串。
# 举例:$(filter-out %.c,$(SOURCES)) 过滤出所有除了.c的文件
#7、排序函数:$(sort <list>) 。单词升序排序。相同单词只留一个
# 举例:$(sort 1 3 2 4)得到1 2 3 4
#8、取序号单词函数:$(word <n>,<text>) 。从text中去序号为n的单词(从1开始算起).若n比text中的单词多,则返回空字符串
# 举例:$(word 2, one two three)得到two
#9、取区域单词函数:$(wordlist <start>,<end>,<text>) 。
# 从text中去序号为start 到序号为end的单词(从1开始算起)。若end大于text的单词,则返回到最后的单词。若start比text中的单词多,则返回空字符串
# 举例:$(wordlist 1,3,one two three four)得到:one two three
#10、统计单词数量函数:$(words <text>) 。
# 举例:$(words one two three four)得到4
#11、取首单词函数:$(firstword <text>)
# 举例:$(firstword one two three four)得到one

#文件名操作函数
#13、取目录名称函数:$(dir <names...>)  
# 举例:$(dir src/foo.c foo.c)得到src/ ./
#14、取文件名称函数:$(notdir <names...>)
# 举例:$(notdir src/foo.c foo.c)得到foo.c foo.c
#15、取后缀名称函数:$(suffix <names...>)
# 举例:$(suffix src/src/a.c src/b.s)得到:.c .s
#16、取前缀名称函数:$(basename <names...>)
# 举例:$(basename src/src/a.c src/b.s )得到:src/src/a src/b
#17、加后缀名称函数:$(addsuffix <suffix>,<names...>)
# 举例:$(addsuffix .c, a b c)得到:a.c b.c c.c
#18、加前缀名称函数:$(addprefix <prefix>,<names...>)
# 举例:$(addprefix src/, a.c b.c c.c)得到:src/a.c src/b.c src/c.c
#19、连接函数:$(join <list1>,<list2>)  #把字符串list2组个单词连接到list1后面去,最后为总数的集合
# 举例:$(join 11 11,22 22)得到1122 1122

#for循环函数
#20、for循环函数:$(foreach <var>,<list>,<logic>)。#从list中逐个取出各元素放到var变量中,在执行logic的语句。最后全部返回。备注:变量var为局部变量。
# 举例:$(foreach temp,a b c d,$(temp).c)得到a.c b.c c.c d.c

#if条件函数
#21、if条件函数: $(if <条件>,<不为空字符串时返回> ),若条件的字符部位空字符,则返回后面的数据
# 举例:$(if 123, yes)得到:yes
#if条件函数: $(if <条件>,<不为空字符串时返回> ,<为空字符串时返回>)
# 举例:$(if , yes,no)得到:no

#待整理....
#知识点:
#1、变量值替换:
# 1)后缀为.o的文件替换为后缀为.c 的文件: bar := $(foo:.o=.c)
# 2)静态模式:后缀为.o的文件替换为后缀为.c 的文件: bar := $(foo:%.o=%.c)
#2、变量的值赋给变量
#3、替换函数:
# 1)把后面字符串的1替换为2:$(subst 1,2,value1)  得到value2。
# 2)替换函数,与替换后缀相结合
#4、宏定义 ifdef else endif、判断是否为空字符串。
#5、追加符号 += 可读性好
#6、override:重写make参数赋值的变量
#7、条件语句:ifeq ,else,endif。ifneq。ifdef。ifndef
#7、变量定义:赋值时,后面有值则表示定义过了。ifdef测试则为真。否则为假

#知识点:
#1、自动化变量:1)第一个依赖元素:$<,  2)全部的依赖元素:$^  3)全部目标元素 $@
#2、静态模式编译 $(COBJS):%.o:%.c #(akos Makefile就是这种模式)
#规则: $(CC) $(CFLAGS) -c -o $@ $<
#3、过滤函数:$(filter, %.o, $(COBJS)), 从COBJS变量中过滤xx.o文件
#4、显示即将执行的命令: 1)去掉@echo中的@,2)make -n或者--just-print只打印即将执行命令。3)make -s 或者--silent禁止全部命令显示,只打印执行过程输出的数据
#5、本次运行结果为下次运行使用:(TAL)cd ..;pwd
#6、.PHONY:伪目标 伪目标 伪目标,举例:.PHONY all clean 6 (避免有文件与伪目标同名是出异常。如make 6,若存在6这个文件这出错了)
#7、make -i 或者--ignore-errors ,忽略错误,make -k 或者--keep-going忽略错误继续运行
#8、进入下级目录,再运行命令:(TAB)make -C src或者cd src && make
#9、将指定变量传递到下一级目录的Makefile,export 变量名: 如:export INCLUDE。 导出全部变量:export , 默认是全局变量:MAKEFLAGS(参数), MAKEFILES
#10、1)字符本身: *应写为\*, $应写为$$ 。举例:(TAB)@echo "* = " \*   (TAB)@echo "$$ = " $$  。
#10、2)变量取值:举例:$(INCLUDE)或者${INCLUDE}。 变量就是C语言的宏展开,最好加上括号,或者大括号。
#11、1)赋值符号 = 可以调用后面的变量。但可能会导致递归情况,不好。
#11、2)复制符号 := 不会调用后面的变量,类似c语言变量
#12、1)使用系统工具:cur_dir := $(shell pwd)
#12、2)注意下空格的使用。   3) FOO ?= bar, 若没有被赋值则赋值。等效于:ifeq ($(origin FOO), undefined) 下一行 FOO = ba 下一行 endif
#12、3)ifeq ($(变量), 值) 。q与( 之间一定要有空格

#if条件
ifeq ($(TEST9),Y)
CC = armcc
AR = armar

#宏定义 -D宏名字
DEFINE += -DAKOS

#路径 -I路径名字
INCLUDE = -I./inc/
CFLAGS     = -Otime -apcs  /interwork -cpu 5TEJ -Wxfdb $(DEFINE) $(INCLUDE)
#CPPFLAGS= $(DEFINE) $(INCLUDE)
COBJS = add.o sub.o demo.o

#伪目标
.PHONY: all clean

#目标:依赖;命令
all: $(COBJS)
echo "makefile test "
$(AR) -rsv target.a $(COBJS)

#编译规则,是之前编译模式的简化版
#$(COBJS):$(patsubst %.o,%.c,$(COBJS)) #第一种
#$(COBJS):$(COBJS:.o=.c) #第二种
$(COBJS):$(COBJS:%.o=%.c) #第三种
#$(COBJS): %.o:%.c #第四种,推荐
#%.o:%.c #第五种,推荐 #所有.o的文件依赖于对应的.c文件
#.c.o: #第六种   #老式风格编译规则
$(CC) $(CFLAGS) -DKUI -c -o $@ $<

#清除标识:
clean:
@echo "clean test"
-rm -rf *.o *.a *.txt
#条件语句结束
endif

KUI 20170309
原创粉丝点击