1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

CMakeを使ってEmscriptenによるWebAssemblyのビルド&デバッグ環境を構築してみた

Last updated at Posted at 2025-07-06

1. 概要

タイトルの通り、CMakeを使ってWebAssemblyのビルド環境を作成し、さらにデバッグもできる環境を構築してみました。
具体的には以下のように、VSCode上でデバッグが可能となりました。
image.png
この関数を呼び出す仕組みはこちらで作ったものを流用しています。

2. ビルド環境構築

CMakeを使って環境を構築します。まずは以下のツールをインストールまたはダウンロードします。

ツール 概要 入手方法
VSCode エディタ 公式HP
からインストール
CMake ビルドシステム生成ツール 公式HP
からインストール
Emscripten SDK Emscriptenで
ビルドするのに使用
公式Gitリポジトリ
からClone
Ninja ビルドツール 公式リリースページ
からダウンロード

2.1 フォルダ構成

以下の構成で進めていきます。

├─Angular
└─Cpp
    ├─emsdk
    ├─ninja
    │      ninja.exe
    │
    └─WASM_CMake
        │  CMakeLists.txt
        │  CMakePresets.json
        │  setup.bat
        │
        ├─.vscode
        │      launch.json
        │      settings.json
        │      tasks.json
        │
        ├─build
        ├─dist
        └─src
                test.cpp

各フォルダは以下の用途で用います。

フォルダ 用途
Angular 以前作成したソースコード
をここに置いているので、そのまま流用します。
Cpp C++を使って作成するものはここに纏めています。
emsdk Cloneしたリポジトリをそのままここに配置します。
ninja リリースページからダウンロードした.exeファイルを置きます。
WASM_CMake 今回の作業のメインフォルダです。
VSCodeではこのフォルダを開きます。
.vscode VSCodeで作業する際に必要な設定ファイルです。
詳細は後の章で説明します。
build CMakeによる生成物はこちらに出力します。
dist 最終的な.wasmファイルはこちらに配置します。
src C++で書くソースファイル置き場です。
冒頭のデバッグ画面で見せたtest.cppはここに置いています。

2.2 CMakePresets.json

CMakeLists.txtを使って諸々処理するための事前設定をここに定義します。

CMakePresets.json
{
	"version": 3,
	"configurePresets": [
		{
			"name": "default",
			"generator": "Ninja",
			"binaryDir": "${sourceDir}/build",
			"cacheVariables": {
				"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/../emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake",
				"CMAKE_MAKE_PROGRAM": "${sourceDir}/../ninja/ninja.exe",
				"CMAKE_EXPORT_COMPILE_COMMANDS": "ON",
				"CMAKE_BUILD_TYPE": "Debug"
			}
		}
	]
}

設定のうち、重要なものをピックアップして説明します。${sourceDir}にはCMakePresets.jsonを配置しているフォルダパスが入ります。

設定 説明
generator ビルドシステム構成に使うビルドツールをここで指定します。
binaryDir 構成したビルドシステムの出力先です。
cacheVariables CMakeの環境変数をここで定義します。
ここで定義しているものは、CMakeLists.txtで再定義する必要がありません。
CMAKE_TOOLCHAIN_FILE Tool Chainです。
CMAKE_MAKE_PROGRAM ビルドツールの本体を記載します。
CMAKE_EXPORT_COMPILE_COMMANDS C++の補完機能を活用するのに有効。
VSCodeで作業するのであれば、とりあえず有効にしておくといい。

※generatorには最初、Visual Studioを設定しようとしていました。しかしそれだとEmscriptenのTool Chainが利用できず、ビルドが通りませんでした。

2.3 CMakeLists.txt

CMakeLists.txt
cmake_minimum_required(VERSION 3.30)
project(WasmProject)

set(TARGET_NAME "WasmTest")
set(EMSDK_PATH "${CMAKE_SOURCE_DIR}/../emsdk")

file(GLOB SRC_FILES
	"${CMAKE_SOURCE_DIR}/src/*.cpp"
	"${CMAKE_SOURCE_DIR}/src/*.h"
)

