0

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

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

程序员的目标:

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

此生成文件中的错误:

我看到的错误是编码器使用了"cd $(ENV_VAR)"而不是"c​​d $$(ENV_VAR)"。因此,正因为如此,我们实际上并没有为“cd”命令使用覆盖的 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

请对此提出任何建议。

4

1 回答 1

1

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

Make 扩展命令中的变量,然后将命令传递给 shell,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);

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

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

default:
    echo "Build started with $@ at $(ENV_VAR)";
    Make -C $(NEW_DIR) ENV_VAR=$(NEW_DIR);
于 2012-09-14T11:57:39.523 回答