# 機能設計書 87-clang-scan-deps

## 概要

本ドキュメントは、clang-scan-depsツールの機能設計について記述する。clang-scan-depsは、C/C++モジュールの依存関係をスキャンし、ビルドシステムに必要な情報を提供するツールである。

### 本機能の処理概要

clang-scan-depsは、ソースファイルを高速にスキャンし、コンパイルに必要なモジュール依存関係を抽出する。従来の依存関係スキャンよりも高速な「Dependency Directives Scan」モードをサポートし、大規模プロジェクトのビルド時間短縮に貢献する。

**業務上の目的・背景**：C++20モジュールやClangモジュールを使用するプロジェクトでは、ビルド前にモジュール間の依存関係を把握し、正しい順序でコンパイルする必要がある。clang-scan-depsはこの依存関係情報を高速に取得し、ビルドシステム（Make、Ninja、CMake等）に提供する。

**機能の利用シーン**：
- C++20モジュールプロジェクトのビルド準備
- Clangモジュールの依存関係解析
- ビルドシステムとの統合
- インクリメンタルビルドの最適化

**主要な処理内容**：
1. コンパイルデータベースまたはコマンドラインからの入力取得
2. 並列での依存関係スキャン
3. モジュールグラフの構築
4. 依存関係情報のJSON出力（Full/P1689/Make形式）
5. PCMパスの計算

**関連システム・外部連携**：Clang DependencyScanningライブラリ、compilation_commands.json。

**権限による制御**：特になし。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | CLIツール | 主画面 | コマンドライン実行 |

## 機能種別

依存関係解析 / ビルドサポート

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| --compilation-database | string | No | コンパイルデータベースのパス | - |
| -- | string list | No | 単一ファイル用コマンドライン | - |
| -o | string | No | 出力ファイル（デフォルト: "-"） | - |
| -j | int | No | 並列スレッド数 | 0以上 |
| --format | string | No | 出力形式（make/p1689/experimental-full） | 有効な形式名 |
| --mode | string | No | スキャンモード | preprocess-dependency-directives/preprocess |
| --module-files-dir | string | No | モジュールファイルのディレクトリ | - |
| --module-names | string | No | スキャン対象モジュール名（カンマ区切り） | - |
| --dependency-target | string | No | 依存関係ターゲット名 | - |
| --optimize-args | string | No | 最適化オプション | none/header-search/system-warnings/vfs/all |
| --resource-dir-recipe | string | No | リソースディレクトリ取得方法 | modify-compiler-path/invoke-compiler |
| --eager-load-pcm | bool | No | PCMの即時ロード | - |
| --print-timing | bool | No | 処理時間を表示 | - |
| --verbose | bool | No | 詳細出力 | - |

### 入力データソース

- compilation_commands.json（コンパイルデータベース）
- コマンドライン引数

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 依存関係情報 | JSON/Make | 形式に応じた依存関係情報 |
| 診断メッセージ | stderr | スキャン中のエラー/警告 |
| VFS統計 | stderr | --verbose時のVFS呼び出し統計 |
| タイミング情報 | stderr | --print-timing時の処理時間 |

### 出力先

- 標準出力または-oで指定されたファイル
- 標準エラー出力（診断、統計情報）

## 処理フロー

### 処理シーケンス

