世界を動かす技術を、日本語で。

Mbake – 50年かかったMakefileフォーマッター兼リンター

概要

mbake はMakefileのフォーマットと検証を自動化するCLIツール。 .PHONY ターゲットの自動検出・挿入や、柔軟な設定ファイルに対応。 VSCode拡張 やCI/CDとの連携もサポート。 プラグインアーキテクチャ による拡張性。 最小限の変更 と一貫性重視の設計思想。

mbake 機能概要

  • 設定ファイル(.bake.toml) によるルールの柔軟なカスタマイズ
  • CI/CD連携 用のチェックモードを搭載
  • プラグインによる拡張性、独自ルール追加が容易
  • 進捗表示付きのリッチなターミナル出力
  • フォーマット前後の構文検証 で安全性確保
  • .PHONYターゲットの自動検出・挿入機能 (動的解析による高精度)
  • 最小限の変更でファイル構造を維持

フォーマットルール

  • インデント・空白
    • レシピ行はタブインデント(tabs推奨)
    • 代入演算子(:=, =, +=, ?=)の前後スペース統一
    • ターゲット依存関係コロンの前後スペース統一
    • 不要な末尾スペース削除
  • 行継続
    • バックスラッシュ前後のスペース正規化
    • シンプルな継続行の結合、複雑なものは保持
  • .PHONY宣言
    • 複数宣言のグループ化
    • 自動挿入(オプション)、既存宣言の強化
    • コマンド解析による動的判定
    • 既存の宣言のみ変更、ファイル構造保持

インストール方法

  • PyPI(推奨)
    • pip install mbake
  • VSCode拡張
    • 拡張機能検索で「mbake Makefile Formatter」をインストール
  • ソースから
    • git clone https://github.com/ebodshojaei/bake.git
    • cd mbake
    • pip install -e .
  • 開発用
    • pip install -e ".[dev]"

使い方

  • サブコマンド形式のCLIbake または mbake どちらも可)
    • バージョン確認: bake --version
    • 設定ファイル初期化: bake init
    • Makefile整形: bake format Makefile
    • 構文検証: bake validate Makefile
  • 設定管理
    • デフォルトで~/.bake.tomlを利用
    • カスタムパス指定や上書きも可能
  • フォーマットオプション
    • 複数ファイル対応、差分表示、バックアップ作成、詳細出力、CI/CDチェック
  • シェル補完
    • bake --install-completionで自動インストール

設定例 (~/.bake.toml)

[formatter]
use_tabs = true
tab_width = 4
space_around_assignment = true
space_before_colon = false
space_after_colon = true
normalize_line_continuations = true
max_line_length = 120
group_phony_declarations = true
phony_at_top = true
auto_insert_phony_declarations = false
remove_trailing_whitespace = true
ensure_final_newline = true
normalize_empty_lines = true
max_consecutive_empty_lines = 2
debug = false
verbose = false

スマート.PHONY検出

  • コマンド内容の動的解析 でファイル生成有無や頻出パターンを判定
    • 例:docker compose up/downnpm testなどは phony
    • 例:gcc -c myapp.c -o myapp.ophonyではない
  • 自動挿入有効化auto_insert_phony_declarations = true)で未記載ターゲットを自動追加

フォーマット前後の例

  • 基本整形前
    CC:=gcc
    CFLAGS= -Wall -g
    SOURCES=main.c \
      utils.c \
      helper.c
    .PHONY: clean
    all: $(TARGET)
      $(CC) $(CFLAGS) -o $@ $^
    .PHONY: install
    clean:
      rm -f *.o
    
  • 整形後
    CC := gcc
    CFLAGS = -Wall -g
    SOURCES = main.c utils.c helper.c
    .PHONY: all clean install
    all: $(TARGET)
      $(CC) $(CFLAGS) -o $@ $^
    clean:
      rm -f *.o
    

CI/CD連携例

  • GitHub Actions
    - name: Check Makefile formatting
      run: |
        pip install mbake
        bake format --check Makefile
    
  • 終了コード
    • 0: フォーマット済みまたは成功
    • 1: フォーマット必要または検証失敗
    • 2: エラー

開発・拡張

  • モジュール・プラグイン構造
    • bake/cli.py: CLI
    • bake/config.py: 設定管理
    • bake/core/formatter.py: フォーマットエンジン
    • bake/core/rules/: 各種ルール
    • bake/plugins/base.py: プラグインインタフェース
  • 独自ルール追加
    • FormatterPlugin継承でカスタムルール実装

コントリビュート手順

  • リポジトリのForkとブランチ作成
  • 機能追加や修正、テストの実装
  • テスト実行(pytest)
  • Pull Request作成

ライセンス・設計思想

  • MITライセンス
  • 最小限の変更とファイル構造維持
  • 一貫性あるフォーマット
  • 高速・信頼性重視
  • 開発者に優しいCLIとエラーメッセージ

Hackerたちの意見

いいね、これを https://pre-commit.com/ のフックとしてパッケージ化できたらいいな。

役に立つために複雑である必要はないよね。シェアしてくれてありがとう!

特定のルールをインラインで無視するための構文に対応してる?READMEには見当たらなかったんだけど。そういう逃げ道があるといいな。

1990年代にこういうツールを使ってたのは確かだよ。The C/C++ Users JournalやDr. Dobbsの開発者向け雑誌に広告が載ってたし。

