WindowsでWebAssemblyの環境を整える


WindowsでC/C++をWebAssemblyに変換したい

WebAssemblyを使ってみる(C/C++をWebAssemblyに変換してChromeで実行) では主にLinux環境下でC/C++をWebAssemblyに変換していました。

今回はWindowsでその環境を整えます。以下今回の作業環境です。

  • Windows 10(64bit)
  • VisualStudio 2015
  • Cmake 3.5.0
  • LLVM 3.9(のはず)

このページではツールのビルドを行い、C/C++をWebAssemblyに変換して実行するのは上の記事で行いますので、ツールの導入以外はそちらを見てください。

流れ

必要なツール群は基本以下の流れで用意します。

  • Cmake (cmake-gui)を使ってVisualStudioのプロジェクトを書き出す
  • ALL_BUILD.vcxprojを開く
  • ビルドする
  • ビルドした成果物を入れるディレクトリにコピー

今回のディレクトリ構成は以下を想定します。

  • C:\Personal\Git 以下に各リポジトリをcloneしたりビルドする。
  • C:\dev\bin 以下に成果物のexeなどを入れる。

作業前に成果物を入れるディレクトリにパスを通して、再起動しておくと後でコマンドがスムーズに使えて良いと思います。

では一つ一つビルドしていきます。

LLVM+clang(WebAssembly対応)

LLVM+clangをVisualStudioでビルドします。

なお、MinGWなどで環境を整え挑戦しましたが、ファイルサイズが大きいの何のと言って70%くらいまでしかビルドが通らないので諦めました。

VisualStudioさんに頑張ってもらいましょう。

clone

まずLLVMのリポジトリ( http://llvm.org/git/llvm.git )をcloneします。

次にLLVMのビルドを行うbuildフォルダを作っておきます。

その後、clangのリポジトリ( http://llvm.org/git/clang.git ) をcloneし、LLVMリポジトリ内のtoolsフォルダにclangフォルダを移動します。

Cmake

Cmakeを起動します。

起動したらBowse SourceでLLVMのフォルダを、Browse Buildで先ほど作ったビルドを行うフォルダを指定します。

次にAdd EntryでLLVM_EXPERIMENTAL_TARGETS_TO_BUILDという名前の値にWebAssemblyを指定します。

ここまで終わると、Cmakeは次のような状態になっているはずです。

ここでGenerateボタンをクリックすると以下の様なダイアログが出るので、VisualStudio 14 2015が選択されていることを確認後、Finishをクリックします。

すべての作業が追わると今回指定した値が一覧で表示されるので、WebAssemblyが有効かどうか確認しておきます。

ビルド

buildフォルダに入ると、VisualStudioのプロジェクトファイルがあると思うので、ALL_BUILD.vcxprojを開いてください。開くのにちょっと時間がかかります。

すべてのプロジェクトを開いたら、ビルドボタンをクリックします。一応Releaseにしておくとファイルサイズとか小さくなります。

ビルドにはおよそ2,3時間かかると思います。

成果物

成果物はDebugもしくはReleaseフォルダ内のbinにあります。

clang.exellc.exeがあることを確認したら、とりあえず中のファイルすべてを、成果物を入れるフォルダ( 今回は C:\dev\bin )にコピーします。

binaryen

次にbinaryenをビルドします。

clone

binaryenのリポジトリ( https://github.com/WebAssembly/binaryen.git )をcloneします。

CMake

CmakeのBrowse SourceとBowse Buildでbinaryenのフォルダを指定します。

Generateボタンを押すと先程と同じくVisualStudioの指定があるので選んでFinishをクリックします。

作業が終わると以下のような状態になっているはずです。

コードの修正とビルド

binaryenのフォルダに入って、ALL_BUILD.vcxprojを開きます。

今回はビルドするとエラーになる箇所があるので、修正します。

src\wasm-s-parser.h

    if (!s[2]->dollared() && !std::isdigit(s[2]->str()[0])) {

このstd::isdigitがないので、std::を外します。

    if (!s[2]->dollared() && !isdigit(s[2]->str()[0])) {

成果物

成果物はbin内のDebugもしくはReleaseフォルダ内にあります。

sexpr-wasm-prototype

clone

sexpr-wasm-prototypeのリポジトリ( https://github.com/WebAssembly/sexpr-wasm-prototype.git )をcloneします。

CMake

CmakeのBrowse SourceとBowse Buildでsexpr-wasm-prototypeのフォルダを指定します。

Generateボタンを押すと先程と同じくVisualStudioの指定があるので選んでFinishをクリックします。

作業が終わると以下のような状態になっているはずです。

プロジェクトの修正とビルド

sexpr-wasm-prototypeのフォルダに入って、ALL_BUILD.vcxprojを開きます。

今回もビルドするとエラーになる箇所があるので、修正します。

まず、警告をエラー扱いしているので、それを外します。

ソリューションエクスプローラー上のsexpr-wasmの上で右クリック→プロパティを開きます。

構成プロパティ→C/C++→全般を選択し、警告をエラーとして扱うの値をいいえにします。

wasm-wastも同様に警告をエラーとして扱わないようにします。

もしDebugビルドの場合、このままでは以下の様なエラーが出ます。

C4013 関数 'memcpy' は定義されていません。int 型の値を返す外部関数と見なします。
C2040 'memcpy': 'void *(void *,const void *,size_t)' は 'void *(void *,const void *,size_t)' と間接操作のレベルが異なります。

英語だと多分これ。

C4013: 'memcpy' undefined; assuming extern returning int
C2040: 'memcpy' : 'void (char *,const char *,int )' differs in levels of indirection from 'void *(void *,const void *,unsigned int )'

これをなんとかすべく、一箇所コードを修正します。

wasm-config.h

このファイルの可能な限り上の方に以下3行を追加します。

#ifndef memcpy
#include<vcruntime_string.h>
#endif

これを追加すると、上記エラーが消えます。

成果物

リポジトリ内のDebugもしくはReleaseフォルダ内にあります。

最後に

これでWindows上でC/C++をWebAssemblyに変換するツール群のビルドは終了です。

パスが通っていれば、WebAssemblyを使ってみる(C/C++をWebAssemblyに変換してChromeで実行) で利用しているclangllcs2wasmsexpr-wasmの各種コマンドが使えるようになっているはずです。

それでは、後は頑張ってください。