【WebAssembly】Visual Studioで WASM のビルド方法【C++】
初めに
最近 仕事の関係で Unity 2018 を使っており、Unity や C++からも取り残されてしまいました。
Unity 2022 の新機能も興味がありましたが、C++ のリハビリと 以前から興味があった WebAssembly を試して見ようと思います。
Building a C++ Wasm Module in Visual Studio 様を参考に Visual Studio で WebAssembly のビルドと実行できるまでのメモです。
参考サイトにはより詳しく書かれています。
色々インストールする
インストール済みであれば飛ばしてください。
Visual Studio 2022 をインストール
emsdk をインストール
Python インストール
前準備
設定済みであれば飛ばしてください。
Visual Studio
Visual Studio Installer を実行して必要なモジュールを追加します。
CMake と C++ Clang モジュールが必要です。

emsdk
emsdk ダウンロード後,
emsdk ビルド環境構築してください。
> cd emsdk
> emsdk.bat install latest
> emsdk.bat activate latest
> emsdk_env.bat
Python
実行確認用にインストールします。
Add Python 3.12 to PATH にチェックして、PATH を通して起動できるようにしてください。
参考先では statikk を使っています。
プロジェクトの作成
CMakeプロジェクトを作成します。

TestCMake としました。

CMakeSettings.json の編集
元の CMakeSettings.json を削除します

新たに 追加から新しいファイルで CMakeSettings.json を作成します。
JSON の編集をクリックして編集します。

とりあえず Debug のみ
CMakeのツールチェーン cmakeToolchain は emsdk の Emscripten.cmake を設定します。
{
"configurations": [
{
"name": "x64-Debug",
"generator": "Ninja",
"configurationType": "Debug",
"buildRoot": "${projectDir}\\out\\build\\${name}",
"installRoot": "${projectDir}\\out\\install\\${name}",
"cmakeCommandArgs": "",
"buildCommandArgs": "",
"ctestCommandArgs": "",
"cmakeToolchain": "C:\\Solutions\\emsdk\\upstream\\emscripten\\cmake\\Modules\\Platform\\Emscripten.cmake",
"inheritEnvironments": [],
"intelliSenseMode": "windows-clang-x64"
}
]
}
CMake 設定の編集で通常の GUI の設定画面になります。

「変数を読み込むための CMake キャッシュの保存と生成」をクリック しキャッシュを作成します。

エラーが出なければOKです。
CMakeLists.txt の編集
emscripten の include を追加します。
# Emscripten のインクルートを追加
target_include_directories( CMakeTest PUBLIC "C:/Solutions/emsdk/upstream/emscripten/cache/sysroot/include")
cmake_minimum_required (VERSION 3.8)
# サポートされている場合は、MSVC コンパイラのホット リロードを有効にします。
if (POLICY CMP0141)
cmake_policy(SET CMP0141 NEW)
set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<IF:$<AND:$<C_COMPILER_ID:MSVC>,$<CXX_COMPILER_ID:MSVC>>,$<$<CONFIG:Debug,RelWithDebInfo>:EditAndContinue>,$<$<CONFIG:Debug,RelWithDebInfo>:ProgramDatabase>>")
endif()
project ("CMakeTest")
# ソースをこのプロジェクトの実行可能ファイルに追加します。
add_executable (CMakeTest "CMakeTest.cpp" "CMakeTest.h")
# Emscripten のインクルートを追加
target_include_directories( CMakeTest PUBLIC "C:/Solutions/emsdk/upstream/emscripten/cache/sysroot/include")
if (CMAKE_VERSION VERSION_GREATER 3.12)
set_property(TARGET CMakeTest PROPERTY CXX_STANDARD 20)
endif()
キャッシュを再構成する場合は
メニュー > プロジェクト > キャッシュを削除し再構成する
を起動します。

ビルドする
ビルドできるようになったのでビルドします。

./out/build/x64-debug/ に
CMakeTest.js
CMakeTest.wasm
が生成されていれば成功です。
このままでは実行確認できないので、html を出力できるようにします。
# Emscripten の テスト html を追加
set(CMAKE_EXECUTABLE_SUFFIX .html)
cmake_minimum_required (VERSION 3.8)
# サポートされている場合は、MSVC コンパイラのホット リロードを有効にします。
if (POLICY CMP0141)
cmake_policy(SET CMP0141 NEW)
set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<IF:$<AND:$<C_COMPILER_ID:MSVC>,$<CXX_COMPILER_ID:MSVC>>,$<$<CONFIG:Debug,RelWithDebInfo>:EditAndContinue>,$<$<CONFIG:Debug,RelWithDebInfo>:ProgramDatabase>>")
endif()
project ("CMakeTest")
# ソースをこのプロジェクトの実行可能ファイルに追加します。
add_executable (CMakeTest "CMakeTest.cpp" "CMakeTest.h")
# Emscripten のインクルートを追加
target_include_directories( CMakeTest PUBLIC "C:/Solutions/emsdk/upstream/emscripten/cache/sysroot/include")
# Emscripten の テスト html を追加
set(CMAKE_EXECUTABLE_SUFFIX .html)
if (CMAKE_VERSION VERSION_GREATER 3.12)
set_property(TARGET CMakeTest PROPERTY CXX_STANDARD 20)
endif()
再度ビルドし ./out/build/x64-debug/ に
CMakeTest.html
が出力されているのを確認します。
実行確認する
ファイル run_debug.bat を追加します。
追加 > 新しいファイル > run_debug.bat
run_debug.bat を編集します。
python で簡易サーバーを実行し、CMakeTest.html を開く内容です。
cd "./out/build/x64-Debug"
rundll32 url.dll,FileProtocolHandler "http://localhost:8000/CMakeTest.html"
python -m http.server 8000
訂正 –cgi オプションは不要でした。

このままでは、ダブルクリックしても編集になり実行はされません。
ダブルクリックで実行できるようにします。
「ファイルを開くアプリケーションの選択…」から実行方法を設定します。

「追加…」 で新しい項目を追加します。
プログラムに PowerShell のフルパスを設定します。
環境によりPath は異なるかもしれません。
Windows10
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
Windows11
C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe
表示名
PowerShell

「既定値として設定」を押して設定します。

run_release.bat も設定しておきます。
エディッタで
エディッタで run_debug.bat タブを閉じてください。
開いたままだとダブルクリックしても編集画面になります。
run_debug.bat をダブルクリックでブラウザーが開き実行結果を確認できます。

実行結果

一度実行すると、リビルドし wasm が更新した場合も、ブラウザーを閉じなくても再読み込みで変更を確認できます。
chrome など 再読み込みで更新されない場合はハードリロード、
Ctrlキー + Shiftキー + Rキーを同時に押すことで、キャッシュを無視してページを再読み込みできます。
ハマりポイント
run_debug.bat や run_release.bat に
UTF8 BOM がついていると、実行に失敗します。
動かない場合は確認してみてください。
最後に
ひとまずビルド環境が出来上がりました。
今後は WebGL や WabGPU や C++20 C++23 を触って見たいと思います。
Building a C++ Wasm Module in Visual Studio 様へ感謝します。とても参考になりました。