Makefile笔记一

Makefile规则

  • 在一些大的工程中,我们会把我们不同模块或是不同功能的源文件放在不同的目录中, 我们可以在每个目录中都书写一个该目录的 Makefile,这有利于让我们的 Makefile 变得更 加地简洁,而不至于把所有的东西全部写在一个 Makefile 中,这样会很难维护我们的 Makefile,这个技术对于我们模块编译和分段编译有着非常大的好处。

静态模式

静态模式方便定义多目标
静态模式的语法规则为:

<这里是目标的合集>:<这里是需要操作的目标筛选>:<这里是目标的依赖筛选>
command

$<

”$<”表示所有的依赖目标集

$@

“$@”表示目标集

$()

$()表示执行一个makefile函数
第一个参数表示函数名
后面的参数为函数的调用参数

或者
$()表示使用变量,参数为变量名

-M/-MM

编译.c或者.cpp文件时的命令选项,自动寻找源文件中的头文件并生成一个依赖关系。

如果你使用 GNU 的 C/C++编译器,你得用 “-MM”参数,不然,“-M”参数会把一些标准库的头文件也包含进来

-n/–just-print

make命令行参数,表示只打印命令而不执行

-s/–slient

make命令行参数,表示全面禁止命令的显示

-i/–ignore-errors

make命令行参数,表示makefile中的所有命令忽略错误

-k/–keep-going

make命令行参数,表示makefile某规则中的命令出错了,那么就终目该规则的执行,但继续执行其它规则。

-w/–print-directory

make命令行参数,会在make执行过程中输出当前的工作目录

命令执行

如果你要让上一条命令的结果应用在下一条命令时,你应该使用分号分隔这两条命令。比如你的第一条命令是cd命令,你希望第二条命令得在cd之后的 基础上运行,那么你就不能把这两条命令写在两行上,而应该把这两条命令写在一行上,用 分号分隔。

忽略命令出错

忽略命令的出错,我们可以在Makefile的命令行前加一个减号“-” (在 Tab 键之后),标记为不管命令出不出错都认为是成功的。

export/unexport

是否把变量传递给下级makefile
如果后面加变量就是针对变量而言,否则对当前makefile文件的所有变量有效

注意:有两个变量SHELLMAKEFLAGS,这两个变量不管你是否export,都会传递到下级。

MAKEFLAGS

系统级的环境变量,用于传递make命令传递的参数,但是下面这些参数并不传递:

  • -C
  • -f
  • -h
  • -o
  • -W

如果在调用下级makefile时不想传递当前makefile调用时的命令参数,可以手动设置MAKEFLAGS=

定义命令包

如果 Makefile 中出现一些相同命令序列,那么我们可以为这些相同的命令序列定义一 个变量。定义这种命令序列的语法以“define”开始,以“endef”结束

# “run-yacc”是这个命令包的名字,其不要和 Makefile 中的变量重名
define run-yacc
yacc $(firstword $^)
mv y.tab.c $@
endef

使用命令包就和使用变量是一样的

$$

表示$符号

变量

  • 变量代表一个文本字符串
  • 变量在声明时需要给予初值
  • 变量在使用时,需要给在变量名前加上“$”符号,但最好用小括号“()”或是大括号“{}”把变量给包括起来
  • 变量类似于C语言的宏,可以在目标、依赖、命令甚至变量的定义中使用

变量的定义

  • 变量可以使用=进行赋值,值可以是后面定义的变量
  • 变量可以使用:=进行赋值,值只能是前面定义的变量
  • 变量可以使用?=进行赋值,如果该变量已经定义过了,忽略,否则赋值
  • 变量可以使用+=进行追加值,如果变量之前没有定义过,那么,“+=”会自动变成“=”,如果前面有变量定义,那么“+=” 会继承于前次操作的赋值符。如果前一次的是“:=”,那么“+=”会以“:=”作为其赋值符

MAKELEVEL

如果我们的 make 有一个嵌套执行的动作,这个变量会记录了我们的当前 Makefile 的调用层数。

$(var:a=b)

var是一个变量,变量中的每个单词,如果以a结尾,将a替换成b

override

