我基本上是在研究一个有缺陷的makefile,它将我与以下场景混淆了。
default:
echo "Build started with $@ at $(ENV_VAR)";
ENV_VAR=$(NEW_DIR);
cd $(ENV_VAR);
$(MAKE);
程序员的目标:
基本上,程序员打算用一个新值(目录路径)覆盖环境变量ENV_VARnew_DIR,然后在该目录中递归执行make。
此生成文件中的错误:
我看到的错误是编码器使用了"cd$(ENV_VAR)">而不是"cd$$(ENV_VAR)">。因此,我们实际上并没有为"cd"命令使用overriden make变量,而是在执行$(make)之前仍然使用环境变量的值。此外,cd命令也因路径不存在而失败。最后我们做了一个递归make。
我的问题
正如我在上一段中提到的,我们正处于递归make的场景中。有趣的是,当第二次调用同一个目标时,我看到$(ENV_VAR)来反映NEW_DIR的重写值。这让我很困惑。
样本输出:
假设:
NEW_DIR=/新目录OLD-DIR=/旧目录
输出:
Build started with default at /old-dir
bin/sh /old-dir: no such file (or) directory
Build started with default at /new-dir
对此有什么建议吗。
$(ENV_VAR)
不正确是对的。但$$(ENV_VAR)
也不正确。
Make展开命令中的变量,然后将命令传递给shell,shell进行自己的展开。所以
default:
echo "Build started with $@ at $(ENV_VAR)";
ENV_VAR=$(NEW_DIR);
cd $(ENV_VAR);
$(MAKE);
成为外壳命令
echo "Build started with $@ at /old_dir";
ENV_VAR=/new_dir;
cd /old_dir;
make
此命令尚未执行;任务还没有完成,已经太晚了。
提议的解决方案也不起作用。此:
default:
echo "Build started with $@ at $(ENV_VAR)";
ENV_VAR=$(NEW_DIR);
cd $$(ENV_VAR);
$(MAKE);
变为:
echo "Build started with $@ at /old_dir";
ENV_VAR=/new_dir;
cd $(ENV_VAR);
make
这看起来不错,但请注意,cd $(ENV_VAR);
是Make语法,而不是shell语法(至少不是bash)。正确的shell语法是cd $ENV_VAR
,因此规则应该是:
default:
echo "Build started with $@ at $(ENV_VAR)";
ENV_VAR=$(NEW_DIR);
cd $$ENV_VAR;
$(MAKE);
根据手册,"默认情况下,只有来自环境或命令行的变量才会传递给递归调用"(但如果您选择,您可以覆盖此行为)。由于ENV_VAR
是一个环境变量,它将被传递给sub-make,如果您在命令shell中修改它,那么sub-make将收到修改后的值。
最后,我建议你这样尝试:
default:
echo "Build started with $@ at $(ENV_VAR)";
Make -C $(NEW_DIR) ENV_VAR=$(NEW_DIR);