译:云与苍凉杯本文为Emscripten-WebAssembly专栏系列之一。更多文章请查看专栏。也可以去作者的博客阅读文章。欢迎加入Wasm与emscripten技术交流群,群聊号:939206522,正文如下:如果你只是想入门,Emscripten的使用还是很简单的。本教程将教您从命令行编译Emscripten代码的各种步骤,以及如何使用文件和在Emscripten代码中使用主要编译优化标志。首先要确保您已经下载并安装了Emscripten。根据您的操作系统,下载和安装过程略有不同。Emscripten主要通过emcc(EmscriptenCompilerFrontend)工作。这是一个命令行工具,可以调用编译所需的其他工具。它可以被视为标准编译器(如gcc或clang)的命令行版本。对于wimdows系统,命令行使用emcc,Linux使用./emcc。验证Emscripten第一次使用Emscripten,请使用以下命令验证Emscripten是否安装正确:emcc-v如果有警告,可能是因为缺少某些工具,请到此链接解决如果有没有warningorerror,往下看。运行Emscripten现在您可以使用Emscripten将C/C++代码编译成JavaScript。首先,编写一个要编译为JavaScript的C文件。例如hello_world.c,像这样:#includeintmain(){printf("hello,world!\n");返回0;注意:这是EmscriptenC文件提供的测试集中最简单的一个。要编译这个C文件,只需要在test目录下打开命令行,在文件名后面加上emcc即可。emcctests/hello_world.c注:test目录为Emscripten测试集所在目录。这样会在test目录下生成一个a.out.js文件,你可以使用node来运行这个a.out.js。nodea.out.js将在节点控制台上打印helloworld!向上。如果编译失败,可以在emcctests/hello_world.c后面加一个-v,即变成emcctests/hello_world.c-v,这样会有一些调试信息,大家可以参考一下编译失败的原因。生成HTMLEmscripten可以为刚才的JavaScript输出生成HTML文件,可以使用-o命令指定要输出的html文件名。emcctests/hello_world.c-ohello.html在浏览器中打开这个hello.html。可以看到在这个HTML页面中有一个文本区域,用来显示C代码中printf()函数打印出来的内容。其实这个区域不仅仅可以显示文字。如果您在C代码中调用SDLAPI,您还可以在画布中显示一个彩色立方体。比如测试用例hello_world_cube.cpp就是这样的。那个测试用例的代码是:#include#include#ifdef__EMSCRIPTEN__#include#endifextern"C"intmain(intargc,char**argv){printf("你好,世界!\n");SDL_Init(SDL_INIT_VIDEO);SDL_Surface*screen=SDL_SetVideoMode(256,256,32,SDL_SWSURFACE);#ifdefTEST_SDL_LOCK_OPTSEM_ASM("SDL.defaults.copyOnLock=false;SDL.defaults.discardOnLock=true;SDL.defaults.opaqueFrontBuffer=false;");#endif如果(SDL_MUSTLOCK(屏幕))SDL_LockSurface(屏幕);for(inti=0;i<256;i++){for(intj=0;j<256;j++){#ifdefTEST_SDL_LOCK_OPTS//Alpha的行为就像在浏览器中一样,因此写入适当的不透明像素。intalpha=255;#else//要通过blitting到屏幕来模拟本机行为,alpha分量将被忽略。通过输出//数据来测试它是否如此(并测试它是否被丢弃)intalpha=(i+j)%255;#endif*((Uint32*)screen->pixels+i*256+j)=SDL_MapRGBA(screen->format,i,j,255-i,alpha);}}if(SDL_MUSTLOCK(screen))SDL_UnlockSurface(screen);SDL_Flip(屏幕);printf("你应该看到一个颜色平滑的正方形-没有锐利的线条,只有正方形的边框!\n");printf("这里有一些文本应该是HTML友好的:amp:|&|双引号:|\"|quote:|'|小于,大于,类似html的标签:||\nanotherline.\n");SDL_Quit();return0;}在文件C/C++中,可以使用libc库API的fopen、fclose等来访问文件js运行在浏览器的沙盒环境,不能直接访问本地文件系统,但是Emscripten模拟了一个文件系统,如果你想继续在你的C/C++代码中使用libc的API,访问的文件应该通过以下方式打包到Emscripten虚拟文件系统中预加载或嵌入。在测试集中,hello_world_file.cpp显示了如何加载文件。测试代码和测试文件hello_world_file.txt如下:#includeintmain(){FILE*file=fopen("tests/hello_world_file.txt","rb");if(!file){printf("无法打开文件\n");返回1;}while(!feof(file)){charc=fgetc(file);如果(c!=EOF){putchar(c);}}fclose(文件);返回0;}==此数据已从文件中读取。该文件是可读的,就好像它位于文件系统中的相同位置(包括目录),就像在您编译源代码的本地文件系统中一样。==下面的命令是指定一个数据文件在运行任何编译代码之前预加载到Emscripten的虚拟文件系统中。这种方法非常有用,因为浏览器只能异步获取数据,而许多本机代码(C/C++)使用同步文件API。然后,使用这种方法可以确保代码(C/C++)在数据加载完成之前被编译。编译好的js)不会从Emscripten的虚拟文件系统中取数据,所以不会出错。下面是编译命令:./emcctests/hello_world_file.cpp-ohello.html--preload-filetests/hello_world_file.txt运行生成的HTML,可以看到hello_world_file.txt文件的内容。优化代码默认情况下,与gcc、clang等编译器一样,Emscripten生成的编译代码是不编译优化的。那么,您可以在命令行参数中使用-O1来生成稍微优化的代码。./emcc-O1tests/hello_world.cpp因为编译生成a.out.js的过程其实并不需要优化,所以其实不管加不加-O1,从编译时间(或者说编译速度)来说,你无法分辨。但是真的没有区别吗?大家可以看看生成的a.out.js文件,会发现还是有区别的。-O1的优化有一些小的优化,清除了一些运行时断言,比如在生成的代码中,printf函数会被put替换。如果要编译优化,不仅可以使用-O1,还可以使用-O2,-O2的优化程度更强。你可以试试看,它的编译代码和-O1有很大的不同。Emscripten测试集Emscripten为您提供了大量的测试用例,几乎涵盖了Emscripten的所有功能。这对开发人员来说是一个很好的资源。有关测试集的更多信息,请单击此处。提示和后续步骤本教程告诉您使用Emscripten的第一步,即使用命令行将c/c++代码编译为js或HTML。学习更多关于Emscripten的一些技巧:这个站点上还有许多更高级的教程,例如,关于编译和构建项目、将您的本机代码集成到Web环境中、打包您的代码等。测试集是一个参考如何使用Emscripten的好地方。例如,如果你想了解--pre-js选项是如何工作的,你可以在测试集中搜索--pre-js,通常你会找到几个例子。阅读本网站的settings.js、emcc和emscripten.h部分。阅读本网站上的常见问题解答。Emscripten专题系列文章是emscripten中文站的一部分。第一篇介绍代码的可移植性和局限性第二篇介绍Emscripten的运行环境第三篇第一篇介绍连接C++和JavaScript第三篇第二篇介绍embind第四篇介绍文件和文件系统第六篇介绍Emscripten如何调试代码