D言語でEmscriptenしたい話

[Emscripten](http://kripken.github.io/emscripten-site/)とは、C/C++をJavaScriptにコンパイルして、
Webブラウザで動かすことができる開発環境、およびプラットフォームのことです。

変換プロセスは以下の通り。

C/C++ →(clang)→ LLVM-IR →(Emscripten)→ JavaScript

Clang LLVMのバックエンドとしてJavaScriptを使っているというわけです。

D言語er的には、DにもLDCというLLVM系のコンパイラがあるので、
DプログラムもJavaScriptにコンパイルできるのでは！？と夢が広がりますね。

# 3年前

EmscriptenとLDCを使えばD言語のSDLゲームがブラウザで動かせる、かも - ABAの日誌
http://aba.hatenablog.com/entry/20130331/p1

↑はLDCに-output-llオプションを付けてLLVM-IRを出力、emccでリンクという方法でした。
今の環境で試したらemccのリンクで失敗。LLVMのバージョン違いが原因？

# 今年

Emscripten対応のldc2を使う、本格的な試みが行われていました。

RUNNING A D GAME IN THE BROWSER
http://code.alaiwan.org/wp/?p=103

dscripten
https://github.com/Ace17/dscripten

さて、Githubの説明にある ./fetch_toolchain を叩いても何故か失敗…。
以下、いろいろ試行錯誤した結果になります。

# Emscripten対応のldc2を作る

fetch_toolchainを参考にしながら環境を作ります。
今回はMacを使いました。

WindowsでもMinGWやcygwinを使えばできるかもしれないですが、
今のところ修羅の道な気がします。

※また、あらかじめJavaSEをインストールしておく必要があります。

## toolchainsディレクトリを用意

llvmのprefixパスのためにツールチェインのディレクトリを作ります。

```
mkdir -p $HOME/toolchains/llvm-js
```

## Emscripten SDK を取得

```
git clone --depth=1 -b master --single-branch https://github.com/kripken/emscripten.git $HOME/toolchains/emscripten
```

## emscripten-llvmをビルド

作業ディレクトリで、emscriptenのllvmとclangを取得

```
git clone --depth=1 -b master --single-branch https://github.com/kripken/emscripten-fastcomp.git emscripten-llvm

git clone --depth=1 -b master --single-branch https://github.com/kripken/emscripten-fastcomp-clang.git emscripten-llvm/tools/clang
```

emscripten-llvmをビルド。

```
mkdir -p bin/emscripten-llvm
cd bin/emscripten-llvm

../../emscripten-llvm/configure --enable-targets=host,js --disable-timestamps --disable-jit --enable-optimized --disable-assertions --enable-bindings=none --disable-docs --prefix=$HOME/toolchains/llvm-js

# 2プロセスでビルド(メモリを大量に食うので控えめに)
make -j2
# ビルド結果をインストール
make install
```

## ldc2をビルド

作業ディレクトリに移動して、ldcを取得。

```
git clone --recursive https://github.com/ldc-developers/ldc.git ldc
git checkout '9566fc58c800aad27b13f2c8d1f4a63b299e0e3e'
```

dscriptenを取得してパッチをあてる。

```
git clone --recursive https://github.com/Ace17/dscripten.git dscripten
patch -d ldc -p1 -i (作業dir)/dscripten/ldc.patch
```

ldc2をビルド

```
mkdir -p bin/ldc
cd bin/ldc

cmake -G "Unix Makefiles" -D "CMAKE_INSTALL_PREFIX=$HOME/toolchains/llvm-js" -D "LLVM_CONFIG=$HOME/toolchains/llvm-js/bin/llvm-config" ../../ldc

# 2プロセスでビルド(メモリを大量に食うので控えめに)
make -j2
# ビルド結果をインストール
make install
```

# デモをビルドしてみる

```
export PATH=$HOME/toolchains/llvm-js/bin:$PATH
export PATH=$HOME/toolchains/emscripten:$PATH
EMMAKEN_JUST_CONFIGURE=1 PATH=$HOME/toolchains/llvm-js/bin:$PATH $HOME/toolchains/emscripten/emcc

cd dscripten
./build_asmjs
```

動作確認用にHTTPサーバーを立てる

```
ruby -run -e httpd ./dscripten -p 8000
```

ブラウザでlocalhost経由で開く

![emsldc.png](https://qiita-image-store.s3.amazonaws.com/0/11172/ad43e7d7-82f9-2b15-7d39-ff7591e1d754.png)

なんかランダムな避けゲーでした。

# 現時点で使えるのはD言語のサブセット

D言語にはその言語仕様を実現するのに結構巨大なDRuntimeが必要ですが、
まだこのEmscripten環境では整備されていません。

dscriptenの /rt 以下に一応それらしきものがありますが…、
まだ必要最小限っていう感じです。今後の拡充に期待ですね。

なので現時点では、[RUNNING A D GAME IN THE BROWSER](http://code.alaiwan.org/wp/?p=103)にも書いてありますが、
動的配列、連想配列、クラス、new演算子、実行時型情報、例外が使えません。
スレッド関連はShared Array Buffer待ちです。

ランタイムフィーチャレベルはC言語相当ということです。
しかしコンパイルタイムの強力なD2仕様はそのまま使えます。

なおライブラリはPhobosは使えないけどSDLは使えるようです。
頑張ればOpenGLも使える？ ちょっと不便だけどゲームは作れそう。

# 余談

昨日 [emscripten night!! #2](https://emsn.connpass.com/event/42375/) というEmscriptenの勉強会が開かれていたそうです。

うえしたは参加してなかったのですが、なかなか濃い話がタイムラインを流れていました。