如果有变量是通常 make 的命令行参数设置的,那么 Makefile 中对这个变量的赋值会被忽略。如果你想在 Makefile 中设置这类参数的值,那么,你可以使用“override”指示符。

多行变量

define 指示符后面跟的是变量的名字,而重起一行定义变量的值,定义是以 endef 关键字结束。其工作方式和“=”操作符一样。变量的值可以包含函数、命令、文字,或是其它变量。因为命令需要以[Tab]键开头,所以如果你用 define 定义的命令变量中没有以[Tab] 键开头,那么 make 就不会把其认为是命令

环境变量

make 运行时的系统环境变量可以在 make 开始运行时被载入到 Makefile 文件中,但是如果Makefile中已定义了这个变量,或是这个变量由make命令行带入,那么系统的环境变 量的值将被覆盖。(如果 make 指定了“-e”参数,那么,系统环境变量将覆盖 Makefile 中 定义的变量)

目标变量

前面我们所讲的在 Makefile 中定义的变量都是“全局变量”,在整个文件,我们都可 以访问这些变量。当然,“自动化变量”除外,如“$<”等这种类量的自动化变量就属于“规 则型变量”,这种变量的值依赖于规则的目标和依赖目标的定义。当然,我样同样可以为某 个目标设置局部变量,这种变量被称为“Target-specific Variable”,它可以和“全局变 量”同名,因为它的作用范围只在这条规则以及连带规则中,所以其值也只在作用范围内有 效。而不会影响规则链以外的全局变量的值。

条件判断

// 如果con1==con2,执行逻辑1
// 否则执行逻辑2
ifeq (con1,con2)
// 执行逻辑1
else
// 执行逻辑2
endif
// 如果con1!=con2,执行逻辑1
// 否则执行逻辑2
ifneq (con1,con2)
// 执行逻辑1
else
// 执行逻辑1
endif
// 如果定义了var变量,执行逻辑1
// 否则执行逻辑2
ifdef var
// 执行逻辑1
else
// 执行逻辑1
endif

函数调用

makefile以下面的方式调用函数

$(<function> <arguments>)

<arguments>是函数的参数,参数间 以逗号“,”分隔,而函数名和参数之间以“空格”分隔。函数调用以“$”开头,以圆括号或花括号把函数名和参数括起。和变量的调用相似

subst

$(subst <from>,<to>,<text>)

字符串替换函数,有三个参数

  • 第一个参数是要被替换的字符串
  • 第二个参数是要替换成的字符串
  • 第三个参数作用目标
  • 返回被替换后的字符串

patsubst

$(patsubst <pattern>,<replacement>,<text>)

模式字符串替换函数,查找字符串中的每个单词,是否符合模式<pattern>,如果符合,替换成<replacement>,这里,<pattern>可以包括通 配符“%”,表示任意长度的字串。如果<replacement>中也包含“%”,那么,<replacement> 中的这个“%”将是<pattern>中的那个“%”所代表的字串
该函数有三个参数

  • 第一个参数是匹配的模式字符串
  • 第二个参数是替换的模式字符串
  • 第三个参数作用目标
  • 返回被替换后的字符串

strip

$(strip <string>)

去掉字串中开头和结尾的空字符。
返回被去掉空格的字符串值

findstring

$(findstring <find>,<in>)

在字符串<in>中查找字符串<find>
如果找到,返回find字符串,否则返回空字符串
该方法一般用于判断字符串是否包含另一个字符串

filter

$(filter <pattern...>,<text>)

该函数过滤字符串,依然是对给定字符串的每个单词进行判定,如果单词能够匹配<pattern…>中的任何一个模式,就保留,否则舍弃。
返回过滤后的字符串

filter-out

$(filter-out <pattern...>,<text>)

反向过滤字符串,依然是对给定字符串的每个单词进行判定,如果单词能够匹配<pattern…>中的任何一个模式,就舍弃,否则保留。
返回过滤后的字符串

sort

$(sort <list>)

给字符串<list>中的单词排序(升序)。
返回排序后的字符串
sort 函数会去掉<list>中相同的单词。

word

$(word <n>,<text>)