add_executable(${TARGET_NAME} ${SRC_FILES})

target_include_directories(${TARGET_NAME} PRIVATE
	"${EMSDK_PATH}/upstream/emscripten/cache/sysroot/include"
)

target_compile_options(${TARGET_NAME} PRIVATE -g)

target_link_options(${TARGET_NAME} PRIVATE
	"-g"
	"-sMODULARIZE=1"
    "-sEXPORT_NAME=${TARGET_NAME}"
	"--no-entry"
)

set_target_properties(${TARGET_NAME} PROPERTIES SUFFIX ".js")

set(OUTPUT_DIST_DIR "${CMAKE_SOURCE_DIR}/dist")
install(FILES
	"${CMAKE_BINARY_DIR}/${TARGET_NAME}.js"
	"${CMAKE_BINARY_DIR}/${TARGET_NAME}.wasm"
	DESTINATION "${OUTPUT_DIST_DIR}"
)

こちらも重要な部分だけをピックアップして説明します。

設定 説明
target_include_directories SDKのincludeパスを指定します。
includeフォルダはパスに"cache"が含まれないものもありますが、そちらはincludeするとビルドエラーとなるよう設定されていますので、上記のパスを指定してください。
target_link_options ビルド時のリンクオプションです。
"-g"はデバッグビルドの際に必要なオプションです。
"-sMODULARIZE=1"は他のプログラムから関数を呼び出せるようモジュール化するための設定です。
EXPORT_NAMEはTypeScriptのコードで処理を呼び出す際のクラス名となります。
"--no-entry"でmain関数を作らなくて済むようにしています。
set_target_properties ビルド後の生成物に関する指定です。
.jsファイルが生成され、さらに(当然ですが).wasmファイルも生成されます。
install どの生成物をどこに配置するか、ここで指定します。

2.4 セットアップスクリプト

これまでの設定ファイルを使用してビルド環境を構築するスクリプトです。

setup.bat
@echo off
setlocal

set EMSDK_PATH="..\emsdk"

call %EMSDK_PATH%"\emsdk_env.bat"
mkdir dist
mkdir build
cd build
cmake -S .. --preset=default
cmake --build .
cmake --install .

endlocal
  • emsdk_env.batを実行することで、ビルドに必要な初期化処理を行います
  • "cmake -S .. --preset=default"で、CMakePresets.jsonの"default"設定を読み込み、CMakeLists.txtを使ってビルドシステムを構築します
  • "cmake --build ."で、構成したビルドシステムを使ってビルドします
  • "cmake --install ."で、生成物をCMakeLists.txtのinstallで指定した通りに処理します

3. VSCodeでビルド

VSCodeでビルドするため準備します。

3.1 拡張機能のインストール

以下の拡張機能をインストールしてください。

  • C/C++ (Microsoftによって作成されているやつ)
  • CMake Tools
  • WebAssembly DWARF Debugging
  • JavaScript Debugger

3.2 settings.json

settings.json
{
  "cmake.configurePreset": "default",
  "cmake.buildPreset": "default",
  "cmake.sourceDirectory": "${workspaceFolder}",
  "cmake.buildDirectory": "${workspaceFolder}/build",
  "C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools"
}

"C_Cpp.default.configurationProvider"に"ms-vscode.cmake-tools"を設定すると、インテリセンスがCMakeLists.txtで設定した情報(インクルードパスなど)を参照できるようになります。

3.3 tasks.json

tasks.json
{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "CMake: Build",
      "type": "shell",
      "command": "cmake",
      "args": [
        "--build",
        "${workspaceFolder}/build"
      ],
      "problemMatcher": []
    },
    {
      "label": "CMake: Install to dist",
      "type": "shell",
      "command": "cmake",
      "args": [
        "--install",
        "${workspaceFolder}/build"
      ],
      "problemMatcher": []
    },
    {
      "label": "CMake: Build and Install",
      "dependsOn": [
        "CMake: Build",
        "CMake: Install to dist"
      ],
      "dependsOrder": "sequence",
      "type": "shell",
      "command": "echo",
      "args": ["Build and Install completed."],
      "group": {
        "kind": "build",
        "isDefault": true
      }
    }
  ]
}

