# 機能設計書 46-ILStrip

## 概要

本ドキュメントは、.NETランタイムにおけるILStripビルドタスクの機能設計を記述したものである。ILStripは、AOT（事前コンパイル）後のアセンブリからILコードを除去し、アプリケーションサイズを削減する機能を提供するMSBuildタスクである。

### 本機能の処理概要

ILStripは、AOTコンパイル済みのアセンブリに含まれる中間言語（IL）コードを削除または無効化することで、実行に不要なコードを除去し、アプリケーションのファイルサイズを削減する。

**業務上の目的・背景**：AOTコンパイル後は、ネイティブコードが生成されるため、元のILコードは実行時に不要となる。しかし、.NETアセンブリのメタデータはリフレクションや型情報の参照に必要なため、完全に削除することはできない。ILStripは、ILコードの本体（メソッドボディ）のみを除去し、メタデータを保持することで、サイズ削減と互換性を両立する。

**機能の利用シーン**：
- モバイルアプリケーション（iOS/Android）のサイズ最適化時
- Blazor WebAssemblyアプリケーションのダウンロードサイズ削減時
- 組み込みシステム向けアプリケーションのフットプリント削減時

**主要な処理内容**：
1. アセンブリファイルの読み込み
2. マネージドアセンブリかどうかの判定
3. アセンブリ全体のストリップ（モード1）
4. 個別メソッドのトリミング（モード2）
5. メソッドボディのゼロ埋め
6. 出力ファイルの生成

**関連システム・外部連携**：
- Mono AOTパイプライン
- MSBuildシステム
- System.Reflection.Metadata

**権限による制御**：特になし。ファイルシステムへの読み書き権限が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | ビルドプロセス（CLI） | 主機能 | AOTビルド後のポストプロセスとして呼び出される |

## 機能種別

ビルドタスク / 最適化

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| Assemblies | ITaskItem[] | Yes | ストリップ対象アセンブリ | 少なくとも1つ |
| DisableParallelStripping | bool | No | 並列処理を無効化 | - |
| TrimIndividualMethods | bool | No | 個別メソッドトリミングモード | - |
| IntermediateOutputPath | string | No | 中間出力パス | - |

### 入力データソース

- AOTコンパイル済みアセンブリファイル（.dll）
- メソッドトークンファイル（TrimIndividualMethodsモード時）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| UpdatedAssemblies | ITaskItem[] | 更新されたアセンブリリスト |

### 出力先

- ストリップ済みアセンブリ: OutputPathメタデータまたは元の場所
- トリミング済みアセンブリ: IntermediateOutputPath/stripped/

## 処理フロー

### 処理シーケンス

