Emscripten 编译器前端 (emcc)

Emscripten 编译器前端 (emcc) 用于从命令行调用 Emscripten 编译器。它实际上是标准编译器(如 gccclang)的直接替换。

命令行语法

emcc [options] file...

(请注意,如果要从当前目录运行 emcc,则需要使用 ./emcc。)

输入文件可以是 Clang 可以处理的源代码文件(C 或 C++)、目标文件(由 emcc -c 生成)或 LLVM 汇编文件。

参数

大多数 clang 选项 以及 gcc 选项 都可以使用,例如

# Display this information
emcc --help

# Display compiler version information
emcc --version

要查看 Emscripten 使用的 Clang 版本支持的 Clang 选项的完整列表,请运行 clang --help

emcc 中修改或新增的选项列在下面

-O0

[编译+链接] 无优化(默认)。这是移植项目的推荐设置,因为它包含各种断言。

此选项和其他优化设置在编译和链接期间都有意义。在编译期间,它会影响 LLVM 优化,在链接期间,它会影响 Binaryen 中代码的最终优化以及 JS 的优化。(对于快速增量构建,-O0 最好,而对于发布版本,你应该使用更高的链接设置。)

-O1

[编译+链接] 简单优化。在编译步骤中,这些包括 LLVM -O1 优化。在链接步骤中,这不会包含 -O0 将执行的 JS 中的各种运行时断言。

-O2

[编译+链接] 与 -O1 相同,但启用了更多优化。在链接期间,这还将启用各种 JavaScript 优化。

注意

这些 JavaScript 优化可以通过删除编译器认为没有使用到的内容来减小代码大小,特别是,如果未在 Module 对象上导出运行时的部分,则可能会将其剥离。编译器知道 –pre-js–post-js 中的代码,因此你可以在其中安全地使用运行时。或者,可以使用 EXPORTED_RUNTIME_METHODS,请参阅 src/settings.js

-O3

[编译+链接] 与 -O2 相同,但还包括可能需要更长时间运行的其他优化。

注意

这是发布版本的良好设置。

-Og

[编译+链接] 与 -O1 相同。在未来的版本中,此选项可能会禁用不同的优化以提高可调试性。

-Os

[编译+链接] 与 -O3 相同,但更侧重于代码大小(并且可能会在速度方面做出权衡)。这会影响 Wasm 和 JavaScript。

-Oz

[编译+链接] 与 -Os 相同,但进一步减小代码大小,并且可能需要更长时间运行。这会影响 Wasm 和 JavaScript。

注意

有关优化代码的更多提示,请参阅 优化代码

-sOPTION[=VALUE]

[不同的 OPTION 在不同的阶段影响,大多数在链接时影响] Emscripten 构建选项。有关可用选项,请参阅 src/settings.js

注意

如果没有指定值,它将默认为 1

注意

对于布尔选项,可以使用 NO_ 前缀来反转其含义。例如,-sEXIT_RUNTIME=0 等效于 -sNO_EXIT_RUNTIME=1,反之亦然。在大多数情况下不建议这样做。

注意

列表可以指定为逗号分隔的字符串

-sEXPORTED_FUNCTIONS=foo,bar

注意

我们还支持更旧的列表格式,这些格式涉及更多引号。列表可以使用或不使用每个元素周围的引号,也可以使用或不使用列表周围的方括号。例如,以下所有都等效

-sEXPORTED_FUNCTIONS="foo","bar"
-sEXPORTED_FUNCTIONS=["foo","bar"]
-sEXPORTED_FUNCTIONS=[foo,bar]

注意

对于包含方括号或引号的列表,大多数 shell 需要在列表周围加上引号(”)(以避免出现错误)。下面展示了两个示例

-sEXPORTED_FUNCTIONS="['liblib.so']"
-s"EXPORTED_FUNCTIONS=['liblib.so']"

你还可以指定选项的值将从文件中读取。例如,以下将根据 **path/to/file** 中文件的內容设置 EXPORTED_FUNCTIONS

-sEXPORTED_FUNCTIONS=@/path/to/file

注意

  • 在这种情况下,文件应包含一个符号列表,每行一个。对于旧版用例,也支持 JSON 格式的文件:例如 ["_func1", "func2"]

  • 指定的文件路径必须是绝对路径,而不是相对路径。

  • 文件可能包含注释,其中行的第一个字符为 '#'

注意

