# 機能設計書 77-mruby-stripコマンド

## 概要

本ドキュメントは、mruby-stripコマンドの設計について記述する。コンパイル済みバイナリ（.mrb）ファイルからデバッグ情報を除去し、ファイルサイズを削減するツールである。

### 本機能の処理概要

mruby-stripコマンドは、mrbcで生成されたRiteBinaryファイル（.mrb）を読み込み、デバッグ情報（ファイル名・行番号等）を除去して再出力する。オプションでローカル変数情報（LVAR）も除去可能。組み込みシステムなどメモリ制約のある環境向けに、バイナリサイズの最適化を行う。

**業務上の目的・背景**：コンパイル済みmrubyバイナリにはデバッグ用のファイル名・行番号情報が含まれるが、本番デプロイ時にはこれらは不要。特にメモリが制限された組み込みシステムでは、バイナリサイズの削減が重要な要件となる。

**機能の利用シーン**：リリースビルド時のバイナリサイズ最適化、組み込みシステムへのデプロイ前処理、ディスク容量の節約。

**主要な処理内容**：
1. コマンドライン引数の解析（-l/--lvar）
2. .mrbファイルの読み込みとirepへの変換
3. デバッグ情報なしでのirepバイナリ再出力
4. 複数ファイルの一括処理

**関連システム・外部連携**：mrbcコマンドで生成された.mrbファイルを入力とする。

**権限による制御**：入出力ファイルへの読み書きパーミッション。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | コマンドラインツール。画面なし |

## 機能種別

バイナリ最適化ツール / コマンドラインツール

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| -l / --lvar | フラグ | No | LVAR（ローカル変数）セクションも除去 | - |
| irepfiles | 文字列列 | Yes | 処理対象の.mrbファイル（複数指定可） | 1つ以上指定されていること |

### 入力データソース

- コンパイル済みRiteBinaryファイル（.mrb）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ストリップ済み.mrb | バイナリ | デバッグ情報が除去されたRiteBinary |

### 出力先

入力ファイルを上書き（インプレース処理）。

## 処理フロー

### 処理シーケンス

