这是我的Makefile
gitignore-create:
touch .gitignore ;\
echo 'node_modules' >> .gitignore ;\
echo 'npm' >> .gitignore ;\
echo '.DS_Store' >> .gitignore ;\
如果我运行make gitignore-create
,我会将gitignore文件作为当前目录。
我正在寻找一种从同一目录运行此makefile命令但是将目标指定给另一个目录的方法。我不想在命令本身中添加cd
。
我试过这样的事情:
# make wrap package=my-package command=gitignore-create
wrap:
pushd packages/$(package)/ && make -C ${CURDIR} $(command) && popd
它只在实际当前目录中创建文件。
答案 0 :(得分:2)
这有很多错误:
wrap:
pushd packages/$(package)/ && make -C ${CURDIR} $(command) && popd
在调用递归make规则时,首先应该从不使用静态命令make
。 始终使用变量$(MAKE)
(或者,如果您愿意,${MAKE}
:它们是相同的。)
其次,你不能使用pushd
和popd
(至少不能移植)因为那些是bash命令,但make总是运行/bin/sh
作为它的shell(除非你改变它)通过设置SHELL
makefile变量),在许多系统上,/bin/sh
不是 bash。
第三,无论如何你都不需要这样做,因为在UNIX / Linux中,与所有正确思考的操作系统一样,当前目录是当前进程的属性(其环境的一部分)并更改当前目录不会更改父进程的当前目录。并且,makefile中的每个配方行都是一个全新的进程(运行shell)。因此,您可以直接在任何配方行中使用cd
,并且一旦该配方行完成并且shell退出,对环境的所有更改(包括当前目录)都将消失:您不必明确撤消它们。
因此,您可以将上述规则等效地编写为:
wrap:
cd packages/$(package)/ && $(MAKE) -C ${CURDIR} $(command)
但是,最终这没有做任何事情,因为当给出make时-C
选项会导致make将其工作目录更改为您提供的值。所以这个方法说,“首先将目录更改为packages/$(package)
,然后运行make并告诉它在启动任何命令之前应该做的第一件事就是将目录更改回原始目录”。显然,这与仅运行make而不更改目录完全相同。
您的解释并不完全清楚,但我想要做的事情是这样的:
# this variable assignment must come before any include statements
myMakefile := $(abspath $(lastword $(MAKEFILE_LIST)))
...
wrap:
cd packages/$(package)/ && $(MAKE) -f $(myMakefile) $(command)
首先记住当前makefile的路径,然后创建一个配方,将目录更改为packages/$(package)
然后运行make给它当前的makefile进行解析(但不更改目录,不要使用{{1} }!)和要运行的命令。