# 機能設計書 11-外部Cコンパイラ連携

## 概要

本ドキュメントは、Nimコンパイラにおける外部Cコンパイラ連携機能の設計仕様を記述する。この機能はNimが生成したCコードを実際の実行可能バイナリに変換するための外部コンパイラ・リンカとの連携を担当する。

### 本機能の処理概要

外部Cコンパイラ連携機能は、NimコンパイラがC言語に変換したソースコードを、GCC、Clang、MSVC等の外部Cコンパイラを呼び出してコンパイル・リンクし、最終的な実行可能バイナリやライブラリを生成する機能である。

**業務上の目的・背景**：Nimは言語設計上、直接マシンコードを生成せず、中間言語としてC/C++コードを生成するアプローチを採用している。この設計により、既存のC/C++エコシステムとの高い互換性、多様なプラットフォームへの対応、そして成熟したCコンパイラの最適化機能の活用が可能となっている。外部Cコンパイラ連携機能は、この設計思想を実現するための中核的なコンポーネントであり、Nimコードから最終成果物（実行ファイル、ライブラリ）への変換パイプラインを完成させる役割を担う。

**機能の利用シーン**：この機能は`nim c`（Cコード生成＆コンパイル）、`nim cpp`（C++コード生成＆コンパイル）、`nim r`（コンパイル＆実行）などのコマンド実行時に利用される。開発者がNimソースコードをコンパイルして実行可能バイナリを得る際、必ずこの機能が呼び出される。また、共有ライブラリ（DLL/SO）や静的ライブラリの生成時にも使用される。

**主要な処理内容**：
1. 対象プラットフォームに適したCコンパイラの自動検出と選択
2. コンパイラ固有のコマンドラインオプションの構築
3. 複数のCソースファイルの並列コンパイル
4. オブジェクトファイルのリンク処理
5. macOSアプリケーションバンドルの生成
6. ビルドキャッシュの管理とインクリメンタルコンパイル

**関連システム・外部連携**：GCC、Clang、MSVC（Visual C++）、TinyC Compiler、Intel C Compiler、NVIDIA NVCC、AMD HIPCCなど、多様な外部コンパイラと連携する。また、各プラットフォーム固有のリンカ（GNU ld、lld、MSVC link.exe等）とも連携する。

**権限による制御**：特になし。システム上で外部コンパイラが利用可能であることが前提となる。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 2 | nim c（Cコード生成） | 主画面 | GCC/Clang/MSVCとの連携によるバイナリ生成 |
| 3 | nim cpp（C++コード生成） | 主画面 | C++コンパイラとの連携によるバイナリ生成 |
| 6 | nim r（コンパイル＆実行） | 補助機能 | 外部コンパイラでバイナリを生成し実行 |

## 機能種別

外部プログラム連携 / ビルド処理 / ファイル出力

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| conf | ConfigRef | Yes | コンパイラ設定オブジェクト | nil不可 |
| toCompile | CfileList | Yes | コンパイル対象のCファイルリスト | 空リスト可 |
| cCompiler | TSystemCC | Yes | 使用するCコンパイラの種類 | TSystemCC enum値 |
| outFile | AbsoluteFile | Yes | 出力ファイルパス | 有効なパス |
| globalOptions | TGlobalOptions | Yes | グローバルオプション（最適化レベル等） | set型 |

### 入力データソース

- NimコンパイラのCコード生成フェーズが出力したCソースファイル
- コマンドライン引数で指定されたコンパイラオプション
- nimcfg設定ファイルで指定されたコンパイラ設定
- 環境変数（CC, CXX等）で指定されたコンパイラパス

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 実行可能ファイル | バイナリファイル | コンパイル・リンクされた実行可能バイナリ |
| オブジェクトファイル | .o/.obj | 各Cソースファイルのコンパイル結果 |
| 共有ライブラリ | .so/.dll/.dylib | 動的リンクライブラリ |
| 静的ライブラリ | .a/.lib | 静的リンクライブラリ |
| JSONビルドキャッシュ | .json | インクリメンタルビルド用キャッシュファイル |

### 出力先

- nimcacheディレクトリ（オブジェクトファイル、中間ファイル）
- 指定された出力パス（最終バイナリ）
- macOS: アプリケーションバンドル（.app）

## 処理フロー

### 処理シーケンス

```
1. コンパイル対象ファイルの確認
   └─ CfileListからキャッシュ済みファイルを除外
2. コンパイルコマンドの構築
   └─ 各CファイルについてgetCompileCFileCmd()を呼び出し
3. 並列コンパイル実行
   └─ execCmdsInParallel()で複数ファイルを並列処理
4. リンクコマンドの構築
   └─ getLinkCmd()でリンカコマンドを生成
5. リンク処理の実行
   └─ コマンドライン長制限を考慮してリンク実行
6. 追加処理（プラットフォーム固有）
   └─ macOS: dsymutil実行、アプリバンドル生成
7. ビルドキャッシュの保存
   └─ JSONビルド命令ファイルの書き込み
```