选项可以指定为单个参数,使用或不使用 -s 和选项名称之间的空格。例如 -sFOO-s FOO。强烈建议使用不带空格的表示法

-g

[编译+链接] 保留调试信息。

  • 在编译为目标文件时,这与 Clanggcc 中相同,它会在目标文件中添加 DWARF 调试信息。

  • 在链接时,这等效于 -g3

-gseparate-dwarf[=FILENAME]

[如果在编译时传递则与 -g3 相同,否则在链接时应用] 保留调试信息,但放在单独的文件中。这与 -g 相同,但主文件将不包含任何调试信息。相反,调试信息将存在于单独的文件中,如果提供了 FILENAME,则与 Wasm 文件相同,但后缀为 .debug.wasm。虽然主文件不包含任何调试信息,但它确实包含一个指向调试文件位置的 URL,以便 devtools 能够找到它。可以使用 -sSEPARATE_DWARF_URL=URL 来定制该位置(例如,如果你想将它托管在不同的服务器上,这很有用)。

-gsplit-dwarf

启用调试分离,它会在 wasm 目标文件旁边创建分离的 DWARF 目标文件。此选项必须与 -c 一起使用。

-gsource-map

[链接] 使用 LLVM 调试信息(必须存在于目标文件中,即它们应该使用 -g 编译)生成源映射。提供此选项后,.wasm 文件将更新为具有 sourceMappingURL 部分。生成的 URL 格式为:<base-url> + <wasm-file-name> + .map<base-url> 默认为空(这意味着源映射将从与 Wasm 文件相同的目录提供服务)。它可以使用 –source-map-base 更改。

-g<level>

[编译+链接] 控制可调试性级别。每个级别都建立在之前的级别上

  • -g0:不进行任何努力来保持代码可调试。

  • -g1:在链接时,保留 JavaScript 中的空白。

  • -g2:在链接时,保留编译代码中的函数名。

  • -g3:在编译为目标文件时,保留调试信息,包括 JS 空白、函数名以及任何 LLVM 调试信息(DWARF)(这与 -g 相同)。

--profiling

[如果在编译时传递则与 -g2 相同,否则在链接时应用] 在发出 JavaScript 时使用合理的默认值,以使构建可读,但仍然对分析有用。这会设置 -g2(保留空白和函数名),并且还会启用可能会影响性能的优化,否则可能不会在 -g2 中执行。

--profiling-funcs

[链接] 在分析中保留函数名,但在其他情况下,像我们在优化构建中通常做的那样,最小化空白和名称。如果你想根据函数名查看分析器结果,但这并不意味着你要读取发出的代码,这将非常有用。

--tracing

[链接] 启用 Emscripten 跟踪 API

--reproduce=<file.tar>

[编译+链接] 编写包含输入和命令的 tar 文件以重现调用。在共享此文件时,请注意它将包含传递给编译器的任何目标文件、源文件和库。

--emit-symbol-map

[链接] 在 Wasm 中的函数索引和函数名称之间保存一个映射文件。通过将名称存储在侧面的文件中,你可以避免发送名称,并且仍然可以通过将索引转换回名称来重建有意义的堆栈跟踪。

注意

当与 -sWASM=2 一起使用时,将创建两个符号文件。 [name].js.symbols (带有 WASM 符号)和 [name].wasm.js.symbols (带有 ASM.js 符号)。

--emit-minification-map <file>

[链接] 在 emscripten 执行导入/导出缩减的情况下,可以使用此选项输出一个文件,该文件将缩减后的名称映射回其原始名称。此文件的格式为每行一个导入/导出,格式为 <minname>:<origname>

-flto

[编译+链接] 启用链接时优化 (LTO)。

--closure 0|1|2

[链接] 运行 Closure Compiler。可能的取值是

  • 0: 不使用 Closure Compiler(在 -O2 及以下版本中的默认值)。

  • 1: 运行 Closure Compiler。这会极大地减小支持 JavaScript 代码的大小(除 WebAssembly 或 asm.js 之外的所有内容)。请注意,这会显着增加编译时间。

  • 2: 在所有发出的代码上运行 Closure Compiler,甚至在asm.js模式下的asm.js输出上运行。这可以进一步减小代码大小,但会阻止大量的asm.js优化,因此除非你希望不惜一切代价减小代码大小,否则不建议使用。

