1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Avalonia UI × Rust エンジン × VS Code 拡張:マルチプラットフォーム/マルチベンダー開発の実践メモ

1
Posted at

はじめに

1つの Rust 製描画エンジンを、2つの入口から使う構成を紹介します。

  • デスクトップアプリ:Avalonia UI(C#)で作るデザイナー
  • エディタ拡張:VS Code 拡張(TypeScript)で作るビューア

この構成で、次の2種類の「マルチ」に対応するときに得た実践的な知見をまとめます。

  • マルチプラットフォーム:Windows / macOS / Linux × x86_64 / ARM64 の6通り
  • マルチベンダー:メーカーごとにプリンタ言語が異なるラベル/レシートプリンタ

以下のクレート名・リポジトリ名はすべてサンプル名です。

1. 全体構成

描画エンジンは Rust 1本です。UI からの入口を2つ用意し、出力先もプレビューとプリンタの2系統を持ちます。

report_core (Rust workspace)
 ├ report_ffi   : C ABI の cdylib (.dll/.so/.dylib) → Avalonia アプリ (C#)
 ├ report_node  : NAPI-RS の .node                 → VS Code 拡張 (TypeScript)
 └ 出力         : プレビュー (Skia) / プリンタ各社のコマンド

ロジックは report_core にだけ置き、バインディング層は薄く保ちます。こうしておくと、UI が増えてもエンジン側の修正は1か所で済みます。

2. Rust エンジン側

  • ワークスペース分割:コア、レンダラ、FFI、Node バインディングを別クレートに分けます。機能を足すときは既存関数を書き換えず、新しい公開関数を追加する形を基本にします。
  • panic を FFI 境界を越えさせない:NAPI-RS の境界で panic するとアンワインドできず、Node プロセス(VS Code の拡張ホスト)ごと落ちます。エラー表示も出ないため、原因の特定が非常に難しくなります。フォントが見つからない、ファイルがない、といった「起こり得る失敗」は、panic にせず警告ログとフォールバックで処理します。
  • フォントのフォールバック:OS ごとにフォント事情が違います。1文字ずつグリフが存在するかを確認し、なければ代替フォントに切り替えると、豆腐(□)表示を防げます。Linux 向けには CJK フォントを同梱しておくと確実です。

3. Avalonia UI 側

  • C# からは DllImport / LibraryImport で cdylib を呼びます。
  • 配布物は dotnet publish -c Release -r <RID> --self-contained で作り、出力フォルダに該当 OS の cdylib を同梱します。
  • macOS:署名と公証(notarize)がないと Gatekeeper でブロックされます。無署名で配布するなら、README に「右クリック → 開く」の手順を書いておきます。
  • Windows:無署名だと SmartScreen の警告が出ます。

4. VS Code 拡張側

  • ネイティブモジュールの読み込み:require で .node を読み込む処理は、必ず try/catch の中に入れます。外に出すと、読み込み失敗が黙って握りつぶされます。
  • NAPI-RS 出力名の罠:napi build --release の出力は index.node です。拡張が別名で読み込む設計なら、ビルドのたびに名前を変えてコピーする必要があります。忘れると、古いバイナリのままパッケージされてしまいます。
  • プラットフォーム別 vsix:vsce package --target win32-x64 のように、OS ごとに別々の .vsix を作ります。
  • Linux の Snap 版 VS Code は非対応:Snap のサンドボックス内は glibc が古い版で固定されているため、ネイティブモジュールが読み込めません。activate() で Snap を検出してメッセージを出し、README には deb/rpm 版が必要と明記します。
  • Cursor 互換:engines.vscode の下限を上げすぎると Cursor に入りません(例:^1.85.0 程度に抑える)。
  • キーバインド:Linux の GNOME では Ctrl+Alt+D がデスクトップ表示と競合します。macOS では Option+英字が特殊文字の入力に取られます。全 OS で安全なのは Ctrl+Alt+数字 系です。
  • 公開前チェック:
    • Open VSX はライセンスのない拡張を拒否します。LICENSE.txt を用意し、"license": "SEE LICENSE IN LICENSE.txt" を書きます。
    • .vscodeignore でテスト用の PDF などを除外しないと、.vsix が肥大化します。
    • Marketplace の name と displayName は、検索に出なくても予約済みで使えないことがあります。候補を複数用意しておきます。
    • package.nls.json と package.nls.ja.json などでコマンド名を多言語化できます。

5. マルチプラットフォーム(OS × CPU アーキテクチャ)

Windows・macOS・Linux の3つの OS と、x86_64・ARM64 の2つの CPU アーキテクチャを組み合わせると、ビルド対象は6種類になります。

OS / CPU VS Code --target .NET RID Rust ターゲット
Windows x64 win32-x64 win-x64 x86_64-pc-windows-msvc
Windows ARM64 win32-arm64 win-arm64 aarch64-pc-windows-msvc
Linux x64 linux-x64 linux-x64 x86_64-unknown-linux-gnu
Linux ARM64 linux-arm64 linux-arm64 aarch64-unknown-linux-gnu
macOS Intel darwin-x64 osx-x64 x86_64-apple-darwin
macOS Apple Silicon darwin-arm64 osx-arm64 aarch64-apple-darwin
  • 実機でビルドと検証を行う方針:描画の正確さは実機で確認するのが確実です。
  • ARM の Windows と Linux:1台の Windows ARM 機でまとめて扱えます。Windows 側で win32-arm64 を、同じマシンの WSL2 Ubuntu で linux-arm64 をビルド・検証します。
  • Linux:古めの Ubuntu でビルドすると、要求する glibc を低く抑えられます。
  • macOS のハマりどころ:
    • sudo xcodebuild -license に同意していないとリンクが失敗します。
    • rustup が古いと edition2024 のクレートがビルドできません。
  • ソース管理:各マシンは GitHub から clone します。フォルダのコピーによる同期はやめます。

6. マルチベンダー(ラベル/レシートプリンタ)

1つのエンジンで、メーカーごとに異なるプリンタ言語へ出力します。

帳票定義 + データ
   ↓
共通の中間描画モデル(特許出願中)
   ├ プレビュー  : Skia で PNG/PDF
   └ プリンタ出力: プロトコル別レンダラ
       ESC/POS / StarPRNT / SBPL / ZPL / TPCL / TSPL / DMX …
  • レイアウトは1回だけ計算する:中間モデルまでは全メーカー共通です。メーカーごとの差分は、出力段のレンダラだけに閉じ込めます。新しいメーカーに対応するときは、レンダラを1つ追加するだけで済みます。
  • 座標単位の違いは出力段で吸収する:単位はプロトコルごとに異なります(ドット、0.1mm など)。内部の単位は統一しておき、変換は各レンダラの中で行います。
  • 機種固有のずれは補正パラメータで持つ:メカ上のセンタリングずれや左余白のずれは、機種ごとの補正値として設定から調整できるようにします。
  • 文字コードは同じプロトコルでも機種で違う:同じ ESC/POS でも、漢字モードの指定コマンドはメーカーによって異なります。
  • プリンタ内蔵フォントの限界:出力はプリンタの内蔵フォントを使います。そのためプレビューが正確に再現できるのは、配置・折り返し・バーコードの座標までです。文字の形や字間は実機での確認が必要です。
  • 画像の扱いを使い分ける:画像を転送するプロトコルと、プリンタに事前登録したグラフィックを名前で参照するだけのプロトコルがあります。
  • 対応状況を公開する:メーカー・機種・プロトコル・検証済みかどうかを CSV で公開します。アプリ側からその CSV を取得すれば、ユーザーは検証済み機種を確認できます。

7. 配布の自動化(ビルドは実機、公開は Actions)

  1. 各実機で .vsix をビルドし、動作を確認します。
  2. 配布用リポジトリに Draft リリースを作り、全ターゲット分の .vsix を添付します。
  3. 「Publish release」を押すと、.github/workflows/release-to-stores.yml が起動します。
  4. Actions が添付ファイルを取得し、全ターゲット分が揃っているか、バージョンが一致しているかを検証します。
  5. 検証を通れば vsce publish --packagePath と ovsx publish を実行します。どちらも --skip-duplicate を付けておくと、再実行しても安全です。

トークンは VSCE_PAT(Azure DevOps、Marketplace の Manage 権限)と OVSX_PAT を、配布用リポジトリの Secrets に登録します。

Avalonia アプリも同じ Draft リリース方式で配布できます。ストアに公開しないので、Actions は不要です。

8. リポジトリ運用

  • ソースと配布物は別リポジトリにします(例:report-designer-src と report-designer-release)。
  • ソースは Private、配布用は Public にします。
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?