Makefile教程 7-10

Makefile教程 7-10

教程整理部分1

教程整理部分2

Makefile教程7:变量

博客地址

这一章节的内容,基本在makefile教程:变量部分都介绍过了。

Makefile教程8:变量,条件判断

makefile8

环境变量

这个本意很简单,就是可以读取操作系统的环境变量,比如:

.PHONY:

debug:
	env=1;export env;echo $(env)

;的这个用法见makefile之命令之间的关联

这里就是定义了一个变量env,并且将其设置为环境变量:export env,这部分属于操作系统的知识,和makefile无关。

之后就是在makefile中读取:echo $(env)读取操作系统中定义的环境变量。


在编译的过程中,可以使用参数-e来指定环境变量,比如还是上面的makefile,在运行时:

make -e env=2 debug

就是可以覆盖掉系统中的环境变量。

目标变量

这个玩意本意很简单,先回顾一下makefile中命令的基本格式:makefile基础

target ... : prerequisites ...
	command

其中,如果我们想定义一些变量,仅仅在这个target中生效,就可以采用这个,比如下面的例子,注意看其中的注释:

.PHONY:
# 这个变量仅仅在 debug 中生效
debug: cmd = pwd
# 这个变量仅仅在 debug2 中生效
debug2: cmd = whoami
debug:
	$(cmd)

debug2:
	$(cmd)

所以运行make debug的时候,真正执行的是pwd,运行make debug2的时候,真正执行的是whoami

模式变量

这个也很简单,就是如果有一些变量我们想放在多个目标变量里,就可以使用这个,比如:

.PHONY:
# 模式变量,顾名思义,它自己本身就是目标变量中的变量
de%: cmd = whoami

debug:
	$(cmd)

debug2:
	$(cmd)

其中debugdebug2都可以使用这个变量。

条件判断

这个很简单,就是在makefile中增加条件判断,比如下面这个例子:

example = hello
# 注意,ifeq 后面一定要空一格,否则会报错
ifeq ($(example),hello)
	output=world
else
	output=makefile
endif

.PHONY:

debug:
	@echo "$(example) $(output)"

条件判断的格式是:

<conditional-directive>
    <text-if-true>
else
		<text-if-false>
endif

其中重点是<conditional-directive>这一部分,可以使用的关键字有:

  • ifeq / if equal
  • ifneq / if not equal
  • ifdef / if define
  • ifndef / if not define

首先是比较两个值是否相同,格式如下:

ifneq (<arg1>, <arg2>)
ifneq '<arg1>' '<arg2>'
ifneq "<arg1>" "<arg2>"
ifneq "<arg1>" '<arg2>'
ifneq '<arg1>' "<arg2>"

也可以像这样,直接根据第一个值是否存在来进行判断

ifeq (ifTrue,)

比如上面的例子:

# 这里假设我们使用了一个未定义的变量
# example = hello

ifeq ($(example),)
	# 条件满足,进入这种情况
	output=world
else
	output=makefile
endif

.PHONY:

debug:
	@echo "$(example) $(output)"

接下来就是判断变量是否定义:

ifdef <variable-name>

makefile教程9:makefile函数

makefile教程9

这里好像主要就是介绍makefile支持的函数。

首先是函数的调用方法:

$(<function> <arguments>)
$(函数名 变量1,变量2,变量3)

下面如果有数字参数的话,不允许小于0。

下面是字符串相关的函数。

字符串替换函数:subst

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

模式字符串替换函数:patsubst

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

所谓“模式”,就是可以模糊搜索的效果,比如%就代表1到多个字符串。

去掉空格:strip

$(strip <string>)

去掉字串中开头和结尾的空字符。

判断是否包含某字符串:findstring

$(findstring <find>,<in>)

如果在in中找到find字符串,则返回find,否则就返回空字符串。

过滤函数:filter

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

text中筛选符合pattern的值

反过滤函数:filter-out

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

filter操作相同,结果不同,filter是符合pattern的值输出,filter-out则是不符合pattern的值输出。

排序函数:sort

$(sort <list>)

list中的值进行排序。排序规则是特殊字符,数字,大写字母,小写字母。

获取字符中的第n个单词数:word

$(word <n>,<text>)

获取text中的第n个值。比如$(word 2, foo bar baz)就是bar。如果超过设置的值,则返回为空。

统计单词中的子单词数量:wordlist

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

$(wordlist 2, 3, foo bar baz)返回值就是bar baz

统计单词数:words

$(words <text>)

比如$(words, foo bar baz)的值就是3。

获取首个单词数:firstword

$(firstword <text>)

比如$(firstword foo bar)的值就是foo


下面就是一些例子:

.PHONY:

