# 機能設計書 86-make（ビルドツール）

## 概要

本ドキュメントは、FreeBSDにおけるmake（bmake）コマンドの機能設計を記述する。bmakeはNetBSD由来のPOSIX互換makeユーティリティであり、Makefileに記述された依存関係とビルドルールに基づいてソフトウェアのビルドを自動化する。FreeBSDのベースシステム全体のビルドに使用される中核的なビルドツールである。

### 本機能の処理概要

**業務上の目的・背景**：makeはソフトウェア開発のビルド自動化において最も基本的なツールである。FreeBSDのカーネル・ユーザランド・ポートの全ビルドプロセスがbmakeに依存しており、FreeBSDの開発・保守の基盤を形成する。依存関係の自動解析、差分ビルド、並列ビルドにより効率的なビルドプロセスを実現する。

**機能の利用シーン**：FreeBSDベースシステムのビルド（buildworld/buildkernel）、ポーツコレクションのビルド、アプリケーションのコンパイル・リンク、インストール処理の自動化。

**主要な処理内容**：
1. Makefile解析: ターゲット・依存関係・コマンドの解析（parse.c）
2. 依存関係グラフ構築: ターゲットの依存関係をDAGとして構築（make.c, targ.c）
3. 条件評価: .if/.else/.endif条件ディレクティブの評価（cond.c）
4. 変数展開: 変数の定義・参照・修飾子処理（var.c）
5. ジョブ実行: 並列ジョブ管理と子プロセスによるコマンド実行（job.c）
6. サフィックスルール: .c.o等の暗黙ルール管理（suff.c）
7. メタモード: ビルドログとファイル依存関係の自動追跡（meta.c）

**関連システム・外部連携**：/bin/sh（コマンド実行シェル）、share/mk/（システムMakefileインクルード群）、ファイルシステム（タイムスタンプ比較）。

**権限による制御**：一般ユーザで実行可能。ビルド対象のディレクトリへの書き込み権限が必要。installターゲットではroot権限が必要な場合がある。

## 関連画面

該当なし（CLIコマンドのため画面は存在しない）

## 機能種別

ビルド自動化処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| -f makefile | string | No | Makefileパス指定（デフォルト: Makefile/makefile） | ファイル存在 |
| -j max_jobs | integer | No | 並列ジョブ数 | 正の整数 |
| -n | flag | No | ドライラン（コマンド表示のみ） | - |
| -k | flag | No | エラー時も他ターゲットの処理続行 | - |
| -V variable | string | No | 変数値の表示 | - |
| -D variable | string | No | 変数の定義 | - |
| -m directory | string | No | sys.mkディレクトリ指定 | 有効なディレクトリ |
| target | string | No | ビルドターゲット（デフォルト: all） | Makefile内に定義 |

### 入力データソース

Makefile（ビルドルール定義）、share/mk/配下のシステムMakefile群、環境変数、コマンドライン変数。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ビルド成果物 | file | コンパイル済みオブジェクト・バイナリ・ライブラリ |
| ビルドログ | string | 実行コマンドの標準出力/標準エラー出力 |
| メタデータ（メタモード時） | file | .metaファイル（ビルド依存関係追跡） |

### 出力先

ファイルシステム（ビルド成果物）、標準出力/標準エラー出力（ビルドログ）。

## 処理フロー

### 処理シーケンス

