Ubuntu 18.04 下 emscripten SDK 的安装
http://kripken.github.io/emscripten-site/docs/getting_started/downloads.html#installation-instructions需要环境
清华安装源 https://mirrors.tuna.tsinghua.edu.cn/help/ubuntu$ sudo apt update$ sudo apt install vim openssh-server git curl wget tar unzip$ sudo apt install build-essential python cmake default-jre下载源
$ cd ~$ git clone https://github.com/juj/emsdk.git$ cd emsdk更新最新版本$ ./emsdk update安装最新的SDK
安装期间会检查并自动下载缺失的llvm、clang、node、emscripten和sdk等,根据提示会显示下载的压缩包网址和本地的目录,如果下载期间发生错误,无法下载到本地,可以用wget等工具手动下载,放到提示的本地目录(emsdk/zips)里,再次运行这条命令( 当然手动下载好,然后复制到zips也是可以的 $ mkdir ~/emsdk/zips $ mv ~/clang-e1.38.4.tar.gz ~/emsdk/zips/ $ mv ~/llvm-e1.38.4.tar.gz ~/emsdk/zips/ $ mv ~/node-v8.9.1-linux-x64.tar.xz ~/emsdk/zips/ $ mv ~/emscripten-llvm-e1.38.4.tar.gz ~/emsdk/zips/ $ mv ~/1.38.4.tar.gz ~/emsdk/zips/ $ ./emsdk install latest $ rm ~/emsdk/zips/*)$ ./emsdk install latest请耐心等待编译完成。为当前用户配置~/.emscripten文件$ ./emsdk activate latest查看安装列表,安装binaryen
$ ./emsdk list./emsdk install binaryen-tag-1.38.4-64bit./emsdk activate binaryen-tag-1.38.4-64bit为当前会话配置环境变量
$ cd ~/emsdk$ source ./emsdk_env.sh$ cd ~/emsdk$ ./emsdk list查看版本
$ emcc --version$ em++ --version备份
$ cd ~$ tar cvzf emsdk.tar.gz emsdk卸载
$ ./emsdk uninstall <tool/sdk name>完全卸载,删除这个目录即可。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
官方教程的例子~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~emcc 用于编译c/c++源程序,简单格式如下:
$ emcc -O2 hello_world.cpp -s WASM=1 -o hello_world.html(1)优化方案:详细见 指定 -O0 或者不指定优化方案,即不优化。指定 -O1 简单优化,优化asm.js,LLVM -O1,移除掉运行时输出和异常捕获等,如printf、puts等代码。指定 -O2 类似O1,然后会压缩js,LLVM -O3,适合release指定 -O3 类似O2,进一步压缩js,推荐release指定 -Os 类似O3,进一步优化bitcode生成和js代码尺寸指定 -Oz 类似Os,更进一步优化代码(2)键值开关:-s OPTION=value默认WASM=1,如果纯js,请设置WASM=0(3)-o xxx.html会输出xxx.html,否则会输出a.out.js和a.out.wasm(4)更详细的指令见 emcc --help 和 ---------------------------例子1:编译hello, world程序---------------------------$ source ~/emsdk/emsdk_env.sh$ mkdir ~/tests$ cd ~/tests$ vim hello_world.c1 #include2 3 int main() {4 printf("hello, world!\n");5 return 0;6 }
$ emcc hello_world.c
耐心等待,会生成a.out.js,如果发生错误,可以用-v选项编译,输出更多的调试信息。$ ls -altotal 160drwxrwxr-x 2 bob bob 4096 6月 1 14:37 .drwxr-xr-x 19 bob bob 4096 6月 1 14:38 ..-rw-rw-r-- 1 bob bob 101699 6月 1 14:37 a.out.js-rw-rw-r-- 1 bob bob 45389 6月 1 14:37 a.out.wasm-rw-rw-r-- 1 bob bob 75 6月 1 14:35 hello_world.c$ node a.out.jshello, world!通过上面的生成文件,会发现同时生成了wasm,但是有的浏览器不支持wasm,需要指定 -s WASM=0
接下来分别生成支持wasm和不支持wasm的情况,同时生成html$ emcc hello_world.c -o hello.html$ emcc hello_world.c -s WASM=0 -o hello_nowasm.html$ ls -altotal 816Kdrwxrwxr-x 2 bob bob 4.0K 6月 1 14:54 .drwxr-xr-x 19 bob bob 4.0K 6月 1 14:54 ..-rw-rw-r-- 1 bob bob 100K 6月 1 14:37 a.out.js-rw-rw-r-- 1 bob bob 45K 6月 1 14:37 a.out.wasm-rw-rw-r-- 1 bob bob 101K 6月 1 14:54 hello.html-rw-rw-r-- 1 bob bob 100K 6月 1 14:54 hello.js-rw-rw-r-- 1 bob bob 101K 6月 1 14:54 hello_nowasm.html-rw-rw-r-- 1 bob bob 298K 6月 1 14:54 hello_nowasm.js-rw-rw-r-- 1 bob bob 45K 6月 1 14:54 hello.wasm-rw-rw-r-- 1 bob bob 75 6月 1 14:35 hello_world.c分别生成了:第一组:hello.html, hello.js, hello.wasm第二组:hello_nowasm.html, hello_nowasm.js可以用一个httpserver启动,然后用浏览器测试两个页面的效果$ python -m SimpleHTTPServer 8080注:wasm的是不支持file:///方式直接打开。 附:wasm的浏览器支持情况 ----------------------------例子2:SDL API显示到<canvas>----------------------------$ cd ~/tests$ vim hello_world_sdl.cpp1 #include2 #include 3 4 #ifdef __EMSCRIPTEN__ 5 #include 6 #endif 7 8 extern "C" int main(int argc, char** argv) { 9 printf("hello, world!\n");10 11 SDL_Init(SDL_INIT_VIDEO);12 SDL_Surface *screen = SDL_SetVideoMode(256, 256, 32, SDL_SWSURFACE);13 14 #ifdef TEST_SDL_LOCK_OPTS15 EM_ASM("SDL.defaults.copyOnLock = false; SDL.defaults.discardOnLock = true; SDL.defaults.opaqueFrontBuffer = false;");16 #endif17 18 if (SDL_MUSTLOCK(screen)) SDL_LockSurface(screen);19 for (int i = 0; i < 256; i++) {20 for (int j = 0; j < 256; j++) {21 #ifdef TEST_SDL_LOCK_OPTS22 // Alpha behaves like in the browser, so write proper opaque pixels.23 int alpha = 255;24 #else25 // To emulate native behavior with blitting to screen, alpha component is ignored. Test that it is so by outputting26 // data (and testing that it does get discarded)27 int alpha = (i+j) % 255;28 #endif29 *((Uint32*)screen->pixels + i * 256 + j) = SDL_MapRGBA(screen->format, i, j, 255-i, alpha);30 }31 }32 if (SDL_MUSTLOCK(screen)) SDL_UnlockSurface(screen);33 SDL_Flip(screen); 34 35 printf("you should see a smoothly-colored square - no sharp lines but the square borders!\n");36 printf("and here is some text that should be HTML-friendly: amp: |&| double-quote: |\"| quote: |'| less-than, greater-than, html-like tags: | |\nanother line.\n");37 38 SDL_Quit();39 40 return 0;41 }
保存后,可删除其他多余的文件
$ rm `ls|grep -v hello_world_sdl.cpp`编译$ emcc hello_world_sdl.cpp -o hello_sdl.html$ ls -altotal 396drwxrwxr-x 2 bob bob 4096 6月 1 15:40 .drwxr-xr-x 19 bob bob 4096 6月 1 15:41 ..-rw-rw-r-- 1 bob bob 102842 6月 1 15:40 hello_sdl.html-rw-rw-r-- 1 bob bob 233934 6月 1 15:40 hello_sdl.js-rw-rw-r-- 1 bob bob 46133 6月 1 15:40 hello_sdl.wasm-rw-rw-r-- 1 bob bob 1385 6月 1 15:33 hello_world_sdl.cpp -------------------例子3:文件打开操作-------------------$ cd ~/tests$ rm *$ vim hello_world_file.cpp1 #include2 int main() { 3 FILE *file = fopen("hello_world_file.txt", "rb"); 4 if (!file) { 5 printf("cannot open file\n"); 6 return 1; 7 } 8 while (!feof(file)) { 9 char c = fgetc(file);10 if (c != EOF) {11 putchar(c);12 }13 }14 fclose (file);15 return 0;16 }
$ cat<<EOF>hello_world_file.txt
==This data has been read from a file.The file is readable as if it were at the same location in the filesystem, including directories, as in the local filesystem where you compiled the source.==EOF$ emcc hello_world_file.cpp -o hello_file.html --preload-file hello_world_file.txt$ ls -altotal 408drwxrwxr-x 2 bob bob 4096 6月 1 15:53 .drwxr-xr-x 19 bob bob 4096 6月 1 15:53 ..-rw-rw-r-- 1 bob bob 199 6月 1 15:53 hello_file.data-rw-rw-r-- 1 bob bob 102843 6月 1 15:53 hello_file.html-rw-rw-r-- 1 bob bob 234871 6月 1 15:53 hello_file.js-rw-rw-r-- 1 bob bob 50317 6月 1 15:53 hello_file.wasm-rw-rw-r-- 1 bob bob 280 6月 1 15:52 hello_world_file.cpp-rw-rw-r-- 1 bob bob 199 6月 1 15:53 hello_world_file.txt注意那个.data文件,查看文件内容就是hello_world_file.txt的内容$ cat hello_file.data==This data has been read from a file.The file is readable as if it were at the same location in the filesystem, including directories, as in the local filesystem where you compiled the source.==