# バッチ設計書 48-tools.ps1

## 概要

本ドキュメントは、Windows向けの共通ビルドツール関数を提供するPowerShellスクリプト `eng/common/tools.ps1` の設計を記述します。このスクリプトは、.NET SDKの初期化、Visual Studio MSBuildの検出、Arcade SDKツールセットの管理など、Windowsビルドプロセスの中核となる機能を提供します。

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

このスクリプトは、他のビルドスクリプトからドットソースされて使用される共通関数ライブラリです。直接実行されるのではなく、関数と変数の定義を提供します。

**業務上の目的・背景**：.NET Runtimeプロジェクトは、Windows環境でも複雑なビルドプロセスを必要とします。Visual StudioのMSBuild検出、.NET SDKのインストール、xcopy MSBuildのダウンロード、Azure Pipelinesとの連携など、多くの共通機能が必要です。本スクリプトはtools.shのWindows版として、同等の機能をPowerShellで提供します。

**バッチの実行タイミング**：他のビルドスクリプト（build.ps1等）からドットソースされて使用されます。スクリプト読み込み時に初期化処理が実行されます。

**主要な処理内容**：
1. ビルド変数の初期化（ci、configuration、verbosity等）
2. .NET SDK/CLIの初期化とインストール
3. Visual Studio MSBuildの検出とxcopy MSBuildのダウンロード
4. Arcade SDKツールセットの初期化
5. MSBuild関数の提供（ロギング、エラー処理含む）
6. NuGetキャッシュパスの管理
7. Azure Pipelinesログ関数の提供
8. プロセス管理（終了時のクリーンアップ）

**前後の処理との関連**：ほぼ全てのWindowsビルドスクリプトがこのスクリプトをドットソースします。build.ps1、msbuild.ps1、sdk-task.ps1などが依存しています。

**影響範囲**：Windowsビルドシステム全体に影響します。このスクリプトの変更は全てのWindowsビルドプロセスに波及します。

## バッチ種別

共通ユーティリティ / ライブラリスクリプト

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | 随時（他スクリプトからドットソース時） |
| 実行時刻 | N/A |
| 実行曜日 | N/A |
| 実行日 | N/A |
| トリガー | 他スクリプトからのドットソース |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| Windows環境 | PowerShell 5.1以上 |
| global.json | リポジトリルートにglobal.jsonが存在すること |
| ネットワーク接続 | SDKダウンロード、vswhere取得時に必要 |

### 実行可否判定

global.jsonが存在しない場合、SDK初期化が失敗します。

## 入力仕様

### 入力パラメータ

このスクリプトは直接パラメータを受け取らず、呼び出し元スクリプトで設定された変数を使用します。

### PowerShell変数

| 変数名 | デフォルト値 | 説明 |
|-------|-------------|------|
| $ci | false | CIモードフラグ |
| $configuration | Debug | ビルド構成 |
| $binaryLog | ci時true | バイナリログ出力フラグ |
| $pipelinesLog | ci時true | Azure Pipelinesログ出力フラグ |
| $verbosity | minimal | MSBuild詳細度 |
| $nodeReuse | ci時false | MSBuildノード再利用フラグ |
| $warnAsError | true | 警告をエラーとして扱うフラグ |
| $useInstalledDotNetCli | true | システムインストール済みdotnetを使用するフラグ |
| $useGlobalNuGetCache | ci時false | グローバルNuGetキャッシュを使用するフラグ |
| $restore | true | パッケージリストアを実行するフラグ |
| $prepareMachine | false | マシン準備/クリーンアップを実行するフラグ |
| $msbuildEngine | null | MSBuildエンジン（vs/dotnet） |
| $excludePrereleaseVS | false | Visual Studioプレリリース版を除外 |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| global.json | JSON | SDKバージョン、Arcade SDKバージョン、VS要件等の定義 |
| dotnet-install.ps1 | PowerShell | .NET SDKインストールスクリプト（ダウンロード） |
| configure-toolset.ps1 | PowerShell | カスタムツールセット設定（オプション） |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| .dotnet/ | ディレクトリ | インストールされた.NET SDK |
| .tools/ | ディレクトリ | vswhere、xcopy MSBuild等のツール |
| artifacts/toolset/ | ディレクトリ | Arcade SDKツールセット |
| artifacts/log/ | ディレクトリ | ビルドログ |
| artifacts/tmp/ | ディレクトリ | 一時ファイル |

### 提供される関数

| 関数名 | 説明 |
|-------|------|
| InitializeDotNetCli | .NET CLI/SDKの初期化 |
| InstallDotNetSdk | .NET SDKのインストール |
| InstallDotNet | .NETランタイム/SDKのインストール |
| InitializeVisualStudioMSBuild | Visual Studio MSBuildの初期化 |
| InitializeBuildTool | ビルドツール（dotnet/VS MSBuild）の初期化 |
| InitializeToolset | Arcade SDKツールセットの初期化 |
| LocateVisualStudio | Visual Studioインストールの検出 |
| InitializeXCopyMSBuild | xcopy MSBuildのダウンロードと初期化 |
| GetNuGetPackageCachePath | NuGetパッケージキャッシュパスの取得 |
| MSBuild | MSBuild実行（Arcadeロガー付き） |
| MSBuild-Core | MSBuild実行（コア） |
| Get-Darc | DARC CLIの取得 |
| GetSdkTaskProject | SDKタスクプロジェクトパスの取得 |
| ExitWithExitCode | 終了処理 |
| Stop-Processes | ビルドプロセスの停止 |
| Exec-Process | プロセス実行（低レベル） |
| Exec-BlockVerbosely | スクリプトブロックの詳細実行 |

## 処理フロー

### 処理シーケンス

