【问题标题】:Specify makefile command target指定 makefile 命令目标
【发布时间】:2016-06-07 02:09:52
【问题描述】:

这是我的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

而且它只在实际的当前目录中创建文件。

【问题讨论】:

    标签: makefile


    【解决方案1】:

    这有很多问题:

    wrap:
            pushd packages/$(package)/ && make -C ${CURDIR} $(command) && popd
    

    首先你应该从不在调用递归生成规则时使用静态命令make总是使用变量$(MAKE)(或者如果你愿意,${MAKE}:它们是相同的)。

    其次,您不能使用pushdpopd(至少不可移植),因为它们是 bash 命令,但 make 始终将 /bin/sh 作为其 shell 运行(除非您通过设置 SHELL 来更改它makefile 变量)并且在许多系统上,/bin/sh 不是 bash。

    第三,无论如何您都不需要这样做,因为在 UNIX/Linux 中,与所有思维正确的操作系统一样,当前目录是当前进程(其环境的一部分)的属性,并且会更改当前目录不会更改父进程的当前目录。而且,makefile 中的每个配方行都是一个全新的进程(运行一个 shell)。因此,您可以在任何配方行中直接使用cd,并且一旦该配方行完成并且shell 退出,对环境的所有更改(包括当前目录)都将消失:您不必显式撤消它们.

    所以你可以把上面的规则等价写成:

    wrap:
            cd packages/$(package)/ && $(MAKE) -C ${CURDIR} $(command)
    

    但是,最终这并没有做任何事情,因为-C 选项在给出 make 时会导致 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进行解析(但不更改目录,不要使用-C!)和要运行的命令。

    【讨论】:

    • 这给了我一些错误cd packages/reggi/ && /Applications/Xcode.app/Contents/Developer/usr/bin/make -f Makefile gitignore-create make[1]: Makefile: No such file or directory make[1]: *** 没有规则来制作目标“Makefile”。停止。 make: *** [wrap] 错误 2
    • 这是我的文件。我基本上想要一种方法让两个底层食谱都存在。 gist.github.com/reggi/e180f3a3b8beaabd3c37a15cb6c6c628,
    • 要么通过检查package 变量是否存在然后 cd'ing 要么通过使用 wrap 方法允许我在此处扩充它。
    • mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST))) 已修复
    • 那么您可能应该将此答案标记为已接受,以便您的问题不再出现未解决,并奖励 MadScientist 一些来之不易的声誉积分。