【问题标题】:How to invoke a function in a shell script from a Makefile如何从 Makefile 调用 shell 脚本中的函数
【发布时间】:2021-02-19 07:56:14
【问题描述】:

我有一个 Makefile,它包含一个目标来打印给定的变量:

print-%:
    @echo $*=$($*)

例如要打印变量CURDIR 的值,我只需发出以下命令:

make print-CURDIR

结果如下:

CURDIR=/Users/j3d/Projects/myproject

现在我想创建一个 shell 脚本,其中包含一组可以从任何 Makefile... 调用的常用函数,这是上面目标的修改版本:

print-%:
    . ./make-util printvar $@

这里是make-util

#!/bin/sh

printvar()
{
    @echo $*=$(*)
}

最后,运行上面的脚本……

j3d@j3ds-macbook-pro myproject % make print-CURDIR

... 没有产生预期的结果:

. ./make-utils CURDIR

我应该如何调用脚本函数才能正确打印给定的变量?

【问题讨论】:

  • 你不能。 Makefile 不是 shell 脚本,shell 脚本也不是 makefile。 Make 通过首先扩展要调用的命令来工作:它将其视为文本字符串并扩展变量。然后,make 启动一个单独的 shell 进程并将扩展文本交给它,让 shell 运行并等待 shell 退出。 shell 无法访问 make 变量,因为它在一个单独的进程中,并且它无法“要求”make 为其提供一些变量(这将如何工作?)
  • 哦,我明白了...我只是想避免在每个 Makefile 中一遍又一遍地重复相同的任务。

标签: shell makefile sh


【解决方案1】:

您可以创建一套 make 配方(如果您使用 GNU make),您可以在多个 makefile 中包含和使用它们,但您必须使用 make 语法,而不是 shell 语法,因为即使配方在展开后变成了 shell 脚本,它们也是制作配方。

您可以研究 GNU make define statementevalcall 函数,以了解在 GNU make 中创建用户定义函数的方法。例如,您可以像这样编写一个 makefile:

$ cat macros.mk
print-%:
        @echo $*=$($*)

然后在您可以使用的其他 makefile 中:

include macros.mk

您会自动获得该规则。

这里有很多很多的可能性,但细节取决于你想做什么。

【讨论】:

    【解决方案2】:

    你快到了:

    由于您将函数的名称作为第一个参数传递,因此您可以做一个

    #!/bin/sh
    printvar()
    {
      @echo $*=$(*)
    }
    "$1"
    

    执行函数。如果你想要更多的安全性(捕捉错误传递一些危险命令而不是函数名的情况),你可以做一个

    [ "$1" = printvar ] && printvar
    [ "$1" = other_function ] && other_function
    

    改为。

    如果你想处理你的脚本Make-variables,你可以将它们作为附加参数传递:

    func=$1
    shift
    [ "$func" = printvar ] && printvar "$@"
    [ "$func" = other_function ] && other_function "$@"
    

    【讨论】:

    • 感谢您的回答。也许我在运行make print-CURDIR 时遗漏了一些东西,我得到了这两个错误:./make-utils: line 5: Makefile: command not found./make-utils: line 5: @echo: command not found。我已经尝试了您提到的所有选项。
    • 你的 shell 脚本中有一个命令,上面写着@echo。这意味着 shell 需要一个名为 @echo 的可执行文件在您的 PATH 中。也许你的意思只是echo
    • @j3d :我也不明白你声明的论点,$*=$(*)。这应该做什么?但这一切都与您最初的问题无关,这只是如何在 shell 脚本中调用函数。如果您的脚本有其他问题,请在Stack Overflow 上提出新问题。请注意,一个问题应该只针对一个问题。
    • 为什么这被标记为已接受的答案?它根本没有回答所提出的问题。请求是获取一个 make recipe(以及扩展的一组这样的 recipe)并将它们放入 shell 脚本函数中,以便它们可以被许多 make recipe 调用。这是不可能的。
    • @MadScientist:关于传递Make变量的信息是后来添加的。最初的问题是如何从shell 脚本调用函数 并传递参数。我在对 OP 的评论中对此进行了解释,并建议他为此提出一个不同的问题,但也扩展了我的答案以提及 Makefile 的用法。实际上,只要您可以将 any 参数从 makefile 传递到脚本,让脚本将其转发到该脚本中定义的函数是微不足道的,所以我看不出真正的问题在这里。
    猜你喜欢
    • 1970-01-01
    • 2019-12-24
    • 2012-03-08
    • 1970-01-01
    • 2019-12-29
    • 2017-10-12
    • 2019-01-19
    • 2012-01-23
    • 1970-01-01
    相关资源
    最近更新 更多