构建makefile文件

来源:互联网 发布:ios7软件下载 编辑:程序博客网 时间:2024/06/04 23:31

makefile文件入门

makefile文件的组成内容

makefile 文件主要有一下5种组成部分

  • 显示规则:显示规则说明了生成一个或多个目标文件的发改发和步骤.
  • 隐式规则:由于make工具有自动推导的功能, 所以在编写makefile文件的时候可以利用该规则,简略地书写makefile.
  • 变量的定义:make工具支持变量的定义,这些变量往往都是字符串,因此makefile中的变量更像是c语言中的宏.
  • 文件指示:其包括3部分,,一部分是在一个makefile中引用另一个makefile,就像c语言中的include一样.另一部分是根据某些情况指定makefile中的有效部分,就像c语言中的与编译#if一样.还有一部分就是定义多行的命令.
  • 注释: makefile中支持行注释. ‘#’

makefile文件包含

  1. 指定make编译指定的makefile文件.

    make -f make.admin

  2. 在makefile中使用include关键字可以把其他的makefile包含进来.

    include <文件名>
    include /home/admin/make.mk *.mk

  3. 如果make工具下执行文件时,用户设置了-I或者–include-dir参数,make工具就会在用户指定的目录下寻找需要包含的makefile文件.

    make –include-dir /home/admin

  4. 如果目录< prefix>/include(一般是’usr/local/bin’或’/usr/include’)存在,make工具也会在这些目录中寻找需要包含的文件.

  5. 用户可以忽略make工具产生的出错信息,而使makefile文件一直执行下去.

    -i < filename>

makefile工具的退出码

makefile文件执行后有一个退出码,该退出码有一下3种情况.

  • 0: 表示makefile文件成功执行.
  • 1: 表示makefile文件执行时出现了错误.
  • 2: 如果用户使用了make的-q选项,并且make使一些目标不需要更新,则返回2.

书写makefile规则

使用基本规则

makefile规则的语法可以有以下2种形式.
第一种形式的调用格式如下:
targets : prerequisites
++++command
++++…
第二种形式的调用格式如下:
targets : prerequisites ; command
++++command
++++…

targets表示目标,目标有2种,第1种是在执行过程中产生的文件名,第2种是某个动作的名称.
command表示命令,如果其不与目标文件和文件依赖规则依赖在统一行,则必须以Tab键开头.如果和文件依赖规则在一行,那么可以用分号隔开.
prerequisites表示生成目标文件所依赖的文件.如果其中的某个文件比目标文件要新,make工具会认为目标文件’需要更新’,make工具会重新生成新的目标文件.如果命令太长,可以使用’\’作为换行符.make工具对一行有多少个字符没有限制.而对于’更新’这个概念,make工具有明确的定义,如果规则的目标满足以下之一,就称为需要更新:
* 目标文件没有生成.
* 某个条件中的文件修改时间比目标文件晚.
* 某个条件中的文件需要更新.
在一条规则被执行之前,规则的条件可能处于以下3种状态.
* 需要更新.
* 不需要更新.
* 错误.
当执行一条规则A时,需要逐个检查它的条件B.
* 如果B需要更新,就执行以B为目标的规则C.之后, 无论是否生成B,都认为B已经被更新.
* 如果找不到C, 并且B已经存在,表示B不需要更新.
* 如果找不到C, 并且B不存在,报告错误, 退出执行.
* 在检查完A的所有条件后,检查A的目标.如果该目标需要更新,就执行A的命令.

使用隐式规则

make工具会自动使用 gcc -c 命令, 将一个扩展为 .c 的C语言程序文件编译成一个同名的.o文件.因此当编译一个单独的.c文件到.o文件时,可以使用隐含规则,让make工具自己推导规则.

使用伪目标

clean伪目标
clean :
++++rm edit main.o kbd.o command.o display.o \
++++insert.o search.o files.o utils.o
由于伪目标不是真正的文件,所以make工具无法生成其依赖关系,并且决定该目标是否需要执行.例如:
.PHONY : clean
伪目标也可以作为默认目标此时其位置必须是第1个目标.

