# 機能設計書 54-illink

## 概要

本ドキュメントは、.NETランタイムにおけるillink（ILリンカー）の機能設計を記述する。illinkは、.NETアセンブリから未使用のコードとメタデータを削除（トリミング）し、アプリケーションサイズを削減するツールである。

### 本機能の処理概要

illinkは、.NETアプリケーションの依存関係グラフを解析し、実際に使用されている型・メソッド・フィールドのみを含む最小サイズのアセンブリを生成する機能である。

**業務上の目的・背景**：.NETアプリケーション、特にクライアントサイドアプリケーション（Blazor WebAssembly、MAUI、コンソールアプリ）において、配布サイズの削減は重要な課題である。illinkは未使用コードを除去することで、ダウンロードサイズ、メモリ使用量、起動時間を改善する。

**機能の利用シーン**：
- 自己完結型（self-contained）アプリケーションの公開
- Blazor WebAssemblyアプリケーションのサイズ最適化
- Native AOTコンパイル時の前処理
- ライブラリの軽量化

**主要な処理内容**：
1. ルートアセンブリの解析とエントリーポイント特定
2. 依存関係グラフの構築（Mark Phase）
3. 未使用コードの特定と削除（Sweep Phase）
4. トリミング警告の生成（リフレクション使用箇所等）
5. 最適化されたアセンブリの出力

**関連システム・外部連携**：
- Mono.Cecilによるアセンブリ読み書き
- .NET SDK（dotnet publish --self-contained）との統合
- MSBuildタスクとしての統合

**権限による制御**：特別な権限制御は行わない。入力アセンブリの読み取りと出力ディレクトリへの書き込み権限が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | illinkはCLIツール/ビルドタスクのため、直接的なUI関連はない |

## 機能種別

開発ツール / トリミングツール

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| -a (assembly) | string | Yes | トリミング対象のルートアセンブリ | 存在するアセンブリ |
| -r (reference) | string | No | 参照アセンブリ | 存在するアセンブリ |
| -x (xml) | string | No | ルート記述XMLファイル | 有効なXML |
| -o (output) | string | Yes | 出力ディレクトリ | 書き込み可能なパス |
| --action | string | No | アセンブリ処理アクション | link/copy/copyused/delete/save |
| --trim-mode | string | No | トリミングモード | link/partial/full |
| --feature-* | bool | No | 機能スイッチ | true/false |
| --warn-* | int | No | 警告レベル | 0-9999 |

### トリミングルートXML例

```xml
<linker>
  <assembly fullname="MyApp">
    <type fullname="MyApp.Program" preserve="all" />
    <type fullname="MyApp.ImportantService" preserve="methods" />
  </assembly>
</linker>
```

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| trimmed assemblies | PE files | トリミングされたアセンブリ |
| warnings | text | トリミング警告メッセージ |
| dependency graph | dgml/xml | 依存関係グラフ（オプション） |

### トリミング警告例

```
warning IL2026: Method 'X.Y.Z' requires unreferenced code 'message'
warning IL2104: Assembly 'A' produced trim warnings
```

## 処理フロー

### 処理シーケンス

```
1. 初期化
   └─ Pipeline構築
   └─ LinkContext初期化
   └─ アセンブリリゾルバ設定

2. Resolve Phase
   └─ ルートアセンブリのロード
   └─ 参照アセンブリの解決

3. Mark Phase (MarkStep)
   └─ エントリーポイントからの到達可能性解析
   └─ 型・メソッド・フィールドのマーキング
   └─ インターフェース実装の追跡
   └─ 属性の処理
   └─ データフロー解析（リフレクション）

4. Sweep Phase (SweepStep)
   └─ マークされていない要素の削除
   └─ アセンブリ参照の更新
   └─ 型フォワーダの処理

5. Clean Phase (CleanStep)
   └─ 空の型・名前空間の削除
   └─ メタデータの整理

6. Output Phase (OutputStep)
   └─ トリミングされたアセンブリの出力
   └─ シンボルファイルの処理
```

### フローチャート

