☠️

Makefile入門|Goで学ぶ、はじめてのMakefile

に公開

はじめに

Goでプログラムを書いていると、

  • go build
  • go run
  • go test

…など、毎回同じコマンドを入力するのが面倒になることありませんか?

そんなときに便利なのが Makefile です。
公式ドキュメントでは「依存関係に応じて必要な処理だけを実行するツール」と説明されていますが、Goプロジェクトに限って言えば 「よく使うコマンドをまとめておける便利な仕組み」 と考えるとわかりやすいです。

最小のMakefileを書いてみる

まずはGoで「Hello, World」を出力するプログラムを作りましょう。

main.go
package main

import "fmt"

func main() {
    fmt.Println("Hello, World")
}

このプログラムをビルド・実行・削除できるMakefileは次の通りです。

Makefile
APP_NAME = hello

build:
	@echo "==> Building..."
	go build -o $(APP_NAME) main.go

run: build
	@echo "==> Running..."
	./$(APP_NAME)

clean:
	@echo "==> Cleaning..."
	rm -f $(APP_NAME)

実行してみる

$ make build
==> Building...

$ make run
==> Running...
Hello, World

$ make clean
==> Cleaning...

ポイントは:

  • build → バイナリを生成
  • runbuild に依存し、ビルド後に実行
  • clean → 生成物を削除(いわゆる phonyターゲット

ここで学んでほしいのは「Makefileがコマンドのショートカットになっている」ということです。

Goプロジェクトでよく使うターゲット例

Goのプロジェクトでは次のようなターゲットを定義することが多いです。

Makefile
APP_NAME = myapp

.PHONY: build run test fmt lint clean

build:
	go build -o $(APP_NAME) ./...

run:
	./$(APP_NAME)

test:
	go test ./...

fmt:
	go fmt ./...

lint:
	golangci-lint run ./...

clean:
	rm -f $(APP_NAME)

実行イメージ

  • make build → プロジェクトをビルド
  • make run → 実行
  • make test → テスト実行
  • make fmt → フォーマット
  • make lint → 静的解析
  • make clean → バイナリ削除

チームで開発している場合でも「みんなが同じコマンド体系で操作できる」ので、環境差異や操作ミスを減らせます。

おわりに

Goの開発でMakefileを使うと、

  • コマンド入力の手間が減る
  • チーム全員が同じ作業手順を使える
  • CI/CDに組み込みやすい

といったメリットがあります。

まずは build / run / test あたりをMakefileにまとめてみてください。
その後で lintfmt、さらにCI向けのターゲットを追加していけば、プロジェクト専用の 便利コマンド集 に育っていきます

Discussion