```
1. 初期化
   └─ main.c: コマンドライン解析、変数初期化、.MAKE.* 変数設定
2. Makefile読み込み・解析
   └─ parse.c: Makefile構文解析、ターゲット・依存関係・コマンド登録
3. 変数展開
   └─ var.c: ${VAR}形式の変数展開、修飾子(:S/:C/:H/:T等)処理
4. 条件評価
   └─ cond.c: .if/.ifdef/.ifndef等の条件ディレクティブ評価
5. サフィックスルール解決
   └─ suff.c: 暗黙ルール(.c.o等)の適用
6. 依存関係解析
   └─ make.c: ターゲットのDAGを走査し、ビルド必要性を判定
7. ジョブ実行
   └─ job.c: fork+execで子プロセスを生成し、コマンドを/bin/sh経由で実行
8. 完了処理
   └─ 終了コード設定（0:成功、1:ターゲット失敗、2:エラー）
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[main: 初期化]
    B --> C[parse: Makefile解析]
    C --> D[cond: 条件評価]
    D --> E[var: 変数展開]
    E --> F[suff: サフィックスルール解決]
    F --> G[targ: 依存関係グラフ構築]
    G --> H[make: ビルド必要性判定]
    H --> I{ビルド必要?}
    I -->|Yes| J[job: ジョブ実行]
    I -->|No| K[スキップ]
    J --> L{並列実行?}
    L -->|Yes| M[fork: 並列ジョブ]
    L -->|No| N[compat: 逐次実行]
    M --> O[完了判定]
    N --> O
    K --> O
    O --> P[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-86-01 | タイムスタンプ比較 | ターゲットの更新日時が依存ファイルより古い場合にリビルド | 依存関係判定時 |
| BR-86-02 | 並列ジョブ制御 | -j Nで最大N個の子プロセスを同時実行 | -jオプション指定時 |
| BR-86-03 | メタモード | .MAKE.MODE=metaで.metaファイルにビルド依存関係を自動記録 | メタモード有効時 |
| BR-86-04 | デフォルトターゲット | ターゲット未指定時は最初のターゲット（慣例的にall） | ターゲット未指定時 |
| BR-86-05 | サフィックスルール | .SUFFIXES定義に基づく暗黙のビルドルール適用 | 明示ルールがない場合 |

### 計算ロジック

依存関係判定: stat(2)でターゲットと依存ファイルのmtimeを比較。ターゲットが存在しないか、依存ファイルのmtimeが新しい場合にリビルドが必要と判定する。

## データベース操作仕様

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 2 | Makefile構文エラー | 不正なMakefile記述 | parse.c: エラー箇所と行番号を表示 |
| 1 | ビルドコマンド失敗 | 子プロセスの非0終了 | job.c: エラー報告、-k未指定時はビルド中止 |
| 2 | Makefile不存在 | 指定されたMakefileが見つからない | エラーメッセージ出力後終了 |
| 2 | 循環依存 | 依存関係グラフにサイクルが存在 | 循環検出しエラー報告 |

### リトライ仕様

リトライは行わない。-kオプションで失敗時も他ターゲットの処理を継続可能。

## トランザクション仕様

ビルドは個別ターゲット単位で実行される。一つのターゲットが失敗しても、既にビルド済みのターゲットはロールバックされない。

## パフォーマンス要件

- -jオプションによる並列ビルドで複数CPUコアを活用可能
- 依存関係のstat(2)呼出回数を最小化するディレクトリキャッシュ（dir.c）
- メタモードではビルド済み成果物の不要リビルドを防止

## セキュリティ考慮事項

- Makefileコマンドは/bin/sh経由で実行されるため、信頼できないMakefileの実行に注意
- 環境変数からの変数注入による意図しないビルド動作の可能性

## 備考

- bmakeはNetBSD make由来。contrib/bmake/から取り込み
- FreeBSDのビルドシステム（Makefile.inc1等）はbmakeの拡張機能に依存
- ソースファイルは19個のCファイルで構成（Makefile:18-39行目のSRCS定義）

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

bmakeの中核データ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | config.h | `usr.bin/bmake/config.h` | ビルド環境の機能検出定義 |

**読解のコツ**: bmakeはautoconf由来のconfig.hでプラットフォーム差異を吸収する。HAVE_*マクロでシステム機能の有無を判定。

#### Step 2: エントリーポイント

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | main.c | `contrib/bmake/main.c` | main()関数。初期化、Makefileロード、ビルド実行のオーケストレーション |

#### Step 3: Makefile解析

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | parse.c | `contrib/bmake/parse.c` | Makefile構文解析。ターゲット・依存関係・コマンドの登録 |
| 3-2 | cond.c | `contrib/bmake/cond.c` | 条件ディレクティブ評価 |
| 3-3 | var.c | `contrib/bmake/var.c` | 変数展開・修飾子処理 |

#### Step 4: 依存関係とビルド

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | targ.c | `contrib/bmake/targ.c` | ターゲットノード管理 |
| 4-2 | make.c | `contrib/bmake/make.c` | 依存関係解析とビルド判定 |
| 4-3 | suff.c | `contrib/bmake/suff.c` | サフィックスルール管理 |

#### Step 5: ジョブ実行

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | job.c | `contrib/bmake/job.c` | 並列ジョブ管理、fork/exec、シグナル処理 |
| 5-2 | compat.c | `contrib/bmake/compat.c` | 互換モード（逐次実行）処理 |

#### Step 6: ユーティリティ

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 6-1 | dir.c | `contrib/bmake/dir.c` | ディレクトリキャッシュ・ファイル検索 |
| 6-2 | hash.c | `contrib/bmake/hash.c` | ハッシュテーブル実装 |
| 6-3 | meta.c | `contrib/bmake/meta.c` | メタモード（ビルド依存関係自動追跡） |
| 6-4 | arch.c | `contrib/bmake/arch.c` | アーカイブ（.a）ライブラリメンバ処理 |

### プログラム呼び出し階層図

```
bmake main()
    |
    +-- MainParseInit()        # 初期化
    +-- Parse_File()           # Makefile解析
    |       +-- parse.c         # 構文解析
    |       +-- cond.c          # 条件評価
    |       +-- var.c           # 変数展開
    |
    +-- MakeStarter()          # ビルド開始
    |       +-- make.c          # 依存関係解析
    |       +-- targ.c          # ターゲットグラフ
    |       +-- suff.c          # サフィックスルール
    |
    +-- Job_Begin() / Compat_Run()  # ジョブ実行
    |       +-- job.c           # 並列ジョブ管理
    |       |       +-- fork()  # 子プロセス生成
    |       |       +-- exec /bin/sh  # コマンド実行
    |       +-- compat.c        # 逐次実行
    |
    +-- dir.c                  # ディレクトリキャッシュ
    +-- meta.c                 # メタモード管理
