序
什么是Makefile?如果你是熟练运用各大集成开发环境的程序猿可能对这个不是太了解,因为Makefile的工作IDE都已经给你做了,如果你是在Linux下编程,那Makefile你就再熟悉不过了。什么?你说你不是程序猿?那你点进来干嘛,出去出去!
Makefile主要就是管理整个工程的编译、链接,比如说一个.c文件你要先用GCC编译成.o,然后多个.o再链接成可执行文件,如果你写好一个Makefile,那么你只需要在控制台输入一个make回车就好了。虽然各个厂商的Makefile语法会有写区别,但大体是类似的,这里就不多做区分了,本文是一个大杂烩。
结构
一般在工程是根目录下会有一个主Makefile文件作为编译入口,在控制台输入make后执行的就是这个文件,在子目录中也有一个Makefile文件,每个Makefile文件管理自己所在的目录(当然,这不是绝对的)。
语法
符号
**\ **: 反斜杠,指下一行还算本行,有时单行太长会进行换行,但Makefile语法上换行就是一条语句的结束了,为了代码阅读方便会在行末使用一个“\”来进行换行
$:取变量的值,如var := 123 那么 $(var)就表示var这个变量的值,也就是123(变量可以不加括号,但一般都加)若要表示$时则用两个$表示($$)
=: 是最基本的赋值,但值是整个文件最后一次赋值的值,如a=1 b=$(a) a=2,此时b的值为2(比较奇葩所以一般不用)
:=: 是覆盖之前的值,依赖与当前所在位置,如a:=1 b=$(a) a:=2,此时b的值为1(比较常见的赋值逻辑,常用的赋值方式)
?=: 是如果没有被赋值过就赋予等号后面的值,如果赋值过就不再赋值(一般用于参数的默认值,Makefile间可以传参)
+=: 是添加等号后面的值,连接之后中间会有一个空格,如 a=abc a+=def,a的值为abc def(一般用于添加依赖文件)
关键字
ifeq ifneq ifdef ifndef else endif 想必这些不用解释吧
include:包含文件,即在所在位置展开文件,和c文件包含头文件类似,如果找不到且Makefile不会创建这个文件,那么编译报错(No such file or directory)
-include:类似include,但找不到文件时不报错
sinclude:同-include,GNU所支持的书写方式
函数
函数的调用方法:很像变量的使用,也是以“$”来标识的,参数间用“,”隔开
$(<function> <arguments1>,<arguments2>... )
$(subst <from>,<to>,<text>):字符串替换,把字串<text>中的<from>字符串替换成<to>,返回替换后的字符串
$(strip <string>):去掉<string>字串中开头和结尾的空字符
$(findstring <find>,<in>):在字串<in>中查找<find>字串,如果找到,那么返回<find>,否则返回空字符串
$(filter <pattern>,<text>):过滤器,将<text>集中符合<pattern>的过滤出来。如$(filter %.o,a.o a.c a.h)结果为a.o
$(dir <names...>):从文件名序列<names>中取出目录部分。目录部分是指最后一个反斜杠(“/”)之
前的部分。如果没有反斜杠,那么返回“./”。如$(dir src/foo.c hacks)返回值是“src/ ./”
$(notdir <names...>):从文件名序列<names>中取出文件名。即最后一个反斜杠“/”之后的部分
$(suffix <names...>):从文件名序列<names>中取出各个文件名的后缀
$(basename <names...>):从文件名序列<names>中取出各个文件名的前缀。如$(basename src/foo.c)结果为src/foo
$(foreach <var>,<list>,<text>):把参数<list>中的单词逐一取出放到参数<var>变量中,然后再执行<text>表达式。每一次<text>会返回一个字符串,循环结束后,<text>的所返回字符串以空格分隔连接成新的字符串返回。如names:= a b c d $(foreach n,$(names),$(n).o)结果为“a.o b.o c.o d.o”
$(if <condition>,<then-part>,<else-part>):if函数,<condition>为空时返回<then-part>否则返回<else-part>
$(wildcard <string>):基于当前目录使用通配符列出所有文件
$(patsubst <pattern>,<replacement>,<text>):使用通配符替换字符串。如$(patsubst %.c,%.o,a.c b.c)结果为a.o b.o
$(shell <cmd>):执行Linux的shell命令
$(lastword <names...>):返回最后一个字串。如$(lastword foo bar)返回bar
$(call <expression>,<parm1>,<parm2>,<parm3>...):函数调用,<expression>中的变量,如$(1),$(2),$(3)等,会被参数<parm1>,<parm2>,<parm3>取代。<expression>的返回值就是call函数的返回值。如$(call $(1) $(2),a,b)结果为“a b”
$(eval <text>):将text放回Makefile文件当成Makefile脚本再解析一遍。这个有点绕,如$(eval aa:aa.c)相当于直接写aa:aa.c,这个的意义在于aa:aa.c这个字串是可以由Makefile脚本生成的
$(error <text ...>):产生一个致命的错误,<text ...>是错误信息
$(warning <text ...>):产生一个警告,<text ...>是警告信息
命令的变量
Makefile会有一些隐含规则,如.o文件依赖于.c文件,这个我们可以不写,会自动调用编译C程序的隐含规则的命令“$(CC) –c $(CFLAGS) $(CPPFLAGS)”来生成,这里用到的变量值是可以设置的(一般用来更改默认编译器)
AR 函数库打包程序。默认命令是“ar”。
AS 汇编语言编译程序。默认命令是“as”。
CC C语言编译程序。默认命令是“cc”。
CXX C++语言编译程序。默认命令是“g++”。
CO 从 RCS文件中扩展文件程序。默认命令是“co”。
CPP C程序的预处理器(输出是标准输出设备)。默认命令是“$(CC) –E”。
FC Fortran 和 Ratfor 的编译器和预处理程序。默认命令是“f77”。
GET 从SCCS文件中扩展文件的程序。默认命令是“get”。
LEX Lex方法分析器程序(针对于C或Ratfor)。默认命令是“lex”。
PC Pascal语言编译程序。默认命令是“pc”。
YACC Yacc文法分析器(针对于C程序)。默认命令是“yacc”。
YACCR Yacc文法分析器(针对于Ratfor程序)。默认命令是“yacc –r”。
MAKEINFO 转换Texinfo源文件(.texi)到Info文件程序。默认命令是“makeinfo”。
TEX 从TeX源文件创建TeX DVI文件的程序。默认命令是“tex”。
TEXI2DVI 从Texinfo源文件创建军TeX DVI 文件的程序。默认命令是“texi2dvi”。
WEAVE 转换Web到TeX的程序。默认命令是“weave”。
CWEAVE 转换C Web 到 TeX的程序。默认命令是“cweave”。
TANGLE 转换Web到Pascal语言的程序。默认命令是“tangle”。
CTANGLE 转换C Web 到 C。默认命令是“ctangle”。
RM 删除文件命令。默认命令是“rm –f”。
MAKE 即make
ARFLAGS 函数库打包程序AR命令的参数。默认值是“rv”。
ASFLAGS 汇编语言编译器参数。(当明显地调用“.s”或“.S”文件时)。
CFLAGS C语言编译器参数。
CXXFLAGS C++语言编译器参数。
COFLAGS RCS命令参数。
CPPFLAGS C预处理器参数。( C 和 Fortran 编译器也会用到)。
FFLAGS Fortran语言编译器参数。
GFLAGS SCCS “get”程序参数。
LDFLAGS 链接器参数。(如:“ld”)
LFLAGS Lex文法分析器参数。
PFLAGS Pascal语言编译器参数。
RFLAGS Ratfor 程序的Fortran 编译器参数。
YFLAGS Yacc文法分析器参数。
MAKEFILE_LIST make程序在读取makefile文件的时候将文件名加入此变量,多个文件用空格隔开
显示命令
在命令前面加@符号表示执行时不显示命令只显示输出。如"@echo 这是输出字符"在样在控制台只输出"这是输出字符"如果不加@则会输出"echo 这是输出字符"后换行再输出"这是输出字符"
注:未完待续
网友评论