mcpField
C
Cross-Platform Build Expert

Cross-Platform Build Expert

github.com/martinholovsky開発48209 回インストール47 週間前に更新
リポジトリ

Cross-Platform Build Expert について

Cross-Platform Build Expert は、Windows、macOS、Linux 向けに Tauri デスクトップアプリを構築する開発者向けのスキルです。プラットフォーム設定、署名と配布、CI ビルド、最適化を扱い、セキュリティとテストにも重点を置きます。

主な機能

  1. 01Tauri のマルチプラットフォームビルド設定
  2. 02Windows、macOS、Linux のターゲット
  3. 03コード署名と公証のガイダンス
  4. 04CI ビルドマトリクスのパターン
  5. 05ビルドサイズと性能の最適化

活用シーン

  1. 01Tauri のマルチプラットフォームビルド設定
  2. 02署名付きアプリリリースの準備
  3. 03各プラットフォーム向け CI の設定
  4. 04ビルド時間やバンドルサイズの削減

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/martinholovsky/claude-skills-generator --skill cross-platform-build-expert

インストール後、Claude Code で/cross-platform-build-expertを入力して読み込まれたか確認します。

同梱ファイルreferences/security-examples.mdreferences/advanced-patterns.md

詳細

クロスプラットフォームビルドのエキスパート

0. 必読の手順

重要:プラットフォーム固有のビルド設定を実装する前に、必ず該当するリファレンスファイルを読んでください。

リファレンスファイルを読む条件

次の場合は references/advanced-patterns.md を読んでください:

  • プラットフォーム固有のビルドマトリックスを設定するとき
  • 条件付きコンパイルを設定するとき
  • プラットフォーム固有の機能を実装するとき
  • ビルドサイズとパフォーマンスを最適化するとき

次の場合は references/security-examples.md を読んでください:

  • コード署名証明書を設定するとき
  • macOS の公証を設定するとき
  • セキュアなビルド環境を実装するとき
  • 署名資格情報を管理するとき

1. 概要

リスクレベル:中

理由:クロスプラットフォームビルドでは、コード署名資格情報、プラットフォーム固有のセキュリティ設定、さまざまなアプリストアを通じた配布が関係します。不適切な署名は、セキュリティ警告、インストールの失敗、または申請の却下につながります。また、ビルド設定から機密情報が漏えいしたり、プラットフォーム固有の脆弱性が生じたりする可能性もあります。

以下を専門とする、クロスプラットフォームのデスクトップアプリビルドのエキスパートです:

  • Windows、macOS、Linux のプラットフォーム固有の設定
  • コード署名と公証の手順
  • 各プラットフォームの配布要件
  • サイズとパフォーマンスを考慮したビルドの最適化
  • マルチプラットフォームビルドのためのTauri の設定
主なユースケース
  • すべてのデスクトッププラットフォーム向けに Tauri アプリケーションをビルドする
  • 信頼できる配布のためにコード署名を設定する
  • マルチプラットフォームビルド用に CI/CD を設定する
  • アプリケーションバンドルを最適化する
  • プラットフォームの配布要件を満たす

2. 基本原則

  1. まず TDD - 実装前にビルド設定のテストを書く
  2. パフォーマンスを意識する - ビルド時間、バンドルサイズ、起動時間を最適化する
  3. すべての対象プラットフォームでテストする - クロスプラットフォームの互換性を決めつけない
  4. プラットフォーム抽象化を利用する - プラットフォーム間の違いには Rust std と Tauri API を使用する
  5. パスの違いに対処する - スラッシュとバックスラッシュ、大文字と小文字の区別
  6. プラットフォームの慣例を尊重する - ファイルの配置場所、UI ガイドライン
  7. すべてのリリースに署名する - ユーザーは署名済みアプリケーションを信頼します
  8. 署名資格情報を保護する - 証明書を決してコミットしない
  9. 署名を検証する - 配布前に確認する
  10. タイムスタンプを使用する - 証明書の有効期限が切れた後も署名が有効であるようにする

3. 技術的な基礎

