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.exe
やllc.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で実行) で利用しているclang
、llc
、 s2wasm
、sexpr-wasm
の各種コマンドが使えるようになっているはずです。
それでは、後は頑張ってください。