Shell中的makefile使用

Posted by     "Pyker" on Monday, December 16, 2019

TOC

  • = : 在等号右侧的值是变量的值,右侧的值可以定义在文件中的任何一处,也就是说,右侧中的变量不一定非要是已经定义好的值,其也可以使用后面定义的值。也就是说用=赋值的变量,在被解析时他的值取决于最后一次赋值时的值,所以你看变量引用的值时不能只往前面看,还要往后面看。

  • := : 用:=来赋值的,前面的变量不能使用后面的变量,只能使用前面已经定义好了的变量

  • ?= : 如果变量前面并没有赋值过则执行这条赋值,如果前面已经赋值过了则本行被忽略。(所谓的没有赋值过其实就是这个变量没有被定义过)

  • += : 用来给一个已经赋值的变量接续赋值(把这次的值加到原来的值的后面)有点类似于strcat函数。(在shell makefile等文件中,可以认为所有变量都是字符串,+=就相当于给字符串stcat接续内容)(注意一个细节,+= 续接的内容和原来的内容之间会自动加一个空格隔开

举例:

# = 举例
A = 123
B = $(A)456
A = 789

$ echo $(B)
789456   # 被解析时他的值取决于最后一次赋值时的值

# := 举例
A := 123
B := $(A)456
A := 789

$ echo $(B)
123456   # 被解析时B只能取他前面的变量。即A=123 

# ?= 举例
A = 123
B = $(A)456
A ?= 789
A1 ?= 000

$ echo $(B) $(A1)
123456   000 # A变量已经定义所以取已定义的值,A1没定义所以取新值

# += 举例
A += 123
A += 789

$ echo $(A)
123 789   # A的两次赋值都会以空格形式拼接起来
  • 三个变量:$@$^$<代表的意义分别是:

    $@–target名称,$^–所有的依赖文件名,$<–第一个依赖文件名

  • 伪目标:.PHONY: target,表示忽略本地存在的target,每次都执行。

  • Makefile中的变量以$开头, 所以,为了避免和shell的变量冲突,shell的变量以​$$开头

# 格式
target: dependencies
    system command
# 默认情况下,target是生成文件的“形式”,每次执行make会根据依赖文件是否比target文件更新来决定是否要重新执行指令;而如果是all或者phony修饰的情况就可能完全是命令的形式。    

例子1

$ cat Makefile
all: build

name ?= pyker
install :
	@echo "shell-install"
deploy :
	@echo "shell-deploy"

build : install deploy
	@echo $@ $< $^ ${name}

$ make  # 默认带all
shell-install
shell-deploy
build install install deploy pyker

例子2

# Makefile文件
$ cat Makefile
# all指执行make或者make all将执行那些target。直接make 默认带上all参数。
all: build echo yy 

# shell多行处理,@表示不输出执行语句
SUBDIR=src example
build:
	@for subdir in ${SUBDIR}; \
	do \
		echo "building " ;\
	done

# makefile内的变量使用$引用
VAR="Hello"
echo:
	@echo "${VAR}"

# shell内部的变量使用$$引用
yy:
	@xx=xx3; \
	echo $${xx}; \
	timel="$(shell date)"; \
	echo $${timel}
	
# make输出结果
$ make build echo yy
building
building
Hello
xx3
2021年 01月 02日 星期六 17:02:03 CST

例子3

#当前目录下存在的文件
$ ls
ber  file  file1  Makefile
# 执行file的target
$ make file
make file
# 执行file1的target
$ make file1
make: “file1”是最新的。
# 执行dele的target
$ make dele
# ber文件被删了
$ ls
file  file1  Makefile

# Makefile内容
$ cat Makefile
.PHONY: file  # .PHONY 忽略了file的存在,都会执行file的target

file:
	@echo "make file"
file1:       # file1 没用 .PHONY进行伪目标,所以file1存在最新的就没执行该target
	@echo "make file1"
dele: $(shell find ./ -name "ber")  # shell方式的依赖先执行,$<拿到结果。删除ber文件
	@rm -rf $<

例子解释:

  • Makefile文件的目标项冒号后的另起一行的代码才是shell代码。

  • make中规定每一Shell命令之前的开头必须使用<tab>字符

  • Makefile中的shell,每一行是一个进程,不同行之间变量值不能传递。所以,Makefile中的shell不管多长也要写在一行。多行的末尾都是; \,以此来保证代码是一行而不是多行.

  • Makefile中的变量以$开头,shell的变量以$$开头

  • 也支持var=$(shell 这里的代码也是shell代码)

  • Makefile中的变量必须用{}包含。不然会出错

  • command中@开头代表不打印命令本体,而是输出结果。多行命令可写多个。注意:;\连接的是一行命令,因此他一个@就行

「真诚赞赏,手留余香」

云原生与运维

真诚赞赏,手留余香

使用微信扫描二维码完成支付


comments powered by Disqus