```
1. 入力検証
   └─ Assembliesの空チェック

2. 出力ディレクトリの準備（TrimIndividualMethods時）
   └─ strippedディレクトリの作成

3. 並列処理の設定
   └─ RequestCoresでコア数取得
   └─ 並列度の決定

4. アセンブリの処理（並列）
   └─ モード判定
   └─ StripAssemblyまたはTrimMethods

5. 結果の収集
   └─ UpdatedAssembliesの生成
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{TrimIndividualMethods?}
    B -->|Yes| C[strippedディレクトリ作成]
    B -->|No| D[並列処理設定]
    C --> D
    D --> E[Parallel.ForEach]
    E --> F{TrimIndividualMethods?}
    F -->|Yes| G[TrimMethods]
    F -->|No| H[StripAssembly]
    G --> I[結果収集]
    H --> I
    I --> J{全て成功?}
    J -->|No| K[エラー終了]
    J -->|Yes| L[UpdatedAssemblies設定]
    L --> M[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-46-01 | マネージド判定 | 非マネージドアセンブリはスキップ | 常時 |
| BR-46-02 | GUID検証 | メソッドトークンファイルのGUIDとアセンブリのMVIDが一致する必要 | TrimIndividualMethods時 |
| BR-46-03 | 共有メソッドボディ | 複数メソッドが同じRVAを共有する場合、すべてのメソッドが不要な場合のみ削除 | TrimIndividualMethods時 |
| BR-46-04 | 増分ビルド | 入力より新しい出力が存在する場合はスキップ | TrimIndividualMethods時 |

### 計算ロジック

並列度の決定:
```csharp
allowedParallelism = DisableParallelStripping ? 1 : Math.Min(Assemblies.Length, Environment.ProcessorCount);
```

メソッドボディ使用カウント:
```csharp
methodBodyUses[rva]++; // 同じRVAを持つメソッドをカウント
methodBodyUses[rva]--; // トリミング対象のメソッドをデクリメント
// count == 0 の場合のみ削除可能
```

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

該当なし（ファイルシステム操作のみ）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 引数エラー | Assembliesが空 | 少なくとも1つのアセンブリを指定 |
| - | ファイルエラー | MethodTokenFileが存在しない | パスを確認 |
| - | GUID不一致 | アセンブリのMVIDとトークンファイルのGUIDが不一致 | 正しいトークンファイルを指定 |
| - | トークンエラー | 無効なメソッドトークン | トークンファイルを再生成 |

### リトライ仕様

リトライは行わない。

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

該当なし

## パフォーマンス要件

- 並列処理によりCPUコア数に応じたスケーラビリティを確保
- 増分ビルドにより不要な処理をスキップ

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

- 入力ファイルパスの検証
- 出力ファイルの上書き制御

## 備考

- ILStripはCilStripライブラリ（Mono.Cecil派生）を使用
- TrimIndividualMethodsモードはより精密な制御が可能だが、処理が複雑

---

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

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

### 推奨読解順序

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

まず、タスクの入力パラメータを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ILStrip.cs | `src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs` | 20-55行目のプロパティ定義 |

**読解のコツ**:
- [Required]属性がAssembliesにのみ付与
- [Output]属性がUpdatedAssembliesに付与
- ConcurrentDictionaryで並列処理時のスレッドセーフを確保

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ILStrip.cs | `src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs` | 57-120行目のExecute() |

**主要処理フロー**:
1. **59-62行目**: 入力検証
2. **64-72行目**: TrimIndividualMethods時のディレクトリ準備
3. **76-87行目**: 並列度の取得（IBuildEngine9.RequestCores）
4. **91-105行目**: Parallel.ForEachで並列処理

#### Step 3: StripAssembly処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ILStrip.cs | `src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs` | 122-156行目のStripAssembly() |

**主要処理フロー**:
- **125-134行目**: OutputPathの決定
- **138行目**: AssemblyStripper.TryStripAssemblyの呼び出し
- **144-146行目**: 成功時のメタデータ設定

#### Step 4: TrimMethods処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | ILStrip.cs | `src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs` | 158-232行目のTrimMethods() |

**主要処理フロー**:
- **161-185行目**: メソッドトークンファイルの検証
- **212-214行目**: GUID検証
- **220-226行目**: メソッドボディ使用状況の計算とトリミング

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

```
Execute()
    │
    ├─ ディレクトリ準備
    │
    ├─ RequestCores()
    │
    └─ Parallel.ForEach
           │
           ├─ TrimIndividualMethods=false
           │      └─ StripAssembly()
           │              └─ AssemblyStripper.TryStripAssembly()
           │
           └─ TrimIndividualMethods=true
                  └─ TrimMethods()
                          │
                          ├─ ComputeGuid() - MVID取得
                          │
                          ├─ ComputeMethodBodyUsage() - 使用カウント
                          │
                          └─ CreateTrimmedAssembly()
                                  │
                                  ├─ ComputeMethodSize()
                                  │
                                  ├─ ComputeMethodHash()
                                  │
                                  └─ ZeroOutMethodBody()
```

### データフロー図

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

Assemblies(.dll) ───▶ AssemblyStripper.TryStripAssembly() ─▶ Stripped(.dll)
                                     │
                                     └─ (TrimIndividualMethods)
                                            │
MethodTokenFile ───────────────────────────▶│
                                            ▼
                                   ComputeMethodBodyUsage()
                                            │
                                            ▼
                                   CreateTrimmedAssembly()
                                            │
                                            ▼
                                   Trimmed(.dll)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ILStrip.cs | `src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs` | ソース | MSBuildタスク実装 |
| AssemblyStripper.cs | `src/mono/browser/build/ILStrip/AssemblyStripper.cs` | ソース | 実際のストリップ処理 |
| CilStrip | 外部ライブラリ | 依存 | Mono.Cecil派生のIL操作ライブラリ |
