Technology Engineering

178inaba の技術ブログ

Makefile のシェル代入演算子は macOS 標準の make では使えない

postd.cc

上記記事で != (ビックリイコール) という演算子を知った。
これはシェル代入演算子といい右辺をシェルのコマンドとして実行し、実行結果を左辺に保存するという演算子である。

今回はシェル代入演算子macOS で動かない現象があったため原因と対策をメモとして残しておく。

macOS で動かない…

以下のようなシェル代入演算子を使用した Makefile がある。

FOO != ls

hello: 
  echo $(FOO)

これを以下のようなディレクトリで実行するが何も出てこないのである。
(-s は実行しているコマンドを表示せず結果のみ表示するオプション。)

$ ls
Makefile    bar     baz

$ make -s

この時点でハマった。

Linux (debian) では動く

「もしかして環境かな」と漠然と思い、 debian を Docker で動かしてその中で実行してみたら動いた。

# make -s
Makefile bar baz

バージョンを確認

debian で動いた事に「なるほど😏」と思いバーションを確認

$ make --version
GNU Make 3.81
Copyright (C) 2006  Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.

This program built for i386-apple-darwin11.3.0
# make --version
GNU Make 4.1
Built for x86_64-pc-linux-gnu
Copyright (C) 1988-2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

macOS の方が 3.81 、 debian の方は 4.1 という事で macOS 標準の方が古かったです。

シェル代入演算子はバージョン 4.0 から追加された

make のリリースノートを確認していくと 4.0 でシェル代入演算子が入った事がわかりました!

GNU Make 4.0 released

  • New feature: "!=" shell assignment operator as an alternative to the $(shell ...) function. Implemented for compatibility with BSD makefiles. Note there are subtle differences between "!=" and $(shell ...). See the description in the GNU make manual. WARNING: Backward-incompatibility! Variables ending in "!" previously defined as "variable!= value" will now be interpreted as shell assignment. Change your assignment to add whitespace between the "!" and "=": "variable! = value"

最新なら macOS でも動いた!

brew install make で最新の make をインストールすることができるので最新の make をインストールして実行してみました!

$ gmake -s
Makefile bar baz

上記のようにちゃんと動いている事が確認できました🎉
(ちなみに brew で make をインストールすると gmake という名前でインストールされます。)

まとめ

シェル代入演算子を使用した Makefile を配布するとチームのメンバーから動かないと言われる可能性が高いので現時点では使用するのはやめておいたほうがよいと思います。
macOS 標準の make が 4.0 以上になってから使用する方がよいでしょう。
それまでは今までどおり $(shell ...) を使用しておくのが無難だと思います。

昔からあるツールも日々進化しているんだなと改めて感じた出来事でした。