注意

  • 在使用 Closure 时,请考虑使用 -sMODULARIZE,因为它将全局变量缩减为可能与全局范围内其他变量冲突的名称。 MODULARIZE 将所有输出放入一个函数中(参见 src/settings.js)。

  • 默认情况下,Closure 会缩减 Module 本身的名称!使用 MODULARIZE 也可以解决这个问题。另一种解决方案是在 Closure 编译代码运行之前确保存在名为 Module 的全局变量,因为这样它将重用该变量。

  • 只有在执行 JavaScript 选项(-O2 或更高版本)时才会运行 Closure。

--closure-args=<args>

[链接] 将参数传递给 Closure Compiler。这是 EMCC_CLOSURE_ARGS 的替代方法。

例如,人们可能希望传递一个 externs 文件以避免缩减在 --pre-js--post-js 文件中定义的 JS 函数。要将包含这些不应缩减的公共 API 的 externs.js 文件传递给 Closure,需要添加以下标志: --closure-args=--externs=path/to/externs.js

--pre-js <file>

[链接] 指定一个文件,其内容将在发出代码之前添加,并与发出代码一起优化。请注意,这可能并非 JS 输出中的第一个内容,例如,如果使用 MODULARIZE(参见 src/settings.js)。如果你希望这样,你可以直接将 emscripten 的输出添加到开头;--pre-js 的好处是它将代码与 emscripten 输出的其余部分一起优化,这可以实现更好的死代码消除和缩减,并且应该仅用于此目的。特别是,--pre-js 代码不应该以可能混淆优化器的方式更改 emscripten 的主要输出,例如,使用 --pre-js + --post-js 将所有输出放在内部函数作用域中(参见 MODULARIZE 以了解如何执行此操作)。

–pre-js (但不是 –post-js)对于在 Module 对象上指定内容也很有用,因为它出现在 JS 查看 Module 之前(例如,你可以在其中定义 Module['print'])。

--post-js <file>

[链接] 与 --pre-js 相似,但在发出代码之后发出文件。

--extern-pre-js <file>

[链接] 指定一个文件,其内容将添加到 JavaScript 输出的开头。此文件将添加到最终 JavaScript 输出的开头,完成所有其他工作(包括优化、可选的 MODULARIZE-化、像 SAFE_HEAP 这样的检测等)之后。这与在 emcc 完成运行后将此文件添加到开头相同,只是提供了一种方便的执行方法。(作为比较,--pre-js--post-js 将代码与其他所有内容一起优化,如果运行 MODULARIZE,则将其保留在相同的作用域中,等等)。

--extern-post-js <file>

[链接] 与 --extern-pre-js 相似,但附加到结尾。

--embed-file <file>

[链接] 指定一个文件(带路径)以嵌入到生成的 WebAssembly 模块中。该路径相对于编译时的当前目录。如果这里传递的是一个目录,则其整个内容将被嵌入。

例如,如果命令包含 --embed-file dir/file.dat,则 dir/file.dat 必须相对于运行emcc 的目录存在。

注意

嵌入文件通常比 预加载 更有效率,因为它避免了在运行时复制文件数据。

有关 --embed-file 选项的更多信息,请参见 打包文件

--preload-file <name>

[链接] 指定一个文件,在异步运行已编译代码之前对其进行预加载。该路径相对于编译时的当前目录。如果这里传递的是一个目录,则其整个内容将被嵌入。

预加载的文件存储在 filename.data 中,其中 filename.html 是你正在编译到的主文件。要运行你的代码,你需要 .html.data

注意

此选项类似于 –embed-file,区别在于它只在生成 HTML 时才相关(它使用异步二进制 XHRs),或者是在网页中使用的 JavaScript。

emcc 运行 tools/file_packager 来执行嵌入和预加载文件的实际打包操作。如果你愿意,可以自己运行文件打包程序(参见 使用文件打包程序工具进行打包)。然后,你应该将文件打包程序的输出放在 emcc 的 --pre-js 中,以便它在你的主编译代码之前执行。

有关 --preload-file 选项的更多信息,请参见 打包文件

--exclude-file <name>

[链接] 要从 –embed-file–preload-file 中排除的文件和目录。支持通配符 (*)。

--use-preload-plugins

[链接] 告诉文件打包程序在加载文件时对它们运行预加载插件。这会执行诸如使用浏览器的编解码器解码图像和音频之类的任务。

--shell-file <path>

[链接] 生成 HTML 输出时使用的骨架 HTML 文件的路径名。使用的外壳文件需要在其中包含此标记: {{{ SCRIPT }}}