3.1 プラットフォームのビルドターゲット
プラットフォームRust ターゲットTauri バンドル
Windows x64x86_64-pc-windows-msvcmsi, nsis
Windows ARMaarch64-pc-windows-msvcmsi, nsis
macOS Intelx86_64-apple-darwindmg, app
macOS Apple Siliconaarch64-apple-darwindmg, app
Linux x64x86_64-unknown-linux-gnudeb, appimage
Linux ARMaarch64-unknown-linux-gnudeb, appimage
3.2 ビルドの依存関係

Windows:

  • Visual Studio Build Tools
  • Windows SDK
  • WebView2 Runtime(Tauri がバンドル)

macOS:

  • Xcode Command Line Tools
  • Apple Developer Certificate
  • 公証用のアプリ固有パスワード

Linux:

  • GTK3 開発ライブラリ
  • WebKitGTK
  • AppIndicator(システムトレイ用)

4. 実装パターン

4.1 Tauri の設定
// tauri.conf.json
{
  "build": {
    "beforeBuildCommand": "npm run build",
    "beforeDevCommand": "npm run dev",
    "devPath": "http://localhost:3000",
    "distDir": "../dist"
  },
  "package": {
    "productName": "MyApp",
    "version": "1.0.0"
  },
  "tauri": {
    "bundle": {
      "active": true,
      "identifier": "com.company.myapp",
      "icon": [
        "icons/32x32.png",
        "icons/128x128.png",
        "icons/[email protected]",
        "icons/icon.icns",
        "icons/icon.ico"
      ],
      "targets": "all",
      "windows": {
        "certificateThumbprint": null,
        "digestAlgorithm": "sha256",
        "timestampUrl": "http://timestamp.digicert.com",
        "wix": {
          "language": "en-US"
        }
      },
      "macOS": {
        "entitlements": "./entitlements.plist",
        "exceptionDomain": "",
        "frameworks": [],
        "minimumSystemVersion": "10.15",
        "signingIdentity": null
      },
      "linux": {
        "deb": {
          "depends": ["libgtk-3-0", "libwebkit2gtk-4.0-37"]
        },
        "appimage": {
          "bundleMediaFramework": true
        }
      }
    },
    "security": {
      "csp": "default-src 'self'; script-src 'self'"
    }
  }
}
4.2 プラットフォーム固有のコード
// src-tauri/src/main.rs

#[cfg(target_os = "windows")]
fn platform_init() {
    // Windows-specific initialization
    use windows::Win32::System::Console::SetConsoleOutputCP;
    unsafe { SetConsoleOutputCP(65001); }  // UTF-8 support
}

#[cfg(target_os = "macos")]
fn platform_init() {
    // macOS-specific initialization
    // Handle Dock, menu bar, etc.
}

#[cfg(target_os = "linux")]
fn platform_init() {
    // Linux-specific initialization
    // Handle DBus, system tray, etc.
}

fn main() {
    platform_init();

    tauri::Builder::default()
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}
4.3 GitHub Actions のビルドマトリックス
name: Build

on:
  push:
    tags:
      - 'v*'

jobs:
  build:
    strategy:
      fail-fast: false
      matrix:
        include:
          - platform: windows-latest
            args: ''
            target: x86_64-pc-windows-msvc
          - platform: macos-latest
            args: '--target x86_64-apple-darwin'
            target: x86_64-apple-darwin
          - platform: macos-latest
            args: '--target aarch64-apple-darwin'
            target: aarch64-apple-darwin
          - platform: ubuntu-22.04
            args: ''
            target: x86_64-unknown-linux-gnu

    runs-on: ${{ matrix.platform }}

    steps:
      - uses: actions/checkout@v4

      - name: Setup Rust
        uses: dtolnay/rust-toolchain@stable
        with:
          targets: ${{ matrix.target }}

      - name: Install Linux Dependencies
        if: matrix.platform == 'ubuntu-22.04'
        run: |
          sudo apt-get update
          sudo apt-get install -y \
            libgtk-3-dev \
            libwebkit2gtk-4.0-dev \
            libappindicator3-dev \
            librsvg2-dev \
            patchelf

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'

      - name: Install Dependencies
        run: npm ci

      - name: Build
        run: npm run tauri build -- ${{ matrix.args }}

      - name: Upload Artifacts
        uses: actions/upload-artifact@v3
        with:
          name: ${{ matrix.target }}
          path: |
            src-tauri/target/${{ matrix.target }}/release/bundle/
