ブログに戻る
compilercross-compilationinfrastructuremilestone

Windows へのクロスコンパイル、iOS ゲームループ、100% テストパリティ

今週、Perryコンパイラに103件のコミット。主要な機能:LinuxからWindowsの実行ファイルをクロスコンパイルできるようになり、iOSアプリでブロッキングゲームループが実行可能になり、コンパイラがテレメトリのためにクラッシュを報告し、セルフホスティングコンパイラがすべての決定論的テストに合格しました。さらにHubインフラの大規模アップグレードと50以上のバグ修正があります。

LinuxからWindowsへのクロスコンパイル

Perryは、LinuxホストからWindows .exeバイナリを生成できるようになりました。これは、コンパイル全体のためにWindowsビルドマシンを実行せずにWindowsをターゲットにする必要があるCI/CDパイプラインに欠けていたピースです。

この実装は、コンパイル時の#[cfg]チェックをランタイムのターゲット検出に置き換えます。コンパイラが非WindowsホストでWindowsターゲットを検出すると、新しいfind_llvm_tool()ヘルパーを通じてRustツールチェーンまたはPATHからlld-link llvm-nm、および llvm-arを検索します。Windowsシステムライブラリは、PERRY_WINDOWS_SYSROOTで指定された xwinスタイルの sysrootから提供されます。

リンカーは自動的に/FORCE:UNRESOLVEDを使用し、不足しているUIシンボルのスタブを生成するため、CLIアプリはクリーンにクロスコンパイルされます。Windowsをターゲットにする場合、出力はデフォルトで.exeになります。詳細は クロスコンパイルドキュメントをご覧ください。

terminal — Linux host

$ perry compile main.ts --target windows

Compiling main.ts for windows-x86_64...

Using lld-link from Rust toolchain

✓ Compiled executable: main.exe (2.8 MB)

iOSゲームループサポート

iOSではUIKitがメインスレッドを所有する必要があります。イベント駆動型アプリには問題ありませんが、ブロッキングwhile (!shouldClose)ループを必要とするゲームにとっては問題です。Perryは--features ios-game-loopフラグでこれを解決しました。

有効にすると、コンパイラは mainの代わりに _perry_user_mainを出力します。ランタイムはメインスレッドで UIApplicationMainを呼び出し、バックグラウンドスレッドでユーザーコードを生成する main()を提供します。Scene delegateとapp delegateがUIKitの完全なライフサイクルを処理し、ゲームループはブロックされずに実行されます。

main.ts

// Your game loop runs on a background thread

while (!shouldClose) {

update();

render();

awaitNextFrame();

}

terminal

$ perry run ios --features ios-game-loop

これにより、ゲーム、シミュレーション、リアルタイムビジュアライゼーションなど、以前はiOSでは実用的でなかったアプリのカテゴリ全体が可能になります。iOSのポンプとコールバックパスもパニックハンドリングでラップされたため、ゲームループまたはUIKitライフサイクルのどちらでのクラッシュもクリーンにキャッチされます。

クラッシュレポート

Perryでコンパイルされたアプリは、起動時にパニックフックと SIGSEGV SIGBUS、および SIGABRTのシグナルハンドラーをインストールするようになりました。致命的なクラッシュが発生すると、詳細がChirpテレメトリシステム用に~/.hone/crash.logに書き込まれます。キャッチされたパニック( catch_callback_panic内)はログをクリアするため、真に回復不可能なクラッシュのみが報告されます。

これは本番環境対応の機能です。フィールドで何か問題が発生した場合、私たちはそれを把握できます — そしてクラッシュログには、ユーザーに手動での報告を求めることなく問題を診断するための十分なコンテキストが含まれています。

Hub: 2段階Windowsビルドパイプライン

Perry Hubのビルドインフラが大幅なアーキテクチャのアップグレードを受けました。以前は、Windows向けのビルドにはコンパイル全体にWindowsワーカーが必要でした。現在、パイプラインは2つのステージに分割されます:

  1. Linuxワーカーが新しいlld-linkサポートを使用してWindowsアーティファクトをクロスコンパイル
  2. Hubがプリコンパイル済みアーティファクトを保持し、Windowsワーカー向けにジョブを再キュー
  3. Windowsワーカーは署名とパッケージングのみを処理 — はるかに軽いタスク

ワーカーがcomplete needs_finishing: "windows"と共に送信すると、Hubは透過的にジョブを再キューします。CLIからはシームレスな単一ビルド体験に見えます。

Hubは、Windowsワーカーが接続されていない場合にAzure Windows VMを自動起動するようにもなり、ビルドワーカーは新しいリリースで最新のPerryバージョンに自動更新されます。手動のインフラ管理が減り、ビルドが高速化します。

ドキュメントの改訂

今週、 docs.perryts.comに2つの主要なドキュメント書き直しが公開されました:

  • perry.tomlリファレンス — すべての設定オプション、バンドルID解決、エントリファイル解決、ビルド番号自動インクリメント、CI/CDの例を網羅した完全なセクションドキュメント
  • Geisterhandリファレンス — クロスプラットフォームUIテストフレームワークの完全なAPIドキュメント、プラットフォームセットアップ、テスト自動化パターン、アーキテクチャ概要