注意

--source-map-base <base-url>

[链接] 发布 WebAssembly 源映射的位置的基准 URL。必须与 -gsource-map 一起使用。

--minify 0

[如果在编译时传递,则与 -g1 相同,否则在链接时应用] 与 -g1 相同。

--js-transform <cmd>

[链接] 指定一个 <cmd>,在对生成的代码进行优化之前调用它。这使你能够修改 JavaScript,例如添加或删除一些代码,并确保这些修改与生成的代码一起优化。

<cmd> 将与生成的代码的文件名作为参数一起调用。要修改代码,你可以读取原始数据,然后将修改后的数据追加到原始数据中或用修改后的数据覆盖原始数据。

<cmd> 被解释为一个以空格分隔的参数列表,例如,<cmd>python processor.py 将导致运行 Python 脚本。

--bind

[链接] 链接到 embind 库。已弃用:改为使用 -lembind

--embind-emit-tsd <path>

[链接] 生成 TypeScript 定义文件。已弃用:改为使用 --emit-tsd

--emit-tsd <path>

[链接] 为 emscripten 模块生成 TypeScript 定义文件。定义文件将包含导出的 Wasm 函数、运行时导出和导出的 embind 绑定(如果使用)。为了从 embind 生成绑定,程序将被检测并运行在 node 中。

--ignore-dynamic-linking

[链接] 告诉编译器忽略动态链接(用户需要稍后手动链接到共享库)。

通常,emcc 会像静态链接一样简单地链接动态库中的代码,如果多次链接同一个动态库,这将失败。使用此选项,将忽略动态链接,这允许构建系统在没有错误的情况下继续进行。

--js-library <lib>

[链接] 除 Emscripten 的核心库 (src/library_*) 中的库外,还要使用的 JavaScript 库。

-v

[通用] 打开详细输出。

这将打印 emscripten 运行的内部子命令,以及传递给 Clang-v

提示

emcc -v 是诊断错误的有用工具。它可以与其他参数一起使用,也可以不使用其他参数。

--check

[通用] 运行 Emscripten 的内部健全性检查并报告当前配置中的任何问题。

--cache <directory>

[通用] 设置用作 Emscripten 缓存的目录。Emscripten 缓存用于存储 libclibcxx 和其他库的预构建版本。

如果与 --clear-cache 结合使用,请确保首先指定此参数。

Emscripten 缓存默认设置为 emscripten/cache,但可以使用 EM_CACHE 环境变量或 CACHE 配置设置覆盖。

--clear-cache

[通用] 手动清除已编译的 Emscripten 系统库(libc++、libc++abi、libc)的缓存。

这通常由系统自动处理,但如果您就地更新 LLVM(而不是为新版本创建不同的目录),缓存机制可能会出现混乱。清除缓存可以修复与缓存不兼容相关的奇怪问题,例如 Clang 无法链接库文件。这也会清除其他缓存数据。清除缓存后,此进程将退出。

默认情况下,这也会清除任何下载端口,因为端口目录通常位于缓存目录中。

--use-port=<port>

[编译+链接] 使用指定的端口。如果您需要使用多个端口,可以使用此选项多次(例如:--use-port=sdl2 --use-port=bzip2)。端口可以使用 : 分隔的选项(例如:--use-port=sdl2_image:formats=png,jpg)。要使用外部端口,您可以直接提供端口的路径(例如:--use-port=/path/to/my_port.py)。要获取有关端口的更多信息,请使用 help 选项(例如:--use-port=sdl2_image:help)。要获取可用端口的列表,请使用 --show-ports

--clear-ports

[通用] 手动从 Emscripten Ports 仓库(sdl2 等)清除端口的本地副本。这也会清除缓存,以删除它们的构建。

您只需要在发生问题且您希望从头开始下载和构建所有使用的端口时执行此操作。此操作完成后,此进程将退出。

--show-ports

[通用] 显示 Emscripten Ports 仓库中可用项目的列表。此操作完成后,此进程将退出。

-Wwarn-absolute-paths

[编译+链接] 启用有关在 -I-L 命令行指令中使用绝对路径的警告。这用于警告不要有意使用绝对路径,因为在引用不可移植的本地系统头文件时,这有时很危险。

--proxy-to-worker