4.4 コード署名の設定

Windows(tauri.conf.json):

{
  "tauri": {
    "bundle": {
      "windows": {
        "certificateThumbprint": "YOUR_CERT_THUMBPRINT",
        "digestAlgorithm": "sha256",
        "timestampUrl": "http://timestamp.digicert.com"
      }
    }
  }
}

macOS(tauri.conf.json):

{
  "tauri": {
    "bundle": {
      "macOS": {
        "signingIdentity": "Developer ID Application: Company Name (TEAM_ID)",
        "entitlements": "./entitlements.plist"
      }
    }
  }
}

macOS エンタイトルメント(entitlements.plist):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>com.apple.security.cs.allow-jit</key>
    <true/>
    <key>com.apple.security.cs.allow-unsigned-executable-memory</key>
    <true/>
    <key>com.apple.security.cs.disable-library-validation</key>
    <true/>
</dict>
</plist>

5. セキュリティ基準

5.1 コード署名の要件
プラットフォーム証明書の種類用途
WindowsEV Code SigningSmartScreen の信頼を即座に獲得
WindowsStandard Code Signing評判の獲得後に信頼を得る
macOSDeveloper ID ApplicationApp Store 外での配布
macOSDeveloper ID Installer署名済み PKG インストーラー
LinuxGPG Keyパッケージ署名
5.2 署名のベストプラクティス
# Windows: Verify signature
signtool verify /pa /v MyApp.exe

# macOS: Verify signature
codesign --verify --deep --strict MyApp.app
spctl --assess --type execute MyApp.app

# macOS: Check notarization
xcrun stapler validate MyApp.app
5.3 ビルドのセキュリティ
  • 証明書はリポジトリではなく、CI/CD のシークレットに保存する
  • 署名はタグ付きリリースの場合にのみ行う
  • ビルド環境はクリーンで、一時的なものにする
  • 依存関係のバージョンを固定し、検証する
  • 署名後に成果物のチェックサムを計算する

6. 実装ワークフロー(TDD)

ステップ 1:まず失敗するテストを書く
// tests/build_config_test.rs
#[cfg(test)]
mod tests {
    use std::path::Path;
    use std::process::Command;

    #[test]
    fn test_tauri_config_exists() {
        assert!(Path::new("src-tauri/tauri.conf.json").exists());
    }

    #[test]
    fn test_icons_all_platforms() {
        let required_icons = vec![
            "icons/icon.ico",      // Windows
            "icons/icon.icns",     // macOS
            "icons/icon.png",      // Linux
        ];
        for icon in required_icons {
            assert!(Path::new(&format!("src-tauri/{}", icon)).exists(),
                "Missing icon: {}", icon);
        }
    }

    #[test]
    fn test_bundle_identifier_format() {
        let config: serde_json::Value = serde_json::from_str(
            &std::fs::read_to_string("src-tauri/tauri.conf.json").unwrap()
        ).unwrap();
        let identifier = config["tauri"]["bundle"]["identifier"].as_str().unwrap();
        assert!(identifier.contains('.'), "Bundle ID must use reverse domain");
    }

    #[test]
    fn test_frontend_builds_successfully() {
        let output = Command::new("npm")
            .args(["run", "build"])
            .output()
            .expect("Failed to run build");
        assert!(output.status.success(), "Frontend build failed");
    }
}
ステップ 2:テストに合格するための最小限の実装を行う
// Create minimal tauri.conf.json
{
  "package": { "productName": "MyApp", "version": "0.1.0" },
  "tauri": {
    "bundle": {
      "identifier": "com.company.myapp",
      "icon": ["icons/icon.ico", "icons/icon.icns", "icons/icon.png"]
    }
  }
}
ステップ 3:リファクタリングして拡張する

設定の拡張に合わせて、プラットフォーム固有のテストを追加します。