使用通配符

makefile文件允许在规则中使用通配符.make工具支持3种通配符”*”,”?”,”[…]”.”~”字表示用户的根目录,该目标通常是由$HOME环境变量所保存.makefile中使用”~”和一个相对路径组合,生成一个完整的路径.如下所示:
~/admin

搜索源文件

  1. 设置vpath变量
    vpath = src:../include
    vpath变量的值被定义为2个目录,分别是src和../include,表示make工具顺序搜索当前目录,当前目录下的include目录.每个目录由”:”分隔.
  2. 使用vpath变量

    • 指定特定模式的文件搜索目录.
      vpath < pattern> < directories>
    • 指定文件的模式.
      vpath < pattern>
    • 清除所有的文件搜索目录.
      vpath

vpath使用方法中的< pattern>需要包含%字符.%的意思是匹配若干个字符(字符数大于等于0).

vpath指定不同的搜索策略(按声明的先后顺序):
vpath %.c /src
vpath %.c /backup
vpath %.c /home/admin

也可以写成一行:
vpath %.c /src : /backup : /home/admin

使用命令

显示命令

make工具会把执行的命令行在命令执行前输出到屏幕上.
@echo compling…..

如果make工具执行时,make参数时-n或–just-print,则可以只显示命令,但不会执行命令.

执行命令

make -s all

如果需要使用上一条命令的结果应用在下一条命令时,应当使用”;”分隔这条命令.

命令出错

每当命令行运行完后,make工具会检测每个命令的返回码.

用户需要忽略命令的出错.make工具支持在规则的命令行前加一个减号”-“(在Tab键之后),忽略对该命令执行结果的判断,如下所示:

clean:
++++-rm -f *.c

表示rm命令出错,该规则也会执行,而不会停止执行该规则.

make 的参数-i或者–ignore-errors可以使makefile文件中所有命令都忽略错误.如果一个规则是以.IGNOREchanging作为目标的,那么这个规则中的所有的命令将会忽略错误,如下所示.

clean:
++++rm -f *.c
.IGNORE : clean

使用变量

使用普通变量

用户可以在makefile文件中定义变量,makefile文件中的变量代表了一个字符串.

makefile变量的命名可以包含字符,数字,下划线(可以是数字开头),并且大小写敏感.

makefile变量在声明的时候需要对其进行赋值,而在使用该变量时需要在变量名前加$符号,例如 $ (VAR).

如果用户需要在makefile文件中使用真实的$字符,则使用$$来表示.

变量中的变量

  1. 使用”=”操作符
    该操作非常简单,”=”左侧时变量,右侧是变量的值,右侧变量的值可以定义在文件的任何一处.也就是说,右侧的变量不一定是已定义好的值,其也可以使用后面定义的值.
  2. 使用”:=”操作符
    使用其定义变量时,前面的变量不能使用后面的变量,只能使用前面已经定义好的变量.如果使用前面未定义的变量,则该变量的值为空.
  3. 使用”?=”操作符
    该操作符的含义是, 如果变量之前没有被定义过,那么变量的值就被定义.如果变量的值之前被定义过了,则赋值语句什么也不做.

追加变量的值

makefile文件允许给一个变量追加一个值,其操作符为”+=”.

自动化变量

自动化变量 表示的意义 $@ 表示规则中的目标集 $% 仅当目标是函数库文件时,表示规则中的目标成员名.例如,如果一个目标是foo.a(bar.o),那么,$%就是bar.o,$@就是foo.a.如果目标不是函数库文件,其值为空 $< 依赖列表中的第一个依赖的名字 $? 所有比目标新的依赖的集合,以空格分隔 $^ 所有依赖的集合,以空格分隔.如果在依赖中有多个重复的,那个这个变量会去除重复的依赖,只保留一份 $+ 这个变量很像$^,也是所有依赖的集合,只是它不去除重复的依赖 $* 这个变量表示目标模式中”%”及其之前的部分

使用条件判断

条件表达式

