Make静态模式中$(dir x/%)在%为目录时的异常行为
Make模式规则中动态生成目录的误区解析
问题场景
使用Make工具时,想创建能动态生成目标目录的规则,把问题简化后写出了这样的规则:
a/b: %: | $(dir x/%)
执行make a/b时,本来以为会报错No rule to make target 'x/a/',结果实际错误却是No rule to make target 'x/'。
根据Make的dir函数说明:“文件名的目录部分是最后一个斜杠(含)之前的所有内容”,实在搞不懂哪里理解错了。
(顺带提一句:我知道用mkdir -p $(@D)能解决问题,现在就想弄明白这个误区到底出在哪。)
误区根源
问题出在模式规则里函数的展开时机:
- 你写的
$(dir x/%)中,%在这里只是个模式占位符,不是被目标匹配后的实际字符串。Make会先执行dir函数的展开——这时候x/%被当成普通文件名处理,%还没被替换成a/b,所以dir x/%的结果就是x/(毕竟最后一个斜杠之前的内容就是x/)。 - 模式规则里的
%替换是在规则匹配阶段才发生的,但函数展开是在规则解析阶段就完成了,两者时机不一样,导致结果和预期不符。
修正方法
如果要实现你预期的效果,得让dir函数在%被替换后再展开,这时候要用到Make的二次展开功能,修改规则如下:
.SECONDEXPANSION: a/b: %: | $$(dir x/%)
这里用$$转义$,让Make第一次解析时保留$(dir x/%),等%被替换成a/b后,再第二次展开dir函数,此时dir x/a/b的结果就是x/a/,就能得到你预期的错误提示了。
内容的提问来源于stack exchange,提问作者Joja
相关产品推荐
相关产品推荐

