makefile知识
1、 Makefile五大内容(显示规则、隐晦规则、变量定义、文件指示、注释)
1.1、显示规则:如何生成一个或多个目标文件(要生成的文件,文件依赖的文件,生成命令);stm32: main.o hello.o
gcc -o stm32 main.o hello.o
1.2、隐晦规则:Makefile的自动推导功能,所以隐晦规则可以编写更加粗简的Makefile文件。main.o: includes.h
1.3、变量定义:定义一系列字符串变量,类似C语言中的宏定义,变量扩展到对应引用位置 objs = main.o led.o... 引用 -rm stm32 $(objs)
1.4、文件指示:①在一个Makefile中应用另一个Makefile,类似C语言的include一样。②根据某些情况指定Makefile中的有效部分,类似C语言中的预编译#if。
include <filename>,其中filename是当前操作系统Shell的文件模式(可以保含路径和通配符); include foo.make *.mk $(bar)
1.5、注释:行注释(#)
2、 make 的工作执行步骤
1.1、读入所有的Makefile
1.2、读入被include的其它Makefile
1.3、初始化文件中的变量
1.4、推导隐晦规则,并分析所有规则
1.5、为所有的目标文件创建依赖关系链
1.6、根据依赖关系,决定哪些目标要重新生成
1.7、执行生成命令
3、 编译(compile)--中间目标文件(Object File)
1.1、每个源文件编译成一个对应的中间目标文件;
1.2、Windows:编译生成.obj文件;
1.3、UNIX: 编译生成.o文件,使用cc;
1.4、Linux:编译生成.o文件,使用gcc;
4、 链接(Link)—链接对应文件
1.1、把大量的object file 合成执行文件的动作叫链接;
1.2、打包中间目标文件,Windows系统就是打包库文件(Library File),也就是.lib文件;在Unix系统就是Archive File,也就是 .a 文件。
5、 语法规则
Targets ... : prerequisites ...
command
...
...
1.1、target 可以是中间目标文件(Object File),也可以是执行文件,更可以为标签(Label);
1.2、prerequisites 是要生成target所需要的文件或者目标;
1.3、command 是make需要执行的命令(任意的shell命令,必须[Tab]键开始)
1.3.1、-c : 编译产生中间目标文件(object file),而不是链接可执行文件;
$gcc -c led.c --->led.o
1.3.2、-o: 用户指定输出文件名;
$gcc led.c -o led.o
1.3.3、-g: 指明编译程序在编译的输出中应产生调试信息;
1.3.4、-O: 优化选项,-O0~3,其中0是不优化,3级优化
$gcc -c O3 led.c
1.3.5、-L: 指定连接库的搜索目录,-l指定连接库名称,-L与-l一般成对出现;
$gcc main.o -L/usr/lib -lqt -o hello
1.3.6、-Wall :打印出编译时所有的错误或者警告信息
1.4、通过make命令执行;
1.5、通过make clean 执行清除所以目标文件,以便重新编译。
6、 使用变量
1.0、变量的命名字可以包含字符、数字,下划线(可以是数字开头),但不应该含有“:”、“#”、“=”或是空字符(空格、回车等),变量是大小写敏感的,建议大小写混合使用 Objects。
1.1、如我们的中间目标文件使用objs变量代替
objs := main.o kbd.o display.o (“:=”操作符可以避免变量无限展开,建议使用“:=”)
1.2、引用变量 $(objs)
1.3、操作符“?=” (FOO ?= bar 如果FOO没有被定义过,那么变量FOO的值就是“bar”,如果FOO先前被定义过,那么这条语将什么也不做)
7、 make自动推导能力
1.1、make看到[.o]文件,会自动把[.c]文件加入依赖关系中
如找到led.o文件,那么led.c就会变为依赖文件,同时会推导出 gcc -c led.c
原先:led.o: led.c led.h include.h
gcc -c led.c
自动推导:led.o: led.h include.h
8、 另类风格Makefile(根据自动推导能力,收拢[.o]和[.h]文件),不建议使用。
1.1、$(objs) : include.h #目标文件变量都引用了include.h
Kdb.o files.o : defs.h #部分目标文件引用了defs.h
9、 清空目标文件的规则:伪目标
.PHONY : clean
Clean :
-rm edit $(objs) #在命令行前加一个减号“-”(在Tab键之后),标记为不管命令出不出错都认为是成功的
10、 引用其他的Makefile
Include <filename>,其中filename是当前操作系统Shell的文件模式(可以保含路径和通配符)
11、 通配符”*” “ ~” “...” “?”
*代表系列文件;如*.c表示所有后缀.c文件。(用”/”转义符“/*”来表示真实的*)
rm -f *.o
~在文件名中也有比较特殊的用途,如~/test表示/home目录下的test目录。
?表示一个自动化变量。
12、 文件搜寻
1.1、 使用特殊变量“VPATH”,make就会在当当前目录找不到的情况下,到所指定的目录中去找寻文件。VPATH = src : ../bps (指定了src 和../bps 两个目录,多个目录用分号隔开)
1.2、 使用关键字“vpath”,更为灵活,可以指定不同的文件在不同的搜索目录中。
① vpath <pattern> <directories> #为符合模式<pattern>的文件指定搜索目录<directories> 如vpath %.h ../includes “%”的意思是匹配零或若干字符
② Vpath <pattern> #清除符合模式<pattern>的文件的搜索目录
③ Vpath #清除所有已被设置好了的文件搜索目录
13、 变量高级用法
1.1、变量值的替换 “$(var:a=b)”或${var:a=b}意思是把变量“var”中所有以“a”字串“结尾”的“a”替换成“b”字串。
foo := a.o b.o #定义变量
bar := $(foo:.o = .c) #把a.o b.o 替换为a.c b.c
或者bar := $(foo:%.o = %.c) #这依赖于被替换字串中的有相同的模式,模式中必须包含一个“%”字符。
1.2、 把变量的值再当成变量
x = y #$(x)的值为y
y = z #$(y)的值为z
a := $($(x)) #$(a)的值为z
14、 追加变量值
1.1、使用“+=”操作符给变量追加值
objects = main.o led.o
objects += key.o #objects的值变为“main.o led.o key.o”
15、 多行变量
1.1、使用define关键字设置变量的值可以有换行,以endef关键字结束。
define two-lines
echo foo
echo $(bar)
endef
16、 调用函数 $(<function> <arguments>)
1.1、字符串替代函数--subst
$(subst <from>,<to>,<text>) #把字串<text>中的<from>字符串替换成<to>
$(subst ee,EE, free of street)#把“ee”替换成“EE”,返回“frEE of strEEt”
1.2、模式字符串替换函数--patsubst
$(patsubst <pattern>,<replacement>,<text>) #查找<text>中的单词(单词以“空格”、“Tab”或“回车”“换行”分隔)是否符合模式<pattern>,如果匹配的话,则以<replacement>替换.
$(patsubst %.c,%.o,x.c.c a.c) #把“x.c.c a.c”符合模式[%.c]的单词替换成[%.o].返回“x.c.o a.o”
1.3、去空格函数--strip
$(strip <string>) #去掉<string>字串中开头和结尾的空字符
$(strip a b c )#把“a b c ”字符串的空格去掉返回“a b c”
1.4、 查找字符串函数--findstring
$(findstring <find>,<in>)#在字串<in>中查找<find>字串,找到返回<find>,没找到返回空字符串
$(findstring a, a b c)#返回“a”
$(findstring a, b c)#返回“”空字符串
1.5、过滤函数--filter
$(filter <pattern...>,<text>) #以<pattern>模式过滤<text>字符串中的单词,保留符合模式<pattern>的单词,支持多个模式,返回符合<pattren...>模式的字符串
source := foo.c bar.c baz.s key.h
foo: $(source)
cc $(filter %.c %.s, $(source)) -o foo
#$(filter %.c %.s, $(source)) 返回的值“foo.c bar.c baz.s”
1.6、 反过滤函数--filter-out
$(filter-out <pattern...>,<text>)#以<pattern>模式过滤<text>字符串中的单词,去除符合模式<pattern>的单词。可以有多个模式,返回不符合模式<pattern>的字符串。
1.7、 排序函数--sort
$(sort <list>)#给字符串<list>中的单词排序(升序),返回排序后的字符串。
$(sort foo bar lose)#返回“bar foo lose”,该函数会弃掉<list>中的相同单词。
1.8、 取单词函数--word
$(word <n>,<text>)#取字符串<text>中第<n>个单词,返回字符串<text>中第<n>个单词。如果<n>比<text>中的单词数要大,那么返回空字符串。
$(word 2, foo bar baz)返回值是“bar”.
1.9、 取单词串函数--wordlist
$(wordlist <s>,<e>,<text>)#从字符串<text>中取从<s>开始到<e>的单词串。<s>和<e>是一个数字.
$(wordlist 2, 3, foo bar baz)返回值是“bar baz”
1.10、 单词个数统计函数--words
$(words <text>)#统计<text>中字符串中的单词个数
$(words, foo bar baz)返回值是“3”
1.11、 首单词函数——firstword
$(firstword <text>)#取字符串<text>中的第一个单词
$(firstword foo bar)返回值是“foo”
1.12、 取目录函数——dir
$(dir <name...>)#从文件名序列<names>中取出目录部分。目录部分是指最后一个反斜杠(“/”)之前的部分。如果没有反斜杠,那么返回“./”。
$(dir src/foo.c hacks)返回值是“src/ ./”。
1.13、 取文件函数——notdir
$(notdir <names...>)#从文件名序列<names>中取出非目录部分。非目录部分是指最后一个反斜杠(“/”)之后的部分。
$(notdir src/foo.c hacks)返回值是“foo.c hacks”。
1.14、 取后缀函数——suffix
$(suffix <names...>)#从文件名序列<names>中取出各个文件名的后缀
$(suffix src/foo.c src-1.0/bar.c hacks)返回值是“.c .c”。
1.15、 取前缀函数——basename
$(basename <names...>)#从文件名序列<names>中取出各个文件名的前缀部分
$(basename src/foo.c src-1.0/bar.c hacks)返回值是“src/foo src-1.0/bar hacks”。
1.16、 加后缀函数——addsuffix
$(addsuffix <suffix>,<names...>)#把后缀<suffix>加到<names>中的每个单词后面。
$(addsuffix .c,foo bar)返回值是“foo.c bar.c”。
1.17、 加前缀函数——addprefix
$(addprefix <prefix>,<names...>)#把前缀<prefix>加到<names>中的每个单词后面
$(addprefix src/,foo bar)返回值是“src/foo src/bar”。
1.18、 连接函数——join
$(join <list1>,<list2>)#把<list2>中的单词对应地加到<list1>的单词后面。如果<list1>的单词个数要比<list2>的多,那么,<list1>中的多出来的单词将保持原样。如果<list2>的单词个数要比<list1>多,那么,<list2>多出来的单词将被复制到<list2>中
$(join aaa bbb , 111 222 333)返回值是“aaa111 bbb222 333”。
1.19、循环函数--foreach
$(foreach <var>,<list>,<text>)#把参数<list>中的单词逐一取出放到参数<var>所指定的变量中,然后再执行<text>所包含的表达式。每一次<text>会返回一个字符串,循环过程中,<text>的所返回的每个字符串会以空格分隔,最后当整个循环结束时,<text>所返回的每个字符串所组成的整个字符串(以空格分隔)将会是foreach函数的返回值。
name := a b c d
files = $(foreach n,$(name),$(n).o) #$(name)中的单词会被挨个取出,并存到变量“n”中,“$(n).o”每次根据“$(n)”计算出一个值,这些值以空格分隔,最后作为foreach函数的返回,所以,$(files)的值是“a.o b.o c.o d.o”。
1.20、
17、 make 的退出码:0 (执行成功返回0)、1(任何错误返回1)、2 (使用“-q”选项,不更新返回2)。
18、 模式规则(模式规则中,至少在规则的目标定义中要包含"%")
%.o:%.c,<command...>
%.o:%.c
$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ #所有的[.c]文件都编译成[.o]文件
19、 自动化变量
$@ #表示模式规则中的目标文件集。
$% #仅当目标是函数库文件中,表示规则中的目标成员名。
$< #依赖目标中的第一个目标名字。
$? #所有比目标新的依赖目标的集合,以空格分隔。
$^ #所有的依赖目标的集合,以空格分隔。
20、 “=”、“:=”、“?=”、“+=”的差异
1.1、“=”是进行赋值,变量值等于Makefile最后赋的值。例如:var_a = A,var_b = $(var_a) BB var_a = AA 最终var_b 的值为AA BB
1.2、“:=”是直接赋值,赋予当前位置的值。例如:var_a := A,var_b := $(var_a) BB var_a := AA 最终var_b 的值为A BB .这个才是意义上的赋值。
1.3、 “?=”是如果该变量没有被赋值,则赋予等号后的值。例如:var := old var ?= new那么此时var的值仍为old。
1.4、“+=”是将等号后面的值添加到前面的变量上。例如:var = a.c b.c var += c.c 那么此时var的值为a.c b.c c.c。
21、
22、
23、
标签:文件,bar,makefile,基础知识,单词,字符串,var,foo From: https://www.cnblogs.com/zblblog/p/18382949