Makefile上でprocess置換を使う方法

TL;DR makeはデフォルトでshが動く。bashなどにしないとprocess置換が使えない。

make中ではprocess置換が使えない?

何も考えずにprocess置換を使おうとするとエラーになってしまう。

$ make 02
python <(python -m prestring.python hello.py)
/bin/sh: -c: line 0: syntax error near unexpected token `('
/bin/sh: -c: line 0: `python <(python -m prestring.python hello.py)'
make: *** [02] Error 2

このときのMakefileは以下のようなもの。

Makefile

00:
  python hello.py

01:
  python -m prestring.python hello.py

# process置換を利用
02:
  python <(python -m prestring.python hello.py)

03:
  python <(python <(python -m prestring.python hello.py))

デフォルトで使われるshellはsh

原因は単純でデフォルトで使われるshellがshなので。これは以下の様なコードを追加して実行してみると確認できる。

$(info $(SHELL))

はい。

$ make 02
/bin/sh

SHELLの値を書き換えてあげればprocess置換ができる

こんなかんじに。

SHELL := $(shell which bash)

やりましたね。ネストしても大丈夫です。

$ make 02
python <(python -m prestring.python hello.py)
print("hello")

$ make 03
python <(python <(python -m prestring.python hello.py))
hello

おまけ

prestring.pythonはこういう結果を返していました。

$ python -m prestring.python hello.py
from prestring.python import PythonModule


def gen(*, m=None, indent='    '):
    m = m or PythonModule(indent=indent)

    m.stmt('print("hello")')
    return m


if __name__ == "__main__":
    m = gen(indent='    ')
    print(m)

実行するとpythonコードを出力するpythonコードです。

$ python <(python -m prestring.python hello.py)
print("hello")

$ python <(python <(python -m prestring.python hello.py))
hello

あ、hello.pyの中身はこんな感じでした。

hello.py

print("hello")

gist