```mermaid
flowchart TD
    A[入力アセンブリ] --> B[Resolve Phase]
    B --> C[Mark Phase]
    C --> D{要素を処理}
    D -->|到達可能| E[マーク付与]
    D -->|到達不可能| F[マークなし]
    E --> D
    F --> D
    D -->|完了| G[Sweep Phase]
    G --> H[マークなし要素を削除]
    H --> I[Clean Phase]
    I --> J[Output Phase]
    J --> K[トリミング済みアセンブリ]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-54-1 | ルート保持 | -aで指定されたアセンブリは常に保持 | 常時 |
| BR-54-2 | エントリーポイント保持 | Mainメソッド等のエントリーポイントは常に保持 | 常時 |
| BR-54-3 | リフレクション警告 | 動的なリフレクション使用は警告を生成 | IL2xxx警告有効時 |
| BR-54-4 | 機能スイッチ評価 | フィーチャー属性に基づくコード除去 | --featureオプション指定時 |
| BR-54-5 | XML記述優先 | XMLで指定されたpreserveは最優先 | XMLルート指定時 |

### アセンブリアクション

| アクション | 説明 |
|-----------|------|
| link | アセンブリをトリミング |
| copy | アセンブリをそのままコピー |
| copyused | 使用されている場合のみコピー |
| delete | アセンブリを出力しない |
| save | 変更がある場合のみ保存 |

### トリミング警告コード（主要）

| コード | 意味 |
|--------|------|
| IL2001 | 型が見つからない |
| IL2026 | RequiresUnreferencedCode属性 |
| IL2046 | リフレクションAPI使用 |
| IL2057 | 未解決の型名 |
| IL2104 | アセンブリに警告あり |

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

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

illinkはデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| IL1001 | ルートアセンブリなし | -aオプションなし | ルートアセンブリを指定 |
| IL1002 | アセンブリ解決失敗 | 参照アセンブリが見つからない | -dで検索パス追加 |
| IL1003 | XML解析エラー | 不正なルートXML | XMLを修正 |

### リトライ仕様

illinkは単一実行のツールであり、リトライ処理は行わない。

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

illinkはトランザクション処理を行わない。エラー発生時は部分的な出力が残る可能性がある。

## パフォーマンス要件

- 一般的なアプリケーション（数十MB）は数十秒以内に処理完了
- 大規模アプリケーションでもメモリ使用量は入力サイズの数倍程度

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

- トリミングによりセキュリティ関連コードが削除されないよう注意
- 難読化されたアセンブリの処理には制限がある
- シンボルファイルの扱いに注意（デバッグ情報の漏洩防止）

## 備考

illinkは.NET SDK 6.0以降で標準的に使用されるトリミングツールである。リフレクションを多用するアプリケーションでは、トリミング属性（DynamicallyAccessedMembers等）を適切に付与する必要がある。

---

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

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

### 推奨読解順序

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

まず、illinkの中心的なデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | LinkContext.cs | `src/tools/illink/src/linker/Linker/LinkContext.cs` | リンカーコンテキスト、全体状態管理 |
| 1-2 | Annotations.cs | `src/tools/illink/src/linker/Linker/Annotations.cs` | マーキング情報の管理 |
| 1-3 | AssemblyAction.cs | `src/tools/illink/src/linker/Linker/AssemblyAction.cs` | アセンブリ処理アクション定義 |
| 1-4 | TypePreserve.cs | `src/tools/illink/src/linker/Linker/TypePreserve.cs` | 型保持レベル定義 |

**読解のコツ**:
- **62行目(LinkContext.cs)**: LinkContextクラスはIMetadataResolver等を実装し、全体の状態を管理
- **65-79行目**: Pipeline、AnnotationStore等の主要コンポーネントを保持

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

処理の開始点を特定する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Driver.cs | `src/tools/illink/src/linker/Linker/Driver.cs` | メイン処理、コマンドライン解析 |
| 2-2 | Pipeline.cs | `src/tools/illink/src/linker/Linker/Pipeline.cs` | ステップパイプライン管理 |

**主要処理フロー**:
- Driver.Main()がエントリーポイント
- Driverインスタンスを作成しRun()を実行
- Pipeline経由で各ステップを順次実行

#### Step 3: Mark Phaseを理解する

到達可能性解析の中核を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | MarkStep.cs | `src/tools/illink/src/linker/Linker.Steps/MarkStep.cs` | マーキング処理の中核 |
| 3-2 | MarkStepContext.cs | `src/tools/illink/src/linker/Linker.Steps/MarkStepContext.cs` | マーキングコンテキスト |
| 3-3 | IMarkHandler.cs | `src/tools/illink/src/linker/Linker.Steps/IMarkHandler.cs` | マークハンドラインターフェース |

**主要処理フロー**:
- **51行目(MarkStep.cs)**: MarkStepクラスがIStepを実装
- **63-70行目**: メソッドキュー、属性キュー等のワークリストを管理
- Process()メソッドでエントリーポイントからの到達可能性を解析

#### Step 4: Sweep Phaseを理解する

未使用コード削除の処理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | SweepStep.cs | `src/tools/illink/src/linker/Linker.Steps/SweepStep.cs` | 未使用要素の削除 |
| 4-2 | CleanStep.cs | `src/tools/illink/src/linker/Linker.Steps/CleanStep.cs` | 空コンテナの削除 |

**主要処理フロー**:
- **43行目(SweepStep.cs)**: SweepStepがBaseStepを継承
- **52-79行目**: Process()でマークされていないアセンブリ・参照を処理
- RemoveUnmarkedAssembly()で未使用アセンブリを削除

#### Step 5: データフロー解析を理解する

リフレクション使用の検出と警告生成を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | ReflectionMethodBodyScanner.cs | `src/tools/illink/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs` | リフレクション解析 |
| 5-2 | FlowAnnotations.cs | `src/tools/illink/src/linker/Linker.Dataflow/FlowAnnotations.cs` | フロー注釈管理 |
| 5-3 | TrimAnalysisPatternStore.cs | `src/tools/illink/src/linker/Linker.Dataflow/TrimAnalysisPatternStore.cs` | トリム解析パターン |

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

```
Driver.Main()
    │
    ├─ new Driver(args)
    │      └─ ParseCommandLine()
    │
    └─ Run()
           │
           ├─ new LinkContext()
           │      ├─ Pipeline
           │      ├─ AnnotationStore
           │      ├─ AssemblyResolver
           │      └─ Tracer
           │
           ├─ Pipeline.Process()
           │      │
           │      ├─ ResolveFromXmlStep
           │      │      └─ ルートのマーキング
           │      │
           │      ├─ MarkStep.Process()
           │      │      ├─ MarkEntryPoint()
           │      │      ├─ ProcessMarkedMethod()
           │      │      ├─ MarkReferencedTypes()
           │      │      └─ ProcessDataflowQueue()
           │      │
           │      ├─ SweepStep.Process()
           │      │      ├─ RemoveUnmarkedAssembly()
           │      │      ├─ SweepAssemblyReferences()
           │      │      └─ SweepType()
           │      │
           │      ├─ CleanStep.Process()
           │      │      └─ CleanAssembly()
           │      │
           │      └─ OutputStep.Process()
           │             └─ WriteAssembly()
           │
           └─ Dispose()
