| 
 
| gnu实用工具 
 
 
 .h文件为头文件用来放函数和变量的声明。
 
 .c或者.cpp文件为源文件用来放函数或变量的定义。
 
 源文件编译之后生成目标文件(.o文件)
 
 将目标文件链接之后生成可执行文件
 
 将众多中间目标文件(.o文件)打包叫库文件(.a文件)
 
 
 
 编译:编译器只检查语法错误,函数和变量是否声明。
 
 链接:连接器将函数和全局变量链接,检查函数和变量的定义。
 
 
 
 写好makefile/Makefile文件,一个make命令可以自动搞定一些。
 
 
 
 makefile使用规则:
 
 1.如果工程没有编译过,需要编译和链接所有c文件和目标文件。
 
 2.如果工程里的某几个c文件被修改,只需要编译修改的c文件,并链接所有目标文件。
 
 3.如果头文件被修改,只需要编译引用了被修改的头文件的c文件,并链接所有目标文件。
 
 
 
 --------------------------------------------------
 
 makefile的格式:
 
 target . . . : prerequisites . . .
 
 command
 
 ...
 
 ...
 
 target:可以是.o文件、可执行文件、标签(lable),多个文件用空格分开。
 
 prerequisites:生成target所需要的文件或目标(目标文件或头文件等),多个文件用空格分开。
 
 
 
 command:跳格键tab开头,利用prerequisites生成target的shell命令(make需要执行的命令)
 
 
 
 可以在makefile文件的结尾定义一些标签,比如打包,备份,清空等:
 
 clean:
 
 rm    elf   a.o   b.o   c.o   d.o
 
 在执行make clean命令后就会删除所有的目标文件。
 
 
 
 可以使用续行符\
 
 
 
 make命令:执行makefile文件,会比较target和prerequisites的时间戳,如果prerequisites比target新,或者target不存在就会执行command,否则会跳过command。
 
 
 
 --------------------------------------------------
 
 共用的头文件可以简化
 
 
 
 a.o   :   a.h   b.h   c.h
 
 b.o   :   b.h   c.h   d.h
 
 c.0   :   c.h   d.h
 
 d.o   :   d.h
 
 等价于:
 
 $(obj)   :   d.h
 
 a.o   b.o   c.o   :   c.h
 
 a.o   b.o   :   b.h
 
 a.o   :   a.h
 
 
 
 --------------------------------------------------
 
 一个makefile组成
 
 
 
 obj = a.o b.o c.o d.o
 
 CC = gcc
 
 elf : $(obj)
 
 $(CC)     -o      elf      $(obj)
 
 $(obj)   :   d.h
 
 a.o   b.o   c.o   :   c.h
 
 a.o   b.o   :   b.h
 
 a.o   :   a.h
 
 .PHONY   :   clean
 
 clean :
 
 -rm   elf   $(obj)
 
 
 
 Makefile中有哪些内容:
 
 显式规则;
 
 隐晦规则;
 
 变量定义;
 
 文件指示:makefile中的引用和根据条件指定有效部分。
 
 #:使用#进行注释。
 
 
 
 @:在commands前面加@就会取消在终端显示执行编译等命令的信息,eg:
 
 @arm-linux-gcc ……
 
 
 
 --------------------------------------------------
 
 Make的工作顺序:
 
 1.     读入所有makefile
 
 2.     读入include的其他makefile
 
 3.     初始化变量
 
 4.     推导隐晦规则,分析所有规则
 
 5.     为所有目标文件创建依赖关系链
 
 6.     依据依赖关系,决定哪些目标需要重新生成
 
 7.     执行生成的命令
 
 
 
 --------------------------------------------------
 
 在makefile中引用其他的makefile
 
 
 
 -include   a.makefile   b.makefile   c.makefile   d.makefile
 
 make会在当前目录寻找文件,也会在/usr/local/bin或/usr/include找,并加载到当前位置;
 
 在include前面加-会忽略错误,继续执行。
 
 
 
 -I
 
 
 
 ---------------------------------------------------
 
 文件寻找
 
 
 
 当有大量源文件时,make只会在当前目录中寻找,需要另外指令路径。
 
 
 
 Makefile的特殊环境变量VPATH可以指定源文件路径,eg:VPATH=../mycode。
 
 
 
 还可以使用makefile的关键字vpath来指定路径,有三种用法:
 
 1.vpath                #为符合patern模式的文件指定搜索目录
 
 2.vpath                                         #清除符合模式patern的文件的搜索目录
 
 3.vpath                                                           #清除所有已经设置好的文件搜索目录
 
 Patern要以%开头。
 
 
 
 Eg:vpath   %.h   ../headers
 
 vpath   %.c   ../srcs
 
 
 
 --------------------------------------------------
 
 伪目标
 
 
 
 伪目标一般放在makefile文件结尾,在make命令中调用,在makefile中用.PHONY来指定,可同时定义多个伪目标,用空格分开,需要用make+伪目标名才能执行。
 
 
 
 可以给伪目标指定依赖文件,如果要一次生成多个可执行文件可以将伪目标放在文件开头,作为默认目标。
 
 all   :   elf1    elf2   elf3
 
 .PHONY   :   all
 
 这样make    all命令就会生成三个可执行文件。
 
 
 
 伪目标同样也可以作为其他目标的依赖。
 
 .PHONY: cleanall     cleanobj     cleanelf
 
 Cleanall: cleanobj     cleanelf
 
 
 
 makefile文件中加清空文件便于重新编译:
 
 clean :
 
 rm   elf   $(obj)
 
 更好的写法是:
 
 .PHONY   :   clean
 
 clean :
 
 -rm   elf   $(obj)
 
 用.PHONY来表示clean是一个伪目标。
 
 在rm前面加-表示忽略错误,继续向后执行。
 
 
 
 --------------------------------------------------
 
 多目标
 
 
 
 Eg:
 
 func-A-elf     func-B-elf:   same.h
 
 Generate   same.h     -$(funcname)   >   $@
 
 等价于:
 
 func-A-elf:   same.h
 
 Generate     same.h     -func-A   >   func-A-elf
 
 func-B-elf:   same.h
 
 Generate     same.h     -func-B   >   func-B-elf
 
 
 
 --------------------------------------------------
 
 静态模式
 
 
 
 静态模式可以更容易的定义多目标规则。
 
 
 
 语法格式:
 
 :        :
 
 
 
 Targets:定义了一组目标文件,可以有通配符。
 
 Target-pattern:指定了目标文件targets的模式。
 
 Prereq-pattern:目标的依赖模式。
 
 
 
 Eg:
 
 obj   =   a.o   b.o
 
 all :   $(objs)
 
 $(objs) :   %.o :   %.c
 
 $(CC)   -c   $(CFLAGS)   $<   -o   $@
 
 等价于:
 
 a.o :   a.c
 
 $(CC)   -c   $(CFLAGS)   a.c   -o   a.o
 
 b.o :   b.c
 
 $(CC)   -c   $(CFLAGS)   b.c   -o   b.o
 
 
 
 --------------------------------------------------
 
 自动生成依赖性
 
 
 
 .c文件包含了很多.h文件,修改不方便,为了处理这种关系。
 
 
 
 gcc   -MM   XXX.c           可以显示源文件和头文件的依赖关系。
 
 
 
 makefile中的处理办法:为每一个.c文件都生成一个.d文件用来存放对应的.c文件的依赖关系。
 
 
 
 产生.d文件的方法:
 
 %.d: %.c
 
 @set -e; rm -f $@; \                                                    #删除所有的目标文件.d文件
 
 $(CC) -M $(CPPFLAGS) $< > $@.$$$$; \                      #根据.c文件生成.d文件,$$$$是随机编号
 
 sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \     #替换
 
 rm -f $@.$$$$                                                             #删除临时文件
 
 
 
 --------------------------------------------------
 
 makefile中的命令:
 
 
 
 1.显示命令:
 
 @echo  XXXX       #只显示XXX
 
 
 
 make的参数:
 
 make   -n/--justprint               #只显示命令,不执行命令
 
 make   -s/--slient                    #禁止命令显示
 
 
 
 2.执行命令:
 
 如果下一条命令的执行需要依赖上一条命令,那么两条命令写在一行,中间用分号隔开。
 
 cd   /home/canux;pwd
 
 
 
 3.命令出错:
 
 如果某个命令出错整个规则执行都出错,为了忽略某个错误,让整个规则运行完,在命令前加-。
 
 
 
 make   -i/--ignore-errors          #某个命令出错,继续执行其他命令,忽略这个错误
 
 make   -k/--keep-going            #某个命令出错了,不执行这个规则,继续执行其他规则
 
 -S/--no-keep-going/--stop          #禁止-k选项
 
 
 
 4.嵌套执行make
 
 在大的工程里,不同模块和功能的源文件放在不同的目录中,所以在每个目录中有一个Makefile文件,在根目录写一个总控的Makefile,便于维护。
 
 
 
 smart210:
 
 cd     /board/sumsung/smart210 && $(MAKE)
 
 
 
 总控Makefile中的变量可以通过申明传递到下级Makefile中,但是不会覆盖下级Makefile中的变量。
 
 传递到下级Makefile的申明方法:
 
 export
 
 禁止传递到下级Makefile的申明方法:
 
 unexport
 
 传递所有变量:
 
 export
 
 
 
 等价于:
 
 variable := value
 
 export variableexport variable = value
 
 等价于:
 
 variable = value
 
 export variable
 
 等价于:
 
 export variable := value
 
 
 
 SHELL和MAKEFLAGS这两个变量总是要传递到下层Makefile中。
 
 MAKEFLAGS是make的参数,但是有几个参数不往下传递。
 
 
 
 5.定义命令包
 
 可以给相同命令序列定义一个变量,以define开始,以endef结束。
 
 define   变量名称
 
 命令1
 
 命令2
 
 ...
 
 endef
 
 
 
 --------------------------------------------------
 
 使用变量
 
 
 
 如果prerequisites包含的文件很多或者会重复用到,那么将这些文件当作一个字符串,给他取个别名:
 
 定义:
 
 obj  =  a.o   b.o   c.o   d.o
 
 使用:
 
 elf : $(obj)
 
 gcc   -o    target   $(obj)
 
 clean :
 
 rm   elf   $(obj)
 
 
 
 1.变量的基础
 
 变量:字符、数据、下划线组成,不应该含有:#=空格回车,大小写敏感。
 
 变量在定义是需要赋初值,在使用时需要$开头,最好还要用()或{}括起来。
 
 
 
 2.变量中的变量
 
 在定义变量时可以用其他变量来构造变量的值。
 
 
 
 一种就是用等号,左侧是变量右侧是值,右侧可以是还没有定义的变量,也可以是已经定义的变量。
 
 foo = $(bar)
 
 bar = $(ugh)
 
 ugh = huh
 
 
 
 另一种是使用:=,前面的变量不能使用后面的变量。
 
 x : = foo
 
 y := $(x) bar
 
 x := later
 
 等价于:
 
 y = foo bar
 
 x = later
 
 
 
 定义一个空格
 
 nullstring:=
 
 space:=$(nullstring)#end of the line
 
 #用来表示变量的结束,前面的空格都属于变量的内容。
 
 
 
 foo ?= bar
 
 ?=符号表示如果foo没有被定义过那么foo=bar,如果foo之前被定义过,那么这条语句无效。
 
 
 
 3.变量的高级用法
 
 
 
 变量值的替换:
 
 格式:$(var:a=b)或 ${var:a=b}
 
 将变量var中以a结尾的元素中的a替换成b,eg:
 
 foo := a.o b.o
 
 bar:=$(foo:.o=.c)
 
 等价于:
 
 bar := a.c b.c
 
 
 
 静态模式定义的变量替换:
 
 foo := a.o b.o c.o
 
 bar := $(foo:%.o=%.c)
 
 依赖于被替换的字符串中有相同的模式,所以可以用%来替换。
 
 
 
 把变量的值再当成变量:
 
 x=y
 
 y=z
 
 a:=$($(x))
 
 等价于
 
 a=z
 
 
 
 通过给参数赋值得到变量的不同的值
 
 a_objects := a.o b.o c.o
 
 1_objects := 1.o 2.o 3.o
 
 sources := $($(a1)_objects:.o=.c)
 
 
 
 ifdef so_sort
 
 func := sort
 
 else
 
 func := strip
 
 endif
 
 bar := a s g k s
 
 foo := $($(func) $(bar))
 
 
 
 把变量当变量也可以用在操作符的左边:
 
 dir = foo
 
 $(dir)_source := $(wildcard $(dir)/*.c)
 
 define $(dir)_print
 
 lpr $($(dir)_source)
 
 endef
 
 
 
 4.追加变量
 
 可以使用+=操作符给变量追加值
 
 obj = a.o b.o c.o
 
 obj += d.o
 
 还可以
 
 obj = $(obj) d.o
 
 
 
 如果变量没有定义过那么+=就等价于=,如果定义过就追加。
 
 如果之前为:=那么+=就是:=
 
 如果之前为=那么+=就是=
 
 
 
 5.override指示符
 
 如果在Makefile中已经定义的变量,又通过make的命令行参数来设置或是环境变量,那么Makefile对这些变量的赋值会被忽略,如果想在makefile中设置这类参数的值,那么可以使用override重定义。
 
 override =
 
 override :=
 
 override +=
 
 
 
 6.多行变量
 
 使用define关键字来设置变量的值,可以换行。
 
 define   变量名
 
 命令
 
 函数
 
 文字
 
 变量
 
 endef
 
 
 
 7.环境变量
 
 系统的环境变量会在make开始运行时载入,如果在Makefile中定义了这个变量,或通过make命令传递个这个变量,那么默认系统变量会被覆盖。
 
 make -e    #系统环境变量会覆盖Makefile中定义的变量。
 
 
 
 在嵌套调用的Makefile中,上层Makefile中定义的环境变量会以系统环境变量的方式传递到下层Makefile。变量需要用export申明才能传递。
 
 
 
 8.目标变量
 
 为某个目标设置局部变量,这个变量只在这条规则和连带规则中有效,这个局部变量也只在这个作用范围有效。局部变量可以和全局变量同名。
 
 
 
 格式:
 
 :
 
 : override
 
 
 
 prog : CFLAGS = -g     #定义局部变量
 
 prog : prog.o foo.o
 
 prog.o : prog.c
 
 $(CC) $(CFLAGS) prog.c
 
 foo.o : foo.c
 
 $(CC) $(CFLAGS) foo.c
 
 不管全局变量CFLAGS是什么,在生成prog目标过程中都是-g。
 
 
 
 9.模式变量
 
 给定一种模式,然后把变量定义在所有符合这种模式的目标上。
 
 
 
 格式:
 
 :     #自定义变量
 
 : override     #系统默认环境变量或make命令传入的变量
 
 
 
 %.o : CFLAGS = -O
 
 所有.o文件的参数都是-O。
 
 
 
 --------------------------------------------------
 
 使用条件判断
 
 
 
 endif
 
 
 
 else
 
 endif
 
 
 
 表示条件关键字,有四个:
 
 
 
 ifeq:比较两个参数是否相等。
 
 ifeq(,)
 
 
 
 ifneq:比较两个参数是否不相等。
 
 ifneq(,)
 
 
 
 ifdef:变量值非空,表达式值为真。
 
 ifdef
 
 
 
 ifndef:变量值为空,表达式值为真。
 
 ifndef
 
 
 
 自动化变量不要放进条件表达式。
 
 
 
 --------------------------------------------------
 
 makefile能使用函数
 
 
 
 1.函数的调用语法
 
 
 
 $( )
 
 ${ }
 
 
 
 function:make支持的函数名
 
 arguments:函数参数,以,分割多个参数。
 
 make调用函数像调用变量一样,需要$开头,然后用(){}括起来。
 
 
 
 2.字符串处理函数
 
 
 
 字符串替换函数:
 
 $(subst ,,)
 
 把字符串中的替换成
 
 
 
 模式字符串替换函数:
 
 $(patsubst ,,)
 
 查找中的单词,单词用空格、tab、回车分割,如果单词符合模式,就以替换。pattern可以用通配符%来表示任意长度的单词,如果replacement中也有%,那么replacement中的%就是pattern中的%所表示的单词。
 
 
 
 去空格函数:
 
 $(strip )
 
 去掉字符串开头和结尾的空字符
 
 
 
 查找字符串函数:
 
 $(findstring ,)
 
 在字符串中查找字符串,如果找到然会,否则返回空。
 
 
 
 过滤函数:
 
 $(filter ,)
 
 以模式过滤字符串中的单词,保留符合模式的单词,返回符合模式的字符串。
 
 
 
 反过滤函数:
 
 $(filter-out ,)
 
 以模式过滤字符串中的单词,除去符合模式的单词,返回不符合模式的字串。
 
 
 
 排序函数:
 
 $(sort )
 
 给字串中的单词排序,默认是升序,按照首字母从小到大。
 
 
 
 取单词函数:
 
 $(word ,)
 
 取字符串中的第个单词,从1开始,如果超过字串大小就返回空。
 
 
 
 取单词串函数:
 
 $(wordlist ,,)
 
 从字符串中取从到的单词字串,如果s超出就返回空,如果e超出就返回没有超出的部分。
 
 
 
 单词个数统计函数:
 
 $(words )
 
 从中统计单词个数。
 
 
 
 首单词函数:
 
 $(firstword )
 
 去中的第一个单词。
 
 
 
 3.文件名操作函数
 
 
 
 取目录函数
 
 $(dir )
 
 从names中取出目录部分,也就是/之前的部分,如果没有/就返回./;
 
 总的来说就是除去单纯的文件名。
 
 
 
 取文件函数
 
 $(notdir )
 
 从names中取出文件,除去目录部分。
 
 
 
 取后缀函数
 
 $(suffix )
 
 从names中取出文件名的后缀,如果没有后缀就返回空串。
 
 
 
 取前缀函数
 
 $(basename )
 
 从names中取出文件名的前缀部分,如果没有前缀就返回空串。
 
 所谓前缀就是除了后缀剩下的部分。
 
 
 
 加后缀函数
 
 $(addsuffix ,)
 
 把后缀加到中的每个单词后面。
 
 
 
 加前缀函数
 
 $(addprefix , )
 
 把前缀加到中的每个单词前面。
 
 
 
 连接函数
 
 $(join ,)
 
 就是把list2中的单词按照位置的对应顺序加到list1中的后面形成一个行的单词序列。
 
 如果list1的单词多,多出来的就不变;如果list2单词多,多出来的就复制到list1后面。
 
 
 
 4.foreach循环函数
 
 语法:
 
 $(foreach ,,)
 
 var是一个变量;
 
 list是一个表达式,由多个单词组成;
 
 text是一般使用var这个变量来枚举list中的单词。
 
 
 
 foreach每次从list中取一个单词赋值给var,text每次根据var的值得到一个结果,
 
 最后返回text的所有结果组成的序列,每次的结果空格分开。
 
 
 
 5.if条件函数
 
 语法:
 
 $(if ,)
 
 $(if ,,)
 
 condition是表达式,如果表达式返回非空字符串,那么表达式为真,执行then-part;
 
 否则执行else-part;返回执行的结果。
 
 
 
 6.call函数
 
 $(call ,,...)
 
 call会用parm 1等参数替换expression这个表达式原来的参数,expression表达式的返回值就是call的函数的返回值。
 
 
 
 7.origin定位函数
 
 $(origin )
 
 定位variable这个变量的定义情况,variable只能是变量名。
 
 
 
 返回结果:
 
 undefined:未定义
 
 default:默认定义
 
 environment:环境变量
 
 file:在Makefile中定义的变量
 
 conmandline:在命令行定义的变量
 
 override:用override重定义的变量
 
 automatic:自动化变量
 
 
 
 8.shell函数
 
 $(shell )
 
 执行shell命令command,返回命令执行结果。
 
 
 
 9.控制make的函数
 
 
 
 产生一个致命的错误:
 
 $(error )
 
 是错误信息;调用这个函数make会产生一个致命错误然后退出运行。
 
 
 
 输出一段警告信息:
 
 $(warning )
 
 是错误信息,调用这个函数打印这个错误信息,make继续运行。
 
 
 
 --------------------------------------------------
 
 make命令的运行
 
 
 
 1.make的退出码
 
 0:成功执行
 
 1:出错返回1
 
 2:使用make的-q选项并且使得一些目标不需要更新,返回2.
 
 
 
 2.指定Makefile
 
 
 
 gnu的make命令默认在当前目录按顺序找三个文件:
 
 GNUmakefile、makefile、Makefile,找到就执行。
 
 
 
 make   -f/--file/--makefile    filename    #可以用参数来指定另外的make文件。
 
 
 
 3.指定目标
 
 
 
 默认make的最终目标是Makefile中的第一个目标,其他目标都是第一个目标连带出来的。
 
 make只执行终极目标和这个终极目标连带的目标,其他的目标不执行。
 
 
 
 任何Makefile中的目标(包括伪目标)都可以被指定成终极目标:make     目标名称
 
 环境变量MAKECMDGOALS存放了指定的终极目标的列表。
 
 
 
 可以写一些伪目标:
 
 all:编译所有目标
 
 clean:删除所有make创建出来的文件
 
 intall:安装已编译好的程序
 
 print:列出改变过的源文件
 
 tar:把源程序打包备份
 
 dist:创建一个压缩文件
 
 TAGS:更新所有目标
 
 check和test:测试Makefile流程
 
 
 
 4.检查规则
 
 
 
 make   -n/--just-print/--dry-run/--recon     #不还行makefile中的规则,只检查命令或执行序列
 
 只打印命令,把规则和连带规则下的命令打印出来,不执行命令。
 
 
 
 make   -t/--touch          #把目标文件的时间更新,但不更改目标文件
 
 就是假装编译目标,但是只是更新了时间没有真正更新。
 
 
 
 make   -W /--what-if=/--assume-new=/--new-file=
 
 指定一个源文件或依赖文件,make会自动推导来运行依赖于这个文件的命令。
 
 
 
 5.make的参数
 
 
 
 -b/-m          #忽略和其他版本make的兼容性
 
 
 
 -B/--always-make          #所有目标都重新编译
 
 
 
 -C
 
 /--directory=
 
 #指定读取makefile的目录
 
 
 
 -debug[=]     #输出make的调试信息
 
 options的取值:
 
 a:输出所有调试信息
 
 b:输出不需要重新编译的目标
 
 v:输出更多不需要重新编译的文件
 
 i:输出所有隐含规则
 
 j:输出执行规则中命令的详细信息
 
 m:输出make读取、更新、执行Makefile的信息
 
 
 
 -d            #相当于-debug=a
 
 
 
 -e/--environment-overrides          #指明环境变量的值覆盖Makefile中的变量的值
 
 
 
 -j[]/--jobs[=]          #指定同时运行的命令的个数
 
 
 
 -l /--load-average[=]/-max-load[=]          #指定make运行命令的负载
 
 
 
 -o /--old-file=/==assume-old=          #指定不重新生成的目标文件,即使依赖文件比目标文件新
 
 
 
 -p/--print-data-base          #输出Makefile中所有数据,包括规则和变量
 
 
 
 -q/--question          #仅检查指定的目标是否需要更新,0表示需要更新,2表示出错
 
 
 
 -r/--no-builtin-rules          #禁止make使用任何隐含规则
 
 
 
 -R/--no-builtin-variabes          #禁止make使用任何作用于变量上的隐含规则
 
 
 
 -s/--silent/--quiet          #在命令运行时不输出命令的输出
 
 
 
 -w/--print-derectory          #输出运行makefile之前和之后的信息。
 
 
 
 --no-print-directory          #禁止-w选项
 
 
 
 --warn-undefined-variables          #只要make发现没有定义的变量就输出警告信息
 
 
 
 --------------------------------------------------
 
 隐含规则
 
 
 
 make的自动推导功能:只要make看到.o文件,就会自动关联.c文件,同时command中的gcc也会自动关联:
 
 a.o   :   a.c   a.h
 
 gcc   -c   a.c   a.h
 
 等价于:
 
 a.o   :   a.h
 
 
 
 make有自己的隐含规则库,从前到后进行自动推导,如果自定义的规则省略了,那么就调用隐含规则。
 
 
 
 1.编译c程序的隐含规则
 
 .o会自动将依赖目标推导为.c,并且自动推导命令为$(CC)   -c   $(CPPFLAGS)  $(CFLAGS)
 
 
 
 2.编译c++程序的隐含规则
 
 .o目标会自动推导依赖为.cc或.C,生成命令$(CXX)   -c   $(CPPFLAGS)   $(CFLAGS)
 
 
 
 3.汇编和汇编预处理的隐含规则
 
 .o目标会自动推导依赖目标为.s,默认使用编译器as,生成命令$(AS)   $(ASFLAGS).
 
 .s会自动推导依赖为.S,默认使用c预编译器,生成命令为$(AS)   $(ASFLAGS)
 
 
 
 4.链接文件的隐含规则
 
 目标依赖于.o,一般使用c编译器运行链接程序ld,生成命令为$(CC)   $(LDFLAGS)   .o   $(LOADLIBES)   $(LDLIBS)
 
 
 
 -----------------------------
 
 隐含规则使用的变量
 
 
 
 如果你在Makefile中重新定义了隐含规则中的变量那么会使用用户定义的变量。
 
 否则就使用默认的变量。
 
 
 
 1.和命令相关的变量
 
 AR       函数打包命令ar
 
 AS       汇编语言编译程序as
 
 LD        链接程序ld
 
 CC       c语言编译程序gcc
 
 CXX      c++语言编译程序g++
 
 CPP      c程序预处理器$(CC)   -E
 
 RM       删除文件命令rm   -f
 
 
 
 2.和命令参数相关的变量
 
 ARFLAGS           函数库打包程序ar命令的参数
 
 ASFLAGS           汇编编译器命令as参数
 
 CFLAGS             c语言编译器参数
 
 CXXFLAGS          c++语言编译器参数
 
 CPPFLAGS         c预处理器参数
 
 LDFLAGS           连接器参数
 
 
 
 -----------------------------
 
 定义模式规则
 
 
 
 %.o : %.c
 
 $(CC)   -c   $(CFLAGS)   $(CPPFLAGS)   $<   -o   $@
 
 依赖的%决定目标的%。
 
 
 
 自动化变量
 
 $^                                                    所有的依赖文件,除去了重复的依赖
 
 $<                                                    第一个依赖文件
 
 $@                                                   目标文件
 
 $*                                                   不包含扩展名的目标文件名称
 
 $+                                                   所有的依赖文件,用空格分开,包含重复的依赖
 
 $?                                                   所有时间戳比目标文件新的依赖文件,以空格分开
 
 $%                                                 如果目标是函数库成员,则表示目标的成员
 
 
 
 自动化变量加上D或F可以获取文件的目录名或当前目录符合模式的文件名。
 
 $(@D)     得到$@的目录
 
 $(@F)     得到$@的文件名
 
 其他同理
 
 
 
 -----------------------------
 
 makefile也兼容老风格的后缀规则
 
 
 
 .c.o是双后缀等价于%.o:%.c
 
 .c是单后缀等价于%:%.c
 
 后缀规则不能有依赖文件,只能有目标
 
 
 
 .c.o:
 
 $(CC)  -c  $(CFLAGS)  $(CPPFLAGS)  -o  $@  $<</div>
 
 
 
 make能自动识别一些后缀,也可以用伪目标.SUFFIXES来定义后缀
 
 .SUFFIXES : .hack .win          #定义自己的后缀
 
 .SUFFIXES     #删除默认后缀
 
 
 
 --------------------------------------------------
 
 使用make更新函数库文件
 
 
 
 函数库就是目标文件的打包文件,一般用ar来打包。
 
 
 
 函数库文件和它的组成格式:archive(member1  member2...)
 
 
 
 foolib(hack.o kludge.o) : hack.o kludge.o
 
 ar cr foolib   hack.o   kludge.o
 
 
 
 (%.o) : %.c
 
 $(CC)  $(CFLAGS)  $(CPPFLAGS)  -c  $<  -o  $*.o
 
 $(AR)  R  $@  $*.o
 
 $(RM)  $*.o
 | 
 |