ビルド実行時のタスクを設定しています。

  • "CMake: Build"で、cmake --buildに相当する処理を実行します
  • "CMake: Install to dist"で、cmake --installに相当する処理を実行します
  • "CMake: Build and Install"で、これら2つをまとめて実行します。groupのkind, isDefaultを上記の通り設定することでビルドに紐づけることができます

3.4 launch.json

launch.json
{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "chrome",
      "request": "attach",
      "name": "Attach to Chrome (WASM)",
      "port": 9222,
      "webRoot": "${workspaceFolder}/../../Angular/WebAssembly/Application/public",
      "sourceMaps": true
    }
  ]
}

デバッグ実行時の処理をここに書きます。.wasmファイルを読み込んでいるブラウザにアタッチすることでデバッグを行います。
webRootは実際にWebアプリが読み込んでいる.wasmファイルのパスを設定する必要があります。
※今回はAngularとEmscriptenとでフォルダが分かれていますので、CMakeLists.txtのinstallで指定したdistフォルダから手動でAngularの方へコピーしています。.wasmにデバッグシンボルが含まれていますので、distに配置されていなくてもアタッチ&デバッグは可能です。

3.5 ソースコードを記述

C++でコードを記述します。

test.cpp
#include <emscripten/emscripten.h>

extern "C" {

EMSCRIPTEN_KEEPALIVE
int add(int x, int y) {
	return x + y;
}

}

3.6 ビルド

Ctrl + Shift + Bを同時押しすることで、tasks.jsonで設定した"CMake: Build and Install"が実行されます。
成功すれば、distフォルダにWasmTest.jsとWasmTest.wasmが生成されます。
※タスクバーのビルドボタンを押しても"CMake: Build and Install"は実行されません。

4. デバッグ

distに生成された.wasmファイルを所定の場所にコピーし、Webアプリを起動します。
こちらの場合だとApplication/wasmが配置場所なので、ここへコピーします。

4.1 大まかな流れ

  1. ng serveでAngularのWebサーバを立ち上げる(Angularを使用されていない方は、ご自身の環境に合わせてサーバーを立ち上げてください)
  2. リモートデバッグを有効にしてブラウザを起動する
  3. ブラウザのURLに、立ち上げたサーバーのアドレスを入力する
  4. VSCodeからブラウザにアタッチ
  5. ブラウザを操作し、WebAssemblyのコードが実行されるようにする

リモートデバッグを有効にしてブラウザを起動する際は、コマンドプロンプトで以下のコマンドを実行してください。ポートはlaunch.jsonに合わせる必要があります。

"C:\Program Files\Google\Chrome\Application\chrome.exe" --remote-debugging-port=9222 --user-data-dir="%TEMP%\chrome-wasm-debug"

またブラウザへのアタッチは、launch.jsonに定義を書いていますので、デバッグ実行を開始することでアタッチが行われます。

4.2 Angularアプリを変更

以前作成したものはそのまま使用できないので、以下の点を変更します。

  • 読み込む.wasmファイルを、"test.wasm"から"WasmTest.wasm"に変更
  • 参照するモジュール名をWASMからWasmTestに変更
  • デバッグ確認しやすいように、add関数をsetIntervalで定期的に実行

4.3 ブレイクを仕込んでみた

add関数が呼ばれたところにブレイクを仕込みました。それが冒頭に見せたこの画面です。変数のウォッチも機能しています。
image.png

5. まとめ

というわけで、CMakeを使ってデバッグ環境を構築しました。
WebAssemblyは有用なのですが、今まではコマンドでビルドを実行していて面倒でした。しかし今回、開発環境を整えることができたので、かなり作業しやすくなりました。
次は開発環境だけでなく、C++のソースコードに手を加えて、高速に動くWebアプリの作成に挑戦していきたいです。

1
1
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
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?