これらは段階的な更新ではありません。どちらもすべての機能と設定オプションをカバーするゼロからの書き直しです。新しいプロジェクトのセットアップやテストの作成を行う場合は、ここから始めてください。

クロスプラットフォームメニューAPI

menuClear menuAddStandardActionは以前macOS専用でした。現在は6つのネイティブプラットフォームすべてで動作します。これには、Windowsでのdispatch_menu_itemにおけるRefCell再入パニックの修正も含まれています。

Android: 16 KBページアラインメント

Google Playは、ネイティブライブラリに16 KBのページアラインメントを要求するようになりました。Perryは適切なCARGO_TARGET_AARCH64_LINUX_ANDROID_RUSTFLAGS を自動的に設定し、コンパニオン.soファイルがAPK/AABに含めるために出力の隣にコピーされます。

Perry React: カンバンボード

React互換レイヤーが実世界のテストを受けました:移動、追加、削除、表示操作を備えた完全な5列カンバンボードです。構築する中で、JSXのネストされた配列childrenレンダリングが発見され修正されました — 再帰的な _appendChildrenハンドラーが.map()呼び出しから返される配列を適切にフラット化するようになりました。さまざまなUIパターンをカバーする14セクションのKitchen Sink WorkBenchデモも新たに追加されました。

Anvil: 100%決定論的テストパリティ

perrysdad — TypeScriptで書かれ、PerryでコンパイルされたセルフホスティングLLVMコンパイラ — が68件中68件の決定論的テストに合格し、メインコンパイラの出力と正確に一致するようになりました。唯一の違いは固有のもの(タイムスタンプ、Math.random())であり、11件のテストはUI、タイマー、暗号化、またはまだ実装されていないプラットフォーム固有の機能を必要とするためスキップされています。

達成に至った主要な作業:

  • インターフェースメソッドディスパッチ — インターフェース型の変数がObjectHeaderのclass_idベースのディスパッチを通じて正しいメソッドを返すように
  • 動的プロパティアクセス — 計算されたプロパティ名のランタイムディスパッチ
  • クロージャとthisバインディング — オブジェクトメソッドの正しいキャプチャセマンティクス
  • フェーズ6進行中 — async/await、ジェネレーター、条件修正

決定論的テストの100%パリティは重要なマイルストーンです。セルフコンパイルされた anvilバイナリが、テスト可能なすべてのシナリオでメインコンパイラとまったく同じ出力を生成することを意味します。完全なセルフホスティングに向けてギャップは狭まっています。

50以上のバグ修正

今週は正確性に関する大きな推進がありました。ハイライト:

  • JSON.parse — 配列が16要素で切り捨てられなくなり、無効な入力が正しく処理されるように
  • Uint8Array — 配列変数からのコンストラクター、.set(source, offset)の実装(以前はno-op)
  • BigInt — クロスモジュール呼び出し用のBIGINT_TAGによるNaN-boxing、keccak256の32ビット切り捨て修正
  • Optional chaining — ネストされた条件式、toString検出、戻り値のNaN-boxing
  • IndexSetPOINTER_TAGの代わりにSTRING_TAGを使用するよう文字列NaN-boxingを修正
  • MySQL — DATETIMEおよびBLOB型、Date(string)コンストラクター
  • Math.min/max — スプレッド引数の処理
  • ネイティブメソッドディスパッチPOINTER_TAGオブジェクトのfield-scan-and-call

これらはエッジケースではありません。JSON.parseが配列を16要素で切り捨てると、あらゆる実際のアプリケーションが壊れます。Uint8Array.setがno-opだと、データがサイレントに破損します。これらは、一度に1つの正確性バグを修正しながら、コンパイラを本番グレードにする修正です。

数字で見る成果

  • 103コミットをPerryメインコンパイラに
  • 3バージョン: v0.2.195、v0.2.196、v0.2.197
  • 1つの主要機能: LinuxからWindowsへのクロスコンパイル
  • 1つの新しいアプリカテゴリ: iOSゲームループ
  • 68/68 perrysdadの決定論的テストパリティ
  • 50以上のバグ修正:NaN-boxing、stdlib、ネイティブFFI全体
  • 2つのドキュメント書き直し: perry.tomlとGeisterhand
  • 5つのHub改善: 2段階パイプライン、Azure自動起動、ワーカー自動更新

次のステップ

Windowsクロスコンパイルは、完全に自動化されたマルチプラットフォームCI/CDへの扉を開きます — TypeScriptをプッシュすれば、各OS専用のビルドマシンなしで、すべてのターゲット向けのネイティブバイナリが得られます。ゲームループサポートは、iOSアプリのまったく新しいカテゴリを解き放ちます。そしてperrysdadの100%決定論的テストパリティは、セルフホスティングが非常に現実的になっていることを意味します。残っているもの:

  • 完全なregexサポート — 最後の主要な言語ギャップ
  • perry/uiの拡張 — ドラッグアンドドロップ、アクセシビリティラベル、DatePicker
  • perrysdadフェーズ6 — async/await、ジェネレーター、完全なPerryパリティに向けた拡張
  • Hubパブリックベータ — 分散ビルドを外部ユーザーに開放

進捗状況は GitHubでフォロー、ドキュメントは docs.perryts.comで閲覧、または ロードマップ で全体像をご確認ください。