# バッチ設計書 22-native-cli

## 概要

本ドキュメントは、clojure-lspプロジェクトにおけるGraalVMネイティブCLI実行ファイル生成バッチ（native-cli）の設計を記載したものである。

### 本バッチの処理概要

本バッチは、GraalVMのnative-imageツールを使用して、clojure-lspをネイティブ実行ファイル（clojure-lsp または clojure-lsp.exe）としてコンパイルする処理である。JVMを必要としない単体の実行可能バイナリを生成し、起動時間の大幅な短縮とメモリ使用量の削減を実現する。

**業務上の目的・背景**：clojure-lspはLSP（Language Server Protocol）サーバーとして動作するため、エディタ起動時に迅速に立ち上がる必要がある。JVMベースの起動は数秒から十数秒かかることがあり、ユーザーエクスペリエンスを損なう。ネイティブイメージ化により起動時間を数十ミリ秒に短縮し、また実行環境にJVMのインストールを不要にすることで、より広いユーザー層への配布を可能にする。

**バッチの実行タイミング**：リリースビルド時に手動またはCI/CDパイプラインで実行される。開発中は必要に応じて実行されるが、ビルド時間が長いため頻繁には実行されない。

**主要な処理内容**：
1. prod-jar関数による本番用スタンドアロンJARの生成（既存JARがない場合）
2. GraalVM native-imageコマンドの実行
3. PGO（Profile-Guided Optimization）プロファイルの適用（Windows以外）
4. 静的リンクオプションの適用（環境変数による制御）
5. 生成されたネイティブバイナリをプロジェクトルートへ移動

**前後の処理との関連**：prod-jarバッチで生成されるJARファイルを入力として使用する。生成されたネイティブバイナリはintegration-testで使用され、release-artifactでGitHubリリースにアップロードされる。

**影響範囲**：プロジェクトルートディレクトリにclojure-lsp（Unix）またはclojure-lsp.exe（Windows）ファイルが生成される。既存ファイルは上書きされる。

## バッチ種別

ビルド処理 / ネイティブイメージ生成

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | 随時 |
| 実行時刻 | 指定なし |
| 実行曜日 | 指定なし |
| 実行日 | 指定なし |
| トリガー | 手動（bb native-cli）またはCI/CD |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| GRAALVM_HOME | GraalVMのインストールディレクトリを指す環境変数が設定されていること |
| native-image | GraalVMにnative-imageコンポーネントがインストールされていること |
| JDK | Java Development Kit がインストールされていること（JAR生成用） |
| Babashka | bb コマンドが利用可能であること |
| メモリ | 最低8GBのRAMが利用可能であること |

### 実行可否判定

GRAALVM_HOME環境変数が設定されていない場合、"Set GRAALVM_HOME env" メッセージを出力して処理を中断する。

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| GRAALVM_HOME | 環境変数 | Yes | なし | GraalVMインストールディレクトリ |
| CLOJURE_LSP_JAR | 環境変数 | No | なし | 事前ビルド済みJARのパス |
| CLOJURE_LSP_XMX | 環境変数 | No | -J-Xmx8g | ビルド時の最大ヒープサイズ |
| CLOJURE_LSP_STATIC | 環境変数 | No | なし | "true"で静的リンクを有効化 |
| CLOJURE_LSP_MUSL | 環境変数 | No | なし | "true"でmusl libcを使用 |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| cli/target/clojure-lsp-standalone.jar | JAR | ネイティブイメージ化対象のuberjar |
| cli/graalvm/default.iprof | iprof | PGOプロファイルデータ（Windows以外で使用） |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| clojure-lsp | ネイティブ実行ファイル | Unix用ネイティブバイナリ |
| clojure-lsp.exe | ネイティブ実行ファイル | Windows用ネイティブバイナリ |

### 出力ファイル仕様

| 項目 | 内容 |
|-----|------|
| ファイル名 | clojure-lsp（Unix）/ clojure-lsp.exe（Windows） |
| 出力先 | プロジェクトルートディレクトリ |
| 文字コード | N/A（バイナリ） |
| 区切り文字 | N/A |

## 処理フロー

### 処理シーケンス

