ARM64EC解説:いつ使うべきか、どう使うか、そして皆を悩ませる依存関係のルール
2026年6月5日 更新
ARM64ECは、Windows on Arm開発において最も誤解されている部分です。OpenSSL、Qt、Ruby、.NETのイシュースレッドで「ARM64?それともARM64EC?」と疑問に思う場面がよくあります。ここではっきりさせましょう。
よく混同される3つの用語
- ARM64 — 純粋なネイティブArm64。最速ですが、Arm64プロセスはArm64バイナリしか読み込めません。
- ARM64EC(Emulation Compatible)— Windows 11のABIで、ネイティブのArm64ECコードとエミュレートされたx64コードが1つのプロセス内で共存します。Arm64EC部分はネイティブ動作、x64部分はエミュレーションで動作します。
- ARM64X — x64/Arm64EC用のビューと純Arm64用のビューの両方を含む単一のPEバイナリで、どちらの種類のプロセスでも読み込めます。共有DLLに使われます。
ARM64ECの正体
ARM64ECは、アプリが一度に完全にネイティブ化できない場合の橋渡し役です。多くの場合、x64のプラグイン、コーデック、またはArm64ビルドがないライブラリに依存しているのが理由です。自分のコードをARM64EC(ネイティブ速度)で再コンパイルし、x64依存部分はエミュレーションで同じプロセス内で動作させ続けます。Windows 11 on Arm自体がこれを利用しており、x64アプリが呼び出すOSコードのほとんどはARM64ECでコンパイルされているため、エミュレートされたアプリは気付かないうちにネイティブ速度のシステムコールを得られます。
ARM64ECにはWindows 11 SDKが必要です。Windows 10 on Armでは利用できません。
皆を悩ませる依存関係のルール
これは最もよく引用される落とし穴で、Microsoftからそのまま引用されています。
x64またはARM64ECのプロセスは、x64とARM64ECの両方のバイナリを読み込んで呼び出すことができますが、Arm64プロセスはArm64バイナリしか読み込めません。
つまり、ARM64ECプロセスはx64 ✓ と ARM64EC ✓ を読み込めますが、純ARM64 ✗ は読み込めません。ARM64ECをビルドして純Arm64の依存関係を取り込もうとすると、読み込みに失敗します。これは、ECビルドにネイティブArm64ライブラリを混ぜてしまう人を悩ませます。
段階的移行の手順
意図されたワークフローは段階的で、アプリは各ステップで動作し続けます。
- 完全にエミュレートされたx64アプリから始めます。
- 最もCPU負荷の高いモジュールを最初にARM64ECで再コンパイルします。労力あたりのパフォーマンス向上が最大になります。
- モジュールごとに続けます。
- すべての依存関係にArm64ビルドができたら、必要に応じて完全にネイティブArm64に移行します。
ARM64Xと純粋フォワーダーのテクニック
x64/ECプロセスと純Arm64プロセスの両方が読み込む必要があるDLLを配布する場合、ARM64Xとしてビルドします。1つのファイルに2つのビューがあります。便利なパターンは純粋フォワーダーです。これは、ローダーを正しいアーキテクチャ固有の実際のDLLにリダイレクトする、コードのない小さなARM64X DLLです。
ビルド成果物の見分け方
- 最終バイナリに対して
link /dump /headersを実行すると、ARM64ECコンテンツに対して8664 machine (x64) (ARM64X)と表示されます。(中間OBJ/LIBはA641 (ARM64EC)と表示されます。これはMSVC内部IDであり、最終的なPEタイプではありません。) - タスクマネージャーでは、ARM64ECアプリは 「ARM64 (x64互換)」 と表示されます。アーキテクチャ列の見方を参照してください。
ARM64ECと完全ネイティブの比較
ARM64ECは手段であり、目的ではありません。すべての依存関係にArm64ビルドがある場合は、純Arm64の方が高速でシンプルです。プロセスごとのエミュレーションもABIの混在もありません。ARM64ECは、x64専用の依存関係が純Arm64パスを妨げる場合、かつその場合にのみ使用してください。完全な移植ロードマップから始め、依存関係の監査によって自分がどの道にいるのかを判断しましょう。