VOYAGE GROUP の初級シェルスクリプター @katzchang です。おはこんばんちわ。
最近、 make 、 Makefile をゴリゴリ使い出しているところなので、それについて今日はちょっと書いてみることにします。
さて、プロフェッショナルな技術者たる皆さんであれば、一生に何度かは「ディレクトリをカレントに入れてメイク、ディレクトリをカレントに入れてメイク…」というご経験があろうことかと思います。 make のイメージといえば:
- C言語で書かれたアレをコンパイルする、よくある手順
- もしかしてC++かもしれないけど大勢に無影響
- たまに失敗するけどあれマジなんなの困る
そんな make 環境ですが、意外にも普通に使えるのです。普通というと、ベターシェルスクリプトとして。ここで「それ、普通じゃないすか」と思った方、いらっしゃいますか?その通り、大したことが書いてないです。お疲れ様でした。以下は、まだ疲れていない方のための記事です。大丈夫、難しいことは書けないので。
Hello Make World
makeの本当の姿、それはターゲット駆動スクリプト言語です。 Makefile に書かれたターゲットを make コマンドで発火させます。訳の分からないことを言うのはここまでにしておいて、とりあえず Hello World から始めましょう。適当なディレクトリを作って、 Makefile ファイルを作って、 make コマンドで実行してみます。
$ mkdir hello_make; cd hello_make $ vim Makefile
Makefileファイルの内容は:
all: hello_make hello_make: echo Hello Make World!!
"echo" の手前は tab です。 tab だけが許されています。ここに論争はありません。そして、makeコマンドで実行:
$ make echo Hello Make World!! Hello Make World!!
普通に echo しているだけです、簡単ですね。 "all" や "hello_make" はターゲットってやつで、 "make" コマンドだけであれば all ターゲットが実行されます。 "all: hello_make" としていることで、 all は hello_make ターゲットに依存している(つまり、事前に実行する)ことになります。 make コマンドにターゲットを続けることで、狙いのものを実行させることもできます。
$ make hello_make echo Hello Make World!! Hello Make World!!
「 make コマンドが実行できない!!」等の場合は、osx make command not found、centos make command not foundなどでおググり頂ければ幸いです。
エラーで止まる
何かの手順をシェルスクリプトにする場合、途中でコケたら嫌ですよね。でも、ステータスコードを途中で拾ってifってexitるとか、いちいち書きたくないですよね?…ですよね?
でも大丈夫、我々には make があります。
たとえば、 curl と grep を組み合わせて、サイトをテストしてみましょう。 grep は、与えた文字列が見つかれば 0 、見つからなければ 1 を、ステータスコードとして返します。では、先程の Makefile に check_hito ターゲットを足してみます。
all: check_hito hello_make hello_make: echo Hello Make World!! check_hito: curl --silent voyagegroup.com | grep "人月を軸にした事業開発会社"
で、make。
$ make curl --silent voyagegroup.com | grep "人月を軸にした事業開発会社" make: *** [check_voyagegroup] Error 1
あぁ、間違いました。「人を軸にした事業開発会社」でしたね。でもこれで、エラーが起こると、その先の "hello_world" ターゲットが実行されていないことがわかりました。
修正し、
check_hito: curl --silent voyagegroup.com | grep "人を軸にした事業開発会社"
make 。
$ make curl --silent voyagegroup.com | grep "人を軸にした事業開発会社" <title>株式会社VOYAGE GROUP | 人を軸にした事業開発会社</title> <meta property="og:title" content="株式会社VOYAGE GROUP | 人を軸にした事業開発会社" /> echo Hello Make World!! Hello Make World!!
hello_world まで、エラーなく実行されたようです。
パラメータが便利
「僕が叩きたいのは voyagegroup.com じゃないんだ、テスト環境は別なんだよ」というあなたに、更に朗報です!対象をパラメータ化してみましょう。
TARGET = voyagegroup.com all: check_hitowo hello_make hello_make: echo Hello Make World!! check_hitowo: curl --silent $(TARGET) | grep "人を軸にした事業開発会社"
上部に TARGET 変数を定義し、 voyagegroup.com としておきます。 curl のパラメータを "$(TARGET)" とすれば、お察しの通り、埋め込まれることになります。make 。
$ make curl --silent voyagegroup.com | grep "人を軸にした事業開発会社" <title>株式会社VOYAGE GROUP | 人を軸にした事業開発会社</title> <meta property="og:title" content="株式会社VOYAGE GROUP | 人を軸にした事業開発会社" /> echo Hello Make World!! Hello Make World!!
さて、 TARGET を変えてみましょう。 make 実行時に、引数として指定します:
$ make TARGET=ecnavi.jp curl --silent ecnavi.jp | grep "人を軸にした事業開発会社" make: *** [check_hito] Error 1
切り替わってますね!正常にエラーになりました。シェルスクリプトと違ってデフォルト値や定義名を与えることができるので、可読性は良さそうな気がしませんか?
次のステップ(やること・やらないこと)
- ビルド用スクリプト
- デプロイ用スクリプト
- テスト用スクリプト
みたいな部分が、私としては今後使いたいようなところです。 make はコマンドとステータスコードで頑張ってくれるので、 phpunit や ant、 git、ssh など、他のコマンドを組み合わせて使うことも簡単にできたりします。
他方、込み入った Makefile はできるだけ避けるべきかもしれません。高度な Makefile を使いこなすほど我々は賢くないという可能性も考えておくべきです。複雑な処理は従来のシェルスクリプトを書けばいいんじゃないでしょうか。というかむしろお好みの、普通のプログラミング言語を使ったほうがよさそうな気がします。ただ、make厨二病にはまだ感染していないので、もしかしてこれから色々ありそうな予感もしますが、そのあたりは追々で。
補足:補完とzsh
zsh が便利なのは言うまでもないですが、 make コマンドでターゲットを補完してくれたり(たぶん初期設定状態で)するのでおすすめです。 Ubuntu の bash も、初期設定状態でも補完できるようになってたりするので、いろいろ便利です。お試しください。