[链接] 在工作线程中运行主应用程序代码,将事件代理到工作线程,并将输出从工作线程代理出来。如果发出 HTML,则发出一个 **.html** 文件,以及一个包含要在工作线程中运行的 JavaScript 的单独 **.js** 文件。如果发出 JavaScript,则目标文件名将包含要在主线程中运行的部分,而另一个带有“.worker.js”后缀的 **.js** 文件将包含工作线程部分。

--emrun

[链接] 使生成的输出能够识别 emrun 命令行工具。这允许在通过 emrun 运行生成的应用程序时捕获 stdoutstderrexit(returncode)。(这将启用 EXIT_RUNTIME=1,允许使用返回码传递正常运行时退出。)

--cpuprofiler

[链接] 将一个简单的 CPU 分析器嵌入到生成的页面中。使用它来执行粗略的交互式性能分析。

--memoryprofiler

[链接] 将一个内存分配跟踪器嵌入到生成的页面中。使用它来分析应用程序对 Emscripten HEAP 的使用情况。

--threadprofiler

[链接] 将一个线程活动分析器嵌入到生成的页面中。使用它来分析应用程序在针对多线程构建 (-pthread) 时对 pthreads 的使用情况。

--em-config <path>

[通用] 指定 **.emscripten** 配置文件的位置。如果未指定,emscripten 将首先在 emscripten 目录本身中搜索 .emscripten,然后在用户的 home 目录 (~/.emscripten) 中搜索。这可以使用 EM_CONFIG 环境变量覆盖。

--valid-abspath <path>

[编译+链接] 注意允许的绝对路径,我们不应该发出警告(通常会对绝对包含路径发出警告,因为它们可能引用本地系统头文件等,这些头文件在交叉编译时需要避免)。

-o <target>

[链接] 链接可执行文件时,target 文件名扩展名定义要生成的输出类型

  • <name> .js : JavaScript (+ 如果发出 WebAssembly,则为单独的 **<name>.wasm** 文件)。(默认)

  • <name> .mjs : ES6 JavaScript 模块 (+ 如果发出 WebAssembly,则为单独的 **<name>.wasm** 文件)。

  • <name> .html : HTML + 单独的 JavaScript 文件 (**<name>.js**; + 如果发出 WebAssembly,则为单独的 **<name>.wasm** 文件)。

  • <name> .wasm : 没有 JavaScript 支持代码的 WebAssembly(“独立 Wasm”;这将启用 STANDALONE_WASM)。

这些规则仅适用于链接。编译到目标代码时(参见下面的 -c),输出文件的名称无关紧要。

-c

[编译] 告诉 emcc 发出一个目标文件,该文件可以与其他目标文件链接以生成可执行文件。

--output_eol windows|linux

[链接] 指定为输出的文本文件生成的换行符。如果传递 “–output_eol windows”,最终输出文件将包含 Windows rn 换行符。使用 “–output_eol linux”,最终生成的将使用 Unix n 换行符写入文件。

--cflags

[其他] 打印出 emcc 将传递给 clang 以将源代码编译为目标形式的标志。您可以使用它来自己调用 clang,然后仅对最终链接+转换为 JS 的输出运行 emcc

环境变量

emcc 受以下列出的几个环境变量影响

  • EMMAKEN_JUST_CONFIGURE [其他]

  • EMCC_AUTODEBUG [编译+链接]

  • EMCC_CFLAGS [编译+链接]

  • EMCC_CORES [通用]

  • EMCC_DEBUG [通用]

  • EMCC_DEBUG_SAVE [通用]

  • EMCC_FORCE_STDLIBS [链接]

  • EMCC_ONLY_FORCED_STDLIBS [链接]

  • EMCC_LOCAL_PORTS [编译+链接]

  • EMCC_STDERR_FILE [通用]

  • EMCC_CLOSURE_ARGS [链接] 要传递给 Closure Compiler 的参数

  • EMCC_STRICT [通用]

  • EMCC_SKIP_SANITY_CHECK [通用]

  • EM_IGNORE_SANITY [通用]

  • EM_CONFIG [通用]

  • EM_LLVM_ROOT [编译+链接]

  • _EMCC_CCACHE [通用] emsdk 在与 ccache 编译器前端集成时设置为 1 的内部设置

emcc.py 中搜索 “os.environ” 以了解如何使用它们。最有趣的是可能是 EMCC_DEBUG,它强制编译器将其构建和临时文件转储到一个临时目录中,以便可以查看这些文件。