### フローチャート

```mermaid
flowchart TD
    A[開始: callCCompiler] --> B{optCompileOnly?}
    B -->|Yes| C[スクリプト生成のみ]
    B -->|No| D[コンパイルコマンド構築]
    D --> E[各Cファイルをループ]
    E --> F{キャッシュ済み?}
    F -->|Yes| E
    F -->|No| G[コンパイルコマンド追加]
    G --> E
    E --> H[並列コンパイル実行]
    H --> I{optNoLinking?}
    I -->|Yes| J[終了]
    I -->|No| K[オブジェクトファイル収集]
    K --> L{HCRモード?}
    L -->|Yes| M[各ファイルを個別リンク]
    L -->|No| N[getLinkCmd呼び出し]
    N --> O{コマンド長超過?}
    O -->|Yes| P[レスポンスファイル経由]
    O -->|No| Q[直接実行]
    P --> R[リンク完了]
    Q --> R
    M --> R
    R --> S{macOS GUI?}
    S -->|Yes| T[アプリバンドル生成]
    S -->|No| U[終了]
    T --> U
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-11-01 | コンパイラ自動選択 | 環境に応じて適切なCコンパイラを自動選択 | --cc指定がない場合 |
| BR-11-02 | 並列コンパイル | CPUコア数に応じてコンパイルを並列実行 | numberOfProcessors > 1 |
| BR-11-03 | コマンドライン長制限 | OSの制限を超える場合はレスポンスファイルを使用 | Windows: 8000文字、macOS: 260000文字 |
| BR-11-04 | キャッシュ利用 | 変更のないファイルは再コンパイルをスキップ | CfileFlag.Cached |

### 計算ロジック

- 並列実行数: `numberOfProcessors`が0の場合は`countProcessors()`で自動取得
- コマンドライン長閾値: Windows 8KB、macOS 260KB、その他Unix 32KB

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

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

本機能はデータベースを使用しない。ファイルシステムベースのキャッシュを使用する。

### ファイルシステム操作

| 操作 | 対象 | 操作種別 | 概要 |
|-----|------|---------|------|
| ビルドキャッシュ読み込み | {project}.json | READ | 前回ビルド情報の読み込み |
| ビルドキャッシュ書き込み | {project}.json | WRITE | ビルド命令の保存 |
| オブジェクトファイル生成 | nimcache/*.o | WRITE | コンパイル結果の保存 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| errGenerated | 外部プログラムエラー | Cコンパイラの実行失敗 | エラーメッセージと終了コードを表示 |
| OSError | システムエラー | ファイルアクセス失敗、プロセス起動失敗 | 詳細なOSエラーメッセージを表示 |
| errInternal | 内部エラー | JSONキャッシュの解析失敗 | キャッシュを再生成 |

### リトライ仕様

外部コンパイラの実行失敗時のリトライは行わない。エラー発生時は即座にコンパイルプロセス全体を停止する。

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

ファイルシステム操作のみのため、トランザクション管理は行わない。一時ファイル（レスポンスファイル、リンカスクリプト）は処理完了後に削除する。

## パフォーマンス要件

- 並列コンパイル: CPUコア数に応じた並列実行でコンパイル時間を短縮
- インクリメンタルビルド: 変更のないファイルの再コンパイルをスキップ
- レスポンスファイル: 大量ファイルのリンク時のコマンドライン制限回避

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

- 外部コンパイラのパスは信頼できるソースから取得
- 生成されるバイナリのパーミッション設定（実行権限の付与）
- macOSアプリバンドル生成時のInfo.plist内容のXMLエスケープ

## 備考

- TSystemCC enum型でサポートされるコンパイラ: gcc, nintendoSwitchGCC, llvmGcc, clang, vcc, nvcc, hipcc, clangcl, icl, icc, bcc, tcc, envcc
- Hot Code Reloading (HCR) モード対応時は各ソースファイルを個別のDLLとしてビルド

---

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

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

### 推奨読解順序

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

まず、外部コンパイラの設定を表すデータ構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | extccomp.nim | `compiler/extccomp.nim` | TInfoCC型（26-61行目）: コンパイラ情報を保持するタプル型の定義 |
| 1-2 | extccomp.nim | `compiler/extccomp.nim` | TInfoCCProp列挙型（27-37行目）: コンパイラの特性フラグ |
| 1-3 | extccomp.nim | `compiler/extccomp.nim` | TSystemCC（options.nim由来）: サポートするコンパイラの列挙 |

**読解のコツ**: TInfoCCタプルは各フィールドがコンパイラ固有の設定（コマンドテンプレート、オプション文字列等）を持つ。compileTmpl、linkTmplフィールドが特に重要で、$optionsや$objfileなどのプレースホルダを含む。

#### Step 2: コンパイラ定義を理解する

各コンパイラの設定がどのように定義されているかを確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | extccomp.nim | `compiler/extccomp.nim` | gcc()関数（75-99行目）: GCCの設定定義 |
| 2-2 | extccomp.nim | `compiler/extccomp.nim` | clang()関数（142-148行目）: Clangの設定定義（llvmGccを継承） |
| 2-3 | extccomp.nim | `compiler/extccomp.nim` | vcc()関数（150-177行目）: MSVCの設定定義 |
| 2-4 | extccomp.nim | `compiler/extccomp.nim` | CC配列（296行目以降）: 全コンパイラ設定の配列 |

**主要処理フロー**:
- **75-99行**: GCC設定 - Unix系OSの標準コンパイラ設定
- **150-177行**: VCC設定 - Windowsプラットフォーム特有のオプション

#### Step 3: コンパイルコマンド構築を理解する

Cファイルをコンパイルするコマンドがどのように構築されるかを把握。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | extccomp.nim | `compiler/extccomp.nim` | getCompileCFileCmd()関数: 個々のCファイルのコンパイルコマンド生成 |
| 3-2 | extccomp.nim | `compiler/extccomp.nim` | getCompileOptions()関数: コンパイルオプションの収集 |

#### Step 4: メインのコンパイル処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | extccomp.nim | `compiler/extccomp.nim` | callCCompiler()関数（971-1059行目）: メインのコンパイル・リンク処理 |
| 4-2 | extccomp.nim | `compiler/extccomp.nim` | execCmdsInParallel()関数（877-899行目）: 並列コンパイル実行 |
| 4-3 | extccomp.nim | `compiler/extccomp.nim` | getLinkCmd()関数: リンクコマンドの構築 |

**主要処理フロー**:
- **971-977行**: コンパイルのみモードの早期リターン
- **984-993行**: 各Cファイルのコンパイルコマンドを構築
- **996行**: 並列コンパイルの実行
- **997-1059行**: リンク処理とプラットフォーム固有処理

#### Step 5: プラットフォーム固有処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | extccomp.nim | `compiler/extccomp.nim` | createMacAppBundle()関数（813-864行目）: macOSアプリバンドル生成 |
| 5-2 | extccomp.nim | `compiler/extccomp.nim` | preventLinkCmdMaxCmdLen()関数（957-969行目）: コマンドライン長制限対策 |
| 5-3 | extccomp.nim | `compiler/extccomp.nim` | linkViaResponseFile()関数（901-928行目）: レスポンスファイル経由リンク |

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

```
callCCompiler()
    │
    ├─ getCompileCFileCmd()
    │      └─ getCompileOptions()
    │      └─ CC[cCompiler] 設定参照
    │
    ├─ execCmdsInParallel()
    │      └─ execProcesses() [並列実行]
    │      └─ execWithEcho() [逐次実行]
    │
    ├─ getLinkCmd()
    │      └─ getLinkOptions()
    │      └─ CC[cCompiler].linkTmpl
    │
    └─ preventLinkCmdMaxCmdLen()
           ├─ linkViaResponseFile()
           ├─ linkViaShellScript()
           └─ execLinkCmd()
```

### データフロー図

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

ConfigRef ─────────────▶ callCCompiler()
CfileList ─────────────▶     │
                             ▼
                      getCompileCFileCmd()
                             │
                             ▼
                      execCmdsInParallel() ─────────▶ *.o (オブジェクトファイル)
                             │
                             ▼
                      getLinkCmd()
                             │
                             ▼
                      execLinkCmd() ─────────────────▶ 実行可能ファイル
                             │
                             ▼
                      writeJsonBuildInstructions() ──▶ *.json (キャッシュ)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| extccomp.nim | `compiler/extccomp.nim` | ソース | 外部Cコンパイラ連携のメイン実装 |
| options.nim | `compiler/options.nim` | ソース | TSystemCC列挙型、ConfigRef定義 |
| platform.nim | `compiler/platform.nim` | ソース | プラットフォーム情報（OS、CPU） |
| msgs.nim | `compiler/msgs.nim` | ソース | エラーメッセージ・ヒント出力 |
| pathutils.nim | `compiler/pathutils.nim` | ソース | パス操作ユーティリティ |
| osproc | `lib/pure/osproc.nim` | 標準ライブラリ | プロセス起動・並列実行 |
