【问题标题】:Executable Makefile that runs in a specific directory在特定目录中运行的可执行 Makefile
【发布时间】:2020-05-17 07:38:40
【问题描述】:

我想达到的目标

  • 使用 shebang 制作可执行文件
  • 预先将其切换到某个目录,因此可以从任何位置调用它

我有什么

/docker/images/Makefile(带有可执行标志):

#!/usr/bin/make -f

default: ...
...

我可以的

cd /docker/images
./Makefile

但是,我希望能够做什么

cd /somewhere/else
/docker/images/Makefile

我尝试了什么

man make 声明,我可以设置 --directoy <dir> 参数。
但是,shebang #!/usr/bin/make --directory=/docker/images -f,不起作用:

$ cd /somewhere/else
$ /docker/images/Makefile
make: *** =/docker/images -f: Datei oder Verzeichnis nicht gefunden.  Schluss.

(未找到文件或目录)

有什么猜测吗?
我正在使用 GNU Make 4.1 使用 Devuan ASCII

我看到related thread 没有解决我的问题。

【问题讨论】:

    标签: linux makefile gnu-make executable gnu


    【解决方案1】:

    当然可以。将/usr/bin/env-S 选项一起使用,这正是为了在shebang 线上分割参数。

    $ cat Makefile
    #!/usr/bin/env -S make -C /docker/images -f
    all:
            echo Foo
    

    输出:

    $ /docker/images/Makefile
    make: Entering directory '/docker/images'
    echo Foo
    Foo
    make: Leaving directory '/docker/images'
    

    【讨论】:

    • 见鬼。如果我的环境支持它,这将是公认的答案:/usr/bin/env --version: env (GNU coreutils) 8.26 Spoiler:它不支持。 (仅 -i、-0、-u)
    • 啊,有道理。这是 8.30 版本的功能,至少在 Ubuntu 20.04 LTS 中有现货。
    【解决方案2】:

    刚刚呢:

    make -C /some/dir/where/there/is/a/makefile
    

    【讨论】:

    • 据我了解,在执行 makefile 之前,这不会更改为 /some/dir/where/there/is/a/,是吗?并且两者都不允许它按照我的要求将 makefile 作为脚本调用。
    • 这正是-C--directory 的用途。因此,您将无法像 /some/dir/makefile 那样将其调用为可执行文件 - 但像 make -C /some/dir/ 那样调用它(它会自动拾取任何名为 makefile 的文件实际上是等效的。我只是为了我的理智重新测试了它,并且在规则中打印pwd 并打印所需的目录。这是建议的替代方法,您不必接受此答案:)
    • 是的,我知道。然而,我正在明确寻找一个解决方案,允许我将其作为可执行文件启动,同时保持运行make -C /somedir Makefile 的可能性。无论如何,感谢您的意见!
    • 再问一个问题 - 您是否需要将 makefile 直接作为可执行文件调用 - 或者在您的 makefile 旁边有一个随附的可执行文件是否可以接受(比如称为 makefile_exec.sh 或其他东西) .然后这可以确定它自己的位置,确保它是当前目录,然后调用make... 在不知道你希望你的makefile可执行的确切原因的情况下很难知道,但是AFAIK这又是另一种等效方法- 但天气它适合您的特定需求,我不知道 :)
    • 是的,正如另一个comment 中提到的,我希望能够将其称为可执行文件。并通过make -C。有点出于好奇,有点因为调用部分的简单性。还有一点只是因为我可以。
    【解决方案3】:

    受到类似方法的启发,我找到了解决方案:

    我的 makefile 现在有以下头:

    #!/bin/bash
    
    # the following block will be executed by bash, but not make
    define BASH_CODE 2>/dev/null
    make -C $(dirname $0) -f $(basename $0) $@
    exit 0
    endef
    
    # the following lines will be interpreted by make, but not bash
    
    # Makefile starts here #
    volumes = $$HOME/docker/volumes
    
    # headings created with https://www.askapache.com/online-tools/figlet-ascii/
    
    default: talk
    
    talk:
        @echo Dies ist ein Test
        pwd
    
    ...
    

    有了这些行,我现在可以执行以下操作:

    1. 致电make -C /path/to/makefile/
    2. 致电/path/to/makefile/Makefile

    谁有更好的解决方案?

    【讨论】:

    • 我会暂时保留这个问题。也许有人有一个更简单的解决方案,我会接受。
    【解决方案4】:

    当我们输入#!/usr/bin/make --directory=/docker/images -f

    然后运行/docker/images/Makefile

    相当于运行:

    /usr/bin/make "--directory=/docker/images -f" /docker/images/Makefile
    

    一种解决方案是委托给第二行:

    #!/home/debian/bin/run_second_line
    # /usr/bin/make --directory=/docker/images -f
    
    default: ...
    ...
    

    在 /home/debian/bin/run_second_line:

    #!/bin/bash
    get_second_line=$(awk 'NR == 2{print}' "$1")
    exec bash -c "${get_second_line#?} $1"
    

    更新:

    它应该与这个 shebang 一起工作:

    #!/usr/bin/perl -euse File::Basename;exec qq`make -C @{[dirname $ARGV[0]]} -f ` . $ARGV[0]
    

    【讨论】:

    • 好吧,虽然它澄清了我的方法不起作用,但它也没有提供解决方案。我想要一个无需调用外部程序或脚本即可工作的解决方案。
    • 我的解决方案满足了您帖子开头的两个要求(您直接运行/docker/images/Makefile)。 a solution that works without having to call an external program or script 不在您的帖子中。
    • 这是正确的。我没有提到对单个文件的限制,因为我没有预见到调用外部脚本的解决方案。很抱歉:D
    猜你喜欢
    • 2020-04-30
    • 1970-01-01
    • 2013-03-12
    • 2018-10-07
    • 1970-01-01
    • 2013-04-08
    • 2011-02-05
    • 2012-09-30
    • 1970-01-01
    相关资源
    最近更新 更多