それならMatthias Andréeのmakelじゃなかったってことだね。* https://git.maandree.se/makel それかunmake。* https://crates.io/crates/unmake それともcheckmake。* https://github.com/checkmake/checkmake (https://news.ycombinator.com/item?id=32460375) それかmake-audit。* https://github.com/david-a-wheeler/make-audit それにmakefile用のSublime linterもあるし。* https://github.com/giampaolo/SublimeLinter-contrib-makefile 50年もかかってないよね、言われてるほどは。(-:

一部のMakefileはインデントや変数の配置を意味の手がかりとして使ってることがあるよね。もしツールがそれを機械的に書き換えたら、意味を壊しながらきれいにするかもしれない。構造的な正しさだけで十分なのか、それとも人間の文脈を保つフォーマッターが必要なのかな?

理想的には、人間の文脈も保つリンターがあればいいんだけどね。でも、人間の文脈はあまりにも曖昧で変動が大きすぎて、実用的じゃないかも。意図が何かを判断するのは難しいし、カスタムルールがたくさんあるリンターが一番良いかもしれないね。

それは他のプログラミング言語と変わらないと思うけど、やっぱり自動フォーマットを好む人が多いよね。

ツールありがとう!これ、めっちゃ面白いね。何年も経った今でも「なんでPython?」ってコメントを見るのは、ほとんどコメディみたいだよ。これを書くならGoを選んでたけど、それはさておき。確かに、Pythonのインストールは難しいし、依存関係の管理はめちゃくちゃ(uv使っても、標準ツールじゃないからね;また別のが出てくるし)、パフォーマンスもひどい。でも、それでも一部のPythonライブラリは、これらの「もっと良い、速い、すごい」言語のコミュニティを合わせたよりも大きなコミュニティを持ってる。Pythonはこれからも残るよ。新参者は始めるのに必要な知識が少なくて済むから好きなんだ。最初はちょっとしたクセなんて気にしないし、結局はそれに慣れちゃうんだよね。それでいいんだ。LLMはGoよりも良いPythonを書けるし(俺はGoが好きだけど、君の好みはどうでもいいよ)。AI研究コミュニティについて少しでも知ってるなら、C++、C、Pythonか、さもなくば出て行けってことは分かるよね。これからもっと多くのツールがPythonで書かれるようになるし、主に新しく入ってくる人たちによってね。その上、アクティブなPythonのベテランが以前よりも早くコードを書いてるから、ネットワーク効果が続いてる。だから、君が考えてる言語はPythonやJSに比べたらニッチになるだろうね。俺もそれは好きじゃないけど、言語やツールが部族主義じゃなくて実力で選ばれてたら、今のウェブのJSの混乱にはなってないはずだよ。

「なんでPython?」ってコメントを見るのは、ほとんどコメディみたいだよ。確かに、Pythonのインストールは難しいし、依存関係の管理はめちゃくちゃ(uv使っても、標準ツールじゃないからね;また別のが出てくるし)、パフォーマンスもひどい。でも... 新参者は始めるのに必要な知識が少なくて済むから好きなんだ。最初はちょっとしたクセなんて気にしないし、結局はそれに慣れちゃうんだよね。君がこれを知ってるかどうかは分からないけど、はっきり言うと、ほとんどのエンドユーザーは自分のシステムにpipがインストールされてないってこと、分かってるよね?「インストール手順」がpipコマンドから始まるプロジェクトは、一般的にはうまくいかないってことも。これがしっかり理解されてるか確認したいんだ... Pythonでツールを作りたいならそれでいいけど、実際に使えるものにしたいなら、pipターゲットじゃなくてバイナリの配布が必要だよ。

Python大好き、何年も使ってるよ。でも依存関係や複数のインタプリタの状況は嫌い。素晴らしいプログラミング言語は、外部ツールなしで自立しているべきだと思う。今のところ、標準ライブラリだけを使う小さなスクリプト以外はPythonを諦めてる。そうでなければ、コンパイル言語を選ぶよ。もっと考えたことがあるけど、ここに書いておくね:http://calvinlc.com/p/2025/06/10/thank-you-and-goodbye-pytho...

Pythonで書かれたソフトウェアを配布するのは、コンパイル可能な言語に比べてパッケージマネージャー経由だと難しいよね。

他に.PHONYターゲットのリストを維持するのが面倒だと思ってる人いる?珍しいエッジケースのためにノイズを増やすだけの作業に感じてた。

「暗黙のルール検索(暗黙のルールの使用を参照)は、.PHONYターゲットではスキップされます。これが、実際のファイルが存在するかどうかを気にしなくても、ターゲットを.PHONYとして宣言することがパフォーマンスに良い理由です。」

Makefileは「make file」だよ。タスクランナーとして乱用されてる。仕事には不適切なツール。Makefileは最終更新日を基にしたファイル依存関係のこと。古いターゲットファイルはソースファイルを使って再構築できる。依存関係の管理であり、インクリメンタルコンパイラの本質だけど、タスクじゃなくてファイルに関することなんだ。

makeのいいところは、どこにでもあって、すぐに使える便利な機能があることだね。

そうだね。その目的にはちょっと微妙だし、Makeの評判を悪くしちゃうよね。

PHONYターゲットには問題なく動くけど、ほとんどの人は実際にはもっと良い方法があるって気づいてないんだよね。

.PHONYターゲットの統合は逆効果だよ。PHONY宣言はそのターゲットの隣にあるべきなんだから。

POSIX構文を受け付けてくれたらいいのに…