如何在 Makefile 目标中使用 Bash 语法?

发布于 2024-07-13 19:26:53 字数 391 浏览 9 评论 0原文

我经常发现 Bash 语法非常有用,例如 diff 中的进程替换<(排序文件1)<(排序文件2)

是否可以在 Makefile 中使用此类 Bash 命令? 我正在考虑这样的事情:

file-differences:
    diff <(sort file1) <(sort file2) > $@

在我的 GNU Make 3.80 中,这将给出一个错误,因为它使用 sh 而不是 bash 来执行命令。

I often find Bash syntax very helpful, e.g. process substitution like in diff <(sort file1) <(sort file2).

Is it possible to use such Bash commands in a Makefile? I'm thinking of something like this:

file-differences:
    diff <(sort file1) <(sort file2) > $@

In my GNU Make 3.80 this will give an error since it uses sh instead of bash to execute the commands.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

浅忆 2024-07-20 19:26:54

有一种方法可以做到这一点,而无需显式地将 SHELL 变量设置为指向 bash。 如果您有许多 makefile,这可能很有用,因为 SHELL 不会被后续 makefile 继承或从环境中获取。 您还需要确保编译您代码的任何人都以这种方式配置他们的系统。

如果您运行 sudo dpkg-reconfigure dash 并对提示回答“否”,您的系统将不会使用 dash 作为默认 shell。 然后它将指向 bash(至少在 Ubuntu 中)。 请注意,使用 dash 作为系统 shell 效率更高一些。

There is a way to do this without explicitly setting your SHELL variable to point to bash. This can be useful if you have many makefiles since SHELL isn't inherited by subsequent makefiles or taken from the environment. You also need to be sure that anyone who compiles your code configures their system this way.

If you run sudo dpkg-reconfigure dash and answer 'no' to the prompt, your system will not use dash as the default shell. It will then point to bash (at least in Ubuntu). Note that using dash as your system shell is a bit more efficient though.

各空 2024-07-20 19:26:54

这不是问题的直接答案, makeit 是用 bash 语法进行有限的 Makefile 替换,它可以在某些情况下很有用(我是作者)

  • 规则可以定义为bash函数
  • 自动完成功能

基本思想是在末尾有while循环脚本:

while [ $# != 0 ]; do
  if [ "$(type -t $1)" == 'function' ]; then
    $1 
  else
    exit 1
  fi 
  shift
done

https://asciinema.org/a/435159

It's not a direct answer to the question, makeit is limited Makefile replacement with bash syntax and it can be useful in some cases (I'm the author)

  • rules can be defined as bash-functions
  • auto-completion feature

Basic idea is to have while loop in the end of the script:

while [ $# != 0 ]; do
  if [ "$(type -t $1)" == 'function' ]; then
    $1 
  else
    exit 1
  fi 
  shift
done

https://asciinema.org/a/435159

关于从前 2024-07-20 19:26:53

GNU Make 文档

5.3.2 Choosing the Shell
------------------------

The program used as the shell is taken from the variable `SHELL'.  If
this variable is not set in your makefile, the program `/bin/sh' is
used as the shell.

所以把 < code>SHELL := /bin/bash 位于你的 makefile 顶部,你应该可以开始了。

顺便说一句:您也可以对一个目标执行此操作,至少对于 GNU Make 来说是这样。 每个目标都可以有自己的变量分配,如下所示:

all: a b

a:
    @echo "a is $0"

b: SHELL:=/bin/bash   # HERE: this is setting the shell for b only
b:
    @echo "b is $0"

将打印:

a is /bin/sh
b is /bin/bash

有关更多详细信息,请参阅文档中的“特定于目标的变量值”。 该行可以位于 Makefile 中的任何位置,不必位于目标之前。

From the GNU Make documentation,

5.3.2 Choosing the Shell
------------------------

The program used as the shell is taken from the variable `SHELL'.  If
this variable is not set in your makefile, the program `/bin/sh' is
used as the shell.

So put SHELL := /bin/bash at the top of your makefile, and you should be good to go.

BTW: You can also do this for one target, at least for GNU Make. Each target can have its own variable assignments, like this:

all: a b

a:
    @echo "a is $0"

b: SHELL:=/bin/bash   # HERE: this is setting the shell for b only
b:
    @echo "b is $0"

That'll print:

a is /bin/sh
b is /bin/bash

See "Target-specific Variable Values" in the documentation for more details. That line can go anywhere in the Makefile, it doesn't have to be immediately before the target.

几度春秋 2024-07-20 19:26:53

你可以直接调用bash,使用-c标志:

bash -c "diff <(sort file1) <(sort file2) > $@"

当然,你可能无法重定向到变量$@,但是当我尝试这样做时,我收到了 -bash: $@: ambigously redirect 作为错误消息,因此您可能需要在深入研究之前先研究一下(尽管我使用的是 bash 3.2.something,所以也许您的工作方式不同)。

You can call bash directly, use the -c flag:

bash -c "diff <(sort file1) <(sort file2) > $@"

Of course, you may not be able to redirect to the variable $@, but when I tried to do this, I got -bash: $@: ambiguous redirect as an error message, so you may want to look into that before you get too into this (though I'm using bash 3.2.something, so maybe yours works differently).

傲娇萝莉攻 2024-07-20 19:26:53

一种可行的方法是将其放在目标的第一行中:

your-target: $(eval SHELL:=/bin/bash)
    @echo "here shell is $0"

One way that also works is putting it this way in the first line of the your target:

your-target: $(eval SHELL:=/bin/bash)
    @echo "here shell is $0"
爱,才寂寞 2024-07-20 19:26:53

如果可移植性很重要,您可能不想依赖 Makefile 中的特定 shell。 并非所有环境都可以使用 bash。

If portability is important you may not want to depend on a specific shell in your Makefile. Not all environments have bash available.

扮仙女 2024-07-20 19:26:53

您可以直接在 Makefile 中调用 bash,而不是使用默认 shell:

bash -c "ls -al"

而不是:

ls -al

You can call bash directly within your Makefile instead of using the default shell:

bash -c "ls -al"

instead of:

ls -al
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文