#[test]
fn test_windows_signing_config() {
    let config: serde_json::Value = serde_json::from_str(
        &std::fs::read_to_string("src-tauri/tauri.conf.json").unwrap()
    ).unwrap();
    let windows = &config["tauri"]["bundle"]["windows"];
    assert!(windows["timestampUrl"].as_str().is_some());
}

#[test]
fn test_macos_minimum_version() {
    let config: serde_json::Value = serde_json::from_str(
        &std::fs::read_to_string("src-tauri/tauri.conf.json").unwrap()
    ).unwrap();
    let min_ver = config["tauri"]["bundle"]["macOS"]["minimumSystemVersion"]
        .as_str().unwrap();
    assert!(min_ver >= "10.15", "Must support macOS 10.15+");
}
ステップ 4:完全な検証を実行する
# Run all build tests
cargo test --manifest-path src-tauri/Cargo.toml

# Verify builds on all platforms (CI)
npm run tauri build -- --target x86_64-pc-windows-msvc
npm run tauri build -- --target x86_64-apple-darwin
npm run tauri build -- --target x86_64-unknown-linux-gnu

# Verify signatures
signtool verify /pa target/release/bundle/msi/*.msi
codesign --verify --deep target/release/bundle/macos/*.app

7. パフォーマンスのパターン

7.1 インクリメンタルビルド
# Cargo.toml - Enable incremental compilation
[profile.dev]
incremental = true

[profile.release]
incremental = true
lto = "thin"  # Faster than "fat" LTO

推奨:インクリメンタルビルドでは、コンパイル済みの成果物を再利用します

# First build: 2-3 minutes
cargo build --release
# Subsequent builds: 10-30 seconds
cargo build --release

非推奨:毎回クリーンビルドする

cargo clean && cargo build --release  # Always slow
7.2 ビルドキャッシュ

推奨:CI で Rust の依存関係をキャッシュする

- name: Cache Cargo
  uses: actions/cache@v4
  with:
    path: |
      ~/.cargo/registry
      ~/.cargo/git
      target
    key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}

非推奨:キャッシュを使わず、ビルドのたびに依存関係をダウンロードする

- name: Build
  run: cargo build --release  # Downloads everything
7.3 並列コンパイル

推奨:並列ジョブを最大限に活用する

# .cargo/config.toml
[build]
jobs = 8  # Match CPU cores

[target.x86_64-unknown-linux-gnu]
rustflags = ["-C", "link-arg=-fuse-ld=mold"]  # Fast linker

非推奨:シングルスレッドでコンパイルする

cargo build -j 1  # Extremely slow
7.4 ツリーシェイキングとデッドコードの除去

推奨:LTO を有効にしてバイナリサイズを縮小する

[profile.release]
lto = true
codegen-units = 1
panic = "abort"
strip = true

非推奨:リリースビルドにデバッグシンボルを含める

[profile.release]
debug = true  # Bloats binary size
7.5 コード分割(フロントエンド)

推奨:ルートを遅延読み込みする

// nuxt.config.ts
export default defineNuxtConfig({
  experimental: {
    treeshakeClientOnly: true
  },
  vite: {
    build: {
      rollupOptions: {
        output: {
          manualChunks: {
            'vendor': ['vue', 'pinia'],
            'three': ['three', '@tresjs/core']
          }
        }
      }
    }
  }
})

非推奨:すべてをまとめてバンドルする

// Single massive bundle
import * as everything from './all-modules'
7.6 ビルドサイズの最適化

推奨:バンドルを分析して最適化する

# Analyze Rust binary
cargo bloat --release --crates

# Analyze frontend bundle
npx nuxi analyze

非推奨:バンドルサイズを無視する

npm run build  # Never check what's included

8. よくある間違いとアンチパターン

8.1 パスのハードコード
// WRONG: Windows-style path
let config = std::fs::read("C:\\Users\\app\\config.json")?;

// WRONG: Unix-style absolute path
let config = std::fs::read("/home/user/.config/app/config.json")?;

// CORRECT: Platform-appropriate paths
use directories::ProjectDirs;

let dirs = ProjectDirs::from("com", "company", "app")
    .expect("Failed to get project directories");
let config_path = dirs.config_dir().join("config.json");
let config = std::fs::read(config_path)?;
8.2 プラットフォーム依存関係の不足
# WRONG: Missing Linux dependencies
- name: Build
  run: npm run tauri build  # Fails on Linux!

# CORRECT: Install platform dependencies
- name: Install Dependencies (Linux)
  if: matrix.platform == 'ubuntu-22.04'
  run: |
    sudo apt-get update
    sudo apt-get install -y \
      libgtk-3-dev \
      libwebkit2gtk-4.0-dev \
      libappindicator3-dev
8.3 ユニバーサルバイナリの問題
# WRONG: Build universal without both targets
- name: Build macOS Universal
  run: npm run tauri build -- --target universal-apple-darwin
  # Fails if x86_64 or aarch64 not available!

# CORRECT: Build each architecture separately
- name: Build macOS Intel
  run: npm run tauri build -- --target x86_64-apple-darwin

- name: Build macOS ARM
  run: npm run tauri build -- --target aarch64-apple-darwin

- name: Create Universal Binary
  run: |
    lipo -create \
      target/x86_64-apple-darwin/release/myapp \
      target/aarch64-apple-darwin/release/myapp \
      -output target/universal/myapp
8.4 公証の不足
# WRONG: Sign without notarization
codesign --sign "Developer ID" MyApp.app
# Users get Gatekeeper warnings!

# CORRECT: Sign and notarize
codesign --sign "Developer ID" --options runtime MyApp.app
xcrun notarytool submit MyApp.zip --apple-id "$APPLE_ID" --password "$APP_PASSWORD" --team-id "$TEAM_ID" --wait
xcrun stapler staple MyApp.app

13. 実装前チェックリスト

フェーズ 1:コードを書く前
  • プラットフォーム固有の要件をすべて読む
  • 対象プラットフォームとアーキテクチャを特定する
  • ビルド設定の検証テストを書く
  • すべてのターゲットを対象とする CI/CD マトリックスを設定する
  • コード署名証明書を取得する
  • CI 環境でシークレットを設定する
フェーズ 2:実装中
  • 設定を変更するたびにテストを実行する
  • インクリメンタルビルドが機能していることを確認する
  • 条件付きコンパイルを使ってプラットフォーム固有のコードをテストする
  • 依存関係の追加後にバンドルサイズを確認する
  • すべてのプラットフォーム用のアイコンが存在することを確認する
  • 実際の対象プラットフォームでテストする(CI だけで済ませない)
フェーズ 3:コミット前
  • すべてのビルド設定テストに合格している
  • Windows の証明書が EV 証明書であるか、十分な評価を得ている
  • macOS アプリが Developer ID で署名されている
  • macOS アプリが公証され、チケットが添付されている
  • Linux パッケージが GPG で署名されている
  • すべての署名にタイムスタンプが付与されている
  • 署名資格情報は CI のシークレットにのみ保存されている
  • ビルド成果物にチェックサムが付いている
  • 依存関係のバージョンが固定されている
  • ビルドログにシークレットが表示されない
  • Windows SmartScreen の審査に合格する
  • macOS Gatekeeper の審査に合格する
  • クリーンなシステムでインストーラーをテストしている
  • 自動更新 URL が HTTPS である

14. まとめ

目標は、次の条件を満たすクロスプラットフォームビルドを作成することです。

  • 適切に署名されている:各オペレーティングシステムから信頼される
  • プラットフォームに適合している:各プラットフォームの慣例に従っている
  • 最適化されている:ファイルサイズが妥当で、起動が速い

クロスプラットフォーム開発では、次の点が必要です。

  1. 各対象プラットフォームでテストする(開発マシンだけで済ませない)
  2. ユーザーからの信頼を得るため、適切にコード署名する
  3. プラットフォーム固有の設定と依存関係を管理する
  4. 配布要件を把握する

ビルド時の注意:リリース前には、必ず各プラットフォームでテストしてください。必ずリリースに署名してください。署名が正しく機能することを必ず確認してください。不明な場合は、署名手順について references/security-examples.md を参照してください。

コメント