2012/09/12

Emscriptenを用いてC++ソースをJavaScriptに変換する

EmscriptenはC/C++ソースからJavaScriptソースへ変換するコンパイラです。

BananaBreadのようなゲームやPythonやRubyのようなスクリプト言語もコンパイルできるようです (Emscripten Wikiにはそれ以外のデモやサンプルへのリンクがあります)。

そこで、今回は導入してHello worldを実行させるまでの手順を紹介します。

Emscriptenの導入

コンパイラであるem++を使うだけなら意外と簡単に導入できます。

  • XcodeのCommand Line Toolsは導入済みとします。
  • JavaScriptの最適化ツールであるClosureコンパイラはEmscriptenに (古いバージョンですが) 入っています。

Emscriptenのセットアップ

次のような感じでNode, Clang, Emscriptenを導入します。 AppleのclangがあるからClang導入がいらないかと思いましたが、llvm-disが必要なので取得必須でした。

なお、brew導入済みであるならば、Nodeに関してはbrew install nodeでもよいかもしれません。

mkdir ~/dev

# Get node
cd ~/src
git clone git://github.com/joyent/node.git
cd node
./configure --prefix=~/dev/node
make && make install

# Get LLVM/Clang
cd ~/dev
curl -O http://llvm.org/releases/3.1/clang+llvm-3.1-x86_64-apple-darwin11.tar.gz
tar zxf clang+llvm-3.0-x86_64-apple-darwin11.tar.gz
mv clang+llvm-3.1-x86_64-apple-darwin11 clang

# Get Emscripten
cd ~/src
git clone git://github.com/kripken/emscripten.git

実行

設定ファイル.emscriptenを編集する必要があります。

まず、em++を引数なしで実行するとホームディレクトリに設定ファイル.emscriptenの雛形が作成されますのでこれを編集すればよいでしょう。

> ~/src/emscripten/em++

==============================================================================
Welcome to Emscripten!

This is the first time any of the Emscripten tools has been run.

A settings file has been copied to ~/.emscripten, at absolute path: /Users/safx/.emscripten

Please edit that file and change the paths to fit your system. Specifically,
make sure LLVM_ROOT and NODE_JS are correct.

This command will now exit. When you are done editing those paths, re-run it.
==============================================================================

とりあえずてきとうに編集して、最低限実行できるようにした.emscriptenは次のようになります。

EMSCRIPTEN_ROOT = os.path.expanduser('~/dev/emscripten')
LLVM_ROOT = os.path.expanduser('~/dev/clang/bin')
NODE_JS = os.path.expanduser('~/dev/node/bin/node')

JAVA = 'java'
TEMP_DIR = '/tmp'
COMPILER_ENGINE = NODE_JS

JS_ENGINES = []

編集後に、再び引数なしでem++を実行するとJava入れろと言われるかもしれません。

Closureを利用するためにはJava VMの導入が必要ですので入れておきましょう。

Hello world

次のようなC++ソースhello.cppがあるとします。

#include <cstdio>
int main(int argc, char** argv) {
    std::printf("hello emscripten!\n");
}

すごくつまらない例ですので、簡単にコンパイルして実行できます。

> ~/dev/emscripten/em++ hello.cpp
> ~/dev/node/bin/node a.out.js 
hello emscripten!

いくつかのオプションはgccと似せてあります。ただし、-oは拡張子によって出力するものが変わります。 -o foo.htmlとすることでキャンバス付きのHTMLを出力します。

> ~/dev/emscripten/em++ -o hello.html hello.cpp  

なお、emccでコンパイルすると次のようなことが行われているようです。

  1. clangでCソースからオブジェクトファイルを得る
  2. llvm-disでオブジェクトファイルからLLVMアセンブリ言語ソースを得る
  3. Emscriptのcompiler.jsでLLVMアセンブリ言語ソースからJavaScriptを得る
  4. (必要ならば) Closureで最適化

より詳細な解説は、Emscript内にある論文や次のURLを参照してください。

まとめ

Emscriptenを導入してHello worldを実行させるまでの手順を紹介しました。

configureとmakeに相当するものとしてそれぞれ、emconfigureとmmakeがあるようです (後者を利用するにはcmakeが必要みたいです)。 また、SDLとOpenGLについてはそれぞれCanvasとWebGLに変換されるようですのでここらへんも試してみたいです。

関連リンク

0 件のコメント:

コメントを投稿

注: コメントを投稿できるのは、このブログのメンバーだけです。