Makefile:需要明确环境变量和make变量的混合使用



我基本上是在研究一个有缺陷的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);

最新更新