```
1. スクリプト読み込み時の初期化
   └─ 変数のデフォルト値設定
   └─ StrictMode有効化（Version 2.0）
   └─ TLS 1.2有効化
   └─ パス解決（RepoRoot、EngRoot、ArtifactsDir等）
   └─ ディレクトリ作成（ToolsetDir、TempDir、LogDir）
   └─ global.json読み込み
   └─ Azure Pipelines変数の設定
   └─ configure-toolset.ps1の読み込み（存在する場合）

2. InitializeDotNetCli呼び出し時
   └─ 環境変数の設定（DOTNET_NOLOGO、DOTNET_CLI_TELEMETRY_OPTOUT等）
   └─ システムインストール済みdotnetの検索
   └─ global.jsonからSDKバージョンを読み取り
   └─ 必要に応じてSDKをインストール
   └─ PATHにdotnetを追加
   └─ createSdkLocationFile指定時、sdk.txtを作成

3. InitializeVisualStudioMSBuild呼び出し時
   └─ 開発者コマンドプロンプトのmsbuildを検索
   └─ LocateVisualStudioでVS検出
   └─ 見つからない場合、xcopy MSBuildをダウンロード
   └─ msbuild.exeパスを返却

4. InitializeToolset呼び出し時
   └─ NuGetキャッシュパスの設定
   └─ Arcade SDKバージョンの読み取り
   └─ ツールセットの復元（未存在時）
   └─ ツールセットパスの返却

5. MSBuild呼び出し時
   └─ Arcadeロガーの設定
   └─ Enable-Nuget-EnhancedRetryの呼び出し
   └─ MSBuild-Coreの呼び出し

6. MSBuild-Core呼び出し時
   └─ CI時の検証（バイナリログ、ノード再利用）
   └─ ビルドツール（dotnet/msbuild）の実行
   └─ エラー処理と終了コード管理
```

### フローチャート

```mermaid
flowchart TD
    A[スクリプトドットソース] --> B[変数初期化]
    B --> C[global.json読み込み]
    C --> D[ディレクトリ作成]
    D --> E[configure-toolset.ps1読み込み]
    E --> F[初期化完了]

    G[InitializeDotNetCli] --> H{SDK存在?}
    H -->|Yes| I[PATHに追加]
    H -->|No| J[dotnet-install.ps1実行]
    J --> I

    K[InitializeVisualStudioMSBuild] --> L{開発者プロンプト?}
    L -->|Yes| M[msbuildパス返却]
    L -->|No| N[LocateVisualStudio]
    N --> O{VS発見?}
    O -->|Yes| M
    O -->|No| P[xcopy MSBuildダウンロード]
    P --> M

    Q[MSBuild] --> R[Enable-Nuget-EnhancedRetry]
    R --> S[Arcadeロガー設定]
    S --> T[MSBuild-Core呼び出し]
```

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

本スクリプトはデータベース操作を行いません。

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

| 処理 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| N/A | N/A | N/A | データベース操作なし |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| exit 1 | SDK初期化失敗 | global.jsonにdotnetキーがない | global.jsonを確認 |
| exit 1 | SDKインストール失敗 | ネットワークエラー、ダウンロード失敗 | ネットワークを確認、リトライ |
| exit 1 | VS検出失敗 | 必要なVSコンポーネントがない | VSをインストール、またはxcopy MSBuildを使用 |
| throw | xcopy MSBuild失敗 | パッケージが見つからない | dotnet-engフィードを確認 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | Retry関数で最大5回 |
| リトライ間隔 | 指数バックオフ（2^n - 1秒） |
| リトライ対象エラー | dotnet-install.ps1、HTTPダウンロードの失敗 |

### 障害時対応

1. ネットワーク接続を確認
2. global.jsonの内容を確認
3. Visual Studioのインストール状況を確認
4. NuGetパッケージソースの設定を確認
5. 一時ディレクトリをクリアして再実行

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

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

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | N/A（ライブラリ） |
| 目標処理時間 | SDK初期化: 初回30秒〜数分、2回目以降1秒以内 |
| メモリ使用量上限 | PowerShell標準使用量内 |

## 排他制御

SDKインストール時、同一ディレクトリへの同時インストールは避けてください。sdk.txt作成時は並行アクセス対応（ランダムファイル名使用）があります。

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| 情報ログ | SDK初期化時 | インストール試行メッセージ |
| 情報ログ | VS検出時 | vswhere実行結果 |
| 情報ログ | MSBuild実行時 | ビルドコマンド情報 |
| エラーログ | 失敗時 | Write-PipelineTelemetryErrorによるCI向けエラー |
| バイナリログ | MSBuild実行時 | artifacts/log/{config}/*.binlog |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| SDK初期化時間 | 5分超過 | CI通知 |
| MSBuild失敗 | 1件以上 | CI通知（Write-PipelineSetResult経由） |

## 備考

- dotnet-install.ps1は30日経過で自動再ダウンロード
- CI環境ではテレメトリ無効化（DOTNET_CLI_TELEMETRY_OPTOUT=1）
- CI環境ではノード再利用無効化（決定論的ビルドのため）
- CI環境ではバイナリログ必須（明示的なオプトアウト除く）
- Visual Studio最低要件: 17.7（$vsMinVersionReqdStr）
- xcopy MSBuildデフォルトバージョン: 18.0.0
- vswhereバージョン: 3.1.7（global.jsonで上書き可能）
- NuGet Enhanced Retry対応（NUGET_ENABLE_ENHANCED_HTTP_RETRY等）
- msbuildEngine変数でビルドエンジン（vs/dotnet）を明示的に選択可能
- global.jsonのtools.vsでVisual Studio要件を指定可能
- $processesToStopOnExitでクリーンアップ対象プロセスを指定（デフォルト: msbuild, dotnet, vbcscompiler）
