Makefile中'$$directoryName'与'$(directoryName)'差异及语法疑问
Makefile变量与自动变量常见问题解析
1. $$directoryName 和 $(directoryName) 的区别
这俩核心是展开时机和主体完全不同:
$(directoryName)是Make自身的变量引用,会在Make解析规则的阶段直接展开成变量对应的值。比如你定义了dir=../dir1,那$(dir)就会被Make替换成../dir1,再把替换后的完整命令传给shell执行。$$directoryName是给shell变量的转义写法。因为Make会把所有$当作自己的变量标识,如果你想让shell拿到$directoryName这个shell变量,就得用$$转义——Make处理时会把$$转换成单个$,最终传给shell的就是$directoryName,由shell来解析这个变量。
2. 为什么for循环用$$dir,简单规则用$(dir)?
咱们结合你的例子拆解看:
简单规则场景
dir = ../dir1 test: $(MAKE) -C $(dir)
这里的$(dir)是让Make直接把变量值展开,最终传给shell执行的命令是make -C ../dir1,全程不需要shell处理变量,所以直接用Make的变量引用就够了。
for循环场景
DIRS = dir1 dir2 dir3 test: for dir in $(DIRS); do \ if $(MAKE) -C $$dir ; then \ true; \ else \ exit 1; \ fi; \ done
这个规则里的命令是一段shell脚本,我们需要shell来循环处理dir这个shell变量。如果直接写$(dir),Make会先把它替换成自己的dir变量值(没定义就是空),这完全不是我们想要的——我们要的是shell循环里的$dir。所以用$$dir让Make转义,处理后传给shell的就是$dir,这样shell才能识别这是自己的循环变量,依次取dir1、dir2、dir3来执行命令。
3. 循环里的$@是什么意思?
$@是Make的自动变量,它代表当前规则的目标名。在你给的规则里:
all clean dep depend print: for dir in $(DIRS); do \ if $(MAKE) $(MAKE_FLAGS) -C $$dir $@; then \ true; \ else \ exit 1; \ fi; \ done
这是个多目标规则,目标包含all、clean、dep等。比如你执行make clean时,$@就会被Make替换成clean,最终传给每个子目录的命令就是make $(MAKE_FLAGS) -C dir1 clean、make $(MAKE_FLAGS) -C dir2 clean……这样每个子目录都会执行对应的目标,完美实现批量处理子目录的同名操作。
内容的提问来源于stack exchange,提问作者emacos
相关产品推荐
相关产品推荐