取字符串<text>中第<n>个单词。(n从1开始)
如果<n>比<text>的单词数要大,返回空字符串
返回取到的单词

wordlist

$(wordlist <s>,<e>,<text>)

从字符串<text>中取从<s>开始到<e>的单词串。<s>和<e>是一个数字。
如果<s>比<text>中的单词数要大,那 么返回空字符串。如果<e>大于<text>的单词数,那么返回从<s>开始,到<text>结束的单词串。

words

$(words <text>)

返回<text>中的单词数。

firstword

$(firstword <text>)

返回字符串<text>的第一个单词

dir

$(dir <names...>)

取目录函数,从文件名序列<names>中取出目录部分。目录部分是指最后一个反斜杠(“/”)之前 的部分。如果没有反斜杠,那么返回“./”。

notdir

$(notdir <names...>)

取文件函数,从文件名序列<names>中取出文件部分。文件部分是指最后一个反斜杠(“/”)之后的部分。如果没有反斜杠,那么返回文件名。

suffix

$(suffix <names...>)

取文件后缀函数,返回文件名序列<names>的后缀序列,如果文件没有后缀,则返回空字串。返回的后缀包含.

basename

$(basename <names...>)

取文件前缀函数,返回文件名序列<names>的前缀序列,如果文件没有前缀,则返回空字串。

addsuffix

$(addsuffix <suffix>,<names...>)

加后缀函数,把后缀<suffix>加到<names>中的每个单词后面。

addprefix

$(addprefix <prefix>,<names...>)

加前缀函数,把前缀<prefix>加到<names>中的每个单词前面。

join

$(join <list1>,<list2>)

合并函数
把<list2>中的单词对应地加到<list1>的单词后面。如果<list1>的单词个数要比 <list2>的多,那么,<list1>中的多出来的单词将保持原样。如果<list2>的单词个数要比 <list1>多,那么,<list2>多出来的单词将被复制到<list1>中。

foreach

$(foreach <var>,<items>,<text>)

循环遍历函数,把参数items中的每个单词取出,保存到var,然后执行text逻辑
text逻辑返回一个字符串
最终的返回结果是每次执行text返回的字符串拼接成一个完整的字符串,拼接以空格连接

if

$(if <condition>,<then-part>)
//或者
$(if <condition>,<then-part>,<else-part>)

call

$(call <expression>,<parm1>,<parm2>,<parm3>...)

call 函数是唯一一个可以用来创建新的参数化的函数。你可以写一个非常复杂的表达式,这个表达式中,你可以定义许多参数,然后你可以用 call 函数来向这个表达式传递参数
当 make 执行这个函数时,<expression>参数中的变量,如$(1),$(2),$(3)等,会被参数<parm1>,<parm2>,<parm3>依次取代。而<expression>的返回值就是 call 函数的返回值。

reverse = $(2) $(1)
// 此时的 foo 的值就是“b a”。
foo = $(call reverse,a,b)

origin

$(origin <variable>)

origin 函数不像其它的函数,他并不操作变量的值,他只是告诉你你的这个变量是哪里来的

注意,<variable>是变量的名字,不应该是引用。所以你最好不要在<variable>中使用 “$”字符。Origin 函数会以其返回值来告诉你这个变量的“出生情况”,下面,是 origin 函数的返回值:

  • undefined:如果<variable>从来没有定义过,origin 函数返回这个值“undefined”。
  • default:如果<variable>是一个默认的定义,比如“CC”这个变量
  • environment:如果<variable>是一个环境变量,并且当 Makefile 被执行时,“-e” 参数没有被打开。
  • file:如果<variable>这个变量被定义在 Makefile 中。
  • command line:如果<variable>这个变量是被命令行定义的。
  • override:如果<variable>是被 override 指示符重新定义的。
  • automatic:如果<variable>是一个命令运行中的自动化变量

shell

$(shell <command line>)

执行操作系统的命令
shell 函数把执行操作系统命令后的输出作为函数返回。

error/warning

$(error <text>)
$(warning <text>)

error会输出错误信息,并结束makefile的执行
warning会输出警告信息,并继续执行makefile

  • 23
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值