# 機能設計書 66-llvm-lipo

## 概要

本ドキュメントは、LLVM llvm-lipo ツールの機能設計について記載する。llvm-lipoは、macOS用のユニバーサルバイナリ（ファットバイナリ）の作成・分割・情報表示を行うツールである。

### 本機能の処理概要

llvm-lipoは、Apple社のlipoツールと互換性のあるユニバーサルバイナリ操作ツールである。複数のアーキテクチャ用バイナリを1つのユニバーサルバイナリに結合したり、ユニバーサルバイナリから特定アーキテクチャを抽出したりできる。

**業務上の目的・背景**：macOSおよびiOSの開発において、複数のアーキテクチャ（x86_64、arm64等）をサポートするアプリケーションを配布するためにユニバーサルバイナリが使用される。llvm-lipoは、これらのユニバーサルバイナリを操作するためのクロスプラットフォーム対応ツールとして提供される。

**機能の利用シーン**：
- 複数アーキテクチャのバイナリを1つのユニバーサルバイナリに結合
- ユニバーサルバイナリから特定アーキテクチャのバイナリを抽出
- ユニバーサルバイナリに含まれるアーキテクチャの確認
- 特定アーキテクチャがサポートされているかの検証
- アーキテクチャスライスの置換

**主要な処理内容**：
1. -create: 複数の入力ファイルからユニバーサルバイナリを作成
2. -thin: ユニバーサルバイナリから指定アーキテクチャを抽出
3. -extract: 指定アーキテクチャのみを含むユニバーサルバイナリを作成
4. -archs: 含まれるアーキテクチャ一覧を表示
5. -info: ファイル情報を表示
6. -verify_arch: 指定アーキテクチャが含まれるか検証
7. -replace: 特定アーキテクチャのスライスを置換

**関連システム・外部連携**：LLVM Object ライブラリ（MachOUniversalBinary、MachOUniversalWriter）

**権限による制御**：特になし（ファイルシステムへのアクセス権限のみ必要）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | CLIツール | 主機能 | コマンドラインインターフェースによる操作 |

## 機能種別

バイナリ操作 / ファイル結合・分割

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| 入力ファイル | string | Yes | Mach-O、Archive、またはユニバーサルバイナリ | ファイルが存在すること |
| -create | flag | No | ユニバーサルバイナリ作成 | - |
| -thin | arch | No | 指定アーキテクチャを抽出 | 有効なアーキテクチャ名 |
| -extract | arch | No | 指定アーキテクチャのみ含むユニバーサルバイナリ作成 | 有効なアーキテクチャ名 |
| -replace | arch file | No | 指定アーキテクチャを別ファイルで置換 | 有効なアーキテクチャ名 |
| -archs | flag | No | アーキテクチャ一覧表示 | - |
| -info | flag | No | ファイル情報表示 | - |
| -verify_arch | arch... | No | 指定アーキテクチャの存在を検証 | - |
| -output | string | No | 出力ファイルパス | - |
| -arch | arch file | No | アーキテクチャを指定して入力ファイルを追加 | 有効なアーキテクチャ名 |
| -segalign | arch value | No | セグメントアラインメントを指定 | 2の累乗 |
| -fat64 | flag | No | Fat64ヘッダーを使用 | - |

### 入力データソース

- ファイルシステム上のMach-Oオブジェクトファイル、Archive、ユニバーサルバイナリ

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ユニバーサルバイナリ | バイナリ | 結合されたユニバーサルバイナリ |
| シンバイナリ | バイナリ | 抽出された単一アーキテクチャバイナリ |
| アーキテクチャ情報 | テキスト | 含まれるアーキテクチャ一覧 |

### 出力先

- 指定された出力ファイル（-output）
- 標準出力（情報表示系コマンド）

## 処理フロー

### 処理シーケンス