条件表达式的语法如下:
< conditional-directie>
< text-if-true>
endif
或者如下所示:
< conditional-directive>
< text-if-true>
else
< text-if-false>
endif

  1. ifeq
    ifeq关键字表示如果相等则执行,其格式如下:
    ifeq(< arg1>,< arg2>)
    ifeq’arg1’ ‘arg2’
    ifeq”< arg1>” “< arg2>”
    ifeq’< arg1>’ ‘< arg2>’
    该关键字比较参数arg1和arg2的值是否相同.如果相同,则表达式为真,否则为假.
  2. ifneq
    ifneq关键字表示如果值非空则执行,其格式如下:
    ifneq (< arg1>,< arg2>)
    ifneq ‘arg1’ ‘arg2’
    ifneq “< arg1>” “< arg2>”
    ifneq ‘< arg1>’ ‘< arg2>’
    该关键字比较参数arg1和arg2的值是否相同,如果不同, 则表达式为真,否则为假.
  3. ifdef
    ifdef关键字表示如果值非空则执行,其格式如下:
    ifdef < variable-name>
    ifdef 关键字判断变量< variable-name>的值. 如果非空,则表达式为真,否则为假.注意,ifdef只是测试一个变量是否有值,并不会把变量扩展到当前位置.
  4. ifndef
    ifndef关键字表示如果值为空则执行,其格式如下:
    ifndef < variable-name>
    ifndef关键字判断变量< variable-name>的值.如果为空表达式为真,否则为假.该表达式同样不会将变量展开.

表达式实例

CC = gcclibs_for_gnu = = -lgnu                      #使用GNU函数库normal_libs =objects = main.o list.o my_lib.o            #所有的目标文件app : $(objects)ifeq ($(CC), gcc)                           #使用GNU函数库    $(CC) -o app $(objects) $(libs_for_gnu)else     $(CC) -o app $(objects) $(normal_libs)endifmain.o : main.c    $(CC) -c main.c                        #生成main.olist.o : list.c    $(CC) -c list.c                        #生成list.omy_lib.o : my_lib.c    $(CC) -c my_lib.c                      #生成my_lib.c

使用函数

函数调用的语法

makefile文件中的函数调用以,:(< function> < arguments>)
或者如下:
$(< function> < arguments>)
< function>表示函数名, < arguments>表示函数的参数列表. 参数间以逗号”,”分隔,而函数名和参数之间以空格分隔.

字符串处理函数

  1. 字符串替换函数
    表达式:$(subst < from>, < to>, < text>)
    函数功能:把字串< text>中的< from>字符串换成< to>.
    返回值:函数返回被替换过后的字符串.
  2. 模式字符串替换函数
    表达式:$(patsubst < pattern>,< replacement>,< test>)
    函数功能:查找< text>中的单词.
    返回值:函数返回被替换过后的字符串.
  3. 去空格函数
    表达式:$(strip < string>)
    函数名称:去空格函数.
    函数功能:去掉< string>字符串中开头和结尾的空字符.
  4. 查找字符串函数
    表达式:$(findstring h,hello)
    函数功能:在字符串< in>中查找< find>字串.
    返回值:如果找到指定的字符串,则返回< find>,否则,返回空字符串.
  5. 过滤函数
    表达式:$(filter < pattern…>, < text>)
    函数功能:以< pattern>模式过滤< text> 字符串中的单词,保留符合< pattern>的单词.
    返回值:返回符合模式< pattern>的字串.
  6. 反过滤函数
    表达式:$(filter-out < pattern…>,< text>)
    函数功能:以< pattern>模式过滤< text>字符串中的单词,去除符合模式< pattern>的单词. 可以有多个模式.
    返回值:返回不符合模式< pattern>的字符串.
  7. 排序函数

  8. 取单词函数

  9. 取单词串函数

  10. 单词个数统计函数

文件名操作函数

foreach函数

if函数

call函数

origin函数

shell函数

makefile实例

makefile实例 — 项目中的makefile

makefile实例 — makefile模板

0 0
原创粉丝点击