```
1. コマンドライン解析
   └─ ParseArgs()でオプションを取得

2. コンパイルデータベースの取得
   └─ getCompilationDatabase()
   └─ JSONCompilationDatabase::loadFromFile() または InplaceCompilationDatabase

3. コンパイルコマンドの調整
   └─ ArgumentsAdjustingCompilations
   └─ inferTargetAndDriverMode()
   └─ inferToolLocation()

4. DependencyScanningServiceの初期化
   └─ スキャンモード、出力形式、最適化オプションを設定

5. 並列スキャンの実行
   └─ ThreadPoolでScanningTaskを並列実行
   └─ 各ワーカーがDependencyScanningToolを使用

6. 依存関係の収集
   └─ Format==Make: getDependencyFile()
   └─ Format==P1689: getP1689ModuleDependencyFile()
   └─ Format==Full: getTranslationUnitDependencies()
   └─ ModuleNames指定時: getModuleDependencies()

7. 結果のマージ
   └─ FullDeps::mergeDeps()でモジュールグラフを統合

8. 出力
   └─ Full: printFullOutput()でJSON出力
   └─ P1689: printDependencies()でJSON出力
   └─ Make: 直接出力
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[ParseArgs]
    B --> C[getCompilationDatabase]
    C --> D{DB取得成功?}
    D -->|No| E[エラー終了]
    D -->|Yes| F[ArgumentsAdjustingCompilations作成]
    F --> G[DependencyScanningService初期化]
    G --> H{入力数}
    H -->|1| I[シングルスレッド実行]
    H -->|複数| J[ThreadPool作成]
    J --> K[並列ScanningTask]
    I --> L[ScanningTask]
    K --> M[待機]
    L --> N{Format?}
    M --> N
    N -->|Make| O[getDependencyFile]
    N -->|P1689| P[getP1689ModuleDependencyFile]
    N -->|Full| Q{ModuleNames?}
    Q -->|Yes| R[getModuleDependencies]
    Q -->|No| S[getTranslationUnitDependencies]
    O --> T[出力]
    P --> U[PD.addRules]
    R --> V[FD.mergeDeps]
    S --> V
    U --> W[PD.printDependencies]
    V --> X[FD.printFullOutput]
    T --> Y{RoundTripArgs?}
    W --> Y
    X --> Y
    Y -->|Yes| Z[roundTripCommands]
    Y -->|No| AA[終了]
    Z --> AA
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 入力排他 | --compilation-databaseと--は同時指定不可 | 常時 |
| BR-02 | 決定論的出力 | モジュールは名前とInputIndexでソート | Full形式出力時 |
| BR-03 | リソースディレクトリ | 絶対パスの場合のみキャッシュを使用 | RDRK_InvokeCompiler |
| BR-04 | PCMパス計算 | ContextHashとModuleNameから一意のパスを生成 | Full形式 |

### 出力形式

| 形式 | 説明 | 用途 |
|------|------|------|
| make | Makefileの依存関係形式 | 従来のビルドシステム |
| p1689 | P1689標準JSON形式 | C++20モジュール |
| experimental-full | 詳細JSON形式 | Clangモジュール |

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

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 1 | 入力エラー | コンパイルデータベースが開けない | パスを確認 |
| 1 | 入力エラー | --と--compilation-database両方指定 | 一方のみ指定 |
| 1 | スキャンエラー | 依存関係スキャンに失敗 | ソースを確認 |
| 1 | 出力エラー | 出力ファイルが作成できない | 書き込み権限確認 |

### リトライ仕様

リトライは行わない。エラーは記録するが、可能な限り他のファイルの処理を継続。

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

該当なし。

## パフォーマンス要件

- マルチスレッドによる並列スキャンをサポート（-jオプション）
- DependencyDirectivesScanモードで高速スキャン
- VFSキャッシュによる重複ファイルアクセスの削減

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

- コンパイルコマンドの実行（--resource-dir-recipe=invoke-compiler時）
- 出力ファイルへの書き込み

## 備考

- Full形式はexperimentalとして提供
- P1689形式はC++20モジュール標準に準拠
- --verboseでVFSの統計情報を出力可能

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ClangScanDeps.cpp | `clang/tools/clang-scan-deps/ClangScanDeps.cpp` | グローバル変数とオプション定義 |

**読解のコツ**:
- **83-101行目**: グローバル変数（OutputFileName, ScanMode, Format等）
- **250-262行目**: SharedStreamクラス（スレッドセーフな出力）
- **264-324行目**: ResourceDirectoryCacheクラス（リソースディレクトリキャッシュ）
- **387-618行目**: FullDepsクラス（完全な依存関係情報を管理）
- **649-715行目**: P1689Depsクラス（P1689形式の依存関係）

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ClangScanDeps.cpp | `clang/tools/clang-scan-deps/ClangScanDeps.cpp` | clang_scan_deps_main関数 |

**主要処理フロー**:
1. **841-849行目**: ターゲット初期化とコンパイルデータベース取得
2. **853-862行目**: VerbatimArgsでない場合のコンパイル調整
3. **865-935行目**: ArgumentsAdjustingCompilationsとArgsAdjuster
4. **937-956行目**: 出力ストリームの設定
5. **984-1136行目**: ScanningTaskラムダ（メインのスキャンロジック）
6. **1144-1159行目**: 並列実行またはシングルスレッド実行
7. **1186-1189行目**: 結果出力

#### Step 3: 引数解析を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ClangScanDeps.cpp | `clang/tools/clang-scan-deps/ClangScanDeps.cpp` | ParseArgs関数 |

**主要処理フロー**:
- **112-248行目**: ParseArgs関数
- **130-144行目**: --modeオプション解析
- **146-160行目**: --formatオプション解析
- **162-187行目**: --optimize-argsオプション解析

#### Step 4: スキャンタスクを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | ClangScanDeps.cpp | `clang/tools/clang-scan-deps/ClangScanDeps.cpp` | ScanningTaskラムダ |

**主要処理フロー**:
- **984-1136行目**: ScanningTaskラムダ全体
- **1008-1015行目**: Make形式の依存関係取得
- **1016-1057行目**: P1689形式の依存関係取得
- **1058-1098行目**: ModuleNames指定時の処理
- **1099-1123行目**: Full形式の翻訳単位依存関係取得

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

```
clang_scan_deps_main (ClangScanDeps.cpp:841)
    │
    ├─ InitializeAllTargetInfos
    │
    ├─ getCompilationDatabase (ClangScanDeps.cpp:756)
    │      ├─ ParseArgs (ClangScanDeps.cpp:112)
    │      └─ JSONCompilationDatabase::loadFromFile
    │          または InplaceCompilationDatabase
    │
    ├─ expandResponseFiles
    │
    ├─ inferTargetAndDriverMode
    │
    ├─ inferToolLocation
    │
    ├─ ArgumentsAdjustingCompilations
    │      └─ appendArgumentsAdjuster (ArgsAdjuster)
    │             └─ ResourceDirectoryCache::findResourceDir
    │
    ├─ DependencyScanningService (コンストラクタ)
    │
    ├─ ThreadPool または シングルスレッド
    │      │
    │      └─ ScanningTask (ClangScanDeps.cpp:984)
    │             │
    │             ├─ DependencyScanningTool (コンストラクタ)
    │             │
    │             ├─ Format==Make
    │             │      └─ WorkerTool.getDependencyFile
    │             │
    │             ├─ Format==P1689
    │             │      └─ WorkerTool.getP1689ModuleDependencyFile
    │             │             └─ PD.addRules
    │             │
    │             ├─ ModuleNames指定時
    │             │      └─ WorkerTool.getModuleDependencies
    │             │             └─ handleModuleResult
    │             │                    └─ FD.mergeDeps
    │             │
    │             └─ Format==Full (ModuleNamesなし)
    │                    └─ WorkerTool.getTranslationUnitDependencies
    │                           └─ FD.mergeDeps
    │
    ├─ RoundTripArgs時
    │      └─ FD.roundTripCommands
    │
    └─ 出力
           ├─ FD.printFullOutput (Full形式)
           └─ PD.printDependencies (P1689形式)
