emcc(Emscripten Compiler Frontend)介绍
翻译:云荒杯倾
本文是Emscripten-WebAssembly专栏系列文章之一,更多文章请查看专栏。
也可以去作者的博客阅读文章。
欢迎加入Wasm和emscripten技术交流群,群聊号码:939206522。
emcc用于从命令行调用Emscripten的编译器,它实际上是标准编译器gcc或者clang的一个替换。
语法
emcc [options] file ...
这个输入文件file,既可以是clang可以编译的C/C++语言,也可以是二进制形式的llvm bitcode或者人类可读形式的llvm assembly文件。
参数
大部分clang或者gcc的选项(option)都是可以工作的,比如:
# 显示信息
emcc --help
# 显示编译器版本信息
emcc --version
如果想看当前Emscripten中clang版本支持的全部选项列表,可以直接使用命令:
clang --help.
emcc修改的或者emcc中新的选项列在下面:
首先是一些编译优化flag,它们-O0,-O1,-O2,-Os,-Oz,-O3。
-O0:
不进行编译优化(这是默认情况)。当你刚开始移植项目是推荐使用它,因为它会包含许多断言。
-O1:
简单优化。推荐你在既想缩短编译时间又想编译优化时使用。它毕竟比-O2级别的优化编译起来快多了。它会进行asm.js和llvm的-O1进行优化,它会relooping,会删除运行时断言和C++异常捕获,它也会使得-s ALIASING_FUNCTION_POINTERS=1。
想要C++异常捕获重新可用,请设置:-s DISABLE_EXCEPTION_CATCHING=0。
-O2:
和-O1类似,不过多了javascript级别的优化以及一些llvm -O3的优化项。当你想发布项目的时候,推荐使用本级别优化。
-O3:
和-O2类似,不过比-O2又多了一些JavaScript优化,而且编译时间明显比-O2长。这个也推荐在发布版本的时候使用。
-Os:
和-O3类似,不过增加了额外的优化以减小生成的代码体积,代价是比-O3性能差一点。-Os优化会同时影响llvm bitcode 和JavaScript文件的生成。
-Oz:
和-Os类似,不过进一步减小了代码体积。
-s OPTION=VALUE
传给编译器的所有涉及到JavaScript代码生成的选项。选项列表,请见settings.js。
对于某个选项的值,不仅可以直接在emcc命令行里面设定,也可以把他们写成json文件。比如下面,就是将DEAD_FUNCTIONS选项的值放到了path/to/file文件里,emcc里面传这个文件的路径。
-s DEAD_FUNCTIONS=@/path/to/file
note:
1、文件内容可以是:["_func1","_func2"];
2、文件路径必须是绝对的,不能是相对的。
-g:
这是保留调试信息flag。
- 如果只是编译到bitcode,那就和clang和gcc中的-g一样。
- 如果是要编译到JavaScript,-g就等于-g3。
-g<level>
控制打印的调试信息数量,每一个level都是在前一个level的基础上编译的:
- -g0:不保留调试信息。
- -g1:保留空格,不压缩。
- -g2:保留函数名。
- -g3:保留变量名,与-g同。变量名一般不是必须编译后保留的,但是如果保留了,可以推断变量的目的,对吧。
- -g4:保留llvm 调试信息,这是能调试的最高级别。
note:
优化级别越高,编译时间越长
--profiling:
--profiling-funcs:
--tracing:
启用Emscripten的tracing API。
--emit-symbol-map:
--js-opts<level>:
允许JavaScript优化,有两个值:
0:不允许JavaScript优化器允许;
1:使用JavaScript优化器。
通常用不到我们设置这一项, 因为设置-O后面的level的时候,这个项就能顺便取到一个合适的值。
note:
有些选项会重写这个flag的值,比如EMTERPRETIFY, DEAD_FUNCTIONS, OUTLINING_LIMIT, SAFE_HEAP 和 SPLIT_MEMORY会将js-opts=1,因为他们依赖js优化器。
--llvm-opts<level>:
启用llvm优化。它的取值有有:
- 0:不使用llvm优化
- 1:llvm -O1优化
- 2:llvm -O2优化
- 3:llvm -O3优化
和--js-opts<level>一样,通常用不到我们设置这一项, 因为设置-O后面的level的时候,这个项就能顺便取到一个合适的值。
--llvm-lto<level>:
启用llvm 连接时 优化。可以取值0,1,2,3。
--closure <on>:
运行压缩编译器(Closure Compiler),可能的取值有,0,1,2:
- 0:是不启用压缩编译器。
- 1:启用。
- 2:启用。
--pre-js <file>
生成代码前,指定一个要把内容添加进来的文件。
--post-js <file>
生成代码后,指定一个要把内容添加进来的文件。
--embed-file <file>
指定一个带路径的文件嵌入到编译生成的js代码里。路径是相对于编译时的当前路径。如果传的是一个目录,则目录下所有文件的内容都会被嵌入到将来生成的js代码中。
--preload-file <name>
异步运行编译代码前,指定一个预加载的文件。路径是相对于编译时的当前路径。如果传的是一个目录,则目录下所有文件的内容都会被预加载到一个.data文件中。
--exclude-file <name>
从 –embed-file and –preload-file后面的目录中排除一些文件,支持使用通配符*。
--use-preload-plugins
告诉文件打包器当文件加载时,运行预加载插件。它用来执行诸如使用浏览器解码器解码图片和音频等。
--shell-file <path>
指定要生成html的模板文件。
--source-map-base <base-url>
--minify 0
等于-g1。
--js-transform <cmd>
优化之前,生成代码之后,设定这一条命令。这条命令可以让你修改JavaScript代码。之后,编译器会将修改的和未修改的一起进行编译优化。
--bind
启用bingdings编译源代码。bingings是Emscripten中连接C++和JavaScript代码的一类API。
--ignore-dynamic-linking
告诉编译器忽视动态链接,之后用户就得手动链接到共享库。
--js-library <lib>
定义除了核心库(src/library_*)以外的js库。
-v
打开详细输出。
这个设置为把-v传给clang,并且启用EMCC_DEBUG生成编译阶段的中间文件。它也会运行Emscripten关于工具链的内部的完整性检查。
tip:
emcc -v是诊断错误的有用工具,不管你是否附加其他参数。
--cache
--clear-cache
--clear-ports
--show-ports
--save-bc PATH
--memory-init-file <on>
规定是否单独生成一个内存初始化文件。取值包括0和1.
- 0:不单独生成.mem文件。
- 1:单独生成.mem文件。
-Wwarn-absolute-paths
启用在-I和-L命令行指令中使用绝对路径的警告。这是用来警告无意中使用了绝对路径的。在引用非可移植的本地系统头文件时,使用绝对路径有时是很危险的。
--proxy-to-worker
--emrun
使生成的代码能够感知emrun命令行工具。当运行emran生成的应用程序时,这样设置就允许stdout、stderr和exit(returncode)被捕获。
--cpuprofiler
在生成的页面上嵌入一个简单的CPU分析器。使用这个来执行粗略的交互式性能分析。
--memoryprofiler
在生成的页面上嵌入内存分配跟踪器,使用它来分析应用程序Emscripten堆的使用情况。
--threadprofiler
在生成的页面上嵌入一个线程活动分析器。当进行多线程编译时,使用它来分析多线程应用程序。
--em-config
--default-obj-ext .ext
--valid-abspath path
设置一个绝对路径的白名单,以防止关于绝对路径的警告。
-o <target>
编译输出的文件格式。target可以取值为:
- name.js:JavaScript文件;
- name.html:HTML+js文件。把js单独生成是为了减小页面加载时间。
- name.bc:llvm bitcode。这是默认值。
- name.o:和上面一样。
note:
如果你用了--memory-init-file,则还会从js文件中再单独分出一部分代码为.mem文件。
-c
生成llvm bitcode代码,而不是JavaScript。
--separate-asm
把asm.js文件单独生成到一个文件中。这样可以减少启动时的内存加载。
--output_eol windows|linux
规定生成的文本文件的行尾,如果是–output_eol windows,就是windows rn行尾,如果是–output_eol linux,则生成Linux行尾的文本文件。
--cflags
环境变量
emcc会受到几个环境变量的影响,如下:
- EMMAKEN_JUST_CONFIGURE
- EMMAKEN_JUST_CONFIGURE_RECURSE
- EMCONFIGURE_JS
- EMCONFIGURE_CC
- EMMAKEN_CXX
- EMMAKEN_COMPILER
- EMMAKEN_CFLAGS
- EMCC_DEBUG
这几个里面比较有意思的是EMCC_DEBUG。比如,如果你在编译之前设置set EMCC_DEBUG=1,那么编译的时候会把编译过程的调试信息和编译各个阶段的中间文件输出到一个临时目录,这算是给开发者提供一些编译期间的帮助或者说调试信息吧。
Emscripten主题系列文章是emscripten中文站点的一部分内容。
第一个主题介绍代码可移植性与限制
第二个主题介绍Emscripten的运行时环境
第三个主题第一篇文章介绍连接C++和JavaScript
第三个主题第二篇文章介绍embind
第四个主题介绍文件和文件系统
第六个主题介绍Emscripten如何调试代码