```
1. parse_args() でコマンドライン引数を解析
2. mrb_open_core() で最小限のVM初期化
3. 各ファイルに対して:
   a. fopen(filename, "rb") で読み込みオープン
   b. mrb_read_irep_file() でirepに変換
   c. fclose
   d. fopen(filename, "wb") で書き込みオープン
   e. mrb_dump_irep_binary(irep, flags, wfile) で再出力
      (flagsにデバッグ情報フラグなし → デバッグ情報除去)
   f. fclose
   g. mrb_irep_decref でirep解放
4. mrb_close() でVM終了
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[parse_args]
    B --> C{引数OK?}
    C -->|No| D[usage表示→終了]
    C -->|Yes| E[mrb_open_core]
    E --> F{次のファイル?}
    F -->|No| G[mrb_close→終了]
    F -->|Yes| H[fopen rb]
    H --> I[mrb_read_irep_file]
    I --> J{読み込み成功?}
    J -->|No| K[エラー→終了]
    J -->|Yes| L[fopen wb]
    L --> M[mrb_dump_irep_binary]
    M --> N{ダンプ成功?}
    N -->|No| O[エラー→終了]
    N -->|Yes| P[fclose + irep解放]
    P --> F
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-77-1 | インプレース処理 | 入力ファイルを直接上書きする | 常時 |
| BR-77-2 | デバッグ情報除去 | flagsにデバッグ情報フラグを含めないことで除去 | 常時（デフォルト動作） |
| BR-77-3 | LVAR除去 | -l指定時はMRB_DUMP_NO_LVARフラグを設定 | -l/--lvarオプション指定時 |
| BR-77-4 | 複数ファイル | 引数で指定された全ファイルを順次処理 | 常時 |
| BR-77-5 | 最小VM | mrb_open_core()でgem不要の最小VM | 常時 |

### 計算ロジック

特になし。

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

本機能はデータベースを使用しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| EXIT_FAILURE | 引数なし | ファイルが1つも指定されていない | "no files to strip"＋usage表示 |
| EXIT_FAILURE | 読み込み失敗 | .mrbファイルが開けない | "can't open file for reading" |
| EXIT_FAILURE | irep読み込み失敗 | .mrbファイルの形式が不正 | "can't read irep file" |
| EXIT_FAILURE | 書き込み失敗 | 出力ファイルが開けない | "can't open file for writing" |
| EXIT_FAILURE | ダンプ失敗 | mrb_dump_irep_binaryがエラー | "error occurred during dumping" |
| EXIT_FAILURE | VM初期化失敗 | mrb_open_coreがNULL | "Invalid mrb_state" |

### リトライ仕様

リトライは不要。

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

該当なし。ファイル書き込み中にエラーが発生した場合、ファイルが破損する可能性がある。

## パフォーマンス要件

特に定義されていない。

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

- 入力ファイルを上書きするため、バックアップなしの破壊的操作

## 備考

- mrb_open_core()を使用するため、gemの初期化は行わない
- デバッグ情報の除去はflagsパラメータで制御（MRB_DUMP_DEBUG_INFOフラグを含めないことで実現）

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | mruby_strip.c | `mrbgems/mruby-bin-strip/tools/mruby-strip/mruby_strip.c` | struct strip_args定義（13-18行目） |

**読解のコツ**: strip_args構造体は非常にシンプル。flagsフィールドにMRB_DUMP_NO_LVARが設定されるかどうかが唯一の可変設定。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | mruby_strip.c | `mrbgems/mruby-bin-strip/tools/mruby-strip/mruby_strip.c` | main関数（110-139行目） |

**主要処理フロー**:
1. **118-122行目**: 引数なしチェック
2. **124-128行目**: parse_argsで引数解析
3. **129-133行目**: mrb_open_coreで最小VM
4. **135行目**: strip関数で実処理
5. **137行目**: mrb_closeで終了

#### Step 3: ストリップ処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | mruby_strip.c | `mrbgems/mruby-bin-strip/tools/mruby-strip/mruby_strip.c` | strip関数（63-108行目） |
| 3-2 | mruby_strip.c | `mrbgems/mruby-bin-strip/tools/mruby-strip/mruby_strip.c` | parse_args関数（28-61行目） |

**主要処理フロー**:
- **68-87行目**: ファイルループ（読み込み→irep変換→読み込みクローズ）
- **89-94行目**: 書き込みオープン
- **97行目**: mrb_dump_irep_binary呼び出し（flags指定でデバッグ情報制御）
- **99-100行目**: クローズ・irep解放

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

```
main
    ├─ parse_args
    ├─ mrb_open_core
    ├─ strip
    │   └─ [各ファイル]
    │       ├─ fopen (rb)
    │       ├─ mrb_read_irep_file
    │       ├─ fclose
    │       ├─ fopen (wb)
    │       ├─ mrb_dump_irep_binary
    │       ├─ fclose
    │       └─ mrb_irep_decref
    └─ mrb_close
```

### データフロー図

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

.mrbファイル ──▶ mrb_read_irep_file ──▶ irep構造体
                      │
                      ▼
              mrb_dump_irep_binary ──▶ .mrbファイル(上書き)
              (flags: デバッグ情報なし)     (サイズ削減)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| mruby_strip.c | `mrbgems/mruby-bin-strip/tools/mruby-strip/mruby_strip.c` | ソース | メイン実装 |
| mrbgem.rake | `mrbgems/mruby-bin-strip/mrbgem.rake` | 設定 | gem定義 |
| mruby_strip.rb | `mrbgems/mruby-bin-strip/bintest/mruby_strip.rb` | テスト | 統合テスト |
