# バッチ設計書 24-rake amalgam

## 概要

本ドキュメントは、mrubyプロジェクトにおける `rake amalgam` タスクのバッチ設計書である。mrubyの全ヘッダーファイルとソースファイルをそれぞれ単一のファイル（`mruby.h` と `mruby.c`）に結合（アマルガメーション）する処理を定義する。

### 本バッチの処理概要

`rake amalgam` は、mrubyのヘッダーファイル群を単一の `mruby.h` に、コアソースファイル群・生成コード・gemソースを単一の `mruby.c` に結合するRakeタスクである。アマルガメーションにより、プロジェクトへの組み込みが容易になる。

**業務上の目的・背景**：mrubyを他のプロジェクトに組み込む際、多数のヘッダーファイルとソースファイルを個別に管理するのは煩雑である。アマルガメーションにより、ヘッダー1ファイルとソース1ファイルだけで mruby を利用できるようになる。SQLiteのような単一ファイル配布と同様のアプローチで、コンパイラの最適化（LTO相当の効果）も期待できる。

**バッチの実行タイミング**：手動実行。mrubyを単一ファイルとして配布・組み込みしたい場合に随時実行する。

**主要な処理内容**：
1. `:gensym` タスクを前提として実行し、プリシンボルヘッダーを生成
2. `MRuby::Amalgam` クラスを使用してヘッダーファイルを結合（`generate_header`）
3. `MRuby::Amalgam` クラスを使用してソースファイルを結合（`generate_source`）
4. ヘッダーのインクルードガード除去、インクルードのインライン展開、マクロ競合の回避処理を実施

**前後の処理との関連**：`:gensym` タスク（プリシンボル生成）が前提。また `mrblib.c`（RubyスクリプトのCソース変換結果）が存在する場合はそれも含まれる。後続バッチは特になし。

**影響範囲**：`build/{target}/amalgam/` ディレクトリに `mruby.h` と `mruby.c` を生成する。

## バッチ種別

コード生成（アマルガメーション）

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | 随時 |
| 実行時刻 | 任意 |
| 実行曜日 | N/A |
| 実行日 | N/A |
| トリガー | 手動（`rake amalgam` コマンド実行） |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| gensym完了 | プリシンボルヘッダーが生成済みであること（`:gensym` タスクに依存） |
| libmruby有効 | ビルドターゲットで `libmruby_enabled?` が true であること |
| Ruby環境 | Rakeが実行可能なRuby環境がセットアップされていること |

### 実行可否判定

`libmruby_enabled?` が true のビルドターゲットに対してのみ実行される。`:gensym` タスクが前提依存として定義されており、未完了の場合は自動実行される。

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| MRUBY_CONFIG | 環境変数（文字列） | No | デフォルトビルド設定 | 使用するビルド構成ファイルのパス |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| include/mruby.h 及び include/mruby/*.h | Cヘッダー | mrubyの公開ヘッダーファイル群 |
| include/mruby/internal.h | Cヘッダー | mrubyの内部ヘッダー |
| src/*.c | Cソース | mrubyコアソースファイル群（26ファイル） |
| build/{target}/include/mruby/presym/*.h | Cヘッダー | 生成済みプリシンボルヘッダー |
| build/{target}/mrblib/mrblib.c | Cソース | Rubyスクリプトから変換されたCソース |
| build/{target}/mrbgems/gem_init.c | Cソース | gem初期化コード |
| mrbgems/*/src/*.c, mrbgems/*/core/*.c | Cソース | 各gemのソースファイル |
| mrbgems/*/include/**/*.h | Cヘッダー | 各gemのヘッダーファイル |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| build/{target}/amalgam/mruby.h | Cヘッダー | 結合済み単一ヘッダーファイル |
| build/{target}/amalgam/mruby.c | Cソース | 結合済み単一ソースファイル |

### 出力ファイル仕様

| 項目 | 内容 |
|-----|------|
| ファイル名 | `mruby.h` / `mruby.c` |
| 出力先 | `build/{target}/amalgam/` |
| 文字コード | バイナリモード（改行コード変換なし） |
| 区切り文字 | N/A |

## 処理フロー

### 処理シーケンス

