libc について
Emscripten は C のソースコードをコンパイルする際に、そのコードで利用されている標準ライブラリも JS にコンパイルします。
例えば次の Hello World は、出力のために prtinf を利用しています。この printf は C の標準ライブラリで定義されている関数です。そのためこのコードを実行するには、C の標準ライブラリである libc に含まれる該当部分とリンクされる必要があります。
#include <stdio.h>
int main(int argc, char **argv){
prtinf("Hello, world!\n");
}
Emscripten は libc の変換結果をキャッシュする
JS になった場合も状況は変わりません。ブラウザの提供する API には printf はありません。そのため上記のコードを JS に変換する際には、printf のコードも併せて変換しなければ、実行できません。そのため Emscripten は必ずこのライブラリをコンパイルし、中間コードにした後、対象のコードと一緒に JS へと変換します。
libc は必ず変換されますが、変更はほとんどされないライブラリでもあります。そのため毎回変換を行うのは時間の無駄です。このことから Emscripten は libc の変換結果をキャッシュします。通常は ~/.emscripten_cache
にキャッシュが保存されています。
$ls ~/.emscripten_cache/
dlmalloc.bc libc.bc struct_info.compiled.json
ここでキャッシュされているのは JS ファイルではなく、コンパイル後に生成された中間コードです。これは Emscripten はリンク後 JS に変換を行うためです。
キャッシュをクリアするには
次の場合、キャッシュがクリアされます。
- 使用する Emscripten のバージョンが変更された場合
- emcc に
--clear-cache
オプションをつけて実行した場合
前者は次のように emsdk activate
を実行した場合に該当します。
$ emsdk activate latest
$ source ${EMSCRITEN_INSTALL_DIR}/emsdk_env.sh
後者は次のように emcc を実行すればキャッシュがクリアされます。
$ emcc --clear-cache
WARNING:root:clearing cache
INFO:root:(Emscripten: Running sanity checks)
$ ls ~/.emscripten_cache
ls ${HOME}/.emscripten_cache: No such file or directory
$ emcc -o helloworld.js helloworld.c
WARNING:root:generating system library: libc.bc...
WARNING:root: ok
WARNING:root:generating system library: dlmalloc.bc...
WARNING:root: ok
```
# どんなときに使うのか
ほとんど使うときはありません。
ただ LLVM がアップデートされ、Emscripten が期待しているものと違うものが利用された場合、正しくリンクができず、変換が失敗することがあります。そのような場合は、キャッシュを一旦クリアすると正しく変換されることがあります。