```
1. コマンドライン引数解析
   └─ parseLipoOptions()でConfigを構築

2. 入力ファイルの読み込み
   └─ readInputBinaries()でバイナリをロード

3. アクションに応じた処理
   ├─ VerifyArch: アーキテクチャ検証
   ├─ PrintArchs: アーキテクチャ一覧表示
   ├─ PrintInfo: ファイル情報表示
   ├─ ThinArch: 指定アーキテクチャ抽出
   ├─ ExtractArch: ユニバーサルバイナリとして抽出
   ├─ CreateUniversal: ユニバーサルバイナリ作成
   └─ ReplaceArch: アーキテクチャ置換

4. 結果の出力
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[引数解析]
    B --> C[入力ファイル読み込み]
    C --> D{アクション?}
    D -->|verify_arch| E[verifyArch]
    D -->|archs| F[printArchs]
    D -->|info| G[printInfo]
    D -->|thin| H[thinSlice]
    D -->|extract| I[extractSlice]
    D -->|create| J[createUniversalBinary]
    D -->|replace| K[replaceSlices]
    E --> L[終了]
    F --> L
    G --> L
    H --> L
    I --> L
    J --> L
    K --> L
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-66-1 | 単一入力制限 | thin/extract/verify_archは単一入力のみ | 該当アクション時 |
| BR-66-2 | アーキテクチャ重複禁止 | 同一アーキテクチャは1つのユニバーサルバイナリに1つのみ | create/replace時 |
| BR-66-3 | アラインメント制約 | segalignは2の累乗かつ2^15以下 | -segalign指定時 |
| BR-66-4 | ファット入力禁止 | thin/replace時の入力はファットファイル不可 | thin/replace時 |

### 計算ロジック

特になし

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

該当なし（データベースを使用しない）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | アーキテクチャ不正 | 無効なアーキテクチャ名を指定 | 有効なアーキテクチャ一覧を表示し終了 |
| - | 入力ファイル不足 | 入力ファイルが指定されていない | エラーメッセージを表示し終了 |
| - | 出力ファイル未指定 | create等で出力ファイルが未指定 | エラーメッセージを表示し終了 |
| - | アーキテクチャ重複 | 同一アーキテクチャが複数存在 | エラーメッセージを表示し終了 |
| - | アーキテクチャ不存在 | 指定アーキテクチャが入力に存在しない | エラーメッセージを表示し終了 |

### リトライ仕様

なし

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

該当なし

## パフォーマンス要件

特に定義なし

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

- 入力ファイルへの読み取りアクセス権限が必要
- 出力ファイルへの書き込みアクセス権限が必要

## 備考

- Apple lipoツールとの互換性を目指している
- Fat64ヘッダーは4GB以上のスライスを含む場合に必要

---

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

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

### 推奨読解順序

#### Step 1: データ構造とオプション定義を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | LipoOpts.td | `llvm/tools/llvm-lipo/LipoOpts.td` | コマンドラインオプション定義 |
| 1-2 | llvm-lipo.cpp | `llvm/tools/llvm-lipo/llvm-lipo.cpp` | Config構造体（111-120行目） |

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | llvm-lipo.cpp | `llvm/tools/llvm-lipo/llvm-lipo.cpp` | llvm_lipo_main関数（732-770行目） |

**主要処理フロー**:
1. **733-735行目**: ターゲット初期化
2. **737行目**: parseLipoOptions()で引数解析
3. **739-740行目**: readInputBinaries()で入力読み込み
4. **742-768行目**: アクションに応じた処理分岐

#### Step 3: 各アクション処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | llvm-lipo.cpp | `llvm/tools/llvm-lipo/llvm-lipo.cpp` | createUniversalBinary関数（608-627行目） |
| 3-2 | llvm-lipo.cpp | `llvm/tools/llvm-lipo/llvm-lipo.cpp` | thinSlice関数（471-520行目） |

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

```
llvm_lipo_main()
    │
    ├─ parseLipoOptions()
    │      └─ Configの構築
    │
    ├─ readInputBinaries()
    │      └─ createBinary()で各入力をロード
    │
    └─ アクション処理
           ├─ verifyArch()
           ├─ printArchs()
           ├─ printInfo()
           ├─ thinSlice()
           ├─ extractSlice()
           ├─ createUniversalBinary()
           │      ├─ buildSlices()
           │      └─ writeUniversalBinary()
           └─ replaceSlices()
```

### データフロー図

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

Mach-Oファイル1 ──┐
                  ├──▶ buildSlices() ──▶ Slice配列
Mach-Oファイル2 ──┘           │
                              ▼
                    writeUniversalBinary()
                              │
                              ▼
                    ユニバーサルバイナリ ─────────▶ 出力ファイル
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| llvm-lipo.cpp | `llvm/tools/llvm-lipo/llvm-lipo.cpp` | ソース | メインプログラム |
| LipoOpts.td | `llvm/tools/llvm-lipo/LipoOpts.td` | 定義 | コマンドラインオプション定義 |
| CMakeLists.txt | `llvm/tools/llvm-lipo/CMakeLists.txt` | ビルド | ビルド設定 |