```
1. rake amalgam タスク開始
   └─ libmruby_enabled? を確認
2. ヘッダーファイル結合（generate_header）
   └─ プリアンブル出力（インクルードガード、標準ヘッダー、gem定義）
   └─ HEADER_ORDER に従ってmrubyヘッダーを順番に処理
   └─ 各ヘッダーのインクルードガードを除去
   └─ #include を再帰的にインライン展開（boxing, presym ヘッダー含む）
   └─ gemヘッダーを処理
   └─ ポストアンブル出力（#endif）
3. ソースファイル結合（generate_source）
   └─ プリアンブル出力（#include "mruby.h"）
   └─ 内部ヘッダー（internal.h, presym/table.h, value_array.h）をインライン
   └─ forward declarations 出力
   └─ CORE_SOURCE_ORDER に従ってコアソースを順番に処理
   └─ マクロクリーンアップ（#undef）
   └─ mrblib.c（生成済みRubyスクリプト）を処理
   └─ gem ソースを処理（各gem の src/ と core/ 配下）
   └─ gem_init.c を処理
4. 完了メッセージ出力
```

### フローチャート

```mermaid
flowchart TD
    A[rake amalgam 開始] --> B{libmruby_enabled?}
    B -->|No| C[スキップ]
    B -->|Yes| D[:gensym 実行]
    D --> E[generate_header]
    E --> F[プリアンブル出力]
    F --> G[HEADER_ORDER でヘッダー結合]
    G --> H[gem ヘッダー結合]
    H --> I[ポストアンブル出力]
    I --> J[generate_source]
    J --> K[内部ヘッダーインライン]
    K --> L[コアソース結合]
    L --> M[マクロクリーンアップ]
    M --> N[mrblib.c 結合]
    N --> O[gem ソース結合]
    O --> P[gem_init.c 結合]
    P --> Q[完了メッセージ出力]
    Q --> R[rake amalgam 完了]
    C --> R
```

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

### 操作別データベース影響一覧

本バッチはデータベース操作を行わない。ファイル生成操作のみ。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| N/A | ファイル未検出 | ソースファイルまたはヘッダーファイルが存在しない | ビルドを実行してから再実行 |
| N/A | gensym失敗 | プリシンボル生成に失敗した場合 | gensym のエラーを解消してから再実行 |
| N/A | ディスク容量不足 | 出力先のディスク容量が不足 | ディスク容量を確保してから再実行 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし（手動で再実行） |
| リトライ間隔 | N/A |
| リトライ対象エラー | N/A |

### 障害時対応

途中で失敗した場合、出力ファイルが不完全な状態で残る可能性がある。再実行すれば上書きされる。

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

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | なし（ファイル生成操作） |
| コミットタイミング | ファイル生成完了時 |
| ロールバック条件 | なし |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | ヘッダー約30ファイル + ソース約26ファイル + gemソース多数 |
| 目標処理時間 | 数秒以内 |
| メモリ使用量上限 | Ruby プロセスの標準的なメモリ使用量 |

## 排他制御

同一ビルドターゲットに対する同時実行は想定されていない。

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| 進捗ログ | ヘッダー生成時 | `GEN {output_path}` |
| 進捗ログ | ソース生成時 | `GEN {output_path}` |
| 完了ログ | 処理完了時 | `Amalgamation complete:` とファイルパスを表示 |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| N/A | N/A | N/A（手動実行タスクのため監視対象外） |

## 備考

- HEADER_ORDER で定義された順序でヘッダーが結合される（依存関係の順序を保証）
- CORE_SOURCE_ORDER で定義された順序でコアソースが結合される
- X-macroヘッダー（`mruby/ops.h`）はインクルード位置ごとに毎回インラインされる（マクロ定義の文脈で展開結果が変わるため）
- CONFLICTING_MACROS に定義されたマクロは各ソースファイル間で `#undef` される
- `mruby-bin-*` で始まるgemはライブラリgemではないため除外される（main関数を含むため）
- boxing ヘッダー（nan/word/no）は条件付きで選択的にインクルードされる
- 生成されるファイルはバイナリモードで書き込まれる（改行コードの変換を防ぐため）
