Makefileを自己文書化する

私たちのプロジェクトではいつも、非常に長いMakefileを使用して、インストールやビルド、テスト、デプロイメントの処理を自動化しています。ターゲット名はほとんど標準化されていますが(make installmake deploy)、中には説明が必要なものもあります(make run-devmake restart-api)。そして、詳細なmakeターゲットを追加するほど、それらの処理内容をテキスト形式で大量に記載しなければなりません。私たちのプロジェクトでは通常、このような文書をREADMEファイルに書いています。


しかしCLI(コマンドラインインタフェース)を用いる場合は、主に自己文書化ツールを使っています。makeと打つだけで、利用可能なコマンドとその説明が一覧表示されたら便利だと思いませんか?


それを実現するのは、実はとても簡単です。まずは各ターゲットを文書化するために、以下のようにターゲット名の後ろに##を付けて、コメントを記載します。

install: ## Install npm dependencies for the api, admin, and frontend apps
    @echo "Installing Node dependencies"
    @npm install

install-dev: install ## Install dependencies and prepared development configuration
    @./node_modules/.bin/selenium-standalone install
    @cp -n ./config/development.js-dist ./config/development.js | true

run-frontend-dev: webpack.PID ## Run the frontend and admin apps in dev (using webpack-dev-server)

webpack.PID:
    @./node_modules/.bin/babel-node ./node_modules/.bin/webpack-dev-server \
        --content-base=build \
        --devtool=cheap-module-inline-source-map \
        --hot \
        --inline \
        --progress \
        & echo "$$!" > webpack.PID

stop-frontend-dev: webpack.PID ## Stop the frontend and admin apps in dev
    @kill `cat $<` && rm $<
    @echo "Webpack server stopped"

restart-frontend: ## Restart the frontend and admin apps in dev
        @make stop-frontend-dev && make run-frontend-dev
        @echo "Frontend app restarted"

内部ターゲット(この例ではwebpack.PIDなど)の説明は不要なので、自己文書化の対象外になります。次にシェルスクリプトのおまじないをいくつか実行して、makefilehelpターゲットを追加します。

.PHONY: help

help:
    @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'

ポイント:このコードスニペットをmakefileにコピーする場合は、必ずテキストエディタがインデントをタブに変換しているかどうか確認する。スペースに変換してはいけない。

ポイントprintfパターン内の値30を大きい数字または小さい数字に変更することで、第1カラムの幅を調整する。

ポイント| sortを削除すると、ターゲットがアルファベット順ではなく、makefileに出現する順番に並べ替えられる。

ご紹介したすばらしいコードは、我々の協働者Briceがインターネット上で見つけた様々なスニペットに影響を受けて書いたものです。これはアウトプットの色付けにANSIコードを使っています。また、LinuxとOS Xの両方で利用できます。

仕上げ:helpターゲットをデフォルトのターゲットにする。

.DEFAULT_GOAL := help

これで、もう大丈夫です。makeは最も古いCLIタスクランチャの1つです。数多くのドキュメンテーションがあり、非常に強力で、どこにでもインストールできます。そのため、インラインヘルプを提供してくれるもののインストールが必要な言語固有のタスクランチャ(npmphp bin/consoleなど)の代わりに使うことが可能です。とにかく、makeを使うコツに興味がある場合は、私たちが書いた別の記事もご覧ください。そこではmakedockerを組み合わせ、コンテナ内でコマンドを実行するmake-docker-commandというプロジェクトについて説明しています。

アップデート:本記事は「The Hacker News」のホームページで特集されました。関連の最新情報やご意見についてはhttps://news.ycombinator.com/item?id=11195539をご覧ください。