```
1. GRAALVM_HOME環境変数チェック
   └─ 未設定の場合はエラーメッセージを出力して終了

2. 入力JAR決定
   └─ CLOJURE_LSP_JAR環境変数が設定されていればそれを使用
   └─ 未設定の場合はprod-jar関数でJARを生成

3. native-imageコマンド構築
   └─ 基本オプション設定
   └─ PGOプロファイル適用（Windows以外かつpgo-instrumentでない場合）
   └─ 静的リンクオプション適用（環境変数による）
   └─ アーキテクチャ固有オプション設定（Linux aarch64の場合）

4. native-imageコマンド実行
   └─ GraalVMのnative-imageツールを呼び出し
   └─ ビルド完了まで待機

5. 終了コード確認
   └─ 0以外の場合はSystem/exitで同じコードで終了

6. ファイル移動
   └─ cli/clojure-lsp[.exe]をプロジェクトルートに移動
```

### フローチャート

```mermaid
flowchart TD
    A[バッチ開始] --> B{GRAALVM_HOME設定?}
    B -->|No| C[エラーメッセージ出力]
    C --> D[処理終了]
    B -->|Yes| E{CLOJURE_LSP_JAR設定?}
    E -->|No| F[prod-jarでJAR生成]
    E -->|Yes| G[指定JARを使用]
    F --> H[native-imageコマンド構築]
    G --> H
    H --> I[native-image実行]
    I --> J{終了コード = 0?}
    J -->|No| K[同じ終了コードで終了]
    J -->|Yes| L[バイナリをルートに移動]
    L --> M[バッチ終了]
```

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

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

本バッチはデータベースを使用しない。

| 処理 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| N/A | N/A | N/A | N/A |

### テーブル別操作詳細

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 環境変数未設定 | GRAALVM_HOMEが未設定 | GraalVMをインストールしGRAALVM_HOMEを設定 |
| 1+ | native-imageエラー | コンパイルエラー、リンクエラー | エラーメッセージを確認し対処 |
| - | メモリ不足 | ビルド時のヒープ不足 | CLOJURE_LSP_XMXで増加 |
| - | リフレクション設定不足 | native-image設定の不備 | graalvm設定ファイルを更新 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0（自動リトライなし） |
| リトライ間隔 | N/A |
| リトライ対象エラー | N/A |

### 障害時対応

1. エラーログを確認し、失敗原因を特定
2. メモリ不足の場合は CLOJURE_LSP_XMX=-J-Xmx16g 等で増加
3. リフレクション関連エラーの場合は tracing config を再実行
4. GraalVMのバージョンを確認し、必要に応じてアップデート

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

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | N/A（ファイルシステム操作のみ） |
| コミットタイミング | N/A |
| ロールバック条件 | N/A |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | 1回の実行で1つのネイティブバイナリを生成 |
| 目標処理時間 | 10〜30分（環境依存） |
| メモリ使用量上限 | 8GB（デフォルト、CLOJURE_LSP_XMXで調整可能） |

## 排他制御

同一プロジェクトディレクトリでの同時実行は想定されていない。複数のビルドプロセスが同時に実行された場合、ファイル競合が発生する可能性がある。

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| 開始ログ | バッチ開始時 | "Building native image..." |
| 進捗ログ | native-image実行中 | GraalVMからの詳細出力（--verbose） |
| 終了ログ | バッチ終了時 | 正常終了時は出力なし |
| エラーログ | 環境変数未設定時 | "Set GRAALVM_HOME env" |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| 処理時間 | 60分 | CI/CDシステム |
| 終了コード | 0以外 | CI/CDシステム |

## 備考

- native-imageオプション詳細：
  - `-H:+ReportExceptionStackTraces`: 例外時のスタックトレースを有効化
  - `--verbose`: 詳細なビルドログを出力
  - `--no-fallback`: JVMフォールバックを無効化（純粋なネイティブイメージ）
  - `--native-image-info`: ネイティブイメージ情報を出力
  - `--features=clj_easy.graal_build_time.InitClojureClasses`: Clojureクラスの初期化を最適化
  - `-march=compatibility`: CPU互換性モード（Windows以外）
  - `-O1`: 最適化レベル1
  - `--pgo=graalvm/default.iprof`: PGOプロファイルを適用（Windows以外）
- 静的リンクオプション（CLOJURE_LSP_STATIC=true時）：
  - `--static`: 静的リンクを有効化
  - `-H:+StaticExecutableWithDynamicLibC`: 動的glibc使用の静的実行ファイル
  - `--libc=musl` + `-H:CCompilerOption=-Wl,-z,stack-size=2097152`: musl libc使用時のオプション