```

### データフロー図

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

ルートアセンブリ     ───▶ ResolveFromXmlStep     ───▶ ルートセット
参照アセンブリ            (ルート解決)

ルートセット         ───▶ MarkStep               ───▶ Annotations
                          (到達可能性解析)             (マーク情報)

Annotations          ───▶ SweepStep              ───▶ 削除済みアセンブリ
                          (未使用削除)

削除済みアセンブリ   ───▶ CleanStep              ───▶ 整理済みアセンブリ
                          (空要素削除)

整理済みアセンブリ   ───▶ OutputStep             ───▶ トリミング済み
                          (出力)                       アセンブリ
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Driver.cs | `src/tools/illink/src/linker/Linker/Driver.cs` | ソース | メインエントリ、CLI処理 |
| LinkContext.cs | `src/tools/illink/src/linker/Linker/LinkContext.cs` | ソース | 全体コンテキスト |
| Pipeline.cs | `src/tools/illink/src/linker/Linker/Pipeline.cs` | ソース | ステップパイプライン |
| Annotations.cs | `src/tools/illink/src/linker/Linker/Annotations.cs` | ソース | マーキング注釈 |
| AssemblyAction.cs | `src/tools/illink/src/linker/Linker/AssemblyAction.cs` | ソース | アクション定義 |
| TypePreserve.cs | `src/tools/illink/src/linker/Linker/TypePreserve.cs` | ソース | 保持レベル定義 |
| MarkStep.cs | `src/tools/illink/src/linker/Linker.Steps/MarkStep.cs` | ソース | マーキング処理 |
| SweepStep.cs | `src/tools/illink/src/linker/Linker.Steps/SweepStep.cs` | ソース | 削除処理 |
| CleanStep.cs | `src/tools/illink/src/linker/Linker.Steps/CleanStep.cs` | ソース | クリーンアップ |
| OutputStep.cs | `src/tools/illink/src/linker/Linker.Steps/OutputStep.cs` | ソース | 出力処理 |
| BaseStep.cs | `src/tools/illink/src/linker/Linker.Steps/BaseStep.cs` | ソース | ステップ基底クラス |
| IStep.cs | `src/tools/illink/src/linker/Linker.Steps/IStep.cs` | ソース | ステップインターフェース |
| ResolveFromXmlStep.cs | `src/tools/illink/src/linker/Linker.Steps/ResolveFromXmlStep.cs` | ソース | XMLルート解決 |
| ReflectionMethodBodyScanner.cs | `src/tools/illink/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs` | ソース | リフレクション解析 |
| FlowAnnotations.cs | `src/tools/illink/src/linker/Linker.Dataflow/FlowAnnotations.cs` | ソース | データフロー注釈 |
| UnreachableBlocksOptimizer.cs | `src/tools/illink/src/linker/Linker.Steps/UnreachableBlocksOptimizer.cs` | ソース | 到達不能コード最適化 |
