$$
$$ 表示真实的 $ 字符,因为$字符已经被makefile用来做变量引用,如$(MAKE),所以需要用$$ 表示真实的 $。
$$$$
$$$$ 在shell中代表进程号
在网上看到$$$$的解释好多都是生成随机数,其实根本不是的!太坑了。
上面所述,单个$已经被占用了,所以在Makefile中想要表示单个$,就只能用$$表示,同理,如果想要表示两个$怎么办呢?那不就是两个$$凑在一起,成为$$$$了嘛。所以实际$$$$代表的是真正的$$而已。
在shell中$$的代表的正是进程号。
关于$$和$$$$的解释查看如下实例:
seq.d : seq.c
@set -e; \
gcc -MM $< > $@.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$
-include seq.d
第一个命令@set -e
@关键字告诉make不输出该行命令;set -e的作用是,当后面的命令的返回值非0时,立即退出。
那么为什么要把几个命令写在”同一行“(是对于make来说,因为\的作用就是连接行),并用分号隔开每个命令?因为在Makefile这样做才能使上一个命令作用于下一个命令。这里是想要set -e作用于后面的命令。
第二个命令gcc -MM $< > $@.$$$$
作用是根据源文件生成依赖关系,并保存到临时文件中。内建变量$<的值为第一个依赖文件(那seq.c),
$$$$为字符串"$$",由于makefile中所有的$字符都是特殊字符(即使在单引号之中!),要得到普通字符$,需要用$$来转义; 而$$是shell的特殊变量,它的值为当前进程号;使用进程号为后缀的名称创建临时文件,是shell编程常用做法,这样可保证文件唯一性。
第三个命令作用是将目标文件加入依赖关系的目录列表中,并保存到目标文件。关于正则表达式部分就不说了,唯一要注意的是内建变量$*,$*的值为第一个依赖文件去掉后缀的名称(这里即是seq)。
第四个命令是将该临时文件删除。
参考链接
sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \: