Makefile:需要明确混合使用环境变量并制作变量

时间:2012-09-14 10:50:46

标签: makefile

我基本上是在研究一个有问题的makefile,这让我对以下情况感到困惑。

default:
     echo "Build started with $@ at $(ENV_VAR)";\
     ENV_VAR=$(NEW_DIR); \
     cd $(ENV_VAR); \
     $(MAKE);

程序员的目标:

程序员基本上打算用新值(目录路径) NEW_DIR 覆盖环境变量 ENV_VAR ,然后在该目录中以递归方式执行make。

此makefile中的错误:

我看到的错误是编码器使用“cd $(ENV_VAR)”而不是“cd $$(ENV_VAR)”。因此,我们实际上并没有在“cd”命令中使用overriden make变量,而是在执行$(MAKE)之前仍然使用环境变量的值。 cd命令也因为不存在的路径而失败。最后我们最终做了递归make。

我的问题

正如我在上一段中所提到的,我们处于递归make的场景中。有趣的是,我看到第二次调用相同的目标时,我看到$(ENV_VAR)反映了NEW_DIR的覆盖值。这让我感到困惑。

示例输出:

假设:

NEW_DIR = / new-dir OLD-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

对此有任何建议。

1 个答案:

答案 0 :(得分:1)

$(ENV_VAR)不对,你是对的。但$$(ENV_VAR)也不正确。

make扩展命令中的变量,然后将命令传递给shell,后者执行自己的扩展。所以

default:
     echo "Build started with $@ at $(ENV_VAR)";\
     ENV_VAR=$(NEW_DIR); \
     cd $(ENV_VAR); \
     $(MAKE);

成为shell命令

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);

根据the manual,“默认情况下,只有来自环境或命令行的变量才会传递给递归调用”(但如果您选择,则可以覆盖此行为)。由于ENV_VAR是一个环境变量,它将被传递给子make,如果你在命令shell中修改它,sub-make将收到修改后的值。

最后,我建议你这样试试:

default:
    echo "Build started with $@ at $(ENV_VAR)";
    Make -C $(NEW_DIR) ENV_VAR=$(NEW_DIR);