```

### データフロー図

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

compilation_commands.json ─┐
                           │
-- コマンドライン ─────────┼─▶ getCompilationDatabase
                           │            │
                           │            ▼
                           │   CompilationDatabase
                           │            │
-j スレッド数 ─────────────┘            ▼
                              ArgumentsAdjustingCompilations
                                        │
                                        ▼
                              DependencyScanningService
                                        │
              ┌─────────────────────────┼─────────────────────────┐
              │                         │                         │
              ▼                         ▼                         ▼
        Thread 1              Thread 2             ...      Thread N
              │                         │                         │
              ▼                         ▼                         ▼
    DependencyScanningTool  DependencyScanningTool    DependencyScanningTool
              │                         │                         │
              └─────────────────────────┼─────────────────────────┘
                                        │
                    ┌───────────────────┼───────────────────┐
                    │                   │                   │
                    ▼                   ▼                   ▼
             Make形式          P1689形式          Full形式
                    │                   │                   │
                    ▼                   ▼                   ▼
             直接出力         P1689Deps::addRules  FullDeps::mergeDeps
                    │                   │                   │
                    │                   ▼                   ▼
                    │         printDependencies   printFullOutput
                    │                   │                   │
                    └───────────────────┼───────────────────┘
                                        │
                                        ▼
                              -o ファイル / stdout
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ClangScanDeps.cpp | `clang/tools/clang-scan-deps/ClangScanDeps.cpp` | ソース | mainエントリーポイント |
| DependencyScanningService.h | `clang/include/clang/DependencyScanning/DependencyScanningService.h` | ヘッダ | スキャンサービス定義 |
| DependencyScanningWorker.h | `clang/include/clang/DependencyScanning/DependencyScanningWorker.h` | ヘッダ | ワーカー定義 |
| DependencyScanningTool.h | `clang/include/clang/Tooling/DependencyScanningTool.h` | ヘッダ | スキャンツールAPI |
| JSONCompilationDatabase.h | `clang/include/clang/Tooling/JSONCompilationDatabase.h` | ヘッダ | コンパイルDB読み込み |
