21世紀に新たにMakefileを書く意味はあるのか?

物心ついた頃は昭和で、十代まるまる20世紀だった地方民にとって、21世紀は「超音速原子力旅客機が飛び、潜水可能な豪華客船が航行し、海底の透明チューブの中を列車が走り、マイカーは自動運転でホバーで空だって飛べるさ」な時代になるはずだったのだが、現実には超音速旅客機による商業飛行は無くなってしまい、客船は未だに潜水せず、列車は海底よりもさらに下の地底のトンネルを走り、私の車は自動運転じゃないしタイヤが4つ付いてるし地面を走ることしかできない。*1

そして、21世紀も10分の1どころか四捨五入すると5分の1が経過したにもかかわらず、未だに私はMakefileを書いている――それも、WindowsmacOSアプリ向けに、新規作成である。

これが、組み込み機器のプロジェクトや、Linux向けアプリだったら、まだ驚きは少ないだろう。

組み込みの場合、最近は統合開発環境が増えたものの、過去のプロジェクトを見渡せば、使用するマイコン向けのコンパイラとセットでmakeが付いてくることは少なくなかった。この場合、システムのビルド用に書かれたMakefileを修正することはままあるものだ。

Linux向けのアプリやライブラリの場合、例えば「組み込みLinux」や「うちのサーバ1台で動かすデーモン」の類の場合、移植性とかあまり気にする必要がないのでautotoolsを持ち出さずにGNU Makeで済ましてしまうことも多い。

しかし、WindowsmacOSアプリである。Makefileを書く意味はあるのだろうか?

実のところ、新たに書いたMakefileは、純粋なソースコードコンパイル用ではない。アプリ本体と関連するプラグイン類のビルド、実行ファイルへの署名、インストーラの作成と署名、作成されたインストーラや関連ファイルをまとめた圧縮ファイルの作成――つまり、Webアプリでいう「デプロイ作業を自動化するスクリプト」の同等品だ。

そのため、Visual Studioのプロジェクトはdevenvで、Xcodeのプロジェクトはxcodebuildで、コマンドライン・ツール経由だが各プロジェクト・ファイルを用いてビルドしている。Makefile内でdevenvやxcodebuildを呼び出している訳だ。

本来ならば、Windowsアプリの場合、Visual Studio Installerプロジェクトを含めた関連するプロジェクトを1つのソリューション・ファイルにまとめて、ビルドの順序を整理し、ビルドの前後に実行するコマンドを設定することで、わざわざNMAKEで苦労せずとも全工程を自動化できるはずだ。こうして作成したソリューション・ファイルをdevenvで実行すれば、Visual StudioGUIを起動する必要もない。

そのはずなのだが――例えば同じリリース・ビルドでも一時的に署名なしでビルドしたいとか、そういう時にどうすればよいのか、ちょっと分からないのである。「一時的に設定を書き換えろ!」とか「一時的にバッチファイルを差し替えて!」という、少々スパルタな回答は避けたい。このあたり、天下のMicrosoftなので何かしら方法を用意してそうなものだが、未だにMSDN(というかMicrosoft謹製のドキュメント)とは相性の悪いままの私は、手がかりすら見つけられていない。なので、わざわざMakefileを書いて、NMAKE実行時に特定のマクロ変数に値をセットすることで署名あり/なしを切り替えられるようにしている。

macOSアプリも、事情は同じだ。というかmacOSアプリのインストーラ作成については、コマンド直叩きで作成する方法しか情報が引っかからないのだが*2……ディスクイメージ(*.dmg)の作成や、ファイルの圧縮(bzip2)まで自動化している。

付け加えると、関連するコンポーネント全てにVisual StudioXcodeのプロジェクト・ファイルが存在するとは限らない場合に、ある種のグルー言語としてNMAKEやGNU Makeを用いることもある。例えばGUIツールキットとしてQtを用いる場合、devenv/xcodebuild以外に「qmake、make/jom、windeployqt/macdeployqt」をMakefileから叩いたりする。

こういったmakeの使い方は、makeの特徴の一つである「更新されたファイルのみ処理する」という機能がうまく働かないことがあるという欠点がある*3。しかし一方で、「コマンドが失敗したら中断する」や「特定のターゲットのみを指定できる」という特徴は健在だ。デプロイの工程を自動化する時、途中でエラーが発生したら中断してほしいし、また後付けで「『○○のビルドだけ実行する』という機能を追加してくれないか?」という要望が出たときに、手軽に対応できるようにしたい。そんな時、makeは依然として役に立つ。

正直なところmakeは(それも、それぞれ独自に機能拡張されたNMAKE、NetBSD make、GNU Makeは)有用だとはいえバッドノウハウ度の高めなツールだ。しかし、なかなか代替の良いツール、それもデフォルトで開発環境に用意されている可能性が高く、かつ比較的規模の小さなプロジェクトにて手軽に使えるツールが見つからない。そのため、私は未だにmakeを重宝している*4

ちなみに、こんなことを書いている私だが、実はmakeは21世紀になってから覚えた。だって、プログラミング自体21世紀になってから始めたんだもん、仕方ないじゃない。

*1:あと今研究されてる自動運転技術は、なんというか、ナンカコレジャナイ感がある。なんでだろう。インタフェースがメカメカしくないからか?

*2:Mac App Storeを使えってことだろうか?

*3:なぜなら、devenvやxcodebuildを実行しないことには、アプリの再ビルドが必要か否か分からないから。ビルド対象のソースファイルなどの依存関係を知りうるのはdevenvやxcodebuildであり、makeは知ることができない。なので、makeはファイル更新日時から「devenvやxcodebuildを実行すべきか否か」を判断することができない。

*4:しかしさすがにNMAKEやNetBSD makeは避けたい。せめてGNU Makeを使わせてほしい。