```

### データフロー図

```
[入力]                       [処理]                          [出力]

Makefile ──> parse.c: 構文解析 ──> 依存関係グラフ(DAG)
share/mk/*.mk ──> var.c: 変数展開
環境変数 ──> cond.c: 条件評価

依存関係グラフ ──> make.c: ビルド判定 ──> ジョブキュー
                   stat()タイムスタンプ比較

ジョブキュー ──> job.c: fork+exec ──> ビルド成果物
                 /bin/sh コマンド実行     (.o, バイナリ, .a等)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| main.c | `contrib/bmake/main.c` | ソース | メインプログラム |
| parse.c | `contrib/bmake/parse.c` | ソース | Makefile構文解析 |
| var.c | `contrib/bmake/var.c` | ソース | 変数展開・修飾子 |
| cond.c | `contrib/bmake/cond.c` | ソース | 条件ディレクティブ |
| make.c | `contrib/bmake/make.c` | ソース | 依存関係解析 |
| targ.c | `contrib/bmake/targ.c` | ソース | ターゲットノード管理 |
| suff.c | `contrib/bmake/suff.c` | ソース | サフィックスルール |
| job.c | `contrib/bmake/job.c` | ソース | 並列ジョブ管理 |
| compat.c | `contrib/bmake/compat.c` | ソース | 逐次実行モード |
| dir.c | `contrib/bmake/dir.c` | ソース | ディレクトリキャッシュ |
| hash.c | `contrib/bmake/hash.c` | ソース | ハッシュテーブル |
| meta.c | `contrib/bmake/meta.c` | ソース | メタモード |
| arch.c | `contrib/bmake/arch.c` | ソース | アーカイブメンバ処理 |
| buf.c | `contrib/bmake/buf.c` | ソース | バッファ管理 |
| for.c | `contrib/bmake/for.c` | ソース | .forループ処理 |
| lst.c | `contrib/bmake/lst.c` | ソース | リンクリスト |
| str.c | `contrib/bmake/str.c` | ソース | 文字列処理 |
| trace.c | `contrib/bmake/trace.c` | ソース | トレース出力 |
| util.c | `contrib/bmake/util.c` | ソース | ユーティリティ |
| Makefile | `usr.bin/bmake/Makefile` | ビルド設定 | FreeBSD向けビルド設定 |
| config.h | `usr.bin/bmake/config.h` | ヘッダ | プラットフォーム設定 |