debug:
	@echo $(subst world,makefile,hello world)
	# hello makefile
	@echo $(patsubst %hello,say hello,hello again)
	# say again
	@echo $(strip without Empty )
	# without Empty
	@echo $(findstring php,php is the best language)
	# php
	@echo $(filter makefile%,makefile1 makefile2 makefile3 1.c 2.c)
	# makefile1 makefile2 makefile3
	@echo $(filter-out makefile%,makefile1 makefile2 makefile3 1.c 2.c)
	# 1.c 2.c
	@echo $(sort 1 2 3 a b c A B , %)
	# % , 1 2 3 A B a b c
	@echo $(word 2,a b c)
	# b
	@echo $(wordlist 1,3,a b c d e f)
	# a b c
	@echo $(words a b c d e f)
	# 6
	@echo $(firstword a b c d e f)
	# a

文件相关函数。

获取目录值:dir

$(dir <names...>)

就是获取names中的目录部分。比如$(dir ./main.c ./src/function.c)就是./ ./src/

获取文件名:notdir

$(notdir <names...>)

就是获取上面部分中的文件部分。比如$(notdir ./main.c ./src/function.c)就是main.c function.c

获取非文件后缀部分:basename

$(basename <names...>)

就是将names中的文件非后缀部分,比如$(basename ./main.c ./src/function.c)就是./main ./src/function

增加文件后缀:addsuffix

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

就是增加文件后缀。比如$(addsuffix .c,1 2 3),输出就是1.c 2.c 3.c

增加文件前缀:addprefix

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

跟上面类似,就是增加文件前缀,比如$(addprefix ./,1.c 2.c 3.c),输出./1.c ./2.c ./3.c

拼接字符串:join

$(join <list1>,<list2>)

这个list2会尽量贴近list1,比如list1list2多,那么没有list2链接的list1就会维持原样。

同样,如果list2list1多,那么没有list1链接的list2就会维持原样。


下面就是一些例子:

.PHONY:

debug:
	@echo $(dir ./main.c ./src/function.c)
	# ./ ./src
	@echo $(notdir ./main.c ./src/function.c)
	# main.c function.c
	@echo $(basename ./main.c ./src/function.c)
	# ./main ./src/function
	@echo $(addsuffix .c,1 2 3)
	# 1.c 2.c 3.c
	@echo $(addprefix ./,1.c 2.c 3.c)
	# ./1.c ./2.c ./3.c
	@echo $(join ./,1 2)
	# ./1 2
	@echo $(join ./ ./src/,1)
	# ./1 ./src/
	@echo $(join ./ ./src/,1 2)
	# ./1 ./src/2

Makefile10:函数

makefile9

循环函数:foreach

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

这个参数的变量解释:

  • list:定义待处理的数据
  • var:定义每次处理的数据的变量名
  • text:处理函数

条件判断:if

$(if <condition>,<then-part>)

或者

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

这个就是if else的结构。

自定义函数:call

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

获取变量的出处:origin

$(origin <variable>)

首先就是<variable>中不能加上$(variable),而仅仅是variable就可以。

其次,可能的返回值有:

  • undefined:未定义
  • default:makefile内部定义的变量
  • enviroment:环境变量,export内容见这里
  • file:定义在当前makefile中
  • command line:命令行定义的,见下面这个例子。

这里分享一下直接拿Linux中的环境变量例子:

.PHONY:

debug:
	debug="hello world" && export debug && echo $(debug)

debug="hello world"就是定义一个变量。

export debug就是定义一个操作系统的环境变量。

echo $(debug)就是调用环境变量。

&&中的内容见这里:命令的关联


  • override:使用override重新定义的。

override的简单作用就是可以覆盖之前定义的变量,比如下面定义的变量:

override debug="hello again"

.PHONY:

debug:
	debug="hello world" && export debug && echo $(debug)

  • automatic:自动化变量。

自动变量就是类似$@,@<这样的变量,更多的变量说明在后面还会讲。

调用 shell 函数

$(shell shellFunction param)

就是$(shell shell函数 参数)

make控制函数

  • 产生一个致命错误:$(error <text ...>)

  • 产生一个警告:$(warning <text ...>)


下面是一个例子:

list=1 2 3 4
files=$(foreach item,$(list),$(item).c)

empty=
hasFile=$(if $(empty),yes)
hasCFile=$(if $(files),yes,no)

privateFunction=$(words $(1))

listNumber=$(call privateFunction,$(list))

.PHONY:

debug:
	@echo $(list)
	# 1 2 3 4
	@echo $(files)
	# 1.c 2.c 3.c 4.c
	@echo $(hasFile)
	# 
	@echo $(hasCFile)
	# yes
	@echo $(listNumber)
	# 4
	@echo $(origin privateFunction)
	# file
	@echo $(shell pwd)
	# 

error:
	# 这里是直接停止,不会首先运行 @echo $(shell whoami) 的部分
	@echo $(shell whoami)
	$(error 停止)
	
warn:
	# 这里是先运行 makefile:28: 警告
	# 接下来再运行一块一块的命令
	@echo $(shell whoami)
	$(warning 警告)
	@echo $(shell whereis make)
上一篇:惠普小型机makefile转移到LINUX


下一篇:读书笔记--内核Makefile与链接脚本