./_static/Emscripten_logo_full.png

Emscripten is a toolchain for compiling to asm.js and WebAssembly, built using LLVM, that lets you run C and C++ on the web at near-native speed without plugins.

Interested to learn more? Read our About Page!


Ready to get started? Download and install the SDK and then proceed to the Tutorial!



Introducing Emscripten

This section explains what Emscripten does, why it is needed, its limitations and its licensing. After reading, you will understand whether Emscripten is the right tool for you, and where to go if you have further questions.

About Emscripten

Emscripten is an Open Source LLVM to JavaScript compiler. Using Emscripten you can:

  • Compile C and C++ code into JavaScript
  • Compile any other code that can be translated into LLVM bitcode into JavaScript.
  • Compile the C/C++ runtimes of other languages into JavaScript, and then run code in those other languages in an indirect way (this has been done for Python and Lua)!

Tip

Emscripten makes native code immediately available on the Web: a platform that is standards-based, has numerous independent compatible implementations, and runs everywhere from PCs to iPads.

With Emscripten, C/C++ developers don’t have the high cost of porting code manually to JavaScript — or having to learn JavaScript at all. Web developers also benefit, as they can use the many thousands of pre-existing native utilities and libraries in their sites.

Practically any portable C or C++ codebase can be compiled into JavaScript using Emscripten, ranging from high performance games that need to render graphics, play sounds, and load and process files, through to application frameworks like Qt. Emscripten has already been used to convert a very long list of real-world codebases to JavaScript, including large projects like CPython, Poppler and the Bullet Physics Engine, as well as commercial projects like the Unreal Engine 4 and the Unity engine. Here are two demos using Unity:

Angrybots game logo
Dead Trigger 2 Game logo

For more demos, see the list on the wiki.

Emscripten generates fast code! Its default output format is asm.js , a highly optimizable subset of JavaScript that can execute at close to native speed in many cases (check out the current benchmark results or run the benchmark tests yourself). Optimized Emscripten code has also been shown to have a similar effective size to native code, when both are gzipped.

For a better understanding of just how fast and fluid Emscripten-ported code can be, check out the Dead Trigger 2 and Angrybots demos above.

Emscripten Toolchain

A high level view of the Emscripten toolchain is given below. The main tool is the Emscripten Compiler Frontend (emcc). This is a drop-in replacement for a standard compiler like gcc.

_images/EmscriptenToolchain.png

Emcc uses Clang and LLVM to compile to wasm or asm.js. Emscripten emits JavaScript that can run that compiled code and provide the necessary runtime support. That JavaScript can be executed by node.js, or from within HTML in a browser.

The Emscripten SDK (emsdk) is used to manage multiple SDKs and tools, and to specify the particular SDK/set of tools currently being used to compile code (the Active Tool/SDK). It can even “install” (download and build) the latest toolchain from GitHub!

Emsdk writes the “active” configuration to the Emscripten Compiler Configuration File (.emscripten). This file is used by emcc to get the correct current toolchain for building.

A number of other tools are not shown — for example, Java can optionally be used by emcc to run the closure compiler, which can further decrease code size.

The whole toolchain is delivered in the Emscripten SDK, and can be used on Linux, Windows or macOS.

Porting code to use Emscripten

Emscripten support for portable C/C++ code is fairly comprehensive. Support for the C standard library, C++ standard library, C++ exceptions, etc. is very good. SDL support is sufficient to run quite a lot of code. OpenGL support in Emscripten support is excellent for OpenGL ES 2.0-type code, and acceptable for other types.

There are differences between the native and Emscripten Runtime Environment, which mean some changes usually need to be made to the native code. That said, many applications will only need to change the way they define their main loop, and also modify their file handling to adapt to the limitations of the browser/JavaScript.

There are also limitations that can make some code easier to port — read Portability Guidelines to determine where you may need to spend more effort.

Community

Welcome to the Emscripten community!

Get in touch

The best ways contact the community are:

  • The GitHub Issue Tracker
  • Mailing list: emscripten-discuss
  • Real-time chat: #emscripten on Discord (there was also an IRC channel on Mozilla IRC, but they are shutting those servers down). We are also open to exploring other options than Discord, if you’re interested to help out, let us know!

Feel free to ask questions, share your ideas, or just join the conversation!

Emscripten also has a presence on social media:

  • #emscripten (Emscripten Hashtag on Twitter)
  • @kripken (an Emscripten developer’s account on Twitter, mentions Emscripten updates)

Report a bug

Bug reports can be posted in the GitHub Issue Tracker.

Contribute

Anyone can contribute to Emscripten. We’ve got some ideas to get you started on our Contributing page!

Open Source License

Emscripten is made available under two permissive open source licenses: the MIT license and the University of Illinois/NCSA Open Source License.

There is little, if any, practical difference between the licenses. They are both offered because the:

  • MIT license is well known and understood.
  • University of Illinois/NCSA Open Source License allows Emscripten’s code to be integrated upstream into LLVM, should the opportunity arise.

The license for Emscripten 1.39.16 (May 19, 2020) is reproduced below. The current full licence can be found on GitHub (and is also present in the root of the SDK).

Emscripten is available under 2 licenses, the MIT license and the
University of Illinois/NCSA Open Source License.

Both are permissive open source licenses, with little if any
practical difference between them.

The reason for offering both is that (1) the MIT license is
well-known, while (2) the University of Illinois/NCSA Open Source
License allows Emscripten's code to be integrated upstream into
LLVM, which uses that license, should the opportunity arise.

The full text of both licenses follows.

==============================================================================

Copyright (c) 2010-2014 Emscripten authors, see AUTHORS file.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

==============================================================================

Copyright (c) 2010-2014 Emscripten authors, see AUTHORS file.
All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
"Software"), to deal with the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

    Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimers.

    Redistributions in binary form must reproduce the above
    copyright notice, this list of conditions and the following disclaimers
    in the documentation and/or other materials provided with the
    distribution.

    Neither the names of Mozilla,
    nor the names of its contributors may be used to endorse
    or promote products derived from this Software without specific prior
    written permission. 

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE.

==============================================================================

This program uses portions of Node.js source code located in src/library_path.js,
in accordance with the terms of the MIT license. Node's license follows:

    """
        Copyright Joyent, Inc. and other Node contributors. All rights reserved.
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to
        deal in the Software without restriction, including without limitation the
        rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
        sell copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:

        The above copyright notice and this permission notice shall be included in
        all copies or substantial portions of the Software.

        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
        FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
        IN THE SOFTWARE.
    """

The musl libc project is bundled in this repo, and it has the MIT license, see
system/lib/libc/musl/COPYRIGHT

The third_party/ subdirectory contains code with other licenses. None of it is
used by default, but certain options use it (e.g., the optional closure compiler
flag will run closure compiler from third_party/).

Release Notes

Changes between tagged Emscripten versions are recorded in the ChangeLog. This log includes high-level information about new features, user-oriented fixes, options, command-line parameters, usage changes, deprecations, significant internal modifications, optimizations, etc. The log for each version links to a detailed diff report, which lists all the incremental changes since the previous release.

In addition, the mailing list is used to announce each new SDK release; these announcements include additional informal release notes and “highlights” information. The easiest way to find these posts is to use this search.

ChangeLog

The ChangeLog for Emscripten 1.39.16 (May 19, 2020) is listed below.

This document describes changes between tagged Emscripten SDK versions.

Note that in the compiler, version numbering is used as the mechanism to
invalidate internal compiler caches, so version numbers do not necessarily
reflect the amount of changes between versions.

To browse or download snapshots of old tagged versions, visit
https://github.com/emscripten-core/emscripten/releases.

Not all changes are documented here. In particular, new features, user-oriented
fixes, options, command-line parameters, usage changes, deprecations,
significant internal modifications and optimizations etc. generally deserve a
mention. To examine the full set of changes between versions, visit the link to
full changeset diff at the end of each section.

See docs/process.md for how version tagging works.

Current Trunk
-------------
- The mmap method of JavaScript filesysem drivers (based on library_fs.js) no
  longer takes a target memory.  Its safer/cleaner/smaller to assume the target
  is the global memory buffer.
- Remove emterpreter and ``EMTERPRETIFY`` settings.  Emterpreter has largerly
  been replaced by asyncify and is fastcomp only so due for removing in
  the near future anyway.

1.39.16: 05/15/2020
-------------------
- Add Math C API for direct access to JavaScript Math object (#11151).
- Address Sanitizer support now includes JavaScript as well, that is, memory
  access of HEAP\* arrays is checked by ASan. That allows errors to be found if
  JS glue code does something wrong like forget to shift a pointer. To use this,
  just build with ASan normally, `-fsanitize=address` at link (#11147).
- Fix embind string conversions in multithreaded builds (#10844).
- `ALLOW_MEMORY_GROWTH` used to silently disable `ABORTING_MALLOC`. It now
  just changes the default, which means you can pass `-s ABORTING_MALLOC=1` to
  override the default, which was not possible before. (If you pass the flag
  and don't want that behavior, stop passing the flag.) (#11131)
- Change the factory function created by using the `MODULARIZE` build option to
  return a Promise instead of the module instance. That is, beforehand

        Module()

  would return an instance (which was perhaps not ready yet if startup was
  async). In the new model, that returns a Promise which you can do `.then` or
  `await` on to get notified when the instance is ready, and the callback
  receives the instance. Note that both before and after this change
  doing `Module()` creates and runs an instance, so the only change is
  the return value from that call.
  This fixes some long-standing bugs with that option which have been reported
  multiple times, but is a breaking change - sorry about that. To reduce the
  risk of confusing breakage, in a build with `ASSERTIONS` we will show a clear
  warning on common errors. For more, see detailed examples for the current
  usage in `src/settings.js` on `MODULARIZE`. (#10697)
- A new `PRINTF_LONG_DOUBLE` option allows printf to print long doubles at full
  float128 precision. (#11130)
- `emscripten_async_queue_on_thread` has been renamed to
  `emscripten_dispatch_to_thread` which no longer implies that it is async -
  the operation is in fact only async if it is sent to another thread, while it
  is sync if on the same one. A new `emscripten_dispatch_to_thread_async`
  function is added which is always async.
- The emscripten cache now lives in a directory called `cache` at the root
  of the emscripten tree by default.  The `CACHE` config setting and the
  `EM_CACHE` environment variable can be used to override this (#11126).
- Honor `CACHE` setting in config file as an alternative to `EM_CACHE`
  environment variable.
- Remove `--cache` command line arg.  The `CACHE` config setting and the
  `EM_CACHE` environment variable can be used to control this.
- Compiling to a file with no suffix will now generate an executable (JS) rather
  than an object file.  This means simple cases like `emcc -o foo foo.c` do the
  expected thing and generate an executable.
- System libraries such as libc and libc++ are now included by default at
  link time rather than selectively included based on the symbols used in the
  input object files.  For small programs that don't use any system libraries
  this might result in slightly slower link times with the old fastcomp
  backend.  In order to exclude these libraries build with `-nostdlib` and/or
  `-nostdlib++`.

1.39.15: 05/06/2020
-------------------
- Add `--extern-pre-js` and `--extern-post-js` emcc flags. Files provided there
  are prepended/appended to the final JavaScript output, *after* all other
  work has been done, including optimization, optional `MODULARIZE`-ation,
  instrumentation like `SAFE_HEAP`, etc. They are the same as prepending/
  appending those files after `emcc` finishes running, and are just a convenient
  way to do that. (For comparison, `--pre-js` and `--post-js` optimize that code
  together with everything else, keep it in the same scope if running
  `MODULARIZE`, etc.).
- Stop defining `FE_INEXACT` and other floating point exception macros in libc,
  since we don't support them. That also prevents musl from including code using
  pragmas that don't make sense for wasm. Ifdef out other uses of those pragmas
  as well, as tip of tree LLVM now fails to compile them on wasm. (#11087)
- Update libcxx and libcxxabi to LLVM 10 release branch (#11038).
- Remove `BINARYEN_PASSES` setting (#11057). We still have
  `BINARYEN_EXTRA_PASSES` (the removed setting completely overrides the set
  of passes from the command line, which doesn't make much sense as some of
  them are mandatory like setting the sbrk ptr).
- Remove `MODULARIZE_INSTANCE` build option (#11037). This was a seldom used
  option that was complicating the logic for `MODULARIZE`. Module instances can
  be created by using `MODULARIZE` and calling the factory function explicitly.
  See the new `--extern-post-js` option added in this release, which can help
  code that used `MODULARIZE_INSTANCE` (you can add an extern post js which
  does `Module = Module();` for example).

1.39.14: 05/01/2020
-------------------
- Update SDL2 to latest in ports, which has recently been updated to include
  upstream 2.0.10.
- Add warning on use of `EMTERPRETIFY` which is soon to be removed.
- Emscripten can now compile assembly files in llvm's .s/.S file format.
- Remove test-only environment variable handling for `EMCC_LEAVE_INPUTS_RAW`.
  The two uses cases in our test code were covered by the `-nostdlib` option.
- Remove untested `CONFIGURE_CC`.  This could be used to override the underlying
  compiler used in emcc/em++ but only during configure tests.  There are other
  ways to control/fake the detected configure features that don't require such
  monkey patching. For example setting defaults via a site file:
  https://www.gnu.org/software/autoconf/manual/autoconf-2.67/html_node/Site-Defaults.html
- Remove undocumented and untested config settings: `COMPILER_OPTS`.  This was
  a global setting in the emscripten config file that would inject extra
  compiler options.
- Allow spaces in a path to Python interpreter when running emscripten from Unix
  shell (#11005).
- Support atexit() in standalone mode (#10995). This also fixes stdio stream
  flushing on exit in that mode.

v1.39.13: 04/17/2020
--------------------
- Support for WebAssembly BigInt integration with a new `WASM_BIGINT` flag. With
  that the VM will use a JS BigInt for a wasm i64, avoiding the need for JS
  legalization. See #10860.
- Add another value for ENVIRONMENT named 'webview' - it is a companion
  option for 'web' and enables some additional compatibility checks
  so that generated code works both in normal web and in a webview like Cordova.
  See #10846

v1.39.12: 04/09/2020
--------------------
- Pass linker flags directly to wasm-ld by default.  We still filter out certain
  flags explicitly.  If there are other flags that it would be useful for us
  to ignore we can add them to the list of ignored flags.
- Optionally support 2GB+ heap sizes. To do this we make the JS code have unsigned
  pointers (we need all 32 bits in them now), which can slightly increase code
  size (>>> instead of >>). This only happens when the heap size may be over
  2GB, which you must opt into explicitly, by setting `MAXIMUM_MEMORY` to a
  higher value (i.e. by default you do not get support for 2GB+ heaps).
  See #10601
- `--llvm-lto` flag is now ignored when using the upstream llvm backend.
  With the upstream backend LTO is controlled via `-flto`.
- Require format string for emscripten_log.
- Program entry points without extensions are now shell scripts rather than
  python programs. See #10729.  This means that `python emcc` no longer works.
  However `emcc`, `emcc.py` and `python emcc.py` all continue to work.
  The reason for this change is that `#!/usr/bin/env python` is no longer
  portable since the python symlink was dropped from Ubuntu 20.04.
- New EM_IMPORT macro to mark C/C++ symbols as imported from outside the module
  (i.e. imported from JS).  Currently we still default to assuming that *all*
  undefined symbols can come from JS, but in the future we hope to mark such
  symbols explicitly to allow the linker to report on genuinely undefined
  symbols.
- Dynamic linking optimizations: Stop emitting unnecessary `fp$` and `g$`
  accessors in main modules, possible in Binaryen thanks to ensuring function
  table indexes are unique (#10741).
- New `JS_MATH` option to use `Math.*` in JS instead of compiled musl (#10821).
- Pass `Module` to Module callback functions like `Module.preRun` (#10777).
- Support not having ports, for packagers of emscripten that don't want
  them (#10810).
- Rename syscalls to have meaningful names (#10750).

v1.39.11: 03/20/2020
--------------------
- The default c++ version is no longer fixed at c++03.  We now fall back to
  clang's default which is currently c++14.
- Remove arc4random function form library.js.  This is a BSD-only library
  function.  Anyone requiring BSD compat should be able to use something like
  https://libbsd.freedesktop.org/.
- Change the meaning of `ASYNCIFY_IMPORTS`: it now contains only new imports
  you add, and does not need to contain the list of default system imports like
  `emscripten_sleep`. There is no harm in providing them, though, so this
  is not a breaking change.
- Enable DWARF support: When compiling with `-g`, normal DWARF emitting happens,
  and when linking with `-g` we preserve that and update it. This is a change
  from before, where we assumed DWARF was unneeded and did not emit it, so this
  can increase the size of debug builds (i.e. builds compiling and/or linking
  with -g). This change is necessary for full debugging support, that is, to
  be able to build with `-g` and use a debugger. Before this change only the
  `-gforce_dwarf` flag enabled DWARF; that flag is now removed. If you want
  the old behavior, build your object files with `-gline-tables-only` (that will
  only add line table info, which is just enough for things like source maps and
  does not include full debug info). For more info and background see #10325.
- Remove hacks from `memset` handling, in particular, in the wasm backend,
  completely remove the JS version of memset from the JS library and from
  `DEFAULT_LIBRARY_FUNCS_TO_INCLUDE`. The regular C version will be linked in
  from compiler_rt normally. A noticeable difference you may see is that
  a JS library cannot add a `__dep` to `memset` - deps only work for JS
  library functions, but now we only have the regular C version. If you hit that
  issue, just add `_memset` to `EXPORTED_FUNCTIONS` (or adjust
  `deps_info.json`).
- Minimal runtime code size optimizations, see #10725, #10724, #10663.
- wasm2js fix for a long-existing but very rare correctness bug, see #10682.
- Use atomics in musl lock/unlock in pthreads builds, which may fix very rare
  pthreads + stdio issues (none have been reported though). See #10670.

v1.39.10: 03/09/2020
--------------------
- Fix a SIMD regression in 1.39.9 (#10658).
- Fix `emscripten_atomic_exchange_u8,16,32,64` (#10657).
- Switch bzip2 to an emscripten-ports mirror.

v1.39.9: 03/05/2020
-------------------
- Add support for -Wall, -Werror, -w, -Wno-error=, -Werror=, for controlling
  internal emscripten errors. The behavior of these flags matches the gcc/clang
  counterparts.
- Rename `TOTAL_MEMORY` to `INITIAL_MEMORY` and `WASM_MEM_MAX` to `MAXIMUM_MEMORY`,
  which are more accurate and match wasm conventions. The old names are still
  supported as aliases.
- Updated of libc++abi and libc++ to llvm 9.0.0 (#10510)
- Refactor syscall interface: Syscalls are no longer variadic (except those
  that are inherently such as open) and no longer take the syscall number as
  arg0.  This should be invisible to most users but will effect any external
  projects that try to implement/emulate the emscripten syscall interface.
  See #10474
- Removed src/library_vr.js, as it was outdated and nonfunctional, and the WebVR
  specification has been obsoleted in favor of the upcoming WebXR specification.
  (#10460)
- Deprecate `WASM_OBJECT_FILES` setting.  There are many standard ways to enable
  bitcode objects (-flto, -flto=full, -flto=thin, -emit-llvm).
- Removed EmscriptenWebGLContextAttributes::preferLowPowerToHighPerformance
  option that has become unsupported by WebGL. Access
  EmscriptenWebGLContextAttributes::powerPreference instead. (#10505)
- When implementing forwarding function aliases in JS libraries, either the
  alias or the target function must contain a signature annotation. (#10550)
- Add an check in Asyncify builds with `ASSERTIONS` that we do not have
  compiled code on the stack when starting to rewind, which is dangerous.
- Implement libc system() for node.js (#10547).
- Standalone mode improvements, time (#10530, #10536), sysconf (#10535),
  getpagesize (#10533), _Exit (#10534)
- Fix many closure compiler warnings (e.g. #10525).
- Avoid unnecessary syscall proxying (#10511).

v1.39.8: 02/14/2020
-------------------
- Add LLD_REPORT_UNDEFINED option that should allow for more detailed
  diagnostics when symbols are undefined at link time.  This currently has
  some limitations and is not enabled by default. For example, EM_JS symbols
  are reported as undefined at link time, as are `__invoke_*` functions.
- wasm2js optimizations. See binaryen#2623.
- WebGPU Compute fixes. Simple examples now work. See #10367.
- Many DWARF debug info fixes. Emitting of DWARF is correct as far as we know,
  including when optimizing (a few passes are disabled for now, but almost all
  work). We still only generate it behind the `-gforce_dwarf` flag for now,
  though (but that should be removed soon).

v1.39.7: 02/03/2020
-------------------
- The checked-in copy of the Closure compiler was removed in favor of getting it
  from npm.  This means that developers now need to run `npm install` after
  checking out emscripten if they want to use closure (--closure).  emsdk users
  are not effected because emsdk runs this as a post install step (#9989).
- Added support for specifying JSDoc minification annotations for Closure in
  JS library, pre and post files. See
  https://github.com/google/closure-compiler/wiki/Annotating-JavaScript-for-the-Closure-Compiler
  (#10272)
- Add new Fibers API for context switching, that supersedes the old coroutine
  API that only ran on fastcomp. See #9859
- Added new linker option -s WASM=2 which produces a dual Wasm+JS build, which
  falls back to using a JavaScript version if WebAssembly is not supported in
  target browser/shell. (#10118)
- Added new linker option -s CLOSURE_WARNINGS=quiet|warn|error that allows aborting
  the build if the Closure compiler produced any warnings.

v1.39.6: 01/15/2020
-------------------
- Development has switched from the "incoming" branch to "master".
- Added new system header <emscripten/heap.h>, which enables querying information
  about the current WebAssembly heap state.
- Reduced default geometric memory overgrowth rate from a very generous 2x factor
  to a more memory conserving +20% factor, and capped maximum reservation to 96MB
  at most.
- Added options MEMORY_GROWTH_GEOMETRIC_STEP and MEMORY_GROWTH_GEOMETRIC_CAP
  to allow customizing the heap growth rates.
- Renamed MEMORY_GROWTH_STEP option to MEMORY_GROWTH_LINEAR_STEP option.
- Added new linker option -s HTML5_SUPPORT_DEFERRING_USER_SENSITIVE_REQUESTS=0
  (default enabled) to allow disabling support for deferred fullscreen mode and
  pointer lock requests for applications that do not need deferring support.

v1.39.5: 12/20/2019
-------------------
- Added support for streaming Wasm compilation in MINIMAL_RUNTIME (off by default)
- All ports now install their headers into a shared directory under
  `EM_CACHE`.  This should not really be a user visible change although one
  side effect is that once a given port is built, its headers are then
  universally accessible, just like the library is universally available as
  `-l<name>`.
- Removed `timestamp` field from mouse, wheel, devicemotion and
  deviceorientation events. The presence of a `timestamp` on these events was
  slightly arbitrary, and populating this field caused a small profileable
  overhead that all users might not care about. It is easy to get a timestamp of
  an event by calling `emscripten_get_now()` or `emscripten_performance_now()`
  inside the event handler function of any event.
- Add fine-grained options for specific legacy browser support,
  `MIN_FIREFOX_VERSION`, `MIN_SAFARI_VERSION`, `MIN_IE_VERSION`,
  `MIN_EDGE_VERSION`, `MIN_CHROME_VERSION`. The existing `LEGACY_VM_SUPPORT`
  option sets all of them to 0, that is, maximal backwards compatibility.
  Note that going forward, we will use these settings in more places, so if
  you do need very old legacy browser support, you may need to set either
  `LEGACY_VM_SUPPORT` or the fine-grained options. For more details see #9937
- Default `DISABLE_DEPRECATED_FIND_EVENT_TARGET_BEHAVIOR` to 1. See #9895.
  With this change the old deprecated HTML5 API event target lookup behavior is
  disabled. There is no "Module.canvas" object, no magic "null" default handling,
  and DOM element 'target' parameters are taken to refer to CSS selectors, instead 
  of referring to DOM IDs. For more information see:
  <https://groups.google.com/forum/#!msg/emscripten-discuss/xScZ_LRIByk/_gEy67utDgAJ>
- WASI API updated from `wasi_unstable` to `wasi_snapshot_preview1`. This
  is mostly an implementation detail, but if you use `STANDALONE_WASM` it means
  that the output of emscripten now requires a runtime with
  `wasi_snapshot_preview1` support.
- `SAFE_STACK` has been removed, as it overlaps with `STACK_OVERFLOW_CHECK`.
   Replace `SAFE_STACK=1` with `STACK_OVERFLOW_CHECK=2` (note the value is 2).
   This also has the effect of enabling stack checking on upstream builds when
   `ASSERTIONS` are enabled (as assertions enable `STACK_OVERFLOW_CHECK=2`).

v1.39.4: 12/03/2019
-------------------
- Remove deprecated `requestFullScreen` method from `library_browser.js`, please
  use `requestFullscreen` (without the capital S).
- Remove deprecated `requestFullScreen` and `cancelFullScreen` from `library_glut.js`
- Remove deprecated `requestFullScreen` and `cancelFullScreen`from `library_glfw.js`
- Fix SDL2_mixer support for ogg vorbis. See #9849
- Various source maps fixes, see #9926 #9882 #9837 #9814

v1.39.3: 11/14/2019
------------------

v1.39.2: 11/06/2019
------------------
 - Archives with missing indexes will now have ranlib run on them automatically
   at link time.  This avoids linker errors when using GNU ar to build archive
   files.
 - `ERROR_ON_MISSING_LIBRARIES` now also applies to internal symbols that start
   with `emscripten_`.  Prior to this change such missing symbols would result
   in a runtime error, now they are reported at compile time.
 - Pthread blocking on the main thread will now warn in the console. If
   `ALLOW_BLOCKING_ON_MAIN_THREAD` is unset then the warning is an error.
 - Add `pthread_tryjoin_np`, which is a POSIX API similar to `pthread_join`
   but without blocking.
 - New function `emscripten_has_asyncify()`.
 - Add support for pthreads in Node.js, using Node Workers. See #9745

v1.39.1: 10/30/2019
-------------------
 - Only MEMFS is included by default, others (NODEFS, IDBFS, WORKERFS, PROXYFS)
   must be linked in explicitly, using `-lnodefs.js`, `-lidbfs.js`',
   `-lworkerfs.js`, `-lproxyfs.js`. See #9645

v1.39.0: 10/18/2019
-------------------
 - The emsdk defaults to the upstream backend (instead of fastcomp) from this
   release onward (but both backends are still fully supported). See
   https://emscripten.org/docs/compiling/WebAssembly.html#backends
 - Add support for overriding `.emscripten` config variables using environment
   variables.  Any config variable `FOO` can be overridden by `EM_FOO` in the
   environment.
 - `-Werror` now also turns warnings in the python driver code into errors.
 - Internal settings have moved from `settings.js` to `settings_internal.js`.
   These are settings that are for internal use only and are not set-able from
   the command line.  If we misclassified any of these please open a bug.
 - `STANDALONE_WASM` mode now supports setting up argv via wasi APIs.
 - `STANDALONE_WASM` mode now supports running static constructors in `_start`.

v1.38.48: 10/11/2019
--------------------
 - Add support for `MAIN_THREAD_EM_ASM` in wasm backend. #9560
 - Add ability to disable FETCH worker in Fastcomp backend via
   `USE_FETCH_WORKER=0`.  This is useful for people who use FETCH, but don't
   perform any synchronous fetches on the main thread. #9567
 - Remove `EMCONFIGURE_JS`. Since #6269 we have set it to "2" which means never
   use native, always use JS.

v1.38.47: 10/02/2019
--------------------
 - Add support for FETCH API in WASM backend. This doesn't support FETCH in the
   main thread (`USE_FETCH_WORKER=0` is enforced). #9490
 - Redefine errno values to be consistent with wasi. This will let us avoid
   needing to convert the values back and forth as we use more wasi APIs.
   This is an ABI change, which should not be noticeable from user code
   unless you use errno defines (like EAGAIN) *and* keep around binaries
   compiled with an older version that you link against. In that case, you
   should rebuild them. See #9545.
 - Removed build option `-s ONLY_MY_CODE` as we now have much better solutions
   for that, like building to a wasm object file or using `STANDALONE_WASM`
   etc. (see
   https://github.com/emscripten-core/emscripten/wiki/WebAssembly-Standalone).
 - Emscripten now supports the config file (.emscripten) being placed in the
   emscripten directory rather that the current user's home directory.
   See #9543

v1.38.46: 09/25/2019
--------------------
 - Rename libpthreads to libpthread to match its normal name on other platforms.
   This change should be completely internal to emscripten.
 - Remove redundant `COMPILER_ENGINE` and `JS_ENGINE` options.  We only support
   node as the compiler engine so just use a single `NODE_JS` option for that.
 - Module.abort is no longer exported by default. It can be exported in the normal
   way using `EXTRA_EXPORTED_RUNTIME_METHODS`, and as with other such changes in
   the past, forgetting to export it will show a clear error in `ASSERTIONS` mode.
 - Remove `EMITTING_JS` flag, and replace it with `STANDALONE_WASM`. That flag indicates
   that we want the wasm to be as standalone as possible. We may still emit JS in
   that case, but the JS would just be a convenient way to run the wasm on the Web
   or in Node.js.
 - `ASYNCIFY_BLACKLIST` and `ASYNCIFY_WHITELIST` now support simple '\*' wildcard matching

v1.38.45: 09/12/2019
--------------------

v1.38.44: 09/11/2019
--------------------
 - Remove Binaryen from the ports system. This means that emscripten will
   no longer automatically build Binaryen from source. Instead, either use
   the emsdk (binaries are provided automatically, just like for LLVM), or
   build it yourself and point `BINARYEN_ROOT` in .emscripten to it. See #9409

v1.38.43: 08/30/2019
---------------------
 - noExitRuntime is no longer a property on the Module object. Use `noExitRuntime`
   instead of `Module.noExitRuntime`.

v1.38.42: 08/19/2019
--------------------
 - Add support for [address sanitizer](https://clang.llvm.org/docs/AddressSanitizer.html)
   and standalone [leak sanitizer](https://clang.llvm.org/docs/LeakSanitizer.html)
   with multiple threads. (#9060, #9076)
 - Remove `ERROR_ON_MISSING_LIBRARIES` setting (it's always on now)
 - Remove the ability to use Python operators in flags that support KB/MB/GB/TB
   suffixes, e.g. `TOTAL_MEMORY`. This means that `-s TOTAL_MEMORY=1024*1024`
   will no longer work. This is done because the mechanism may result in
   execution of arbitrary code via command line flags.

v1.38.41: 08/07/2019
--------------------
 - Remove fastcomp's implementation of Asyncify. This has been deprecated for
   a long time, since we added Emterpreter-Async, and now we have a new Asyncify
   implementation in the upstream wasm backend. It is recommended to upgrade to
   the upstream backend and use Asyncify there if you need it. (If you do still
   need the older version, you can use 1.38.40.)
 - Drop ExitStatus from inheriting from Error(), as that could capture the whole
   global scope, preventing temporary variables at page startup from being garbage
   collected. (#9108)
 - `__builtin_return_address` now requires `-s USE_OFFSET_CONVERTER=1` to work. (#9073)
 - emrun now uses HTTP/1.1 instead of HTTP/1.0.
 - `callMain` is no longer exported by default on Module, to allow better JS
   minification. You must add it to `EXTRA_EXPORTED_RUNTIME_METHODS` if you want
   to call it on Module. (In assertions builds, an error with an explanation is
   shown.)
 - Allow expressions with side effects as `EM_ASM`'s arguments and prohibit
   non-arithmetic arguments (e.g. pointers, functions, arrays, objects). (#9054)
 - `emcc` on Windows now uses native newline byte sequence to get a line to
   print for parse error reporting. (#9088)
 - Internal API update: one can now specialize embind's (un)marshalling for a
   group of types via SFINAE, instead of a single type. (#9089)

v1.38.40: 07/24/2019
--------------------
 - LLVM backend pthread builds no longer use external memory initialization
   files, replacing them with passive data segments.
 - LLVM backend now supports thread local storage via the C extension `__thread`
   and the C11/C++11 keyword `thread_local`. (#8976)
 - Internal API change: Move read, readAsync, readBinary, setWindowTitle from
   the Module object to normal JS variables. If you use those internal APIs,
   you must change `Module.readAsync()/Module['readAsync']()` to `readAsync()`.
   Note that read is also renamed to `read_` (since "`read`" is an API call in
   the SpiderMonkey shell). In builds with ASSERTIONS, an error message is
   shown about the API change. This change allows better JS minification
   (the names read, readAsync etc. can be minified, and if the variables are
   not used they can be removed entirely). Defining these APIs on Module
   (which was never documented or intended, but happened to work) is also
   no longer allowed (but you can override `read_` etc. from JS).

v1.38.39: 07/16/2019
--------------------
 - Add support for [address sanitizer](https://clang.llvm.org/docs/AddressSanitizer.html). (#8884)
   - Currently, only supports one thread without dynamic linking.
 - Rename Bysyncify (the name used during development) to Asyncify. This keeps
   the name consistent with the old ASYNCIFY flag, no need for a new one, as
   they basically do the same thing.

v1.38.38: 07/08/2019
--------------------
 - Add support for standalone [leak sanitizer](https://clang.llvm.org/docs/LeakSanitizer.html). (#8711)

v1.38.37: 06/26/2019
--------------------
 - Set ENV['LANG'] following the user's preferred language (HTTP Accept-Language / navigator.languages[0])
 - `emscripten_run_script_string` now returns C `NULL` instead of the string `null`
   or `undefined` when the result of the `eval` is JavaScript `null` or `undefined`.
 - Add a new system for managing system libraries. (#8780)
   This may require minor changes when performing certain operations:
     - When using `embuilder.py` to build a specific library, the name may have
       changed: for consistency, all library names are prefixed with lib now.
     - `embuilder.py` now only builds the requested library, and not its dependencies
       and certain system libraries that are always built. For example, running
       `embuilder.py build libc` no longer builds `libcompiler_rt` if it hasn't be built.
     - When using `EMCC_FORCE_STDLIBS` with a list of libraries, you must now use
       the simplified names, for example, `libmalloc` and `libpthreads` instead of
       `libdlmalloc` or `libpthreads_stub`. These names will link in the correct
       version of the library: if the build is configured to use `emmalloc`, `libmalloc`
       will mean `libemmalloc`, and if thread support is disabled, `libpthreads` will
       mean `libpthreads_stub`. This allows you to say `libmalloc` or `libpthreads` without
       worrying about which implementation is supposed to be used, and avoid duplicate
       symbols if you used the wrong implementation.
 - LLVM wasm backend pthreads fixes, see #8811, #8718

v1.38.36: 06/15/2019
--------------------

v1.38.35: 06/13/2019
--------------------
 - Include some [waterfall fixes](https://github.com/WebAssembly/waterfall/pull/541)
   for the emsdk builds on linux regarding libtinfo.
 - NOTE: due to a CI failure, builds for mac and windows were not generated.

v1.38.34: 06/01/2019
--------------------
 - Add support for [undefined behavior sanitizer](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html).
    - This allows `emcc -fsanitize=undefined` to work. (#8651)
    - The minimal runtime (`-fsanitize-minimal-runtime`) also works. (#8617)

v1.38.33: 05/23/2019
--------------------
 - First release to use the new chromium build infrastructure
   https://groups.google.com/forum/#!msg/emscripten-discuss/WhDtqVyW_Ak/8DfDnfk0BgAJ
 - Add `emscripten_return_address` which implements the functionality of
   gcc/clang's `__builtin_return_address`. (#8617)

v1.38.32: SKIPPED
-----------------
 - The transition from the old to the new CI occurred around here. To avoid
   ambiguity while both CIs were still generating builds, we just tagged a new
   one (1.38.33) on the new CI and skipped 1.38.32.
 - The transition also moves all builds and downloads away from the old
   mozilla-games infrastructure to the new chromium ones. As a result all links
   to *mozilla-games* URLs will not work (these were never documented, but could
   be seen from the internals of the emsdk; the new emsdk uses the proper new
   URLs, so you can either use the sdk normally or find the URLs from there).

v1.38.31: 04/24/2019
--------------------
 - Change `ino_t/off_t` to 64-bits. (#8467)
 - Add port for bzip2 library (`libbz2.a`). (#8349)
 - Add port for libjpeg library. (#8361)
 - Enable `ERROR_ON_MISSING_LIBRARIES` by default (#8461)

v1.38.30: 03/21/2019
--------------------
 - Remove Module.buffer which was exported by default unnecessarily. This was an
   undocumented internal detail, but in theory, code may have relied on it.
   (#8277)

v1.38.29: 03/11/2019
--------------------

v1.38.28: 02/22/2019
--------------------
 - Option `-s EMTERPRETIFY_WHITELIST` now accepts shell-style wildcards;
   this allows matching static functions with conflicting names that
   the linker distinguishes by appending a random suffix.
 - Normalize mouse wheel delta in `library_browser.js`. This changes the scroll
   amount in SDL, GLFW, and GLUT. (#7968)

v1.38.27: 02/10/2019
--------------------
 - Change how `EMCC_LOCAL_PORTS` works, to be more usable. See #7963
 - Remove deprecated Pointer_stringify (use UTF8ToString instead). See #8011
 - Added a new option `-s DISABLE_DEPRECATED_FIND_EVENT_TARGET_BEHAVIOR=1` that
   changes the lookup semantics of DOM elements in html5.h event handler
   callbacks and WebGL context creation. The new behavior is to use CSS selector
   strings to look up DOM elements over the old behavior, which was somewhat
   ad hoc constructed rules around default Emscripten uses. The old behavior
   will be deprecated and removed in the future. Build with -s ASSERTIONS=1
   to get diagnostics messages related to this transition.
 - Breaking change with -s USE_PTHREADS=1 + -s FETCH=1: When building with
   -o a.html, the generated worker script is now named "a.fetch.js" according
   to the base name of the specified output, instead of having a fixed name
   "fetch-worker.js".

v1.38.26: 02/04/2019
--------------------
 - Fix some pthreads proxying deadlocks. See #7865

v1.38.25: 01/18/2019
--------------------
 - Move kripken/emscripten,emscripten-fastcomp,emscripten-fastcomp-clang to
   emscripten-core/\*

v1.38.24: 01/17/2019
--------------------
 - Perform JS static allocations at compile time (#7850)

v1.38.23: 01/10/2019
--------------------
 - Remove BINARYEN_METHOD: no more support for interpret modes, and if you want
   non-wasm, use WASM=0.
 - Support specifying multiple possible ENVIRONMENTs (#7809)

v1.38.22: 01/08/2019
--------------------
 - Add Regal port. See #7674
 - System libraries have been renamed to include the `lib` prefix.  If you use
   `EMCC_FORCE_STDLIBS` or `EMCC_ONLY_FORCED_STDLIBS` to select system libraries
   you may need to add the `lib` prefix.
 - Rename `pthread-main.js` to `NAME.worker.js`, where `NAME` is the main
   name of your application, that is, if you emit `program.js` then you'll get
   `program.worker.js` (this allows more than one to exist in the same
   directory, etc.).
 - Dynamic linker has been taught to handle library -> library dependencies.

v1.38.21: 11/30/2018
--------------------
 - fastcomp: Remove `runPostSets` function and replace with normal static
   constructor function. See #7579

v1.38.20: 11/20/2018
--------------------
 - Remove SPLIT_MEMORY option.
 - Move getTempRet0/setTempRet0 to be JS library functions rather than
   auto-generated by fastcomp.
 - Change `strptime()`'s handling of the "%c" to match that of `strftime()`.
   This is a breaking change for code which depends on the old definition of
   "%c".

v1.38.19: 11/15/2018
--------------------

v1.38.18: 11/08/2018
--------------------
 - Wasm dynamic linking: Rename `tableBase/memoryBase` to
   `__table_base/__memory_base` (#7467)

v1.38.17: 11/07/2018
--------------------
 - Minify wasm import and export names. This decreases JS and wasm size by
   minifying the identifiers where JS calls into wasm or vice versa, which
   are not minifiable by closure or other JS-only tools. This happens in
   -O3, -Os and above. See #7431

v1.38.16: 11/02/2018
--------------------
 - Breaking change: Do not automatically set EXPORT_ALL for MAIN_MODULES or
   SIDE_MODULES. This means that you must explicitly export things that will
   be called from outside (normally, on EXPORTED_FUNCTIONS), or
   you can manually enable EXPORT_ALL yourself (which returns to the exact
   same behavior as before). This change brings us in line with more standard
   dynamic linking, and will match what the LLVM wasm backend will have.
   See #7312.
 - Invalid -s flags on the command line are now treated as errors.
 - Remove BUILD_AS_SHARED_LIBRARY setting.

v1.38.15: 10/25/2018
--------------------

v1.38.14: 10/22/2018
--------------------
 - Errors are now reported when functions listed in EXPORTED_FUNCTIONS are not
   defined. This can be disabled via ERROR_ON_UNDEFINED_SYMBOLS=0. See #7311.

v1.38.13: 10/10/2018
--------------------
 - Support `-s NO_X=1` as an alias for `-s X=0` and vice versa, which
   simplifies current settings with `NO_`-prefixed names. See #7151.
 - Various `EMULATED_FUNCTION_POINTER` improvements. See #7108, #7128.
 - `ERROR_ON_UNDEFINED_SYMBOLS` is now the default.  See #7196

v1.38.12: 09/03/2018
--------------------
 - Update SDL2 to 2.0.7. See #7016.
 - Optionally build using native object files (wasm backend only).
   For now this is behind a new option flag: `-s WASM_OBJECT_FILES=1`.
   See #6875.

v1.38.11: 08/02/2018
--------------------
 - Support for loading wasm files in the same dir as the JS file, using
   node.js/Web-specific techniques as applicable. See #5368 and followups.
 - Add an API for async side module compilation in wasm. See #6663.
 - Remove builtin Crunch support. See #6827.

v1.38.10: 07/23/2018
--------------------
 - Change the type of `size_t` and friends from int to long. This may have
   noticeable effects if you depend on the name mangling of a function that uses
   `size_t` (like in `EXPORTED_FUNCTIONS`), and you must rebuild source files to
   bitcode (so your bitcode is in sync with the system libraries after they are
   rebuilt with this change). Otherwise this should not have any noticeable
   effects for users. See #5916.

v1.38.9: 07/22/2018
-------------------
 - Fix `Module.locateFile` to resolve relative paths to *.wasm, *.mem and other
   files relatively to the main JavaScript file rather than the current working
   directory (see #5368).
   - Add second argument `prefix` to `Module.locateFile` function that contains
     the path to the JavaScript file where files are loaded from by default.
   - Remove `Module.*PrefixURL` APIs (use `Module.locateFile` instead).

v1.38.8: 07/06/2018
-------------------
 - Fix a regression in 1.38.7 with binaryen no longer bundling binaryen.js
   (which emscripten doesn't need, that's just for handwritten JS users, but
   emscripten did check for its presence).

v1.38.7: 07/06/2018
-------------------
 - Correctness fix for stack handling in `invoke_*()s`. This may add noticeable
   overhead to programs using C++ exceptions and (less likely) setjmp/longjmp -
   please report any issues. See #6666 #6702
 - Deprecate Module.ENVIRONMENT: Now that we have a compile-time option to set
   the environment, also having a runtime one on Module is complexity that we
   are better off without. When Module.ENVIRONMENT is used with ASSERTIONS it
   will show an error to direct users to the new option (-s ENVIRONMENT=web , or
   node, etc., at compile time).
 - Breaking change: Do not export print/printErr by default. Similar to other
   similar changes (like getValue/setValue). We now use out() and err()
   functions in JS to print to stdout/stderr respectively. See #6756.

v1.38.6: 06/13/2018
-------------------

v1.38.5: 06/04/2018
-------------------
 - Update libc++ to 6.0, bringing c++17 support (std::byte etc.)

v1.38.4: 05/29/2018
-------------------
 - Fix asm.js validation regression from 1.38.2.

v1.38.3: 05/25/2018
-------------------
 - Upgrade to LLVM 6.0.1.

v1.38.2: 05/25/2018
--------------------
 - Add ENVIRONMENT option to specify at compile time we only need JS to support
   one runtime environment (e.g., just the web). When emitting HTML, set that to
   web so we emit web code only. #6565
 - Regression in asm.js validation due to cttz optimization #6547

v1.38.1: 05/17/2018
-------------------
 - Remove special-case support for `src/struct_info.compiled.json`: Make it a
   normal cached thing like system libraries, not something checked into the
   source tree.
 - Breaking change: Emit WebAssembly by default. Only the default is changed -
   we of course still support asm.js, and will for a very long time. But
   changing the default makes sense as the recommended output for most use cases
   should be WebAssembly, given it has shipped in all major browsers and
   platforms and is more efficient than asm.js. Build with `-s WASM=0` to
   disable wasm and use asm.js if you want that (or use `-s
   LEGACY_VM_SUPPORT=1`, which emits output that can run in older browsers,
   which includes a bunch of polyfills as well as disables wasm). (#6419)

v1.38.0: 05/09/2018
-------------------

v1.37.40: 05/07/2018
--------------------
 - Fix regression in 1.37.39 on  -s X=@file  parsing (see #6497, #6436)

v1.37.39: 05/01/2018
--------------------
 - Regression: Parsing of `-s X=@file`  broke if the file contains a newline
   (see #6436; fixed in 1.37.40)

v1.37.38: 04/23/2018
--------------------
 - Breaking change: Simplify exception handling, disabling it by default.
   Previously it was disabled by default in -O1 and above and enabled in -O0,
   which could be confusing. You may notice this change if you need exceptions
   and only run in -O0 (since if you test in -O1 or above, you'd see you need to
   enable exceptions manually), in which case you will receive an error at
   runtime saying that exceptions are disabled by default and that you should
   build with `-s DISABLE_EXCEPTION_CATCHING=0` to enable them.
 - Fix regression in 1.37.37 on configure scripts on MacOS (see #6456)

v1.37.37: 04/13/2018
--------------------
 - Regression: configure scripts on MacOS may be broken (see #6456; fixed in 1.37.38)

v1.37.36: 03/13/2018
--------------------

v1.37.35: 02/23/2018
--------------------
 - MALLOC option, allowing picking between dlmalloc (previous allocator and
   still the default) and emmalloc, a new allocator which is smaller and
   simpler.
 - Binaryen update that should fix all known determinism bugs.

v1.37.34: 02/16/2018
--------------------
 - `addFunction` is now supported on LLVM wasm backend, but when being used on
   the wasm backend, you need to provide an additional second argument, a Wasm
   function signature string. Each character within a signature string
   represents a type. The first character represents the return type of a
   function, and remaining characters are for parameter types.
    - 'v': void type
    - 'i': 32-bit integer type
    - 'j': 64-bit integer type (currently does not exist in JavaScript)
    - 'f': 32-bit float type
    - 'd': 64-bit float type
   For asm.js and asm2wasm you can provide the optional second argument, but it
   isn't needed. For that reason this isn't a breaking change, however,
   providing the second argument is recommended so that code is portable across
   all backends and modes.

v1.37.33: 02/02/2018
--------------------

v1.37.32: 01/31/2018
--------------------

v1.37.31: 01/31/2018
--------------------
 - LLVM and clang updates from upstream (5.0svn, close 5.0 release).

v1.37.30: 01/31/2018
--------------------

v1.37.29: 01/24/2018
--------------------

v1.37.28: 01/08/2018
--------------------
 - Breaking change: Don't export the `ALLOC_*` numeric constants by default. As
   with previous changes, a warning will be shown in `-O0` and when `ASSERTIONS`
   are on if they are used.
 - Breaking change: Don't export FS methods by default. As with previous
   changes, a warning will be shown in `-O0` and when `ASSERTIONS` are on, which
   will suggest either exporting the specific methods you need, or using
   `FORCE_FILESYSTEM` which will auto export all the main filesystem methods.
   Aside from using FS methods yourself, you may notice this change when using a
   file package created standalone, that is, by running the file packager
   directly and then loading it at run time (as opposed to telling `emcc` to
   package the files for you, in which case it would be aware of them at compile
   time); you should build with `FORCE_FILESYSTEM` to ensure filesystem support
   for that case.

v1.37.27: 12/24/2017
--------------------
 - Breaking change: Remove the `Runtime` object, and move all the useful methods
   from it to simple top-level functions. Any usage of `Runtime.func` should be
   changed to `func`.

v1.37.26: 12/20/2017
--------------------
 - Breaking change: Change `NO_EXIT_RUNTIME` to 1 by default. This means that by
   default we don't include code to shut down the runtime, flush stdio streams,
   run atexits, etc., which is better for code size. When `ASSERTIONS` is on, we
   warn at runtime if there is text buffered in the streams that should be
   flushed, or atexits are used.
 - Meta-DCE for JS+wasm: remove unused code between JS+wasm more aggressively.
   This should not break valid code, but may break code that depended on unused
   code being kept around (like using a function from outside the emitted JS
   without exporting it - only exported things are guaranteed to be kept alive
   through optimization).

v1.37.24: 12/13/2017
--------------------
 - Breaking change: Similar to the getValue/setValue change from before (and
   with the same `ASSERTIONS` warnings to help users), do not export the
   following runtime methods by default: ccall, cwrap, allocate,
   Pointer_stringify, AsciiToString, stringToAscii, UTF8ArrayToString,
   UTF8ToString, stringToUTF8Array, stringToUTF8, lengthBytesUTF8, stackTrace,
   addOnPreRun, addOnInit, addOnPreMain, addOnExit, addOnPostRun,
   intArrayFromString, intArrayToString, writeStringToMemory,
   writeArrayToMemory, writeAsciiToMemory.

v1.37.23: 12/4/2017
-------------------
 - Breaking change: Do not polyfill Math.{clz32, fround, imul, trunc} by
   default. A new `LEGACY_VM_SUPPORT` option enables support for legacy
   browsers. In `ASSERTIONS` mode, a warning is shown if a polyfill was needed,
   suggesting using that option.
 - Breaking change: Do not export getValue/setValue runtime methods by default.
   You can still use them by calling them directly in code optimized with the
   main file (pre-js, post-js, js libraries; if the optimizer sees they are
   used, it preserves them), but if you try to use them on `Module` then you
   must export them by adding them to `EXTRA_EXPORTED_RUNTIME_METHODS`. In `-O0`
   or when `ASSERTIONS` is on, a run-time error message explains that, if they
   are attempted to be used incorrectly.

v1.37.17: 7/25/2017
------------------
 - Updated to libc++'s "v2" ABI, which provides better alignment for string data
   and other improvements. This is an ABI-incompatible change, so bitcode files
   from previous versions will not be compatible.

v1.37.13: 5/26/2017
-------------------
 - Improved Android support for emrun.
 - Duplicate function elimination fixes (#5186)
 - Fix problem with embinding derived classes (#5193)
 - Fix CMake compiler detection when EMCC_SKIP_SANITY_CHECK=1 is used. (#5145)
 - Implemented GLFW Joystick API (#5175)
 - Fixed a bug with emcc --clear-ports command (#5248)
 - Updated Binaryen to version 33.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.37.12...1.37.13
    - Emscripten-LLVM: no changes.
    - Emscripten-Clang: no changes.

v1.37.12: 5/1/2017
------------------
 - Added emscripten-legalize-javascript-ffi option to LLVM to allow disabling JS FFI mangling
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.37.11...1.37.12
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.37.11...1.37.12
    - Emscripten-Clang: no changes.

v1.37.11: 5/1/2017
------------------
 - Added missing SIGSTKSZ define after musl 1.1.15 update (#5149)
 - Fix emscripten_get_mouse_status (#5152)
 - Fix _mm_set_epi64x() function (#5103)
 - Fix issue with number of gamepads connected at initial page load (#5169, #5170)
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.37.10...1.37.11
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.37.10...1.37.11
    - Emscripten-Clang: https://github.com/emscripten-core/emscripten-fastcomp-clang/compare/1.37.10...1.37.11

v1.37.10: 4/20/2017
-------------------
 - Added stub for pthread_setcancelstate for singlethreaded runs.
 - Fixed an outlining bug on function returns (#5080)
 - Implemented new parallel test runner architecture (#5074)
 - Added Cocos2D to Emscripten ports. (-s USE_COCOS2D=1)
 - Updated Binaryen to version 32, which migrates Emscripten to use the new
   WebAssembly Names section. This is a forwards and backwards breaking change
   with respect to reading debug symbol names in Wasm callstacks. Use of the new
   Names section format first shipped in Emscripten 1.37.10, Binaryen version
   32, Firefox 55, Firefox Nightly 2017-05-18 and Chrome 59; earlier versions
   still used the old format. For more information, see
   https://github.com/WebAssembly/design/pull/984 and
   https://github.com/WebAssembly/binaryen/pull/933.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.37.9...1.37.10
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.37.9...1.37.10
    - Emscripten-Clang: no changes.

v1.37.9: 3/23/2017
------------------
 - Added new build feature -s GL_PREINITIALIZED_CONTEXT=1 which allows pages to
   manually precreate the GL context they use for customization purposes.
 - Added a custom callback hook Module.instantiateWasm() which allows user shell
   HTML file to manually perform Wasm instantiation for preloading and progress
   bar purposes.
 - Added a custom callback hook Module.getPreloadedPackage() to file preloader
   code to allow user shell HTML file to manually download .data files for
   preloading and progress bar purposes.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.37.8...1.37.9
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.37.8...1.37.9
    - Emscripten-Clang: no changes.

v1.37.8: 3/17/2017
------------------
 - Fixed a bug with robust_list initialization on pthreads build mode.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.37.7...1.37.8
    - Emscripten-LLVM: no changes.
    - Emscripten-Clang: no changes.

v1.37.7: 3/15/2017
------------------
 - Updated to LLVM 4.0.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.37.6...1.37.7
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.37.6...1.37.7
    - Emscripten-Clang: https://github.com/emscripten-core/emscripten-fastcomp-clang/compare/1.37.6...1.37.7

v1.37.6: 3/15/2017
------------------
 - Implemented readdir() function for WORKERFS.
 - Fixed bugs with Fetch API (#4995, #5027)
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.37.5...1.37.6
    - Emscripten-LLVM: no changes.
    - Emscripten-Clang: no changes.

v1.37.5: 3/13/2017
------------------
 - Updated musl to version 1.1.15 from earlier version 1.0.5.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.37.4...1.37.5
    - Emscripten-LLVM: no changes.
    - Emscripten-Clang: no changes.

v1.37.4: 3/13/2017
------------------
 - Fixed glGetUniformLocation() to work according to spec with named uniform blocks.
 - Fixed WebAssembly Memory.grow() to work.
 - Switched to 16KB page size from earlier 64KB.
 - Optimize alBufferData() operation.
 - Fixed a resource lookup issue with multiple OpenAL audio contexts.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.37.3...1.37.4
    - Emscripten-LLVM: no changes.
    - Emscripten-Clang: no changes.

v1.37.3: 2/16/2017
------------------
 - Updated Binaryen to version 0x01. First official stable WebAssembly support version. (#4953)
 - Optimized memcpy and memset with unrolling and SIMD, when available.
 - Improved Emscripten toolchain profiler to track more hot code.
 - Added new linker flag -s WEBGL2_BACKWARDS_COMPATIBILITY_EMULATION=1 to allow
   simultaneously targeting WebGL 1 and WebGL 2.
 - Optimize Emscripten use of multiprocessing pools.
 - More WebGL 2 garbage free optimizations.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.37.2...1.37.3
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.37.2...1.37.3
    - Emscripten-Clang: no changes.

v1.37.2: 1/31/2017
------------------
 - Fixed a build error with boolean SIMD types.
 - Improved WebAssembly support, update Binaryen to version 22.
 - Update GL, GLES, GLES2 and GLES3 headers to latest upstream Khronos versions.
 - Implement support for new garbage free WebGL 2 API entrypoints which improve
   performance and reduce animation related stuttering.
 - Fixed a bug where -s USE_PTHREADS builds would not have correct heap size if
   -s TOTAL_MEMORY is not being used.
 - Fixed array type issue that prevented glTexImage3D() and glTexSubImage3D()
   from working.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.37.1...1.37.2
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.37.1...1.37.2
    - Emscripten-Clang: no changes.

v1.37.1: 12/26/2016
-------------------
 - Implemented new Fetch API for flexible multithreaded XHR and IndexedDB
   access.
 - Implemented initial version of new ASMFS filesystem for multithreaded
   filesystem operation.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.37.0...1.37.1
    - Emscripten-LLVM: no changes.
    - Emscripten-Clang: no changes.

v1.37.0: 12/23/2016
-------------------
 - Added support for LLVM sin&cos intrinsics.
 - Fix GLFW mouse button mappings (#4317, #4659)
 - Add support for --emit-symbol-map to wasm
 - Fixed handling of an invalid path in chdir (#4749)
 - Added new EMSCRIPTEN_STRICT mode, which can be enabled to opt in to removing
   support for deprecated behavior.
 - Remove references to Web Audio .setVelocity() function, which has been
   removed from the spec.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.36.14...1.37.0
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.36.14...1.37.0
    - Emscripten-Clang: no changes.

v1.36.14: 11/3/2016
-------------------
 - Added support to emscripten_async_wget() for relative paths.
 - Fixed FS.mkdirTree('/') to work.
 - Updated SDL 2 port to version 12.
 - Added more missing pthreads stubs.
 - Normalize system header includes to use the preferred form #include
   <emscripten/foo.h> to avoid polluting header include namespaces.
 - Fixed a bug where transitioning to fullscreen could cause a stack overflow in GLFW.
 - Added new system CMake option
   -DEMSCRIPTEN_GENERATE_BITCODE_STATIC_LIBRARIES=ON to choose if static
   libraries should be LLVM bitcode instead of .a files.
 - Improved SIMD support to be more correct to the spec.
 - Updated Binaryen to version 18. (#4674)
 - Fixed dlopen with RTLD_GLOBAL parameter.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.36.13...1.36.14
    - Emscripten-LLVM: no changes.
    - Emscripten-Clang: no changes.

v1.36.13: 10/21/2016
--------------------
 - Pass optimization settings to asm2wasm.
 - Fix to exporting emscripten_builtin_malloc() and emscripten_builtin_free()
   when heap is split to multiple parts.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.36.12...1.36.13
    - Emscripten-LLVM: no changes.
    - Emscripten-Clang: no changes.

v1.36.12: 10/20/2016
--------------------
 - Improved Emscripten toolchain profiler with more data. (#4566)
 - Export dlmalloc() and dlfree() as emscripten_builtin_malloc() and
   emscripten_builtin_free() to allow user applications to hook into memory
   allocation (#4603)
 - Improved asm.js -s USE_PTHREADS=2 build mode compatibility when
   multithreading is not supported.
 - Improved WebGL support with closure compiler (#4619)
 - Improved Bianaryen WebAssembly support
 - Added support for GL_disjoint_timer_query extension (#4575)
 - Improved Emscripten compiler detection with CMake (#4129, #4314, #4318)
 - Added support for int64 in wasm.
 - Optimize small constant length memcpys in wasm.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.36.11...1.36.12
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.36.11...1.36.12
    - Emscripten-Clang: no changes.

v1.36.11: 9/24/2016
-------------------
 - Added new runtime functions
   emscripten_sync/async/waitable_run_in_main_runtime_thread() for proxying
   calls with pthreads (#4569)
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.36.10...1.36.11
    - Emscripten-LLVM: no changes.
    - Emscripten-Clang: no changes.

v1.36.10: 9/24/2016
-------------------
 - Improved compiler logging print messages on first run experience. (#4501)
 - Fixed log printing in glFlushMappedBufferRange() and glGetInfoLog()
   functions. (#4521)
 - Added setjmp/longjmp handling for wasm.
 - Improved support for --proxy-to-worker build mode.
 - Improved GLES3 support for glGet() features that WebGL2 does not have. (#4514)
 - Added support for implementation defined glReadPixels() format.
 - Improved WebGL 2 support with closure compilter. (#4554)
 - Implemented support for nanosleep() when building in pthreads mode (#4578)
 - Added support for  llvm_ceil_f64 and llvm_floor_f64 intrinsics.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.36.9...1.36.10
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.36.9...1.36.10
    - Emscripten-Clang: no changes.

v1.36.9: 8/24/2016
------------------
 - Fixed glGet for GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING to work. (#1330)
 - Move the DYNAMICTOP variable from JS global scope to inside the heap so that
   the value is shared to multithreaded applications. This removes the global
   runtime variable DYNAMICTOP in favor of a new variable DYNAMICTOP_PTR.
   (#4391, #4496)
 - Implemented brk() system function.
 - Fixed --output-eol to work with --proxy-to-worker mode.
 - Improved reported error message when execution fails to stack overflow.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.36.8...1.36.9
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.36.8...1.36.9
    - Emscripten-Clang: no changes.

v1.36.8: 8/20/2016
------------------
 - Fixed a memory leak in ctor_evaller.py on Windows (#4446)
 - Migrate to requiring CMake 3.4.3 as the minimum version for Emscripten CMake
   build integration support.
 - Fixed an issue that prevented -s INLINING_LIMIT from working (#4471)
 - Fixed a bug with Building.llvm_nm interpretation of defined symbols (#4488)
 - Add support for DISABLE_EXCEPTION_CATCHING and EXCEPTION_CATCHING_WHITELIST
   options for wasm.
 - Added new emprofile.py script which can be used to profile toolchain wide
   performance. (#4491)
 - Added new linker flag --output-eol, which specifices what kind of line
   endings to generate to the output files. (#4492)
 - Fixed a Windows bug where aborting execution with Ctrl-C might hang
   Emscripten to an infinite loop instead. (#4494)
 - Implement support for touch events to GLUT (#4493)
 - Deprecated unsafe function writeStringToMemory() from src/preamble.js. Using
   stringToUTF8() is recommended instead. (#4497)
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.36.7...1.36.8
    - Emscripten-LLVM: no changes.
    - Emscripten-Clang: no changes.

v1.36.7: 8/8/2016
-----------------
 - Updated to latest upstream LLVM 3.9.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.36.6...1.36.7
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.36.6...1.36.7
    - Emscripten-Clang: https://github.com/emscripten-core/emscripten-fastcomp-clang/compare/1.36.6...1.36.7

v1.36.6: 8/8/2016
-----------------
 - Fixed wheelDelta for MSIE (#4316)
 - Fixed inconsistencies in fullscreen API signatures (#4310, #4318, #4379)
 - Changed the behavior of Emscripten WebGL createContext() to not forcibly set
   CSS style on created canvases, but let page customize the style themselves
   (#3406, #4194 and #4350, #4355)
 - Adjusted the reported GL_VERSION field to adapt to the OpenGL ES
   specifications (#4345)
 - Added support for GLES3 GL_MAJOR/MINOR_VERSION fields. (#4368)
 - Improved -s USE_PTHREADS=1 and --proxy-to-worker linker options to be
   mutually compatible. (#4372)
 - Improved IDBFS to not fail on Safari where IndexedDB support is spotty
   (#4371)
 - Improved SIMD.js support when using Closure minifier. (#4374)
 - Improved glGetString to be able to read fields from WEBGL_debug_renderer_info
   extension. (#4381)
 - Fixed an issue with glFramebufferTextureLayer() not working correctly.
 - Fixed a bug with std::uncaught_exception() support (#4392)
 - Implemented a multiprocess lock to access the Emscripten cache. (#3850)
 - Implemented support for the pointerlockerror event in HTML5 API (#4373)
 - Report WebGL GLSL version number in GL_SHADING_LANGUAGE_VERSION string (#4365)
 - Optimized llvm_ctpop_i32() and conversion of strings from C to JS side
   (#4402, #4403)
 - Added support for the OffscreenCanvas proposal, and transferring canvases to
   offscreen in pthreads build mode, linker flag -s OFFSCREENCANVAS_SUPPORT=0/1
   (#4412)
 - Fixed an issue after updating to new LLVM version that response files passed
   to llvm-link must have forward slashes (#4434)
 - Fixed a memory leak in relooper in LLVM.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.36.5...1.36.6
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.36.5...1.36.6
    - Emscripten-Clang: no changes.

v1.36.5: 5/24/2016
------------------
 - Added support for passing custom messages when running in web worker.
 - Improved fp128 support when targeting WebAssembly.
 - Updated cpuprofiler.js to support tracing time spent in WebGL functions.
 - Fixed an issue with glFenceSync() function call signature (#4260, #4339)
 - Added missing zero argument version of emscripten_sync_run_in_main_thread().
 - Improves support for targeting pthreads when using Closure minifier (#4348).
 - Fixed an issue where pthreads enabled code did not correctly validate as asm.js
 - Fixed an issue with incorrect SIMD.js related imports (#4341)
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.36.4...1.36.5
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.36.4...1.36.5
    - Emscripten-Clang: no changes.

v1.36.4: 5/9/2016
-----------------
 - Added EM_TRUE and EM_FALSE #defines to html5.h.
 - Fixed an issue with GLFW window and framebuffer size callbacks.
 - Added support for more missing WebGL 2 texture formats (#4277)
 - Added support for source files with no extension.
 - Updated emrun.py to latest version, adds support to precompressed content and
   running as just a web server without launching a browser.
 - Updated experimental WebAssembly support to generate 0xb version code.
 - Automatically build Binaryen when needed.
 - Updated libc++ to SVN revision 268153. (#4288)
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.36.3...1.36.4
    - Emscripten-LLVM: no changes.
    - Emscripten-Clang: no changes.

v1.36.3: 4/27/2016
------------------
 - Fixed a deadlock bug with pthreads support.
 - Remove sources from temporary garbage being generated in OpenAL code (#4275)
 - Added support for calling alert() from pthreads code.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.36.2...1.36.3
    - Emscripten-LLVM: no changes.
    - Emscripten-Clang: no changes.

v1.36.2: 4/22/2016
------------------
 - Improve support for targeting WebAssembly with Binaryen.
 - Improve support for LLVM's WebAssembly backend (EMCC_WASM_BACKEND=1
   environment variable).
 - Separate out emscripten cache structure to asmjs and wasm directories.
 - Fix a bug where Emscripten would spawn too many unused python subprocesses (#4158)
 - Optimize Emscripten for large asm.js projects.
 - Added sdl2_net to Emscripten ports.
 - Updated to latest version of the SIMD polyfill (#4165)
 - Fixed an issue with missing texture formats support in GLES 3 (#4176)
 - Added a new WebAssembly linker option -s BINARYEN_IMPRECISE=1 (default=0)
   which mutes potential traps from WebAssembly int div/rem by zero and
   float-to-int conversions.
 - Added support for EXT_color_buffer_float extension.
 - Fixed behavior of SSE shift operations (#4165).
 - Fixed a bug where ctor_evaller.py (-Oz builds) would hang on Windows.
 - Fixed a bug where emscripten_set_main_loop() with EM_TIMING_SETTIMEOUT would
   incorrectly compute the delta times (#4200, #4208)
 - Update pthreads support to latest proposed spec version. (#4212, #4220)
 - Fixed an unresolved symbol linker error in embind (#4225)
 - Fix file_packager.py --use-preload-cache option to also work on Safari and
   iOS (#2977, #4253)
 - Added new file packager option --indexedDB-name to allow specifying the
   database name to use for the cache (#4219)
 - Added DWARF style debugging information.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.36.1...1.36.2
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.36.1...1.36.2
    - Emscripten-Clang: no changes.

v1.36.1: 3/8/2016
-----------------
 - Fixed glfwSetWindowSizeCallback to conform to GLFW2 API.
 - Update OpenAL sources only when the browser window is visible to avoid
   occasional stuttering static glitches when the page tab is hidden. (#4107)
 - Implemented LLVM math intrinsics powi, trunc and floor.
 - Added support for SDL_GL_ALPHA_SIZE in GL context initialization. (#4125)
 - Added no-op stubs for several pthread functions when building without
   pthreads enabled (#4130)
 - Optimize glUniform*fv and glVertexAttrib*fv functions to generate less
   garbage and perform much faster (#4128)
 - Added new EVAL_CTORS optimization pass which evaluates global data
   initializer constructors at link time, which would improve startup time and
   reduce code size of these ctors.
 - Implemented support for OpenAL AL_PITCH option.
 - Implemented new build options -s STACK_OVERFLOW_CHECK=0/1/2 which adds
   runtime stack overrun checks. 0: disabled, 1: minimal, between each frame, 2:
   at each explicit JS side stack allocation call to allocate().
 - Fixed an issue with -s SPLIT_MEMORY mode where an unsigned 32-bit memory
   access would come out as signed. (#4150)
 - Fixed asm.js validation in call handlers to llvm_powi_f*.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.36.0...1.36.1
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.36.0...1.36.1
    - Emscripten-Clang: no changes.

v1.36.0: 2/23/2016
------------------
 - Fixed an OpenAL bug where OpenAL sources would not respect global volume setting.
 - Fixed an issue where alGetListenerf() with AL_GAIN would not return the
   correct value. (#4091)
 - Fixed an issue where setting alListenerf() with AL_GAIN would not set the
   correct value. (#4092)
 - Implemented new JS optimizer "Duplicate Function Elimination" pass which
   collapses identical functions to save code size.
 - Implemented the _Exit() function.
 - Added support for SSE3 and SSSE3 intrinsics (#4099) and partially for SSE 4.1
   intrinsics (#4030, #4101)
 - Added support for -include-pch flag (#4086)
 - Fixed a regex syntax in ccall on Chrome Canary (#4111)
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.35.23...1.36.0
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.35.23...1.36.0
    - Emscripten-Clang: no changes.

v1.35.23: 2/9/2016
------------------
 - Provide $NM environment variable to point to llvm-nm when running
   emconfigure, which helps e.g. libjansson to build (#4036)
 - Fixed glGetString(GL_SHADING_LANGUAGE_VERSION) to return appropriate result
   depending on if running on WebGL1 vs WebGL2, instead of hardcoding the result
   (#4040)
 - Fixed a regression with CMake try_run() possibly failing, caused by the
   addition of CMAKE_CROSSCOMPILING_EMULATOR in v1.32.3.
 - Fixed CMake to work in the case when NODE_JS is an array containing
   parameters to be passed to Node.js. (#4045)
 - Fixed a memory issue that caused the Emscripten memory initializer file
   (.mem.js) to be unnecessarily retained in memory during runtime (#4044)
 - Added support for complex valued mul and div ops.
 - Added new option "Module.environment" which allows overriding the runtime ENVIRONMENT_IS_WEB/ENVIRONMENT_IS_WORKER/ENVIRONMENT_IS_NODE/ENVIRONMENT_IS_SHELL fields.
 - Fixed an issue with SAFE_HEAP methods in async mode (#4046)
 - Fixed WebSocket constructor to work in web worker environment (#3849)
 - Fixed a potential issue with some browsers reporting gamepad axis values outside \[-1, 1\] (#3602)
 - Changed libcxxabi to be linked in last, so that it does not override weakly
   linked methods in libcxx (#4053)
 - Implemented new JSDCE code optimization pass which removes at JS link stage
   dead code that is not referenced anywhere (in addition to LLVM doing this for
   C++ link stage).
 - Fixed a Windows issue where embedding memory initializer as a string in JS
   code might cause corrupted output. (#3854)
 - Fixed an issue when spaces are present in directory names in response files
   (#4062)
 - Fixed a build issue when using --tracing and -s ALLOW_MEMORY_GROWTH=1
   simultaneously (#4064)
 - Greatly updated Emscripten support for SIMD.js intrinsics (non-SSE or NEON)
 - Fixed an issue where compiler would not generate a link error when JS library
   function depended on a nonexisting symbol. (#4077)
 - Removed UTF16 and UTF32 marshalling code from being exported by default.
 - Removed the -s NO_BROWSER linker option and automated the detection of when
   that option is needed.
 - Removed the JS implemented C++ symbol name demangler, now always depend on
   the libcxxabi compiled one.
 - Fixed an issue where Emscripten linker would redundantly generate missing
   function stubs for some functions that do exist.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.35.22...1.35.23
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.35.22...1.35.23
    - Emscripten-Clang: no changes.

v1.35.22: 1/13/2016
-------------------
 - Updated to latest upstream LLVM trunk as of January 13th.
 - Bumped up the required LLVM version from LLVM 3.8 to LLVM 3.9.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.35.21...1.35.22
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.35.21...1.35.22
    - Emscripten-Clang: https://github.com/emscripten-core/emscripten-fastcomp-clang/compare/1.35.21...1.35.22

v1.35.21: 1/13/2016
-------------------
 - Improved support for handling GLFW2 keycodes.
 - Improved emranlib, system/bin/sdl-config and system/bin/sdl2-config to be
   executable in both python2 and python3.
 - Fixed build flags -s AGGRESSIVE_VARIABLE_ELIMINATION=1 and -s USE_PTHREADS=2
   to correctly work when run on a browser that does not support pthreads.
 - Fixed a build issue that caused sequences of \r\r\n to be emitted on Windows.
 - Fixed an issue that prevented building LLVM on Visual Studio 2015
   (emscripten-fastcomp-clang #7)
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.35.20...1.35.21
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.35.20...1.35.21
    - Emscripten-Clang: https://github.com/emscripten-core/emscripten-fastcomp-clang/compare/1.35.20...1.35.21

v1.35.20: 1/10/2016
-------------------
 - Fixed -s USE_PTHREADS compilation mode to account that SharedArrayBuffer
   specification no longer allows futex waiting on the main thread. (#4024)
 - Added new python2 vs python3 compatibility wrappers for emcmake, emconfigure, emmake and emar.
 - Fixed atomicrmw i64 codegen (#4025)
 - Optimized codegen to simplify "x != 0" to just "x" when output is a boolean.
 - Fixed a compiler crash when generating atomics code in debug builds of LLVM.
 - Fixed a compiler crash when generating SIMD.js code that utilizes
   non-canonical length vectors (e.g. <float x 3>)
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.35.19...1.35.20
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.35.19...1.35.20
    - Emscripten-Clang: no changes.

v1.35.19: 1/7/2016
------------------
 - Updated to latest upstream LLVM trunk as of January 7th.
 - Full list of changes:
    - Emscripten: no changes.
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.35.18...1.35.19
    - Emscripten-Clang: https://github.com/emscripten-core/emscripten-fastcomp-clang/compare/1.35.18...1.35.19

v1.35.18: 1/7/2016
------------------
 - Implemented getpeername() and fixed issues with handling getsockname() (#3997)
 - Fixed an issue with daylight saving time in mktime() (#4001)
 - Optimized pthreads code to avoid unnecessary FFI transitions (#3504)
 - Fixed issues with strftime() (#3993)
 - Deprecated memory growth support in asm.js.
 - Implemented llvm_bitreverse_i32() (#3976)
 - Fixed missing include header that affected building relooper on some compilers.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.35.17...1.35.18
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.35.17...1.35.18
    - Emscripten-Clang: no changes.

v1.35.17: 1/4/2016
------------------
 - Updated to latest upstream LLVM trunk as of January 4th.
 - Full list of changes:
    - Emscripten: no changes.
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.35.16...1.35.17
    - Emscripten-Clang: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.35.16...1.35.17

v1.35.16: 1/4/2016
------------------
 - Improved support for -s USE_PTHREADS=2 build mode and added support for Atomics.exchange().
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.35.15...1.35.16
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.35.15...1.35.16
    - Emscripten-Clang: no changes.

v1.35.15: 1/4/2016
------------------
 - Fixed an error with glClearbufferfv not working. (#3961)
 - Improved file packager code so that file:// URLs work in Chrome too (#3965)
 - Fixed issues with the --memoryprofiler UI.
 - Fixed a Windows issue when generating system libraries in cache (#3939)
 - Fixed a regression from v1.35.13 where GLES2 compilation would not work when
   -s USE_PTHREADS=1 was passed.
 - Added support for WebIDL arrays as input parameters to WebIDL binder.
 - Updated build support when using the LLVM wasm backend.
 - Added new linker option --threadprofiler which generates a threads dashboard
   on the generated page for threads status overview. (#3971)
 - Improved backwards compatibility of building on GCC 4.3 - 4.6.
 - Fixed an asm.js validation issue when building against updated SIMD.js specification. (#3986)
 - Improved Rust support.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.35.14...1.35.15
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.35.14...1.35.15
    - Emscripten-Clang: no changes.

v1.35.14: 12/15/2015
--------------------
 - Updated to latest upstream LLVM trunk as of December 15th.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.35.13...1.35.14
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.35.13...1.35.14
    - Emscripten-Clang: https://github.com/emscripten-core/emscripten-fastcomp-clang/compare/1.35.13...1.35.14

v1.35.13: 12/15/2015
--------------------
 - Updated -s USE_PTHREADS code generation to reflect that the SharedInt*Array
   hierarchy no longer exists in the SharedArrayBuffer spec.
 - Removed references to Atomic.fence() which no longer is part of the
   SharedArrayBuffer specification.
 - Fixed an issue where JS code minifiers might generate bad code for cwrap
   (#3945)
 - Updated compiler to issue a warning when --separate-asm is being used and
   output suffix is .js.
 - Added new build option -s ONLY_MY_CODE which aims to eliminate most of the
   Emscripten runtime and generate a very minimal compiler output.
 - Added new build option -s WASM_BACKEND=0/1 which controls whether to utilize
   the upstream LLVM wasm emitting codegen backend.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.35.12...1.35.13
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.35.12...1.35.13
    - Emscripten-Clang: no changes.

v1.35.12: 11/28/2015
--------------------
 - Update to latest upstream LLVM trunk as of November 28th.
 - Fix Emscripten to handle new style format outputted by llvm-nm.
 - Added new build option BINARYEN_METHOD to allow choosing which wasm
   generation method to use.
 - Updates to Binaryen support.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.35.11...1.35.12
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.35.11...1.35.12
    - Emscripten-Clang: https://github.com/emscripten-core/emscripten-fastcomp-clang/compare/1.35.11...1.35.12

v1.35.11: 11/27/2015
--------------------
 - Updated atomics test to stress 64-bit atomics better (#3892)
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.35.10...1.35.11
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.35.10...1.35.11
    - Emscripten-Clang: no changes.

v1.35.10: 11/25/2015
--------------------
 - Integration with Binaryen.
 - Add a performance warning when multiple FS.syncfs() calls are in flight simultaneously.
 - Correctly pass GLFW_REPEAT when sending key press repeats.
 - Improved filesystem performance when building in multithreaded mode (#3923)
 - Improve error detection when data file fails to load.
 - Clarified that -s NO_DYNAMIC_EXECUTION=1 and -s RELOCATABLE=1 build modes are mutually exclusive.
 - Added new build option -s NO_DYNAMIC_EXECUTION=2 which demotes eval() errors
   to warnings at runtime, useful for iterating fixes in a codebase for multiple
   eval()s  (#3930)
 - Added support to Module.locateFile(filename) to locate the pthread-main.js file (#3500)
 - Changed -s USE_PTHREADS=2 and -s PRECISE_F32=2 to imply --separate-asm
   instead of requiring it, to be backwards compatible (#3829, #3933)
 - Fixed bad codegen for some 64-bit atomics (#3892, #3936)
 - When emitting NaN canonicalization warning, also print the location in code
   where it occurs.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.35.9...1.35.10
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.35.9...1.35.10
    - Emscripten-Clang: no changes.

v1.35.9: 11/12/2015
-------------------
 - Implement glfwSetInputMode when mode is GLFW_CURSOR and value is GLFW_CURSOR_NORMAL|GLFW_CURSOR_DISABLED
 - Add explicit abort() when dlopen() is called without linking support
 - Make emcc explicitly reinvoke itself from python2 if called from python3.
 - Optimize memory initializer to omit zero-initialized values (#3907)
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.35.8...1.35.9
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.35.8...1.35.9
    - Emscripten-Clang: no changes.

v1.35.8: 11/10/2015
-------------------
 - Removed obsoleted EXPORTED_GLOBALS build option.
 - Export filesystem as global object 'FS' in Emscripten runtime.
 - Fixed realpath() function on directories.
 - Fixed round() and roundf() to work when building without -s PRECISE_F32=1 and
   optimize these to be faster (#3876)
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.35.7...1.35.8
    - Emscripten-LLVM: no changes.
    - Emscripten-Clang: no changes.

v1.35.7: 11/4/2015
------------------
 - Updated to latest upstream LLVM trunk version as of November 4th.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.35.6...1.35.7
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.35.6...1.35.7
    - Emscripten-Clang: https://github.com/emscripten-core/emscripten-fastcomp-clang/compare/1.35.6...1.35.7

v1.35.6: 11/4/2015
------------------
 - This tag was created for technical purposes, and has no changes compared to
   v1.35.6.

v1.35.5: 11/4/2015
------------------
 - Removed Content-Length and Connection: close headers in POST requests.
 - Migrate to using the native C++11-implemented optimizer by default.
 - Fixed call to glDrawBuffers(0, *); (#3890)
 - Fixed lazy file system to work with closure (#3842)
 - Fixed gzip compression with lazy file system (#3837)
 - Added no-op gracefully failing stubs for process spawn functions (#3819)
 - Clarified error message that memory growth is not supported with shared modules (#3893)
 - Initial work on wasm support in optimizer
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.35.4...1.35.5
    - Emscripten-LLVM: no changes.
    - Emscripten-Clang: no changes.

v1.35.4: 10/26/2015
-------------------
 - Move to legalization in the JS backend.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.35.3...1.35.4
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.35.3...1.35.4
    - Emscripten-Clang: https://github.com/emscripten-core/emscripten-fastcomp-clang/compare/1.35.3...1.35.4

v1.35.3: 10/26/2015
-------------------
 - Ignore O_CLOEXEC on NODEFS (#3862)
 - Improved --js-library support in CMake by treating these as libraries (#3840)
 - Still support -Wno-warn-absolute-paths (#3833)
 - Add support to zext <4 x i1> to <4x i32>
 - Emit emscripten versions of llvm and clang in clang --version
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.35.2...1.35.3
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.35.2...1.35.3
    - Emscripten-Clang: https://github.com/emscripten-core/emscripten-fastcomp-clang/compare/1.35.2...1.35.3

v1.35.2: 10/20/2015
-------------------
 - Rebase against upstream LLVM "google/stable" branch, bringing us to LLVM 3.8.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.35.1...1.35.2
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.35.1...1.35.2
    - Emscripten-Clang: https://github.com/emscripten-core/emscripten-fastcomp-clang/compare/1.35.1...1.35.2

v1.35.1: 10/20/2015
-------------------
 - Fixed a bug where passing -s option to LLVM would not work.
 - Work around a WebAudio bug on WebKit "pauseWebAudio failed: TypeError: Not
   enough arguments" (#3861)
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.35.0...1.35.1
    - Emscripten-LLVM: no changes.
    - Emscripten-Clang: no changes.

v1.35.0: 10/19/2015
-------------------
 - Fixed out of memory abort message.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.34.12...1.35.0
    - Emscripten-LLVM: no changes.
    - Emscripten-Clang: no changes.

v1.34.12: 10/13/2015
--------------------
 - Added new experimental build option -s SPLIT_MEMORY=1, which splits up the
   Emscripten HEAP to multiple smaller slabs.
 - Added SDL2_ttf to Emscripten ports.
 - Added support for building GLES3 code to target WebGL 2. (#3757, #3782)
 - Fixed certain glUniform*() functions to work properly when called in
   conjunction with -s USE_PTHREADS=1.
 - Fixed support for -l, -L and -I command line parameters to accept a space
   between the path, i.e. "-l SDL". (#3777)
 - Fixed SSE2 support in optimized builds.
 - Changed the default behavior of warning when absolute paths are passed to -I
   to be silent. To enable the absolute paths warning, pass
   "-Wwarn-absolute-paths" flag to emcc.
 - Added new linker option -s ABORTING_MALLOC=0 that can be used to make
   malloc() return 0 on failed allocation (Current default is to abort execution
   of the page on OOM) (#3822)
 - Removed the default behavior of automatically decoding all preloaded assets on page startup (#3785)
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.34.11...1.34.12
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.34.11...1.34.12
    - Emscripten-Clang: no changes.

v1.34.11: 9/29/2015
-------------------
 - Fixed asm.js validation on autovectorized output
 - Fix an issue with printing to iostream in global ctors (#3824)
 - Added support for LLVM pow intrinsics with integer exponent.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.34.10...1.34.11
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.34.10...1.34.11
    - Emscripten-Clang: no changes.

v1.34.10: 9/25/2015
-------------------
 - Added wasm compressor/decompressor polyfill (#3766)
 - Added support for sRGB texture formats.
 - Removed the deprecated --compression option.
 - Fixed an issue with asm.js validation for pthreads being broken since v1.34.7 (#3719)
 - Added built-in cpu performance profiler, which is enabled with linker flag --cpuprofiler. (#3781)
 - Added build-in memory usage profiler, which is enabled with linker flag --memoryprofiler. (#3781)
 - Fixed multiple arities per EM_ASM block (#3804)
 - Fixed issues with SSE2 an NaN bit patterns. (emscripten-fastcomp #116)
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.34.9...1.34.10
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.34.9...1.34.10
    - Emscripten-Clang: no changes.

v1.34.9: 9/18/2015
------------------
 - Fixed an issue with --llvm-lto 3 builds (#3765)
 - Optimized LZ4 compression
 - Fixed a bug where glfwCreateWindow would return success even on failure
   (#3764)
 - Greatly optimized the -s SAFE_HEAP=1 linker flag option by executing the heap
   checks in asm.js side instead.
 - Fixed the return value of EM_ASM_DOUBLE (#3770)
 - Implemented getsockname syscall (#3769)
 - Don't warn on unresolved symbols when LINKABLE is specified.
 - Fixed various issues with SSE2 compilation in optimized builds.
 - Fixed a breakage with -s USE_PTHREADS=2 (#3774)
 - Added support for GL_HALF_FLOAT in WebGL 2. (#3790)
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.34.8...1.34.9
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.34.8...1.34.9
    - Emscripten-Clang: no changes.

v1.34.8: 9/9/2015
-----------------
 - Fixed a race condition at worker startup (#3741)
 - Update emrun to latest, which improves unit test run automation with emrun.
 - Added support for LZ4 compressing file packages, used with the -s LZ4=1 linker flag. (#3754)
 - Fixed noisy build warning on "unexpected number of arguments in call to strtold" (#3760)
 - Added new linker flag --separate-asm that splits the asm.js module and the
   handwritten JS functions to separate files.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.34.7...1.34.8
    - Emscripten-LLVM: no changes.
    - Emscripten-Clang: no changes.

v1.34.7: 9/5/2015
-----------------
 - Fixed uses of i64* in side modules.
 - Improved GL support when proxying, and fake WebAudio calls when proxying.
 - Added new main loop timing mode EM_TIMING_SETIMMEDIATE for rendering with
   vsync disabled (#3717)
 - Updated emrun to latest version, adds --safe_firefox_profile option to run
   emrun pages in clean isolated environment.
 - Implemented glGetStringi() method for WebGL2/GLES3. (#3472, #3725)
 - Automatically emit loading code for EMTERPRETIFY_FILE if emitting html.
 - Added new build option -s USE_PTHREADS=2 for running pthreads-enabled pages
   in browsers that do not support SharedArrayBuffer.
 - Added support for building SSE2 intrinsics based code (emmintrin.h), when
   -msse2 is passed to the build.
 - Added exports for getting FS objects by their name (#3690)
 - Updated LLVM to latest upstream PNaCl version (Clang 3.7, July 29th).
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.34.6...1.34.7
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.34.6...1.34.7
    - Emscripten-Clang: https://github.com/emscripten-core/emscripten-fastcomp-clang/compare/1.34.6...1.34.7

v1.34.6: 8/20/2015
------------------
 - Added new build option -s EMULATED_FUNCTION_POINTERS=2.
 - Fixed a bug with calling functions pointers that take float as parameter
   across dynamic modules.
 - Improved dynamic linking support with -s LINKABLE=1.
 - Added new build option -s MAIN_MODULE=2.
 - Cleaned up a few redundant linker warnings (#3702, #3704)
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.34.5...1.34.6
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.34.5...1.34.6
    - Emscripten-Clang: no changes.

v1.34.5: 8/18/2015
------------------
 - Added Bullet physics, ogg and vorbis to emscripten-ports.
 - Added FreeType 2.6 to emscripten-ports.
 - Fixed CMake handling when building OpenCV.
 - Fixed and issue with exceptions being thrown in empty glBegin()-glEnd()
   blocks (#3693)
 - Improved function pointer handling between dynamically linked modules
 - Fixed some OpenAL alGetSource get calls (#3669)
 - Fixed issues with building the optimizer on 32-bit Windows (#3673)
 - Increased optimizer stack size on Windows to 10MB (#3679)
 - Added support for passing multiple input files to opt, to speed up
   optimization and linking in opt.  
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.34.4...1.34.5
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.34.4...1.34.5
    - Emscripten-Clang: no changes.

v1.34.4: 8/4/2015
-----------------
 - Add special handling support for /dev/null as an input file (#3552)
 - Added basic printf support in NO_FILESYSTEM mode (#3627)
 - Update WebVR support to the latest specification, and add support for
   retrieving device names
 - Improved --proxy-to-worker build mode with proxying (#3568, #3623)
 - Generalized EXPORT_FS_METHODS to EXPORT_RUNTIME_METHODS
 - Added node externs for closure
 - Fixed a memory allocation bug in pthreads code (#3636)
 - Cleaned up some debug assertion messages behind #ifdef ASSERTIONS (#3639)
 - Fixed umask syscall (#3637)
 - Fixed double alignment issue with formatStrind and emscripten_log (#3647)
 - Added new EXTRA_EXPORTED_RUNTIME_METHODS build option
 - Updated emrun to latest version
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.34.3...1.34.4
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.34.3...1.34.4
    - Emscripten-Clang: no changes.

v1.34.3: 7/15/2015
------------------
 - Move libc to musl+syscalls
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.34.2...1.34.3
    - Emscripten-LLVM: no changes.
    - Emscripten-Clang: no changes.

v1.34.2: 7/14/2015
------------------
 - Upgrade to new SIMD.js polyfill version and improved SIMD support.
 - Improved WebGL support in --proxy-to-worker mode (#3569)
 - Removed warning on unimplemented JS library functions
 - Fix WebGL 2 support with closure compiler
 - Fixed an issue with WebRTC support (#3574)
 - Fixed emcc to return a correct error process exit code when invoked with no input files
 - Fixed a compiler problem where global data might not get aligned correctly for SIMD.
 - Fixed a LLVM backend problem which caused recursive stack behavior when
   linking large codebases, which was seen to cause a stack overflow crash on
   Windows.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.34.1...1.34.2
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.34.1...1.34.2
    - Emscripten-Clang: no changes.

v1.34.1: 6/18/2015
------------------
 - Fixed an issue with resize canvas not working with GLFW.
 - Fixed handling of empty else blocks.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.34.0...1.34.1
    - Emscripten-LLVM: no changes.
    - Emscripten-Clang: no changes.

v1.34.0: 6/16/2015
------------------
 - Fixed an issue when generating .a files from object files that reside on
   separate drives on Windows (#3525).
 - Added a missing dependency for GLFW (#3530).
 - Removed the Emterpreter YIELDLIST option.
 - Added support for enabling memory growth before the runtime is ready.
 - Added a new feature to store the memory initializer in a string literal
   inside the generated .js file.
 - Fixed a code miscompilation issue with a constexpr in fcmp.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.33.2...1.34.0
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.33.2...1.34.0
    - Emscripten-Clang: no changes.

v1.33.2: 6/9/2015
-----------------
 - Added support for OpenAL Extension AL_EXT_float32 (#3492).
 - Added support for handling command line flags -M and -MM (#3518).
 - Fixed a code miscompilation issue with missing ';' character (#3520).
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.33.1...1.33.2
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.33.1...1.33.2
    - Emscripten-Clang: no changes.

v1.33.1: 6/3/2015
-----------------
 - Added support for multithreading with the POSIX threads API (pthreads), used
   when compiling and linking with the -s USE_PTHREADS=1 flag (#3266).
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.33.0...1.33.1
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.33.0...1.33.1
    - Emscripten-Clang: no changes.

v1.33.0: 5/29/2015
------------------
 - Fix an issue with writing to /dev/null (#3454).
 - Added a hash to objects inside .a files to support to linking duplicate
   symbol names inside .a files (#2142).
 - Provide extensions ANGLE_instanced_arrays and EXT_draw_buffers as aliases to
   the WebGL ones.
 - Fixed LLVM/Clang to build again on Windows after previous LLVM upgrade.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.32.4...1.33.0
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.32.4...1.33.0
    - Emscripten-Clang: no changes.

v1.32.4: 5/16/2015
------------------
 - Update LLVM and Clang to PNaCl's current 3.7 merge point (April 17 2015)
 - Added libpng to Emscripten-ports.
 - Added intrinsic llvm_fabs_f32.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.32.3...1.32.4
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.32.3...1.32.4
    - Emscripten-Clang: https://github.com/emscripten-core/emscripten-fastcomp-clang/compare/1.32.3...1.32.4

v1.32.3: 5/15/2015
------------------
 - Improved dynamic linking support.
 - Added new option to file_packager.py to store metadata externally.
 - Improved CMake support with CMAKE_CROSSCOMPILING_EMULATOR (#3447).
 - Added support for sysconf(_SC_PHYS_PAGES) (#3405, 3442).
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.32.2...1.32.3
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.32.2...1.32.3
    - Emscripten-Clang: no changes.

v1.32.2: 5/8/2015
-----------------
 - Removed a (name+num)+num -> name+newnum optimization, which caused heavy
   performance regressions in Firefox when the intermediate computation wraps
   around the address space (#3438).
 - Improved dynamic linking support.
 - Improved emterpreter when doing dynamic linking.
 - Fixed an issue with source maps debug info containing zeroes as line numbers.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.32.1...1.32.2
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.32.1...1.32.2
    - Emscripten-Clang: no changes.

v1.32.1: 5/2/2015
-----------------
 - Removed old deprecated options -s INIT_HEAP, MICRO_OPTS, CLOSURE_ANNOTATIONS,
   INLINE_LIBRARY_FUNCS, SHOW_LABELS, COMPILER_ASSERTIONS and
   COMPILER_FASTPATHS.
 - Added support for dynamic linking and dlopen().
 - Fixed a compilation issue that affected -O2 builds and higher (#3430).
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.32.0...1.32.1
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.32.0...1.32.1
    - Emscripten-Clang: no changes.

v1.32.0: 4/28/2015
------------------
 - Compile .i files properly as C and not C++ (#3365).
 - Removed old deprecated options -s PRECISE_I32_MUL, CORRECT_ROUNDINGS,
   CORRECT_OVERFLOWS, CORRECT_SIGNS, CHECK_HEAP_ALIGN, SAFE_HEAP_LINES,
   SAFE_HEAP >= 2, ASM_HEAP_LOG, SAFE_DYNCALLS, LABEL_DEBUG, RUNTIME_TYPE_INFO
   and EXECUTION_TIMEOUT, since these don't apply to fastcomp, which is now the
   only enabled compilation mode.
 - Preliminary work towards supporting dynamic linking and dlopen().
 - Fixed an issue where emrun stripped some characters at output (#3394).
 - Fixed alignment issues with varargs.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.31.3...1.32.0
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.31.3...1.32.0
    - Emscripten-Clang: no changes.

v1.31.3: 4/22/2015
------------------
 - Improved support for -E command line option (#3365).
 - Removed the old optimizeShifts optimization pass that was not valid for
   asm.js code.
 - Fixed an issue when simultaneously using EMULATE_FUNCTION_POINTER_CASTS and
   EMULATED_FUNCTION_POINTERS.
 - Fixed an issue with -s PRECISE_I64_MATH=2 not working (#3374).
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.31.2...1.31.3
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.31.2...1.31.3
    - Emscripten-Clang: no changes.

v1.31.2: 4/20/2015
------------------
 - Added support for file suffixes .i and .ii (#3365).
 - Fixed an issue with embind and wide strings (#3299).
 - Removed more traces of the old non-fastcomp compiler code.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.31.1...1.31.2
    - Emscripten-LLVM: no changes.
    - Emscripten-Clang: no changes.

v1.31.1: 4/17/2015
------------------
 - Added support for unicode characters in EM_ASM() blocks (#3348).
 - Removed the pointer masking feature as experimental and unsupported.
 - Fixed an issue where exit() did not terminate execution of Emterpreter (#3360).
 - Removed traces of the old non-fastcomp compiler code.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.31.0...1.31.1
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.31.0...1.31.1
    - Emscripten-Clang: no changes.

v1.31.0: 4/14/2015
------------------
 - Remove references to unsupported EMCC_FAST_COMPILER mode, fastcomp is always enabled (#3347).
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.30.6...1.31.0
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.30.6...1.31.0
    - Emscripten-Clang: no changes.

v1.30.6: 4/14/2015
------------------
 - Removed support for the deprecated jcache functionality (#3313).
 - Added support to emscripten_GetProcAddress() to fetch symbols with the ANGLE
   suffix (#3304, #3315).
 - Added immintrin.h header file to include all SSE support.
 - Added an async option to ccall (#3307).
 - Stopped from using 0 as a valid source ID for OpenAL (#3303).
 - When project has disabled exception catching, build an exceptions-disabled
   version of libcxx.
 - Split libcxx into two parts to optimize code size for projects that only need
   small amount of libcxx (#2545, #3308).
 - Avoid fprintf usage in emscripten_GetProcAddress() to allow using it with -s
   NO_FILESYSTEM=1 (#3327).
 - Removed old deprecated functionalities USE_TYPED_ARRAYS, FHEAP, GC emulation
   and non-asmjs-emscripten ABI.
 - Don't refer to prefixed GL extensions when creating a GL context (#3324).
 - Removed support code for x86_fp80 type (#3341).
 - Optimize EM_ASM() calls even more (#2596).
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.30.5...1.30.6
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.30.5...1.30.6
    - Emscripten-Clang: no changes.

v1.30.5: 4/7/2015
-----------------
 - Fixed WebIDL operation when closure is enabled after the previous EM_ASM()
   optimizations.
 - Optimized jsCall() to handle variadic cases of number of arguments faster
   (#3290, #3305).
 - Removed support for the getwd() function (#1115, #3309).
 - Fixed a problem with -s IGNORED_FUNCTIONS and -s DEAD_FUNCTIONS not working
   as expected (#3239).
 - Fixed an issue with -s EMTERPRETIFY_ASYNC=1 and emscripten_sleep() not
   working (#3307).
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.30.4...1.30.5
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.30.4...1.30.5
    - Emscripten-Clang: no changes.

v1.30.4: 4/3/2015
-----------------
 - Optimized the performance and security of EM_ASM() blocks by avoiding the use
   of eval() (#2596).
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.30.3...1.30.4
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.30.3...1.30.4
    - Emscripten-Clang: no changes.

v1.30.3: 4/3/2015
-----------------
 - Improved error handling in library_idbstore.js.
 - Fixed an asm.js validation issue with EMULATE_FUNCTION_POINTER_CASTS=1 feature (#3300).
 - Fixed Clang build by adding missing nacltransforms project after latest
   LLVM/Clang upstream merge.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.30.2...1.30.3
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.30.2...1.30.3
    - Emscripten-Clang: https://github.com/emscripten-core/emscripten-fastcomp-clang/compare/1.30.2...1.30.3

v1.30.2: 4/1/2015
-----------------
 - Added support to writing to mmap()ed memory by implementing msync() (#3269).
 - Updated SDL2 port to version 7.
 - Exported new singleton function Module.createContext() for creating a GL
   context from SDL2.
 - Added support for asm.js/Emscripten arch in Clang.
 - Finished LLVM 3.6 upgrade merge.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.30.1...1.30.2
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.30.1...1.30.2
    - Emscripten-Clang: https://github.com/emscripten-core/emscripten-fastcomp-clang/compare/1.30.1...1.30.2

v1.30.1: 3/24/2015
------------------
 - Upgraded LLVM+Clang from vrsion 3.5 to version 3.6.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.30.0...1.30.1
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.30.0...1.30.1
    - Emscripten-Clang: https://github.com/emscripten-core/emscripten-fastcomp-clang/compare/1.30.0...1.30.1

v1.30.0: 3/24/2015
------------------
 - Fixed a bug where html5.h API would not remove event handlers on request.
 - Fixed a regression issue that broke building on Windows when attempting to
   invoke tools/gen_struct_info.py.
 - Improved memory growth feature to better handle growing to large memory sizes
   between 1GB and 2GB (#3253).
 - Fixed issues with emrun with terminating target browser process, managing
   lingering sockets and command line quote handling.
 - Fixed a bug where unsigned integer return values in embind could be returned
   as signed (#3249).
 - Improved handling of lost GL contexts.
 - Changed malloc to be fallible (return null on failure) when memory growth is
   enabled (#3253).
 - Fixed a bug with WebIDL not being able to handle enums (#3258).
 - Updated POINTER_MASKING feature to behave as a boolean rather than a mask
   (#3240).
 - Improved "emcmake cmake" on Windows to automatically remove from path any
   entries that contain sh.exe in them, which is not supported by CMake.
 - Fixed an issue with symlink handling in readlink (#3277).
 - Updated SDL2 port to version 6.
 - Removed the obsolete FAST_MEMORY build option.
 - Added reciprocalApproximation and reciprocalSqrtApproximation SIMD intrinsics.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.29.12...1.30.0
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.29.12...1.30.0
    - Emscripten-Clang: no changes.

v1.29.12: 3/15/2015
-------------------
 - Fix a bug where SDL_malloc and SDL_free were not available. (#3247)
 - Fix various issues with emrun usage. (#3234)
 - Fixed an off-by-one memory access in native optimizer.
 - Improve emterpreter support.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.29.11...1.29.12
    - Emscripten-LLVM: no changes.
    - Emscripten-Clang: no changes.

v1.29.11: 3/11/2015
-------------------
 - Remove the requirement to pass -s PRECISE_F32=1 manually when building with
   SIMD support.
 - Fix a temp directory leak that could leave behind empty directories in the
   temp directory after build (#706)
 - Improve support for growable Emscripten heap in asm.js mode.
 - Added a warning message when generating huge asset bundles with file packager.
 - Fixed a bug where emscripten_get_gamepad_status might throw a JS exception if
   called after a gamepad was disconnected.
 - Improve emterpreter sleep support.
 - Optimize code generation when multiple consecutive bitshifts are present.
 - Optimize redundant stack save and restores, and memcpy/memsets.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.29.10...1.29.11
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.29.10...1.29.11
    - Emscripten-Clang: no changes.

v1.29.10: 2/19/2015
-------------------
 - Add a warning message when generating code that has a very large number of
   variables, which optimization flags could remove.
 - Improve support for SIMD casts and special loads.
 - Fix the process return code when using EMCONFIGURE_JS=1.
 - Improved the error message in abort().
 - Fix main loop handling during emterpreter sync save/load.
 - Handle emscripten_async_call and friends during sleep, by pausing all
   safeSet*() operations.
 - Add support for Google WTF when building with --tracing.
 - Improve emterpreter stability with fuzzing.
 - Add an option to load the memory initializer file from a typed array (#3187)
 - Remove linker warning message when linking to -lm, since Emscripten includes
   musl that implements the math libraries built-in.
 - Add support for SDL_WM_SetCaption(), which calls to Module['setWindowTitle'],
   or if not present, sets the web page title. (#3192)
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.29.9...1.29.10
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.29.9...1.29.10
    - Emscripten-Clang: no changes.

v1.29.9: 2/9/2015
-------------------
 - Documented FORCE_ALIGNED_MEMORY to be no longer supported.
 - Fixes issues with native optimizer handling of "if () else {}" statements.
   (#3129)
 - Improved cross-browser support for EMSCRIPTEN_FULLSCREEN_FILTERING_NEAREST.
   (#3165)
 - Added new linker option --profiling-funcs, which generates output that is
   otherwise minified, except that function names are kept intact, for use in
   profilers and getting descriptive call stacks.
 - The Module object is no longer written in global scope. (#3167)
 - Added new emscripten_idb_* API. (#3169)
 - Added new function emscripten_wget_data().
 - Add support for GL_RED with GLES3/WebGL2. (#3176)
 - Added basic WebVR support. (#3177)
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.29.8...1.29.9
    - Emscripten-LLVM: no changes.
    - Emscripten-Clang: no changes.

v1.29.8: 1/31/2015
-------------------
 - Fix a temp file leak with emterpreter. (#3156)
 - Fix a typo that broke glBlitFramebuffer. (#3159)
 - Added scandir() and alphasort() from musl. (#3161)
 - Add a warning if multiple .a files with same basename are being linked
   together. (#2619)
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.29.7...1.29.8
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.29.7...1.29.8
    - Emscripten-Clang: no changes.

v1.29.7: 1/28/2015
-------------------
 - Fixed an issue with backwards compatibility in emscripten-ports. (#3144)
 - Warn on duplicate entries in archives. (#2619)
 - Removed the MAX_SETJMPS limitation to improve setjmp/longjpmp support.
   (#3151)
 - Improve the native optimizer to not emit empty if clauses in some cases.
   (#3154)
 - Optimize Math.clz32, Math.min, NaN, and inf handling in asm.js.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.29.6...1.29.7
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.29.6...1.29.7
    - Emscripten-Clang: no changes.

v1.29.6: 1/23/2015
-------------------
 - Fixed an issue where calling glGen*() when the GL context was lost might
   throw a JS exception, instead a GL_INVALID_OPERATION is now recorded.
 - Improve label handling in native optimizer.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.29.5...1.29.6
    - Emscripten-LLVM: no changes.
    - Emscripten-Clang: no changes.

v1.29.5: 1/23/2015
-------------------
 - Enable compiling source files with the extension ".c++".
 - Enable versioning of the emscripten ports so that older Emscripten versions
   can keep using older versions of the ports (#3144)
 - Added a whitelist option to emterpreter, a linker flag of form -s
   EMTERPRETIFY_WHITELIST=["symbol1","symbol2"]. (#3129)
 - Improved emscripten_get_pointerlock_status() to always fill the output
   structure even when pointer lock is not supported.
 - Added an environment variable EMCC_NO_OPT_SORT=0/1 option to configure
   whether the generated output should have the functions sorted by length,
   useful for debugging.
 - Added new tool tools/merge_pair.py which allows bisecting differences between
   two output files to find discrepancies.
 - Improved parsing in cashew.
 - Improved output message from emconfigure and emmake when inputs are unexpected.
 - Added built-in asm handler for LLVM fabs operation.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.29.4...1.29.5
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.29.4...1.29.5
    - Emscripten-Clang: no changes.

v1.29.4: 1/21/2015
-------------------
 - Added new C <-> JS string marshalling functions asciiToString(),
   stringToAscii(), UTF8ToString(), stringToUTF8() that can be used to copy
   strings across the JS and C boundaries. (#2363)
 - Added new functions lengthBytesUTF8(), lengthBytesUTF16() and
   lengthBytesUTF32() to allow computing the byte lengths of strings in
   different encodings. (#2363)
 - Upgraded SDL2 port to version 4.
 - Add support for saving the emterpreter stack when there are functions
   returning a value on the stack (#3129)
 - Notice async state in emterpreter trampolines (#3129)
 - Optimize SDL1 pixel copying to the screen.
 - Fixed an issue with emterpreter parsing. (#3141)
 - Fixed an issue with native optimizer and -s PPRECISE_F32=1.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.29.3...1.29.4
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.29.3...1.29.4
    - Emscripten-Clang: no changes.

v1.29.3: 1/16/2015
-------------------
 - Fixed a bug with OpenGL context initialization enableExtensionsByDefault. (#3135)
 - Fixed an issue with nested if parsing in native optimizer.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.29.2...1.29.3
    - Emscripten-LLVM: no changes.
    - Emscripten-Clang: no changes.

v1.29.2: 1/16/2015
-------------------
 - Fixed an issue with embind compilation in LLVM 3.5.
 - Fixed an issue with SDL audio queueing stability, which would queue audio too
   eagerly and cause stutter in some applications (#3122, #3124)
 - Enabled native JS optimizer to be built automatically on Windows, requires
   VS2012 or VS2013. 
 - Improve error message to reflect the fact that DLOPEN_SUPPORT is currently
   not available (#2365)
 - Improve SIMD load and store support.
 - Upgraded SDL2 port to version 3.
 - Fix a bug with native JS optimizer and braces in nested ifs.
 - Improved emterpreter support.
 - Fixed LLVM 3.5 to build with Visual Studio on Windows (emscripten-fastcomp #61)
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.29.1...1.29.2
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.29.1...1.29.2
    - Emscripten-Clang: no changes.

v1.29.1: 1/7/2015
-------------------
 - Migrated to upstream PNaCl LLVM+Clang 3.5 from the previous 3.4.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.29.0...1.29.1
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.29.0...1.29.1
    - Emscripten-Clang: https://github.com/emscripten-core/emscripten-fastcomp-clang/compare/1.29.0...1.29.1

v1.29.0: 1/7/2015
-------------------
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.28.3...1.29.0
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.28.3...1.29.0
    - Emscripten-Clang: no changes.

v1.28.3: 1/4/2015
-------------------
 - embuilder.py tool
 - Many fixes for native optimizer on Windows
 - Perform LLVM LTO in a separate invocation of opt, so that it does not mix
   with legalization and other stuff we do at link time
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.28.2...1.28.3
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.28.2...1.28.3
    - Emscripten-Clang: https://github.com/emscripten-core/emscripten-fastcomp-clang/compare/1.28.2...1.28.3

v1.28.2: 12/17/2014
-------------------
 - Enable native optimizer by default
 - Disable slow2asm legacy testing (asm.js mode in pre-fastcomp)
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.28.1...1.28.2
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.28.1...1.28.2
    - Emscripten-Clang: no changes.

v1.28.1: 12/15/2014
-------------------
 - Use a lot more MUSL math functions
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.28.0...1.28.1
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.28.0...1.28.1
    - Emscripten-Clang: no changes.

v1.28.0: 12/12/2014
-------------------
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.27.2...1.28.0
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.27.2...1.28.0
    - Emscripten-Clang: no changes.

v1.27.2: 12/10/2014
-------------------
 - Added more complete support for SSE1 SIMD intrinsics API. (#2792)
 - Fixed an issue with glTexImage2D on GL_LUMINANCE + GL_FLOAT textures. (#3039)
 - Use the cashew asm.js parser in native optimizer.
 - Fixed issues with IE when running closure minified pages. (#3012)
 - Enabled asm.js validation for SIMD compilation.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.27.1...1.27.2
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.27.1...1.27.2
    - Emscripten-Clang: no changes.

v1.27.1: 11/20/2014
-------------------
 - Migrated to upstream PNaCl LLVM+Clang 3.4 from the previous 3.3.
 - Added a FindOpenGL.cmake to support find_package() for OpenGL in CMake scripts.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.27.0...1.27.1
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.27.0...1.27.1
    - Emscripten-Clang: https://github.com/emscripten-core/emscripten-fastcomp-clang/compare/1.27.0...1.27.1

v1.27.0: 11/20/2014
-------------------
 - Added new work in progress option -s NATIVE_OPTIMIZER=1 that migrates
   optimizer code from JS to C++ for better performance.
 - Fixed an embind issue when compiling with closure (#2974)
 - Fixed an embind issue with unique_ptr (#2979)
 - Fixed a bug with new GL context initialization in proxy to worker mode.
 - Fixed an issue where GL context event handlers would leak after a GL context
   has been freed.
 - Optimized embind operation in Chrome by avoiding using Function.prototype.bind().
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.26.1...1.27.0
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.26.1...1.27.0
    - Emscripten-Clang: no changes.

v1.26.1: 11/7/2014
------------------
 - Fixed emscripten::val handle for special js values (#2930)
 - Implemented SDL 1.2 SDL_SetClipRect / SDL_GetClipRect (#2931)
 - Added support for building zlib from Emscripten Ports with linker flag -s USE_ZLIB=1.
 - Improved experimental GLES3 support.
 - Fixed issues with llseek (#2945)
 - Enable using emscripten_get_now() in web workers (#2953)
 - Added stricter input data validation in GL code.
 - Added new HTML5 C API for managing fullscreen mode transitions to resolve
   cross-browser issue #2556 (#2975)
 - Fixed an issue with using structs in va_args (#2923)
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.26.0...1.26.1
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.26.0...1.26.1
    - Emscripten-Clang: https://github.com/emscripten-core/emscripten-fastcomp-clang/compare/1.26.0...1.26.1

v1.26.0: 10/29/2014
-------------------
 - Fixed an issue where emar would forward --em-config to llvm-ar (#2886)
 - Added a new "emterpreter" feature that allows running Emscripten compiled
   code in interpreted form until asm.js compilation is ready (-s
   EMTERPRETIFY=1).
    - For more information, see
      https://groups.google.com/d/msg/emscripten-discuss/vhaPL9kULxk/_eD2G06eucwJ
 - Added new "Emscripten Ports" architecture that enables building SDL2 with -s
   USE_SDL=2 command line flag.
 - Added support for SDL 1.2 SDL_CreateRGBSurfaceFrom() function.
 - Improved experimental SIMD support.
 - Use only minimum necessary digits to print floating point literals in
   generated JS code for smaller code output.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.25.2...1.26.0
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.25.2...1.26.0
    - Emscripten-Clang: no changes.

v1.25.2: 10/16/2014
-------------------
 - Fixed a bug in tmpfile() function not allocating the mode argument correctly.
 - Fixed a bug with handling empty files in IDBFS (#2845)
 - Added an implementation of the utimes() function (#2845)
 - Added experimental WebGL 2.0 support with the linker flag -s USE_WEBGL2=1.
   (#2873)
 - Fixed a UnboundTypeError occurring in embind (#2875)
 - Fixed an error "IndexSizeError: Index or size is negative or greater than the
   allowed amount" being thrown by Emscripten SDL 1.2 surface blit code. (#2879)
 - Fixed a JS minifier issue that generated "x--y from x - -y" (#2869)
 - Added a new emcc command line flag "--cache <dir>" to control the location of
   the Emscripten cache directory (#2816)
 - Implemented SDL_ConvertSurface() and added support for SDL_SRCALPHA in
   SDL_SetAlpha (#2871)
 - Fixed issues with the GL library handling of invalid input values.
 - Optimized SDL copyIndexedColorData function (#2890)
 - Implemented GLES3 emulation for glMapBufferRange() for upcoming WebGL 2
   support, using the -s FULL_ES3=1 linker option.
 - Fixed a bug where setting up and cancelling the main loop multiple times
   would stack up the main loop to be called too frequently (#2839)
 - Introduced a new API emscripten_set_main_loop_timing() for managing the
   Emscripten main loop calling frequency (#2839)
 - Added new optimization flags SDL.discardOnLock and SDL.opaqueFrontBuffer to
   Emscripten SDL 1.2 SDL_LockSurface() and SDL_UnlockSurface() (#2870)
 - Fixed a bug with glfwGetProcAddress().
 - Added option to customize GLOBAL_BASE (the starting address of global
   variables in the Emscripten HEAP).
 - Added the ability to register mouseover and mouseout events from the HTML5
   API.
 - Improved experimental SIMD support.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.25.1...1.25.2
    - Emscripten-LLVM: no changes.
    - Emscripten-Clang: no changes.

v1.25.1: 10/1/2014
------------------
 - Updated heap resize support code when -s ALLOW_MEMORY_GROWTH=1 is defined.
 - Updated libc++ to new version from upstream svn revision 218372, 2014-09-24.
 - Fixed a bug where building on Windows might generate output JS files with
   incorrect syntax (emscripten-fastcomp #52)
 - Improved experimental SIMD support.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.25.0...1.25.1
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.25.0...1.25.1
    - Emscripten-Clang: no changes.


v1.25.0: 9/30/2014
------------------
 - Fixed a warning message with -s EXPORTED_FUNCTIONS.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.24.1...1.25.0
    - Emscripten-LLVM: no changes.
    - Emscripten-Clang: no changes.

v1.24.1: 9/27/2014
------------------
 - Fixed issues with the tmpnam and tmpfile functions (#2797, 2798)
 - Fixed CMake package find code to not search any system directories, because
   Emscripten is a cross-compiler.
 - Improved support for the proposed solution for heap resizing.
 - Fixed an issue where one could not run a main loop without having first a GL
   context created when -s FULL_ES2 or -s LEGACY_GL_EMULATION were set.
 - For compatibility, Emscripten will no longer warn about missing library files
   for -lGL, -lGLU and -lglut libraries, since Emscripten provides the
   implementation for these without having to explicitly link to anything.
 - Added support for readonly (const) attributes and automatically call
   Pointer_stringify on DOMStrings in WebIDL.
 - Improved SIMD support for the experimental Ecmascript SIMD spec.
 - Added support for GLFW 3.0.
 - Added new Emscripten HTML 5 functions emscripten_set_mouseenter_callback()
   and emscripten_set_mouseleave_callback().
 - Emscripten now recognizes an environment variable
   EMCC_JSOPT_BLACKLIST=a,b,c,d which can be used to force-disable Emscripten to
   skip running specific JS optimization passes. This is intended as a debugging
   aid to help zoom in on JS optimizer bugs when compiling with -O1 and greater.
   (#2819)
 - Fixed a bug where Module['TOTAL_STACK'] was ignored (#2837).
 - Improved SIMD support for the experimental Ecmascript SIMD spec. Preliminary asm.js validation.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.24.0...1.24.1
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.24.0...1.24.1
    - Emscripten-Clang: no changes.

v1.24.0: 9/16/2014
------------------
 - Renamed the earlier Module.locateFilePackage() to Module.locateFile() added
   in v1.22.2 to better reflect its extended usage.
 - Improved exceptions support with exception_ptr.
 - Fixed a bug where restoring files from IDBFS would not preserve their file modes.
 - Fixed and issue where one could not pass a null pointer to strftime() function.
 - Improved SIMD support for the experimental Ecmascript SIMD spec.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.23.5...1.24.0
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.23.5...1.24.0
    - Emscripten-Clang: no changes.

v1.23.5: 9/12/2014
------------------
 - Added new functions emscripten_get_device_pixel_ratio(),
   emscripten_set_canvas_css_size() and emscripten_get_canvas_css_size() which
   allow handling High DPI options from C code.
 - Fixed bugs with timzone-related functions in the JS-implemented C standard
   library.
 - Implemented clock_gettime(CLOCK_MONOTONIC) and added a new function
   emscripten_get_now_is_monotonic() to query whether the JS-provided timer is
   monotonic or not.
 - Fixed an issue where the user could not pass --llvm-opts=xxx when also
   specifying --llvm-lto=2.
 - Renamed the linker option -profiling to --profiling for consistency. The old
   form is still supported.
 - Formalized the set of valid characters to be used in files passed to the
   file_packager.py (#2765).
 - Implemented SDL function SDL_BlitScaled.
 - Fixed a bug with right modifier keys in SDL.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.23.4...1.23.5
    - Emscripten-LLVM: no changes.
    - Emscripten-Clang: no changes.

v1.23.4: 9/7/2014
------------------
 - Implemented new targetX and targetY fields for native HTML5 mouse and touch
   events (#2751)
 - Improved SIMD support for the experimental Ecmascript SIMD spec.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.23.3...1.23.4
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.23.3...1.23.4
    - Emscripten-Clang: no changes.

v1.23.3: 9/7/2014
------------------
 - Removed the scons-tools SCons build system as unused.
 - Fixed an issue where applications could not handle WebGL context creation
   failures gracefully.
 - Fixed a bug where the stringToC function in ccall/cwrap might not allocate
   enough space to hold unicode strings.
 - Removed CMake from attempting to link to library -ldl when building projects,
   by unsetting CMAKE_DL_LIBS.
 - Fixed a bug where write_sockaddr might return undefined data in its output
   structure.
 - Added a new _experimental_ -s POINTER_MASKING=1 linker option that might help
   JS VMs to optimize asm.js code.
 - Added first version of a memory tracing API to profile memory usage in
   Emscripten applications.
 - Added functions glob and globfree from musl regex library.
 - Improved SIMD support for the experimental Ecmascript SIMD spec.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.23.2...1.23.3
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.23.2...1.23.3
    - Emscripten-Clang: no changes.

v1.23.2: 9/2/2014
------------------
 - Adjusted the process and group ids reported by the stub library functions to
   be closer to native unix values.
 - Set stack to be aligned to 16 bytes. (#2721)
 - Fixed a compiler error "unresolved symbol:
   __cxa_decrement_exception_refcount" (#2715)
 - Added a new warning message that instructs that building .so, .dll and .dylib
   files is not actually supported, and is faked for compatibility reasons for
   existing build chains. (#2562)
 - Fixed problems with SDL mouse scrolling (#2643)
 - Implemented OpenAL function alSourceRewind.
 - Removed several old header files from the Emscripten repository that had been
   included for emulation purposes (zlib.h, png.h, tiff.h, tiffio.h), but their
   implementation is not included.
 - Work around an issue in d8 with binary file reading that broke e.g. printf
   when running in d8. (#2731)
 - Rigidified the semantics of Module.preRun and Module.postRun: These must
   always be JS arrays, single functions are not allowed (#2729)
 - Improved compiler warning diagnostics when generating output that will not
   validate as asm.js (#2737)
 - Updated to latest emrun version to enable support for passing arguments with
   hyphens to the program. (#2742)
 - Added Bessel math functions of the first kind  (j0, j1, jn) from musl.
 - Improved SIMD support for the experimental Ecmascript SIMD spec.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.23.1...1.23.2
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.23.1...1.23.2
    - Emscripten-Clang: no changes.

v1.23.1: 8/26/2014
------------------
 - Add support for the Chrome variant of the Gamepad API.
 - Updates to SIMD.js support.
 - Implemented glutSetCursor function.
 - Added new link-time options -s NO_FILESYSTEM=1 and -s NO_BROWSER=1 to enable
   reducing output file sizes when those functionalities are not necessary.
 - Added a new option --closure 2 to allow running closure even on the asm.js output.
 - Fixed a regression bug that broke the use of
   emscripten_set_socket_error_callback() in emscripten.h
 - Removed the support for old discontinued Mozilla Audio Data API in src/library_sdl.js.
 - Removed the support for using Web Audio ScriptProcessorNode to stream audio.
 - Improved SDL audio streaming by using the main rAF() callback instead of a
   separate setTimeout() callback to schedule the audio data.
 - Deprecated compiling without typed arrays support. 
 - Migrated to using musl PRNG functions. Fixes reported bugs about the quality of randomness (#2341)
 - Improved SIMD support for the experimental Ecmascript SIMD spec.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.23.0...1.23.1
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.23.0...1.23.1
    - Emscripten-Clang: no changes.

v1.23.0: 8/21/2014
------------------
 - Added support for array attributes in WebIDL bindings.
 - Allow cloning pointers that are scheduled for deletion in embind, and add
   support for null in embind_repr().
 - Fixed possible issues with rounding and flooring operations.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.22.2...1.23.0
    - Emscripten-LLVM: no changes.
    - Emscripten-Clang: no changes.

v1.22.2: 8/19/2014
------------------
 - Adds stack overflow checks when building with the link flag -s ASSERTIONS=1.
 - Fix an issue where EM_ASM was not usable with closure when closure removed
   the Module object (#2639)
 - The locale "POSIX" is now recognized (#2636)
 - Fixed a problem with embind on IE11.
 - Added OpenAL functions alSource3i, alListener3f, alGetEnumValue and
   alSpeedOfSound and also recognize ALC_MAX_AUXILIARY_SENDS.
 - Fixed an issue where emcc would create .o files in the current directory when
   compiling multiple code files simultaneously (#2644)
 - The -s PROXY_TO_WORKER1= option now looks for a GET option "?noProxy" in the
   page URL to select at startup time whether proxying should be on or off.
 - Added new functions emscripten_yield, emscripten_coroutine_create and
   emscripten_coroutine_next which implement coroutines when building with the
   -s ASYNCIFY=1 option.
 - Optimized the size of intermediate generated .o files by omitting LLVM debug
   info from them when not needed. (#2657)
 - Fixed WebSocket connection URLs to allow a port number in them, e.g.
   "server:port/addr" (2610)
 - Added support for void* to the WebIDL binder, via the identifier VoidPtr.
 - Optimize emcc to not copy bitcode files around redundantly.
 - Fix stat() to correctly return ENOTDIR when expected (#2669).
 - Fixed issues with nested exception catching (#1714).
 - Increased the minimum size of the Emscripten HEAP to 64k instead of a previous 4k.
 - The {{{ cDefine('name') }}} macros now raise a compile-time error if the
   define name is not found, instead of hiding the error message inside the
   compiled output (#2672)
 - Fixed an issue where --emrun parameter was not compatible with the -s
   PROXY_TO_WORKER=1 option.
 - Improved WebGL support when compiling with the PROXY_TO_WORKER=1 option.
 - Fixed a regression issue with the handling of running dtors of classes that
   use virtual inheritance. (#2682)
 - Added an option Module.locateFilePackage() as a means to customize where data
   files are found in relative to the running page (#2680). NOTE: This parameter
   was later renamed to Module.locateFile() instead in release 1.24.0.
 - Fixed a bug where OpenAL sources would not properly delete.
 - Fixed a bug with upstream libc++ on std::map, std::multimap and
   std::unordered_map self-assignment
   (http://llvm.org/bugs/show_bug.cgi?id=18735)
 - Allow using __asm__ __volatile__("": : :"memory") as a compile-time
   reordering barrier (#2647)
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.22.1...1.22.2
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.22.1...1.22.2
    - Emscripten-Clang: no changes.

v1.22.1: 8/7/2014
------------------
 - Added support for prefixing functions with '$' in JS libraries, in order to
   cause them not be prefixed with '_' when compiling.
 - Improved WebIDL compiler to support enums.
 - Fixed a bug with emscripten_force_exit() that would throw an exception (#2629).
 - Fixed setlocale() when setting a bad locale. (#2630)
 - Fixed a compiler miscompilation bug when optimizing loops. (#2626)
 - Fixed an issue with rethrowing an exception (#2627)
 - Fixed a bug where malloc()ing from JS code would leak memory if the C/C++
   side does not use malloc() (#2621)
 - Removed an unnecessary assert() in glReadPixels, and improved it to support
   more texture pixel types.
 - Fixed a bug with std::locale accepting unknown locale names (#2636)
 - Added support for WebIDL binder to work with Closure (#2620)
 - Added no-op SDL IMG_Quit() and TTF_Quit() symbols.
 - Migrated to building libcxx and libcxxapi with -Oz optimization flags.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.22.0...1.22.1
    - Emscripten-LLVM: no changes.
    - Emscripten-Clang: no changes.

v1.22.0: 8/5/2014
------------------
 - Added support to emrun to dump files to the local filesystem for debugging
   purposes.
 - Implemented emscripten_wget in ASYNCIFY mode.
 - Improved extension catching support (#2616)
 - Fixed .a link groups to also work when linking to bitcode. (#2568)
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.21.10...1.22.0
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.21.10...1.22.0
    - Emscripten-Clang: no changes.

v1.21.10: 7/29/2014
-------------------
 - Fixed a Windows-specific issue where the generated output files might contain
   line endings of form \r\r\n. This caused browser debuggers to get confused
   with line numbers. (#2133)
 - Improved the node.js workaround introduced in v1.21.8.
 - Implemented new HTML5 API for direct WebGL context creation, emscripten_webgl_*().
 - Fixed a bug when loading in node.js and loaded by another module (#2586)
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.21.9...1.21.10
    - Emscripten-LLVM: no changes.
    - Emscripten-Clang: no changes.

v1.21.9: 7/28/2014
------------------
 - Fixed issues with exception catching. (#2531)
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.21.8...1.21.9
    - Emscripten-LLVM: no changes.
    - Emscripten-Clang: no changes.

v1.21.8: 7/28/2014
------------------
 - Fixed an issue when using --embed-file to embed very large files.
 - Worked around a Windows node.js bug where the compiler output might get cut
   off when the compilation ends in an error.
   (https://github.com/joyent/node/issues/1669)
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.21.7...1.21.8
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.21.7...1.21.8
    - Emscripten-Clang: no changes.

v1.21.7: 7/25/2014
------------------
 - Added new environment varaible EMCC_ONLY_FORCED_STDLIBS which can be used to
   restrict to only linking to the chosen set of Emscripten-provided libraries.
   (See also EMCC_FORCE_STDLIBS)
 - Adjusted argv[0] and environment variables USER, HOME, LANG and _ to report a
   more convenient set of default values. (#2565)
 - Fixed an issue where the application could not use environ without also
   referring to getenv() (#2557)
 - Fixed an issue with IDBFS running in web workers.
 - Print out an error if IDBFS is used without IDB support.
 - Fixed calling Runtime.getFuncWrapper() when -s ALIASING_FUNCTION_POINTERS=1 (#2010)
 - Fixed an issue where deleting files during directory iteration would produce
   incorrect iteration results (#2528)
 - Fixed support for strftime with %z and %Z (#2570)
 - Fixed a bug with truncate() throwing an exception (#2572)
 - Improved the linker to generate warning messages if user specifies -s X=Y
   linker flags that do not exist (#2579)
 - Fixed an issue with creating read-only files (#2573)
 - Added first implementation for the ASYNCIFY option, which splits up
   synchronous blocking loops to asynchronous execution. For more information on
   this approach, see https://github.com/emscripten-core/emscripten/wiki/Asyncify
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.21.6...1.21.7
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.21.6...1.21.7
    - Emscripten-Clang: no changes.

v1.21.6: 7/22/2014
------------------
 - Separated OpenAL AL and ALC errors to properly separate fields.
 - When using EGL to initialize a GL context, initialize a stencil buffer to the
   context as well, since proper EGL context choosing is not yet implemented.
 - Added new linker flag -s DEMANGLE_SUPPORT to choose whether to compile the
   application with libcxxabi-provided demangling support ___cxa_demangle().
 - Fixed a problem where calling stat() on a nonexisting file in the runtime VFS
   would result in an exception being thrown. (#2552)
 - When using the -v flag, no longer retain intermediate compilation files. To
   preserve the intermediate files, set the EMCC_DEBUG=1 environment variable.
   (#2538)
 - Added a new HTML setting Module.memoryInitializerPrefixURL which specifies a
   prefix for where the memory initializer file .mem.js should be loaded from
   (#2542)
 - Implemented eglReleaseThread to work according to spec.
 - Implemented a new function emscripten_force_exit() which immediately shuts
   down the C runtime.
 - Fixed a bug with exception handling that resulted in an error unresolved
   symbol: _ZTISt13bad_exception (#2560)
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.21.5...1.21.6
    - Emscripten-LLVM: no changes.
    - Emscripten-Clang: no changes.

v1.21.5: 7/21/2014
------------------
 - Added support for glDrawBuffers with the WEBGL_draw_buffers extension.
 - Added stub implementation for eglReleaseThread.
 - Fixed a bug where passing -E to emcc used the system include headers instead
   of the built-in ones. (#2534)
 - Fixed the stacktrace() function to work on MSIE as well.
 - Removed the zlib.h header file from system include directory, since
   Emscripten does not provide an implementation of zlib built-in.
 - Added support for __cxa_bad_typeid (#2547)
 - Fixed an internal compiler crash with a certain pattern involving optimized
   builds and int64_t (#2539)
 - Fixed an issue with -s EXCEPTION_CATCHING_WHITELIST handling where an
   extension that was a substring of another might get erroneously handled.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.21.4...1.21.5
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.21.4...1.21.5
    - Emscripten-Clang: no changes.

v1.21.4: 7/17/2014
------------------
 - Implemented the getsockopt() function.
 - Added new event callback functions emscripten_set_socket_xx_callback() that
   allow listening to WebSocket events in an asynchronous manner.
 - Greatly improved CMake support, now various forms of configure-time test
   builds are supported, and the default extension is set to ".js"
 - Prohibit the virtual filesystem from creating files with name '.' or '..' at
   runtime.
 - Have runtime mkdir() function call normalize the path to be created before
   creation.
 - Fixed an issue with omitting the third paramter in cwrap() call (#2511).
 - Fixed an issue where mouse event handling would throw an exception if the
   page did not contain a canvas object.
 - Fixed a GL initialization problem when user has extended Array with custom
   functions (#2514)
 - Added new compiler defines __EMSCRIPTEN_major__, __EMSCRIPTEN_minor__ and
   __EMSCRIPTEN_tiny__ which communicate the compiler version major.minor.tiny
   to compiled applications (#2343)
 - Fixed a bug where emrun did not properly capture the exit code when exit
   runtime via not calling exit().
 - Fixed an error message when symlinkin invalid filenams at runtime.
 - Fixed a bug in EGL context creation that parsed the input context creation
   parameters with wrong terminator.
 - Improved ffdb.py to be smarter when to attempt port forwarding to connect to
   a FFOS device DevTools port.
 - Implemented strsignal() function (#2532)
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.21.3...1.21.4
    - Emscripten-LLVM: no changes.
    - Emscripten-Clang: no changes.

v1.21.3: 7/10/2014
------------------
 - Added implementations for SDL function SDL_AudioQuit and SDL_VideoQuit.
 - Fix an issue with the optimizeShifts optimization enabled in previous version.
 - Fixed the -s RELOOPER command line parameter to work.
 - Fixed a bug where building the system libc migt result in a compiler deadlock
   on Windows.
 - Removed emcc from trying to link in .dll files as static libraries on
   Windows.
 - Added support for GL_HALF_FLOAT_OES.
 - Fixed a bug where emcmake did not work on Windows.
 - Use multithreaded compilation to build libc.
 - Fixed an issue where the GL interop library could throw an exception in an
   error condition, instead of raising a GL error.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.21.2...1.21.3
    - Emscripten-LLVM: no changes.
    - Emscripten-Clang: no changes.

v1.21.2: 7/5/2014
------------------
 - Improved the checks that detect that code is run only while the runtime is
   initialized.
 - The memory initializer file (.mem.js) is now emitted by default when
   compiling with at least -O2 optimization level.
 - Fixed a performance issue where built-in math functions (Math.sqrt, etc.)
   took a slightly slower path (#2484).
 - Added support for the ffs libc function.
 - Re-enabled optimizeShifts optimization when not compiling for asm.js (#2481)
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.21.1...1.21.2
    - Emscripten-LLVM: no changes.
    - Emscripten-Clang: no changes.

v1.21.1: 7/3/2014
------------------
 - Fixed an issue where wrong python interpreter could get invoked on Windows
   when both native and cygwin python were installed.
 - Updated musl from version 0.9.13 to version 1.0.3.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.21.0...1.21.1
    - Emscripten-LLVM: no changes.
    - Emscripten-Clang: no changes.

v1.21.0: 7/2/2014
------------------
 - Enable memory init files (.mem) by default in optimized builds (-O2+), as if
   --memory-init-file 1  is specified. This makes the default behavior on
   optimized builds emit smaller and faster-to-load code, but does require that
   you ship both a .js and a .mem file (if you prefer not to, can use
   --memory-init-file 1  ).
 - Implemented new SDL 1.2 functions SDL_GetRGB, SDL_GetRGBA and SDL_putenv.
 - Added support for /dev/random, /dev/urandom and C++11 std::random_device,
   which will use cryptographically secure random api if available. (#2447)
 - Added support for CMake find_path() directive.
 - Added support for std::unique_ptr in embind.
 - Improved Windows support for ffdb.py.
 - Implemented the clip_rect structure for created SDL surfaces.
 - Fixed a regression with SDL touch events (#2466)
 - Added support for C++11 std::thread::hardware_concurrency which backs to
   navigator.hardwareConcurrency. See
   http://wiki.whatwg.org/wiki/Navigator_HW_Concurrency (#2456)
 - Optimized embind code generation with constexprs.
 - Enabled the use of Runtime.add&removeFunction when closure minification is
   active (#2446)
 - Implemented support for accessing WebGL when building via the proxy to worker
   architecture.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.20.0...1.21.0
    - Emscripten-LLVM: no changes.
    - Emscripten-Clang: no changes.

v1.20.0: 6/13/2014
------------------
 - Optimize in-memory virtual filesystem performance when serialized to an IndexedDB.
 - Fixed memcpy regression with ta0 and ta1 modes.
 - Fixed an issue with line numbers being messed up when generating source maps (#2410)
 - Fixed an ffdb logging bug that could cause it to drop messages if they were
   being received too fast. Added support getting memory and system descriptions
   with ffdb.
 - Added a new extension to SDL "emscripten_SDL_SetEventHandler()" which enabled
   application to perform SDL event handling inside a JS event handler to
   overcome browser security restrictions. (#2417)
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.19.2...1.20.0
    - Emscripten-LLVM: no changes.
    - Emscripten-Clang: no changes.

v1.19.2: 6/9/2014
------------------
 - Updated CMake support for response file handling.
 - Fixed issues with glfwGetProcAddress and glfwSetWindowSizeCallback.
 - Fixed an issue with regexes that caused issues on IE11 runtime (#2400)
 - Added a new functions emscripten_get_preloaded_image_data() and
   emscripten_get_preloaded_image_data_from_FILE() to obtain pixel data of
   preloaded images.
 - Greatly improved ffdb capabilities to operate a FFOS device.
 - Fixed a Windows-specific bug where the user temp directory was littered with
   temporary .rsp files that did not get cleaned up.
 - Improved SIMD support.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.19.1...1.19.2
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.19.1...1.19.2
    - Emscripten-Clang: no changes.

v1.19.1: 6/3/2014
------------------
 - Migrate to using musl sscanf and sprintf and the family that writes to
   memory, and not directly to the filesystem.
 - Improve the error messages from -s SAFE_HEAP_ACCESS=1 runtime checks.
 - Added new linker flag -s NO_DYNAMIC_EXECUTION=1 which removes the use of
   eval() and new Function() in the generated output. For more information, see
   "Eval and related functions are disabled" in
   https://developer.chrome.com/extensions/contentSecurityPolicy .
 - Fixed a compiler issue when very large double constants are present. (#2392)
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.19.0...1.19.1
    - Emscripten-LLVM: no changes.
    - Emscripten-Clang: no changes.

v1.19.0: 5/29/2014
------------------
 - Added an error message to signal that linkable modules are not supported in fastcomp.
 - Fixed a miscompilation issue that resulted in an error "SyntaxError: invalid
   increment operand" and a statement +(+0) being generated (#2314)
 - Make optimized compiler output smaller by running the shell code through
   uglify when not using closure.
 - Fixed a crash in SDL audio loading code introduced in v1.18.3
 - Fixed an issue where glTex(Sub)Image2D might throw an exception on error,
   instead of setting glGetError().
 - Added new typedefs emscripten_align1_short, emscripten_align{1/2}_int,
   emscripten_align{1/2}_float and emscripten_align{1/2/4}_double to ease
   signaling the compiler that unaligned data is present. (#2378)
 - Fixed an embind issue with refcount tracking on smart pointers.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.18.4...1.19.0
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.18.4...1.19.0
    - Emscripten-Clang: no changes.

v1.18.4: 5/27/2014
------------------
 - Fixed error message on unsupported linking options (#2365)
 - Updated embind to latest version from IMVU upstream.
 - Fixed an issue where source maps did not load properly in Firefox.
 - Added a more descriptive error message to fastcomp when MAX_SETJMPS limit is
   violated. (#2379)
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.18.3...1.18.4
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.18.3...1.18.4
    - Emscripten-Clang: no changes.

v1.18.3: 5/21/2014
------------------
 - Added support to emcc command line for "archive groups": -Wl,--start-group
   and -Wl,--end-group
 - Greatly optimized ccall and cwrap implementations.
 - Added new support for SDL_Mix backend to use WebAudio to play back audio clips.
 - Fixed a registerizeHarder issue with elimination of conditional expressions.
 - Migrated single-character standard C functions (islower, tolower, and the
   family) to use musl implementations.
 - Updated relooper to not optimize out breaks if it causes excessive nesting.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.18.2...1.18.3
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.18.2...1.18.3
    - Emscripten-Clang: no changes.

v1.18.2: 5/19/2014
------------------
 - Fixed a problem which blocked user applications from handling WebGL context
   loss events themselves.
 - Added a new HTML5 api function emscripten_is_webgl_context_lost() which
   allows polling for context loss in addition to receiving events.
 - Improved async wget progress events to work better across browsers.
 - Improved WebIDL binder support.
 - Added new typeof() function to emscripten::val.
 - Added support for SDL window events SDL_WINDOWEVENT_FOCUS_GAINED,
   SDL_WINDOWEVENT_FOCUS_LOST, SDL_WINDOWEVENT_SHOWN, SDL_WINDOWEVENT_HIDDEN.
 - Fixed a compiler miscompilation on unsigned i1 bitcasts (#2350)
 - Fixed a compiler bug where doubles in varargs might not get 8-byte aligned (#2358)
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.18.1...1.18.2
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.18.1...1.18.2
    - Emscripten-Clang: no changes.

v1.18.1: 5/12/2014
------------------
 - Fixed an issue where the mouse wheel scroll did not work with SDL.
 - Fixed an issue with emscripten_async_wget, which undesirably expected that
   the string pointer passed to it stayed alive for the duration of the
   operation (#2349)
 - Emscripten now issues a warning message when the EXPORTED_FUNCTIONS list
   contains invalid symbol names (#2338)
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.18.0...1.18.1
    - Emscripten-LLVM: no changes.
    - Emscripten-Clang: no changes.

v1.18.0: 5/10/2014
------------------
 - Enable support for low-level C<->JS interop to marshall 64 bit integers from
   C to JS.
 - Fixed an issue that caused some programs to immediately run out of memory
   "(cannot enlarge memory arrays)" at startup. (#2334)
 - Fixed a crash issue with generated touch events that didn't correspond to a real touch.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.17.0...1.18.0
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.17.0...1.18.0
    - Emscripten-Clang: no changes.

v1.17.0: 5/6/2014
------------------
 - Enabled asm.js compilation and -s PRECISE_F32 support when using embind.
 - Improved relooper to emit switches in many-entried blocks.
 - Fixed a GLFW bug where mouse wheel direction was reversed.
 - Fixed glfwGetKey to work even when no callback is registered with
   glfwGetKeyCallback (#1320)
 - Added a new tool 'webidl_binder' that generates C <-> JS interop code from
   WebIDL descriptions.
 - Fix emscripten compilation to work on pages that don't contain a HTML canvas.
 - Added a new error message to default shell when an uncaught exception is thrown.
 - Improved error diagnostics reported by -s SAFE_HEAP=1.
 - Added support for registering callbacks hook to VFS file open, write, move,
   close and delete.
 - Added embind support to std::basic_string<unsigned char>
 - By default, the C runtime will no longer exit after returning from main()
   when safeSetTimeout() or safeSetInterval() is used.
 - Fixed an issue with sscanf formatting (#2322)
 - Fixed an issue where precompiled headers were given a wrong output filename (#2320)
 - Enabled registerizeHarder optimization pass to work when outlining is enabled.
 - Fixed an issue with strptime month handling (#2324)
 - Added an initial implementation of a new tool 'ffdb' which can be used to
   operate a Firefox OS phone from the command line.
 - Fixed a compiler crash on assertion failure '!contains(BranchesOut, Target)'
   (emscripten-fastcomp #32)
 - Added a new ABI to Clang that targets Emscripten specifically. Stop aligning
   member functions to save some space in the function table array.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.16.0...1.17.0
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.16.0...1.17.0
    - Emscripten-Clang: https://github.com/emscripten-core/emscripten-fastcomp-clang/compare/1.16.0...1.17.0

v1.16.0: 4/16/2014
------------------
 - Removed browser warnings message in VFS library about replacing __proto__ performance issue. 
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.15.1...1.16.0
    - Emscripten-LLVM: no changes.
    - Emscripten-Clang: https://github.com/emscripten-core/emscripten-fastcomp-clang/compare/1.15.1...1.16.0

v1.15.1: 4/15/2014
------------------
 - Added support for SDL2 touch api.
 - Added new user-controllable emdind-related define #define
   EMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES, which allows optimizing embind for minimal
   size when std::type_info is not needed. 
 - Fixed issues with CMake support where CMAKE_AR and CMAKE_RANLIB were not
   accessible from CMakeLists.txt files.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.15.0...1.15.1
    - Emscripten-LLVM: no changes.
    - Emscripten-Clang: no changes.

v1.15.0: 4/11/2014
------------------
 - Fix outlining feature for functions that return a double (#2278)
 - Added support for C++11 atomic constructs (#2273)
 - Adjusted stdout and stderr stream behavior in the default shell.html to
   always print out to both web page text log box, and the browser console.
 - Fixed an issue with loop variable optimization.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.14.1...1.15.0
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.14.1...1.15.0
    - Emscripten-Clang: https://github.com/emscripten-core/emscripten-fastcomp-clang/compare/1.14.1...1.15.0

v1.14.1: 4/8/2014
------------------
 - Added new command line utility 'emcmake', which can be used to call
   emconfigure for cmake.
 - Added a new emcc command line parameter '--valid-abspath', which allows
   selectively suppressing warning messages that occur when using absolute path
   names in include and link directories.
 - Added a new emcc linker command line parameter '--emit-symbol-map', which
   will save a map file between minified global names and the original function
   names.
 - Fixed an issue with --default-object-ext not always working properly.
 - Added optimizations to eliminate redundant loop variables and redundant
   self-assignments.
 - Migrated several libc functions to use compiled code from musl instead of
   handwritten JS implementations.
 - Improved embind support.
 - Renamed the EM_ASM_() macro to the form EM_ASM_ARGS().
 - Fixed mouse button ordering issue in glfw.
 - Fixed an issue when creating a path name that ends in a slash (#2258, #2263)
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.14.0...1.14.1
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.14.0...1.14.1
    - Emscripten-Clang: no changes.

v1.14.0: 3/25/2014
------------------
 - Added new emcc linker command line option '-profiling', which defaults JS
   code generation options suited for benchmarking and profiling purposes.
 - Implemented the EGL function eglWaitGL().
 - Fixed an issue with the HTML5 API that caused the HTML5 event listener unregistration to fail.
 - Fixed issues with numpad keys in SDL support library.
 - Added a new JS optimizer pass 'simplifyIfs', which is run when -s
   SIMPLIFY_IFS=1 link flag is set and -g is not specified. This pass merges
   multiple nested if()s together into single comparisons, where possible.
 - Removed false positive messages on missing internal "emscripten_xxx" symbols at link stage.
 - Updated to latest relooper version.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.13.2...1.14.0
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.13.2...1.14.0
    - Emscripten-Clang: no changes.

v1.13.2: 3/15/2014
------------------
 - Fixed issues with SDL audio on Safari.
 - Fixed issues with HTML5 API mouse scroll events on Safari.
 - Fixed issues with HTML5 fullscreen requests in IE11.
 - Enabled support for emscripten_get_callstack on IE10+.
 - Fixed issues with Closure symbol minification.
 - Further improved em_asm()-related error messages.
 - Updated to latest relooper version.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.13.1...1.13.2
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.13.1...1.13.2
    - Emscripten-Clang: no changes.

v1.13.1: 3/10/2014
------------------
 - Disallow C implicit function declarations by making it an error instead of a
   warning by default. These will not work with Emscripten, due to strict
   Emscripten signature requirements when calling function pointers (#2175).
 - Allow transitioning to full screen from SDL as a response to mouse press
   events.
 - Fixed a bug in previous 1.13.0 release that broke fullscreen transitioning
   from working.
 - Fixed emscripten/html5.h to be used in C source files.
 - Fix an issue where extraneous system libraries would get included in the
   generated output (#2191).
 - Added a new function emscripten_async_wget2_data() that allows reading from
   an XMLHTTPRequest directly into memory while supporting advanced features.
 - Fixed esc key code in GLFW.
 - Added new emscripten_debugger() intrinsic function, which calls into JS
   "debugger;" statement to break into a JS debugger.
 - Fixed varargs function call alignment of doubles to 8 bytes.
 - Switched to using default function local stack alignment to 16 bytes to be SIMD-friendly.
 - Improved error messages when user code has a syntax error in em_asm() statements.
 - Switched to using a new custom LLVM datalayout format for Emscripten. See
   https://github.com/emscripten-core/emscripten-fastcomp/commit/65405351ba0b32a8658c65940e0b65ceb2601ad4
 - Optimized function local stack space to use fewer temporary JS variables.
 - Full list of changes:
    - Emscripten: https://github.com/emscripten-core/emscripten/compare/1.13.0...1.13.1
    - Emscripten-LLVM: https://github.com/emscripten-core/emscripten-fastcomp/compare/1.13.0...1.13.1
    - Emscripten-Clang: https://github.com/emscripten-core/emscripten-fastcomp-clang/compare/1.13.0...1.13.1

v1.13.0: 3/3/2014
------------------
 - Fixed the deprecated source mapping syntax warning.
 - Fixed a buffer overflow issue in emscripten_get_callstack (#2171).
 - Added support for -Os (optimize for size) and -Oz (aggressively optimize for
   size) arguments to emcc.
 - Fixed a typo that broko the call signature of glCompressedTexSubImage2D()
   function (#2173).
 - Added new browser fullscreen resize logic that always retains aspect ratio
   and adds support for IE11.
 - Improve debug messaging with bad function pointer calls when -s ASSERTIONS=2
   is set.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.12.3...1.13.0

v1.12.3: 2/27/2014
------------------
 - Fixed alcOpenDevice on Safari.
 - Improved the warning message on missing symbols to not show false positives (#2154).
 - Improved EmscriptenFullscreenChangeEvent HTML5 API structure to return
   information about HTML element and screen sizes for convenience.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.12.2...1.12.3

v1.12.2: 2/25/2014
------------------
 - Added better warning message if Emscripten, LLVM and Clang versions don't match.
 - Introduced the asmjs-unknown-emscripten target triple that allows
   specializing LLVM codegen for Emscripten purposes.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.12.1...1.12.2

v1.12.1: 2/25/2014
------------------
 - TURNED ON FASTCOMP BY DEFAULT. This means that you will need to migrate to
   fastcomp-clang build. Either use an Emscripten SDK distribution, or to build
   manually, see
   http://kripken.github.io/emscripten-site/docs/building_from_source/LLVM-Backend.html
   for info.
 - Migrate to requiring Clang 3.3 instead of Clang 3.2. The fastcomp-clang
   repository by Emscripten is based on Clang 3.3.
 - Deprecated old Emscripten libgc implementation.
 - asm.js will now be always enabled, even in -O0 builds in fastcomp.
 - Remove support for -s RUNTIME_TYPE_INFO, which is unsupported in fastcomp.
 - Added a new "powered by Emscripten" logo.
 - Updated default shell.html graphical layout.
 - Added new macro EM_ASM_, which allows sending values to JS without returning anything.
 - Deprecated the jcache compiler option. It should not be needed anymore.
 - Added support for fetching callstack column information in Firefox 30 in emscripten_get_callstack.
 - Fix issues with missing exceptions-related symbols in fastcomp.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.12.0...1.12.1

v1.12.0: 2/22/2014
------------------
 - Improved the runtime abort error message when calling an invalid function
   pointer if compiled with -s ASSERTIONS=1 and 2. This allows the developer to
   better deduce errors with bad function pointers or function pointers casted
   and invoked via a wrong signature.
 - Added a new api function emscripten_set_main_loop_arg, which allows passing a
   userData pointer that will be carried via the function call, useful for
   object-oriented encapsulation purposes (#2114).
 - Fixed CMake MinSizeRel configuration type to actually optimize for minimal size with -Os.
 - Added support for GLES2 VAO extension OES_vertex_array_object for browsers that support it.
 - Fix issues with emscripten/html5.f when compiled with the SAFE_HEAP option.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.11.1...1.12.0

v1.11.1: 2/19/2014
------------------
 - Improved eglSwapBuffers to be spec-conformant.
 - Fixed an issue with asm.js validation and va_args (#2120).
 - Fixed asm.js validation issues found with fuzzing.
 - Added new link-time compiler flag -s RETAIN_COMPILER_SETTINGS=1, which
   enables a runtime API for querying which Emscripten settings were used to
   compile the file.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.11.0...1.11.1

v1.11.0: 2/14/2014
------------------
 - Implemented some new SDL library functions.
 - Renamed standard file descriptors to have handles 0, 1 and 2 rather than 1, 2
   and 3 to coincide with unix numbering.
 - Improved embind support with smart pointers and mixins.
 - Improved the registerization -O3 optimization pass around switch-case constructs.
 - Upper-case files with suffix .C are now also recognized (#2109).
 - Fixed an issue with glGetTexParameter (#2112).
 - Improved exceptions support in fastcomp.
 - Added new linker option -s NO_EXIT_RUNTIME=1, which can be used to set a
   default value for the Module["noExitRuntime"] parameter at compile-time.
 - Improved SDL audio buffer queueing when the sample rate matches the native
   web audio graph sample rate.
 - Added an optimization that removes redundant Math.frounds in -O3.
 - Improved the default shell.html file.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.10.4...1.11.0

v1.10.4: 2/10/2014
------------------
 - Added support for legacy GL emulation in fastcomp.
 - Deprecated the --split-js compiler option. This is not supported in fastcomp. 
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.10.3...1.10.4

v1.10.3: 2/9/2014
------------------
 - Work on supporting GL/EGL GetProcAddress.
 - Fixed issues with shared lib linking support.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.10.2...1.10.3

v1.10.2: 2/7/2014
------------------
 - Added basic FS unmount support.
 - Improved screen orientation lock API to return a success code.
 - Added PRECISE_F32 support to fastcomp.
 - Fixed issues in fastcomp related to special floating point literal
   serialization.
 - Improved SDL audio buffer queueing.
 - Added new link-time option -s WARN_UNALIGNED=1 to fastcomp to report compiler
   warnings about generated unaligned memory accesses, which can hurt
   performance.
 - Optimized libc strcmp and memcmp with the implementations from musl libc.
 - Optimized libc memcpy and memset to back to native code for large buffer sizes.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.10.1...1.10.2

v1.10.1: 1/31/2014
------------------
 - Improve srand() and rand() to be seedable and use a Linear Congruential
   Generator (LCG) for the rng generation for performance.
 - Improved OpenAL library support.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.10.0...1.10.1

v1.10.0: 1/29/2014
------------------
 - Improved C++ exception handling.
 - Improved OpenAL library support.
 - Fixed an issue where loading side modules could try to allocate from sealed
   heap (#2060).
 - Fixed safe heap issues (2068).
 - Added new EM_ASM variants that return a value but do not receive any inputs
   (#2070).
 - Add support for simultaneously using setjmp and C++ exceptions in fastcomp.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.9.5...1.10.0

v1.9.5: 1/25/2014
------------------
 - Added a spinner logo to default html shell.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.9.4...1.9.5

v1.9.4: 1/24/2014
------------------
 - Add support for Ninja and Eclipse+Ninja builds with Emscripten+CMake.
 - Fixed regressions with GL emulation.
 - Added support for #if !X in .js library preprocessor.
 - Make the syntax EM_ASM("code"); not silently fail. Note that the proper form
   is EM_ASM(code); without double-quotes.
 - Optimize generated code size by minifying loop labels as well.
 - Revised the -O3 optimization level to mean "safe, but very slow optimizations
   on top of -O2", instead of the old meaning "unsafe optimizations". Using -O3
   will now only do safe optimizations, but can be very slow compared to -O2.
 - Implemented a new registerization optimization pass that does extra variable
   elimination in -O3 and later to reduce the number of local variables in
   functions.
 - Implemented a new emscripten/html5.h interface that exposes common HTML5 APIs
   directly to C code without having to handwrite JS wrappers.
 - Improved error messages reported on user-written .js libraries containing
   syntax errors (#2033).
 - Fixed glBufferData() function call signature with null data pointer.
 - Added new option Module['filePackagePrefixURL'] that allows customizing the
   URL where the VFS package is loaded from.
 - Implemented glGetTexEnviv and glGetTexEnvfv in GL emulation mode.
 - Optimized the size of large memory initializer sections.
 - Fixed issues with the safe heap compilation option.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.9.3...1.9.4

v1.9.3: 1/17/2014
------------------
 - re-merge split blocks in multiples
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.9.2...1.9.3

v1.9.2: 1/16/2014
------------------
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.9.1...1.9.2

v1.9.1: 1/16/2014
------------------
 - Optimize desktop GL fixed function pipeline emulation texture load
   instruction counts when GL_COMBINE is used.
 - fix Math_floor coercion in unrecommended codegen modes
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.9.0...1.9.1

v1.9.0: 1/16/2014
------------------
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.8.14...1.9.0

v1.8.14: 1/15/2014
------------------
 - add musl fputws and fix vswprintf.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.8.13...1.8.14

v1.8.13: 1/15/2014
------------------
 - remove musl use of fwritex
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.8.12...1.8.13

v1.8.12: 1/15/2014
------------------
 - Added new GLEW 1.10.0 emulation support.
 - Fixed an issue where the runtime could start more than once when run in a
   browser (#1992)
 - Fix a regression in wprintf.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.8.11...1.8.12

v1.8.11: 1/15/2014
------------------
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.8.10...1.8.11

v1.8.10: 1/14/2014
------------------
 - Update libc implementation from musl libc.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.8.9...1.8.10

v1.8.9: 1/14/2014
------------------
 - add fputwc, which enables wprintf.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.8.8...1.8.9

v1.8.8: 1/14/2014
------------------
 - Update to latest libcxx and libcxxabi libraries.
 - Fix handling of floating point negative zero (#1898)
 - Fixed a memory leak in relooper in previous release.
 - Fixed an issue in previous release with VBO handling in GL optimizations.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.8.7...1.8.8

v1.8.7: 1/13/2014
------------------
 - Added support to numpad keycodes in glut support library.
 - Fix SIMD support with fastcomp.
 - Fixed a compiler error 'ran out of names' that could occur with too many
   minified symbol names.
 - Work around webkit imul bug https://bugs.webkit.org/show_bug.cgi?id=126345
   (#1991)
 - Optimized desktop GL fixed function pipeline emulation path for better
   performance.
 - Added support for exceptions when building with fastcomp.
 - Fix and issue where the run() function could be called multiple times at
   startup (#1992)
 - Removed a relooper limitation with fixed buffer size.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.8.6...1.8.7

v1.8.6: 1/8/2014
------------------
 - Added support for the libuuid library, see http://linux.die.net/man/3/libuuid.
 - Fixed .js file preprocessor to preprocess recursively (#1984).
 - Fixed a compiler codegen issue related to overflow arithmetic (#1975)
 - Added new link-time optimization flag -s AGGRESSIVE_VARIABLE_ELIMINATION=1
   that enables the aggressiveVariableElimination js optimizer pass, which tries
   to remove temporary variables in generated JS code at the expense of code
   size.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.8.5...1.8.6

v1.8.5: 1/7/2014
------------------
 - Fixed compiler issues when used with LLVM 3.4.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.8.4...1.8.5

v1.8.4: 1/6/2014
------------------
 - Added support to Return and Backspace keys to glut
 - Fixed compiler issues when used with LLVM 3.4.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.8.3...1.8.4

v1.8.3: 1/5/2014
------------------
 - Improved SDL and page scroll pos handling support for IE10 and IE11.
 - Optimized SDL_UnlockSurface performance.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.8.2...1.8.3

v1.8.2: 1/4/2014
------------------
 - Fixed glGetFramebufferAttachmentParameteriv and an issue with glGetXXX when
   the returned value was null.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.8.1...1.8.2

v1.8.1: 1/3/2014
------------------
 - Added support for WebGL hardware instancing extension.
 - Improved fastcomp native LLVM backend support.
 - Added support for #include filename.js to JS libraries.
 - Deprecated --compression emcc command line parameter that manually compressed
   output JS files, due to performance issues. Instead, it is best to rely on
   the web server to serve compressed JS files.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.8.0...1.8.1

v1.8.0: 12/28/2013
------------------
 - Fix two issues with function outliner and relooper.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.7.9...1.8.0

v1.7.9: 12/27/2013
------------------
 - Added new command line parameter --em-config that allows specifying a custom
   location for the .emscripten configuration file.
 - Reintroduced relaxed asm.js heap sizes, which no longer need to be power of
   2, but a multiple of 16MB is sufficient.
 - Added emrun command line tool that allows launching .html pages from command
   line on desktop and Android as if they were native applications. See
   https://groups.google.com/forum/#!topic/emscripten-discuss/t2juu3q1H8E . Adds
   --emrun compiler link flag.
 - Began initial work on the "fastcomp" compiler toolchain, a rewrite of the
   previous JS LLVM AST parsing and codegen via a native LLVM backend.
 - Added --exclude-file command line flag to emcc and a matching --exclude
   command line flag to file packager, which allows specifying files and
   directories that should be excluded while packaging a VFS data blob.
 - Improved GLES2 and EGL support libraries to be more spec-conformant.
 - Optimized legacy GL emulation code path. Added new GL_FFP_ONLY optimization
   path to fixed function pipeline emulation.
 - Added new core functions emscripten_log() and emscripten_get_callstack() that
   allow printing out log messages with demangled and source-mapped callstack
   information.
 - Improved BSD Sockets support. Implemented getprotobyname() for BSD Sockets library.
 - Fixed issues with simd support.
 - Various bugfixes: #1573, #1846, #1886, #1908, #1918, #1930, #1931, #1942, #1948, ..
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.7.8...1.7.9

v1.7.8: 11/19/2013
------------------
 - Fixed an issue with -MMD compilation parameter.
 - Added EM_ASM_INT() and EM_ASM_DOUBLE() macros. For more information, read
   https://groups.google.com/forum/#!topic/emscripten-discuss/BFGTJPCgO6Y .
 - Fixed --split parameter to also work on Windows.
 - Fixed issues with BSD sockets accept() call.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.7.7...1.7.8

v1.7.7: 11/16/2013
------------------
 - Improve SDL audio buffer queue timing support.
 - Improved default precision of clock_gettime even when not using CLOCK_REALTIME.
 - Optimize and fix issues with LLVM IR processing.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.7.6...1.7.7

v1.7.6: 11/15/2013
------------------
 - Added regex implementation from musl libc.
 - The command line parameter -s DEAD_FUNCTIONS=[] can now be used to explicitly
   kill functions coming from built-in library_xx.js.
 - Improved EGL support and GLES2 spec conformance.
 - Reverted -s TOTAL_MEMORY=x to require pow2 values, instead of the relaxed
   'multiples of 16MB'. This is because the relaxed rule is released only in
   Firefox 26 which is currently in Beta and ships on the week of December 10th
   (currently in Beta). As of writing, current stable Firefox 25 does not yet
   support these.
 - Adjusted the default linker behavior to warn about all missing symbols,
   instead of silently ignoring them. Use -s WARN_ON_UNDEFINED_SYMBOLS=0 to
   suppress these warnings if necessary.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.7.5...1.7.6

v1.7.5: 11/13/2013
------------------
 - Fix issues with the built-in C++ function name demangler.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.7.4...1.7.5

v1.7.4: 11/12/2013
------------------
 - Fixed issues with BSD sockets code and SDL joystick implementation.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.7.3...1.7.4

v1.7.3: 11/12/2013
------------------
 - Added support for generating single-precision floating point instructions.
    - For more information, read
      https://blog.mozilla.org/javascript/2013/11/07/efficient-float32-arithmetic-in-javascript/
 - Made GLES2 support library more spec-conformant by throwing fewer exceptions
   on errors. Be sure to build with -s GL_ASSERTIONS=1, remember to use
   glGetError() and check the browser console to best detect WebGL rendering
   errors.
 - Converted return value of emscripten_get_now() from float to double, to not
   lose precision in the function call.
 - Added support for joysticks in SDL via the Gamepad API
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.7.2...1.7.3
 
v1.7.2: 11/9/2013
------------------
 - The compiler now always generates a .js file that contains the generated
   source code even when compiling to a .html file.
    - Read https://groups.google.com/forum/#!topic/emscripten-discuss/EuHMwqdSsEs
 - Implemented depth+stencil buffer choosing behavior in GLUT, SDL and GLFW.
 - Fixed memory leaks generated by glGetString and eglGetString.
 - Greatly optimized startup times when virtual filesystems with a large amount
   of files in them.
 - Added some support for SIMD generated by LLVM.
 - Fixed some mappings with SDL keyboard codes.
 - Added a new command line parameter --no-heap-copy to compiler and file
   packager that can be used to optimize VFS memory usage at startup.
 - Updated libcxx to revision 194185, 2013-11-07.
 - Improvements to various library support. 
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.7.1...1.7.2

v1.7.1: 10/24/2013
------------------
 - Remove old call to Runtime.warn in file packager code
 - Fix bug with parsing of empty types.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.7.0...1.7.1

v1.7.0: 10/23/2013
------------------
 - Adds mouse wheel events support in GLUT library.
 - Adds support for a new link parameter -s CASE_INSENSITIVE_VFS=1 to enable
   Emscripten virtual filesystem to search files ignoring case.
 - *Numerous* optimizations in both compilation and runtime stages.
 - Remove unnecessary whitespace, compact postSets function, and other
   optimizations in compilation output to save on generated file size.
 - Fixes float parsing from negative zero.
 - Removes the -s EMIT_GENERATED_FUNCTIONS link parameter as unneeded.
 - Fixes an issue where updating subranges of GL uniform arrays was not
   possible.
 - asm.js heap size (-s TOTAL_MEMORY=x) no longer needs to be a power of 2. As a
   relaxed rule, choosing any multiple of 16MB is now possible.
 - O1 optimization no longer runs the 'simplifyExpressions' optimization pass.
   This is to improve build iteration times when using -O1. Use -O2 to run that
   pass.
 - EM_ASM() can now be used even when compiling to asm.js.
 - All currently specified non-debugging-related WebGL 1 extensions are now
   enabled by default on startup, no need to ctx.getExtension() manually to
   enable them.
 - Improve readability of uncaught JavaScript exceptions that are thrown all the
   way up to the web console by printing out the stack trace of where the throw
   occurred.
 - Fix an issue when renaming a directory to a subdirectory.
 - Several compiler stability fixes.
 - Adds a JavaScript implementation of cxa_demangle function for demangling call
   stack traces at runtime for easier debugging.
 - GL context MSAA antialising is now DISABLED by default, to make the GL
   behavior consistent with desktop usage.
 - Added support to SDL, GLUT and GLFW libraries to specify MSAA on/off at startup.
 - Implemented glColor4ubv in GL emulation mode.
 - Fix an issue with LLVM keyword __attribute__ ((__constructor__)) (#1155).
 - Fix an issue with va_args and -s UNALIGNED_MEMORY=1 (#1705).
 - Add initial support code for LLVM SIMD constructs and a JavaScript SIMD
   polyfill implementation from
   https://github.com/johnmccutchan/ecmascript_simd/ .
 - Fixed support for node.js native filesystem API NODEFS on Windows.
 - Optimize application startup times of Emscripten-compiled programs by
   enabling the virtual filesystem XHR and asm.js compilation to proceed in
   parallel when opening a page.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.6.4...1.7.0

v1.6.4: 9/30/2013
------------------
 - Implements a new preprocessor tool for preparsing C struct definitions
   (#1554), useful for Emscripten support library implementors.
 - Fix parsing issue with sscanf (#1668).
 - Improved the responsiveness of compiler print output on Windows.
 - Improved compilation times at link stage.
 - Added support for new "NODEFS" filesystem that directly accesses files on the
   native filesystem. Only usable with node.js when compiling to JS.
 - Added support for new IDBFS filesystem for accessing files in IndexedDB storage (#1601.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.6.3...1.6.4

v1.6.3: 9/26/2013
------------------
 - Emscripten CMake toolchain now generates archive files with .a suffix when
   project target type is static library, instead of generatic .bc files
   (#1648).
 - Adds iconv library from the musl project to implement wide functions in C
   library (#1670).
 - Full list of changes:
   https://github.com/emscripten-core/emscripten/compare/1.6.2...1.6.3

v1.6.2: 9/25/2013
------------------
 - Added support for dprintf() function (#1250).
 - Fixes several compiler stability issues (#1637, #1166, #1661, #1651 and more).
 - Enables support for WEBGL_depth_texture.
 - Adds support for new link flag -s GL_ASSERTIONS=1 which can be used to add
   extra validation layer to the Emscripten GL library to catch code issues.
 - Adds support to Web Audio API in SDL audio backend so that SDL audio now
   works in Chrome and new Opera as well.
 - Fixes an alpha blending issue with SDL_SetAlpha.
 - Implemented locale-related code in C library.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.6.1...1.6.2

v1.6.1: 9/22/2013
------------------
 - Several optimizations to compiler link stage.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.6.0...1.6.1

v1.6.0: 9/21/2013
------------------
 - Enable support for %[] pattern in scanf.
 - Added dependency tracking support to linked .js files in CMake toolchain.
 - The hex prefix 0x is now properly handled in sscanf (#1632).
 - Simplify internal compiler operations by removing the internal framework.js. 
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.5.9...1.6.0

v1.5.9: 9/15/2013
------------------
 - Add support for SDL_Delay in web workers.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.5.8...1.5.9

v1.5.8: 9/14/2013
------------------
 - Add support for the GCC -E compiler flag.
 - Update Emscripten libc headers to musl-0.9.13.
 - Added new utility function emscripten_async_load_script() to asynchronously
   load a new .js script URL.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.5.7...1.5.8

v1.5.7: 8/30/2013
------------------
 - The script tag in default shell.html is now marked 'async', which enables
   loading the JS script code asynchronously in Firefox without making the main
   thread unresponsive.
 - Implemented new utility function emscripten_get_canvas_size() which returns
   the current Module <canvas> element size in pixels.
 - Optimize code size in compiled side modules.
 - Optimize startup memory usage by avoiding unnecessary copying of VFS data at
   startup.
 - Add support for SDL_WM_ToggleFullScreen().
 - Add support for emscripten_get_now() when running in SpiderMonkey shell.
 - Added new environment variable EM_BUILD_VERBOSE=0,1,2,3 to set an extra
   compiler output verbosity level for debugging.
 - Added better support for dlopen() to simulate dynamic library loading in
   JavaScript.
 - Improved support for BSD sockets and networking.
 - Added new SOCKFS filesystem, which reads files via a network connection.
 - Avoid issues with long command line limitations in CMake toolchain by using
   response files.
 - Fix issues with client-side vertex data rendering in GL emulation mode.
 - Improved precision of clock_gettime().
 - Improve function outlining support.
 - Added support for using NMake generator with CMake toolchain.
 - Improved support for flexible arrays in structs (#1602).
 - Added ability to marshal UTF16 and UTF32 strings between C++ <-> JS code.
 - Added a new commandline tool validate_asms.py to help automating asm.js
   validation testing.
 - Improved stability with inline asm() syntax.
 - Updated libc headers to new version.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.5.6...1.5.7

v1.5.6: 8/17/2013
------------------
 - Improved BSD sockets support.
 - Added touch events support to GLUT library.
 - Added new --js-opts=0/1 command line option to control whether JS optimizer
   is run or not.
 - Improved OpenAL support.
 - Added new command line tool tools/find_bigvars.py which can be used on an
   output file to detect large functions and needs for outlining.
 - Merged link flags -s FORCE_GL_EMULATION and -s DISABLE_GL_EMULATION to a
   single opt-in flag -s LEGACY_GL_EMULATION=0/1 to control whether GL emulation
   is active.
 - Improved SDL input support.
 - Several stability-related compiler fixes.
 - Fixed source mapping generation support on Windows.
 - Added back the EMSCRIPTEN_KEEPALIVE attribute qualifier to help prevent
   inlining and to retain symbols in output without dead code elimination
   occurring.
 - Fix issues when marshalling UTF8 strings between C<->JS.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.5.5...1.5.6

v1.5.5: 8/9/2013
------------------
 - Update libcxx to revision 187959, 2013-08-08.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.5.4...1.5.5

v1.5.4: 8/9/2013
------------------
 - Fixed multiple issues with C stdlib support.
 - Fix audio buffer queueing issues with OpenAL.
 - Improved BSD sockets support.
 - Added a new compile+link time command line option -Wno-warn-absolute-paths to
   hide the emscripten compiler warning when absolute paths are passed into the
   compiler.
 - Added new link flag -s STB_IMAGE=0/1 and integrate it to SDL image loading to
   enable synchronous image loading support with SDL.
 - Several improvements on function outlining support.
 - Fix issues with GLES2 interop support.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.5.3...1.5.4

v1.5.3: 6/28/2013
------------------
 - Added new optimization level --llvm-lto 3 to run even more aggressive LTO
   optimizations.
 - Improve optimizations for libc and other libraries.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.5.2...1.5.3

v1.5.2: 6/27/2013
------------------
 - Added support for generating source maps along the built application when -g
   is specified. This lets the browser show original .cpp sources when
   debugging.
 - GLUT and SDL improvements.
 - Added new link option -g<level> where level=0-4, which allows controlling
   various levels of debuggability added to the output.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.5.1...1.5.2

v1.5.1: 6/22/2013
------------------
 - File packager now skips all directories and files starting with '.', and hidden files on Windows.
 - Fix issues with strnlen, memmove, LDBL_ constants, va_args, float.h, and others.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.5.0...1.5.1

v1.5.0: 6/17/2013
------------------
 - Several compiler optimizations.
 - Improve SDL key events support.
 - Increase debug logging when specifying emcc -v.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.4.9...1.5.0

v1.4.9: 6/8/2013
------------------
 - Several compiler optimizations.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.4.8...1.4.9

v1.4.8: 6/6/2013
------------------
 - Add support for webrtc-based sockets.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.4.7...1.4.8

v1.4.7: 6/2/2013
------------------
 - Remove more unneeded break and continue statements in relooper.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.4.6...1.4.7

v1.4.6: 6/2/2013
------------------
 - Improve relooper code.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.4.5...1.4.6

v1.4.5: 6/1/2013
------------------
 - Improve relooper code.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.4.4...1.4.5

v1.4.4: 6/1/2013
------------------
 - Add support for symlinks in source files.
 - Fix various issues with SDL.
 - Added -s FORCE_ALIGNED_MEMORY=0/1 link time flag to control whether all loads
   and stores are assumed to be aligned.
 - Fix file packager to work with closure.
 - Major improvements to embind support, and optimizations.
 - Improve GL emulation.
 - Optimize VFS usage.
 - Allow emscripten to compile .m and .mm files.
 - Added new syntax --preload-file src@dst to file packager command line to
   allow placing source files to custom destinations in the FS.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.4.3...1.4.4

v1.4.3: 5/8/2013
------------------
 - Fix issue with strcat.
 - Major embind improvements.
 - Switch to le32-unknown-nacl LLVM target triple as default build option
   instead of the old i386-pc-linux-gnu target triple.
 - Improve compiler logging behavior.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.4.2...1.4.3

v1.4.2: 5/3/2013
------------------
 - Fix issues with le32-unknown-nacl LLVM target triple.
 - Add some GLEW support.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.4.1...1.4.2

v1.4.1: 4/28/2013
------------------
 - Implement support for le32-unknown-nacl LLVM target triple.
 - Added new cmdline option -s ERROR_ON_UNDEFINED_SYMBOLS=0/1 to give
   compile-time error on undefined symbols at link time. Default off.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.3.8...1.4.1

v1.3.8: 4/29/2013
------------------
 - Improved 64-bit integer ops codegen.
 - Added Indexed DB support to vfs.
 - Improve warning message on dangerous function pointer casts when compiling in
   asm.js mode.
 - Added --use-preload-cache command line option to emcc, to be used with the
   file packager.
 - Fixes to libcextra.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.3.7...1.3.8

v1.3.7: 4/24/2013
------------------
 - Merge IMVU implementation of embind to emscripten trunk. Embind allows
   high-level C++ <-> JS types interop.
 - Enable asm.js compilation in -O1 and higher by default. Fix issues when
   compiling to asm.js.
 - Improve libc support with Emscripten with the musl libc headers.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.3.6...1.3.7

v1.3.6: 4/2/2013
------------------
 - Fix hang issue with strtof.
 - Update libcxx to upstream r178253 from March 29, 2013.
 - Fix issues with GL emulation.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.3.5...1.3.6

v1.3.5: 3/25/2013
------------------
 - Get exceptions working as they did before.
 - Remove symbol removing hack.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.3.4...1.3.5

v1.3.4: 3/24/2013
------------------
 - Update to new libcxx and libcxxabi versions from upstream.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.3.3...1.3.4

v1.3.3: 3/23/2013
------------------
 - Remove unneeded check from relooper.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.3.2...1.3.3

v1.3.2: 3/22/2013
------------------
 - Fix issues with fgets. 
 - Add support for non-fullscreen pointer lock.
 - Improve OpenAL support.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.3.1...1.3.2

v1.3.1: 3/19/2013
------------------
 - Improve SDL audio and mixer support.
 - Add GLES2 emulation features when -s FULL_ES2=1 is specified.
 - Add support for OpenAL.
 - Add new -s OPENAL_DEBUG=0/1 link command line option.
 - Fixed an issue with mouse coordinate being offset with canvas.
 - Removed -s UTF_STRING_SUPPORT=0 parameter, this is now always on.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.3.0...1.3.1

v1.3.0: 3/11/2013
------------------
 - Improve GLES2 emulation with -s FULL_ES2=1.
 - Deprecated -s USE_TYPED_ARRAYS=1 and -s QUANTUM_SIZE=1.
 - Implement a minifier infrastructure when compiling for asm.js.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.2.9...1.3.0

v1.2.9: 3/7/2013
------------------
 - Improved canvas behavior when transitioning between fullscreen.
 - Added support for getopt().
 - Fixed several libc issues.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.2.8...1.2.9

v1.2.8: 3/6/2013
------------------
 - Remove unnecessary recursion in relooper RemoveUnneededFlows.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.2.7...1.2.8

v1.2.7: 3/6/2013
------------------
 - Added SDL_Mixer support.
 - Implemented stubs for several Unix and threading-related functions.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.2.6...1.2.7

v1.2.6: 3/5/2013
------------------
 - Relooper updates.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.2.5...1.2.6

v1.2.5: 3/5/2013
------------------
 - Greatly improve GL emulation support.
 - Handle %c in sscanf.
 - Improve compilation times by optimizing parallel execution in the linker.
 - Improve several compiler stability issues detected from fuzzing tests.
 - Implemented emscripten_jcache_printf.
 - Allow running emscripten.py outside emcc itself.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.2.4...1.2.5

v1.2.4: 2/2/2013
------------------
 - Work on adding support for asm.js compilation.
 - Improve EGL support.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.2.3...1.2.4

v1.2.3: 1/9/2013
------------------
 - Work on adding support for asm.js compilation.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.2.2...1.2.3

v1.2.2: 1/8/2013
------------------
 - Work on adding support for asm.js compilation.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.2.1...1.2.2

v1.2.1: 1/8/2013
------------------
 - Improvements to GLUT, SDL and BSD sockets headers.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.2.0...1.2.1

v1.2.0: 1/1/2013
------------------
 - Work on adding support for asm.js compilation.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.1.0...1.2.0

v1.1.0: 12/12/2012
------------------
 - Fix several issues with Windows support.
 - Added a standalone toolchain for CMake.
 - Added emscripten_run_script_string().
 - Optimize compilation times via threading.
 - Update to requiring Clang 3.2. Older versions may no longer work.
 - Several improvements to emscripten library support headers.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.0.1a...1.1.0

v1.0.1a: 11/11/2012
------------------
 - Add relooper code to repository.
 - Full list of changes: https://github.com/emscripten-core/emscripten/compare/1.0.1...1.0.1a

v1.0.1: 11/11/2012
------------------
 - First commit that introduced versioning to the Emscripten compiler.

Talks and Publications

Papers

Books

  • WebGL Insights: Desaulniers, N. (2015). Chapter 5: Emscripten and WebGL. In P. Cozzi, WebGL Insights (pp. 71-88). Boca Raton, Florida: A K Peters/CRC Press. Amazon CRC Press.
  • HTML5 Game Development Insights — Book with a chapter on Emscripten (2014).

Getting Started

Now you know why Emscripten is right for you, it’s time to get started.

This section provides a walk-through of downloading and installing the SDK and the basics of using the Emscripten toolchain. The general FAQ answers many common questions about setting up and using Emscripten.

We also explain where to Report Bugs in the toolchain and the site. The Emscripten Test Suite is a great resource for finding examples of how to use Emscripten.

Download and install

Note

You can also build Emscripten from source if you prefer that to downloading binaries using the emsdk.

Note

There are additional ways to install Emscripten than the instructions below, for example, using brew on MacOS, the package manager on your linux distro, or a Docker image, etc. However, the emsdk is the only officially supported way to use Emscripten that is supported by the Emscripten project, and the only one that we constantly test (emsdk CI, Emscripten GitHub CI, Chromium CI). (While we don’t officially support other ways of getting Emscripten, we definitely appreciate the efforts by third parties to package Emscripten for users’ convenience, and we’d like to help out, please get in touch if you are such a packager!)

Installation instructions

First check the Platform-specific notes below and install any prerequisites.

The core Emscripten SDK (emsdk) driver is a Python script. You can get it for the first time with

# Get the emsdk repo
git clone https://github.com/emscripten-core/emsdk.git

# Enter that directory
cd emsdk

Note

You can also get the emsdk without git, by selecting “Clone or download => Download ZIP” on the emsdk GitHub page.

Run the following emsdk commands to get the latest tools from GitHub and set them as active:

# Fetch the latest version of the emsdk (not needed the first time you clone)
git pull

# Download and install the latest SDK tools.
./emsdk install latest

# Make the "latest" SDK "active" for the current user. (writes ~/.emscripten file)
./emsdk activate latest

# Activate PATH and other environment variables in the current terminal
source ./emsdk_env.sh

Note

On Windows, run emsdk instead of ./emsdk, and emsdk_env.bat instead of source ./emsdk_env.sh.

Note

git pull will fetch the current list of tags, but very recent ones may not yet be present there. You can run ./emsdk update-tags to update the list of tags directly.

If you change the location of the SDK (e.g. take it to another computer on an USB), re-run the ./emsdk activate latest and source ./emsdk_env.sh commands.

Emsdk install targets

In the description above we asked the emsdk to install and activate latest, which is the latest tagged release. That is often what you want.

You can also install a specific version by specifying it, for example,

./emsdk install 1.38.45

Note

When installing old versions from before the build infrastructure rewrite (anything before 1.38.33), you need to write something like ./emsdk install sdk-1.38.20-64bit (add sdk- and -64bit) as that was the naming convention at the time.

You can also specify which backend you want to use, either fastcomp or upstream (without specifying the backend, the current default is used), for example,

# Get a specific version using the upstream backend.
./emsdk install latest-upstream

# Get a specific version using the fastcomp backend.
./emsdk install 1.38.45-fastcomp

There are also “tip-of-tree builds”, which are the very latest code that passes integration tests on Chromium CI. This is updated much more frequently than tagged releases, but may be less stable (we tag releases manually using a more careful procedure). Tip-of-tree builds may be useful for continuous integration that uses the emsdk (as Emscripten’s GitHub CI does), and you may want to use it in your own CI as well, so that if you find a regression on your project you can report it and prevent it from reaching a tagged release. Tip-of-builds may also be useful if you want to test a feature that just landed but didn’t reach a release yet. To use a tip-of-tree build, use the tot target, and note that you must specify the backend explicitly,

# Get a tip-of-tree using the upstream backend.
./emsdk install tot-upstream

# Get a tip-of-tree using the fastcomp backend.
./emsdk install tot-fastcomp

(In the above examples we installed the various targets; remember to also activate them as in the full example from earlier.)

Platform-specific notes

Windows
  1. Install Python 2.7.12 or newer (older versions may not work due to a GitHub change with SSL).

Note

Instead of running emscripten on Windows directly, you can use the Windows Subsystem for Linux to run it in a Linux environment.

macOS

If you use MacOS 10.13.3 or later then you should have a new enough version of Python installed (older versions may not work due to a GitHub change with SSL). Otherwise you can manually install and use Python 2.7.12 or newer.

These instructions explain how to install all the required tools. You can test whether some of these are already installed on the platform and skip those steps.

  1. Install the Xcode Command Line Tools. These are a precondition for git.
  • Install Xcode from the macOS App Store.
  • In Xcode | Preferences | Downloads, install Command Line Tools.
  1. Install git:
  1. Install cmake if you do not have it yet:
Linux

Note

Emsdk does not install any tools to the system, or otherwise interact with Linux package managers. All file changes are done inside the emsdk/ directory.

  • Python, CMake, and Java are not provided by emsdk. The user is expected to install these beforehand with the system package manager:

    # Install Python
    sudo apt-get install python2.7
    
    # Install CMake (optional, only needed for tests and building Binaryen)
    sudo apt-get install cmake
    
    # Install Java (optional, only needed for Closure Compiler minification)
    sudo apt-get install default-jre
    

Note

You need Python 2.7.12 or newer because older versions may not work due to a GitHub change with SSL).

Note

If you want to use your system’s Node.js instead of the emsdk’s, it may be node instead of nodejs, and you can adjust the NODE_JS attribute of your ~/.emscripten file to point to it.

  • Git is not installed automatically. Git is only needed if you want to use tools from one of the development branches emscripten-incoming or emscripten-master:

    # Install git
    sudo apt-get install git-core
    

Verifying the installation

The easiest way to verify the installation is to compile some code using Emscripten.

You can jump ahead to the Emscripten Tutorial, but if you have any problems building you should run through the basic tests and troubleshooting instructions in Verifying the Emscripten Development Environment.

Updating the SDK

Tip

You only need to install the SDK once! After that you can update to the latest SDK at any time using Emscripten SDK (emsdk).

Type the following in a command prompt

# Fetch the latest registry of available tools.
./emsdk update

# Download and install the latest SDK tools.
./emsdk install latest

# Set up the compiler configuration to point to the "latest" SDK.
./emsdk activate latest

# Activate PATH and other environment variables in the current terminal
source ./emsdk_env.sh

The package manager can do many other maintenance tasks ranging from fetching specific old versions of the SDK through to using the versions of the tools on GitHub (or even your own fork). Check out all the possibilities in the “How to” guides.

Uninstalling the Emscripten SDK

If you want to remove the whole SDK, just delete the directory containing the SDK.

It is also possible to remove specific tools in the SDK using emsdk.

Emscripten Tutorial

Using Emscripten is, at a base level, fairly simple. This tutorial takes you through the steps needed to compile your first Emscripten examples from the command line. It also shows how to work with files and set the main compiler optimization flags.

First things first

Make sure you have downloaded and installed Emscripten (the exact approach for doing this will depend your operating system: Linux, Windows, or Mac).

Emscripten is accessed using the Emscripten Compiler Frontend (emcc). This script invokes all the other tools needed to build your code, and can act as a drop-in replacement for a standard compiler like gcc or clang. It is called on the command line using ./emcc or ./em++.

Note

On Windows the tool is called using the slightly different syntax: emcc or em++. The remainder of this tutorial uses the Linux approach (./emcc).

For the next section you will need to open a command prompt:

  • On Linux or macOS, open a Terminal.
  • On Windows open the Emscripten Command Prompt, a command prompt that has been pre-configured with the correct system paths and settings to point to the active Emscripten tools. To access this prompt, type Emscripten in the Windows 8 start screen, and then select the Emscripten Command Prompt option.

Navigate with the command prompt to the emscripten directory under the SDK. This is a folder below the emsdk root directory, typically <emsdk root directory>/fastcomp/emscripten/ (for the older “fastcomp” compiler; for the newer upstream LLVM wasm backend it will be <emsdk root directory>/upstream/emscripten/). The examples below will depend on finding files relative to that location.

Note

In older emscripten versions the directory structure was different: the version number appeared, and the backend (fastcomp/upstream) did not, so you would use something like <emsdk root directory>/emscripten/1.20.0/.

Verifying Emscripten

If you haven’t run Emscripten before, run it now with:

./emcc -v

If the output contains warnings about missing tools, see Verifying the Emscripten Development Environment for debugging help. Otherwise continue to the next sections where we’ll build some code.

Running Emscripten

You can now compile your first C/C++ file to JavaScript.

First, lets have a look at the file to be compiled: hello_world.c. This is the simplest test code in the SDK, and as you can see, all it does is print “hello, world!” to the console and then exit.

/*
 * Copyright 2011 The Emscripten Authors.  All rights reserved.
 * Emscripten is available under two separate licenses, the MIT license and the
 * University of Illinois/NCSA Open Source License.  Both these licenses can be
 * found in the LICENSE file.
 */

#include <stdio.h>

int main() {
  printf("hello, world!\n");
  return 0;
}

To build the JavaScript version of this code, simply specify the C/C++ file after emcc (use em++ to force compilation as C++):

./emcc tests/hello_world.c

You should see two files generated by that command: a.out.js and a.out.wasm. The second is a WebAssembly file containing the compiled code, and the first is a JavaScript file containing the runtime support to load and execute it. You can run them using node.js:

node a.out.js

This prints “hello, world!” to the console, as expected.

Note

Older node.js versions do not have WebAssembly support yet. In that case you will see an error message suggesting that you build with -s WASM=0 to disable WebAssembly, and then emscripten will emit the compiled code as JavaScript. In general, WebAssembly is recommended as it has widespread browser support and is more efficient both to execute and to download (and therefore emscripten emits it by default), but sometimes you may need your code to run in an environment where it is not yet present and so should disable it.

Tip

If an error occurs when calling emcc, run it with the -v option to print out a lot of useful debug information.

Note

In this section, and later on, we run some files from the tests/ folder. That folder contains files for the Emscripten test suite. Some can be run standalone, but others must be run through the test harness itself, see Emscripten Test Suite for more information.

Generating HTML

Emscripten can also generate HTML for testing embedded JavaScript. To generate HTML, use the -o (output) command and specify an html file as the target file:

./emcc tests/hello_world.c -o hello.html

You can now open hello.html in a web browser.

Note

Unfortunately several browsers (including Chrome, Safari, and Internet Explorer) do not support file:// XHR requests, and can’t load extra files needed by the HTML (like a .wasm file, or packaged file data as mentioned lower down). For these browsers you’ll need to serve the files using a local webserver and then open http://localhost:8000/hello.html).

Once you have the HTML loaded in your browser, you’ll see a text area for displaying the output of the printf() calls in the native code.

The HTML output isn’t limited just to just displaying text. You can also use the SDL API to show a colored cube in a <canvas> element (on browsers that support it). For an example, build the hello_world_sdl.cpp test code and then refresh the browser:

./emcc tests/hello_world_sdl.cpp -o hello.html

The source code for the second example is given below:

// Copyright 2011 The Emscripten Authors.  All rights reserved.
// Emscripten is available under two separate licenses, the MIT license and the
// University of Illinois/NCSA Open Source License.  Both these licenses can be
// found in the LICENSE file.

#include <stdio.h>
#include <SDL/SDL.h>

#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#endif

extern "C" int main(int argc, char** argv) {
  printf("hello, world!\n");

  SDL_Init(SDL_INIT_VIDEO);
  SDL_Surface *screen = SDL_SetVideoMode(256, 256, 32, SDL_SWSURFACE);

#ifdef TEST_SDL_LOCK_OPTS
  EM_ASM("SDL.defaults.copyOnLock = false; SDL.defaults.discardOnLock = true; SDL.defaults.opaqueFrontBuffer = false;");
#endif

  if (SDL_MUSTLOCK(screen)) SDL_LockSurface(screen);
  for (int i = 0; i < 256; i++) {
    for (int j = 0; j < 256; j++) {
#ifdef TEST_SDL_LOCK_OPTS
      // Alpha behaves like in the browser, so write proper opaque pixels.
      int alpha = 255;
#else
      // To emulate native behavior with blitting to screen, alpha component is ignored. Test that it is so by outputting
      // data (and testing that it does get discarded)
      int alpha = (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(screen); 

  printf("you should see a smoothly-colored square - no sharp lines but the square borders!\n");
  printf("and here is some text that should be HTML-friendly: amp: |&| double-quote: |\"| quote: |'| less-than, greater-than, html-like tags: |<cheez></cheez>|\nanother line.\n");

  SDL_Quit();

  return 0;
}

Using files

Note

Your C/C++ code can access files using the normal libc stdio API (fopen, fclose, etc.)

JavaScript is usually run in the sandboxed environment of a web browser, without direct access to the local file system. Emscripten simulates a file system that you can access from your compiled C/C++ code using the normal libc stdio API.

Files that you want to access should be preloaded or embedded into the virtual file system. Preloading (or embedding) generates a virtual file system that corresponds to the file system structure at compile time, relative to the current directory.

The hello_world_file.cpp example shows how to load a file (both the test code and the file to be loaded shown below):

// Copyright 2012 The Emscripten Authors.  All rights reserved.
// Emscripten is available under two separate licenses, the MIT license and the
// University of Illinois/NCSA Open Source License.  Both these licenses can be
// found in the LICENSE file.

#include <stdio.h>
int main() {
  FILE *file = fopen("tests/hello_world_file.txt", "rb");
  if (!file) {
    printf("cannot open file\n");
    return 1;
  }
  while (!feof(file)) {
    char c = fgetc(file);
    if (c != EOF) {
      putchar(c);
    }
  }
  fclose (file);
  return 0;
}

==
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.
==

Note

The example expects to be able to load a file located at tests/hello_world_file.txt:

FILE *file = fopen("tests/hello_world_file.txt", "rb");

We compile the example from the directory “above” tests to ensure that virtual filesystem is created with the correct structure relative to the compile-time directory.

The following command is used to specify a data file to preload into Emscripten’s virtual file system — before running any compiled code. This approach is useful because Browsers can only load data from the network asynchronously (except in Web Workers) while a lot of native code uses synchronous file system access. Preloading ensures that the asynchronous download of data files is complete (and the file is available) before compiled code has the opportunity to access the Emscripten file system.

./emcc tests/hello_world_file.cpp -o hello.html --preload-file tests/hello_world_file.txt

Run the above command, then open hello.html in a web browser to see the data from hello_world_file.txt being displayed.

For more information about working with the file system see the File System Overview, File System API and Synchronous Virtual XHR Backed File System Usage.

Optimizing code

Emscripten, like gcc and clang, generates unoptimized code by default. You can generate slightly-optimized code with the -O1 command line argument:

./emcc -O1 tests/hello_world.cpp

The “hello world” code created in a.out.js doesn’t really need to be optimized, so you won’t see a difference in speed when compared to the unoptimized version.

However, you can compare the generated code to see the differences. -O1 applies several minor optimizations and removes some runtime assertions. For example, printf will have been replaced by puts in the generated code.

The optimizations provided by -O2 (see here) are much more aggressive. If you run the following command and inspect the generated code (a.out.js) you will see that it looks very different:

./emcc -O2 tests/hello_world.cpp

For more information about compiler optimization options see Optimizing Code and the emcc tool reference.

Emscripten Test Suite and Benchmarks

Emscripten has a comprehensive test suite, which covers virtually all Emscripten functionality. These tests are an excellent resource for developers as they provide practical examples of most features, and are known to build successfully on the master branch.

See Emscripten Test Suite for more information.

General tips and next steps

This tutorial walked you through your first steps in calling Emscripten from the command line. There is, of course, far more you can do with the tool. Below are other general tips for using Emscripten:

Emscripten Test Suite

Emscripten has a comprehensive test suite, which covers virtually all Emscripten functionality. These tests are an excellent resource for developers as they provide practical examples of most features, and are known to pass on the master branch. In addition to correctness tests, there are also benchmarks that you can run.

This article explains how to run the test and benchmark suite, and provides an overview of what tests are available.

Setting up

To run the tests, you need an emscripten setup, as it will run emcc and other commands. See the developer’s guide for how best to do that.

Running tests

Run the test suite runner (tests/runner.py) with no arguments to see the help message:

python tests/runner.py

The tests are divided into modes. You can run either an entire mode or an individual test, or use wildcards to run some tests in some modes. For example:

# run one test (in the default mode)
python tests/runner.py test_loop

# run one test in a specific mode (here, asm.js -O2)
python tests/runner.py asm2.test_loop

# run a test in a bunch of modes (here, all asm.js modes)
python tests/runner.py asm*.test_loop

# run a bunch of tests in one mode (here, all i64 tests in wasm -O3)
python tests/runner.py wasm3.test_*i64*

# run all tests in a specific mode (here, asm.js -O1)
python tests/runner.py asm1

The core test modes (defined at the bottom of tests/test_core.py) let you run a specific test in either asm.js or wasm, and with different optimization flags. There are also non-core test modes, that run tests in more special manner (in particular, in those tests it is not possible to say “run the test with a different optimization flag” - that is what the core tests are for). The non-core test modes include

  • other: Non-core tests running in the shell.
  • browser: Tests that run in a browser.
  • sockets: Networking tests that run in a browser.
  • interactive: Browser tests that are not fully automated, and require user interaction (these should be automated eventually).
  • sanity: Tests for emscripten setting itself up. This modifies your .emscripten file temporarily.
  • benchmark: Runs benchmarks, measuring speed and code size.

The wildcards we mentioned above work for non-core test modes too, for example:

# run one browser test
python tests/runner.py browser.test_sdl_image

# run all SDL2 browser tests
python tests/runner.py browser.test_sdl2*

# run all browser tests
python tests/runner.py browser

Skipping Tests

An individual test can be skipped by passing the “skip:” prefix. E.g.

python tests/runner.py other skip:other.test_cmake

Wildcards can also be passed in skip, so

python tests/runner.py browser skip:browser.test_pthread_*

will run the whole browser suite except for all the pthread tests in it.

Running a bunch of random tests

You can run a random subset of the test suite, using something like

python tests/runner.py random100

Replace 100 with another number as you prefer. This will run that number of random tests, and tell you the statistical likelihood of almost all the test suite passing assuming those tests do. This works just like election surveys do - given a small sample, we can predict fairly well that so-and-so percent of the public will vote for candidate A. In our case, the “candidates” are pass or fail, and we can predict how much of the test suite will pass given that sample. Assuming the sample tests all pass, we can say with high likelihood that most of the test suite will in fact pass. (Of course, this is no guarantee, and even a single test failure is serious, however, this gives a quick estimate that your patch does not cause significant and obvious breakage.)

Important Tests

Please see the bottom the file tests/test_core.py for the current test modes, as they may change slowly over time. When you want to run the entire test suite locally, these are currently the important commands:

# Run all core wasm tests
python tests/runner.py wasm*

# Run "other" test suite
python tests/runner.py other

# Run "browser" test suite - this requires a web browser
python tests/runner.py browser

# Run "sockets" test suite - this requires a web browser too
python tests/runner.py sockets

# Run "sanity" test suite - this tests setting up emscripten during
# first run, etc., and so it modifies your .emscripten file temporarily.
python tests/runner.py sanity

# Optionally, also run benchmarks to check for regressions
python tests/runner.py benchmark

Benchmarking

Emscripten has a benchmark suite that measures both speed and code size. To run it, do:

# Run all benchmarks
python tests/runner.py benchmark

Usually you will want to customize the python in tests/test_benchmark.py to run the benchmarks you want, see benchmarkers in the source code.

Debugging test failures

Setting the Debug mode (EMCC_DEBUG) is useful for debugging tests, as it emits debug output and intermediate files (the files go in /tmp/emscripten_temp/):

# On Windows, use "set" to set and un-set the EMCC_DEBUG environment variable:
set EMCC_DEBUG=1
python tests/runner.py test_hello_world
set EMCC_DEBUG=0

# On Linux, you can do this all in one line
EMCC_DEBUG=1 python tests/runner.py test_hello_world

# EMCC_DEBUG=2 generates additional debug information.
EMCC_DEBUG=2 python tests/runner.py test_hello_world

You can also specify EMTEST_SAVE_DIR=1 in the environment to save the temporary directory that the test runner uses into /tmp/emscripten_test/. This is a test suite-specific feature, and is useful for inspecting test outputs as well as temporary files generated by the test. By default, the temporary directory will be cleaned between each test run, but setting EMTEST_SAVE_DIR=2 will preserve the directory even when a new test is started.

The Debugging topic provides more guidance on how to debug Emscripten-generated code.

Bug Reporting

All bugs should be filed in the GitHub main Emscripten repository Issue Tracker.

Please supply as much relevant information as possible, including:

  • Original source code.
  • Generated bitcode (.bc, .o or .ll)
  • Environment information — including emcc and clang versions (as reported by emcc -v).
  • Error symptoms.
  • Proposed solutions, ideally with a pull request.

Tip

Compile with EMCC_DEBUG=1 and grab the /tmp/emscripten_temp/emcc-* files (these include the bitcode and JavaScript in several stages). Note that the emscripten_temp directory should be emptied manually first, so it only contains new content!

LLVM, wasm-ld, clang, Binaryen bugs

If uncertain, bugs can always be posted to the main repository. But if you are sure a bug is in an upstream project, you can file it there:

  • LLVM bug tracker . For most issues use the “libraries” product and the “Backend: WebAssembly” component. For wasm-ld issues, use “lld” and “wasm”.
  • Binaryen bug tracker

Pull requests must (of course) go to the proper repository.

Site and documentation bugs

Documentation (site) bugs should be filed in the same Issue Tracker.

Include relevant information including:

  • The URL and title of the affected page(s).
  • A description of the problem.
  • Suggestions for a possible solution.

Tip

The Page bug link on the bottom-right of every page opens the Issue Tracker pre-seeded with the current page URL and title.

FAQ

This FAQ contains answers to many questions asked on IRC and the mailing list.

How do I compile code?

See the Emscripten Tutorial and emcc.

Why do I get multiple errors building basic code and the tests?

All the tests in the Emscripten test suite are known to build and pass on our test infrastructure, so if you see failures locally it is likely that there is some problem with your environment. (Rarely, there may be temporary breakage, but never on a tagged release version.)

First call emcc -v, which runs basic sanity checks and prints out useful environment information. If that doesn’t help, follow the instructions in Verifying the Emscripten Development Environment.

You might also want to go through the Emscripten Tutorial again, as it is updated as Emscripten changes.

I tried something: why doesn’t it work?

Some general steps that might help figure things out:

  • See if the problem happens without optimizations (-O0, or not specifying any optimization level). Without optimizations, emscripten enables many assertions at compile and runtime, which may catch a problem and display an error message with a suggestion for how to fix it.
  • Search the documentation on this site.
  • Check if there is a test for the failing functionality in the Emscripten test suite (run grep -r in tests/). They should all pass (with only rare exceptions), so they provide concrete “known-good” examples of how various options and code are used.

Do I need to change my build system to use Emscripten?

In most cases you will be able to use your project’s current build system with Emscripten. See Building Projects.

Why is code compilation slow?

Emscripten makes some trade-offs that make the generated code faster and smaller, at the cost of longer compilation times. For example, we build parts of the standard library along with your code, which enables some additional optimizations, but takes a little longer to compile.

Note

You can determine what compilation steps take longest by compiling with EMCC_DEBUG=1 in the environment and then reviewing the debug logs (by default in /tmp/emscripten_temp). Note that compiling in debug mode takes longer than normal, because we print out a lot of intermediate steps to disk, so it’s useful for debugging but not for actual compiling.

The main tips for improving build time are:

  • Use -O0 for fast iteration builds. You can still compile with higher optimization levels, but specifying -O0 during link will make the link step much faster.
  • Compile on a machine with more cores:
    • For compiling your source files, use a parallel build system (for example, in make you can do something like make -j8 to run using 8 cores).
    • For the link step, Emscripten can run some optimizations in parallel (specifically, Binaryen optimizations for wasm, and our JavaScript optimizations). Increasing the number of cores results in an almost linear improvement. Emscripten will automatically use more cores if they are available, but you can control that with EMCC_CORES=N in the environment (which is useful if you have many cores but relatively less memory).

Why does my code run slowly?

Make sure you optimize code by building with -O2 (even more aggressive optimization is available, at the cost of significantly increased compilation time).

Why is my compiled code big?

Make sure you build with -O3 or -Os so code is fully optimized and minified. You should use the closure compiler, gzip compression on your webserver, etc., see the section on code size in Optimizing code.

Why does compiling code that works on another machine gives me errors?

Make sure you are using the Emscripten bundled system headers. Using emcc will do so by default, but problems may occur if you use your local system headers with emcc or compile into LLVM bitcode yourself.

How can I reduce startup time?

Make sure that you are running an optimized build (smaller builds are faster to start up).

Network latency is also a possible factor in startup time. Consider putting the file loading code in a separate script element from the generated code so that the browser can start the network download in parallel to starting up the codebase (run the file packager and put file loading code in one script element, and the generated codebase in a later script element).

How do I run a local webserver for testing / why does my program stall in “Downloading…” or “Preparing…”?

That error can happen when loading the page using a file:// URL, which works in some browsers but not in others. Instead, it’s best to use a local webserver. For example, Python has one built in, python -m http.server in Python 3 or python -m SimpleHTTPServer in Python 2. After doing that, you can visit http://localhost:8000/.

Otherwise, to debug this, look for an error reported on the page itself, or in the browser devtools (web console and network tab), or in your webserver’s logging.

What is “No WebAssembly support found. Build with -s WASM=0 to target JavaScript instead” or “no native wasm support detected”?

Those errors indicate that WebAssembly support is not present in the VM you are trying to run the code in. Compile with -s WASM=0 to disable WebAssembly (and emit asm.js instead) if you want your code to run in such environments (all modern browsers support WebAssembly, but in some cases you may want to reach 100% of browsers, including legacy ones).

Why do I get machine type must be wasm32 or is not a valid input file during linking?

The first error means the linker inputs did not contain wasm32 code - that is, they contain instructions in some other format, like native x86 or ARM or something like that. You can run the file command-line utility to see what they actually contain. Common issues are:

  • LLVM IR from the old backend, if you built the project with a version before 1.39.0 (which used the old backend by default), and are doing an incremental rebuild now. To fix that, do a complete rebuild from scratch of all your project’s files, including libraries (this error often happens if you have prebuilt libraries from a third party; those must be recompiled too with the new backend).
  • The build system was run without emscripten integration, and emitted native code. To fix that, use emconfigure/emmake, see Building Projects. In this case emcc.py will show that second error, “is not a valid input file”.

Why does my code fail to compile with an error message about inline assembly (or {"text":"asm"})?

Emscripten cannot compile inline assembly code (because it is CPU specific, and Emscripten is not a CPU emulator).

You will need to find where inline assembly is used, and disable it or replace it with platform-independent code.

Note

Emscripten automatically unsets the following #define values, as these are commonly set in projects to enable platform dependent code (inline assembly):

#undef __i386__
#undef __x86_64__

Why does my HTML app hang?

The browser event model uses co-operative multitasking — each event has a “turn” to run, and must then return control to the browser event loop so that other events can be processed. A common cause of HTML pages hanging is JavaScript that does not complete and return control to the browser.

Graphical C++ apps typically have an infinite main loop in which event handling, processing and rendering is done, followed by a delay to keep the frame-rate right (SDL_DELAY in SDL apps). As the main loop does not complete (is infinite) it cannot return control to the browser, and the app will hang.

Apps that use an infinite main loop should be re-coded to put the actions for a single iteration of the loop into a single “finite” function. In the native build this function can be run in an infinite loop as before. In the Emscripten build it is set as the main loop function and will be called by the browser at a specified frequency.

There is more information on this topic in Emscripten Runtime Environment.

How do I run an event loop?

To run a C function repeatedly, use emscripten_set_main_loop() (this is discussed in Emscripten Runtime Environment). The related functions in emscripten.h are also useful, allowing you to add events that block the main loop, etc.

To respond to browser events use the SDL API in the normal way. There are examples in the SDL tests (search for SDL in tests/runner.py).

See also: Why does my HTML app hang?

Why doesn’t my SDL app work?

See the SDL automatic tests for working examples: python tests/runner.py browser.

What are my options for audio playback?

Emscripten has partial support for SDL1 and 2 audio, and OpenAL.

To use SDL1 audio, include it as #include <SDL/SDL_mixer.h>. You can use it that way alongside SDL1, SDL2, or another library for platform integration.

To use SDL2 audio, include it as #include <SDL2/SDL_mixer.h> and use -s USE_SDL_MIXER=2. Format support is currently limited to OGG and WAV.

How can my compiled program access files?

Emscripten uses a virtual file system that may be preloaded with data or linked to URLs for lazy loading. See the File System Overview for more details.

Why can’t my code access a file in the same directory?

Emscripten-generated code running in the browser cannot access files in the local file system. Instead you can use preloading and embedding to work around the lack of synchronous file IO. See File System Overview for more information.

It is possible to allow access to local file system for code running in node.js, use the NODEFS filesystem option.

How can I tell when the page is fully loaded and it is safe to call compiled functions?

(You may need this answer if you see an error saying something like you need to wait for the runtime to be ready (e.g. wait for main() to be called), which is a check enabled in ASSERTIONS builds.)

Calling a compiled function before a page has fully loaded can result in an error, if the function relies on files that may not be present (for example the .mem file and preloaded files are loaded asynchronously, and therefore if you just place some JS that calls compiled code in a --post-js, that code will be called synchronously at the end of the combined JS file, potentially before the asynchronous event happens, which is bad).

The easiest way to find out when loading is complete is to add a main() function, and within it call a JavaScript function to notify your code that loading is complete.

Note

The main() function is called after startup is complete as a signal that it is safe to call any compiled method.

For example, if allReady() is a JavaScript function you want called when everything is ready, you can do:

#include <emscripten.h>

int main() {
  EM_ASM( allReady() );
}

Another option is to define an onRuntimeInitialized function,

Module['onRuntimeInitialized'] = function() { ... };

That method will be called when the runtime is ready and it is ok for you to call compiled code. In practice, that is exactly the same time at which main() would be called, so onRuntimeInitialized doesn’t let you do anything new, but you can set it from JavaScript at runtime in a flexible way.

Here is an example of how to use it:

<script type="text/javascript">
  var Module = {
    onRuntimeInitialized: function() {
      Module._foobar(); // foobar was exported
    }
  };
</script>
<script type="text/javascript" src="my_project.js"></script>

The crucial thing is that Module exists, and has the property onRuntimeInitialized, before the script containing emscripten output (my_project.js in this example) is loaded.

Another option is to use the MODULARIZE option, using -s MODULARIZE=1. That puts all of the generated JavaScript into a factory function, which you can call to create an instance of your module. The factory function returns a Promise that resolves with the module instance. The promise is resolved once it’s safe to call the compiled code, i.e. after the compiled code has been downloaded and instantiated. For example, if you build with -s MODULARIZE=1 -s 'EXPORT_NAME="createMyModule"' (see details in settings.js), then you can do this:

createMyModule().then((myModule) => {
  // this is reached when everything is ready, and you can call methods on myModule
});

What does “exiting the runtime” mean? Why don’t atexit()s run?

(You may need this answer if you see an error saying something like atexit() called, but EXIT_RUNTIME is not set or stdio streams had content in them that was not flushed. you should set EXIT_RUNTIME to 1.)

By default Emscripten sets EXIT_RUNTIME=0, which means that we don’t include code to shut down the runtime. That means that when main() exits, we don’t flush the stdio streams, or call the destructors of global C++ objects, or call atexit callbacks. This lets us emit smaller code by default, and is normally what you want on the web: even though main() exited, you may have something asynchronous happening later that you want to execute.

In some cases, though, you may want a more “commandline” experience, where we do shut down the runtime when main() exits. You can build with -s EXIT_RUNTIME=1, and then we will call atexits and so forth. When you build with ASSERTIONS, you should get a warning when you need this. For example, if your program prints something without a newline,

#include <stdio.h>

int main() {
  printf("hello"); // note no newline
}

If we don’t shut down the runtime and flush the stdio streams, “hello” won’t be printed. In an ASSERTIONS build you’ll get a notification saying stdio streams had content in them that was not flushed. you should set EXIT_RUNTIME to 1.

Why do functions in my C/C++ source code vanish when I compile to JavaScript, and/or I get No functions to process?

Emscripten does dead code elimination of functions that are not called from the compiled code. While this does minimize code size, it can remove functions that you plan to call yourself (outside of the compiled code).

To make sure a C function remains available to be called from normal JavaScript, it must be added to the EXPORTED_FUNCTIONS using the emcc command line. For example, to prevent functions my_func() and main() from being removed/renamed, run emcc with:

emcc -s "EXPORTED_FUNCTIONS=['_main', '_my_func']"  ...

Note

_main should be in the export list, as in that example, if you have a main() function. Otherwise, it will be removed as dead code; there is no special logic to keep main() alive by default.

Note

EXPORTED_FUNCTIONS affects compilation to JavaScript. If you first compile to an object file, then compile the object to JavaScript, you need that option on the second command.

If your function is used in other functions, LLVM may inline it and it will not appear as a unique function in the JavaScript. Prevent inlining by defining the function with EMSCRIPTEN_KEEPALIVE:

void EMSCRIPTEN_KEEPALIVE yourCfunc() {..}

EMSCRIPTEN_KEEPALIVE also exports the function, as if it were on EXPORTED_FUNCTIONS.

Note

  • All functions not kept alive through EXPORTED_FUNCTIONS or EMSCRIPTEN_KEEPALIVE will potentially be removed. Make sure you keep the things you need alive using one or both of those methods.
  • Exported functions need to be C functions (to avoid C++ name mangling).
  • Decorating your code with EMSCRIPTEN_KEEPALIVE can be useful if you don’t want to have to keep track of functions to export explicitly, and when these exports do not change. It is not necessarily suitable for exporting functions from other libraries — for example it is not a good idea to decorate and recompile the source code of the C standard library. If you build the same source in multiple ways and change what is exported, then managing exports on the command line is easier.
  • Running emcc with -s LINKABLE=1 will also disable link-time optimizations and dead code elimination. This is not recommended as it makes the code larger and less optimized.

Another possible cause of missing code is improper linking of .a files. The .a files link only the internal object files needed by previous files on the command line, so the order of files matters, and this can be surprising. If you are linking .a files, make sure they are at the end of the list of files, and in the right order amongst themselves. Alternatively, just use .so files instead in your project.

Tip

It can be useful to compile with EMCC_DEBUG=1 set for the environment (EMCC_DEBUG=1 emcc ... on Linux, set EMMCC_DEBUG=1 on Windows). This splits up the compilation steps and saves them in /tmp/emscripten_temp. You can then see at what stage the code vanishes (you will need to do llvm-dis on the bitcode stages to read them, or llvm-nm, etc.).

Why is the File System API is not available when I build with closure?

The Closure Compiler will minify the File Server API code. Code that uses the file system must be optimized with the File System API, using emcc’s --pre-js option.

Why does my code break and gives odd errors when using -O2 --closure 1?

The Closure Compiler minifies variable names, which results in very short variable names like i, j, xa, etc. If other code declares variables with the same names in global scope, this can cause serious problems.

This is likely to be the cause if you can successfully run code compiled with -O2 set and --closure unset.

One solution is to stop using small variable names in the global scope (often this is a mistake — forgetting to use var when assigning to a variable).

Another alternative is to wrap the generated code (or your other code) in a closure, as shown:

var CompiledModule = (function() {
  .. GENERATED CODE ..
  return Module;
  })();

Why do I get TypeError: Module.someThing is not a function?

The Module object will contain exported methods. For something to appear there, you should add it to EXPORTED_FUNCTIONS for compiled code, or EXTRA_EXPORTED_RUNTIME_METHODS for a runtime method (like getValue). For example,

emcc -s "EXPORTED_FUNCTIONS=['_main', '_my_func']" ...

would export a C method my_func (in addition to main, in this example). And

emcc -s "EXTRA_EXPORTED_RUNTIME_METHODS=['ccall']" ...

will export ccall. In both cases you can then access the exported function on the Module object.

Note

You can use runtime methods directly, without exporting them, if the compiler can see them used. For example, you can use getValue in EM_ASM code, or a --pre-js, by calling it directly. The optimizer will not remove that JS runtime method because it sees it is used. You only need to use Module.getValue if you want to call that method from outside the JS code the compiler can see, and then you need to export it.

Note

Emscripten used to export many runtime methods by default. This increased code size, and for that reason we’ve changed that default. If you depend on something that used to be exported, you should see a warning pointing you to the solution, in an unoptimized build, or a build with ASSERTIONS enabled, which we hope will minimize any annoyance. See ChangeLog.md for details.

Why does Runtime no longer exist? Why do I get an error trying to access Runtime.someThing?

1.37.27 includes a refactoring to remove the Runtime object. This makes the generated code more efficient and compact, but requires minor changes if you used Runtime.* APIs. You just need to remove the Runtime. prefix, as those functions are now simple functions in the top scope (an error message in -O0 or builds with assertions enabled with suggest this). In other words, replace

x = Runtime.stackAlloc(10);

with

x = stackAlloc(10);

Note

The above will work for code in a --pre-js or JS library, that is, code that is compiled together with the emscripten output. If you try to access Runtime.* methods from outside the compiled code, then you must export that function (using EXTRA_EXPORTED_RUNTIME_METHODS), and use it on the Module object, see that FAQ entry.

Why do I get a NameError or a problem occurred in evaluating content after a "-s" when I use a -s option?

That may occur when running something like

# this fails on most Linuxes
emcc a.c -s EXTRA_EXPORTED_RUNTIME_METHODS=['addOnPostRun']

# this fails on macOS
emcc a.c -s EXTRA_EXPORTED_RUNTIME_METHODS="['addOnPostRun']"

You may need to quote things like this:

# this works in the shell on most Linuxes and on macOS
emcc a.c -s "EXTRA_EXPORTED_RUNTIME_METHODS=['addOnPostRun']"

# or you may need something like this in a Makefile
emcc a.c -s EXTRA_EXPORTED_RUNTIME_METHODS=\"['addOnPostRun']\"

The proper syntax depends on the OS and shell you are in, and if you are writing in a Makefile, etc.

Why do I get an odd python error complaining about libcxx.bc or libcxxabi.bc?

A possible cause is that building libcxx or libcxxabi failed. Go to system/lib/libcxx (or libcxxabi) and do emmake make to see the actual error. Or, clean the Emscripten cache (./emcc --clear-cache) and then compile your file with EMCC_DEBUG=1 in the environment. libcxx will then be built in /tmp/emscripten_temp/libcxx, and you can see configure*, make* files that are the output of configure and make, etc.

Another possible cause of this error is the lack of make, which is necessary to build these libraries. If you are on Windows, you need cmake.

Why do I get an error mentioning Uglify and throw new JS_Parse_Error?

In -O2 and above, emscripten will optimize the JS using Uglify1. If you added any JS (using --pre-js/--post-js/EM_ASM/EM_JS) and it contains JS that Uglify1 can’t parse - like recent ES6 features - then it will throw such a parsing error.

In the long term we hope to upgrade our internal JS parser. Meanwhile, you can move such code to another script tag on the page, that is, not pass it through the emscripten optimizer.

See also

Why does running LLVM bitcode generated by emcc through lli break with errors about impure_ptr?

Note

lli is not maintained, and has odd errors and crashes. We do include tools/nativize_llvm.py (which compiles bitcode to a native executable) but it will also hit the impure_ptr error.

The issue is that newlib uses impure_ptr code, while glibc uses something else. The result is that bitcode built with the Emscripten will not run locally unless your machine uses newlib (basically, only embedded systems).

The impure_ptr error only occurs during explicit use of stdout etc., so printf(..) will work, but fprintf(stdout, ..) will not. Usually it is simple to modify your code to avoid this problem.

Why do I get a stack size error when optimizing: RangeError: Maximum call stack size exceeded or similar?

You may need to increase the stack size for node.js.

On Linux and Mac macOS, you can just do NODE_JS = ['node', '--stack_size=8192'] in the Emscripten Compiler Configuration File (.emscripten). On Windows, you will also need --max-stack-size=8192, and also run editbin /stack:33554432 node.exe.

Why do I get error: cannot compile this aggregate va_arg expression yet and it says compiler frontend failed to generate LLVM bitcode, halting afterwards?

This is a limitation of the asm.js target in Clang. This code is not currently supported.

Why does building from source fail during linking (at 100%)?

Building Fastcomp from source (and hence the SDK) can fail at 100% progress. This is due to out of memory in the linking stage, and is reported as an error: collect2: error: ld terminated with signal 9 [Killed].

The solution is to ensure the system has sufficient memory. On Ubuntu 14.04.1 LTS 64bit, you should use at least 6Gb.

Why do I get odd rounding errors when using float variables?

In asm.js, by default Emscripten uses doubles for all floating-point variables, that is, 64-bit floats even when C/C++ code contains 32-bit floats. This is simplest and most efficient to implement in JS as doubles are the only native numeric type. As a result, you may see rounding errors compared to native code using 32-bit floats, just because of the difference in precision between 32-bit and 64-bit floating-point values.

To check if this is the issue you are seeing, build with -s PRECISE_F32=1. This uses proper 32-bit floating-point values, at the cost of some extra code size overhead. This may be faster in some browsers, if they optimize Math.fround, but can be slower in others. See src/settings.js for more details on this option.

(This is not an issue for wasm, which has native float types.)

How do I pass int64_t and uint64_t values from js into wasm functions?

JS can’t represent int64s, so what happens is that in exported functions (that you can call from JS) we “legalize” the types, by turning an i64 argument into two i32s (low and high bits), and an i64 return value becomes an i32, and you can access the high bits by calling a helper function called getTempRet0.

Can I use multiple Emscripten-compiled programs on one Web page?

Emscripten output by default is just some code. When put in a script tag, that means the code is in the global scope. So multiple such modules on the same page can’t work.

But by putting each module in a function scope, that problem is avoided. Emscripten even has a compile flag for this, MODULARIZE, useful in conjunction with EXPORT_NAME (details in settings.js).

However, there are still some issues if the same Module object (that defines the canvas, text output area, etc.) is used among separate modules. By default Emscripten output even looks for Module in the global scope, but when using MODULARIZE, you get a function you must call with the Module as a param, so that problem is avoided. But note that each module will probably want its own canvas, text output area, etc.; just passing in the same Module object (e.g. from the default HTML shell) may not work.

So by using MODULARIZE and creating a proper Module object for each module, and passing those in, multiple modules can work fine.

Another option is to use an iframe, in which case the default HTML shell will just work, as each will have its own canvas, etc. But this is overkill for small programs, which can run modularly as described above.

Can I build JavaScript that only runs on the Web?

Yes, you can see the ENVIRONMENT option in settings.js. For example, building with emcc -s ENVIRONMENT=web will emit code that only runs on the Web, and does not include support code for Node.js and other environments.

This can be useful to reduce code size, and also works around issues like the Node.js support code using require(), which Webpack will process and include unnecessary code for.

Why the weird name for the project?

I don’t know why; it’s a perfectly cromulent word!

Compiling and Running Projects

This section contains topics about building projects and running the output.

Building Projects

Building large projects with Emscripten is very easy. Emscripten provides two simple scripts that configure your makefiles to use emcc as a drop-in replacement for gcc — in most cases the rest of your project’s current build system remains unchanged.

Integrating with a build system

To build using Emscripten you need to replace gcc with emcc in your makefiles. This is done using emconfigure, which sets the appropriate environment variables like CXX (C++ compiler) and CC (the compiler).

Consider the case where you normally build with the following commands:

./configure
make

To build with Emscripten, you would instead use the following commands:

# Run emconfigure with the normal configure command as an argument.
./emconfigure ./configure

# Run emmake with the normal make to generate linked LLVM bitcode.
./emmake make

# Compile the linked bitcode generated by make (project.bc) to JavaScript.
#  'project.bc' should be replaced with the make output for your project (e.g. 'yourproject.so')
#  [-Ox] represents build optimisations (discussed in the next section).
./emcc [-Ox] project.bc -o project.js

emconfigure is called with the normal configure as an argument (in configure-based build systems), and emmake with make as an argument. If your build system uses CMake, replace ./configure with cmake . etc. in the above example. If your build system doesn’t use configure or CMake, then you can omit the first step and just run make (although then you may need to edit the Makefile manually).

Tip

We recommend you call both emconfigure and emmake scripts in configure- and CMake-based build systems. Whether you actually need to call both tools depends on the build system (some systems will store the environment variables in the configure step, and others will not).

Make generates linked LLVM bitcode. It does not automatically generate JavaScript during linking because all the files must be compiled using the same optimizations and compiler options — and it makes sense to do this in the final conversion from bitcode to JavaScript.

Note

The file output from make might have a different suffix: .a for a static library archive, .so for a shared library, .o or .bc for object files (these file extensions are the same as gcc would use for the different types). Irrespective of the file extension, these files contain linked LLVM bitcode that emcc can compile into JavaScript in the final step. If the suffix is something else - like no suffix at all, or something like .so.1 - then you may need to rename the file before sending it to emcc.

Note

Some build systems may not properly emit bitcode using the above procedure, and you may see is not valid bitcode warnings. You can run file to check if a file contains bitcode (also you can manually check if the contents start with BC). It is also worth running emmake make VERBOSE=1 which will print out the commands it runs - you should see emcc being used, and not the native system compiler. If emcc is not used, you may need to modify the configure or cmake scripts.

Emscripten build output files

Emscripten compiler output often consists of several files and not just one. The set of produced files changes depending on the final linker flags passed to emcc/em++. Here is a cheat sheet of which files are produced under which conditions:

  • emcc … -o output.html builds a output.html file as an output, as well as an accompanying output.js launcher file, and a output.wasm WebAssembly file.
  • emcc … -o output.js omits generating a HTML launcher file (expecting you to provide it yourself if you plan to run in browser), and produces two files, output.js and output.wasm. (that can be run in e.g. node.js shell)
  • emcc … -o output.bc does not produce a final asm.js/wasm build, but stops at LLVM bitcode generation stage, and produces a single LLVM bitcode file output.bc. Likewise only one bitcode file is produced if output suffix is .ll, .o, ‘.obj’, ‘.lo’, .lib, .dylib or .so.
  • emcc … -o output.a generates a single archive file output.a.
  • emcc … -o output.{html,js} -s WASM=0 causes the compiler to target asm.js, and therefore a .wasm file is not produced.
  • emcc … -o output.{html,js} -s WASM=0 –separate-asm likewise targets asm.js, but splits up the generated code to two files, output.js and output.asm.js.
  • emcc … -o output.html -s WASM=0 -s PRECISE_F32=2 (combination of targeting .html, asm.js and PRECISE_F32=2) implies as if –separate-asm was passed, so also produces output.asm.js.
  • emcc … -o output.{html,js} –emit-symbol-map produces a file output.{html,js}.symbols if WebAssembly is being targeted (-s WASM=0 not specified), or if asm.js is being targeted and -Os, -Oz or -O2 or higher is specified, but debug level setting is -g1 or lower (i.e. if symbols minification did occur).
  • emcc … -o output.{html,js} -s WASM=0 –memory-init-file 1 causes the generation of output.{html,js}.mem memory initializer file. Pasing -O2, -Os or -Oz also implies –memory-init-file 1.
  • emcc … -o output.{html,js} -g4 generates a source map file output.wasm.map. If targeting asm.js with -s WASM=0, the filename is output.{html,js}.map.
  • emcc … -o output.{html,js} –preload-file xxx directive generates a preloaded MEMFS filesystem file output.data.
  • emcc … -o output.{html,js} -s WASM={0,1} -s SINGLE_FILE=1 merges JavaScript and WebAssembly code in the single output file output.{html,js} (in base64) to produce only one file for deployment. (If paired with –preload-file, the preloaded .data file still exists as a separate file)

This list is not exhaustive, but illustrates most commonly used combinations.

Building projects with optimizations

Emscripten performs compiler optimization at two levels: each source file is optimized by LLVM as it is compiled into an object file, and then JavaScript/WebAssembly-specific optimizations are applied when converting object files into the final JavaScript/WebAssembly.

In order to properly optimize code, it is usually best to use the same optimization flags and other compiler options when compiling source to object code, and object code to JavaScript (or HTML).

Consider the examples below:

# Sub-optimal - JavaScript/WebAssembly optimizations are omitted
./emcc -O2 a.cpp -o a.bc
./emcc -O2 b.cpp -o b.bc
./emcc a.bc b.bc -o project.js

# Sub-optimal - LLVM optimizations omitted
./emcc a.cpp -o a.bc
./emcc b.cpp -o b.bc
./emcc -O2 a.bc b.bc -o project.js

# Usually the right thing: The SAME LLVM and JavaScript options are provided at both levels.
./emcc -O2 a.cpp -o a.bc
./emcc -O2 b.cpp -o b.bc
./emcc -O2 a.bc b.bc -o project.js

However, sometimes you may want slightly different optimizations on certain files:

# Optimize the first file for size, and the rest using `-O2`.
./emcc -Oz a.cpp -o a.bc
./emcc -O2 b.cpp -o b.bc
./emcc -O2 a.bc b.bc -o project.js

Note

Unfortunately each build-system defines its own mechanisms for setting compiler and optimization methods. You will need to work out the correct approach to set the LLVM optimization flags for your system.

  • Some build systems have a flag like ./configure --enable-optimize.
  • You can control whether LLVM optimizations are run using --llvm-opts N where N is an integer in the range 0-3. Sending -O2 --llvm-opts 0 to emcc during all compilation stages will disable LLVM optimizations but utilize JavaScript optimizations. This can be useful when debugging a build failure.

JavaScript/WebAssembly optimizations are specified in the final step (sometimes called “link”, as that step typically also links together a bunch of files that are all compiled together into one JavaScript/WebAssembly output). For example, to compile with -O1:

# Compile the linked bitcode to JavaScript with -O1 optimizations.
./emcc -O1 project.bc -o project.js

Building projects with debug information

Building a project containing debug information requires that debug flags are specified for both the LLVM and JavaScript compilation phases.

To make Clang and LLVM emit debug information in the bitcode files you need to compile the sources with -g (exactly the same as with clang or gcc normally). To get emcc to include the debug information when compiling the bitcode to JavaScript, specify -g or one of the -gN debug level options.

Note

Each build-system defines its own mechanisms for setting debug flags. To get Clang to emit LLVM debug information, you will need to work out the correct approach for your system.

  • Some build systems have a flag like ./configure --enable-debug.

The flags for emitting debug information when compiling from bitcode to JavaScript are specified as an emcc option in the final step:

# Compile the linked bitcode to JavaScript.
# -g or -gN can be used to set the debug level (N)
./emcc -g project.bc -o project.js

For more general information, see the topic Debugging.

Using libraries

Built-in support is available for a number of standard libraries: libc, libc++ and SDL. These will automatically be linked when you compile code that uses them (you do not even need to add -lSDL, but see below for more SDL-specific details).

If your project uses other libraries, for example zlib or glib, you will need to build and link them. The normal approach is to build the libraries to bitcode and then compile library and main program bitcode together to JavaScript.

For example, consider the case where a project “project” uses a library “libstuff”:

# Compile libstuff to bitcode
./emconfigure ./configure
./emmake make

# Compile project to bitcode
./emconfigure ./configure
./emmake make

# Compile the library and code together to HTML
emcc project.bc libstuff.bc -o final.html

It is also possible to link the bitcode libraries first, and then compile the combined .bc file to JavaScript:

# Generate bitcode files project.bc and libstuff.bc
...

# Link together the bitcode files
emcc project.bc libstuff.bc -o allproject.bc

# Compile the combined bitcode to HTML
emcc allproject.bc -o final.html

Emscripten Ports

Emscripten Ports is a collection of useful libraries, ported to Emscripten. They reside on github, and have integration support in emcc. When you request that a port be used, emcc will fetch it from the remote server, set it up and build it locally, then link it with your project, add necessary include to your build commands, etc. For example, SDL2 is in ports, and you can request that it be used with -s USE_SDL=2. For example,

./emcc tests/sdl2glshader.c -s USE_SDL=2 -s LEGACY_GL_EMULATION=1 -o sdl2.html

You should see some notifications about SDL2 being used, and built if it wasn’t previously. You can then view sdl2.html in your browser.

Note

SDL_image has also been added to ports, use it with -s USE_SDL_IMAGE=2. To see a list of all available ports, run emcc --show-ports. For SDL2_image to be useful, you generally need to specify the image formats you are planning on using with e.g. -s SDL2_IMAGE_FORMATS='["bmp","png","xpm"]' (note: jpg support is not available yet as of Jun 22 2018 - libjpg needs to be added to emscripten-ports). This will also ensure that IMG_Init works properly when you specify those formats. Alternatively, you can use emcc --use-preload-plugins and --preload-file your images, so the browser codecs decode them (see Preloading files). A code path in the SDL2_image port will load through emscripten_get_preloaded_image_data(), but then your calls to IMG_Init with those image formats will fail (as while the images will work through preloading, IMG_Init reports no support for those formats, as it doesn’t have support compiled in - in other words, IMG_Init does not report support for formats that only work through preloading).```

Note

SDL_net has also been added to ports, use it with -s USE_SDL_NET=2. To see a list of all available ports, run emcc --show-ports.

Note

Emscripten also has support for older SDL1, which is built-in. If you do not specify SDL2 as in the command above, then SDL1 is linked in and the SDL1 include paths are used. SDL1 has support for sdl-config, which is present in system/bin. Using the native sdl-config may result in compilation or missing-symbol errors. You will need to modify the build system to look for files in emscripten/system or emscripten/system/bin in order to use the Emscripten sdl-config.

Adding more ports

Adding more ports is fairly easy. Basically, the steps are

  • Make sure the port is open source and has a suitable license.
  • Add it to emscripten-ports on github. The ports maintainers can create the repo and add the relevant developers to a team for that repo, so they have write access.
  • Add a script to handle it under tools/ports/ (see existing code for examples) and use it in tools/ports/__init__.py.
  • Add testing in the test suite.

Build system issues

Build system self-execution

Some large projects generate executables and run them in order to generate input for later parts of the build process (for example, a parser may be built and then run on a grammar, which then generates C/C++ code that implements that grammar). This sort of build process causes problems when using Emscripten because you cannot directly run the code you are generating.

The simplest solution is usually to build the project twice: once natively, and once to JavaScript. When the JavaScript build procedure fails because a generated executable is not present, you can then copy that executable from the native build, and continue to build normally. This approach was successfully used for compiling Python (see tests/python/readme.md for more details).

In some cases it makes sense to modify the build scripts so that they build the generated executable natively. For example, this can be done by specifying two compilers in the build scripts, emcc and gcc, and using gcc just for generated executables. However, this can be more complicated than the previous solution because you need to modify the project build scripts, and you may have to work around cases where code is compiled and used both for the final result and for a generated executable.

Dynamic linking

Emscripten’s goal is to generate the fastest and smallest possible code, and for that reason it focuses on generating a single JavaScript file for an entire project. For that reason, dynamic linking should be avoided when possible.

By default, Emscripten .so files are the same as .bc or .o files, that is, they contain LLVM bitcode. Dynamic libraries that you specify in the final build stage (when generating JavaScript or HTML) are linked in as static libraries. Emcc ignores commands to dynamically link libraries when linking together bitcode (i.e., not in the final build stage). This is to ensure that the same dynamic library is not linked multiple times in intermediate build stages, which would result in duplicate symbol errors.

There is experimental support for true dynamic libraries, loaded as runtime, either via dlopen or as a shared library. See that link for the details and limitations.

Configure may run checks that appear to fail

Projects that use configure, cmake, or some other portable configuration method may run checks during the configure phase to verify that the toolchain and paths are set up properly. Emcc tries to get checks to pass where possible, but you may need to disable tests that fail due to a “false negative” (for example, tests that would pass in the final execution environment, but not in the shell during configure).

Tip

Ensure that if a check is disabled, the tested functionality does work. This might involve manually adding commands to the make files using a build system-specific method.

Note

In general configure is not a good match for a cross-compiler like Emscripten. configure is designed to build natively for the local setup, and works hard to find the native build system and the local system headers. With a cross-compiler, you are targeting a different system, and ignoring these headers etc.

Archive (.a) files

Emscripten supports .a archive files, which are bundles of object files. This is an old format for libraries, and it has special semantics - for example, the order of linking matters with .a files, but not with plain object files (in .bc, .o or .so). For the most part those special semantics should work in Emscripten, however, we support .a files using llvm’s tools, which have a few limitations.

The main limitation is that if you have multiple files in a single .a archive that have the same basename (for example, dir1/a.o, dir2/a.o), then llvm-ar cannot access both of those files. Emscripten will attempt to work around this by adding a hash to the basename, but collisions are still possible in principle.

Where possible it is better to generate shared library files (.so) rather than archives (.a) — this is generally a simple change in your project’s build system. Shared libraries are simpler, and are more predictable with respect to linking.

Manually using emcc

The Emscripten Tutorial showed how emcc can be used to compile single files into JavaScript. Emcc can also be used in all the other ways you would expect of gcc:

# Generate a.out.js from C++. Can also take .ll (LLVM assembly) or .bc (LLVM bitcode) as input
./emcc src.cpp

# Generate src.o containing LLVM bitcode.
./emcc src.cpp -c

# Generate result.js containing JavaScript.
./emcc src.cpp -o result.js

# Generate result.bc containing LLVM bitcode (the suffix matters).
./emcc src.cpp -o result.bc

# Generate a.out.js from two C++ sources.
./emcc src1.cpp src2.cpp

# Generate src1.o and src2.o, containing LLVM bitcode
./emcc src1.cpp src2.cpp -c

# Combine two LLVM bitcode files into a.out.js
./emcc src1.o src2.o

# Combine two LLVM bitcode files into another LLVM bitcode file
./emcc src1.o src2.o -o combined.o

In addition to the capabilities it shares with gcc, emcc supports options to optimize code, control what debug information is emitted, generate HTML and other output formats, etc. These options are documented in the emcc tool reference (./emcc --help on the command line).

Detecting Emscripten in Preprocessor

Emscripten provides the following preprocessor macros that can be used to identify the compiler version and platform:

  • The preprocessor define __EMSCRIPTEN__ is always defined when compiling programs with Emscripten.
  • The preprocessor variables __EMSCRIPTEN_major__, __EMSCRIPTEN_minor__ and __EMSCRIPTEN_tiny__ specify, as integers, the currently used Emscripten compiler version.
  • Emscripten behaves like a variant of Unix, so the preprocessor defines unix, __unix and __unix__ are always present when compiling code with Emscripten.
  • Emscripten uses Clang/LLVM as its underlying codegen compiler, so the preprocessor defines __llvm__ and __clang__ are defined, and the preprocessor defines __clang_major__, __clang_minor__ and __clang_patchlevel__ indicate the version of Clang that is used.
  • Clang/LLVM is GCC-compatible, so the preprocessor defines __GNUC__, __GNUC_MINOR__ and __GNUC_PATCHLEVEL__ are also defined to represent the level of GCC compatibility that Clang/LLVM provides.
  • The preprocessor string __VERSION__ indicates the GCC compatible version, which is expanded to also show Emscripten version information.
  • Likewise, __clang_version__ is present and indicates both Emscripten and LLVM version information.
  • Emscripten is a 32-bit platform, so size_t is a 32-bit unsigned integer, __POINTER_WIDTH__=32, __SIZEOF_LONG__=4 and __LONG_MAX__ equals 2147483647L.
  • When targeting asm.js, the preprocessor defines __asmjs and __asmjs__ are present.
  • When targeting SSEx SIMD APIs using one of the command line compiler flags -msse, -msse2, -msse3, -mssse3, or -msse4.1, one or more of the preprocessor flags __SSE__, __SSE2__, __SSE3__, __SSSE3__, __SSE4_1__ will be present to indicate available support for these instruction sets.
  • If targeting the pthreads multithreading support with the compiler & linker flag -s USE_PTHREADS=1, the preprocessor define __EMSCRIPTEN_PTHREADS__ will be present.

Examples / test code

The Emscripten test suite (tests/runner.py) contains a number of good examples — large C/C++ projects that are built using their normal build systems as described above: freetype, openjpeg, zlib, bullet and poppler.

It is also worth looking at the build scripts in the ammo.js project.

Troubleshooting

  • Make sure to use emar (which calls llvm-ar), as the system ar may not support our object files. emmake and emconfigure set the AR environment variable correctly, but a build system might incorrectly hardcode ar.

  • Similarly, using the system ranlib instead of emranlib (which calls llvm-ranlib) may lead to problems, like not supporting our object files and removing the index, leading to archive has no index; run ranlib to add one from wasm-ld. Again, using emmake/emconfigure should avoid this by setting the env var RANLIB, but a build system might have it hardcoded, or require you to pass an option.

  • The compilation error multiply defined symbol indicates that the project has linked a particular static library multiple times. The project will need to be changed so that the problem library is linked only once.

    Note

    You can use llvm-nm to see which symbols are defined in each bitcode file.

    One solution is to use the dynamic-linking approach described above. This ensures that libraries are linked only once, in the final build stage.

Building to WebAssembly

WebAssembly is a binary format for executing code on the web, allowing fast start times (smaller download and much faster parsing in browsers when compared to JS or asm.js). Emscripten compiles to WebAssembly by default, but you can also compile to JS for older browsers.

For some historical background, see

Setup

WebAssembly is emitted by default, without the need for any special flags.

Note

If you don’t want WebAssembly, you can disable it with something like

emcc [..args..] -s WASM=0

Note

Emscripten’s WebAssembly support depends on Binaryen, which is provided by the emsdk (if you don’t use the emsdk, you need to build it and set it up in your .emscripten file).

Note

Deciding to compile to wasm or JS can be done at the linking stage: it doesn’t affect the object files.

Backends

Emscripten emits WebAssembly using the upstream LLVM wasm backend, since version 1.39.0 (October 2019), and the old fastcomp backend is deprecated (you can still use the deprecated fastcomp backend by getting latest-fastcomp instead of the normal latest, or 1.39.0-fastcomp instead of 1.39.0, etc.).

There are some differences you may notice between the two backends, if you upgrade from fastcomp to upstream:

  • The wasm backend is strict about linking files with different features sets - for example, if one file was built with atomics but another was not, it will error at link time. This prevents possible bugs, but may mean you need to make some build system fixes.
  • WASM=0 behaves differently in the two backends. In fastcomp we emit asm.js, while in upstream we emit JS (since not all wasm constructs can be expressed in asm.js). Also, the JS support implements the same external WebAssembly.* API, so in particular startup will be async just like wasm by default, and you can control that with WASM_ASYNC_COMPILATION (even though WASM=0).
  • The wasm backend uses wasm object files by default. That means that it does codegen at the compile step, which makes the link step much faster - like a normal native compiler. For comparison, in fastcomp the compile step emits LLVM IR in object files.
    • You normally wouldn’t notice this, but some compiler flags affect codegen, like DISABLE_EXCEPTION_CATCHING. Such flags must be passed during codegen. The simple and safe thing is to pass all -s flags at both compile and link time.
    • You can enable Link Time Optimization (LTO) with the usual llvm flags (-flto, -flto=full, -flto=thin, at both compile and link times). These flags will make the wasm backend behave more like fastcomp.
    • With fastcomp LTO optimization passes will not be run by default; for that you must pass --llvm-lto 1. With the llvm backend LTO passes will be run on any object files that are in bitcode format.
    • Another thing you might notice is that fastcomp’s link stage is able to perform some minor types of link time optimization even without LTO being set. The LLVM backend requires actually setting LTO for those things.
  • wasm-ld, the linker used by the wasm backend, requires libraries (.a archives) to contain symbol indexes. This matches the behaviour the native GNU linker. While emar will create such indexes by default, native tools such as GNU ar and GNU strip are not aware of the WebAssembly object format and cannot create archive indexes. In particular, if you run GNU strip on an archive file that contains WebAssembly object files it will remove the index which makes the archive unusable at link time.
  • Fastcomp emits asm.js and so has some limitations on function pointers. For example, the RESERVED_FUNCTION_POINTERS setting exists there to work around the fact that we can’t grow the table. In the upstream backend table growth is easy, and you can just enable ALLOW_TABLE_GROWTH.
  • Fastcomp and upstream use very different LLVM and clang versions (fastcomp has been stuck on LLVM 6, upstream is many releases after). This affects optimizations, usually by making the upstream version faster and smaller. However, in rare cases you may see a regression (for example, in some cases UN-optimized code may be less optimal in upstream, so make sure to optimize both when compiling and when linking).
  • Also see the blocker bugs on the wasm backend, and the wasm backend tagged issues.

Binaryen codegen options

Trapping

WebAssembly can trap - throw an exception - on things like division by zero, rounding a very large float to an int, and so forth. In asm.js such things were silently ignored, as in JavaScript they do not throw, so this is a difference between JavaScript and WebAssembly that you may notice, with the browser reporting an error like float unrepresentable in integer range, integer result unrepresentable, integer overflow, or Out of bounds Trunc operation.

Fastcomp/asm2wasm

In fastcomp/asm2wasm, emscripten will emit code that is optimized for size and speed, which means it emits code that may trap on the things mentioned before. That mode is called allow. The other modes are clamp, which will avoid traps by clamping values to a reasonable range, and js, which ensures the exact same behavior as JavaScript does (which also does clamping, but makes sure to clamp exactly like JavaScript does, and also do other things JavaScript would).

In general, using clamp is safest, as whether such a trap occurs depends on how the LLVM optimizer optimizes code. In other words, there is no guarantee that this will not be an issue, and updating LLVM can make a problem appear or vanish (the wasm spec process has recognized this problem and intends to standardize new operations that avoid it). Also, there is not a big downside to using clamp: it is only slightly larger and slower than the default allow, in most cases. To do so, build with

-s "BINARYEN_TRAP_MODE='clamp'"

However, if the default (to allow traps) works in your codebase, then it may be worth keeping it that way, for the (small) benefits. Note that js, which preserves the exact same behavior as JavaScript does, adds a large amount of overhead, so unless you really need that, use clamp (js is often useful for debugging, though).

LLVM wasm backend

The LLVM wasm backend avoids traps by adding more code around each possible trap (basically clamping the value if it would trap). This can increase code size and decrease speed, if you don’t need that extra code. The proper solution for this is to use newer wasm instructions that do not trap, by calling emcc or clang with -mnontrapping-fptoint. That code may not run in older VMs, though.

Compiler output

When using emcc to build to WebAssembly, you will see a .wasm file containing that code, as well as the usual .js file that is the main target of compilation. Those two are built to work together: run the .js (or .html, if that’s what you asked for) file, and it will load and set up the WebAssembly code for you, properly setting up imports and exports for it, etc. Basically, you don’t need to care about whether the compiled code is asm.js or WebAssembly, it’s just a compiler flag, and otherwise everything should just work (except the WebAssembly should be faster).

  • Note that the .wasm file is not standalone - it’s not easy to manually run it without that .js code, as it depends on getting the proper imports that integrate with JS. For example, it receives imports for syscalls so that it can do things like print to the console. There is work in progress towards ways to create standalone .wasm files, see the WebAssembly Standalone page.

You may also see additional files generated, like a .data file if you are preloading files into the virtual filesystem. All that is exactly the same as when building to asm.js. One difference you may notice is the lack of a .mem file, which for asm.js contains the static memory initialization data, which in WebAssembly we can pack more efficiently into the WebAssembly binary itself.

Testing native WebAssembly in browsers

WebAssembly support is enabled by default as of Firefox 52, Chrome 57 and Opera 44. On Edge 15 you can enable it via “Experimental JavaScript Features” flag.

Debugging

asm.js support is considered very stable now, and you can change between it and wasm with -s WASM=0, so if you see something odd in a wasm build, comparing to a parallel asm.js build can help. In general, any difference between the two could be a compiler bug or browser bug, but there are a few legitimate causes of different behavior between the two, that you may want to rule out:

  • wasm allows unaligned accesses, i.e. it will load 4 bytes from an unaligned address the same way x86 does (it doesn’t care it’s unaligned). asm.js works more like ARM CPUs which mostly don’t accept such things (but they often trap, while asm.js just returns a wrong result). To rule this out, you can build with -s SAFE_HEAP=1, that will catch all such invalid accesses.
  • Timing issues - wasm might run faster or slower. To some extent you can mitigate that by building with -s DETERMINISTIC=1.
  • Trap mode. As mentioned above, we can generate wasm that traps or that avoids traps. Make sure the trap mode is "js" when comparing builds. The "js" trap mode is also useful in a single build, as otherwise operations like division or float-to-int may trap, and the optimizer may happen to change whether a trap occurs or not, which can be confusing (for example, enabling SAFE_HEAP may prevent some optimizations, and a trap may start to occur). Instead, in the "js" trap mode there are no traps and all operations are deterministically defined as identical to JavaScript.
  • Minor libc and runtime differences exist between wasm and asm.js. We used to have a way to emit more compatable builds (-s "BINARYEN_METHOD='asmjs,native-wasm'" etc.) but due to its complexity and low value it was removed.
  • Floating-point behavior: WebAssembly uses 32-bit floats in a standard way, while asm.js by default implements floats using doubles. That can lead to differences in the precision of results. You can force 32-bit float behavior in asm.js with -s PRECISE_F32=1, in which case it should be identical to wasm.
  • Browser instability: It’s worth testing multiple browsers, as one might have a wasm bug that another doesn’t. You can also test the Binaryen interpreter (e.g. using the interpret-binary method, as discussed above).

If you find that an asm.js build has the same behavior as a wasm one, then it is currently easier to debug the asm.js build: you can edit the source easily (add debug printouts, etc.), there is debug info and source maps support, etc.

Debugging WebAssembly

When you do need to debug a WebAssembly build, the following tips might help you.

WebAssembly doesn’t have source maps support yet, but building with -g will emit both a text and a binary wasm, and it will include function names in both, and also include source file and line number information in the text, for example, building hello world might produce this .wat:

;; tests/hello_world.c:4
(drop
  (call $_printf
    (i32.const 1144)
    (get_local $$vararg_buffer)
  )
)
;; tests/hello_world.c:5
(return
  (i32.const 0)
)

This indicates that the printf call comes from line 4, and the return from line 5, of hello_world.c.

.wasm files and compilation

WebAssembly code is prepared somewhat differently than asm.js. asm.js can be bundled inside the main JS file, while as mentioned earlier WebAssembly is a binary file on the side, so you will have more than one file to distribute.

Another noticeable effect is that WebAssembly is compiled asynchronously by default, which means you must wait for compilation to complete before calling compiled code (by waiting for main(), or the onRuntimeInitialized callback, etc., which you also need to do when you have anything else that makes startup async, like a .mem file for asm.js, or preloaded file data, etc.). You can turn off async compilation by setting WASM_ASYNC_COMPILATION=0, but that may not work in Chrome due to current limitations there.

  • Note that even with async compilation turned off, fetching the WebAssembly binary may need to be an asynchronous operation (since the Web does not allow synchronous binary downloads on the main thread). If you can fetch the binary yourself, you can set Module['wasmBinary'] and it will be used from there, and then (with async compilation off) compilation should be synchronous.

Web server setup

To serve wasm in the most efficient way over the network, make sure your web server has the proper MIME time for .wasm files, which is application/wasm. That will allow streaming compilation, where the browser can start to compile code as it downloads.

In Apache, you can do this with

AddType application/wasm .wasm

Also make sure that gzip is enabled:

AddOutputFilterByType DEFLATE application/wasm

If you serve large .wasm files, the webserver will consume CPU compressing them on the fly at each request. Instead you can pre-compress them to .wasm.gz and use content negotiation:

Options Multiviews
RemoveType .gz
AddEncoding x-gzip .gz
AddType application/wasm .wasm

Running HTML files with emrun

emrun is a command line tool that can run generated HTML pages via a locally launched web server. This is helpful when using web browsers that cannot run a generated .html file via a file:// URL (e.g. by double-clicking the file) because of the default browser CORS rules.

emrun also enables all kinds of command-line automation, for example, integrating unit tests into an Emscripten environment in a project build farm.

Features

emrun supports the following uses:

  • Launch your Emscripten-generated HTML page in a web browser from the command line.
  • Capture application stdout and stderr streams during the run, and print them to a terminal or log them to a file.
  • Pass command-line arguments to the application and read them from GET parameters in the launched URL, or argc and argv in main().
  • Detect when a launched application quits via a call to C’s exit(returncode), then pass the specified return code to the terminal.
  • Choose which installed browser to run, or even run a browser on an Android device connected to the local computer through adb.

Quick how-to

Using emrun is simple:

  1. Rebuild your Emscripten application and add the --emrun linker flag.

This flag injects code into the generated Module object to enable capture of stdout, stderr and exit().

Note

If you skip this step, you can still run any .html file with emrun, but the capture will not work.

  1. Open a terminal, navigate to the build output directory, and call emrun page.html.
This will spawn a new web server to host the page and launch your default system browser to visit that page. emrun will block until the page calls exit(returncode), after which it will quit back to shell with the given process exit code.

Choosing the browser to run

The --browser <filename-or-browser-alias> command line option allows you to launch an HTML file using a particular browser, by specifying either its “browser alias” or the full path to its executable (if the flag is not specified, the default system browser is launched).

To enumerate the list of browser aliases on your system, use the --list_browsers command:

> emrun --list_browsers

emrun has automatically found the following browsers in the default install locations on the system:

- firefox: Mozilla Firefox 26.0.0.5087
- firefox_beta: Mozilla Firefox 26.0.0.5077
- firefox_aurora: Mozilla Firefox Aurora 28.0.0.5098
- firefox_nightly: Mozilla Firefox Nightly 29.0.0.5098
- chrome: Google Chrome 31.0.1650.63
- chrome_canary: Google Chrome 34.0.1752.0
- iexplore: Microsoft Internet Explorer 11.0.9600.16384
- opera: Opera 18.0.1284.63

Note

For your browser to be detected, it should be installed in the default install location on the system (%ProgramFiles% on Windows and /Applications/ on macOS) or by adding it to the PATH for the current user.

You can pass the --browser <alias> option to launch with a given browser. For example, to run the Firefox Nightly browser you would call:

emrun --browser firefox_nightly page.html

To launch using a browser’s filename use:

--browser /path/to/browser/executable page.html

If you just want to launch a web server you can pass the --no_browser command line flag. In this case emrun will run the server without spawning the browser (this is similar to using a local webserver).

Security implications

emrun spawns its own web server to host the target .html file. This has the following security implications:

  • The web server is a generic file server that by default serves all files in the directory where the .html file resides, and all directories under that directory tree.
  • The web server will be visible to other computers on the same network.

Controlling web server operation

The following command line flags control how emrun spawns the web server:

  • --no_server: Do not launch a web server. The target file is run via the file:// protocol, if possible.
  • --serve_after_close: Do not quit emrun; continue running the server even after the user closes the web browser. Use this flag when you want to visit the page multiple times or with different browsers during the same run.
  • --serve_after_exit: Do not quit emrun; continue running the server after the page finishes with a call to exit(returncode).
  • --serve_root <path>: Specify a custom directory to use as the root directory for the spawned web server. By default, the directory where the .html file resides is used.
  • --port <number>: Specify the web server TCP port. The default port is 6931.
  • --silence_timeout <seconds>: Specify the emrun silence timeout. If the application does not print anything to stdout or stderr in this many seconds, the page/browser is assumed to be hung, and emrun will quit. This is disabled by default.
  • --timeout <seconds>: Specify the emrun timeout. If the whole page run lasts longer than this many seconds, the page/browser is assumed to be hung, and emrun will quit. This is disabled by default.
  • --hostname <name>: Specify the web server TCP hostname. The default hostname is localhost.
  • --timeout_returncode <code>: Specifies the process return code that emrun quits with if a page run timeout occurs. By default this is 99999.

Controlling log output

The following command line flags affect logging output:

  • --verbose: Print detailed information about emrun internal steps.
  • --log_stdout <filename>: Write all stdout messages from the application to the named file (instead of printing to terminal).
  • --lot_stderr <filename>: Write all stderr messages from the application to the named file (instead of printing to terminal).
  • --system_info: Print detailed information about the current system before launching. This is useful during automated runs when you want to capture hardware information to logs.
  • --browser_info: Print information about which browser is about to be launched.
  • --log_html: Reformat application output as HTML markup.
  • --no_emrun_detect: Hide the warning message that is launched if a target .html file is detected to not have been built with --emrun.

Cleaning up after the run

These command line flags allow you to clean up open browser processes before starting a new run — this is important for automated testing on build servers:

  • --kill_start: Terminate all instances of the target browser process before starting the run. Pass this flag to ensure that no old (hung) instances of the target browser process exist that could interfere with the current run. This is disabled by default.
  • --kill_exit: Terminate all instances of the target browser process when emrun quits. Pass this flag to ensure that browser pages closed when the run is over. This is disabled by default. Note that it may be necessary to explicitly use the --browser=/path/to/browser command line option when using --kill_exit, or otherwise the termination might not function properly.

Warning

These operations cause the browser process to be forcibly terminated. Any windows or tabs you have open will be closed, including any that might contain unsaved data.

Running web pages in Firefox

When running web pages via emrun using Firefox, you may want to set one or more of the following browser prefs:

; Make sure to unblock popups being spawned from http://localhost/.
browser.popups.showPopupBlocker;false

; Don't ask the user to change the default browser when spawning the browser.
browser.shell.checkDefaultBrowser;false

; Don't autorestore previous tabs, just open the one from the command line.
browser.sessionstore.resume_from_crash;false
services.sync.prefs.sync.browser.sessionstore.restore_on_demand;false
browser.sessionstore.restore_on_demand;false

; Don't bring up the modal "Start in Safe Mode" dialog after browser is killed, since
; that is an expected path for --kill_start and --kill_exit options.
browser.sessionstore.max_resumed_crashes;-1
toolkit.startup.max_resumed_crashes;-1

; Don't fail on long-running scripts, but have emrun instead control execution termination.
dom.max_script_run_time;0
dom.max_chrome_script_run_time;0

; Accelerate browser update background timer tick so that autoupdates take place as quickly as possible.
; This is useful for continuous integration servers wanting to always test the latest browser version.
app.update.download.backgroundInterval;1

; Always run in private browsing mode to avoid caching any pages (but also disables IndexedDB persistency!).
browser.privatebrowsing.autostart;true

; When switching between multiple Firefox browser versions/channels, suppress showing the first time welcome page.
startup.homepage_override_url;about:blank
startup.homepage_welcome_url;about:blank

To set a Firefox browser pref, navigate to the page about:config in the browser navigation bar.

Running web pages on an Android device

emrun can automate browser-based testing on Android.

For this to work, you need to:

  • Connect an Android phone to the local system via USB, with its developer mode enabled. There is no need to root the phone.
  • Install the adb tool on the host system and make sure it is present in the PATH environment variable.
  • Check that adb is working by calling adb devices to see that your device is listed.
  • Install any browser apk to the device that you want to be able to run.

To run on Android, add the --android command line flag and use the --browser <alias> command line flag to explicitly choose the correct browser to run.

Note

Omitting --browser (to launch a default Android browser) is not supported.

Note

Running on Android will omit the --hostname option

The following browser aliases have been tested and shown to work: firefox, firefox_beta, firefox_aurora, firefox_nightly, chrome, chrome_beta, opera.

The following browser aliases are also supported, but have known issues:

  • opera_mini: The browser launches, but for some reason it times out when trying to load any page.
  • dolphin: Works, but does not support WebGL.

Otherwise, using emrun for browser-based testing on Android is the same as when testing on the host system.

Building projects on Travis CI

Travis CI is a popular continuous integration service which offers free plans for open source projects. Thanks to a Docker image by trzeci installing emscripten in Travis CI is essentially a one line task.

A sample .travis.yml

notifications:
  email: false

language: node_js
node_js:
  - node

sudo: required

services:
  - docker

before_install:
  - docker run -dit --name emscripten -v $(pwd):/src trzeci/emscripten:sdk-incoming-64bit bash

script:
  - docker exec -it emscripten make helloworld.js
  - make test

Let’s break it down:

notifications:
  email: false

language: node_js
node_js:
  - node

sudo: required

services:
  - docker

These lines set up the basic settings for the Travis container. Most people do not want email notifications, but feel free to leave out those lines if you do.

language: node_js and node_js: - node tell Travis we are a Node.js project, and that we want the latest stable Node release.

sudo: required and services: - docker are required to enable Docker in the Travis container.

before_install:
  - docker run -dit --name emscripten -v $(pwd):/src trzeci/emscripten:sdk-incoming-64bit bash

In the before_install stage we download the Docker image, create a container with that image, and then give it the name emscripten. The -dit options tell Docker that we want the container to run bash in the background.

This Docker image contains everything emscripten needs to run, as well as several additional build tools such as make and cmake. If you do not need them you can use the emscripten-slim image instead, which excludes them and will be downloaded and installed slightly quicker. The emscripten versions available are listed at the Docker Hub.

script:
  - docker exec -it emscripten make helloworld.js
  - make test

In the script stage we can now run the commands we want, inside the Docker container we created earlier. In this sample we are using make, but you can call emcc directly if you prefer.

The Docker container is set up to use the same directories as Travis, so the second line uses the same Makefile, and can also depend on the output of the Docker command. If your test suite needs a later version of Node than what is installed by emsdk (Node v4), you will need to run the tests outside of Docker as a normal Travis command.

For an example of this setup in practice, see the Travis page for emglken, which is also set up to use Greenkeeper for automatic testing of dependency updates.

Deploying Emscripten Compiled Pages

Emscripten compiled output can either be run directly in a JS shell from command line, or hosted on a web page. When hosting asm.js and WebAssembly compiled pages as .html for browsers to execute, Emscripten provides a default HTML shell file that serves as a launcher to run the code, simplified to get started with development. However when getting ready to release and host the content on a web site, a number of extra features and customizations are likely needed to polish the visitor experience. This guide highlights things to pay attention to when deploying sites to the public.

Build Files and Custom Shell

Emscripten build output consists of two essential parts: 1) the low level compiled code module and 2) the JavaScript runtime to interact with it. If targeting WebAssembly which is done with linker flags -s WASM=1 -o out.html, the compiled code is stored in a file out.wasm and the runtime lives in a file out.js. When targeting asm.js there exists an additional binary file out.mem that contains the static memory section of the compiled code. This part is embedded in the out.wasm file when targeting WebAssembly.

By default when targeting asm.js, the compiled code and the runtime are fused in the same out.js file. For moderately large asm.js projects, it is recommended to use the --separate-asm flag to separate the compiled code to its own out.asm.js file, which enables browsers to optimize memory usage for the compiled asm.js code.

Additional build output files can also exist, depending on which features are used. If the Emscripten file packager is used, a binary out.data package is generated, along with an associated out.data.js loader file. Also Emscripten pthreads and Fetch APIs have their own associated Web Worker related script .js output files.

Developers can choose to output either to JavaScript or HTML. If outputting JavaScript (emcc -o out.js), the developer is expected to manually create the out.html main page in which the code is run in browsers. When targeting HTML with emcc -o out.html (the recommended build mode), Emscripten will generate the HTML shell file automatically. This shell file can be customized by using the emcc -o out.html --shell-file path/to/custom_shell.html linker directive. Copy the default minimal HTML shell file from Emscripten repository to your project tree to get a good starting template for a customized shell file.

The following sections offer tips for improving the site experience.

Optimizing Download Sizes

The biggest slowdown to speedy page loading is most often the need to download large amounts of asset data for the project, especially if the page is heavy on WebGL textures or geometry. Compiled code generally takes up more space than handwritten JavaScript, but machine code compresses efficiently. Therefore when hosting asm.js and WebAssembly, it is critical to ensure that all content is transferred using gzip compression, which all browsers and CDNs nowadays support built-in. Gzip compressing .wasm files give on average 60-75% size reductions compared to uncompressed ones, so it practically never makes sense to serve uncompressed files.

  • To serve gzip-compressed assets on a CDN, use a gzip compression tool and precompress asset files offline before uploading to the CDN. Some web servers support compressing files on the fly, but for static asset content, that should be avoided since it can be costly for the server CPU to keep recompressing the files. Adjust the configuration of the web server to host the precompressed files with the HTTP response header Content-Encoding: gzip. This instructs web browsers that the downloaded content should be transparently uncompressed before handing the data off to the page itself.
  • WebAssembly has now shipped in Firefox 52 and Chrome 57. Emscripten also supports targeting WebAssembly, by using the -s WASM=1 linker flag. WebAssembly is an evolution of asm.js, and if your project already successfully compiles to asm.js, it is likely to already work with WebAssembly as well. Compressed WebAssembly output files can be around 20% smaller than compressed asm.js files, but for builds with debugging and profiling information, the difference can even be up to 50%, so the benefit is large.
  • Make sure that gzip compression does not confuse the MIME types that the assets are served with. All JavaScript files (precompressed or not) should be best served with the HTTP response header Content-Type: application/javascript, and all asset files (.data, .mem) should be served with the header Content-Type: application/octet-stream. WebAssembly .wasm files should be served with Content-Type: application/wasm.
  • Try to minimize the amount of preloaded asset data that is downloaded up front with the Emscripten --preload-file linker flag. This data file is loaded up before the Emscripten compiled application starts to execute main() function at all, so all files that are stored in this package can greatly slow down the time to start up. Prefer to break up downloaded asset files to multiple separate packages and using asynchronous asset download APIs in Emscripten which can operate while the application is running.
  • Asset sizes for WebGL applications are often dominated by the amount of textures, such that using compressed texture formats helps to shrink down asset sizes. The web can be quite a different platform to target compared to native platforms, since on the web one cannot necessarily assume that a specific compressed texture format would be supported on the visitor’s hardware, especially if developing a site that should work both on mobile and desktop browsers. The best practice to support a wide range of hardware is to generate multiple sets of compressed textures, one for each supported platform, and download the appropriate one based on the formats that the WebGL context supports.
  • If multiple screen sizes are being targeted, e.g. in desktop and mobile form factors, consider separating textures out to SD and HD variants to make the page load up quicker for mobile devices that have a smaller display resolution.

Optimizing Page Startup Times

In addition to downloading the page, other parts of the startup sequence can sometimes also be slow. Things to consider here are:

  • If targeting asm.js and running on Firefox or Edge, the web page console displays a log message after the asm.js module has been compiled. This log message includes timing information about how long the compilation took. Asm.js compilation begins the moment the asm.js script source file is added to the DOM, and once it finishes, the onload event of the script tag is called. This can be used to time how long asm.js compilation takes on Safari, Opera and Chrome.
  • It is recommended to migrate to WebAssembly to speed up compiled code startup times in browsers. WebAssembly modules are much faster to parse and compile compared to asm.js. Additionally, compiled WebAssembly.Module objects can be manually persisted to IndexedDB, which avoids the compilation step altogether on the second run. (see next section)
  • Occassionally it can be easy to misattribute slow startup to asm.js/WebAssembly compilation, when the actual cause of slowness can in fact be in executing the main() function entry point of the application itself. This is because these two actions are run closely back to back to each other. It is worthwhile to be precise to profile these two actions separately, check out the function callMain() in src/preamble.js which kicks off the execution of application main() code. If executing main() takes too long time, consider splitting it out to separate operations that are driven by multiple setTimeout() calls or by the emscripten_set_main_loop() event loop.
  • To speed up network transfers, experience shows that the under regular network conditions, the fastest approach is to aggressively start all network downloads simultaneously in parallel (assuming there are only a handful of them), as opposed to e.g. downloading a single input file at a time before starting the next one. Therefore to maximize network transfer speed, try to write the main HTML page of the application to start all needed network downloads in parallel instead of queueing them up for sequential transfer.
  • In the case when the first time load of the page is dominated by network transfers, it is useful to take advantage of the fact that the CPU is otherwise mostly idle while waiting for downloads to finish. This CPU time can be utilized to perform other heavy tasks. An ideal candidate for this is to download and compile the asm.js/WebAssembly module already while downloading other page assets.
  • A currently known issue on Windows based systems is that compiling WebGL shaders can be slow. This is also a primary candidate for an action to be performed in parallel while downloading other assets for the page.

Providing a Quick Second Time Load

While the first run experience of visiting a page can take some time to finish all downloads, the second run experience of the page can be made much faster by making sure that the results of the first visit are cached by the browser.

  • All browsers have an implementation defined limit (20MB or 50MB) for assets, and files larger than that will bypass the browser’s built-in web caches altogether. Therefore it is recommended that large .data files are manually cached to IndexedDB by the main page. The Emscripten linker option --use-preload-cache can be used to have Emscripten implement this, although it can be desirable to manually manage this on the html page in a custom manner, since that allows taking control of which database the assets are cached to, and what kind of scheme will be used to evict data from it.
  • Compilation results of asm.js modules are cached automatically by the browser, and there is little control over this. WebAssembly on the other hand supports explicit caching of compiled WebAssembly.Module objects to IndexedDB. This feature should be always leveraged, since it allows skipping the whole compilation process on the second page visit.
  • If the compiled C/C++ code itself performs any computation e.g. in main() that could be skipped on the second load, use either IndexedDB or the localStorage APIs to cache the results of this computation across page runs. IndexedDB is suitable for storing large files, but it works asynchronously. The localStorage API on the other hand is fully synchronous, but its usage is restricted to storing small cookie style data fields only.
  • When implementing IndexedDB based caching, it is good to note that as an asynchronous API that performs disk accesses, IndexedDB operations have some latency as well. Therefore if performing multiple read operations at startup, it is good to fire all of them up in parallel where possible, to reduce latency.
  • Another important point with persisting data is that for best practices towards the user, it is good to provide an explicit visual identification when using IndexedDB or localStorage to persist large amounts of data, and offer an easy mechanism to clear or uninstall that data. This is because currently browsers do not implement convenient UIs for fine grained deletion of data from these storages, but clearing data often is presented as a “clear cache from all pages” type of option.

Reserving Memory for Compiled Code

An inherent property of asm.js and WebAssembly applications is that they need a linear block of memory to represent the application heap. This is often the single largest memory allocation that an Emscripten compiled page does, and therefore is the one that is at the biggest risk of failing if the user’s system is low on memory.

Because this memory allocation needs to be contiguous, it can happen that the user’s browser process does have enough memory, but only the address space of the process is too fragmented, and there is not enough linear address space available to satisfy the allocation. To avoid this issue, the best practice is to allocate the WebAssembly.Memory object (ArrayBuffer for asm.js) up front at the top of the main page, before any other allocations or page script load actions are done. This ensures that the allocation has best chances to succeed. See the fields Module['buffer'] and Module['wasmMemory'] for more information.

Additionally, it is possible to opt in to content process isolation specifically for a web page that needs this kind of a large allocation. To utilize this machinery, specify the HTTP response header Large-Allocation: <MBytes> when serving the main html page. This support is currently implemented in Firefox 53.

Last, it is easy to accidentally cling to large unneeded blocks of memory after the page has loaded. For example, in WebAssembly, once the WebAssembly Module has been instantiated to a WebAssembly.Instance object, the original WebAssembly.Module object is no longer needed in memory, and it is best to clear all references to it so that the garbage collector can reclaim it, because the Module object can be dozens of megabytes in size. Similar, make sure that all XHRed files, asset data and large scripts are not referenced anymore when not used. Check out the browser’s memory profiling tool, and the about:memory page in Firefox to perform memory profiling to ensure that memory is not being wasted.

Robust Error Handling

To provide the best possible user experience, make sure that the different ways that the page can fail are taken into account, and good error reporting is provided to the user. In particular, proceed through the following checklist for best practices.

  • Aim to fail as early as possible. A large source of frustration for users comes from scenarios where user’s system is not ready to run the given page, but the error only becomes apparent after having waited for a minute to download 100MB worth of assets. For example, try to allocate the needed heap memory up front before actually loading up the page. This way if the memory allocation fails, the failure is immediate and no asset downloads need to be attempted at all.

  • If a particular browser is known to not be supported, resist the temptation to read navigator.userAgent field to gate users with that browser, if at all possible. For example, if your page needs WebGL 2 but Safari is known not to support it, do not exclude out Safari users with a following type of check:

    if (navigator.userAgent.indexOf('Safari') != -1) alert('Your browser does not support WebGL 2!');
    

but instead, detect the actual errors:

if (!canvas.getContext('webgl2')) alert('Your browser does not support WebGL 2!'); // And look for webglcontextcreationerror here for an error reason.

This way the page will be future compatible once support for the particular feature later becomes available.

  • Test various failure cases up front by simulating different issues and browser limitations. For example, on Firefox, it is possible to manually disable WebGL 2 by navigating to about:config and setting the preference webgl.enable-webgl2 to false. This allows you to debug what kind of error reporting your page will present to the user in such a scenario. To disable WebGL support altogether for testing purposes, set the preference webgl.disabled to true.

  • When working with IndexedDB, prepare to handle out of quota errors when user is about to run out of free disk space or allowed quota for the domain.

  • Simulate out of memory errors by allocating unrealistically much memory for WebAssembly.Memory object and for the preloaded file packages, if using any. Make sure that out of memory errors are flagged correctly as such (and reported to the user or to an error database).

  • Simulate download timeouts either intrusively by programmatically aborting XHR downloads, physically disconnecting network access, or by using external tools such as Fiddler. These types of tools can show up a lot of unexpected failure cases and help diagnose that the error handling path for such scenarios is as desired.

  • Use a network limiter tool to constrain download or upload bandwidth speeds to simulate slow network connections. This can uncover bugs related to timing dependencies for network transfers. For example, a small network transfer may be implicitly assumed to finish before a large one, but that might not always be the case.

  • When developing the page locally, perform testing by using a local web server and not just via file:// URLs. The script emrun.py in Emscripten source tree is designed to serve as an ad hoc web server for this purpose. Emrun is preconfigured to handle serving gzip compressed files (with suffix .gz), and enables support for the Large-Allocation header, and allows command line automation runs of compiled pages.

  • Catch all exceptions that come from within entry points that call to compiled asm.js and WebAssembly code. There are three distinct exception classes that compiled code can throw:

    1. C++ exceptions that are represented by a thrown integer and not caught by the C++ program. This integer points to a memory location in the application heap that contains pointer to the thrown object.
    2. Exceptions caused by Emscripten runtime calling the abort() function. These correspond to a fatal error that execution of the compiled code cannot recover from. For example, this can occur when calling an invalid function pointer.
    3. Traps caused by compiled WebAssembly code. These correspond to fatal errors coming from the WebAssembly VM. This can occur for example when performing an integer division by zero, or when converting a large floating point number to an integer when the float is out of range of the numbers representable by that integer type. See the linker flag -s BINARYEN_TRAP_MODE for more details.
  • Implement a final “catch all” error handler on the page by implementing a window.onerror script. This will be called as a last resort if no other source handled an exception that was raised on the page. See window.onerror documentaton on MDN.

  • Do not let the html page “freeze” and bury the error message in the web page console, because most users will not know how to find it there. Strive to provide meaningful error reports to the user on the main html page, preferably with hints on how to act. If updating a browser version or GPU drivers, or freeing up some space on disk might have a chance to help the page to run, let the user know what they could try out. If the error in question is completely unexpected, consider providing a link or an email address where to report the issue to.

  • Provide meaningful and interactive loading progress indicators to show the user whether the loading progress is still proceeding and what is going to happen next. Try to prevent leading the user to a “I wonder if it is still loading or if it hung?” state of mind.

Prepare for The Web Environment

When planning a testing matrix before pushing a site live, the following items can be a good idea to review.

  • Web page behavior can be subtly different when run as a top level window vs when run in an iframe. Make sure to test both scenarios if these are applicable.
  • Test both 32 bit and 64 bit browsers, especially simulate out of memory scenarios on 32 bit browsers.
  • Be aware of the HTTP Cross-Origin Access Control rules and how they pertain to the site architecture you are hosting.
  • Be aware of the Content Security Policy rules and make note of what kind of CSP policy the site is planned to run with.
  • Be mindful of the Mixed Content Security restrictions that browsers impose.
  • Make sure that the site runs well in private browsing (incognito) mode. For example, this will prevent the site from persisting data to IndexedDB.
  • Test that the page works well when put into a background tab. Use the blur, focus and visibilitychange DOM events to react to page hide and show events. This is relevant in particular for applications that perform audio playback.
  • If the page uses WebGL, make sure that it is able to gracefully handle the WebGL context loss event. Use the WebGL_lose_context developer extension to programmatically trigger context loss events when testing.
  • Verify that the page works as intended on displays with different window.devicePixelRatio (DPI) settings, in particular when using WebGL. See Khronos.org: HandlingHighDPI. On Windows and macOS, try changing the desktop display scaling setting to test different values of window.devicePixelRatio that the browser reports.
  • Test out that different page zoom levels do not break the site layout, especially when navigating to the page with the browser window already pre-zoomed.
  • Likewise, verify that the page layout does not break when resizing the browser window, or when visiting the site having already initially sized the browser window to very small or large size, or to a disproportionate aspect ratio.
  • Especially if targeting mobile, be aware of the <meta viewport> tag for how to develop a site layout that works well on mobile.
  • If the page uses WebGL, test out different GPUs on target platforms. In particular, verify the site behavior when simulating the lack of any needed WebGL extensions, and compressed texture format support.
  • If using the requestAnimationFrame() API (i.e. emscripten_set_main_loop() function) to drive rendering, be aware that the rate at which the function is called is not always 60 Hz, but can vary at runtime e.g. when moving the browser window from one display to another in a multimonitor setup, if the displays have different refresh rates. Update intervals such as 75Hz, 90Hz, 100Hz, 120Hz, 144Hz and 200Hz are becoming more common.
  • Simulate lack of any special APIs that the page might need, e.g. Gamepad, Acceleration or Touch Events, and make sure that appropriate error flow is handled in those cases as well.

If you have good tips or suggestsions to share, please help improve this guide by posting feedback to the Emscripten bug tracker or the emscripten-discuss mailing list.

Building and Deploying on GitLab

GitLab CI/CD is a popular continuous integration service which offers free plans to everyone. Thanks to an Alpine Linux package by Jakub Jirutka installing emscripten in GitLab CI/CD is literally a one line task.

A sample .gitlab-ci.yml

image: alpine:3.9

before_script:
  - apk add emscripten make --repository=http://dl-cdn.alpinelinux.org/alpine/edge/testing

pages:
  script:
  - make
  artifacts:
    paths:
    - public
  only:
    - master

Let’s break it down:

before_script:
  - apk add emscripten make --repository=http://dl-cdn.alpinelinux.org/alpine/edge/testing

In the before_script stage we download the package from the Alpine Linux testing repository.

This step also contains the command to add an additional build tool make.

script:
  - make

In the script stage we can now run the commands we want. In this sample we are using make, but you can call emcc directly if you prefer.

For an example of this setup in practice, see the Example Emscripten site using GitLab Pages.

Porting

The topics in this section cover the main integration points that you need to consider when porting C/C++ code to Emscripten, along with general coding and debugging guidelines.

Code Portability and Limitations

Emscripten can be used to compile almost any portable C/C++ code to JavaScript. The topics in this section help identify less portable code, and code that may need to be changed because of limitations in the browser environment or Emscripten-compiled JavaScript.

Portability Guidelines

Emscripten can be used to compile almost any portable C++/C code to JavaScript.

This section explains what types of code are non-portable (or more difficult to port), and what code can be compiled but will run slowly. Developers can use this information for evaluating the effort to port and re-write code.

Current Web limitations

  • Multithreading depends on SharedArrayBuffer, which is still being standardized and implemented by browsers. Emscripten has working support for threads, which you can try in development browsers by setting the proper preference.
  • SIMD is also in the process of standardization and implementation.

Code that cannot be compiled

The following types of code would need to be re-written in order to work with Emscripten. (While in theory it might be possible for Emscripten to work around these issues using emulation, it would be very slow.)

  • Code relying on a big-endian architecture. Emscripten-compiled code currently requires a little-endian host to run on, which accounts for 99% of machines connected to the internet. This is because JavaScript typed arrays (used for views on memory) obey the host byte ordering and LLVM needs to know which endianness to target.
  • Code that uses low-level features of the native environment, for example native stack manipulation in conjunction with setjmp/longjmp (we support proper setjmp/longjmp, i.e., jumping down the stack, but not jumping up to an unwound stack, which is undefined behavior).
  • Code that scans registers or the stack. This won’t work because a variable in a register or on the stack may be held in a JavaScript local variable (which cannot be scanned).

Note

Code of this type might be used for conservative garbage collection. You can do conservative scanning when there is no other code on the stack, e.g. from an iteration of the main event loop. Other solutions include the SpillPointers pass in Binaryen.

  • Code with architecture-specific inline assembly (like an asm() containing x86 code) is not portable. That code would need to be replaced with portable C or C++. Sometimes a codebase will have both portable code and optional inline assembly as an optimization, so you might find an option to disable the inline assembly.

Code that compiles but might run slowly

Note

Understanding these issues can be helpful when optimising code.

The following types of code will compile, but may not run as fast as expected:

  • In asm.js (but not WebAssembly), 64-bit int variables. Mathematical operations (+, -, *, /) are slow because they are emulated (bitwise operations are reasonably fast). JavaScript does not have a native 64-bit int type so this is unavoidable.
  • C++ Exceptions. In JavaScript such code generally makes the JavaScript engine turn off various optimizations. For that reason exceptions are turned off by default in -O1 and above. To re-enable them, run emcc with -s DISABLE_EXCEPTION_CATCHING=0 (see src/settings.js).
  • setjmp also prevents relooping around it, forcing us to emulate control flow using a less efficient approach.

Other issues

  • Code that relies on x86 alignment behavior. x86 allows unaligned reads and writes (so for example you can read a 16-bit value from a non-even address), but other architectures do not (32-bit ARM will raise SIGILL). For asm.js loads and stores are forced to aligned offsets; for WebAssembly unaligned loads and stores will work but may be slow depending on the underlying CPU. If you build your code with SAFE_HEAP=1 then you will get a clear runtime exception, see Debugging.

API Limitations

The browser environment and JavaScript are different from the native environments that C and C++ typically run in. These differences impose some limitations on how native APIs can be called and used. This section lists some of the more obvious limitations.

Networking

Emscripten supports libc networking functions but you must limit yourself to asynchronous (non-blocking) operations. This is required because the underlying JavaScript networking functions are asynchronous.

File Systems

Emscripten supports libc file system functions and C/C++ code can be written in the normal way.

Code run in a browser environment is sandboxed, and does not have direct access to the local file system. Instead, Emscripten creates a virtual file system that may be preloaded with data or linked to URLs for lazy loading. This affects when synchronous file system functions can be called and how a project is compiled. See the File System Overview for more information.

Application Main Loop

The browser event model uses co-operative multitasking — each event has a “turn” to run, and must then return control to the browser event loop so that other events can be processed. A common cause of HTML pages hanging is JavaScript that does not complete and return control to the browser.

This can affect how an application using an infinite main loop is written. See Emscripten Runtime Environment for more information.

Other APIs

Support for other portable C/C++ code is fairly comprehensive.

Function Pointer Issues

There are two main issues with function pointers:

  1. Function pointer casts can cause function pointer calls to fail.

    Function pointers must be called with the correct type: it is undefined behavior in C and C++ to cast a function pointer to another type and call it that way. This does work in most native platforms, however, despite it being UB, but in asm.js and in wasm it can fail. In that case, you may see an abort(10) or some other number, and if assertions are on you may see a message with details that start with

    Invalid function pointer called
    

    Rarely, you may see a compiler warning like this:

    warning: implicit declaration of function
    

    This may be related to a function pointer cast problem as implicit declarations may have a different type than how you call them. However, in general the compiler cannot warn about this, and you will only see a problem at runtime.

  2. Older versions of clang can generate different code for C and C++ calls when a structure is passed by value (for completeness, one convention is struct byval and the other is field a, field b). The two formats are incompatible with each other, and you may get a warning.

    The workaround is to pass the structure by reference, or simply not mix C and C++ in that location (for example, rename the .c file to .cpp).

Debugging function pointer issues

The SAFE_HEAP and ASSERTION options can catch some of these errors at runtime and provide useful information. You can also see if EMULATE_FUNCTION_POINTER_CASTS fixes things for you, but see later down about the overhead.

Working around function pointer issues

There are three solutions to this problem (the second is preferred):

  • Cast the function pointer back to the correct type before it is called. This is problematic because it requires that the caller knows the original type.
  • Manually write an adapter function that does not need to be cast, and calls the original function. For example, it might ignore a parameter, and in that way bridge between the different function pointer types.
  • Use EMULATE_FUNCTION_POINTER_CASTS. When you build with -s EMULATE_FUNCTION_POINTER_CASTS=1, Emscripten emits code to emulate function pointer casts at runtime, adding extra arguments/dropping them/changing their type/adding or dropping a return type/etc. This can add significant runtime overhead, so it is not recommended, but is be worth trying.

For a real-world example, consider the code below:

#include <stdio.h>

typedef void(*voidReturnType)(const char *);

void voidReturn(const char *message) {
  printf( "voidReturn: %s\n", message );
}


int intReturn(const char *message) {
  printf( "intReturn: %s\n", message );
  return 1;
}

void voidReturnNoParam() {
  printf( "voidReturnNoParam:\n" );
}

void callFunctions(const voidReturnType * funcs, size_t size) {
  size_t current = 0;
  while (current < size) {
    funcs[current]("hello world");
    current++;
  }
}

int main() {
  voidReturnType functionList[3];

  functionList[0] = voidReturn;
  functionList[1] = (voidReturnType)intReturn;         // Breaks in Emscripten.
  functionList[2] = (voidReturnType)voidReturnNoParam; // Breaks in Emscripten.

  callFunctions(functionList, 3);
}

The code defines three functions with different signatures: voidReturn of type vi (void (int)), intReturn of type ii, and voidReturnNoParam of type v. These function pointers are cast to type vi and added to a list. The functions are then called using the function pointers in the list.

The code runs (and works) when compiled to native machine code (on all major platforms). You can try it by saving the code as main.c and executing cc main.c and then ./a.out. You’ll see this output:

voidReturn: hello world
intReturn: hello world
voidReturnNoParam:

However, the code fails with a runtime exception in Emscripten, and displays the console output:

voidReturn: hello world
Invalid function pointer called with signature 'vi'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)
Build with ASSERTIONS=2 for more info.

Note

You can try this yourself. Save the code as main.c, compile using emcc -O0 main.c -o main.html, and then load main.html into a browser.

The code fragment below shows how we can cast the function pointer back to its original signature just before calling it, so that it is found in the correct table. This requires the receiver of the table to have special knowledge about what is in the list (you can see this in the special case for index 1 in the while loop). Additionally, emcc will continue to complain about the original cast taking place in main() when adding the function to functionList[1].

void callFunctions(const voidReturnType * funcs, size_t size) {
  size_t current = 0;
  while (current < size) {
    if ( current == 1 ) {
      ((intReturnType)funcs[current])("hello world"); // Special-case cast
    } else {
      funcs[current]("hello world");
    }
    current++;
  }
}

The code fragment below shows how to make and use an adapter function that calls the original function. The adapter is defined with the same signature as it will have when called, and is hence available in the expected function-pointer table.

void voidReturnNoParamAdapter(const char *message) {
  voidReturnNoParam();
}

int main() {
  voidReturnType functionList[3];

  functionList[0] = voidReturn;
  functionList[1] = (voidReturnType)intReturn; // Fixed in callFunctions
  functionList[2] = voidReturnNoParamAdapter; // Fixed by Adapter

  callFunctions(functionList, 3);
}

Specific Browser Limitations

This page lists some of the differences between the latest versions of the major browsers that are relevant to Emscripten-compiled applications and games:

  • The function emscripten_get_now() returns a wallclock time as a float in milliseconds. Opera 12.16 and Windows Google Chrome 28.0.1500.95 have a limitation that the timer precision is only in milliseconds. On other major browsers (IE10, Firefox 22, Chrome 28 on non-Windows) it has sub-millisecond precision.
  • WebGL is not fully supported on Internet Explorer (at least prior to IE12):
    • Internet Explorer 10 and older do not support WebGL. Trying to initialize a GL context via EGL, GLUT, SDL or similar will fail. Emscripten applications that do not depend on OpenGL can still run on this browser.
    • Internet Explorer 11 supports only part of WebGL 1.0. Some commands, shaders etc. may not work. You may be able to limit your app to using the subset that is supported by IE11.
    • WebGL support on other major browsers is fairly good (see WebGL support in different browsers).
  • Opera 12.16 has limited support for the W3C File API. In particular it does not support createObjectURL functionality, which means that it is not possible to use the browser’s image codecs to decode preloaded files in the Emscripten virtual file system.
  • OpenAL and SDL audio support in Emscripten depend on the Web Audio API (see Web Audio API support in different browsers).

Emscripten Runtime Environment

The Emscripten runtime environment is different to that expected by most C/C++ applications. Emscripten works hard to abstract and mitigate these differences, so that in general code can be compiled with little or no change.

This article expands on some of the differences and the resulting API Limitations, and outlines the few changes you may need to make to your C/C++ code.

Input/output

Emscripten implements the Simple DirectMedia Layer API (SDL) for the browser environment, which provides low level access to audio, keyboard, mouse, joystick, and graphics hardware. Applications that use SDL typically require no input/output changes to run in the browser.

In addition, we have more limited support for glut, glfw, glew and xlib.

Applications that do not use SDL or the other APIs can use the Emscripten-specific APIs for input and output:

  • html5.h, which defines the Emscripten low-level glue bindings to interact with HTML5 events from native code, including access to keys, mouse, wheel, device orientation, battery levels, vibration, etc.
  • Multimedia and Graphics APIs, including OpenGL and EGL.

File Systems

A lot of C/C++ code uses the synchronous file system APIs in libc and libcxx to access code in the local file system. This is problematic because the browser prevents code from directly accessing files on the host system, and because JavaScript only supports asynchronous file access outside of web workers.

Emscripten provides an implementation of libc and libcxx and a virtual file system so that normal C/C++ code can be compiled and run without change. Most developers need only specify the set of files to be packaged for preloading into the virtual file system at runtime.

Note

Using a virtual file system bypasses the limitations listed above. The file data is packaged at compile time and downloaded into the file system using asynchronous JavaScript APIs before the compiled code is allowed to run. The compiled code then makes “file” calls that are really just calls into program memory.

The default file system (MEMFS) stores files in-memory, so that any changes are lost when the page is reloaded. If file changes need to be stored more permanently then developers can mount the IDBFS file system, which allows data to be persisted in the browser. When running code in node.js, developers can mount NODEFS to give code direct access to the local file system.

Emscripten also has an API to support asynchronous file access.

For more information and examples see Files and File Systems.

Browser main loop

The browser event model uses co-operative multitasking — each event has a “turn” to run, and must then return control to the browser so that other events can be processed. A common cause of HTML pages hanging is JavaScript that does not complete and return control to the browser.

Graphical C++ apps typically run in an infinite loop. Within each iteration of the loop the app performs event handling, processing and rendering, followed by a delay (“wait”) to keep the frame rate constant. This infinite loop is a problem in the browser environment because there is no way for control to return to the browser so other code can run. After a period the browser will notify the user that the page is stuck and offer to halt or close it.

Similarly, JavaScript APIs like WebGL can only run when the current “turn” is over, and will automatically render and swap buffers at that point. This contrasts with OpenGL C++ apps where you would need to swap the buffers manually.

Implementing an asynchronous main loop in C/C++

The standard solution for this problem is to define a C function that performs one iteration of your main loop (not including the “delay”). For a native build this function can be called in an infinite loop, leaving the behaviour effectively unchanged.

Within Emscripten compiled code we use emscripten_request_animation_frame_loop() to get the environment to call this same function at the proper frequency for rendering a frame (that is, if the browser renders at 60fps, it will call this 60 times per second). The iteration is still run “infinitely” but now other code can run between iterations and the browser does not hang.

Typically you will have a small section with #ifdef __EMSCRIPTEN__ for the two cases. For example:

#include <emscripten.h>
#include <emscripten/html5.h>
#include <stdio.h>

// Our "main loop" function. This callback receives the current time as
// reported by the browser, and the user data we provide in the call to
// emscripten_request_animation_frame_loop().
EM_BOOL one_iter(double time, void* userData) {
  // Can render to the screen here, etc.
  puts("one iteration");
  // Return true to keep the loop running.
  return EM_TRUE;
}

int main() {
#ifdef __EMSCRIPTEN__
  // Receives a function to call and some user data to provide it.
  emscripten_request_animation_frame_loop(one_iter, 0);
#else
  while (1) {
    one_iter();
    // Delay to keep frame rate constant (using SDL).
    SDL_Delay(time_to_next_frame());
  }
#endif
}

Note

A more full-featured API is provided in emscripten_set_main_loop(), which lets you specify the frequency at which to call the function, and other things.

Note

When using SDL you will often need to set the main loop, unless you
are just rendering a single frame and halting. You should also note:
  • The current Emscripten implementation of SDL_QUIT will work if you use emscripten_set_main_loop(). As the page is shut, it will force a final direct call to the main loop, giving it a chance to notice the SDL_QUIT event. If you do not use a main loop, your app will close before you have had an opportunity to notice this event.
  • There are limitations to what you can do as the page shuts (in onunload). Some actions like showing alerts are banned by browsers at this point.

Using Asyncify to yield to the browser

Another option is to use Asyncify which will rewrite the program so that it can return to the browser’s main event loop by just calling emscripten_sleep(). Note that this rewriting causes size and speed overhead while emscripten_request_animation_frame_loop / emscripten_set_main_loop as described earlier do not.

Execution lifecycle

When an Emscripten-compiled application is loaded, it starts by preparing data in the preloading phase. Files you marked for preloading (using emcc --preload-file, or manually from JavaScript with FS.createPreloadedFile()) are set up at this stage.

You can add additional operations with addRunDependency(), which is a counter of all dependencies to be executed before compiled code can run. As these are completed you can call removeRunDependency() to remove the completed dependencies.

Note

Generally it is not necessary to add additional operations — preloading is suitable for almost all use cases.

When all dependencies are met, Emscripten will call run(), which proceeds to call your main() function. The main() function should be used to perform initialization tasks, and will often call emscripten_set_main_loop() (as described above). The main loop function will be then be called at the requested frequency.

You can affect the operation of the main loop in several ways:

  • emscripten_push_main_loop_blocker() adds a function that blocks the main loop until the blocker completes.

    This is useful, for example, to manage loading new game levels. After a level completes, you can push blockers for each action involved (unpacking the file, generate the data structures, etc.) When all the blockers have completed the main loop will resume and the game should run the new level. You can also use this function in conjunction with emscripten_set_main_loop_expected_blockers() to keep the user informed of progress.

  • emscripten_pause_main_loop() pauses the main loop, and emscripten_resume_main_loop() resumes it. These are low level (less recommended) alternatives to the blocker functions.

  • emscripten_async_call() lets you call a function after some specific interval. This will use requestAnimationFrame (by default) or setTimeout if a specific interval was requested.

The browser execution environment reference (emscripten.h) describes a number of other methods for controlling execution.

Emscripten memory representation

In both asm.js and WebAssembly Emscripten represents memory in a way similar to native architectures. Pointers represent offsets into memory, structs use the same amount of address space as they normally do, and so forth.

In WebAssembly, this is done using a WebAssembly.Memory which was designed for that purpose. In asm.js, Emscripten uses a single typed array, with different views providing access to different types (HEAPU32 for 32-bit unsigned integers, etc.).

Emscripten experimented with other memory representations in the past, ending up on the “typed arrays mode 2” approach for JS and then asm.js, as described above, and then WebAssembly implemented something similar.

Connecting C++ and JavaScript

Emscripten provides various options for connecting “normal” JavaScript and compiled code, which range from functions to call compiled C/C++ from JavaScript (and vice versa) through to accessing environment variables from compiled code.

The topic Interacting with code provides an overview of all the methods. The other two topics provide additional detail on the Embind and WebIDL Binder tools.

Note

For information on how compiled code interacts with the browser environment, see Emscripten Runtime Environment. For file system-related manners, see the File System Overview.

Interacting with code

Emscripten provides numerous methods to connect and interact between JavaScript and compiled C or C++:

This article explains each of the methods listed above, and provides links to more detailed information.

Note

For information on how compiled code interacts with the browser environment, see Emscripten Runtime Environment. For file system related manners, see the File System Overview.

Note

Before you can call your code, the runtime environment may need to load a memory initialization file, preload files, or do other asynchronous operations depending on optimization and build settings. See How can I tell when the page is fully loaded and it is safe to call compiled functions? in the FAQ.

Calling compiled C functions from JavaScript using ccall/cwrap

The easiest way to call compiled C functions from JavaScript is to use ccall() or cwrap().

ccall() calls a compiled C function with specified parameters and returns the result, while cwrap() “wraps” a compiled C function and returns a JavaScript function you can call normally. cwrap() is therefore more useful if you plan to call a compiled function a number of times.

Consider the tests/hello_function.cpp file shown below. The int_sqrt() function to be compiled is wrapped in extern "C" to prevent C++ name mangling.

// Copyright 2012 The Emscripten Authors.  All rights reserved.
// Emscripten is available under two separate licenses, the MIT license and the
// University of Illinois/NCSA Open Source License.  Both these licenses can be
// found in the LICENSE file.

#include <math.h>

extern "C" {

int int_sqrt(int x) {
  return sqrt(x);
}

}

To compile this code run the following command in the Emscripten home directory:

./emcc tests/hello_function.cpp -o function.html -s EXPORTED_FUNCTIONS='["_int_sqrt"]' -s EXTRA_EXPORTED_RUNTIME_METHODS='["ccall", "cwrap"]'

EXPORTED_FUNCTIONS tells the compiler what we want to be accessible from the compiled code (everything else might be removed if it is not used), and EXTRA_EXPORTED_RUNTIME_METHODS tells the compiler that we want to use the runtime functions ccall and cwrap (otherwise, it will remove them if it does not see they are used).

Note

EXPORTED_FUNCTIONS affects compilation to JavaScript. If you first compile to an object file, then compile the object to JavaScript, you need that option on the second command. If you do it all together as in the example here (source straight to JavaScript) then this just works, of course.

After compiling, you can call this function with cwrap() using the following JavaScript:

int_sqrt = Module.cwrap('int_sqrt', 'number', ['number'])
int_sqrt(12)
int_sqrt(28)

The first parameter is the name of the function to be wrapped, the second is the return type of the function (or a JavaScript null value if there isn’t one), and the third is an array of parameter types (which may be omitted if there are no parameters). The types are “number” (for a JavaScript number corresponding to a C integer, float, or general pointer), “string” (for a JavaScript string that corresponds to a C char* that represents a string) or “array” (for a JavaScript array or typed array that corresponds to a C array; for typed arrays, it must be a Uint8Array or Int8Array).

You can run this yourself by first opening the generated page function.html in a web browser (nothing will happen on page load because there is no main()). Open a JavaScript environment (Control-Shift-K on Firefox, Control-Shift-J on Chrome), and enter the above commands as three separate commands, pressing Enter after each one. You should get the results 3 and 5 — the expected output for these inputs using C++ integer mathematics.

ccall() is similar, but receives another parameter with the parameters to pass to the function:

// Call C from JavaScript
var result = Module.ccall('int_sqrt', // name of C function
  'number', // return type
  ['number'], // argument types
  [28]); // arguments

// result is 5

Note

This example illustrates a few other points, which you should remember when using ccall() or cwrap():

  • These methods can be used with compiled C functions — name-mangled C++ functions won’t work.
  • We highly recommended that you export functions that are to be called from JavaScript:
    • Exporting is done at compile time. For example: -s EXPORTED_FUNCTIONS='["_main","_other_function"]' exports main() and other_function().
    • Note that you need _ at the beginning of the function names in the EXPORTED_FUNCTIONS list.
    • Note that _main is mentioned in that list. If you don’t have it there, the compiler will eliminate it as dead code. The list of exported functions is the entire list that will be kept alive (unless other code was kept alive in another manner).
    • Emscripten does dead code elimination to minimize code size — exporting ensures the functions you need aren’t removed.
    • At higher optimisation levels (-O2 and above), code is minified, including function names. Exporting functions allows you to continue to access them using the original name through the global Module object.
    • If you want to export a JS library function (something from a src/library*.js file, for example), then in addition to EXPORTED_FUNCTIONS, you need to add it to DEFAULT_LIBRARY_FUNCS_TO_INCLUDE, as the latter will force the method to actually be included in the build.
  • The compiler will remove code it does not see is used, to improve code size. If you use ccall in a place it sees, like code in a --pre-js or --post-js, it will just work. If you use it in a place the compiler didn’t see, like another script tag on the HTML or in the JS console like we did in this tutorial, then because of optimizations and minification you should export ccall from the runtime, using EXTRA_EXPORTED_RUNTIME_METHODS, for example using -s 'EXTRA_EXPORTED_RUNTIME_METHODS=["ccall", "cwrap"]', and call it on Module (which contains everything exported, in a safe way that is not influenced by minification or optimizations).

Interacting with an API written in C/C++ from NodeJS

Say you have a C library that exposes some procedures:

//api_example.c
#include <stdio.h>
#include <emscripten.h>

EMSCRIPTEN_KEEPALIVE
void sayHi() {
  printf("Hi!\n");
}

EMSCRIPTEN_KEEPALIVE
int daysInWeek() {
  return 7;
}

Compile the library with emcc:

emcc api_example.c -o api_example.js

Require the library and call its procedures from node:

var em_module = require('./api_example.js');

em_module._sayHi(); // direct calling works
em_module.ccall("sayHi"); // using ccall etc. also work
console.log(em_module._daysInWeek()); // values can be returned, etc.

Call compiled C/C++ code “directly” from JavaScript

Functions in the original source become JavaScript functions, so you can call them directly if you do type translations yourself — this will be faster than using ccall() or cwrap(), but a little more complicated.

To call the method directly, you will need to use the full name as it appears in the generated code. This will be the same as the original C function, but with a leading _.

Note

If you use ccall() or cwrap(), you do not need to prefix function calls with _ – just use the C name.

The types of the parameters you pass to functions need to make sense. Integers and floating point values can be passed as is. Pointers are simply integers in the generated code.

Strings in JavaScript must be converted to pointers for compiled code – the relevant function is UTF8ToString(), which given a pointer returns a JavaScript string. Converting a JavaScript string someString to a pointer can be accomplished using ptr = `` allocate(intArrayFromString(someString), 'i8', ALLOC_NORMAL) <allocate>.

Note

The conversion to a pointer allocates memory, which needs to be freed up via a call to free(ptr) afterwards (_free in JavaScript side)

There are other convenience functions for converting strings and encodings in preamble.js.

Calling JavaScript from C/C++

Emscripten provides two main approaches for calling JavaScript from C/C++: running the script using emscripten_run_script() or writing “inline JavaScript”.

The most direct, but slightly slower, way is to use emscripten_run_script(). This effectively runs the specified JavaScript code from C/C++ using eval(). For example, to call the browser’s alert() function with the text ‘hi’, you would call the following JavaScript:

emscripten_run_script("alert('hi')");

Note

The function alert is present in browsers, but not in node or other JavaScript shells. A more generic alternative is to call console.log.

A faster way to call JavaScript from C is to write “inline JavaScript”, using EM_JS() or EM_ASM() (and related macros).

EM_JS is used to declare JavaScript functions from inside a C file. The “alert” example might be written using EM_JS like:

#include <emscripten.h>

EM_JS(void, call_alert, (), {
  alert('hello world!');
  throw 'all done';
});

int main() {
  call_alert();
  return 0;
}

EM_JS’s implementation is essentially a shorthand for implementing a JavaScript library.

EM_ASM is used in a similar manner to inline assembly code. The “alert” example might be written with inline JavaScript as:

#include <emscripten.h>

int main() {
  EM_ASM(
    alert('hello world!');
    throw 'all done';
  );
  return 0;
}

When compiled and run, Emscripten will execute the two lines of JavaScript as if they appeared directly in the generated code. The result would be an alert, followed by an exception. (Note, however, that under the hood Emscripten still does a function call even in this case, which has some amount of overhead.)

You can also send values from C into JavaScript inside EM_ASM, for example:

EM_ASM({
  console.log('I received: ' + $0);
}, 100);

This will show I received: 100.

You can also receive values back, for example the following will print out I received: 100 and then 101:

int x = EM_ASM_INT({
  console.log('I received: ' + $0);
  return $0 + 1;
}, 100);
printf("%d\n", x);

See the emscripten.h docs for more details.

Note

  • You need to specify if the return value is an int or a double using the appropriate macro EM_ASM_INT or EM_ASM_DOUBLE.
  • The input values appear as $0, $1, etc.
  • return is used to provide the value sent from JavaScript back to C.
  • See how { and } are used here to enclose the code. This is necessary to differentiate the code from the arguments passed later, which are the input values (this is how C macros work).
  • When using the EM_ASM macro, ensure that you only use single quotes(‘). Double quotes(“) will cause a syntax error that is not detected by the compiler and is only shown when looking at a JavaScript console while running the offending code.

Implement a C API in JavaScript

It is possible to implement a C API in JavaScript! This is the approach used in many of Emscripten’s libraries, like SDL1 and OpenGL.

You can use it to write your own APIs to call from C/C++. To do this you define the interface, decorating with extern to mark the methods in the API as external symbols. You then implement the symbols in JavaScript by simply adding their definition to library.js (by default). When compiling the C code, the compiler looks in the JavaScript libraries for relevant external symbols.

By default, the implementation is added to library.js (and this is where you’ll find parts of Emscripten’s libc). You can put the JavaScript implementation in your own library file and add it using the emcc option --js-library. See test_js_libraries in tests/test_other.py for a complete working example, including the syntax you should use inside the JavaScript library file.

As a simple example, consider the case where you have some C code like this:

extern void my_js(void);

int main() {
  my_js();
  return 1;
}

Note

When using C++ you should encapsulate extern void my_js(); in an extern "C" {} block to prevent C++ name mangling:

extern "C" {
  extern void my_js();
}

Then you can implement my_js in JavaScript by simply adding the implementation to library.js (or your own file). Like our other examples of calling JavaScript from C, the example below just creates a dialog box using a simple alert() function.

my_js: function() {
  alert('hi');
},

If you add it to your own file, you should write something like

mergeInto(LibraryManager.library, {
  my_js: function() {
    alert('hi');
  },
});

mergeInto just copies the properties on the second parameter onto the first, so this add my_js onto LibraryManager.library, the global object where all JavaScript library code should be.

JavaScript limits in library files

If you’re not familiar with JavaScript, say if you’re a C/C++ programmer and just using emscripten, then the following issues probably won’t come up, but if you’re an experienced JavaScript programmer you need to be aware some common JavaScript practices can not be used in certain ways in emscripten library files.

To save space, by default, emscripten only includes library properties referenced from C/C++. It does this by calling toString on each used property on the JavaScript libraries that are linked in. That means that you can’t use a closure directly, for example, as toString isn’t compatible with that - just like when using a string to create a Web Worker, where you also can’t pass a closure. (Note that this limitation is just for the values for the keys of the object passes to mergeInto in the JS library, that is, the toplevel key-value pairs are special. Interior code inside a function can have arbitrary JS, of course).

To avoid this limitation of JS libraries, you can put code in another file using the --pre-js or --post-js options, which allow arbitrary normal JS, and it is included and optimized with the rest of the output. That is the recommended approach for most cases. Another option is another <script> tag.

Alternatively, if you prefer to use a JS library file, you can have a function replace itself and have it called during initialization.

mergeInto(LibraryManager.library, {

  // Solution for bind or referencing other functions directly
  good_02__postset: '_good_02();',
  good_02: function() {
    _good_02 = document.querySelector.bind(document);
  },

  // Solution for closures
  good_03__postset: '_good_03();',
  good_03: function() {
    var callCount = 0;
    _good_03 = function() {
      console.log("times called: ", ++callCount);
    };
  },

  // Solution for curry/transform
  good_05__postset: '_good_05();',
  good_05: function() {
    _good_05 = curry(scrollTo, 0);
 },

});

A __postset is a string the compiler will emit directly to the output file. For the example above this code will be emitted.

 function _good_02() {
   _good_o2 = document.querySelector.bind(document);
 }

 function _good_03() {
   var callCount = 0;
   _good_03 = function() {
     console.log("times called: ", ++callCount);
   };
 }

 function _good_05() {
   _good_05 = curry(scrollTo, 0);
};

// Call each function once so it will replace itself
_good_02();
_good_03();
_good_05();

You can also put most of your code in the xxx__postset strings. The example below each method declares a dependency on $method_support and are otherwise dummy functions. $method_support itself has a corresponding __postset property with all the code to set the various methods to the functions we actually want.

mergeInto(LibraryManager.library, {
  $method_support: {},
  $method_support__postset: [
    '(function() {                                  ',
    '  var SomeLib = function() {                   ',
    '    this.callCount = 0;                        ',
    '  };                                           ',
    '                                               ',
    '  SomeLib.prototype.getCallCount = function() {',
    '    return this.callCount;                     ',
    '  };                                           ',
    '                                               ',
    '  SomeLib.prototype.process = function() {     ',
    '    ++this.callCount;                          ',
    '  };                                           ',
    '                                               ',
    '  SomeLib.prototype.reset = function() {       ',
    '    this.callCount = 0;                        ',
    '  };                                           ',
    '                                               ',
    '  var inst = new SomeLib();                    ',
    '  _method_01 = inst.getCallCount.bind(inst);   ',
    '  _method_02 = inst.process.bind(inst);        ',
    '  _method_03 = inst.reset.bind(inst);          ',
    '}());                                          ',
  ].join('\n'),
  method_01: function() {},
  method_01__deps: ['$method_support'],
  method_02: function() {},
  method_01__deps: ['$method_support'],
  method_03: function() {},
  method_01__deps: ['$method_support'],
 });

Note: If you are using node 4.1 or newer you can use multi-line strings. They are only used at compile time not runtime so output will still run in ES5 based environments.

Another option is to put most of your code in an object, not a function,

mergeInto(LibraryManager.library, {
  $method_support__postset: 'method_support();',
  $method_support: {
    init: function() {
      var SomeLib = function() {
        this.callCount = 0;
      };

      SomeLib.prototype.getCallCount = function() {
        return this.callCount;
      };

      SomeLib.prototype.process = function() {
        ++this.callCount;
      };

      SomeLib.prototype.reset = function() {
        this.callCount = 0;
      };

      var inst = new SomeLib();
      _method_01 = inst.getCallCount.bind(inst);
      _method_02 = inst.process.bind(inst);
      _method_03 = inst.reset.bind(inst);
    }
  },
  method_01: function() {},
  method_01__deps: ['$method_support'],
  method_02: function() {},
  method_01__deps: ['$method_support'],
  method_03: function() {},
  method_01__deps: ['$method_support'],
 });

See the library_*.js files for other examples.

Note

  • JavaScript libraries can declare dependencies (__deps), however those are only for other JavaScript libraries. See examples in /src with the name format library_*.js
  • You can add dependencies for all your methods using autoAddDeps(myLibrary, name) where myLibrary is the object with all your methods, and name is the thing they all depend upon. This is useful when all the implemented methods use a JavaScript singleton containing helper methods. See library_webgl.js for an example.
  • If a JavaScript library depends on a compiled C library (like most of libc), you must edit src/deps_info.json. Search for “deps_info” in tools/system_libs.py.
  • The keys passed into mergeInto generate functions that are prefixed by _. In other words my_func: function() {}, becomes function _my_func() {}, as all C methods in emscripten have a _ prefix. Keys starting with $ have the $ stripped and no underscore added.

Calling JavaScript functions as function pointers from C

You can use addFunction to return an integer value that represents a function pointer. Passing that integer to C code then lets it call that value as a function pointer, and the JavaScript function you sent to addFunction will be called.

See test_add_function in tests/test_core.py for an example.

When using addFunction, there is a backing array where these functions are stored. This array must be explicitly sized, which can be done via a compile-time setting, RESERVED_FUNCTION_POINTERS. For example, to reserve space for 20 functions to be added:

emcc ... -s RESERVED_FUNCTION_POINTERS=20 ...

Note

When using addFunction on LLVM wasm backend, you need to provide an additional second argument, a Wasm function signature string. Each character within a signature string represents a type. The first character represents the return type of a function, and remaining characters are for parameter types.

  • 'v': void type
  • 'i': 32-bit integer type
  • 'j': 64-bit integer type (currently does not exist in JavaScript)
  • 'f': 32-bit float type
  • 'd': 64-bit float type

For example, if you add a function that takes an integer and does not return anything, you can do addFunction(your_function, 'vi');. See tests/interop/test_add_function_post.js for an example.

Access memory from JavaScript

You can access memory using getValue(ptr, type) and setValue(ptr, value, type). The first argument is a pointer (a number representing a memory address). type must be an LLVM IR type, one of i8, i16, i32, i64, float, double or a pointer type like i8* (or just *).

There are examples of these functions being used in the tests — see tests/core/test_utf.in and tests/test_core.py.

Note

This is a lower-level operation than ccall() and cwrap() — we do need to care what specific type (e.g. integer) is being used.

You can also access memory ‘directly’ by manipulating the arrays that represent memory. This is not recommended unless you are sure you know what you are doing, and need the additional speed over getValue() and setValue().

A case where this might be required is if you want to import a large amount of data from JavaScript to be processed by compiled code. For example, the following code allocates a buffer, copies in some data, calls a C function to process the data, and finally frees the buffer.

var buf = Module._malloc(myTypedArray.length*myTypedArray.BYTES_PER_ELEMENT);
Module.HEAPU8.set(myTypedArray, buf);
Module.ccall('my_function', 'number', ['number'], [buf]);
Module._free(buf);

Here my_function is a C function that receives a single integer parameter (or a pointer, they are both just 32-bit integers for us) and returns an integer. This could be something like int my_function(char *buf).

The converse case of exporting allocated memory into JavaScript can be tricky when wasm-based memory is allowed to grow (by compiling with -s ALLOW_MEMORY_GROWTH=1). Increasing the size of memory changes to a new buffer and existing array views essentially become invalid, so you cannot simply do this:

function func() {
  var ptr = callSomething(len);               // if memory grows ...
  return HEAPU8.subarray(buffer, buffer+len); // ... this will fail
}

Here, if callSomething calls malloc and returns the allocated pointer, and if that malloc grew memory, you will not be able to read the returned data unless you renew the view:

function func() {
  var ptr = callSomething(len);
  return new Uint8Array(HEAPU8.subarray(ptr, ptr+len)); // create a new view
}

Note that a second instance of memory growth will possibly invalidate the current view, requiring another update of the view (you can, of course, avoid this problem by copying the data.)

Affect execution behaviour

Module is a global JavaScript object, with attributes that Emscripten-generated code calls at various points in its execution.

Developers provide an implementation of Module to control how notifications from Emscripten are displayed, which files that are loaded before the main loop is run, and a number of other behaviours. For more information see Module object.

Environment variables

Sometimes compiled code needs to access environment variables (for instance, in C, by calling the getenv() function). Emscripten-generated JavaScript cannot access the computer’s environment variables directly, so a “virtualised” environment is provided.

The JavaScript object ENV contains the virtualised environment variables, and by modifying it you can pass variables to your compiled code. Care must be taken to ensure that the ENV variable has been initialised by Emscripten before it is modified — using Module.preRun is a convenient way to do this.

For example, to set an environment variable MY_FILE_ROOT to be "/usr/lib/test/" you could add the following JavaScript to your Module setup code:

Module.preRun.push(function() {ENV.MY_FILE_ROOT = "/usr/lib/test"})

Binding C++ and JavaScript — WebIDL Binder and Embind

The JavaScript methods for calling compiled C functions are efficient, but cannot be used with name-mangled C++ functions.

WebIDL Binder and Embind create bindings between C++ and JavaScript, allowing C++ code entities to be used in a natural manner from JavaScript. Embind additionally supports calling JavaScript code from C++.

Embind can bind almost any C++ code, including sophisticated C++ constructs (e.g. shared_ptr and unique_ptr). The WebIDL Binder supports C++ types that can be expressed in WebIDL. While this subset is smaller than supported by Embind, it is more than sufficient for most use cases — examples of projects that have been ported using the binder include the Box2D and Bullet physics engines.

Both tools allow mapped items to be used from JavaScript in a similar way. However they operate at different levels, and use very different approaches for defining the binding:

  • Embind declares bindings within the C/C++ file.
  • WebIDL-Binder declares the binding in a separate file. This is run through the binder tool to create “glue” code that is then compiled with the project.

Note

There is no strong evidence that one tool is “better” than the other in terms of performance (no comparative benchmarks exist), and both have been used successfully in a number of projects. The selection of one tool over the other will usually be based on which is the most natural fit for the project and its build system.

Embind

Embind is used to bind C++ functions and classes to JavaScript, so that the compiled code can be used in a natural way by “normal” JavaScript. Embind also supports calling JavaScript classes from C++.

Embind has support for binding most C++ constructs, including those introduced in C++11 and C++14. Its only significant limitation is that it does not currently support raw pointers with complicated lifetime semantics.

This article shows how to use EMSCRIPTEN_BINDINGS() blocks to create bindings for functions, classes, value types, pointers (including both raw and smart pointers), enums, and constants, and how to create bindings for abstract classes that can be overridden in JavaScript. It also briefly explains how to manage the memory of C++ object handles passed to JavaScript.

Tip

In addition to the code in this article:

Note

Embind was inspired by Boost.Python and uses a very similar approach for defining bindings.

A quick example

The following code uses an EMSCRIPTEN_BINDINGS() block to expose the simple C++ lerp() function() to JavaScript.

// quick_example.cpp
#include <emscripten/bind.h>

using namespace emscripten;

float lerp(float a, float b, float t) {
    return (1 - t) * a + t * b;
}

EMSCRIPTEN_BINDINGS(my_module) {
    function("lerp", &lerp);
}

To compile the above example using embind, we invoke emcc with the bind option:

emcc --bind -o quick_example.js quick_example.cpp

The resulting quick_example.js file can be loaded as a node module or via a <script> tag:

<!doctype html>
<html>
  <script>
    var Module = {
      onRuntimeInitialized: function() {
        console.log('lerp result: ' + Module.lerp(1, 2, 0.5));
      }
    };
  </script>
  <script src="quick_example.js"></script>
</html>

Note

We use the onRuntimeInitialized callback to run code when the runtime is ready, which is an asynchronous operation (in order to compile WebAssembly).

Note

Open the developer tools console to see the output of console.log.

The code in an EMSCRIPTEN_BINDINGS() block runs when the JavaScript file is initially loaded (at the same time as the global constructors). The function lerp()’s parameter types and return type are automatically inferred by embind.

All symbols exposed by embind are available on the Emscripten Module object.

Important

Always access objects through the Module object object, as shown above.

While the objects are also available in the global namespace by default, there are cases where they will not be (for example, if you use the closure compiler to minify code or wrap compiled code in a function to avoid polluting the global namespace). You can of course use whatever name you like for the module by assigning it to a new variable: var MyModuleName = Module;.

Classes

Exposing classes to JavaScript requires a more complicated binding statement. For example:

class MyClass {
public:
  MyClass(int x, std::string y)
    : x(x)
    , y(y)
  {}

  void incrementX() {
    ++x;
  }

  int getX() const { return x; }
  void setX(int x_) { x = x_; }

  static std::string getStringFromInstance(const MyClass& instance) {
    return instance.y;
  }

private:
  int x;
  std::string y;
};

// Binding code
EMSCRIPTEN_BINDINGS(my_class_example) {
  class_<MyClass>("MyClass")
    .constructor<int, std::string>()
    .function("incrementX", &MyClass::incrementX)
    .property("x", &MyClass::getX, &MyClass::setX)
    .class_function("getStringFromInstance", &MyClass::getStringFromInstance)
    ;
}

The binding block defines a chain of member function calls on the temporary class_ object (this same style is used in Boost.Python). The functions register the class, its constructor(), member function(), class_function() (static) and property().

Note

This binding block binds the class and all its methods. As a rule you should bind only those items that are actually needed, as each binding increases the code size. For example, it would be rare to bind private or internal methods.

An instance of MyClass can then be created and used in JavaScript as shown below:

var instance = new Module.MyClass(10, "hello");
instance.incrementX();
instance.x; // 11
instance.x = 20; // 20
Module.MyClass.getStringFromInstance(instance); // "hello"
instance.delete();

Memory management

JavaScript, specifically ECMA-262 Edition 5.1, does not support finalizers or weak references with callbacks. Therefore there is no way for Emscripten to automatically call the destructors on C++ objects.

Warning

JavaScript code must explicitly delete any C++ object handles it has received, or the Emscripten heap will grow indefinitely.

var x = new Module.MyClass;
x.method();
x.delete();

var y = Module.myFunctionThatReturnsClassInstance();
y.method();
y.delete();

Value types

Manual memory management for basic types is onerous, so embind provides support for value types. Value arrays are converted to and from JavaScript Arrays and value objects are converted to and from JavaScript Objects.

Consider the example below:

struct Point2f {
    float x;
    float y;
};

struct PersonRecord {
    std::string name;
    int age;
};

PersonRecord findPersonAtLocation(Point2f);

EMSCRIPTEN_BINDINGS(my_value_example) {
    value_array<Point2f>("Point2f")
        .element(&Point2f::x)
        .element(&Point2f::y)
        ;

    value_object<PersonRecord>("PersonRecord")
        .field("name", &PersonRecord::name)
        .field("age", &PersonRecord::age)
        ;

    function("findPersonAtLocation", &findPersonAtLocation);
}

The JavaScript code does not need to worry about lifetime management.

var person = Module.findPersonAtLocation([10.2, 156.5]);
console.log('Found someone! Their name is ' + person.name + ' and they are ' + person.age + ' years old');

Advanced class concepts

Raw pointers

Because raw pointers have unclear lifetime semantics, embind requires their use to be marked with allow_raw_pointers.

For example:

class C {};
C* passThrough(C* ptr) { return ptr; }
EMSCRIPTEN_BINDINGS(raw_pointers) {
    class_<C>("C");
    function("passThrough", &passThrough, allow_raw_pointers());
}

Note

Currently the markup serves only to whitelist raw pointer use, and show that you’ve thought about the use of the raw pointers. Eventually we hope to implement Boost.Python-like raw pointer policies for managing object ownership.

External constructors

There are two ways to specify constructors for a class.

The zero-argument template form invokes the natural constructor with the arguments specified in the template. For example:

class MyClass {
public:
  MyClass(int, float);
  void someFunction();
};

EMSCRIPTEN_BINDINGS(external_constructors) {
  class_<MyClass>("MyClass")
    .constructor<int, float>()
    .function("someFunction", &MyClass::someFunction)
    ;
}

The second form of the constructor takes a function pointer argument, and is used for classes that construct themselves using a factory function. For example:

class MyClass {
  virtual void someFunction() = 0;
};
MyClass* makeMyClass(int, float); //Factory function.

EMSCRIPTEN_BINDINGS(external_constructors) {
  class_<MyClass>("MyClass")
    .constructor(&makeMyClass, allow_raw_pointers())
    .function("someFunction", &MyClass::someFunction)
    ;
}

The two constructors present exactly the same interface for constructing the object in JavaScript. Continuing the example above:

var instance = new MyClass(10, 15.5);
// instance is backed by a raw pointer to a MyClass in the Emscripten heap
Smart pointers

To manage object lifetime with smart pointers, embind must be told about the smart pointer type.

For example, consider managing a class C’s lifetime with std::shared_ptr<C>. The best way to do this is to use smart_ptr_constructor() to register the smart pointer type:

EMSCRIPTEN_BINDINGS(better_smart_pointers) {
    class_<C>("C")
        .smart_ptr_constructor("C", &std::make_shared<C>)
        ;
}

When an object of this type is constructed (e.g. using new Module.C()) it returns a std::shared_ptr<C>.

An alternative is to use smart_ptr() in the EMSCRIPTEN_BINDINGS() block:

EMSCRIPTEN_BINDINGS(smart_pointers) {
    class_<C>("C")
        .constructor<>()
        .smart_ptr<std::shared_ptr<C>>("C")
        ;
}

Using this definition, functions can return std::shared_ptr<C> or take std::shared_ptr<C> as arguments, but new Module.C() would still return a raw pointer.

unique_ptr

embind has built-in support for return values of type std::unique_ptr.

Custom smart pointers

To teach embind about custom smart pointer templates, you must specialize the smart_ptr_trait template.

Non-member-functions on the JavaScript prototype

Methods on the JavaScript class prototype can be non-member functions, as long as the instance handle can be converted to the first argument of the non-member function. The classic example is when the function exposed to JavaScript does not exactly match the behavior of a C++ method.

struct Array10 {
    int& get(size_t index) {
        return data[index];
    }
    int data[10];
};

val Array10_get(Array10& arr, size_t index) {
    if (index < 10) {
        return val(arr.get(index));
    } else {
        return val::undefined();
    }
}

EMSCRIPTEN_BINDINGS(non_member_functions) {
    class_<Array10>("Array10")
        .function("get", &Array10_get)
        ;
}

If JavaScript calls Array10.prototype.get with an invalid index, it will return undefined.

Deriving from C++ classes in JavaScript

If C++ classes have virtual or abstract member functions, it’s possible to override them in JavaScript. Because JavaScript has no knowledge of the C++ vtable, embind needs a bit of glue code to convert C++ virtual function calls into JavaScript calls.

Abstract methods

Let’s begin with a simple case: pure virtual functions that must be implemented in JavaScript.

struct Interface {
    virtual void invoke(const std::string& str) = 0;
};

struct InterfaceWrapper : public wrapper<Interface> {
    EMSCRIPTEN_WRAPPER(InterfaceWrapper);
    void invoke(const std::string& str) {
        return call<void>("invoke", str);
    }
};

EMSCRIPTEN_BINDINGS(interface) {
    class_<Interface>("Interface")
        .function("invoke", &Interface::invoke, pure_virtual())
        .allow_subclass<InterfaceWrapper>("InterfaceWrapper")
        ;
}

allow_subclass() adds two special methods to the Interface binding: extend and implement. extend allows JavaScript to subclass in the style exemplified by Backbone.js. implement is used when you have a JavaScript object, perhaps provided by the browser or some other library, and you want to use it to implement a C++ interface.

Note

The pure_virtual annotation on the function binding allows JavaScript to throw a helpful error if the JavaScript class does not override invoke(). Otherwise, you may run into confusing errors.

extend example
var DerivedClass = Module.Interface.extend("Interface", {
    // __construct and __destruct are optional.  They are included
    // in this example for illustration purposes.
    // If you override __construct or __destruct, don't forget to
    // call the parent implementation!
    __construct: function() {
        this.__parent.__construct.call(this);
    },
    __destruct: function() {
        this.__parent.__destruct.call(this);
    },
    invoke: function() {
        // your code goes here
    },
});

var instance = new DerivedClass;
implement example
var x = {
    invoke: function(str) {
        console.log('invoking with: ' + str);
    }
};
var interfaceObject = Module.Interface.implement(x);

Now interfaceObject can be passed to any function that takes an Interface pointer or reference.

Non-abstract virtual methods

If a C++ class has a non-pure virtual function, it can be overridden — but does not have to be. This requires a slightly different wrapper implementation:

struct Base {
    virtual void invoke(const std::string& str) {
        // default implementation
    }
};

struct BaseWrapper : public wrapper<Base> {
    EMSCRIPTEN_WRAPPER(BaseWrapper);
    void invoke(const std::string& str) {
        return call<void>("invoke", str);
    }
};

EMSCRIPTEN_BINDINGS(interface) {
    class_<Base>("Base")
        .allow_subclass<BaseWrapper>("BaseWrapper")
        .function("invoke", optional_override([](Base& self, const std::string& str) {
            return self.Base::invoke(str);
        }))
        ;
}

When implementing Base with a JavaScript object, overriding invoke is optional. The special lambda binding for invoke is necessary to avoid infinite mutual recursion between the wrapper and JavaScript.

Base classes

Base class bindings are defined as shown:

EMSCRIPTEN_BINDINGS(base_example) {
    class_<BaseClass>("BaseClass");
    class_<DerivedClass, base<BaseClass>>("DerivedClass");
}

Any member functions defined on BaseClass are then accessible to instances of DerivedClass. In addition, any function that accepts an instance of BaseClass can be given an instance of DerivedClass.

Automatic downcasting

If a C++ class is polymorphic (that is, it has a virtual method), then embind supports automatic downcasting of function return values.

class Base { virtual ~Base() {} }; // the virtual makes Base and Derived polymorphic
class Derived : public Base {};
Base* getDerivedInstance() {
    return new Derived;
}
EMSCRIPTEN_BINDINGS(automatic_downcasting) {
    class_<Base>("Base");
    class_<Derived, base<Base>>("Derived");
    function("getDerivedInstance", &getDerivedInstance, allow_raw_pointers());
}

Calling Module.getDerivedInstance from JavaScript will return a Derived instance handle from which all of Derived’s methods are available.

Note

Embind must understand the fully-derived type for automatic downcasting to work.

Overloaded functions

Constructors and functions can be overloaded on the number of arguments, but embind does not support overloading based on type. When specifying an overload, use the select_overload() helper function to select the appropriate signature.

struct HasOverloadedMethods {
    void foo();
    void foo(int i);
    void foo(float f) const;
};

EMSCRIPTEN_BINDING(overloads) {
    class_<HasOverloadedMethods>("HasOverloadedMethods")
        .function("foo", select_overload<void()>(&HasOverloadedMethods::foo))
        .function("foo_int", select_overload<void(int)>(&HasOverloadedMethods::foo))
        .function("foo_float", select_overload<void(float)const>(&HasOverloadedMethods::foo))
        ;
}

Enums

Embind’s enumeration support works with both C++98 enums and C++11 “enum classes”.

enum OldStyle {
    OLD_STYLE_ONE,
    OLD_STYLE_TWO
};

enum class NewStyle {
    ONE,
    TWO
};

EMSCRIPTEN_BINDINGS(my_enum_example) {
    enum_<OldStyle>("OldStyle")
        .value("ONE", OLD_STYLE_ONE)
        .value("TWO", OLD_STYLE_TWO)
        ;
    enum_<NewStyle>("NewStyle")
        .value("ONE", NewStyle::ONE)
        .value("TWO", NewStyle::TWO)
        ;
}

In both cases, JavaScript accesses enumeration values as properties of the type.

Module.OldStyle.ONE;
Module.NewStyle.TWO;

Constants

To expose a C++ constant() to JavaScript, simply write:

EMSCRIPTEN_BINDINGS(my_constant_example) {
    constant("SOME_CONSTANT", SOME_CONSTANT);
}

SOME_CONSTANT can have any type known to embind.

Memory views

In some cases it is valuable to expose raw binary data directly to JavaScript code as a typed array, allowing it to be used without copying. This is useful for instance for uploading large WebGL textures directly from the heap.

Memory views should be treated like raw pointers; lifetime and validity are not managed by the runtime and it’s easy to corrupt data if the underlying object is modified or deallocated.

#include <emscripten/bind.h>
#include <emscripten/val.h>

using namespace emscripten;

unsigned char *byteBuffer = /* ... */;
size_t bufferLength = /* ... */;

val getBytes() {
    return val(typed_memory_view(bufferLength, byteBuffer));
}

EMSCRIPTEN_BINDINGS(memory_view_example) {
    function("getBytes", &getBytes);
}

The calling JavaScript code will receive a typed array view into the emscripten heap:

var myUint8Array = Module.getBytes()
var xhr = new XMLHttpRequest();
xhr.open('POST', /* ... */);
xhr.send(myUint8Array);

The typed array view will be of the appropriate matching type, such as Uint8Array for an unsigned char array or pointer.

Using val to transliterate JavaScript to C++

Embind provides a C++ class, emscripten::val, which you can use to transliterate JavaScript code to C++. Using val you can call JavaScript objects from your C++, read and write their properties, or coerce them to C++ values like a bool, int, or std::string.

The example below shows how you can use val to call the JavaScript Web Audio API from C++:

Note

This example is based on the excellent Web Audio tutorial: Making sine, square, sawtooth and triangle waves (stuartmemo.com). There is an even simpler example in the emscripten::val documentation.

First consider the JavaScript below, which shows how to use the API:

// Get web audio api context
var AudioContext = window.AudioContext || window.webkitAudioContext;

// Got an AudioContext: Create context and OscillatorNode
var context = new AudioContext();
var oscillator = context.createOscillator();

// Configuring oscillator: set OscillatorNode type and frequency
oscillator.type = 'triangle';
oscillator.frequency.value = 261.63; // value in hertz - middle C

// Playing
oscillator.connect(context.destination);
oscillator.start();

// All done!

The code can be transliterated to C++ using val, as shown below:

#include <emscripten/val.h>
#include <stdio.h>
#include <math.h>

using namespace emscripten;

int main() {
  val AudioContext = val::global("AudioContext");
  if (!AudioContext.as<bool>()) {
    printf("No global AudioContext, trying webkitAudioContext\n");
    AudioContext = val::global("webkitAudioContext");
  }

  printf("Got an AudioContext\n");
  val context = AudioContext.new_();
  val oscillator = context.call<val>("createOscillator");

  printf("Configuring oscillator\n");
  oscillator.set("type", val("triangle"));
  oscillator["frequency"].set("value", val(261.63)); // Middle C

  printf("Playing\n");
  oscillator.call<void>("connect", context["destination"]);
  oscillator.call<void>("start", 0);

  printf("All done!\n");
}

First we use global() to get the symbol for the global AudioContext object (or webkitAudioContext if that does not exist). We then use new_() to create the context, and from this context we can create an oscillator, set() its properties (again using val) and then play the tone.

The example can be compiled on the Linux/macOS terminal with:

emcc -O2 -Wall -Werror --bind -o oscillator.html oscillator.cpp

Built-in type conversions

Out of the box, embind provides converters for many standard C++ types:

C++ type JavaScript type
void undefined
bool true or false
char Number
signed char Number
unsigned char Number
short Number
unsigned short Number
int Number
unsigned int Number
long Number
unsigned long Number
float Number
double Number
std::string ArrayBuffer, Uint8Array, Uint8ClampedArray, Int8Array, or String
std::wstring String (UTF-16 code units)
emscripten::val anything

For convenience, embind provides factory functions to register std::vector<T> (register_vector()) and std::map<K, V> (register_map()) types:

EMSCRIPTEN_BINDINGS(stl_wrappers) {
    register_vector<int>("VectorInt");
    register_map<int,int>("MapIntInt");
}

A full example is shown below:

#include <emscripten/bind.h>
#include <string>
#include <vector>

using namespace emscripten;

std::vector<int> returnVectorData () {
  std::vector<int> v(10, 1);
  return v;
}

std::map<int, std::string> returnMapData () {
  std::map<int, std::string> m;
  m.insert(std::pair<int, std::string>(10, "This is a string."));
  return m;
}

EMSCRIPTEN_BINDINGS(module) {
  function("returnVectorData", &returnVectorData);
  function("returnMapData", &returnMapData);

  // register bindings for std::vector<int> and std::map<int, std::string>.
  register_vector<int>("vector<int>");
  register_map<int, std::string>("map<int, string>");
}

The following JavaScript can be used to interact with the above C++.

var retVector = Module['returnVectorData']();

// vector size
var vectorSize = retVector.size();

// reset vector value
retVector.set(vectorSize - 1, 11);

// push value into vector
retVector.push_back(12);

// retrieve value from the vector
for (var i = 0; i < retVector.size(); i++) {
    console.log("Vector Value: ", retVector.get(i));
}

// expand vector size
retVector.resize(20, 1);

var retMap = Module['returnMapData']();

// map size
var mapSize = retMap.size();

// retrieve value from map
console.log("Map Value: ", retMap.get(10));

// figure out which map keys are available
// NB! You must call `register_vector<key_type>`
// to make vectors available
var mapKeys = retMap.keys();
for (var i = 0; i < mapKeys.size(); i++) {
    var key = mapKeys.get(i);
    console.log("Map key/value: ", key, retMap.get(key));
}

// reset the value at the given index position
retMap.set(10, "OtherValue");

Performance

At time of writing there has been no comprehensive embind performance testing, either against standard benchmarks, or relative to WebIDL Binder.

The call overhead for simple functions has been measured at about 200 ns. While there is room for further optimisation, so far its performance in real-world applications has proved to be more than acceptable.

WebIDL Binder

The WebIDL Binder provides a simple and lightweight approach to binding C++, so that compiled code can be called from JavaScript as if it were a normal JavaScript library.

The WebIDL Binder uses WebIDL to define the bindings, an interface language that was specifically designed for gluing together C++ and JavaScript. Not only is this a natural choice for the bindings, but because it is low-level it is relatively easy to optimize.

The binder supports the subset of C++ types that can be expressed in WebIDL. This subset is more than sufficient for most use cases — examples of projects that have been ported using the binder include the Box2D and Bullet physics engines.

This topic shows how bind and use C++ classes, functions and other types using IDL.

Note

An alternative to the WebIDL Binder is to use Embind. For more information see Binding C++ and JavaScript — WebIDL Binder and Embind.

A quick example

Binding using the WebIDL Binder is a three-stage process:

  • Create a WebIDL file that describes the C++ interface.
  • Use the binder to generate C++ and JavaScript “glue” code.
  • Compile this glue code with the Emscripten project.
Defining the WebIDL file

The first step is to create a WebIDL file that describes the C++ types you are going to bind. This file will duplicate some of the information in the C++ header file, in a format that is explicitly designed both for easy parsing, and for representing code items.

For example, consider the following C++ classes:

class Foo {
public:
  int getVal();
  void setVal(int v);
};

class Bar {
public:
  Bar(long val);
  void doSomething();
};

The following IDL file can be used to describe them:

interface Foo {
  void Foo();
  long getVal();
  void setVal(long v);
};

interface Bar {
  void Bar(long val);
  void doSomething();
};

The mapping between the IDL definition and the C++ is fairly obvious. The main things to notice are:

  • The IDL class definitions include a function returning void that has the same name as the interface. This constructor allows you to create the object from JavaScript, and must be defined in IDL even if the C++ uses the default constructor (see Foo above).
  • The type names in WebIDL are not identical to those in C++ (for example, int maps to long above). For more information about the mappings see WebIDL types.

Note

structs are defined in the same way as the classes above — using the interface keyword.

Generating the bindings glue code

The bindings generator (tools/webidl_binder.py) takes a Web IDL file name and an output file name as inputs, and creates C++ and JavaScript glue code files.

For example, to create the glue code files glue.cpp and glue.js for the IDL file my_classes.idl, you would use the following command:

python tools/webidl_binder.py my_classes.idl glue
Compiling the project (using the bindings glue code)

To use the glue code files (glue.cpp and glue.js) in a project:

  1. Add --post-js glue.js in your final emcc command. The post-js option adds the glue code at the end of the compiled output.
  2. Create a file called something like my_glue_wrapper.cpp to #include the headers of the classes you are binding and glue.cpp. This might have the following content:
#include <...> // Where "..." represents the headers for the classes we are binding.
#include <glue.cpp>

Note

The C++ glue code emitted by the bindings generator does not include the headers for the classes it binds because they are not present in the Web IDL file. The step above makes these available to the glue code. Another alternative would be to include the headers at the top of glue.cpp, but then they would be overwritten every time the IDL file is recompiled.

  1. Add my_glue_wrapper.cpp to the final emcc command.

The final emcc command includes both the C++ and JavaScript glue code, which are built to work together:

emcc my_classes.cpp my_glue_wrapper.cpp --post-js glue.js -o output.js

The output now contains everything needed to use the C++ classes through JavaScript.

Modular output

When using the WebIDL binder, often what you are doing is creating a library. In that case, the MODULARIZE option makes sense to use. It wraps the entire JavaScript output in a function, and returns a Promise which resolves to the initialized Module instance.

var instance;
Module().then(module => {
  instance = module;
});

The promise is resolved when it is safe to run compiled code, i.e. after it has been has been downloaded and instantiated. The promise is resolved at the same time the onRuntimeInitialized callback is invoked, so there’s no need to use onRuntimeInitialized when using MODULARIZE.

You can use the EXPORT_NAME option to change Module to something else. This is good practice for libraries, as then they don’t include unnecessary things in the global scope, and in some cases you want to create more than one.

Using C++ classes in JavaScript

Once binding is complete, C++ objects can be created and used in JavaScript as though they were normal JavaScript objects. For example, continuing the above example, you can create the Foo and Bar objects and call methods on them.

var f = new Module.Foo();
f.setVal(200);
alert(f.getVal());

var b = new Module.Bar(123);
b.doSomething();

Important

Always access objects through the Module object object, as shown above.

While the objects are also available in the global namespace by default, there are cases where they will not be (for example, if you use the closure compiler to minify code or wrap compiled code in a function to avoid polluting the global namespace). You can of course use whatever name you like for the module by assigning it to a new variable: var MyModuleName = Module;.

Important

You can only use this code when it is safe to call compiled code, see more details in that FAQ entry.

JavaScript will automatically garbage collect any of the wrapped C++ objects when there are no more references. If the C++ object doesn’t require specific clean up (i.e. it doesn’t have a destructor) then no other action needs to be taken.

If a C++ object does need to be cleaned up, you must explicitly call Module.destroy(obj) to invoke its destructor — then drop all references to the object so that it can be garbage collected. For example, if Bar were to allocate memory that requires cleanup:

var b = new Module.Bar(123);
b.doSomething();
Module.destroy(b); // If the C++ object requires clean up

Note

The C++ constructor is called transparently when a C++ object is created in JavaScript. There is no way, however, to tell if a JavaScript object is about to be garbage collected, so the binder glue code can’t automatically call the destructor.

You will usually need to destroy the objects which you create, but this depends on the library being ported.

Attributes

Object attributes are defined in IDL using the attribute keyword. These can then be accessed in JavaScript using either get_foo()/set_foo() accessor methods, or directly as a property of the object.

// C++
int attr;
// WebIDL
attribute long attr;
// JavaScript
var f = new Module.Foo();
f.attr = 7;
// Equivalent to:
f.set_attr(7);

console.log(f.attr);
console.log(f.get_attr());

For read-only attributes, see Const.

Pointers, References, Value types (Ref and Value)

C++ arguments and return types can be pointers, references, or value types (allocated on the stack). The IDL file uses different decoration to represent each of these cases.

Undecorated argument and return values in the IDL are assumed to be pointers in the C++:

// C++
MyClass* process(MyClass* input);
// WebIDL
MyClass process(MyClass input);

References should be decorated using [Ref]:

// C++
MyClass& process(MyClass& input);
// WebIDL
[Ref] MyClass process([Ref] MyClass input);

Note

If [Ref] is omitted on a reference, the generated glue C++ will not compile (it fails when it tries to convert the reference — which it thinks is a pointer — to an object).

If the C++ returns an object (rather than a reference or a pointer) then the return type should be decorated using [Value]. This will allocate a static (singleton) instance of that class and return it. You should use it immediately, and drop any references to it after use.

// C++
MyClass process(MyClass& input);
// WebIDL
[Value] MyClass process([Ref] MyClass input);

Const

C++ arguments or return types that use const can be specified in IDL using [Const].

For example, the following code fragments show the C++ and IDL for a function that returns a constant pointer object.

//C++
const myObject* getAsConst();
// WebIDL
[Const] myObject getAsConst();

Attributes that correspond to const data members must be specified with the readonly keyword, not with [Const]. For example:

//C++
const int numericalConstant;
// WebIDL
readonly attribute long numericalConstant;

This will generate a get_numericalConstant() method in the bindings, but not a corresponding setter. The attribute will also be defined as read-only in JavaScript, meaning that trying to set it will have no effect on the value, and will throw an error in strict mode.

Tip

It is possible for a return type to have multiple specifiers. For example, an method that returns a contant reference would be marked up in the IDL using [Ref, Const].

Un-deletable classes (NoDelete)

If a class cannot be deleted (because the destructor is private), specify [NoDelete] in the IDL file.

[NoDelete]
interface Foo {
...
};

Defining inner classes and classes inside namespaces (Prefix)

C++ classes that are declared inside a namespace (or another class) must use the IDL file Prefix keyword to specify the scope. The prefix is then used whenever the class is referred to in C++ glue code.

For example, the following IDL definition ensures that Inner class is referred to as MyNameSpace::Inner

[Prefix="MyNameSpace::"]
interface Inner {
..
};

Operators

You can bind to C++ operators using [Operator=]:

[Operator="+="] TYPE1 add(TYPE2 x);

Note

  • The operator name can be anything (add is just an example).
  • Support is currently limited to operators that contain =: +=, *=, -= etc., and to the array indexing operator [].

enums

Enums are declared very similarly in C++ and IDL:

// C++
enum AnEnum {
  enum_value1,
  enum_value2
};

// WebIDL
enum AnEnum {
  "enum_value1",
  "enum_value2"
};

The syntax is slightly more complicated for enums declared inside a namespace:

// C++
namespace EnumNamespace {
  enum EnumInNamespace {
  e_namespace_val = 78
  };
};

// WebIDL
enum EnumNamespace_EnumInNamespace {
  "EnumNamespace::e_namespace_val"
};

When the enum is defined inside a class, the IDL definitions for the enum and class interface are separate:

// C++
class EnumClass {
 public:
  enum EnumWithinClass {
  e_val = 34
  };
  EnumWithinClass GetEnum() { return e_val; }

  EnumNamespace::EnumInNamespace GetEnumFromNameSpace() { return EnumNamespace::e_namespace_val; }
};



// WebIDL
enum EnumClass_EnumWithinClass {
  "EnumClass::e_val"
};

interface EnumClass {
  void EnumClass();

  EnumClass_EnumWithinClass GetEnum();

  EnumNamespace_EnumInNamespace GetEnumFromNameSpace();
};

Sub-classing C++ base classes in JavaScript (JSImplementation)

The WebIDL Binder allows C++ base classes to be sub-classed in JavaScript. In the IDL fragment below, JSImplementation="Base" means that the associated interface (ImplJS) will be a JavaScript implementation of the C++ class Base.

[JSImplementation="Base"]
interface ImplJS {
  void ImplJS();
  void virtualFunc();
  void virtualFunc2();
};

After running the bindings generator and compiling, you can implement the interface in JavaScript as shown:

var c = new ImplJS();
c.virtualFunc = function() { .. };

When C++ code has a pointer to a Base instance and calls virtualFunc(), that call will reach the JavaScript code defined above.

Note

  • You must implement all the methods you mentioned in the IDL of the JSImplementation class (ImplJS) or compilation will fail with an error.
  • You will also need to provide an interface definition for the Base class in the IDL file.

Pointers and comparisons

All the binding functions expect to receive wrapper objects (which contain a raw pointer) rather than a raw pointer. You shouldn’t normally need to deal with raw pointers (these are simply memory addresses/integers). If you do, the following functions in the compiled code can be useful:

  • wrapPointer(ptr, Class) — Given a raw pointer (an integer), returns a wrapped object.

    Note

    If you do not pass the Class, it will be assumed to be the root class — this probably isn’t what you want!

  • getPointer(object) — Returns a raw pointer.

  • castObject(object, Class) — Returns a wrapping of the same pointer but to another class.

  • compare(object1, object2) — Compares two objects’ pointers.

Note

There is always a single wrapped object for a certain pointer to a certain class. This allows you to add data on that object and use it elsewhere using normal JavaScript syntax (object.attribute = someData etc.)

compare() should be used instead of direct pointer comparison because it is possible to have different wrapped objects with the same pointer if one class is a subclass of the other.

NULL

All the binding functions that return pointers, references, or objects will return wrapped pointers. The reason is that by always returning a wrapper, you can take the output and pass it to another binding function without that function needing to check the type of the argument.

One case where this can be confusing is when returning a NULL pointer. When using bindings, the returned pointer will be NULL (a global singleton with a wrapped pointer of 0) rather than null (the JavaScript built-in object) or 0.

void*

The void* type is supported through a VoidPtr type that you can use in IDL files. You can also use the any type.

The difference between them is that VoidPtr behaves like a pointer type in that you get a wrapper object, while any behaves like a 32-bit integer (which is what raw pointers are in Emscripten-compiled code).

WebIDL types

The type names in WebIDL are not identical to those in C++. This section shows the mapping for the more common types you’ll encounter.

C++ IDL
bool boolean
float float
double double
char byte
char* DOMString (represents a JavaScript string)
unsigned char octet
int long
long long
unsigned short unsigned short
unsigned long unsigned long
long long long long
void void
void* any or VoidPtr (see void*)

Note

The WebIDL types are fully documented in this W3C specification.

Test and example code

For a complete working example, see test_webidl in the test suite. The test suite code is guaranteed to work and covers more cases than this article alone.

Another good example is ammo.js, which uses the WebIDL Binder to port the Bullet Physics engine to the Web.

Files and File Systems

This section contains articles related to using files in Emscripten-compiled code.

See also

API Reference:

File System Overview

The following sections provide a brief overview of the Emscripten file system environment and architecture. In addition to discussing support for standard C/C++ synchronous file APIs, it briefly discusses the File System API and Emscripten’s Asynchronous File System API.

Emscripten file system runtime environment

Native code and “normal” JavaScript use quite different file-access paradigms. Portable native code usually calls synchronous file APIs in libc and libcxx, while JavaScript allows only asynchronous file access (except in web workers). In addition, JavaScript does not have direct access to the host file system when run inside the sandbox environment provided by a web browser.

Emscripten provides a virtual file system that simulates the local file system, so that native code using synchronous file APIs can be compiled and run with little or no change.

Packaging Files explains how you can use emcc to specify which files you need to include in the file system. For many developers, that may be all you need to do.

Emscripten file system architecture

The main elements of the Emscripten File System architecture are shown below. Most native code will call the synchronous file APIs in libc and libcxx. These in turn call the underlying File System API, which by default uses the MEMFS virtual file system.

File System Architecture

MEMFS is mounted at / when the runtime is initialized. Files to be added to the MEMFS virtual file system are specified at compile time using emcc, as discussed in Packaging Files. The files are loaded asynchronously by JavaScript using Synchronous XHRs when the page is first loaded. The compiled code is only allowed to run (and call synchronous APIs) when the asynchronous download has completed and the files are available in the virtual file system.

With MEMFS all files exist strictly in-memory, and any data written to them is lost when the page is reloaded. If persistent data is required you can mount the IDBFS file system in a browser or NODEFS on node.js. NODEFS provides direct access to the local file system, but only when run inside node.js. You can call the File System API directly from your own JavaScript to mount new file systems, and to perform other synchronous file system operations that might be required. There is more information on this topic in File systems.

If you need to fetch other files from the network to the file system then use emscripten_wget() and the other methods in the Asynchronous File System API. These methods are asynchronous and the application must wait until the registered callback completes before trying to read them.

Packaging Files

This topic shows how to package the files that will be used to populate Emscripten’s virtual file system when the page is loaded.

There are two alternatives for how files are packaged: preloading and embedding. Embedding puts the specified files inside the generated JavaScript, while preloading packages the files separately. Embedding files is much less efficient than preloading and should only be used when packaging small numbers of small files. Preloading also enables the option to separately host the data.

Emcc uses the file packager to package the files and generate the File System API calls that create and load the file system at run time. While Emcc is the recommended tool for packaging, there are cases where it can make sense to run the file packager manually.

With --use-preload-plugins, files can be automatically decoded based on their extension. See Preloading files for more information.

Packaging using emcc

The easiest way to package files is to use emcc at compile time. The preload and embed commands select their respective packaging methods.

The command below shows how to package files for preloading:

emcc file.cpp -o file.html --preload-file asset_dir

The command generates file.html, file.js and file.data. The .data file contains all the files in asset_dir/, and is loaded by file.js.

Note

The Tutorial demonstrates preloading using the hello_world_file.cpp test code.

The command for embedding is shown below. In this case emcc generates file.html and file.js — the contents of asset_dir/ are embedded directly into the file.js:

emcc file.cpp -o file.html --embed-file asset_dir

By default, the files to be packaged should be nested in or below the compile-time command prompt directory. At runtime the same nested file structure is mapped to the virtual file system, with the root corresponding to the command prompt directory.

For example, consider a file structure dir1/dir2/dir3/asset_dir/ where the project is compiled from dir2. When we package asset_dir, we specify its relative location dir3/asset_dir/:

emcc file.cpp -o file.html --preload-file dir3/asset_dir

The folder is available at this same location dir3/asset_dir in the virtual file system at runtime. Similarly, if we packaged a file in dir2, it would be available in the root of the virtual file system at runtime.

The @ symbol can be used to map packaged files from any location in the local file system to any location in the virtual file system. This is discussed below in Modifying file locations in the virtual file system.

Packaging using the file packager tool

You can also run the file packager manually using the instructions at the top of file_packager.py.

The file packager generates a .data file and .js file. The .js file contains the code to use the data file, and must be loaded before loading your main compiled code. (For instance, add <script> tags at the end of your --shell-file right before {{{ SCRIPT }}}`.)

Note

  • Using the file packager allows you to run file packaging separately from compiling the code.
  • You can load multiple datafiles by running the file packager on each and loading the .js outputs. See BananaBread for an example of dynamic loading (cube2/js/game-setup.js).

Changing the data file location

By default, the .data file containing all the preloaded files is loaded from the same URL as your .js file. In some cases it may be useful to have the data file in a different location from the other files — for example if your .html and .js change a lot you may want to keep the data file on a fast CDN somewhere else.

This model is supported by specifying Module.locateFile function to return URL where the data file is stored. The function must be specified in a <script> element before the one that loads the data file.

Modifying file locations in the virtual file system

The default approach for packaging is to directly map the nested file structure at compile time — relative to the compile-time command prompt directory — to the root of the virtual file system. The @ symbol can be used in a path at build time to explicitly specify where the resource will be located in the virtual file system at runtime.

Note

The @ symbol is needed because sometimes it is useful to package files that are not nested below the compile-time directory, and for which there is therefore no default mapping to a location in the virtual file system.

For example, we can map the preloaded folder ../../asset_dir to the root of the virtual file system (/) using:

emcc file.cpp -o file.html --preload-file ../../asset_dir@/

We can also map a new path and filename. For example, to make the embedded file ../res/gen123.png available as /main.png we might do:

emcc file.cpp -o file.html --embed-file ../res/[email protected]

Valid Character Set

The following characters may be used in filenames: A-Z, a-z, 0-9, the space character and any of the characters !#$%&'()+,-.;=@[]^_`{}~. Additionally, the following characters may be used if your host filesystem supports them: "*<>?| (Windows does not allow using these in filenames). When specifying the character @ on the command line, it must be escaped to the form @@ to avoid triggering the src@dst mapping notation (see above). The characters /, \ and : cannot be used.

Monitoring file usage

Important

Only package the files your app actually needs, in order to reduce download size and improve startup speed.

There is an option to log which files are actually used at runtime. To use it, define the Module.logReadFiles object. Each file that is read will be logged to stderr.

An alternative approach is to look at FS.readFiles() in your compiled JavaScript. This is an object with keys for all the files that were read from. You may find it easier to use than logging as it records files rather than potentially multiple file accesses.

Note

You can also modify the FS.readFiles() object or remove it entirely. This can be useful, say, in order to see which files are read between two points in time in your app.

Preloading files

With --use-preload-plugins, files can be automatically decoded based on their extension. This can also be done manually by calling emscripten_run_preload_plugins() on each file. The files remain stored in their original form in the file system, but their decoded form can be used directly.

The following formats are supported:

  • Images (.jpg, .jpeg, .png, .bmp): The files are decoded using the browser’s image decoder, and can then be used by IMG_Load (SDL1 and SDL2 port, which rely on emscripten_get_preloaded_image_data()). (Set Module.noImageDecoding to true to disable).
  • Audio (.ogg, .wav, .mp3): The files are decoded using the browser’s audio decoder, and can then by used with Mix_LoadWAV (SDL1 only). (Set Module.noAudioDecoding to true to disable).
  • Dynamic libraries (.so): The files are precompiled and instantiated using WebAssembly.instantiate. This is useful for browsers, such as Chrome, that require compiling large WebAssembly modules asynchronously, if you then want to load the module synchronously using dlopen later. (Set Module.noWasmDecoding to true to disable).

Test code

The test suite contains many file packaging examples, and is a good place to search for working code.

Synchronous Virtual XHR Backed File System Usage

Emscripten supports lazy loading of binary data from HTTP servers using XHR. This functionality can be used to create a backend for synchronous file access from compiled code.

The backend can improve start up time as the whole file system does not need to be preloaded before compiled code is run. It can also be very efficient if the web server supports byte serving — in this case Emscripten can just read the parts of files that are actually needed.

Warning

This mechanism is only possible in Web Workers (due to browser limitations).

Note

If byte serving is not supported then Emscripten will have to load the whole file (however big) even if a single byte is read.

Test code

An example of how to implement a synchronous virtual XHR backed file system is provided in the test code at tests/test_browser.py (see test_chunked_synchronous_xhr). The test case also contains an HTTP server (see test_chunked_synchronous_xhr_server) showing CORS headers that might need to be set (if the resources are hosted from the same domain Emscripten runs from, there is no issue).

The tests use checksummer.c as the Emscripten-compiled program. This is simply a vanilla C program using synchronous libc file system calls like fopen(), fread(), fclose() etc.

JavaScript code is added (using emcc’s pre-js option) to map the file system calls in checksummer.c to a file in the virtual file system. This file is created early in Emscripten initialisation using FS.createLazyFile(), but only loaded with content from the server when the file is first accessed by compiled code. The added JavaScript code also sets up communication between the web worker and the main thread.

Instructions

  1. You will need to add JavaScript to the generated code to map the file accessed by your compiled native code and the server.

    The test code simply creates a file in the virtual file system using FS.createLazyFile() and sets the compiled code to use the same file (/bigfile):

    
          if (typeof(Module) === "undefined") Module = {};
          Module["arguments"] = ["/bigfile"];
          Module["preInit"] = function() {
              FS.createLazyFile('/', "bigfile", "http://localhost:11111/bogus_file_path", true, false);
          };
          
    

    Note

    • The compiled test code (in this case) gets the file name from command line arguments — these are set in Emscripten using Module.arguments.
    • The call to create the file is added to Module.preInit. This ensures that it is run before any compiled code.
    • The additional JavaScript is added using emcc’s prejs option.
  2. The added JavaScript should also include code to allow the web worker to communicate with the original thread.

    The test code adds the following JavaScript to the web worker for this purpose. It uses postMessage() to send its stdout back to the main thread.

    
          Module["print"] = function(s) { self.postMessage({channel: "stdout", line: s}); };
          Module["printErr"] = function(s) { self.postMessage({channel: "stderr", char: s, trace: ((doTrace && s === 10) ? new Error().stack : null)}); doTrace = false; };
        
    

    Note

    If you use the above solution, the parent page should probably contain handwritten glue code to handle the stdout data.

  3. You will need a page that spawns the web worker.

    The test code that does this is shown below:

    
          <!doctype html>
          <html>
          <head><meta charset="utf-8"><title>Chunked XHR</title></head>
          <html>
          <body>
            Chunked XHR Web Worker Test
            <script>
              var worker = new Worker(""" + json.dumps(worker_filename) + r""");
              var buffer = [];
              worker.onmessage = function(event) {
                if (event.data.channel === "stdout") {
                  var xhr = new XMLHttpRequest();
                  xhr.open('GET', 'http://localhost:%s/report_result?' + event.data.line);
                  xhr.send();
                  setTimeout(function() { window.close() }, 1000);
                } else {
                  if (event.data.trace) event.data.trace.split("\n").map(function(v) { console.error(v); });
                  if (event.data.line) {
                    console.error(event.data.line);
                  } else {
                    var v = event.data.char;
                    if (v == 10) {
                      var line = buffer.splice(0);
                      console.error(line = line.map(function(charCode){return String.fromCharCode(charCode);}).join(''));
                    } else {
                      buffer.push(v);
                    }
                  }
                }
              };
            </script>
          </body>
          </html>
        """ % self.port)
        
    

Multimedia and Graphics

This section contains articles about Emscripten’s support for graphics and audio APIs.

EGL Support in Emscripten

Note

This article is under construction.

Khronos Group publishes a specification called EGL, which is an API that handles (among other tasks) graphics context creation, rendering surface management, and interop between different Khronos Group graphics APIs (OpenGL, OpenGL ES, OpenVG). For detailed information, see the Khronos EGL webpage.

Currently, EGL is not very widely used across operating systems/graphics driver vendors. The most notable adoption is in the Android architecture, where EGL is the primary method for creating rendering contexts for OpenGL ES 1&2 when using the Android NDK. Also, Mesa has an implementation of the EGL specification in its graphics driver.

Emscripten also supplies an implementation of the EGL v1.4 specification. This allows C/C++ client code to use a (nearly) unified codebase for creating a GLES2 (WebGL) rendering context across Web, Linux (with Mesa) and Android NDK. The implementation of the EGL specification in Emscripten is not perfect, see the end of this page for a status chart.

What EGL is not?

Somewhat disappointingly, EGL is not a self-sufficient complete solution for initializing GLES2 graphics rendering (on any platform, not just Emscripten) and overseeing various associated tasks. The specification is limited in its scope and lacks some features. In particular, EGL cannot help with the following tasks:

  • Creating a render window. The EGL specification does not specify how a target window is created to which to render to. One must use platform-specific native window system functions (X11, Win32 API, ANativeWindow) to first create a render window.
  • Specifying render window size in arbitrary pixel increments. EGL does not have any functionality to request a desired size for the main render window, or to resize it.
  • Specifying a fullscreen video mode/screen resolution. EGL cannot be used to control whether to render in a windowed or fullscreen mode, or to toggle between these at runtime.

Therefore, for each platform, including Emscripten, there exists platform-specific means to perform these tasks.

How to create a WebGL context using EGL?

In the web environment, WebGL is the technology used for 3D-accelerated rendering. WebGL is almost identical to GLES2, and because EGL does not apply at all for WebGL, for all purposes in this page, the terms WebGL and GLES2 are used interchangeably. Therefore to create a WebGL context, one uses EGL, and according to its wording, creates a GLES2 context.

Initialization

Perform the following steps to create a GLES2 context using EGL:

  1. Obtain a handle to an EGLDisplay object by calling eglGetDisplay.
  2. Initialize EGL on that display by calling eglInitialize.
  3. Call eglGetConfigs and/or eglChooseConfig one or multiple times to find the EGLConfig that represents the desired main render target parameters. To examine the attributes of an EGLConfig, call eglGetConfigAttrib.
  4. At this point, one would use whatever platform-specific functions available (X11, Win32 API, ANativeWindow) to set up a native window to render to. For Emscripten, this step does not apply, and can be skipped.
  5. Create a main render target surface (EGLSurface) by calling eglCreateWindowSurface with a valid display and config parameters. Set window and attribute list parameters to null.
  6. Create a GLES2 rendering context (EGLContext) by calling eglCreateContext, followed by a call to eglMakeCurrent to activate the rendering context. When creating the context, specify the context attribute EGL_CONTEXT_CLIENT_VERSION == 2.

After these steps, you have a set of EGL objects EGLDisplay, EGLConfig, EGLSurface and EGLContext that represent the main GLES2 rendering context.

Cleanup

The sequence to clean up at de-initialization is as follows:

  1. Free up the currently active rendering context by calling eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT).
  2. Deinitialize the EGLContext object by calling eglDestroyContext on it.
  3. Destroy all initialized EGLSurface objects by calling eglDestroySurface on them.
  4. Deinitialize EGL altogether by calling eglTerminate(display).
  5. Delete the native rendering window. This step does not apply for Emscripten.
Sample code

Example code for using EGL to initialize a WebGL context can be found in the sample applications in the emscripten/test/glbook directory, more specifically in the file esUtil.c.

Implementation status and notes

This section lists all EGL v1.4 functions and describes their current implementation status in Emscripten.

Fully implemented
  • eglInitialize, eglGetConfigs, eglQueryContext, eglQueryString, eglQuerySurface, eglGetCurrentContext, glGetCurrentSurface, eglGetCurrentDisplay, eglReleaseThread, eglDestroySurface, eglDestroyContext: Implemented and should work according to the EGL v1.4 specification.

  • eglSwapBuffers: Implemented, but this function cannot really control the swap behavior under WebGL. Calling this function is optional under Emscripten. In WebGL, the contents of the display are always presented to the screen only after the code yields its execution back to the browser, that is, when you return from the tick callback handler you passed to emscripten_set_main_loop(). The eglSwapBuffers function can however still be used to detect when a GL context loss event occurs.

  • eglGetDisplay: Implemented according to the specification. Emscripten does not utilize multiple EGLNativeDisplayType objects, so pass in EGL_DEFAULT_DISPLAY here. Emscripten currently actually ignores any value passed in here for Linux emulation purposes, but you should not rely on this in the future.

  • eglGetError: Implemented according to the specification.

    Important

    According to the specification, eglGetError reports the single most recent error rather than the list of all previous errors. Don’t call this function in a loop in the same way you would call glGetError.

Partially implemented
  • eglChooseConfig: Implemented as a stub, but this function does not do searching/filtering, and is at the moment identical to eglGetConfigs (issue #643).
  • eglGetConfigAttrib: Implemented. Querying for the attributes EGL_BUFFER_SIZE, EGL_ALPHA_SIZE, EGL_BLUE_SIZE, EGL_GREEN_SIZE, EGL_RED_SIZE, EGL_DEPTH_SIZE and EGL_STENCIL_SIZE currently return hardcoded default values (issue #644). The attributes EGL_MIN_SWAP_INTERVAL and EGL_MAX_SWAP_INTERVAL don’t currently have any function. Instead, call emscripten_set_main_loop() to specify the main loop update rate.
  • eglCreateWindowSurface: Implemented, except it is not possible to call this function multiple times to create multiple render windows.
  • eglCreateContext: Implemented as a stub. It is not possible to call this function multiple times to create multiple contexts.
  • eglBindAPI, eglQueryAPI: Implemented, although these functions have little utility on Emscripten, since only the GLES2 client API is supported.
  • eglWaitClient, eglWaitNative: Implemented as no-op functions. These have no meaning on Emscripten.
  • eglSwapInterval: Implemented as a no-op stub. Currently this function cannot set the vsync interval, or enable/disable it.
  • eglMakeCurrent: Implemented as a no-op stub.
  • eglTerminate: Implemented as a no-op function stub. JavaScript apps are not often shut down manually, but when closing the browser or switching the web page, the browser manages all teardown automatically. Therefore this function does not have a critical importance in Emscripten.
  • eglGetProcAddress: Implemented, experimental.
Missing functionality

The following functions are currently not implemented:

  • eglCreatePbufferSurface, eglCreatePixmapSurface, eglCreatePbufferFromClientBuffer, eglSurfaceAttrib, eglBindTexImage, eglReleaseTexImage, eglWaitGL, eglCopyBuffers.

Important

Do not call these functions in Emscripten code, or the application will halt on trying to execute an undefined function.

EGL extensions

Currently, Emscripten does not implement any extensions in the EGL Extension Registry.

OpenGL support in Emscripten

Emscripten provides three OpenGL modes:

This topic provides information about the modes, and how they are enabled.

Tip

We highly recommend using the WebGL-friendly subset of OpenGL ES 2.0/3.0 for new code, and porting existing code to this subset if possible. The other two modes are less efficient, and should only be considered for codebases that rely heavily on those features.

WebGL-friendly subset of OpenGL ES 2.0/3.0

By default, Emscripten targets the WebGL-friendly subset of OpenGL ES 2.0. This is the set of GL ES commands that map directly to WebGL, so that each GL command has a roughly direct mapping to WebGL. It includes almost all of OpenGL ES 2.0, with the notable exception of client-side arrays, and some other features that are listed in WebGL 1.0 Specification/Chapter 6.

To program against the WebGL subset of OpenGL ES, one uses the GL ES 2.0 header files and the GL ES 2.0 API, while adhering to the limitations specified in Chapter 6 of the WebGL specification.

This mode is used by default because it best matches the WebGL features provided by browsers.

To target WebGL 2, pass the linker flag -s MAX_WEBGL_VERSION=2. Specifying this flag enables (and defaults to, unless otherwise specified at context creation time) the creation of WebGL 2 contexts at runtime, but it is still possible to create WebGL 1 contexts, so applications can choose whether to require WebGL 2 or whether to support a fallback to WebGL 1.

To only target WebGL 2 and drop support for WebGL 1 altogether to save code size, pass the linker flags -s MIN_WEBGL_VERSION=2 and -s MAX_WEBGL_VERSION=2.

OpenGL ES 2.0/3.0 emulation

This build mode emulates some features of OpenGL ES 2.0/3.0 that are not part of the core WebGL 1 specification.

In particular, this mode emulates client-side arrays that are missing [1] from the WebGL-friendly subset of OpenGL ES 2.0/3.0.

This allows you to use functions glDrawArrays and glDrawElements etc. without a bound buffer, and Emscripten’s GL bindings will set up the buffer automatically (WebGL requires that a buffer be bound).

Note

This build mode has a limitation that the largest index in client-side index buffer must be smaller than the total number of indices in that buffer. See issue #4214 for more details.

To enable OpenGL ES 2.0 emulation, specify the emcc option -s FULL_ES2=1 when linking the final executable (.js/.html) of the project.

To enable OpenGL ES 3.0 emulation, specify the emcc option -s FULL_ES3=1 when linking the final executable (.js/.html) of the project. This adds emulation for mapping memory blocks to client side memory. The flags -s FULL_ES2=1 and -s FULL_ES3=1 are orthogonal, so either one or both can be specified to emulate different features.

Emulation of older Desktop OpenGL API features

This OpenGL mode enables support for a number of legacy desktop OpenGL 1.x features and commands (for example “immediate mode” and glNormalPointer).

While the emulation is by no means complete, it has been sufficient to port the Sauerbraten 3D game (BananaBread project) and some other real-world codebases using Emscripten.

To enable this mode, specify the emcc option -s LEGACY_GL_EMULATION=1 when linking the final executable (.js/.html) of the project.

Optimization settings

In this mode (-s LEGACY_GL_EMULATION=1), there are a few extra flags that can be used to tune the performance of the GL emulation layer:

  • -s GL_UNSAFE_OPTS=1 attempts to skip redundant GL work and cleanup. This optimization is unsafe, so is not enabled by default.
  • -s GL_FFP_ONLY=1 tells the GL emulation layer that your code will not use the programmable pipeline/shaders at all. This allows the GL emulation code to perform extra optimizations when it knows that it is safe to do so.
  • Add the Module.GL_MAX_TEXTURE_IMAGE_UNITS integer to your shell .html file to signal the maximum number of texture units used by the code. This ensures that the GL emulation layer does not waste clock cycles iterating over unused texture units when examining which Fixed Function Pipeline (FFP) emulation shader to run.
What if my codebase depends on an desktop OpenGL feature that is currently unsupported?

You can consider building the codebase against the Regal Desktop OpenGL emulation library, which aims to support Desktop OpenGL features on top of OpenGL ES 2.0. This may work better or worse than Emscripten’s GL emulation depending on the project.

OpenGL ES extensions

When porting code, it should be noted that desktop OpenGL, OpenGL ES and WebGL each have their own extension registries. This means that neither desktop OpenGL or OpenGL ES extensions are automatically also WebGL extensions, although some amount of parity does exist. See the WebGL 1.0 extension registry for the full list of registered extensions.

Additionally, in WebGL, unlike in desktop or mobile OpenGL, extensions must be activated first before the features they expose take effect. If you use one of the native APIs SDL, EGL, GLUT or GLFW to create your GL context, this will be done automatically for most extensions. If instead you use the HTML5 WebGL context creation API, you must explicitly choose whether to autoenable WebGL extensions. If an extension was not automatically enabled at context creation time, the HTML5 API function emscripten_webgl_enable_extension can be used to activate it. Debugging related extensions, draft extensions and vendor-prefixed extensions (MOZ_*, WEBKIT_*) are never enabled automatically at context creation time, but must always be activated manually.

When migrating from WebGL 1 to WebGL 2, take note that some WebGL 1 extensions are migrated to core WebGL 2, and therefore their functionality is no longer advertised as GL extensions. This does not mean that the features would be missing, but that it is possible to utilize these features in WebGL 2 without needing to feature test the presence of a GL extension first.

Test code/examples

The files in tests/glbook provide a number of simple examples that use only the WebGL-friendly subset of OpenGL ES 2.0/3.0.

The other modes are covered in various tests, including several in tests/test_browser.py. The best way to locate the tests is to search the source code for the appropriate compiler flags: FULL_ES2, LEGACY_GL_EMULATION etc.

Bug Reports

The Emscripten bug tracker has labels specific to OpenGL and OpenGL Emulation for tracking various GL-related issues.

Footnotes:

[1]Client-side arrays are missing from WebGL because they are less efficient than properly using GPU-side data.

Audio

Emscripten ships with its own implementation of the OpenAL 1.1 API, using the Web Audio API as a backend.

You can reasonably expect ported OpenAL applications to “just work” with no additional effort. Just link with the -lopenal linker flag.

There are some implementation-specific aspects which are worth considering and are documented here.

Warning

There used to be no additional flag to pass to the compiler in order to use OpenAL. However, specifying -lopenal as mentioned above should be considered mandatory (at some point in the future, it will be)!

Supported OpenAL extensions

The following extensions are supported by Emscripten’s OpenAL implementation.

  • ALC_SOFT_pause_device;
  • ALC_SOFT_HRTF;
  • AL_EXT_float32;
  • AL_SOFT_loop_points;
  • AL_SOFT_source_length;
  • AL_EXT_source_distance_model;
  • AL_SOFT_source_spatialize;

Warning

This doesn’t mean you should just assume their presence ! For correctness, you should always check if an extension is supported before using it, like a good application would do.

Guidelines for Audio on Emscripten

Know that your application needs to yield to the Javascript main loop for audio processing to take place (See Browser main loop).

Put simply, this kind of code will block indefinitely :

while(nframes < THE_NUMBER_OF_FRAMES_WE_WANT)
    alcGetIntegerv(device, ALC_CAPTURE_SAMPLES, 1, &nframes);

The above snippet usually works in native applications because most OpenAL implementations own and manage one or more separate threads. This is not the case in Emscripten.

What you must do instead is perform each such query only once per “main loop iteration” (i.e the callback you provide via emscripten_set_main_loop() or emscripten_set_main_loop_arg()).

Emscripten-specific capture behavior

Attempting to open an input stream to the user’s audio capture device results in the asynchronous appearance of a small browser-specific dialog asking for the user’s permission, and on some browsers, the capture device to choose.

With this in mind, when alcCaptureOpenDevice() is called with valid and supported parameters, a “proxy” device is returned, which successfully captures no sample until the user clicks “Allow” on said dialog.

That means, when calling alcGetIntegerv(device, ALC_CAPTURE_SAMPLES, 1, &nframes), nframes remains set to zero until the user clicks “Allow”. You might want to make your app handle this specific behavior.

If the user clicks “Deny”, the device is invalidated (because this is somewhat similar to unplugging the physical device) and calls to alcCapture* functions on that device then consistently fail with ALC_INVALID_DEVICE. Your application should be prepared to handle this properly.

Note

Some browsers “remember” this choice and apply it automatically every time it would be asked again instead. There’s no way for the implementation to detect this behavior.

Useful implementation details of OpenAL capture

Internally, Web Audio’s capture data is always backed by a Javascript Float32Array. Thus, AL_FORMAT_MONO_FLOAT32 and AL_FORMAT_STEREO_FLOAT32 are the only formats which do not require converting acquired samples from their initial type to another.

Also, the actual sample rate at which samples are acquired from the device is currently dictated by the browser and hardware, instead of user code. If this sample rate does not match the one your app requests, the implementation is required to perform resampling on your behalf.

That sample rate is given by audioCtx.sampleRate, where audioCtx is the AudioContext object used internally by the relevant capture ALCdevice. Currently, Emscripten provides no direct way for applications to access this value, but this might be provided through an Emscripten-specific OpenAL extension (which is not here yet because it requires registration).

Right now though there’s a quick and de facto reliable way to do this (C example):

#ifdef __EMSCRIPTEN__

#include <emscripten.h>

// Avoid calling this more than once! Caching the value is up to you.
unsigned query_sample_rate_of_audiocontexts() {
    return EM_ASM_INT({
        var AudioContext = window.AudioContext || window.webkitAudioContext;
        var ctx = new AudioContext();
        var sr = ctx.sampleRate;
        ctx.close();
        return sr;
    });
}
#endif

It is reasonable to expect this sample rate to be either 44100Hz or 48000Hz. You can test it right now by copying the javascript part into your browser’s console if you’re curious.

Improving and extending the implementation

Currently, the OpenAL capture implementation performs naïve linear resampling because it is simple and the small loss of quality was deemed acceptable.

However, you’re welcome to improve this by contributing if you so wish! See this issue , for instance.

Likewise, if you’d like to see a particular extension implemented (whether it is registered or not), then your best bet is to either file an issue (provided no related prior issue existed for this), or contribute! See Contributing for guidelines.

Debugging

One of the main advantages of debugging cross-platform Emscripten code is that the same cross-platform source code can be debugged on either the native platform or using the web browser’s increasingly powerful toolset — including debugger, profiler, and other tools.

Emscripten provides a lot of functionality and tools to aid debugging:

  • Compiler debug information flags that allow you to preserve debug information in compiled code and even create source maps so that you can step through the native C++ source when debugging in the browser.
  • Debug mode, which emits debug logs and stores intermediate build files for analysis.
  • Compiler settings to enable runtime checking of memory accesses and common allocation errors.
  • Manual print debugging of Emscripten-generated code is also supported, which is in some ways even better than on native platforms.
  • AutoDebugger, which automatically instruments LLVM bitcode to write out each store to memory.

This article describes the main tools and settings provided by Emscripten for debugging, along with a section explaining how to debug a number of Emscripten-specific issues.

Debug information

Emcc strips out most of the debug information from optimized builds by default. Optimisation levels -O1 and above remove LLVM debug information, and also disable runtime ASSERTIONS checks. From optimization level -O2 the code is minified by the Closure Compiler and becomes virtually unreadable.

The emcc -g flag can be used to preserve debug information in the compiled output. By default, this option preserves white-space, function names and variable names.

The flag can also be specified with one of five levels: -g0, -g1, -g2, -g3, and -g4. Each level builds on the last to provide progressively more debug information in the compiled output. The -g3 flag provides the same level of debug information as the -g flag.

The -g4 option provides the most debug information — it generates source maps that allow you to view and debug the C/C++ source code in your browser’s debugger on Firefox, Chrome or Safari!

Note

Some optimizations may be disabled when used in conjunction with the debug flags. For example, if you compile with -O3 -g4 some of the normal -O3 optimizations will be disabled in order to provide the requested debugging information.

Debug mode (EMCC_DEBUG)

The EMCC_DEBUG environment variable can be set to enable Emscripten’s debug mode:

# Linux or macOS
EMCC_DEBUG=1 emcc tests/hello_world.cpp -o hello.html

# Windows
set EMCC_DEBUG=1
emcc tests/hello_world.cpp -o hello.html
set EMCC_DEBUG=0

With EMCC_DEBUG=1 set, emcc emits debug output and generates intermediate files for the compiler’s various stages. EMCC_DEBUG=2 additionally generates intermediate files for each JavaScript optimizer pass.

The debug logs and intermediate files are output to TEMP_DIR/emscripten_temp, where TEMP_DIR is the OS default temporary directory (e.g. /tmp on UNIX).

The debug logs can be analysed to profile and review the changes that were made in each step.

Note

The debug mode can also be enabled by specifying the verbose output compiler flag (emcc -v).

Compiler settings

Emscripten has a number of compiler settings that can be useful for debugging. These are set using the emcc -s option, and will override any optimization flags. For example:

emcc -O1 -s ASSERTIONS=1 tests/hello_world

Some important settings are:

  • ASSERTIONS=1 is used to enable runtime checks for common memory allocation errors (e.g. writing more memory than was allocated). It also defines how Emscripten should handle errors in program flow. The value can be set to ASSERTIONS=2 in order to run additional tests.

    ASSERTIONS=1 is enabled by default. Assertions are turned off for optimized code (-O1 and above).

  • SAFE_HEAP=1 adds additional memory access checks, and will give clear errors for problems like dereferencing 0 and memory alignment issues.

    You can also set SAFE_HEAP_LOG to log SAFE_HEAP operations.

  • Passing the STACK_OVERFLOW_CHECK=1 linker flag adds a runtime magic token value at the end of the stack, which is checked in certain locations to verify that the user code does not accidentally write past the end of the stack. While overrunning the Emscripten stack is not a security issue (JavaScript is sandboxed already), writing past the stack causes memory corruption in global data and dynamically allocated memory sections in the Emscripten HEAP, which makes the application fail in unexpected ways. The value STACK_OVERFLOW_CHECK=2 enables slightly more detailed stack guard checks, which can give a more precise callstack at the expense of some performance. Default value is 2 if ASSERTIONS=1 is set, and disabled otherwise.

  • DEMANGLE_SUPPORT=1 links in code to automatically demangle stack traces, that is, emit human-readable C++ function names instead of _ZN.. ones.

A number of other useful debug settings are defined in src/settings.js. For more information, search that file for the keywords “check” and “debug”.

Sanitizers

Emscripten also supports some of Clang’s sanitizers, such as Undefined Behaviour Sanitizer and Address Sanitizer.

emcc verbose output

Compiling with the emcc -v option passes -v to LLVM and runs Emscripten’s internal sanity checks on the toolchain.

The verbose mode also enables Emscripten’s Debug mode (EMCC_DEBUG) to generate intermediate files for the compiler’s various stages.

Manual print debugging

You can also manually instrument the source code with printf() statements, then compile and run the code to investigate issues.

If you have a good idea of the problem line you can add print(new Error().stack) to the JavaScript to get a stack trace at that point. Also available is stackTrace(), which emits a stack trace and also tries to demangle C++ function names if DEMANGLE_SUPPORT is enabled (if you don’t want or need C++ demangling in a specific stack trace, you can call jsStackTrace()).

Debug printouts can even execute arbitrary JavaScript. For example:

function _addAndPrint($left, $right) {
  $left = $left | 0;
  $right = $right | 0;
  //---
  if ($left < $right) console.log('l<r at ' + stackTrace());
  //---
  _printAnInteger($left + $right | 0);
}

Disabling optimizations

It can sometimes be useful to compile with either LLVM optimizations (llvm-opts) or JavaScript optimizations (js-opts) disabled.

For example, the following command enables Debug information and -O2 optimization (for both LLVM and JavaScript), but then explicitly turns off the JavaScript optimizer.

emcc -O2 --js-opts 0 -g4 tests/hello_world_loop.cpp

The result is code that can be more useful for debugging issues related to LLVM-optimized code:

function _main() {
  var label = 0;
  var $puts=_puts(((8)|0)); //@line 4 "tests/hello_world.c"
  return 1; //@line 5 "tests/hello_world.c"
}

Emscripten-specific issues

Memory Alignment Issues

The Emscripten memory representation is compatible with C and C++. However, when undefined behavior is involved you may see differences with native architectures, and also differences between Emscripten’s output for asm.js and WebAssembly:

  • In asm.js, loads and stores must be aligned, and performing a normal load or store on an unaligned address can fail silently (access the wrong address). If the compiler knows a load or store is unaligned, it can emulate it in a way that works but is slow.
  • In WebAssembly, unaligned loads and stores will work. Each one is annotated with its expected alignment. If the actual alignment does not match, it will still work, but may be slow on some CPU architectures.

Tip

SAFE_HEAP can be used to reveal memory alignment issues.

Generally it is best to avoid unaligned reads and writes — often they occur as the result of undefined behavior, as mentioned above. In some cases, however, they are unavoidable — for example if the code to be ported reads an int from a packed structure in some pre-existing data format. In that case, to make things work properly in asm.js, and be fast in WebAssembly, you must be sure that the compiler knows the load or store is unaligned. To do so you can:

  • Manually read individual bytes and reconstruct the full value
  • Use the emscripten_align* typedefs, which define unaligned versions of the basic types (short, int, float, double). All operations on those types are not fully aligned (use the 1 variants in most cases, which mean no alignment whatsoever).

Function Pointer Issues

If you get an abort() from a function pointer call to nullFunc or b0 or b1 (possibly with an error message saying “incorrect function pointer”), the problem is that the function pointer was not found in the expected function pointer table when called.

Note

nullFunc is the function used to populate empty index entries in the function pointer tables (b0 and b1 are shorter names used for nullFunc in more optimized builds). A function pointer to an invalid index will call this function, which simply calls abort().

There are several possible causes:

  • Your code is calling a function pointer that has been cast from another type (this is undefined behavior but it does happen in real-world code). In optimized Emscripten output, each function pointer type is stored in a separate table based on its original signature, so you must call a function pointer with that same signature to get the right behavior (see Function Pointer Issues in the code portability section for more information).
  • Your code is calling a method on a NULL pointer or dereferencing 0. This sort of bug can be caused by any sort of coding error, but manifests as a function pointer error because the function can’t be found in the expected table at runtime.

In order to debug these sorts of issues:

  • Compile with -Werror. This turns warnings into errors, which can be useful as some cases of undefined behavior would otherwise show warnings.
  • Use -s ASSERTIONS=2 to get some useful information about the function pointer being called, and its type.
  • Look at the browser stack trace to see where the error occurs and which function should have been called.
  • Build with SAFE_HEAP=1 and function pointer aliasing disabled (ALIASING_FUNCTION_POINTERS=0). This should make it impossible for a function pointer to be called with the wrong type without raising an error: -s SAFE_HEAP=1 -s ALIASING_FUNCTION_POINTERS=0

Another function pointer issue is when the wrong function is called. SAFE_HEAP=1 can help with this as it detects some possible errors with function table accesses.

ALIASING_FUNCTION_POINTERS=0 is also useful because it ensures that calls to function pointer addresses in the wrong table result in clear errors. Without this setting such calls just execute whatever function is at the address, which can be much harder to debug.

Infinite loops

Infinite loops cause your page to hang. After a period the browser will notify the user that the page is stuck and offer to halt or close it.

If your code hits an infinite loop, one easy way to find the problem code is to use a JavaScript profiler. In the Firefox profiler, if the code enters an infinite loop you will see a block of code doing the same thing repeatedly near the end of the profile.

Note

The Browser main loop may need to be re-coded if your application uses an infinite main loop.

AutoDebugger

The AutoDebugger is the ‘nuclear option’ for debugging Emscripten code.

Warning

This option is primarily intended for Emscripten core developers.

The AutoDebugger will rewrite the LLVM bitcode so it prints out each store to memory. This is useful because you can compare the output for different compiler settings in order to detect regressions, or compare the output of JavaScript and LLVM bitcode compiled using LLVM Nativizer or LLVM interpreter.

The AutoDebugger can potentially find any problem in the generated code, so it is strictly more powerful than the CHECK_* settings and SAFE_HEAP. One use of the AutoDebugger is to quickly emit lots of logging output, which can then be reviewed for odd behavior. The AutoDebugger is also particularly useful for debugging regressions.

The AutoDebugger has some limitations:

  • It generates a lot of output. Using diff can be very helpful for identifying changes.
  • It prints out simple numerical values rather than pointer addresses (because pointer addresses change between runs, and hence can’t be compared). This is a limitation because sometimes inspection of addresses can show errors where the pointer address is 0 or impossibly large. It is possible to modify the tool to print out addresses as integers in tools/autodebugger.py.

To run the AutoDebugger, compile with the environment variable EMCC_AUTODEBUG=1 set. For example:

# Linux or macOS
EMCC_AUTODEBUG=1 emcc tests/hello_world.cpp -o hello.html

# Windows
set EMCC_AUTODEBUG=1
emcc tests/hello_world.cpp -o hello.html
set EMCC_AUTODEBUG=0

AutoDebugger Regression Workflow

Use the following workflow to find regressions with the AutoDebugger:

  • Compile the working code with EMCC_AUTODEBUG=1 set in the environment.
  • Compile the code using EMCC_AUTODEBUG=1 in the environment again, but this time with the settings that cause the regression. Following this step we have one build before the regression and one after.
  • Run both versions of the compiled code and save their output.
  • Compare the output using a diff tool.

Any difference between the outputs is likely to be caused by the bug.

Note

False positives can be caused by calls to clock(), which will differ slightly between runs.

You can also make native builds using the LLVM Nativizer tool. This can be run on the autodebugged .ll file, which will be emitted in /tmp/emscripten_temp when EMCC_DEBUG=1 is set.

Note

  • The native build created using the LLVM Nativizer will use native system libraries. Direct comparisons of output with Emscripten-compiled code can therefore be misleading.
  • Attempting to interpret code compiled with -g using the LLVM Nativizer or lli may crash, so you may need to build once without -g for these tools, then build again with -g. Another option is to use tools/exec_llvm.py in Emscripten, which will run lli after cleaning out debug info.

Need help?

The Emscripten Test Suite contains good examples of almost all functionality offered by Emscripten. If you have a problem, it is a good idea to search the suite to determine whether test code with similar behavior is able to run.

If you’ve tried the ideas here and you need more help, please Get in touch.

Pthreads support

Emscripten has support for multithreading using SharedArrayBuffer in browsers. That API allows sharing memory between the main thread and web workers as well as atomic operations for synchronization, which enables Emscripten to implement support for the Pthreads (POSIX threads) API. This support is considered stable in Emscripten.

Note

As of Sep 2019, some browsers have disabled SharedArrayBuffer due to the Spectre set of vulnerabilities. Until it is restored you can still experiment with it if you flip a pref in those browsers. In other browsers (like Chrome on desktop), SharedArrayBuffer is fully enabled by default and you don’t need to flip any flags.

Compiling with pthreads enabled

By default, support for pthreads is not enabled. To enable code generation for pthreads, the following command line flags exist:

  • Pass the compiler flag -s USE_PTHREADS=1 when compiling any .c/.cpp files, AND when linking to generate the final output .js file.
  • Optionally, pass the linker flag -s PTHREAD_POOL_SIZE=<integer> to specify a predefined pool of web workers to populate at page preRun time before application main() is called. This is important because if the workers do not already exist then we may need to wait for the next browser event iteration for certain things, see below.

There should be no other changes required. In C/C++ code, the preprocessor check #ifdef __EMSCRIPTEN_PTHREADS__ can be used to detect whether Emscripten is currently targeting pthreads.

Note

It is not possible to build one binary that would be able to leverage multithreading when available and fall back to single threaded when not. The best you can do is two separate builds, one with and one without threads, and pick between them at runtime.

Additional flags

  • -s PROXY_TO_PTHREAD: In this mode your original main() is replaced by a new one that creates a pthread and runs the original main() on it. As a result, your application’s main() is run off the browser main (UI) thread, which is good for responsiveness. The browser main thread does still run code when things are proxied to it, for example to handle events, rendering, etc.

Note that Emscripten has the --proxy-to-worker linker flag which sounds similar but is unrelated. That flag does not use pthreads or SharedArrayBuffer, and instead uses a plain Web Worker to run your main program (and postMessage to proxy messages back and forth).

Proxying

The Web allows certain operations to only happen from the main browser thread, like interacting with the DOM. As a result, various operations are proxied to the main browser thread if they are called on a background thread. See bug 3495 for more information and how to try to work around this until then. To check which operations are proxied, you can look for the function’s implementation in the JS library (src/library_*) and see if it is annotated with __proxy: 'sync' or __proxy: 'async'; however, note that the browser itself proxies certain things (like some GL operations), so there is no general way to be safe here (aside from not blocking on the main browser thread).

In addition, Emscripten currently has a simple model of file I/O only happening on the main application thread (as we support JS plugin filesystems, which cannot share memory); this is another set of operations that are proxied.

Proxying can cause problems in certain cases, see the section on blocking below.

Blocking on the main browser thread

Note that in most cases the “main browser thread” is the same as the “main application thread”. The main browser thread is where web pages start to run JavaScript, and where JavaScript can access the DOM (a page can also create a Web Worker, which would no longer be on the main thread). The main application thread is the one on which you started up the application (by loading the main JS file emitted by Emscripten). If you started it on the main browser thread - by it being a normal HTML page - then the two are identical. However, you can also start a multithreaded application in a worker; in that case the main application thread is that worker, and there is no access to the main browser thread.

The Web API for atomics does not allow blocking on the main thread (specifically, Atomics.wait doesn’t work there). Such blocking is necessary in APIs like pthread_join and anything that uses a futex wait under the hood, like usleep(), emscripten_futex_wait(), or pthread_mutex_lock(). To make them work, we use a busy-wait on the main browser thread, which can make the browser tab unresponsive, and also wastes power. (On a pthread, this isn’t a problem as it runs in a Web Worker, where we don’t need to busy-wait.)

Busy-waiting on the main browser thread in general will work despite the downsides just mentioned, for things like waiting on a lightly-contended mutex. However, things like pthread_join and pthread_cond_wait are often intended to block for long periods of time, and if that happens on the main browser thread, and while other threads expect it to respond, it can cause a surprising deadlock. That can happen because of proxying, see the previous section. If the main thread blocks while a worker attempts to proxy to it, a deadlock can occur.

The bottom line is that on the Web it is bad for the main browser thread to wait on anything else. Therefore by default Emscripten warns if pthread_join and pthread_cond_wait happen on the main browser thread, and will throw an error if ALLOW_BLOCKING_ON_MAIN_THREAD is zero (whose message will point to here).

To avoid these problems, you can use PROXY_TO_PTHREAD, which as mentioned earlier moves your main() function to a pthread, which leaves the main browser thread to focus only on receiving proxied events. This is recommended in general, but may take some porting work, if the application assumed main() was on the main browser thread.

Another option is to replace blocking calls with nonblocking ones. For example you can replace pthread_join with pthread_tryjoin_np. This may require your application to be refactored to use asynchronous events, perhaps through emscripten_set_main_loop() or Asyncify.

Special considerations

The Emscripten implementation for the pthreads API should follow the POSIX standard closely, but some behavioral differences do exist:

  • When the linker flag -s PTHREAD_POOL_SIZE=<integer> is not specified and pthread_create() is called, the new thread will not start until control is yielded back to the browser’s main event loop, because the web worker cannot be created while JS or wasm code is running. This is a violation of POSIX behavior and will break common code which creates a thread and immediately joins it or otherwise synchronously waits to observe an effect such as a memory write. Using a pool creates the web workers before main is called, allowing thread creation to be synchronous.
  • The Emscripten implementation does not support POSIX signals, which are sometimes used in conjunction with pthreads. This is because it is not possible to send signals to web workers and pre-empt their execution. The only exception to this is pthread_kill() which can be used as normal to forcibly terminate a running thread.
  • The Emscripten implementation does also not support multiprocessing via fork() and join().
  • For web security purposes, there exists a fixed limit (by default 20) of threads that can be spawned when running in Firefox Nightly. #1052398. To adjust the limit, navigate to about:config and change the value of the pref “dom.workers.maxPerDomain”.
  • Some of the features in the pthreads specification are unsupported since the upstream musl library that Emscripten utilizes does not support them, or they are marked optional and a conformant implementation need not support them. Such unsupported features in Emscripten include prioritization of threads, and pthread_rwlock_unlock() is not performed in thread priority order. The functions pthread_mutexattr_set/getprotocol(), pthread_mutexattr_set/getprioceiling() and pthread_attr_set/getscope() are no-ops.
  • One particular note to pay attention to when porting is that sometimes in existing codebases the callback function pointers to pthread_create() and pthread_cleanup_push() omit the void* argument, which strictly speaking is undefined behavior in C/C++, but works in several x86 calling conventions. Doing this in Emscripten will issue a compiler warning, and can abort at runtime when attempting to call a function pointer with incorrect signature, so in the presence of such errors, it is good to check the signatures of the thread callback functions.
  • Note that the function emscripten_num_logical_cores() will always return the value of navigator.hardwareConcurrency, i.e. the number of logical cores on the system, even when shared memory is not supported. This means that it is possible for emscripten_num_logical_cores() to return a value greater than 1, while at the same time emscripten_has_threading_support() can return false. The return value of emscripten_has_threading_support() denotes whether the browser has shared memory support available.
  • Pthreads + memory growth (ALLOW_MEMORY_GROWTH) is especially tricky, see wasm design issue #1271. This currently causes JS accessing the wasm memory to be slow - but this will likely only be noticeable if the JS does large amounts of memory reads and writes (wasm runs at full speed, so moving work over can fix this). This also requires that your JS be aware that the HEAP* views may need to be updated - JS code embedded with --js-library etc will automatically be transformed to use the GROWABLE_HEAP_* helper functions where HEAP* are used, but external code that uses Module.HEAP* directly may encounter problems with views being smaller than memory.

Also note that when compiling code that uses pthreads, an additional JavaScript file NAME.worker.js is generated alongside the output .js file (where NAME is the basename of the main file being emitted). That file must be deployed with the rest of the generated code files. By default, NAME.worker.js will be loaded relative to the main HTML page URL. If it is desirable to load the file from a different location e.g. in a CDN environment, then one can define the Module.locateFile(filename) function in the main HTML Module object to return the URL of the target location of the NAME.worker.js entry point. If this function is not defined in Module, then the default location relative to the main HTML file is used.

Running code and tests

Any code that is compiled with pthreads support enabled will currently only work in the Firefox Nightly channel, since the SharedArrayBuffer specification is still in an experimental research stage before standardization. There exists two test suites that can be used to verify the behavior of the pthreads API implementation in Emscripten:

  • The Emscripten unit test suite contains several pthreads-specific tests in the “browser.” suite. Run any of the tests named browser.test_pthread_*.
  • An Emscripten-specialized version of the Open POSIX Test Suite is available at juj/posixtestsuite GitHub repository. This suite contains about 300 tests for pthreads conformance. To run this suite, the pref dom.workers.maxPerDomain should first be increased to at least 50.

Please check these first in case of any issues. Bugs can be reported to the Emscripten bug tracker as usual.

Networking

Emscripten compiled applications have a number of ways to connect with online servers. Check the subtopics here to learn about the different strategies that are available.

If you are familiar with networking concepts provided by different web APIs, such as XmlHttpRequest, Fetch, WebSockets and WebRTC, you can quickly get started by leveraging what you already know: by calling out from C/C++ code to JavaScript (see the “Connecting C++ and JavaScript” section), you can establish networked connections by writing regular JavaScript. For C/C++ developers, Emscripten provides a few approaches, described here.

Emscripten WebSockets API

WebSockets API provides connection-oriented message-framed bidirectional asynchronous networking communication to the browser. It is the closest to TCP on the web that web sites can access, direct access to TCP sockets is not possible from web browsers.

Emscripten provides a passthrough API for accessing the WebSockets API from C/C++ code. This is useful for developers who would prefer not to write any JavaScript code, or deal with the C/C++ and JavaScript language interop. See the system include file <emscripten/websocket.h> for details. One benefit that the Emscripten WebSockets API provides over manual WebSockets access in JavaScript is the ability to share access to a WebSocket handle across multiple threads, something that can be time consuming to develop from scratch.

To target Emscripten WebSockets API, you must link it in with a “-lwebsocket.js” linker directive.

Emulated POSIX TCP Sockets over WebSockets

If you have existing TCP networking code written in C/C++ that utilizes the Posix Sockets API, by default Emscripten attempts to emulate such connections to take place over the WebSocket protocol instead. For this to work, you will need to use something like WebSockify on the server side to enable the TCP server stack to receive incoming WebSocket connections. This emulation is not very complete at the moment, it is likely that you will run into problems out of the box and need to adapt the code to work within the limitations that this emulation provides.

This is the default build mode for POSIX sockets, no linker flags or option settings are needed to enable it.

Full POSIX Sockets over WebSocket Proxy Server

Emscripten provides a native POSIX Sockets proxy server program, located in directory tools/websocket_to_posix_proxy/, that allows full POSIX Sockets API access from a web browser. This support works by proxying all POSIX Sockets API calls from the browser to the Emscripten POSIX Sockets proxy server (via transparent use of WebSockets API), and the proxy server then performs the native TCP/UDP calls on behalf of the page. This allows a web browser page to run full TCP & UDP connections, act as a server to accept incoming connections, and perform host name lookups and reverse lookups. Because all API calls are individually proxied, this support can be slow. This support is mostly useful for developing testing infrastructure and debugging.

The following POSIX sockets functions are proxied in this manner:
  • socket(), socketpair(), shutdown(), bind(), connect(), listen(), accept(), getsockname(), getpeername(), send(), recv(), sendto(), recvfrom(), sendmsg(), recvmsg(), getsockopt(), setsockopt(), getaddrinfo(), `getnameinfo().
The following POSIX sockets functions are currently not proxied (and will not work):
  • poll(), close() (use shutdown() instead), select()

To use POSIX sockets proxying, link the application with flags “-lwebsocket.js -s PROXY_POSIX_SOCKETS=1 -s USE_PTHREADS=1 -s PROXY_TO_PTHREAD=1”. That is, POSIX sockets proxying builds on top of the Emscripten WebSockets library, and requires multithreading and proxying the application main() to a pthread.

For an example of how the POSIX Sockets proxy server works in an Emscripten client program, see the file tests/websocket/tcp_echo_client.cpp.

XmlHttpRequests and Fetch API

For HTTP transfers, one can use the browser built-in XmlHttpRequest (XHR) API and the newer Fetch API. These can be accessed directly from JavaScript. Emscripten also provides passthrough APIs to perform HTTP requests. For more information, see the emscripten_async_wget*() C API and the Emscripten Fetch API.

WebRTC and UDP

Direct UDP communication is not available in browsers, but as a close alternative, the WebRTC specification provides a mechanism to perform UDP-like communication with WebRTC Data Channels. Currently Emscripten does not provide a C/C++ API for interacting with WebRTC.

Porting SIMD code targeting WebAssembly

Emscripten supports the WebAssembly SIMD proposal when using the WebAssembly LLVM backend. To enable SIMD, pass the -msimd128 flag at compile time. This will also turn on LLVM’s autovectorization passes, so no source modifications are necessary to benefit from SIMD.

At the source level, the GCC/Clang SIMD Vector Extensions can be used and will be lowered to WebAssembly SIMD instructions where possible. In addition, there is a portable intrinsics header file that can be used.

#include <wasm_simd128.h>

Separate documentation for the intrinsics header is a work in progress, but its usage is straightforward and its source can be found at wasm_simd128.h. These intrinsics are under active development in parallel with the SIMD proposal and should not be considered any more stable than the proposal itself. Note that most engines will also require an extra flag to enable SIMD. For example, Node requires –experimental-wasm-simd.

WebAssembly SIMD is not supported when using the Fastcomp backend.

Limitations and behavioral differences

When porting native SIMD code, it should be noted that because of portability concerns, the WebAssembly SIMD specification does not expose the full native instruction sets. In particular the following changes exist:

  • Emscripten does not support x86 or any other native inline SIMD assembly or building .s assembly files, so all code should be written to use SIMD intrinsic functions or compiler vector extensions.
  • WebAssembly SIMD does not have control over managing floating point rounding modes or handling denormals.
  • Cache line prefetch instructions are not available, and calls to these functions will compile, but are treated as no-ops.
  • Asymmetric memory fence operations are not available, but will be implemented as fully synchronous memory fences when SharedArrayBuffer is enabled (-s USE_PTHREADS=1) or as no-ops when multithreading is not enabled (default, -s USE_PTHREADS=0).

SIMD-related bug reports are tracked in the Emscripten bug tracker with the label SIMD.

Compiling SIMD code targeting x86 SSE instruction set

Emscripten supports compiling existing x86 SSE utilizing codebases by passing the -msse directive to the compiler, and including the header <xmmintrin.h>.

Currently only the SSE1 instruction set is supported.

The following table highlights the performance landscape that can be expected from the different SSE1 instrinsics. Even if you are directly targeting the native Wasm SIMD opcodes via wasm_simd128.h header, this table can be useful for understanding the performance limitations that the Wasm SIMD specification has when running on x86 hardware.

For detailed information on each SSE intrinsic function, visit the excellent Intel Intrinsics Guide on SSE1.

The following legend is used to highlight the expected performance of various instructions:
  • ✅ Wasm SIMD has a native opcode that matches the x86 SSE instruction, should yield native performance
  • 💡 while the Wasm SIMD spec does not provide a proper performance guarantee, given a suitably smart enough compiler and a runtime VM path, this intrinsic should be able to generate the identical native SSE instruction.
  • 🟡 there is some information missing (e.g. type or alignment information) for a Wasm VM to be guaranteed to be able to reconstruct the intended x86 SSE opcode. This might cause a penalty depending on the target CPU hardware family, especially on older CPU generations.
  • ⚠️ the underlying x86 SSE instruction is not available, but it is emulated via at most few other Wasm SIMD instructions, causing a small penalty.
  • ❌ the underlying x86 SSE instruction is not exposed by the Wasm SIMD specification, so it must be emulated via a slow path, e.g. a sequence of several slower SIMD instructions, or a scalar implementation.
  • 💣 the underlying x86 SSE opcode is not available in Wasm SIMD, and the implementation must resort to such a slow emulated path, that a workaround rethinking the algorithm at a higher level is advised.
  • 💭 the given SSE intrinsic is available to let applications compile, but does nothing.
  • ⚫ the given SSE intrinsic is not available. Referencing the intrinsic will cause a compiler error.

Certain intrinsics in the table below are marked “virtual”. This means that there does not actually exist a native x86 SSE instruction set opcode to implement them, but native compilers offer the function as a convenience. Different compilers might generate a different instruction sequence for these.

x86 SSE intrinsics available via #include <xmmintrin.h>
Intrinsic name WebAssembly SIMD support
_mm_set_ps ✅ wasm_f32x4_make
_mm_setr_ps ✅ wasm_f32x4_make
_mm_set_ss ⚠️ emulated with wasm_f32x4_make
_mm_set_ps1 (_mm_set1_ps) ✅ wasm_f32x4_splat
_mm_setzero_ps 💡 emulated with wasm_f32x4_const(0)
_mm_load_ps 🟡 wasm_v128_load. VM must guess type.
_mm_loadl_pi ❌ scalar loads + shuffle
_mm_loadh_pi ❌ scalar loads + shuffle
_mm_loadr_ps 💡 Virtual. Simd load + shuffle.
_mm_loadu_ps 🟡 wasm_v128_load. VM must guess type.
_mm_load_ps1 (_mm_load1_ps) 🟡 Virtual. Simd load + shuffle.
_mm_load_ss ❌ emulated with wasm_f32x4_make
_mm_storel_pi ❌ scalar stores
_mm_storeh_pi ❌ shuffle + scalar stores
_mm_store_ps 🟡 wasm_v128_store. VM must guess type.
_mm_stream_ps 🟡 wasm_v128_store. VM must guess type.
_mm_prefetch 💭 No-op.
_mm_sfence ⚠️ A full barrier in multithreaded builds.
_mm_shuffle_ps 🟡 wasm_v32x4_shuffle. VM must guess type.
_mm_storer_ps 💡 Virtual. Shuffle + Simd store.
_mm_store_ps1 (_mm_store1_ps) 💡 Virtual. Emulated with shuffle.
_mm_store_ss 💡 emulated with scalar store
_mm_storeu_ps 🟡 wasm_v128_store. VM must guess type.
_mm_storeu_si16 💡 emulated with scalar store
_mm_storeu_si64 💡 emulated with scalar store
_mm_movemask_ps 💣 emulated with scalar branching
_mm_move_ss 💡 emulated with a shuffle
_mm_add_ps ✅ wasm_f32x4_add
_mm_add_ss ⚠️ emulated with a shuffle
_mm_sub_ps ✅ wasm_f32x4_sub
_mm_sub_ss ⚠️ emulated with a shuffle
_mm_mul_ps ✅ wasm_f32x4_mul
_mm_mul_ss ⚠️ emulated with a shuffle
_mm_div_ps ✅ wasm_f32x4_div
_mm_div_ss ⚠️ emulated with a shuffle
_mm_min_ps TODO: pmin once it works
_mm_min_ss ⚠️ emulated with a shuffle
_mm_max_ps TODO: pmax once it works
_mm_max_ss ⚠️ emulated with a shuffle
_mm_rcp_ps ❌ emulated with full precision div
_mm_rcp_ss ❌ emulated with full precision div+shuffle
_mm_sqrt_ps ✅ wasm_f32x4_sqrt
_mm_sqrt_ss ⚠️ emulated with a shuffle
_mm_rsqrt_ps ❌ emulated with full precision div+sqrt
_mm_rsqrt_ss ❌ emulated with full precision div+sqrt+shuffle
_mm_unpackhi_ps 💡 emulated with a shuffle
_mm_unpacklo_ps 💡 emulated with a shuffle
_mm_movehl_ps 💡 emulated with a shuffle
_mm_movelh_ps 💡 emulated with a shuffle
_MM_TRANSPOSE4_PS 💡 emulated with a shuffle
_mm_cmplt_ps ✅ wasm_f32x4_lt
_mm_cmplt_ss ⚠️ emulated with a shuffle
_mm_cmple_ps ✅ wasm_f32x4_le
_mm_cmple_ss ⚠️ emulated with a shuffle
_mm_cmpeq_ps ✅ wasm_f32x4_eq
_mm_cmpeq_ss ⚠️ emulated with a shuffle
_mm_cmpge_ps ✅ wasm_f32x4_ge
_mm_cmpge_ss ⚠️ emulated with a shuffle
_mm_cmpgt_ps ✅ wasm_f32x4_gt
_mm_cmpgt_ss ⚠️ emulated with a shuffle
_mm_cmpord_ps ❌ emulated with 2xcmp+and
_mm_cmpord_ss ❌ emulated with 2xcmp+and+shuffle
_mm_cmpunord_ps ❌ emulated with 2xcmp+or
_mm_cmpunord_ss ❌ emulated with 2xcmp+or+shuffle
_mm_and_ps 🟡 wasm_v128_and. VM must guess type.
_mm_andnot_ps 🟡 wasm_v128_andnot. VM must guess type.
_mm_or_ps 🟡 wasm_v128_or. VM must guess type.
_mm_xor_ps 🟡 wasm_v128_xor. VM must guess type.
_mm_cmpneq_ps ✅ wasm_f32x4_ne
_mm_cmpneq_ss ⚠️ emulated with a shuffle
_mm_cmpnge_ps ⚠️ emulated with not+ge
_mm_cmpnge_ss ⚠️ emulated with not+ge+shuffle
_mm_cmpngt_ps ⚠️ emulated with not+gt
_mm_cmpngt_ss ⚠️ emulated with not+gt+shuffle
_mm_cmpnle_ps ⚠️ emulated with not+le
_mm_cmpnle_ss ⚠️ emulated with not+le+shuffle
_mm_cmpnlt_ps ⚠️ emulated with not+lt
_mm_cmpnlt_ss ⚠️ emulated with not+lt+shuffle
_mm_comieq_ss ❌ scalarized
_mm_comige_ss ❌ scalarized
_mm_comigt_ss ❌ scalarized
_mm_comile_ss ❌ scalarized
_mm_comilt_ss ❌ scalarized
_mm_comineq_ss ❌ scalarized
_mm_ucomieq_ss ❌ scalarized
_mm_ucomige_ss ❌ scalarized
_mm_ucomigt_ss ❌ scalarized
_mm_ucomile_ss ❌ scalarized
_mm_ucomilt_ss ❌ scalarized
_mm_ucomineq_ss ❌ scalarized
_mm_cvtsi32_ss (_mm_cvt_si2ss) ❌ scalarized
_mm_cvtss_si32 (_mm_cvt_ss2si) 💣 scalar with complex emulated semantics
_mm_cvttss_si32 (_mm_cvtt_ss2si) 💣 scalar with complex emulated semantics
_mm_cvtsi64_ss ❌ scalarized
_mm_cvtss_si64 💣 scalar with complex emulated semantics
_mm_cvttss_si64 💣 scalar with complex emulated semantics
_mm_cvtss_f32 💡 scalar get
_mm_malloc ✅ Allocates memory with specified alignment.
_mm_free ✅ Aliases to free().
_MM_GET_EXCEPTION_MASK ✅ Always returns all exceptions masked (0x1f80).
_MM_GET_EXCEPTION_STATE ❌ Exception state is not tracked. Always returns 0.
_MM_GET_FLUSH_ZERO_MODE ✅ Always returns _MM_FLUSH_ZERO_OFF.
_MM_GET_ROUNDING_MODE ✅ Always returns _MM_ROUND_NEAREST.
_mm_getcsr ✅ Always returns _MM_FLUSH_ZERO_OFF|_MM_ROUND_NEAREST|0x1f80.
_MM_SET_EXCEPTION_MASK ⚫ Not available. Fixed to all exceptions masked.
_MM_SET_EXCEPTION_STATE ⚫ Not available. Fixed to zero/clear state.
_MM_SET_FLUSH_ZERO_MODE ⚫ Not available. Fixed to _MM_FLUSH_ZERO_OFF.
_MM_SET_ROUNDING_MODE ⚫ Not available. Fixed to _MM_ROUND_NEAREST.
_mm_setcsr ⚫ Not available.
_mm_undefined_ps ✅ Virtual
⚫ The following extensions that SSE1 instruction set brought to 64-bit wide MMX registers are not available:
  • _mm_avg_pu8, _mm_avg_pu16, _mm_cvt_pi2ps, _mm_cvt_ps2pi, _mm_cvt_pi16_ps, _mm_cvt_pi32_ps, _mm_cvt_pi32x2_ps, _mm_cvt_pi8_ps, _mm_cvt_ps_pi16, _mm_cvt_ps_pi32, _mm_cvt_ps_pi8, _mm_cvt_pu16_ps, _mm_cvt_pu8_ps, _mm_cvtt_ps2pi, _mm_cvtt_pi16_ps, _mm_cvttps_pi32, _mm_extract_pi16, _mm_insert_pi16, _mm_maskmove_si64, _m_maskmovq, _mm_max_pi16, _mm_max_pu8, _mm_min_pi16, _mm_min_pu8, _mm_movemask_pi8, _mm_mulhi_pu16, _m_pavgb, _m_pavgw, _m_pextrw, _m_pinsrw, _m_pmaxsw, _m_pmaxub, _m_pminsw, _m_pminub, _m_pmovmskb, _m_pmulhuw, _m_psadbw, _m_pshufw, _mm_sad_pu8, _mm_shuffle_pi16 and _mm_stream_pi.

Any code referencing these intrinsics will not compile.

Asyncify

Asyncify lets synchronous C or C++ code interact with asynchronous JavaScript. This allows things like:

  • A synchronous call in C that yields to the event loop, which allows browser events to be handled.
  • A synchronous call in C that waits for an asynchronous operation in JS to complete.

Asyncify automatically transforms your compiled code into a form that can be paused and resumed, and handles pausing and resuming for you, so that it is asynchronous (hence the name “Asyncify”) even though you wrote it in a normal synchronous way.

See the Asyncify introduction blogpost for general background and details of how it works internally. The following expands on the Emscripten examples from that post.

Note

This post talks about Asyncify using the new LLVM wasm backend. There was an older Asyncify implementation for the old fastcomp backend. The two algorithms and implementations are entirely separate, so if you are using fastcomp, these docs may not be accurate - you should upgrade to the wasm backend and new Asyncify!

Sleeping / yielding to the event loop

Let’s begin with the example from that blogpost:

// example.cpp
#include <emscripten.h>
#include <stdio.h>

// start_timer(): call JS to set an async timer for 500ms
EM_JS(void, start_timer, (), {
  Module.timer = false;
  setTimeout(function() {
    Module.timer = true;
  }, 500);
});

// check_timer(): check if that timer occurred
EM_JS(bool, check_timer, (), {
  return Module.timer;
});

int main() {
  start_timer();
  // Continuously loop while synchronously polling for the timer.
  while (1) {
    if (check_timer()) {
      printf("timer happened!\n");
      return 0;
    }
    printf("sleeping...\n");
    emscripten_sleep(100);
  }
}

You can compile that with

emcc -O3 example.cpp -s ASYNCIFY

Note

It’s very important to optimize (-O3 here) when using Asyncify, as unoptimized builds are very large.

And you can run it with

nodejs a.out.js

You should then see something like this:

sleeping...
sleeping...
sleeping...
sleeping...
sleeping...
timer happened!

The code is written with a straightforward loop, which does not exit while it is running, which normally would not allow async events to be handled by the browser. With Asyncify, those sleeps actually yield to the browser’s main event loop, and the timer can happen!

Making async Web APIs behave as if they were synchronous

Aside from emscripten_sleep and the other standard sync APIs Asyncify supports, you can also add your own functions. To do so, you must create a JS function that is called from wasm (since Emscripten controls pausing and resuming the wasm from the JS runtime). One way to do that is with a JS library function; another is to use EM_JS, which we’ll use in this next example:

// example.c
#include <emscripten.h>
#include <stdio.h>

EM_JS(void, do_fetch, (), {
  Asyncify.handleSleep(function(wakeUp) {
    out("waiting for a fetch");
    fetch("a.html").then(response => {
      out("got the fetch response");
      // (normally you would do something with the fetch here)
      wakeUp();
    });
  });
});

int main() {
  puts("before");
  do_fetch();
  puts("after");
}

The async operation happens in the EM_JS function do_fetch(), which calls Asyncify.handleSleep. It gives that function the code to be run, and gets a wakeUp function that it calls in the asynchronous future at the right time. After we call wakeUp() the compiled C code resumes normally.

In this example the async operation is a fetch, which means we need to wait for a Promise. While that is async, note how the C code in main() is completely synchronous!

To run this example, first compile it with

./emcc example.c -O3 -o a.html -s ASYNCIFY -s 'ASYNCIFY_IMPORTS=["do_fetch"]'

Note that you must tell the compiler that do_fetch() can do an asynchronous operation, using ASYNCIFY_IMPORTS, otherwise it won’t instrument the code to allow pausing and resuming; see more details later down.

To run this, you must run a local webserver and then browse to http://localhost:8000/a.html. You will see something like this:

before
waiting for a fetch
got the fetch response
after

That shows that the C code only continued to execute after the async JS completed.

More on ASYNCIFY_IMPORTS

As in the above example, you can add JS functions that do an async operation but look synchronous from the perspective of C. The key thing is to add such methods to ASYNCIFY_IMPORTS, regardless of whether the JS function is from a JS library or EM_JS. That list of imports is the list of imports to the wasm module that the Asyncify instrumentation must be aware of. Giving it that list tells it that all other JS calls will not do an async operation, which lets it not add overhead where it isn’t needed.

Returning values

You can also return values from async JS functions. Here is an example:

// example.c
#include <emscripten.h>
#include <stdio.h>

EM_JS(int, get_digest_size, (const char* str), {
  // Note how we return the output of handleSleep() here.
  return Asyncify.handleSleep(function(wakeUp) {
    const text = UTF8ToString(str);
    const encoder = new TextEncoder();
    const data = encoder.encode(text);
    out("ask for digest for " + text);
    window.crypto.subtle.digest("SHA-256", data).then(digestValue => {
      out("got digest of length " + digestValue.byteLength);
      // Return the value by sending it to wakeUp(). It will then be returned
      // from handleSleep() on the outside.
      wakeUp(digestValue.byteLength);
    });
  });
});

int main() {
  const char* silly = "some silly text";
  printf("%s's digest size is: %d\n", silly, get_digest_size(silly));
  return 0;
}

You can build this with

../emcc example.c -s ASYNCIFY=1 -s 'ASYNCIFY_IMPORTS=["get_digest_size"]' -o a.html -O2

This example calls the Promise-returning window.crypto.subtle() API (the example is based off of this MDN example ). Note how we pass the value to be returned into wakeUp(). We must also return the value returned from handleSleep(). The calling C code then gets it normally, after the Promise completes.

Optimizing

As mentioned earlier, unoptimized builds with Asyncify can be large and slow. Build with optimizations (say, -O3) to get good results.

Asyncify adds overhead, both code size and slowness, because it instruments code to allow unwinding and rewinding. That overhead is usually not extreme, something like 50% or so. Asyncify achieves that by doing a whole-program analysis to find functions need to be instrumented and which do not - basically, which can call something that reaches one of ASYNCIFY_IMPORTS. That analysis avoids a lot of unnecessary overhead, however, it is limited by indirect calls, since it can’t tell where they go - it could be anything in the function table (with the same type).

If you know that indirect calls are never on the stack when unwinding, then you can tell Asyncify to ignore indirect calls using ASYNCIFY_IGNORE_INDIRECT.

If you know that some indirect calls matter and others do not, then you can provide a manual list of functions to Asyncify:

  • ASYNCIFY_BLACKLIST is a list of functions that do not unwind the stack. Asyncify will do it’s normal whole-program analysis under the assumption that those do not unwind.
  • ASYNCIFY_WHITELIST is a list of the only functions that can unwind the stack. Asyncify will instrument those and no others.

For more details see settings.js. Note that the manual settings mentioned here are error-prone - if you don’t get things exactly right, your application can break. If you don’t absolutely need maximal performance, it’s usually ok to use the defaults.

Potential problems

Stack overflows

If you see an exception thrown from an asyncify_* API, then it may be a stack overflow. You can increase the stack size with the ASYNCIFY_STACK_SIZE option.

Reentrancy

While waiting on an asynchronous operation browser events can happen. That is often the point of using Asyncify, but unexpected events can happen too. For example, if you just want to pause for 100ms then you can call emscripten_sleep(100), but if you have any event listeners, say for a keypress, then if a key is pressed the handler will fire. If that handler calls into compiled code, then it can be confusing, since it starts to look like coroutines or multithreading, with multiple executions interleaved.

It is not safe to start an async operation while another is already running. The first must complete before the second begins.

Such interleaving may also break assumptions in your codebase. For example, if a function uses a global and assumes nothing else can modify it until it returns, but if that function sleeps and an event causes other code to change that global, then bad things can happen.

Starting to rewind with compiled code on the stack

The examples above show wakeUp() being called from JS (after a callback, typically), and without any compiled code on the stack. If there were compiled code on the stack, then that could interfere with properly rewinding and resuming execution, in confusing ways, and therefore an assertion will be thrown in a build with ASSERTIONS.

(Specifically, the problem there is that while rewinding will work properly, if you later unwind again, that unwinding will also unwind through that extra compiled code that was on the stack - causing a later rewind to behave badly.)

A simple workaround you may find useful is to do a setTimeout of 0, replacing wakeUp() with setTimeout(wakeUp, 0);. That will run wakeUp in a later callback, when nothing else is on the stack.

Migrating from older APIs

If you have code uses the old Emterpreter-Async API, or the old Asyncify, then the new API is somewhat different, and you may need some minor changes:

  • The Emterpreter had “yielding” as a concept, but it isn’t needed in Asyncify. You can replace emscripten_sleep_with_yield() calls with emscripten_sleep().
  • The JS API is different. See notes above on Asyncify.handleSleep(), and see src/library_async.js for more examples.

API Reference

This section lists Emscripten’s public API, organised by header file. At a very high level it consists of:

  • emscripten.h: APIs for integrating with the browser environment.
  • html5.h: Low level glue bindings for interfacing with HTML5 APIs from native code.
  • preamble.js: APIs for working with compiled code from JavaScript.
  • File System API (library_fs.js): APIs for managing file systems and synchronous file operations.
  • Fetch API: API for managing accesses to network XHR and IndexedDB.
  • Module object: Global JavaScript object that can be used to control code execution and access exported methods.
  • val.h (under-construction): Embind API to support transliteration of JavaScript code to C++.
  • bind.h (under-construction): Embind API for binding C++ functions and classes so that they can be called from JavaScript in a natural way.
  • trace.h: A tracing API for doing memory usage analysis.
  • vr.h: API for using WebVR from native code.
  • fiber.h: API for working with Fibers (co-operative threads)
  • Advanced APIs: APIs for advanced users/core developers.

emscripten.h

This page documents the public C++ APIs provided by emscripten.h.

Emscripten uses existing/familiar APIs where possible (for example: SDL). This API provides C++ support for capabilities that are specific to JavaScript or the browser environment, or for which there is no existing API.

Inline assembly/JavaScript

Guide material for the following APIs can be found in Calling JavaScript from C/C++.

Defines

EM_JS(return_type, function_name, arguments, code)

Convenient syntax for JavaScript library functions.

This allows you to declare JavaScript in your C code as a function, which can be called like a normal C function. For example, the following C program would display two alerts if it was compiled with Emscripten and run in the browser:

EM_JS(void, two_alerts, (), {
  alert('hai');
  alert('bai');
});

int main() {
  two_alerts();
  return 0;
}

Arguments can be passed as normal C arguments, and have the same name in the JavaScript code. These arguments can either be of type int32_t or double.

EM_JS(void, take_args, (int x, float y), {
  console.log('I received: ' + [x, y]);
});

int main() {
  take_args(100, 35.5);
  return 0;
}

Null-terminated C strings can also be passed into EM_JS functions, but to operate on them, they need to be copied out from the heap to convert to high-level JavaScript strings.

EM_JS(void, say_hello, (const char* str), {
  console.log('hello ' + UTF8ToString(str));
}

In the same manner, pointers to any type (including void *) can be passed inside EM_JS code, where they appear as integers like char * pointers above did. Accessing the data can be managed by reading the heap directly.

EM_JS(void, read_data, (int* data), {
  console.log('Data: ' + HEAP32[data>>2] + ', ' + HEAP32[(data+4)>>2]);
});

int main() {
  int arr[2] = { 30, 45 };
  read_data(arr);
  return 0;
}

In addition, EM_JS functions can return a value back to C code. The output value is passed back with a return statement:

EM_JS(int, add_forty_two, (int n), {
  return n + 42;
});

EM_JS(int, get_memory_size, (), {
  return HEAP8.length;
});

int main() {
  int x = add_forty_two(100);
  int y = get_memory_size();
  // ...
}

Strings can be returned back to C from JavaScript, but one needs to be careful about memory management.

EM_JS(const char*, get_unicode_str, (), {
  var jsString = 'Hello with some exotic Unicode characters: Tässä on yksi lumiukko: ☃, ole hyvä.';
  // 'jsString.length' would return the length of the string as UTF-16
  // units, but Emscripten C strings operate as UTF-8.
  var lengthBytes = lengthBytesUTF8(jsString)+1;
  var stringOnWasmHeap = _malloc(lengthBytes);
  stringToUTF8(jsString, stringOnWasmHeap, lengthBytes);
  return stringOnWasmHeap;
});

int main() {
  const char* str = get_unicode_str();
  printf("UTF8 string says: %s\n", str);
  // Each call to _malloc() must be paired with free(), or heap memory will leak!
  free(str);
  return 0;
}
EM_ASM(...)

Convenient syntax for inline assembly/JavaScript.

This allows you to declare JavaScript in your C code “inline”, which is then executed when your compiled code is run in the browser. For example, the following C code would display two alerts if it was compiled with Emscripten and run in the browser:

EM_ASM(alert('hai'); alert('bai'));

Arguments can be passed inside the JavaScript code block, where they arrive as variables $0, $1 etc. These arguments can either be of type int32_t or double.

EM_ASM({
  console.log('I received: ' + [$0, $1]);
}, 100, 35.5);

Note the { and }.

Null-terminated C strings can also be passed into EM_ASM blocks, but to operate on them, they need to be copied out from the heap to convert to high-level JavaScript strings.

EM_ASM(console.log('hello ' + UTF8ToString($0)), "world!");

In the same manner, pointers to any type (including void *) can be passed inside EM_ASM code, where they appear as integers like char * pointers above did. Accessing the data can be managed by reading the heap directly.

int arr[2] = { 30, 45 };
EM_ASM({
  console.log('Data: ' + HEAP32[$0>>2] + ', ' + HEAP32[($0+4)>>2]);
}, arr);

Note

  • As of Emscripten 1.30.4, the contents of EM_ASM code blocks appear inside the normal JS file, and as result, Closure compiler and other JavaScript minifiers will be able to operate on them. You may need to use safety quotes in some places (a['b'] instead of a.b) to avoid minification from occurring.
  • The C preprocessor does not have an understanding of JavaScript tokens, and as a result, if the code block contains a comma character ,, it may be necessary to wrap the code block inside parentheses. For example, code EM_ASM(return [1,2,3].length); will not compile, but EM_ASM((return [1,2,3].length)); does.
EM_ASM_INT(code, ...)

This macro, as well as the EM_ASM_DOUBLE one, behave like EM_ASM, but in addition they also return a value back to C code. The output value is passed back with a return statement:

int x = EM_ASM_INT({
  return $0 + 42;
}, 100);

int y = EM_ASM_INT(return HEAP8.length);

Strings can be returned back to C from JavaScript, but one needs to be careful about memory management.

char *str = (char*)EM_ASM_INT({
  var jsString = 'Hello with some exotic Unicode characters: Tässä on yksi lumiukko: ☃, ole hyvä.';
  var lengthBytes = lengthBytesUTF8(jsString)+1;
  // 'jsString.length' would return the length of the string as UTF-16
  // units, but Emscripten C strings operate as UTF-8.
  var stringOnWasmHeap = _malloc(lengthBytes);
  stringToUTF8(jsString, stringOnWasmHeap, lengthBytes);
  return stringOnWasmHeap;
});
printf("UTF8 string says: %s\n", str);
free(str); // Each call to _malloc() must be paired with free(), or heap memory will leak!
EM_ASM_DOUBLE(code, ...)

Similar to EM_ASM_INT but for a double return value.

MAIN_THREAD_EM_ASM(code, ...)

This behaves like EM_ASM, but does the call on the main thread. This is useful in a pthreads build, when you want to interact with the DOM from a pthread; this basically proxies the call for you.

This call is proxied in a synchronous way to the main thread, that is, execution will resume after the main thread has finished running the JS. Synchronous proxying also makes it possible to return a value, see the next two variants.

MAIN_THREAD_EM_ASM_INT(code, ...)

Similar to MAIN_THREAD_EM_ASM but returns an int value.

MAIN_THREAD_EM_ASM_DOUBLE(code, ...)

Similar to MAIN_THREAD_EM_ASM but returns a double value.

MAIN_THREAD_ASYNC_EM_ASM(code, ...)

Similar to MAIN_THREAD_EM_ASM but is proxied in an asynchronous way, that is, the main thread will receive a request to run the code, and will run it when it can; the worker will not wait for that. (Note that if this is called on the main thread, then there is nothing to proxy, and the JS is executed immediately and synchronously.)

Calling JavaScript From C/C++

Guide material for the following APIs can be found in Calling JavaScript from C/C++.

Function pointer types for callbacks

The following types are used to define function callback signatures used in a number of functions in this file.

em_callback_func

General function pointer type for use in callbacks with no parameters.

Defined as:

typedef void (*em_callback_func)(void)
em_arg_callback_func

Generic function pointer type for use in callbacks with a single void* parameter.

This type is used to define function callbacks that need to pass arbitrary data. For example, emscripten_set_main_loop_arg() sets user-defined data, and passes it to a callback of this type on completion.

Defined as:

typedef void (*em_arg_callback_func)(void*)
em_str_callback_func

General function pointer type for use in callbacks with a C string (const char *) parameter.

This type is used for function callbacks that need to be passed a C string. For example, it is used in emscripten_async_wget() to pass the name of a file that has been asynchronously loaded.

Defined as:

typedef void (*em_str_callback_func)(const char *)

Functions

void emscripten_run_script(const char *script)

Interface to the underlying JavaScript engine. This function will eval() the given script. Note: If -s DYNAMIC_EXECUTION=0 is set, this function will not be available.

This function can be called from a pthread, and it is executed in the scope of the Web Worker that is hosting the pthread. To evaluate a function in the scope of the main runtime thread, see the function emscripten_sync_run_in_main_runtime_thread().

Parameters:
  • script (const char*) – The script to evaluate.
Return type:

void

int emscripten_run_script_int(const char *script)

Interface to the underlying JavaScript engine. This function will eval() the given script. Note: If -s DYNAMIC_EXECUTION=0 is set, this function will not be available.

This function can be called from a pthread, and it is executed in the scope of the Web Worker that is hosting the pthread. To evaluate a function in the scope of the main runtime thread, see the function emscripten_sync_run_in_main_runtime_thread().

Parameters:
  • script (const char*) – The script to evaluate.
Returns:

The result of the evaluation, as an integer.

Return type:

int

char *emscripten_run_script_string(const char *script)

Interface to the underlying JavaScript engine. This function will eval() the given script. Note that this overload uses a single buffer shared between calls. Note: If -s DYNAMIC_EXECUTION=0 is set, this function will not be available.

This function can be called from a pthread, and it is executed in the scope of the Web Worker that is hosting the pthread. To evaluate a function in the scope of the main runtime thread, see the function emscripten_sync_run_in_main_runtime_thread().

Parameters:
  • script (const char*) – The script to evaluate.
Returns:

The result of the evaluation, as a string.

Return type:

char*

void emscripten_async_run_script(const char *script, int millis)

Asynchronously run a script, after a specified amount of time.

This function can be called from a pthread, and it is executed in the scope of the Web Worker that is hosting the pthread. To evaluate a function in the scope of the main runtime thread, see the function emscripten_sync_run_in_main_runtime_thread().

Parameters:
  • script (const char*) – The script to evaluate.
  • millis (int) – The amount of time before the script is run, in milliseconds.
Return type:

void

void emscripten_async_load_script(const char *script, em_callback_func onload, em_callback_func onerror)

Asynchronously loads a script from a URL.

This integrates with the run dependencies system, so your script can call addRunDependency multiple times, prepare various asynchronous tasks, and call removeRunDependency on them; when all are complete (or if there were no run dependencies to begin with), onload is called. An example use for this is to load an asset module, that is, the output of the file packager.

This function is currently only available in main browser thread, and it will immediately fail by calling the supplied onerror() handler if called in a pthread.

Parameters:
  • script (const char*) – The script to evaluate.
  • onload (em_callback_func) – A callback function, with no parameters, that is executed when the script has fully loaded.
  • onerror (em_callback_func) – A callback function, with no parameters, that is executed if there is an error in loading.
Return type:

void

Browser Execution Environment

Guide material for the following APIs can be found in Emscripten Runtime Environment.

Functions

void emscripten_set_main_loop(em_callback_func func, int fps, int simulate_infinite_loop)

Set a C function as the main event loop for the calling thread.

If the main loop function needs to receive user-defined data, use emscripten_set_main_loop_arg() instead.

The JavaScript environment will call that function at a specified number of frames per second. If called on the main browser thread, setting 0 or a negative value as the fps will use the browser’s requestAnimationFrame mechanism to call the main loop function. This is HIGHLY recommended if you are doing rendering, as the browser’s requestAnimationFrame will make sure you render at a proper smooth rate that lines up properly with the browser and monitor. If you do not render at all in your application, then you should pick a specific frame rate that makes sense for your code.

If simulate_infinite_loop is true, the function will throw an exception in order to stop execution of the caller. This will lead to the main loop being entered instead of code after the call to emscripten_set_main_loop() being run, which is the closest we can get to simulating an infinite loop (we do something similar in glutMainLoop in GLUT). If this parameter is false, then the behavior is the same as it was before this parameter was added to the API, which is that execution continues normally. Note that in both cases we do not run global destructors, atexit, etc., since we know the main loop will still be running, but if we do not simulate an infinite loop then the stack will be unwound. That means that if simulate_infinite_loop is false, and you created an object on the stack, it will be cleaned up before the main loop is called for the first time.

This function can be called in a pthread, in which case the callback loop will be set up to be called in the context of the calling thread. In order for the loop to work, the calling thread must regularly “yield back” to the browser by exiting from its pthread main function, since the callback will be able to execute only when the calling thread is not executing any other code. This means that running a synchronously blocking main loop is not compatible with the emscripten_set_main_loop() function.

Since requestAnimationFrame() API is not available in web workers, when called emscripten_set_main_loop() in a pthread with fps <= 0, the effect of syncing up to the display’s refresh rate is emulated, and generally will not precisely line up with vsync intervals.

Tip

There can be only one main loop function at a time, per thread. To change the main loop function, first cancel the current loop, and then call this function to set another.

Note

See emscripten_set_main_loop_expected_blockers(), emscripten_pause_main_loop(), emscripten_resume_main_loop() and emscripten_cancel_main_loop() for information about blocking, pausing, and resuming the main loop of the calling thread.

Note

Calling this function overrides the effect of any previous calls to emscripten_set_main_loop_timing() in the calling thread by applying the timing mode specified by the parameter fps. To specify a different timing mode for the current thread, call the function emscripten_set_main_loop_timing() after setting up the main loop.

Parameters:
  • func (em_callback_func) – C function to set as main event loop for the calling thread.
  • fps (int) – Number of frames per second that the JavaScript will call the function. Setting int <=0 (recommended) uses the browser’s requestAnimationFrame mechanism to call the function.
  • simulate_infinite_loop (int) – If true, this function will throw an exception in order to stop execution of the caller.
void emscripten_set_main_loop_arg(em_arg_callback_func func, void *arg, int fps, int simulate_infinite_loop)

Set a C function as the main event loop for the calling thread, passing it user-defined data.

See also

The information in emscripten_set_main_loop() also applies to this function.

Parameters:
  • func (em_arg_callback_func) – C function to set as main event loop. The function signature must have a void* parameter for passing the arg value.
  • arg (void*) – User-defined data passed to the main loop function, untouched by the API itself.
  • fps (int) – Number of frames per second at which the JavaScript will call the function. Setting int <=0 (recommended) uses the browser’s requestAnimationFrame mechanism to call the function.
  • simulate_infinite_loop (int) – If true, this function will throw an exception in order to stop execution of the caller.
void emscripten_push_main_loop_blocker(em_arg_callback_func func, void *arg)
void emscripten_push_uncounted_main_loop_blocker(em_arg_callback_func func, void *arg)

Add a function that blocks the main loop for the calling thread.

The function is added to the back of a queue of events to be blocked; the main loop will not run until all blockers in the queue complete.

In the “counted” version, blockers are counted (internally) and Module.setStatus is called with some text to report progress (setStatus is a general hook that a program can define in order to show processing updates).

Note

  • Main loop blockers block the main loop from running, and can be counted to show progress. In contrast, emscripten_async_calls are not counted, do not block the main loop, and can fire at specific time in the future.
Parameters:
  • func (em_arg_callback_func) – The main loop blocker function. The function signature must have a void* parameter for passing the arg value.
  • arg (void*) – User-defined arguments to pass to the blocker function.
Return type:

void

void emscripten_pause_main_loop(void)
void emscripten_resume_main_loop(void)

Pause and resume the main loop for the calling thread.

Pausing and resuming the main loop is useful if your app needs to perform some synchronous operation, for example to load a file from the network. It might be wrong to run the main loop before that finishes (the original code assumes that), so you can break the code up into asynchronous callbacks, but you must pause the main loop until they complete.

Note

These are fairly low-level functions. emscripten_push_main_loop_blocker() (and friends) provide more convenient alternatives.

void emscripten_cancel_main_loop(void)

Cancels the main event loop for the calling thread.

See also emscripten_set_main_loop() and emscripten_set_main_loop_arg() for information about setting and using the main loop.

Note

This function cancels the main loop, which means that it will no longer be called. No other changes occur to control flow. In particular, if you started the main loop with the simulate_infinite_loop option, you can still cancel the main loop, but execution will not continue in the code right after setting the main loop (we do not actually run an infinite loop there - that’s not possible in JavaScript, so to simulate an infinite loop we halt execution at that stage, and then the next thing that runs is the main loop itself, so it seems like an infinite loop has begun there; canceling the main loop sort of breaks the metaphor).

int emscripten_set_main_loop_timing(int mode, int value)

Specifies the scheduling mode that the main loop tick function of the calling thread will be called with.

This function can be used to interactively control the rate at which Emscripten runtime drives the main loop specified by calling the function emscripten_set_main_loop(). In native development, this corresponds with the “swap interval” or the “presentation interval” for 3D rendering. The new tick interval specified by this function takes effect immediately on the existing main loop, and this function must be called only after setting up a main loop via emscripten_set_main_loop().

param int mode:The timing mode to use. Allowed values are EM_TIMING_SETTIMEOUT, EM_TIMING_RAF and EM_TIMING_SETIMMEDIATE.
Parameters:
  • value (int) –

    The timing value to activate for the main loop. This value interpreted differently according to the mode parameter:

    • If mode is EM_TIMING_SETTIMEOUT, then value specifies the number of milliseconds to wait between subsequent ticks to the main loop and updates occur independent of the vsync rate of the display (vsync off). This method uses the JavaScript setTimeout function to drive the animation.
    • If mode is EM_TIMING_RAF, then updates are performed using the requestAnimationFrame function (with vsync enabled), and this value is interpreted as a “swap interval” rate for the main loop. The value of 1 specifies the runtime that it should render at every vsync (typically 60fps), whereas the value 2 means that the main loop callback should be called only every second vsync (30fps). As a general formula, the value n means that the main loop is updated at every n’th vsync, or at a rate of 60/n for 60Hz displays, and 120/n for 120Hz displays.
    • If mode is EM_TIMING_SETIMMEDIATE, then updates are performed using the setImmediate function, or if not available, emulated via postMessage. See setImmediate on MDN <https://developer.mozilla.org/en-US/docs/Web/API/Window/setImmediate> for more information. Note that this mode is strongly not recommended to be used when deploying Emscripten output to the web, since it depends on an unstable web extension that is in draft status, browsers other than IE do not currently support it, and its implementation has been considered controversial in review.
Return type:

int

Returns:

The value 0 is returned on success, and a nonzero value is returned on failure. A failure occurs if there is no main loop active before calling this function.

Note

Browsers heavily optimize towards using requestAnimationFrame for animation instead of the other provided modes. Because of that, for best experience across browsers, calling this function with mode=EM_TIMING_RAF and value=1 will yield best results. Using the JavaScript setTimeout function is known to cause stutter and generally worse experience than using the requestAnimationFrame function.

Note

There is a functional difference between setTimeout and requestAnimationFrame: If the user minimizes the browser window or hides your application tab, browsers will typically stop calling requestAnimationFrame callbacks, but setTimeout-based main loop will continue to be run, although with heavily throttled intervals. See setTimeout on MDN <https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers.setTimeout#Inactive_tabs> for more information.

void emscripten_get_main_loop_timing(int *mode, int *value)

Returns the current main loop timing mode that is in effect. For interpretation of the values, see the documentation of the function emscripten_set_main_loop_timing(). The timing mode is controlled by calling the functions emscripten_set_main_loop_timing() and emscripten_set_main_loop().

param mode:If not null, the used timing mode is returned here.
type mode:int*
param value:If not null, the used timing value is returned here.
type value:int*
void emscripten_set_main_loop_expected_blockers(int num)

Sets the number of blockers that are about to be pushed.

The number is used for reporting the relative progress through a set of blockers, after which the main loop will continue.

For example, a game might have to run 10 blockers before starting a new level. The operation would first set this value as ‘10’ and then push the 10 blockers. When the 3rd blocker (say) completes, progress is displayed as 3/10.

Parameters:
  • num (int) – The number of blockers that are about to be pushed.
void emscripten_async_call(em_arg_callback_func func, void *arg, int millis)

Call a C function asynchronously, that is, after returning control to the JavaScript event loop.

This is done by a setTimeout.

When building natively this becomes a simple direct call, after SDL_Delay (you must include SDL.h for that).

If millis is negative, the browser’s requestAnimationFrame mechanism is used. (Note that 0 means that setTimeout is still used, which basically means “run asynchronously as soon as possible”.)

Parameters:
  • func (em_arg_callback_func) – The C function to call asynchronously. The function signature must have a void* parameter for passing the arg value.
  • arg (void*) – User-defined argument to pass to the C function.
  • millis (int) – Timeout before function is called.
void emscripten_exit_with_live_runtime(void)

Exits the program immediately, but leaves the runtime alive so that you can continue to run code later (so global destructors etc., are not run). Note that the runtime is kept alive automatically when you do an asynchronous operation like emscripten_async_call(), so you don’t need to call this function for those cases.

void emscripten_force_exit(int status)

Shuts down the runtime and exits (terminates) the program, as if you called exit().

The difference is that emscripten_force_exit will shut down the runtime even if you previously called emscripten_exit_with_live_runtime() or otherwise kept the runtime alive. In other words, this method gives you the option to completely shut down the runtime after it was kept alive beyond the completion of main().

Note that if EXIT_RUNTIME is not set (which is the case by default) then the runtime cannot be shut down, as we do not include the code to do so. Build with -s EXIT_RUNTIME=1 if you want to be able to exit the runtime.

Parameters:
  • status (int) – The same as for the libc function exit().
double emscripten_get_device_pixel_ratio(void)

Returns the value of window.devicePixelRatio.

Return type:double
Returns:The pixel ratio or 1.0 if not supported.
void emscripten_hide_mouse(void)

Hide the OS mouse cursor over the canvas.

Note that SDL’s SDL_ShowCursor command shows and hides the SDL cursor, not the OS one. This command is useful to hide the OS cursor if your app draws its own cursor.

double emscripten_get_now(void)

Returns the highest-precision representation of the current time that the browser provides.

This uses either Date.now or performance.now. The result is not an absolute time, and is only meaningful in comparison to other calls to this function.

Return type:double
Returns:The current time, in milliseconds (ms).
float emscripten_random(void)

Generates a random number in the range 0-1. This maps to Math.random().

Return type:float
Returns:A random number.

Asynchronous File System API

Typedefs

em_async_wget_onload_func

Function pointer type for the onload callback of emscripten_async_wget_data() (specific values of the parameters documented in that method).

Defined as:

typedef void (*em_async_wget_onload_func)(void*, void*, int)
em_async_wget2_onload_func

Function pointer type for the onload callback of emscripten_async_wget2() (specific values of the parameters documented in that method).

Defined as:

typedef void (*em_async_wget2_onload_func)(void*, const char*)
em_async_wget2_onstatus_func

Function pointer type for the onerror and onprogress callbacks of emscripten_async_wget2() (specific values of the parameters documented in that method).

Defined as:

typedef void (*em_async_wget2_onstatus_func)(void*, int)
em_async_wget2_data_onload_func

Function pointer type for the onload callback of emscripten_async_wget2_data() (specific values of the parameters documented in that method).

Defined as:

typedef void (*em_async_wget2_data_onload_func)(unsigned, void*, void *, unsigned)
em_async_wget2_data_onerror_func

Function pointer type for the onerror callback of emscripten_async_wget2_data() (specific values of the parameters documented in that method).

Defined as:

typedef void (*em_async_wget2_data_onerror_func)(unsigned, void*, int, const char*)
em_async_wget2_data_onprogress_func

Function pointer type for the onprogress callback of emscripten_async_wget2_data() (specific values of the parameters documented in that method).

Defined as:

typedef void (*em_async_wget2_data_onprogress_func)(unsigned void*, int, int)
em_run_preload_plugins_data_onload_func

Function pointer type for the onload callback of emscripten_run_preload_plugins_data() (specific values of the parameters documented in that method).

Defined as:

typedef void (*em_run_preload_plugins_data_onload_func)(void*, const char*)

Functions

void emscripten_async_wget(const char* url, const char* file, em_str_callback_func onload, em_str_callback_func onerror)

Loads a file from a URL asynchronously.

In addition to fetching the URL from the network, preload plugins are executed so that the data is usable in IMG_Load and so forth (we asynchronously do the work to make the browser decode the image or audio etc.). See Preloading files for more information on preloading files.

When the file is ready the onload callback will be called. If any error occurs onerror will be called. The callbacks are called with the file as their argument.

Parameters:
  • char* url (const) – The URL to load.
  • char* file (const) – The name of the file created and loaded from the URL. If the file already exists it will be overwritten. If the destination directory for the file does not exist on the filesystem, it will be created. A relative pathname may be passed, which will be interpreted relative to the current working directory at the time of the call to this function.
  • onload (em_str_callback_func) –

    Callback on successful load of the file. The callback function parameter value is:

    • (const char)* : The name of the file that was loaded from the URL.
  • onerror (em_str_callback_func) –

    Callback in the event of failure. The callback function parameter value is:

    • (const char)* : The name of the file that failed to load from the URL.
void emscripten_async_wget_data(const char* url, void *arg, em_async_wget_onload_func onload, em_arg_callback_func onerror)

Loads a buffer from a URL asynchronously.

This is the “data” version of emscripten_async_wget().

Instead of writing to a file, this function writes to a buffer directly in memory. This avoids the overhead of using the emulated file system; note however that since files are not used, it cannot run preload plugins to set things up for IMG_Load and so forth (IMG_Load etc. work on files).

When the file is ready then the onload callback will be called. If any error occurred onerror will be called.

Parameters:
  • url (const char*) – The URL of the file to load.
  • arg (void*) – User-defined data that is passed to the callbacks, untouched by the API itself. This may be used by a callback to identify the associated call.
  • onload (em_async_wget_onload_func) –

    Callback on successful load of the URL into the buffer. The callback function parameter values are:

    • (void)* : Equal to arg (user defined data).
    • (void)* : A pointer to a buffer with the data. Note that, as with the worker API, the data buffer only lives during the callback; it must be used or copied during that time.
    • (int) : The size of the buffer, in bytes.
  • onerror (em_arg_callback_func) –

    Callback in the event of failure. The callback function parameter values are:

    • (void)* : Equal to arg (user defined data).
int emscripten_async_wget2(const char* url, const char* file, const char* requesttype, const char* param, void *arg, em_async_wget2_onload_func onload, em_async_wget2_onstatus_func onerror, em_async_wget2_onstatus_func onprogress)

Loads a file from a URL asynchronously.

This is an experimental “more feature-complete” version of emscripten_async_wget().

In addition to fetching the URL from the network, preload plugins are executed so that the data is usable in IMG_Load and so forth (we asynchronously do the work to make the browser decode the image, audio, etc.). See Preloading files for more information on preloading files.

When the file is ready the onload callback will be called with the object pointers given in arg and file. During the download the onprogress callback is called.

Parameters:
  • url (const char*) – The URL of the file to load.
  • file (const char*) – The name of the file created and loaded from the URL. If the file already exists it will be overwritten. If the destination directory for the file does not exist on the filesystem, it will be created. A relative pathname may be passed, which will be interpreted relative to the current working directory at the time of the call to this function.
  • requesttype (const char*) – ‘GET’ or ‘POST’.
  • param (const char*) – Request parameters for POST requests (see requesttype). The parameters are specified in the same way as they would be in the URL for an equivalent GET request: e.g. key=value&key2=value2.
  • arg (void*) – User-defined data that is passed to the callbacks, untouched by the API itself. This may be used by a callback to identify the associated call.
  • onload (em_async_wget2_onload_func) –

    Callback on successful load of the file. The callback function parameter values are:

    • (void)* : Equal to arg (user defined data).
    • (const char)* : The file passed to the original call.
  • onerror (em_async_wget2_onstatus_func) –

    Callback in the event of failure. The callback function parameter values are:

    • (void)* : Equal to arg (user defined data).
    • (int) : The HTTP status code.
  • onprogress (em_async_wget2_onstatus_func) –

    Callback during load of the file. The callback function parameter values are:

    • (void)* : Equal to arg (user defined data).
    • (int) : The progress (percentage completed).
Returns:

A handle to request (int) that can be used to abort the request.

int emscripten_async_wget2_data(const char* url, const char* requesttype, const char* param, void *arg, int free, em_async_wget2_data_onload_func onload, em_async_wget2_data_onerror_func onerror, em_async_wget2_data_onprogress_func onprogress)

Loads a buffer from a URL asynchronously.

This is the “data” version of emscripten_async_wget2(). It is an experimental “more feature complete” version of emscripten_async_wget_data().

Instead of writing to a file, this function writes to a buffer directly in memory. This avoids the overhead of using the emulated file system; note however that since files are not used, it cannot run preload plugins to set things up for IMG_Load and so forth (IMG_Load etc. work on files).

When the file is ready the onload callback will be called with the object pointers given in arg, a pointer to the buffer in memory, and an unsigned integer containing the size of the buffer. During the download the onprogress callback is called with progress information. If an error occurs, onerror will be called with the HTTP status code and a string containing the status description.

Parameters:
  • url (const char*) – The URL of the file to load.
  • requesttype (const char*) – ‘GET’ or ‘POST’.
  • param (const char*) – Request parameters for POST requests (see requesttype). The parameters are specified in the same way as they would be in the URL for an equivalent GET request: e.g. key=value&key2=value2.
  • arg (void*) – User-defined data that is passed to the callbacks, untouched by the API itself. This may be used by a callback to identify the associated call.
  • free (int) – Tells the runtime whether to free the returned buffer after onload is complete. If false freeing the buffer is the receiver’s responsibility.
  • onload (em_async_wget2_data_onload_func) –

    Callback on successful load of the file. The callback function parameter values are:

    • (unsigned) : Handle to the request
    • (void)* : Equal to arg (user defined data).
    • (void)* : A pointer to the buffer in memory.
    • (unsigned) : The size of the buffer (in bytes).
  • onerror (em_async_wget2_data_onerror_func) –

    Callback in the event of failure. The callback function parameter values are:

    • (unsigned) : Handle to the request
    • (void)* : Equal to arg (user defined data).
    • (int) : The HTTP error code.
    • (const char)* : A string with the status description.
  • onprogress (em_async_wget2_data_onprogress_func) –

    Callback called (regularly) during load of the file to update progress. The callback function parameter values are:

    • (unsigned) : Handle to the request
    • (void)* : Equal to arg (user defined data).
    • (int) : The number of bytes loaded.
    • (int) : The total size of the data in bytes, or zero if the size is unavailable.
Returns:

A handle to request (int) that can be used to abort the request.

void emscripten_async_wget2_abort(int handle)

Abort an asynchronous request raised using emscripten_async_wget2() or emscripten_async_wget2_data().

Parameters:
  • handle (int) – A handle to request to be aborted.
void emscripten_run_preload_plugins_data(char* data, int size, const char *suffix, void *arg, em_run_preload_plugins_data_onload_func onload, em_arg_callback_func onerror)

Runs preload plugins on a buffer of data asynchronously. This is a “data” version of emscripten_run_preload_plugins(), which receives raw data as input instead of a filename (this can prevent the need to write data to a file first). See Preloading files for more information on preload plugins.

When file is loaded then the onload callback will be called. If any error occurs onerror will be called.

onload also receives a second parameter, which is a ‘fake’ filename which you can pass into IMG_Load (it is not an actual file, but it identifies this image for IMG_Load to be able to process it). Note that the user of this API is responsible for free() ing the memory allocated for the fake filename.

Parameters:
  • data (char*) – The buffer of data to process.
  • suffix (const char*) – The file suffix, e.g. ‘png’ or ‘jpg’.
  • arg (void*) – User-defined data that is passed to the callbacks, untouched by the API itself. This may be used by a callback to identify the associated call.
  • onload (em_run_preload_plugins_data_onload_func) –

    Callback on successful processing of the data. The callback function parameter values are:

    • (void)* : Equal to arg (user defined data).
    • (const char)* : A ‘fake’ filename which you can pass into IMG_Load. See above for more information.
  • onerror (em_arg_callback_func) –

    Callback in the event of failure. The callback function parameter value is:

    • (void)* : Equal to arg (user defined data).

Asynchronous IndexedDB API

IndexedDB is a browser API that lets you store data persistently, that is, you can save data there and load it later when the user re-visits the web page. IDBFS provides one way to use IndexedDB, through the Emscripten filesystem layer. The emscripten_idb_* methods listed here provide an alternative API, directly to IndexedDB, thereby avoiding the overhead of the filesystem layer.
void emscripten_idb_async_load(const char *db_name, const char *file_id, void* arg, em_async_wget_onload_func onload, em_arg_callback_func onerror)

Loads data from local IndexedDB storage asynchronously. This allows use of persistent data, without the overhead of the filesystem layer.

When the data is ready then the onload callback will be called. If any error occurred onerror will be called.

Parameters:
  • db_name – The IndexedDB database from which to load.
  • file_id – The identifier of the data to load.
  • arg (void*) – User-defined data that is passed to the callbacks, untouched by the API itself. This may be used by a callback to identify the associated call.
  • onload (em_async_wget_onload_func) –

    Callback on successful load of the URL into the buffer. The callback function parameter values are:

    • (void)* : Equal to arg (user defined data).
    • (void)* : A pointer to a buffer with the data. Note that, as with the worker API, the data buffer only lives during the callback; it must be used or copied during that time.
    • (int) : The size of the buffer, in bytes.
  • onerror (em_arg_callback_func) –

    Callback in the event of failure. The callback function parameter values are:

    • (void)* : Equal to arg (user defined data).
void emscripten_idb_async_store(const char *db_name, const char *file_id, void* ptr, int num, void* arg, em_arg_callback_func onstore, em_arg_callback_func onerror);

Stores data to local IndexedDB storage asynchronously. This allows use of persistent data, without the overhead of the filesystem layer.

When the data has been stored then the onstore callback will be called. If any error occurred onerror will be called.

Parameters:
  • db_name – The IndexedDB database from which to load.
  • file_id – The identifier of the data to load.
  • ptr – A pointer to the data to store.
  • num – How many bytes to store.
  • arg (void*) – User-defined data that is passed to the callbacks, untouched by the API itself. This may be used by a callback to identify the associated call.
  • onstore (em_arg_callback_func) –

    Callback on successful store of the data buffer to the URL. The callback function parameter values are:

    • (void)* : Equal to arg (user defined data).
  • onerror (em_arg_callback_func) –

    Callback in the event of failure. The callback function parameter values are:

    • (void)* : Equal to arg (user defined data).
void emscripten_idb_async_delete(const char *db_name, const char *file_id, void* arg, em_arg_callback_func ondelete, em_arg_callback_func onerror)

Deletes data from local IndexedDB storage asynchronously.

When the data has been deleted then the ondelete callback will be called. If any error occurred onerror will be called.

Parameters:
  • db_name – The IndexedDB database.
  • file_id – The identifier of the data.
  • arg (void*) – User-defined data that is passed to the callbacks, untouched by the API itself. This may be used by a callback to identify the associated call.
  • ondelete (em_arg_callback_func) –

    Callback on successful delete

    • (void)* : Equal to arg (user defined data).
  • onerror (em_arg_callback_func) –

    Callback in the event of failure. The callback function parameter values are:

    • (void)* : Equal to arg (user defined data).
void emscripten_idb_async_exists(const char *db_name, const char *file_id, void* arg, em_idb_exists_func oncheck, em_arg_callback_func onerror)

Checks if data with a certain ID exists in the local IndexedDB storage asynchronously.

When the data has been checked then the oncheck callback will be called. If any error occurred onerror will be called.

Parameters:
  • db_name – The IndexedDB database.
  • file_id – The identifier of the data.
  • arg (void*) – User-defined data that is passed to the callbacks, untouched by the API itself. This may be used by a callback to identify the associated call.
  • oncheck (em_idb_exists_func) –

    Callback on successful check, with arguments

    • (void)* : Equal to arg (user defined data).
    • int : Whether the file exists or not.
  • onerror (em_arg_callback_func) –

    Callback in the event of failure. The callback function parameter values are:

    • (void)* : Equal to arg (user defined data).
int emscripten_run_preload_plugins(const char* file, em_str_callback_func onload, em_str_callback_func onerror)

Runs preload plugins on a file asynchronously. It works on file data already present and performs any required asynchronous operations available as preload plugins, such as decoding images for use in IMG_Load, or decoding audio for use in Mix_LoadWAV. See Preloading files for more information on preloading plugins.

Once the operations are complete, the onload callback will be called. If any error occurs onerror will be called. The callbacks are called with the file as their argument.

Parameters:
  • file (const char*) – The name of the file to process.
  • onload (em_str_callback_func) –

    Callback on successful processing of the file. The callback function parameter value is:

    • (const char)* : The name of the file that was processed.
  • onerror (em_str_callback_func) –

    Callback in the event of failure. The callback function parameter value is:

    • (const char)* : The name of the file for which the operation failed.
Returns:

0 if successful, -1 if the file does not exist

Return type:

int

Compiling

EMSCRIPTEN_KEEPALIVE

Forces LLVM to not dead-code-eliminate a function.

This also exports the function, as if you added it to EXPORTED_FUNCTIONS.

For example:

void EMSCRIPTEN_KEEPALIVE my_function() { printf("I am being kept alive\n"); }

Worker API

Typedefs

int worker_handle

A wrapper around web workers that lets you create workers and communicate with them.

Note that the current API is mainly focused on a main thread that sends jobs to workers and waits for responses, i.e., in an asymmetrical manner, there is no current API to send a message without being asked for it from a worker to the main thread.

em_worker_callback_func

Function pointer type for the callback from emscripten_call_worker() (specific values of the parameters documented in that method).

Defined as:

typedef void (*em_worker_callback_func)(char*, int, void*)

Functions

worker_handle emscripten_create_worker(const char * url)

Creates a worker.

A worker must be compiled separately from the main program, and with the BUILD_AS_WORKER flag set to 1.

Parameters:
  • url (const char*) – The URL of the worker script.
Returns:

A handle to the newly created worker.

Return type:

worker_handle

void emscripten_destroy_worker(worker_handle worker)

Destroys a worker. See emscripten_create_worker()

Parameters:
  • worker (worker_handle) – A handle to the worker to be destroyed.
void emscripten_call_worker(worker_handle worker, const char *funcname, char *data, int size, em_worker_callback_func callback, void *arg)

Asynchronously calls a worker.

The worker function will be called with two parameters: a data pointer, and a size. The data block defined by the pointer and size exists only during the callback: it cannot be relied upon afterwards. If you need to keep some of that information outside the callback, then it needs to be copied to a safe location.

The called worker function can return data, by calling emscripten_worker_respond(). When the worker is called, if a callback was given it will be called with three arguments: a data pointer, a size, and an argument that was provided when calling emscripten_call_worker() (to more easily associate callbacks to calls). The data block defined by the data pointer and size behave like the data block in the worker function — it exists only during the callback.

Parameters:
  • worker (worker_handle) – A handle to the worker to be called.
  • funcname (const char*) – The name of the function in the worker. The function must be a C function (so no C++ name mangling), and must be exported (EXPORTED_FUNCTIONS).
  • data (char*) – The address of a block of memory to copy over.
  • size (int) – The size of the block of memory.
  • callback (em_worker_callback_func) –

    Worker callback with the response. This can be null. The callback function parameter values are:

    • (char)* : The data pointer provided in emscripten_call_worker().
    • (int) : The size of the block of data.
    • (void)* : Equal to arg (user defined data).
  • arg (void*) – An argument (user data) to be passed to the callback
void emscripten_worker_respond(char *data, int size)
void emscripten_worker_respond_provisionally(char *data, int size)

Sends a response when in a worker call (that is, when called by the main thread using emscripten_call_worker()).

Both functions post a message back to the thread which called the worker. The emscripten_worker_respond_provisionally() variant can be invoked multiple times, which will queue up messages to be posted to the worker’s creator. Eventually, the _respond variant must be invoked, which will disallow further messages and free framework resources previously allocated for this worker call.

Note

Calling the provisional version is optional, but you must call the non-provisional version to avoid leaks.

Parameters:
  • data (char*) – The message to be posted.
  • size (int) – The size of the message, in bytes.
int emscripten_get_worker_queue_size(worker_handle worker)

Checks how many responses are being waited for from a worker.

This only counts calls to emscripten_call_worker() that had a callback (calls with null callbacks are ignored), and where the response has not yet been received. It is a simple way to check on the status of the worker to see how busy it is, and do basic decisions about throttling.

Parameters:
Returns:

The number of responses waited on from a worker.

Return type:

int

Logging utilities

Defines

EM_LOG_CONSOLE

If specified, logs directly to the browser console/inspector window. If not specified, logs via the application Module.

EM_LOG_WARN

If specified, prints a warning message.

EM_LOG_INFO

If specified, prints an info message to console (combined with EM_LOG_CONSOLE).

EM_LOG_DEBUG

If specified, prints a debug message to console (combined with EM_LOG_CONSOLE).

EM_LOG_ERROR

If specified, prints an error message. If neither EM_LOG_WARN, EM_LOG_ERROR, EM_LOG_INFO nor EM_LOG_DEBUG is specified, an info message is printed. EM_LOG_WARN, EM_LOG_INFO, EM_LOG_DEBUG and EM_LOG_ERROR are mutually exclusive.

EM_LOG_C_STACK

If specified, prints a call stack that contains file names referring to original C sources using source map information.

EM_LOG_JS_STACK

If specified, prints a call stack that contains file names referring to lines in the built .js/.html file along with the message. The flags EM_LOG_C_STACK and EM_LOG_JS_STACK can be combined to output both untranslated and translated file and line information.

EM_LOG_DEMANGLE

If specified, C/C++ function names are de-mangled before printing. Otherwise, the mangled post-compilation JavaScript function names are displayed.

EM_LOG_NO_PATHS

If specified, the pathnames of the file information in the call stack will be omitted.

EM_LOG_FUNC_PARAMS

If specified, prints out the actual values of the parameters the functions were invoked with.

Functions

int emscripten_get_compiler_setting(const char *name)

Returns the value of a compiler setting.

For example, to return the integer representing the value of PRECISE_F32 during compilation:

emscripten_get_compiler_setting("PRECISE_F32")

For values containing anything other than an integer, a string is returned (you will need to cast the int return value to a char*).

Some useful things this can do is provide the version of Emscripten (“EMSCRIPTEN_VERSION”), the optimization level (“OPT_LEVEL”), debug level (“DEBUG_LEVEL”), etc.

For this command to work, you must build with the following compiler option (as we do not want to increase the build size with this metadata):

-s RETAIN_COMPILER_SETTINGS=1
Parameters:
  • name (const char*) – The compiler setting to return.
Returns:

The value of the specified setting. Note that for values other than an integer, a string is returned (cast the int return value to a char*).

Return type:

int

int emscripten_has_asyncify()

Returns whether pseudo-synchronous functions can be used.

Return type:int
Returns:1 if program was compiled with ASYNCIFY=1, 0 otherwise.
void emscripten_debugger()

Emits debugger.

This is inline in the code, which tells the JavaScript engine to invoke the debugger if it gets there.

void emscripten_log(int flags, const char* format, ...)

Prints out a message to the console, optionally with the callstack information.

Parameters:
  • flags (int) – A binary OR of items from the list of EM_LOG_xxx flags that specify printing options.
  • char* format (const) – A printf-style format string.
  • ... – A printf-style “…” parameter list that is parsed according to the printf formatting rules.
int emscripten_get_callstack(int flags, char *out, int maxbytes)

Programmatically obtains the current callstack.

To query the amount of bytes needed for a callstack without writing it, pass 0 to out and maxbytes, in which case the function will return the number of bytes (including the terminating zero) that will be needed to hold the full callstack. Note that this might be fully accurate since subsequent calls will carry different line numbers, so it is best to allocate a few bytes extra to be safe.

Parameters:
  • flags (int) – A binary OR of items from the list of EM_LOG_xxx flags that specify printing options. The flags EM_LOG_CONSOLE, EM_LOG_WARN and EM_LOG_ERROR do not apply in this function and are ignored.
  • out (char*) – A pointer to a memory region where the callstack string will be written to. The string outputted by this function will always be null-terminated.
  • maxbytes (int) – The maximum number of bytes that this function can write to the memory pointed to by out. If there is not enough space, the output will be truncated (but always null-terminated).
Returns:

The number of bytes written (not number of characters, so this will also include the terminating zero).

Return type:

int

char *emscripten_get_preloaded_image_data(const char *path, int *w, int *h)

Gets preloaded image data and the size of the image.

The function returns pointer to loaded image or NULL — the pointer should be free()’d. The width/height of the image are written to the w and h parameters if the data is valid.

Parameters:
  • path – Full path/filename to the file containing the preloaded image.
  • w (int*) – Width of the image (if data is valid).
  • h (int*) – Height of the image (if data is valid).
Type:

const char*

Returns:

A pointer to the preloaded image or NULL.

Return type:

char*

char *emscripten_get_preloaded_image_data_from_FILE(FILE *file, int *w, int *h)

Gets preloaded image data from a C FILE*.

Parameters:
  • file (FILE*) – The FILE containing the preloaded image.
  • w (int*) – Width of the image (if data is valid).
  • h (int*) – Height of the image (if data is valid).
Type:

const char*

Returns:

A pointer to the preloaded image or NULL.

Return type:

char*

int emscripten_print_double(double x, char *to, signed max)

Prints a double as a string, including a null terminator. This is useful because JS engines have good support for printing out a double in a way that takes the least possible size, but preserves all the information in the double, i.e., it can then be parsed back in a perfectly reversible manner (snprintf etc. do not do so, sadly).

Parameters:
  • x (double) – The double.
  • to (char*) – A pre-allocated buffer of sufficient size, or NULL if no output is requested (useful to get the necessary size).
  • max (signed) – The maximum number of bytes that can be written to the output pointer ‘to’ (including the null terminator).
Return type:

The number of necessary bytes, not including the null terminator (actually written, if to is not NULL).

Socket event registration

The functions in this section register callback functions for receiving socket events. These events are analogous to WebSocket events but are emitted after the internal Emscripten socket processing has occurred. This means, for example, that the message callback will be triggered after the data has been added to the recv_queue, so that an application receiving this callback can simply read the data using the file descriptor passed as a parameter to the callback. All of the callbacks are passed a file descriptor (fd) representing the socket that the notified activity took place on. The error callback also takes an int representing the socket error number (errno) and a char* that represents the error message (msg).

Only a single callback function may be registered to handle any given event, so calling a given registration function more than once will cause the first callback to be replaced. Similarly, passing a NULL callback function to any emscripten_set_socket_*_callback call will de-register the callback registered for that event.

The userData pointer allows arbitrary data specified during event registration to be passed to the callback, this is particularly useful for passing this pointers around in Object Oriented code.

In addition to being able to register network callbacks from C it is also possible for native JavaScript code to directly use the underlying mechanism used to implement the callback registration. For example, the following code shows simple logging callbacks that are registered by default when SOCKET_DEBUG is enabled:

Module['websocket']['on']('error', function(error) {console.log('Socket error ' + error);});
Module['websocket']['on']('open', function(fd) {console.log('Socket open fd = ' + fd);});
Module['websocket']['on']('listen', function(fd) {console.log('Socket listen fd = ' + fd);});
Module['websocket']['on']('connection', function(fd) {console.log('Socket connection fd = ' + fd);});
Module['websocket']['on']('message', function(fd) {console.log('Socket message fd = ' + fd);});
Module['websocket']['on']('close', function(fd) {console.log('Socket close fd = ' + fd);});

Most of the JavaScript callback functions above get passed the file descriptor of the socket that triggered the callback, the on error callback however gets passed an array that contains the file descriptor, the error code and an error message.

Note

The underlying JavaScript implementation doesn’t pass userData. This is mostly of use to C/C++ code and the emscripten_set_socket_*_callback calls simply create a closure containing the userData and pass that as the callback to the underlying JavaScript event registration mechanism.

Callback functions

em_socket_callback

Function pointer for emscripten_set_socket_open_callback(), and the other socket functions (except emscripten_set_socket_error_callback()). This is defined as:

typedef void (*em_socket_callback)(int fd, void *userData);
Parameters:
  • fd (int) – The file descriptor of the socket that triggered the callback.
  • userData (void*) – The userData originally passed to the event registration function.
em_socket_error_callback

Function pointer for the emscripten_set_socket_error_callback(), defined as:

typedef void (*em_socket_error_callback)(int fd, int err, const char* msg, void *userData);
Parameters:
  • fd (int) – The file descriptor of the socket that triggered the callback.
  • err (int) – The code for the error that occurred.
  • msg (int) – The message for the error that occurred.
  • userData (void*) – The userData originally passed to the event registration function.

Functions

void emscripten_set_socket_error_callback(void *userData, em_socket_error_callback callback)

Triggered by a WebSocket error.

See Socket event registration for more information.

Parameters:
  • userData (void*) – Arbitrary user data to be passed to the callback.
  • callback (em_socket_error_callback) – Pointer to a callback function. The callback returns a file descriptor, error code and message, and the arbitrary userData passed to this function.
void emscripten_set_socket_open_callback(void *userData, em_socket_callback callback)

Triggered when the WebSocket has opened.

See Socket event registration for more information.

Parameters:
  • userData (void*) – Arbitrary user data to be passed to the callback.
  • callback (em_socket_callback) – Pointer to a callback function. The callback returns a file descriptor and the arbitrary userData passed to this function.
void emscripten_set_socket_listen_callback(void *userData, em_socket_callback callback)

Triggered when listen has been called (synthetic event).

See Socket event registration for more information.

Parameters:
  • userData (void*) – Arbitrary user data to be passed to the callback.
  • callback (em_socket_callback) – Pointer to a callback function. The callback returns a file descriptor and the arbitrary userData passed to this function.
void emscripten_set_socket_connection_callback(void *userData, em_socket_callback callback)

Triggered when the connection has been established.

See Socket event registration for more information.

Parameters:
  • userData (void*) – Arbitrary user data to be passed to the callback.
  • callback (em_socket_callback) – Pointer to a callback function. The callback returns a file descriptor and the arbitrary userData passed to this function.
void emscripten_set_socket_message_callback(void *userData, em_socket_callback callback)

Triggered when data is available to be read from the socket.

See Socket event registration for more information.

Parameters:
  • userData (void*) – Arbitrary user data to be passed to the callback.
  • callback (em_socket_callback) – Pointer to a callback function. The callback returns a file descriptor and the arbitrary userData passed to this function.
void emscripten_set_socket_close_callback(void *userData, em_socket_callback callback)

Triggered when the WebSocket has closed.

See Socket event registration for more information.

Parameters:
  • userData (void*) – Arbitrary user data to be passed to the callback.
  • callback (em_socket_callback) – Pointer to a callback function. The callback returns a file descriptor and the arbitrary userData passed to this function.

Unaligned types

Typedefs

emscripten_align1_short
emscripten_align2_int
emscripten_align1_int
emscripten_align2_float
emscripten_align1_float
emscripten_align4_double
emscripten_align2_double
emscripten_align1_double

Unaligned types. These may be used to force LLVM to emit unaligned loads/stores in places in your code where SAFE_HEAP found an unaligned operation.

For usage examples see tests/core/test_set_align.c.

Note

It is better to avoid unaligned operations, but if you are reading from a packed stream of bytes or such, these types may be useful!

Pseudo-synchronous functions

These functions require Asyncify (-s ASYNCIFY=1). These functions are asynchronous but appear synchronous in C. See Asyncify for more details.

Sleeping

void emscripten_sleep(unsigned int ms)

Sleep for ms milliseconds. This is a normal “synchronous” sleep, which blocks all other operations while it runs. In other words, if there are other async events waiting to happen, they will not happen during this sleep, which makes sense as conceptually this code is on the stack (that’s how it looks in the C source code).

Network

void emscripten_wget(const char* url, const char* file)

Load file from url in synchronously. For the asynchronous version, see the emscripten_async_wget().

In addition to fetching the URL from the network, preload plugins are executed so that the data is usable in IMG_Load and so forth (we synchronously do the work to make the browser decode the image or audio etc.). See Preloading files for more information on preloading files.

This function is blocking; it won’t return until all operations are finished. You can then open and read the file if it succeeded.

Parameters:
  • char* url (const) – The URL to load.
  • char* file (const) – The name of the file created and loaded from the URL. If the file already exists it will be overwritten. If the destination directory for the file does not exist on the filesystem, it will be created. A relative pathname may be passed, which will be interpreted relative to the current working directory at the time of the call to this function.
void emscripten_wget_data(const char* url, void** pbuffer, int* pnum, int *perror);

Synchronously fetches data off the network, and stores it to a buffer in memory, which is allocated for you. You must free the buffer, or it will leak!

Parameters:
  • url – The URL to fetch from
  • pbuffer – An out parameter that will be filled with a pointer to a buffer containing the data that is downloaded. This space has been malloced for you, and you must free it, or it will leak!
  • pnum – An out parameter that will be filled with the size of the downloaded data.
  • perror – An out parameter that will be filled with a non-zero value if an error occurred.

IndexedDB

void emscripten_idb_load(const char *db_name, const char *file_id, void** pbuffer, int* pnum, int *perror);

Synchronously fetches data from IndexedDB, and stores it to a buffer in memory, which is allocated for you. You must free the buffer, or it will leak!

Parameters:
  • db_name – The name of the database to load from
  • file_id – The name of the file to load
  • pbuffer – An out parameter that will be filled with a pointer to a buffer containing the data that is downloaded. This space has been malloced for you, and you must free it, or it will leak!
  • pnum – An out parameter that will be filled with the size of the downloaded data.
  • perror – An out parameter that will be filled with a non-zero value if an error occurred.
void emscripten_idb_store(const char *db_name, const char *file_id, void* buffer, int num, int *perror);

Synchronously stores data to IndexedDB.

Parameters:
  • db_name – The name of the database to store to
  • file_id – The name of the file to store
  • buffer – A pointer to the data to store
  • num – How many bytes to store
  • perror – An out parameter that will be filled with a non-zero value if an error occurred.
void emscripten_idb_delete(const char *db_name, const char *file_id, int *perror);

Synchronously deletes data from IndexedDB.

Parameters:
  • db_name – The name of the database to delete from
  • file_id – The name of the file to delete
  • perror – An out parameter that will be filled with a non-zero value if an error occurred.
void emscripten_idb_exists(const char *db_name, const char *file_id, int* pexists, int *perror);

Synchronously checks if a file exists in IndexedDB.

Parameters:
  • db_name – The name of the database to check in
  • file_id – The name of the file to check
  • pexists – An out parameter that will be filled with a non-zero value if the file exists in that database.
  • perror – An out parameter that will be filled with a non-zero value if an error occurred.

Fastcomp Asyncify functions

Fastcomp’s Asyncify support has asynchronous functions that appear synchronously in C, the linker flag -s ASYNCIFY=1 is required to use these functions. See Asyncify for more details.

Typedefs

emscripten_coroutine

A handle to the structure used by coroutine supporting functions.

Functions

void emscripten_sleep_with_yield(unsigned int ms)

Sleep for ms milliseconds, while allowing other asynchronous operations, e.g. caused by emscripten_async_call, to run normally, during this sleep. Note that this method does still block the main loop, as otherwise it could recurse, if you are calling this method from it. Even so, you should use this method carefully: the order of execution is potentially very confusing this way.

Note

This only works in fastcomp. In the wasm backend, just use sleep, which does not have strict yield checking.

emscripten_coroutine emscripten_coroutine_create(em_arg_callback_func func, void *arg, int stack_size)

Create a coroutine which will be run as func(arg).

Parameters:
  • stack_size (int) – the stack size that should be allocated for the coroutine, use 0 for the default value.
int emscripten_coroutine_next(emscripten_coroutine coroutine)

Run coroutine until it returns, or emscripten_yield is called. A non-zero value is returned if emscripten_yield is called, otherwise 0 is returned, and future calls of emscripten_coroutine_next on this coroutine is undefined behaviour.

void emscripten_yield(void)

This function should only be called in a coroutine created by emscripten_coroutine_create, when it called, the coroutine is paused and the caller will continue.

Upstream Asyncify functions

These functions only work with the upstream wasm backend when using Asyncify.

Typedefs

em_scan_func

Function pointer type for use in scan callbacks, receiving two pointers, for the beginning and end of a range of memory. You can then scan that range.

Defined as:

typedef void (*em_scan_func)(void*, void*)

Functions

void emscripten_scan_stack(em_scan_func func)

Scan the C userspace stack, which means the stack managed by the compiled code (as opposed to the wasm VM’s internal stack, which is not directly observable). This data is already in linear memory; this function just gives you a simple way to know where it is.

void emscripten_scan_registers(em_scan_func func)

Scan “registers”, by which we mean data that is not in memory. In wasm, that means data stored in locals, including locals in functions higher up the stack - the wasm VM has spilled them, but none of that is observable to user code).

This function requires Asyncify - it relies on that option to spill the local state all the way up the stack. As a result, it will add overhead to your program.

void emscripten_lazy_load_code()

This creates two wasm files at compile time: the first wasm which is downloaded and run normally, and a second that is lazy-loaded. When an emscripten_lazy_load_code() call is reached, we load the second wasm and resume execution using it.

The idea here is that the initial download can be quite small, if you place enough emscripten_lazy_load_code() calls in your codebase, as the optimizer can remove code from the first wasm if it sees it can’t be reached. The second downloaded wasm can contain your full codebase, including rarely-used functions, in which case the lazy-loading may not happen at all.

Note

This requires building with -s ASYNCIFY_LAZY_LOAD_CODE.

ABI functions

The following functions are not declared in emscripten.h, but are used internally in our system libraries. You may care about them if you replace the Emscripten runtime JS code, or run Emscripten binaries in your own runtime.

void emscripten_notify_memory_growth(i32 index)

Called when memory has grown. In a JS runtime, this is used to know when to update the JS views on the wasm memory, which otherwise we would need to constantly check for after any wasm code runs. See this wasi discussion.

Parameters:
  • index (i32) – Which memory has grown.

html5.h

The C++ APIs in html5.h define the Emscripten low-level glue bindings to interact with HTML5 events from native code.

Tip

The C++ APIs map closely to their equivalent HTML5 JavaScript APIs. The HTML5 specifications listed below provide additional detailed reference “over and above” the information provided in this document.

In addition, the Test/Example code can be reviewed to see how the code is used.

The HTML5 specifications for APIs that are mapped by html5.h include:

How to use this API

Most of these APIs use an event-based architecture; functionality is accessed by registering a callback function that will be called when the event occurs.

Note

The Gamepad API is currently an exception, as only a polling API is available. For some APIs, both an event-based and a polling-based model are exposed.

Registration functions

The typical format of registration functions is as follows (some methods may omit various parameters):

EMSCRIPTEN_RESULT emscripten_set_some_callback(
  const char *target,   // ID of the target HTML element.
  void *userData,   // User-defined data to be passed to the callback.
  EM_BOOL useCapture,   // Whether or not to use capture.
  em_someevent_callback_func callback   // Callback function.
);

The target parameter is the ID of the HTML element to which the callback registration is to be applied. This field has the following special meanings:

  • EMSCRIPTEN_EVENT_TARGET_WINDOW: The event listener is applied to the JavaScript window object.
  • EMSCRIPTEN_EVENT_TARGET_DOCUMENT: The event listener is applied to the JavaScript document object.
  • EMSCRIPTEN_EVENT_TARGET_SCREEN: The event listener is applied to the JavaScript window.screen object.
  • 0 or NULL: If building with the option -s DISABLE_DEPRECATED_FIND_EVENT_TARGET_BEHAVIOR=1 (default), NULL denotes an invalid element. If building with legacy option -s DISABLE_DEPRECATED_FIND_EVENT_TARGET_BEHAVIOR=0 (not recommended), a default element is chosen automatically based on the event type.
  • #canvas: If building with legacy option -s DISABLE_DEPRECATED_FIND_EVENT_TARGET_BEHAVIOR=0 (not recommended), the event listener is applied to the Emscripten default WebGL canvas element. If building with the option -s DISABLE_DEPRECATED_FIND_EVENT_TARGET_BEHAVIOR=1 (default), #canvas is interpreted as a CSS query selector: “the first element with CSS ID ‘canvas’”.
  • Any other string: A CSS selector lookup is performed to the DOM with the passed string, and the the event listener is applied to the first element that matches the query.

If the above are insufficient for you, you can add custom mappings in JavaScript using something like

specialHTMLTargets["!canvas"] = Module.canvas;

That will let !canvas map to the canvas held in Module.canvas. (You can write that JavaScript in an EM_JS or EM_ASM block that happens before you call the registration function, for example.)

The userData parameter is a user-defined value that is passed (unchanged) to the registered event callback. This can be used to, for example, pass a pointer to a C++ class or similarly to enclose the C API in a clean object-oriented manner.

The useCapture parameter maps to useCapture in EventTarget.addEventListener. It indicates whether or not to initiate capture: if true the callback will be invoked only for the DOM capture and target phases; if false the callback will be triggered during the target and bubbling phases. See DOM Level 3 Events for a more detailed explanation.

Most functions return the result using the type EMSCRIPTEN_RESULT. Zero and positive values denote success. Negative values signal failure. None of the functions fail or abort by throwing a JavaScript or C++ exception. If a particular browser does not support the given feature, the value EMSCRIPTEN_RESULT_NOT_SUPPORTED will be returned at the time the callback is registered.

Callback functions

When the event occurs the callback is invoked with the relevant event “type” (for example EMSCRIPTEN_EVENT_CLICK), a struct containing the details of the event that occurred, and the userData that was originally passed to the registration function. The general format of the callback function is:

typedef EM_BOOL (*em_someevent_callback_func) // Callback function. Return true if event is "consumed".
  (
  int eventType, // The type of event.
  const EmscriptenSomeEvent *someEvent, // Information about the event.
  void *userData // User data passed from the registration function.
  );

Callback handlers that return an EM_BOOL may specify true to signal that the handler consumed the event (this suppresses the default action for that event by calling its .preventDefault(); member). Returning false indicates that the event was not consumed — the default browser event action is carried out and the event is allowed to pass on/bubble up as normal.

Calling a registration function with a null pointer for the callback causes a de-registration of that callback from the given target element. All event handlers are also automatically unregistered when the C exit() function is invoked during the atexit handler pass. Either use the function emscripten_set_main_loop() or set Module.noExitRuntime = true; to make sure that leaving main() will not immediately cause an exit() and clean up the event handlers.

Functions affected by web security

Some functions, including emscripten_request_pointerlock() and emscripten_request_fullscreen(), are affected by web security.

While the functions can be called anywhere, the actual “requests” can only be raised inside the handler for a user-generated event (for example a key, mouse or touch press/release).

When porting code, it may be difficult to ensure that the functions are called inside appropriate event handlers (so that the requests are raised immediately). As a convenience, developers can set deferUntilInEventHandler=true to automatically defer insecure requests until the user next presses a keyboard or mouse button. This simplifies porting, but often results in a poorer user experience. For example, the user must click once on the canvas to hide the pointer or transition to full screen.

Where possible, the functions should only be called inside appropriate event handlers. Setting deferUntilInEventHandler=false causes the functions to abort with an error if the request is refused due to a security restriction: this is a useful mechanism for discovering instances where the functions are called outside the handler for a user-generated event.

Test/Example code

The HTML5 test code demonstrates how to use this API:

General types

EM_BOOL

This is the Emscripten type for a bool. Possible values:

EM_TRUE

This is the Emscripten value for true.

EM_FALSE

This is the Emscripten value for false.

EM_UTF8

This is the Emscripten type for a UTF8 string (maps to a char). This is used for node names, element ids, etc.

Function result values

Most functions in this API return a result of type EMSCRIPTEN_RESULT. None of the functions fail or abort by throwing a JavaScript or C++ exception. If a particular browser does not support the given feature, the value EMSCRIPTEN_RESULT_NOT_SUPPORTED will be returned at the time the callback is registered.

EMSCRIPTEN_RESULT

This type is used to return the result of most functions in this API. Zero and positive values denote success, while negative values signal failure. Possible values are listed below.

EMSCRIPTEN_RESULT_SUCCESS

The operation succeeded.

EMSCRIPTEN_RESULT_DEFERRED

The requested operation cannot be completed now for web security reasons, and has been deferred for completion in the next event handler.

EMSCRIPTEN_RESULT_NOT_SUPPORTED

The given operation is not supported by this browser or the target element. This value will be returned at the time the callback is registered if the operation is not supported.

EMSCRIPTEN_RESULT_FAILED_NOT_DEFERRED

The requested operation could not be completed now for web security reasons. It failed because the user requested the operation not be deferred.

EMSCRIPTEN_RESULT_INVALID_TARGET

The operation failed because the specified target element is invalid.

EMSCRIPTEN_RESULT_UNKNOWN_TARGET

The operation failed because the specified target element was not found.

EMSCRIPTEN_RESULT_INVALID_PARAM

The operation failed because an invalid parameter was passed to the function.

EMSCRIPTEN_RESULT_FAILED

Generic failure result message, returned if no specific result is available.

EMSCRIPTEN_RESULT_NO_DATA

The operation failed because no data is currently available.

Keys

Defines

EMSCRIPTEN_EVENT_KEYPRESS
EMSCRIPTEN_EVENT_KEYDOWN
EMSCRIPTEN_EVENT_KEYUP
Emscripten key events.
DOM_KEY_LOCATION

The location of the key on the keyboard; one of the values below.

DOM_KEY_LOCATION_STANDARD
DOM_KEY_LOCATION_LEFT
DOM_KEY_LOCATION_RIGHT
DOM_KEY_LOCATION_NUMPAD

Locations of the key on the keyboard.

Struct

EmscriptenKeyboardEvent

The event structure passed in keyboard events: keypress, keydown and keyup.

Note that since the DOM Level 3 Events spec is very recent at the time of writing (2014-03), uniform support for the different fields in the spec is still in flux. Be sure to check the results in multiple browsers. See the unmerged pull request #2222 for an example of how to interpret the legacy key events.

EM_UTF8 key

The printed representation of the pressed key.

Maximum size 32 char (i.e. EM_UTF8 key[32]).

EM_UTF8 code

A string that identifies the physical key being pressed. The value is not affected by the current keyboard layout or modifier state, so a particular key will always return the same value.

Maximum size 32 char (i.e. EM_UTF8 code[32]).

unsigned long location

Indicates the location of the key on the keyboard. One of the DOM_KEY_LOCATION values.

EM_BOOL ctrlKey
EM_BOOL shiftKey
EM_BOOL altKey
EM_BOOL metaKey

Specifies which modifiers were active during the key event.

EM_BOOL repeat

Specifies if this keyboard event represents a repeated press.

EM_UTF8 locale

A locale string indicating the configured keyboard locale. This may be an empty string if the browser or device doesn’t know the keyboard’s locale.

Maximum size 32 char (i.e. EM_UTF8 locale[32]).

EM_UTF8 charValue

The following fields are values from previous versions of the DOM key events specifications. See the character representation of the key. This is the field char from the docs, but renamed to charValue to avoid a C reserved word.

Maximum size 32 char (i.e. EM_UTF8 charValue[32]).

Warning

This attribute has been dropped from DOM Level 3 events.

unsigned long charCode

The Unicode reference number of the key; this attribute is used only by the keypress event. For keys whose char attribute contains multiple characters, this is the Unicode value of the first character in that attribute.

Warning

This attribute is deprecated, you should use the field key instead, if available.

unsigned long keyCode

A system and implementation dependent numerical code identifying the unmodified value of the pressed key.

Warning

This attribute is deprecated, you should use the field key instead, if available.

unsigned long which

A system and implementation dependent numeric code identifying the unmodified value of the pressed key; this is usually the same as keyCode.

Warning

This attribute is deprecated, you should use the field key instead, if available. Note thought that while this field is deprecated, the cross-browser support for which may be better than for the other fields, so experimentation is recommended. Read issue https://github.com/emscripten-core/emscripten/issues/2817 for more information.

Callback functions

em_key_callback_func

Function pointer for the keypress callback functions, defined as:

typedef EM_BOOL (*em_key_callback_func)(int eventType, const EmscriptenKeyboardEvent *keyEvent, void *userData);
Parameters:
  • eventType (int) – The type of key event.
  • keyEvent (const EmscriptenKeyboardEvent*) – Information about the key event that occurred.
  • userData (void*) – The userData originally passed to the registration function.
Returns:

true (non zero) to indicate that the event was consumed by the callback handler.

Return type:

EM_BOOL

Functions

EMSCRIPTEN_RESULT emscripten_set_keypress_callback(const char *target, void *userData, EM_BOOL useCapture, em_key_callback_func callback)
EMSCRIPTEN_RESULT emscripten_set_keydown_callback(const char *target, void *userData, EM_BOOL useCapture, em_key_callback_func callback)
EMSCRIPTEN_RESULT emscripten_set_keyup_callback(const char *target, void *userData, EM_BOOL useCapture, em_key_callback_func callback)

Registers a callback function for receiving browser-generated keyboard input events.

Parameters:
  • target (const char*) – Target HTML element id.
  • userData (void*) – User-defined data to be passed to the callback (opaque to the API).
  • useCapture (EM_BOOL) – Set true to use capture.
  • callback (em_key_callback_func) – A callback function. The function is called with the type of event, information about the event, and user data passed from this registration function. The callback should return true if the event is consumed.
Returns:

EMSCRIPTEN_RESULT_SUCCESS, or one of the other result values.

Return type:

EMSCRIPTEN_RESULT

See also:

Note

To receive events, the element must be focusable, see https://github.com/emscripten-core/emscripten/pull/7484#issuecomment-437887001

Mouse

Defines

EMSCRIPTEN_EVENT_CLICK
EMSCRIPTEN_EVENT_MOUSEDOWN
EMSCRIPTEN_EVENT_MOUSEUP
EMSCRIPTEN_EVENT_DBLCLICK
EMSCRIPTEN_EVENT_MOUSEMOVE
EMSCRIPTEN_EVENT_MOUSEENTER
EMSCRIPTEN_EVENT_MOUSELEAVE
Emscripten mouse events.

Struct

EmscriptenMouseEvent

The event structure passed in mouse events: click, mousedown, mouseup, dblclick, mousemove, mouseenter and mouseleave.

long screenX
long screenY

The coordinates relative to the browser screen coordinate system.

long clientX
long clientY

The coordinates relative to the viewport associated with the event.

EM_BOOL ctrlKey
EM_BOOL shiftKey
EM_BOOL altKey
EM_BOOL metaKey

Specifies which modifiers were active during the mouse event.

unsigned short button

Identifies which pointer device button changed state (see MouseEvent.button):

  • 0 : Left button
  • 1 : Middle button (if present)
  • 2 : Right button
unsigned short buttons

A bitmask that indicates which combinations of mouse buttons were being held down at the time of the event.

long movementX
long movementY;

If pointer lock is active, these two extra fields give relative mouse movement since the last event.

long targetX
long targetY

These fields give the mouse coordinates mapped relative to the coordinate space of the target DOM element receiving the input events (Emscripten-specific extension).

long canvasX
long canvasY

These fields give the mouse coordinates mapped to the Emscripten canvas client area (Emscripten-specific extension).

long padding

Internal, and can be ignored.

Note

Implementers only: pad this struct to multiple of 8 bytes to make WheelEvent unambiguously align to 8 bytes.

Callback functions

em_mouse_callback_func

Function pointer for the mouse event callback functions, defined as:

typedef EM_BOOL (*em_mouse_callback_func)(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData);
Parameters:
  • eventType (int) – The type of mouse event.
  • mouseEvent (const EmscriptenMouseEvent*) – Information about the mouse event that occurred.
  • userData (void*) – The userData originally passed to the registration function.
Returns:

true (non zero) to indicate that the event was consumed by the callback handler.

Return type:

EM_BOOL

Functions

EMSCRIPTEN_RESULT emscripten_set_click_callback(const char *target, void *userData, EM_BOOL useCapture, em_mouse_callback_func callback)
EMSCRIPTEN_RESULT emscripten_set_mousedown_callback(const char *target, void *userData, EM_BOOL useCapture, em_mouse_callback_func callback)
EMSCRIPTEN_RESULT emscripten_set_mouseup_callback(const char *target, void *userData, EM_BOOL useCapture, em_mouse_callback_func callback)
EMSCRIPTEN_RESULT emscripten_set_dblclick_callback(const char *target, void *userData, EM_BOOL useCapture, em_mouse_callback_func callback)
EMSCRIPTEN_RESULT emscripten_set_mousemove_callback(const char *target, void *userData, EM_BOOL useCapture, em_mouse_callback_func callback)
EMSCRIPTEN_RESULT emscripten_set_mouseenter_callback(const char *target, void *userData, EM_BOOL useCapture, em_mouse_callback_func callback)
EMSCRIPTEN_RESULT emscripten_set_mouseleave_callback(const char *target, void *userData, EM_BOOL useCapture, em_mouse_callback_func callback)

Registers a callback function for receiving browser-generated mouse input events.

Parameters:
  • target (const char*) – Target HTML element id.
  • userData (void*) – User-defined data to be passed to the callback (opaque to the API).
  • useCapture (EM_BOOL) – Set true to use capture.
  • callback (em_mouse_callback_func) – A callback function. The function is called with the type of event, information about the event, and user data passed from this registration function. The callback should return true if the event is consumed.
Returns:

EMSCRIPTEN_RESULT_SUCCESS, or one of the other result values.

Return type:

EMSCRIPTEN_RESULT

EMSCRIPTEN_RESULT emscripten_get_mouse_status(EmscriptenMouseEvent *mouseState)

Returns the most recently received mouse event state.

Note that for this function call to succeed, emscripten_set_xxx_callback must have first been called with one of the mouse event types and a non-zero callback function pointer to enable the Mouse state capture.

Parameters:
Returns:

EMSCRIPTEN_RESULT_SUCCESS, or one of the other result values.

Return type:

EMSCRIPTEN_RESULT

Wheel

Defines

EMSCRIPTEN_EVENT_WHEEL

Emscripten wheel event.

DOM_DELTA_PIXEL

The units of measurement for the delta must be pixels (from spec).

DOM_DELTA_LINE

The units of measurement for the delta must be individual lines of text (from spec).

DOM_DELTA_PAGE

The units of measurement for the delta must be pages, either defined as a single screen or as a demarcated page (from spec).

Struct

EmscriptenWheelEvent

The event structure passed in mousewheel events.

EmscriptenMouseEvent mouse

Specifies general mouse information related to this event.

double deltaX
double deltaY
double deltaZ

Movement of the wheel on each of the axis. Note that these values may be fractional, so you should avoid simply casting them to integer, or it might result in scroll values of 0. The positive Y scroll direction is when scrolling the page downwards (page CSS pixel +Y direction), which corresponds to scrolling the mouse wheel downwards (away from the screen) on Windows, Linux, and also on macOS when the ‘natural scroll’ option is disabled.

unsigned long deltaMode

One of the DOM_DELTA_ values that indicates the units of measurement for the delta values.

Callback functions

em_wheel_callback_func

Function pointer for the wheel event callback functions, defined as:

typedef EM_BOOL (*em_wheel_callback_func)(int eventType, const EmscriptenWheelEvent *wheelEvent, void *userData);
Parameters:
  • eventType (int) – The type of wheel event (EMSCRIPTEN_EVENT_WHEEL).
  • wheelEvent (const EmscriptenWheelEvent*) – Information about the wheel event that occurred.
  • userData (void*) – The userData originally passed to the registration function.
Returns:

true (non zero) to indicate that the event was consumed by the callback handler.

Return type:

EM_BOOL

Functions

EMSCRIPTEN_RESULT emscripten_set_wheel_callback(const char *target, void *userData, EM_BOOL useCapture, em_wheel_callback_func callback)

Registers a callback function for receiving browser-generated mousewheel events.

Parameters:
  • target (const char*) – Target HTML element id.
  • userData (void*) – User-defined data to be passed to the callback (opaque to the API).
  • useCapture (EM_BOOL) – Set true to use capture.
  • callback (em_wheel_callback_func) – A callback function. The function is called with the type of event, information about the event, and user data passed from this registration function. The callback should return true if the event is consumed.
Returns:

EMSCRIPTEN_RESULT_SUCCESS, or one of the other result values.

Return type:

EMSCRIPTEN_RESULT

UI

Defines

EMSCRIPTEN_EVENT_RESIZE
EMSCRIPTEN_EVENT_SCROLL
Emscripten UI events.

Struct

EmscriptenUiEvent

The event structure passed in DOM element UIEvent events: resize and scroll.

long detail

Specifies additional detail/information about this event.

int documentBodyClientWidth
int documentBodyClientHeight

The clientWidth/clientHeight of the document.body element.

int windowInnerWidth
int windowInnerHeight

The innerWidth/innerHeight of the browser window.

int windowOuterWidth
int windowOuterHeight;

The outerWidth/outerHeight of the browser window.

int scrollTop
int scrollLeft

The page scroll position.

Callback functions

em_ui_callback_func

Function pointer for the UI event callback functions, defined as:

typedef EM_BOOL (*em_ui_callback_func)(int eventType, const EmscriptenUiEvent *uiEvent, void *userData);
Parameters:
  • eventType (int) – The type of UI event (EMSCRIPTEN_EVENT_RESIZE).
  • uiEvent (const EmscriptenUiEvent*) – Information about the UI event that occurred.
  • userData (void*) – The userData originally passed to the registration function.
Returns:

true (non zero) to indicate that the event was consumed by the callback handler.

Return type:

EM_BOOL

Functions

EMSCRIPTEN_RESULT emscripten_set_resize_callback(const char *target, void *userData, EM_BOOL useCapture, em_ui_callback_func callback)
EMSCRIPTEN_RESULT emscripten_set_scroll_callback(const char *target, void *userData, EM_BOOL useCapture, em_ui_callback_func callback)

Registers a callback function for receiving DOM element resize and scroll events.

Note

  • For the resize callback, pass in target = 0 to get resize events from the Window object.
  • The DOM3 Events specification only requires that the Window object sends resize events. It is valid to register a resize callback on other DOM elements, but the browser is not required to fire resize events for these.
Parameters:
  • target (const char*) – Target HTML element id.
  • userData (void*) – User-defined data to be passed to the callback (opaque to the API).
  • useCapture (EM_BOOL) – Set true to use capture.
  • callback (em_ui_callback_func) – A callback function. The function is called with the type of event, information about the event, and user data passed from this registration function. The callback should return true if the event is consumed.
Returns:

EMSCRIPTEN_RESULT_SUCCESS, or one of the other result values.

Return type:

EMSCRIPTEN_RESULT

Focus

Defines

EMSCRIPTEN_EVENT_BLUR
EMSCRIPTEN_EVENT_FOCUS
EMSCRIPTEN_EVENT_FOCUSIN
EMSCRIPTEN_EVENT_FOCUSOUT
Emscripten focus events.

Struct

EmscriptenFocusEvent

The event structure passed in DOM element blur, focus, focusin and focusout events.

EM_UTF8 nodeName

The nodeName of the target HTML Element.

Maximum size 128 char (i.e. EM_UTF8 nodeName[128]).

EM_UTF8 id

The ID of the target element.

Maximum size 128 char (i.e. EM_UTF8 id[128]).

Callback functions

em_focus_callback_func

Function pointer for the focus event callback functions, defined as:

typedef EM_BOOL (*em_focus_callback_func)(int eventType, const EmscriptenFocusEvent *focusEvent, void *userData);
Parameters:
  • eventType (int) – The type of focus event (EMSCRIPTEN_EVENT_BLUR).
  • focusEvent (const EmscriptenFocusEvent*) – Information about the focus event that occurred.
  • userData (void*) – The userData originally passed to the registration function.
Returns:

true (non zero) to indicate that the event was consumed by the callback handler.

Return type:

EM_BOOL

Functions

EMSCRIPTEN_RESULT emscripten_set_blur_callback(const char *target, void *userData, EM_BOOL useCapture, em_focus_callback_func callback)
EMSCRIPTEN_RESULT emscripten_set_focus_callback(const char *target, void *userData, EM_BOOL useCapture, em_focus_callback_func callback)
EMSCRIPTEN_RESULT emscripten_set_focusin_callback(const char *target, void *userData, EM_BOOL useCapture, em_focus_callback_func callback)
EMSCRIPTEN_RESULT emscripten_set_focusout_callback(const char *target, void *userData, EM_BOOL useCapture, em_focus_callback_func callback)

Registers a callback function for receiving DOM element blur, focus, focusin and focusout events.

Parameters:
  • target (const char*) – Target HTML element id.
  • userData (void*) – User-defined data to be passed to the callback (opaque to the API).
  • useCapture (EM_BOOL) – Set true to use capture.
  • callback (em_focus_callback_func) – A callback function. The function is called with the type of event, information about the event, and user data passed from this registration function. The callback should return true if the event is consumed.
Returns:

EMSCRIPTEN_RESULT_SUCCESS, or one of the other result values.

Return type:

EMSCRIPTEN_RESULT

Device orientation

Defines

EMSCRIPTEN_EVENT_DEVICEORIENTATION

Emscripten deviceorientation events.

Struct

EmscriptenDeviceOrientationEvent

The event structure passed in the deviceorientation event.

double alpha
double beta
double gamma

The orientation of the device in terms of the transformation from a coordinate frame fixed on the Earth to a coordinate frame fixed in the device.

The image (source: dev.opera.com) and definitions below illustrate the co-ordinate frame:

  • alpha: the rotation of the device around the Z axis.
  • beta: the rotation of the device around the X axis.
  • gamma: the rotation of the device around the Y axis.
Image of device showing X, Y, Z axes
EM_BOOL absolute

If false, the orientation is only relative to some other base orientation, not to the fixed coordinate frame.

Callback functions

em_deviceorientation_callback_func

Function pointer for the orientation event callback functions, defined as:

typedef EM_BOOL (*em_deviceorientation_callback_func)(int eventType, const EmscriptenDeviceOrientationEvent *deviceOrientationEvent, void *userData);
Parameters:
  • eventType (int) – The type of orientation event (EMSCRIPTEN_EVENT_DEVICEORIENTATION).
  • deviceOrientationEvent (const EmscriptenDeviceOrientationEvent*) – Information about the orientation event that occurred.
  • userData (void*) – The userData originally passed to the registration function.
Returns:

true (non zero) to indicate that the event was consumed by the callback handler.

Return type:

EM_BOOL

Functions

EMSCRIPTEN_RESULT emscripten_set_deviceorientation_callback(void *userData, EM_BOOL useCapture, em_deviceorientation_callback_func callback)

Registers a callback function for receiving the deviceorientation event.

Parameters:
  • userData (void*) – User-defined data to be passed to the callback (opaque to the API).
  • useCapture (EM_BOOL) – Set true to use capture.
  • callback (em_deviceorientation_callback_func) – A callback function. The function is called with the type of event, information about the event, and user data passed from this registration function. The callback should return true if the event is consumed.
Returns:

EMSCRIPTEN_RESULT_SUCCESS, or one of the other result values.

Return type:

EMSCRIPTEN_RESULT

EMSCRIPTEN_RESULT emscripten_get_deviceorientation_status(EmscriptenDeviceOrientationEvent *orientationState)

Returns the most recently received deviceorientation event state.

Note that for this function call to succeed, emscripten_set_deviceorientation_callback() must have first been called with one of the mouse event types and a non-zero callback function pointer to enable the deviceorientation state capture.

Parameters:
Returns:

EMSCRIPTEN_RESULT_SUCCESS, or one of the other result values.

Return type:

EMSCRIPTEN_RESULT

Device motion

Defines

EMSCRIPTEN_EVENT_DEVICEMOTION

Emscripten devicemotion event.

Struct

EmscriptenDeviceMotionEvent

The event structure passed in the devicemotion event.

double accelerationX
double accelerationY
double accelerationZ

Acceleration of the device excluding gravity.

double accelerationIncludingGravityX
double accelerationIncludingGravityY
double accelerationIncludingGravityZ

Acceleration of the device including gravity.

double rotationRateAlpha
double rotationRateBeta
double rotationRateGamma

The rotational delta of the device.

int supportedFields

A bitfield that is a combination of EMSCRIPTEN_DEVICE_MOTION_EVENT_SUPPORTS_* fields that specifies the different fields of this structure that the current browser supports. If for example the EMSCRIPTEN_DEVICE_MOTION_EVENT_SUPPORTS_ACCELERATION bit is not present in this field, then the accelerationX/Y/Z fields of this structure should be assumed to not be valid.

Callback functions

em_devicemotion_callback_func

Function pointer for the devicemotion event callback functions, defined as:

typedef EM_BOOL (*em_devicemotion_callback_func)(int eventType, const EmscriptenDeviceMotionEvent *deviceMotionEvent, void *userData);
Parameters:
  • eventType (int) – The type of devicemotion event (EMSCRIPTEN_EVENT_DEVICEMOTION).
  • deviceMotionEvent (const EmscriptenDeviceMotionEvent*) – Information about the devicemotion event that occurred.
  • userData (void*) – The userData originally passed to the registration function.
Returns:

true (non zero) to indicate that the event was consumed by the callback handler.

Return type:

EM_BOOL

Functions

EMSCRIPTEN_RESULT emscripten_set_devicemotion_callback(void *userData, EM_BOOL useCapture, em_devicemotion_callback_func callback)

Registers a callback function for receiving the devicemotion event.

Parameters:
  • userData (void*) – User-defined data to be passed to the callback (opaque to the API).
  • useCapture (EM_BOOL) – Set true to use capture.
  • callback (em_devicemotion_callback_func) – A callback function. The function is called with the type of event, information about the event, and user data passed from this registration function. The callback should return true if the event is consumed.
Returns:

EMSCRIPTEN_RESULT_SUCCESS, or one of the other result values.

Return type:

EMSCRIPTEN_RESULT

EMSCRIPTEN_RESULT emscripten_get_devicemotion_status(EmscriptenDeviceMotionEvent *motionState)

Returns the most recently received devicemotion event state.

Note that for this function call to succeed, emscripten_set_devicemotion_callback() must have first been called with one of the mouse event types and a non-zero callback function pointer to enable the devicemotion state capture.

Parameters:
Returns:

EMSCRIPTEN_RESULT_SUCCESS, or one of the other result values.

Return type:

EMSCRIPTEN_RESULT

Orientation

Defines

EMSCRIPTEN_EVENT_ORIENTATIONCHANGE

Emscripten orientationchange event.

EMSCRIPTEN_ORIENTATION_PORTRAIT_PRIMARY

Primary portrait mode orientation.

EMSCRIPTEN_ORIENTATION_PORTRAIT_SECONDARY

Secondary portrait mode orientation.

EMSCRIPTEN_ORIENTATION_LANDSCAPE_PRIMARY

Primary landscape mode orientation.

EMSCRIPTEN_ORIENTATION_LANDSCAPE_SECONDARY

Secondary landscape mode orientation.

Struct

EmscriptenOrientationChangeEvent

The event structure passed in the orientationchange event.

int orientationIndex

One of the EM_ORIENTATION_PORTRAIT_xxx fields, or -1 if unknown.

int orientationAngle

Emscripten-specific extension: Some browsers refer to window.orientation, so report that as well.

Orientation angle in degrees. 0: “default orientation”, i.e. default upright orientation to hold the mobile device in. Could be either landscape or portrait.

Callback functions

em_orientationchange_callback_func

Function pointer for the orientationchange event callback functions, defined as:

typedef EM_BOOL (*em_orientationchange_callback_func)(int eventType, const EmscriptenOrientationChangeEvent *orientationChangeEvent, void *userData);
Parameters:
  • eventType (int) – The type of orientationchange event (EMSCRIPTEN_EVENT_ORIENTATIONCHANGE).
  • orientationChangeEvent (const EmscriptenOrientationChangeEvent*) – Information about the orientationchange event that occurred.
  • userData (void*) – The userData originally passed to the registration function.
Returns:

true (non zero) to indicate that the event was consumed by the callback handler.

Return type:

EM_BOOL

Functions

EMSCRIPTEN_RESULT emscripten_set_orientationchange_callback(void *userData, EM_BOOL useCapture, em_orientationchange_callback_func callback)

Registers a callback function for receiving the orientationchange event.

Parameters:
  • userData (void*) – User-defined data to be passed to the callback (opaque to the API).
  • useCapture (EM_BOOL) – Set true to use capture.
  • callback (em_orientationchange_callback_func) – A callback function. The function is called with the type of event, information about the event, and user data passed from this registration function. The callback should return true if the event is consumed.
Returns:

EMSCRIPTEN_RESULT_SUCCESS, or one of the other result values.

Return type:

EMSCRIPTEN_RESULT

EMSCRIPTEN_RESULT emscripten_get_orientation_status(EmscriptenOrientationChangeEvent *orientationStatus)

Returns the current device orientation state.

Parameters:
Returns:

EMSCRIPTEN_RESULT_SUCCESS, or one of the other result values.

Return type:

EMSCRIPTEN_RESULT

EMSCRIPTEN_RESULT emscripten_lock_orientation(int allowedOrientations)

Locks the screen orientation to the given set of allowed orientations.

Parameters:
Returns:

EMSCRIPTEN_RESULT_SUCCESS, or one of the other result values.

Return type:

EMSCRIPTEN_RESULT

EMSCRIPTEN_RESULT emscripten_unlock_orientation(void)

Removes the orientation lock so the screen can turn to any orientation.

Returns:EMSCRIPTEN_RESULT_SUCCESS, or one of the other result values.
Return type:EMSCRIPTEN_RESULT

Fullscreen

Defines

EMSCRIPTEN_EVENT_FULLSCREENCHANGE

Emscripten fullscreenchange event.

EMSCRIPTEN_FULLSCREEN_SCALE

An enum-like type which specifies how the Emscripten runtime should treat the CSS size of the target element when displaying it in fullscreen mode via calls to functions emscripten_request_fullscreen_strategy() and emscripten_enter_soft_fullscreen().

EMSCRIPTEN_FULLSCREEN_SCALE_DEFAULT

Specifies that the DOM element should not be resized by Emscripten runtime when transitioning between fullscreen and windowed modes. The browser will be responsible for scaling the DOM element to the fullscreen size. The proper browser behavior in this mode is to stretch the element to fit the full display ignoring aspect ratio, but at the time of writing, browsers implement different behavior here. See the discussion at https://github.com/emscripten-core/emscripten/issues/2556 for more information.

EMSCRIPTEN_FULLSCREEN_SCALE_STRETCH

Specifies that the Emscripten runtime should explicitly stretch the CSS size of the target element to cover the whole screen when transitioning to fullscreen mode. This will change the aspect ratio of the displayed content.

EMSCRIPTEN_FULLSCREEN_SCALE_ASPECT

Specifies that the Emscripten runtime should explicitly scale the CSS size of the target element to cover the whole screen, while adding either vertical or horizontal black letterbox padding to preserve the aspect ratio of the content. The aspect ratio that is used here is the render target size of the canvas element. To change the desired aspect ratio, call emscripten_set_canvas_element_size() before entering fullscreen mode.

EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE

An enum-like type which specifies how the Emscripten runtime should treat the pixel size (render target resolution) of the target canvas element when displaying it in fullscreen mode via calls to functions emscripten_request_fullscreen_strategy() and emscripten_enter_soft_fullscreen(). To better understand the underlying distinction between the CSS size of a canvas element versus the render target size of a canvas element, see https://www.khronos.org/webgl/wiki/HandlingHighDPI.

EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE_NONE

Specifies that the Emscripten runtime should not do any changes to the render target resolution of the target canvas element that is displayed in fullscreen mode. Use this mode when your application is set up to render to a single fixed resolution that cannot be changed under any condition.

EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE_STDDEF

Specifies that the Emscripten runtime should resize the render target of the canvas element to match 1:1 with the CSS size of the element in fullscreen mode. On high DPI displays (window.devicePixelRatio > 1), the CSS size is not the same as the physical screen resolution of the device. Call emscripten_get_device_pixel_ratio() to obtain the pixel ratio between CSS pixels and actual device pixels of the screen. Use this mode when you want to render to a pixel resolution that is DPI-independent.

EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE_HIDEF

Specifies that the Emscripten runtime should resize the canvas render target size to match 1:1 with the physical screen resolution on the device. This corresponds to high definition displays on retina iOS and other mobile and desktop devices with high DPI. Use this mode to match and render 1:1 to the native display resolution.

EMSCRIPTEN_FULLSCREEN_FILTERING

An enum-like type that specifies what kind of image filtering algorithm to apply to the element when it is presented in fullscreen mode.

EMSCRIPTEN_FULLSCREEN_FILTERING_DEFAULT

Specifies that the image filtering mode should not be changed from the existing setting in the CSS style.

EMSCRIPTEN_FULLSCREEN_FILTERING_NEAREST

Applies a CSS style to the element that displays the content using a nearest-neighbor image filtering algorithm in fullscreen mode.

EMSCRIPTEN_FULLSCREEN_FILTERING_BILINEAR

Applies a CSS style to the element that displays the content using a bilinear image filtering algorithm in fullscreen mode. This is the default browser behavior.

Struct

EmscriptenFullscreenChangeEvent

The event structure passed in the fullscreenchange event.

EM_BOOL isFullscreen

Specifies whether an element on the browser page is currently fullscreen.

EM_BOOL fullscreenEnabled

Specifies if the current page has the ability to display elements fullscreen.

EM_UTF8 nodeName

The nodeName of the target HTML Element that is in full screen mode.

Maximum size 128 char (i.e. EM_UTF8 nodeName[128]).

If isFullscreen is false, then nodeName, id and elementWidth and elementHeight specify information about the element that just exited fullscreen mode.

EM_UTF8 id

The ID of the target HTML element that is in full screen mode.

Maximum size 128 char (i.e. EM_UTF8 id[128]).

int elementWidth
int elementHeight

The new pixel size of the element that changed fullscreen status.

int screenWidth
int screenHeight

The size of the whole screen, in pixels.

EmscriptenFullscreenStrategy

The options structure that is passed in to functions emscripten_request_fullscreen_strategy() and emscripten_enter_soft_fullscreen() to configure how the target element should be displayed in fullscreen mode.

EMSCRIPTEN_FULLSCREEN_SCALE scaleMode

Specifies the rule how the CSS size (the displayed size) of the target element is resized when displayed in fullscreen mode.

EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE canvasResolutionScaleMode

Specifies how the render target size (the pixel resolution) of the target element is adjusted when displayed in fullscreen mode.

EMSCRIPTEN_FULLSCREEN_FILTERING filteringMode

Specifies the image filtering algorithm to apply to the element in fullscreen mode.

em_canvasresized_callback_func canvasResizedCallback

If nonzero, points to a user-provided callback function which will be called whenever either the CSS or the canvas render target size changes. Use this callback to reliably obtain information about canvas resize events.

void *canvasResizedCallbackUserData

Stores a custom data field which will be passed to all calls to the user-provided callback function.

Callback functions

em_fullscreenchange_callback_func

Function pointer for the fullscreen event callback functions, defined as:

typedef EM_BOOL (*em_fullscreenchange_callback_func)(int eventType, const EmscriptenFullscreenChangeEvent *fullscreenChangeEvent, void *userData);
Parameters:
  • eventType (int) – The type of fullscreen event (EMSCRIPTEN_EVENT_FULLSCREENCHANGE).
  • fullscreenChangeEvent (const EmscriptenFullscreenChangeEvent*) – Information about the fullscreen event that occurred.
  • userData (void*) – The userData originally passed to the registration function.
Returns:

true (non zero) to indicate that the event was consumed by the callback handler.

Return type:

EM_BOOL

Functions

EMSCRIPTEN_RESULT emscripten_set_fullscreenchange_callback(const char *target, void *userData, EM_BOOL useCapture, em_fullscreenchange_callback_func callback)

Registers a callback function for receiving the fullscreenchange event.

Parameters:
Returns:

EMSCRIPTEN_RESULT_SUCCESS, or one of the other result values.

Return type:

EMSCRIPTEN_RESULT

EMSCRIPTEN_RESULT emscripten_get_fullscreen_status(EmscriptenFullscreenChangeEvent *fullscreenStatus)

Returns the current page fullscreen state.

Parameters:
Returns:

EMSCRIPTEN_RESULT_SUCCESS, or one of the other result values.

Return type:

EMSCRIPTEN_RESULT

EMSCRIPTEN_RESULT emscripten_request_fullscreen(const char *target, EM_BOOL deferUntilInEventHandler)

Requests the given target element to transition to full screen mode.

Note

This function can be called anywhere, but for web security reasons its associated request can only be raised inside the event handler for a user-generated event (for example a key, mouse or touch press/release). This has implications for porting and the value of deferUntilInEventHandler — see Functions affected by web security for more information.

Note

This function only performs a fullscreen request without changing any parameters of the DOM element that is to be displayed in fullscreen mode. At the time of writing, there are differences in how browsers present elements in fullscreen mode. For more information, read the discussion at https://github.com/emscripten-core/emscripten/issues/2556. To display an element in fullscreen mode in a way that is consistent across browsers, prefer calling the function emscripten_request_fullscreen_strategy() instead. This function is best called only in scenarios where the preconfigured presets defined by emscripten_request_fullscreen_strategy() conflict with the developer’s use case in some way.

Parameters:
  • target (const char*) – Target HTML element id.
  • deferUntilInEventHandler (EM_BOOL) – If true requests made outside of a user-generated event handler are automatically deferred until the user next presses a keyboard or mouse button. If false the request will fail if called outside of a user-generated event handler.
Returns:

EMSCRIPTEN_RESULT_SUCCESS, or one of the other result values.

Return type:

EMSCRIPTEN_RESULT

EMSCRIPTEN_RESULT emscripten_request_fullscreen_strategy(const char *target, EM_BOOL deferUntilInEventHandler, const EmscriptenFullscreenStrategy *fullscreenStrategy)

Requests the given target element to transition to full screen mode, using a custom presentation mode for the element. This function is otherwise the same as emscripten_request_fullscreen(), but this function adds options to control how resizing and aspect ratio, and ensures that the behavior is consistent across browsers.

Note

This function makes changes to the DOM to satisfy consistent presentation across browsers. These changes have been designed to intrude as little as possible, and the changes are cleared once windowed browsing is restored. If any of these changes are conflicting, see the function emscripten_request_fullscreen() instead, which performs a bare fullscreen request without any modifications to the DOM.

Parameters:
  • fullscreenStrategy (const EmscriptenFullscreenStrategy*) – [in] Points to a configuration structure filled by the caller which specifies display options for the fullscreen mode.
EMSCRIPTEN_RESULT emscripten_exit_fullscreen(void)

Returns back to windowed browsing mode from a proper fullscreen mode.

Do not call this function to attempt to return to windowed browsing mode from a soft fullscreen mode, or vice versa.

Returns:EMSCRIPTEN_RESULT_SUCCESS, or one of the other result values.
Return type:EMSCRIPTEN_RESULT
EMSCRIPTEN_RESULT emscripten_enter_soft_fullscreen(const char *target, const EmscriptenFullscreenStrategy *fullscreenStrategy)

Enters a “soft” fullscreen mode, where the given target element is displayed in the whole client area of the page and all other elements are hidden, but does not actually request fullscreen mode for the browser. This function is useful in cases where the actual Fullscreen API is not desirable or needed, for example in packaged apps for Firefox OS, where applications essentially already cover the whole screen.

Pressing the esc button does not automatically exit the soft fullscreen mode. To return to windowed presentation mode, manually call the function emscripten_exit_soft_fullscreen().

EMSCRIPTEN_RESULT emscripten_exit_soft_fullscreen()

Returns back to windowed browsing mode from a soft fullscreen mode. Do not call this function to attempt to return to windowed browsing mode from a real fullscreen mode, or vice versa.

Pointerlock

Defines

EMSCRIPTEN_EVENT_POINTERLOCKCHANGE

Emscripten pointerlockchange event.

EMSCRIPTEN_EVENT_POINTERLOCKERROR

Emscripten pointerlockerror event.

Struct

EmscriptenPointerlockChangeEvent

The event structure passed in the pointerlockchange event.

EM_BOOL isActive

Specifies whether an element on the browser page currently has pointer lock enabled.

EM_UTF8 nodeName

The nodeName of the target HTML Element that has the pointer lock active.

Maximum size 128 char (i.e. EM_UTF8 nodeName[128]).

EM_UTF8 id

The ID of the target HTML element that has the pointer lock active.

Maximum size 128 char (i.e. EM_UTF8 id[128]).

Callback functions

em_pointerlockchange_callback_func

Function pointer for the pointerlockchange event callback functions, defined as:

typedef EM_BOOL (*em_pointerlockchange_callback_func)(int eventType, const EmscriptenPointerlockChangeEvent *pointerlockChangeEvent, void *userData);
Parameters:
  • eventType (int) – The type of pointerlockchange event (EMSCRIPTEN_EVENT_POINTERLOCKCHANGE).
  • pointerlockChangeEvent (const EmscriptenPointerlockChangeEvent*) – Information about the pointerlockchange event that occurred.
  • userData (void*) – The userData originally passed to the registration function.
Returns:

true (non zero) to indicate that the event was consumed by the callback handler.

Return type:

EM_BOOL

em_pointerlockerror_callback_func

Function pointer for the pointerlockerror event callback functions, defined as:

typedef EM_BOOL (*em_pointerlockerror_callback_func)(int eventType, const void *reserved, void *userData);
Parameters:
  • eventType (int) – The type of pointerlockerror event (EMSCRIPTEN_EVENT_POINTERLOCKERROR).
  • void* reserved (const) – Reserved for future use; pass in 0.
  • userData (void*) – The userData originally passed to the registration function.
Returns:

true (non zero) to indicate that the event was consumed by the callback handler.

Return type:

EM_BOOL

Functions

EMSCRIPTEN_RESULT emscripten_set_pointerlockchange_callback(const char *target, void *userData, EM_BOOL useCapture, em_pointerlockchange_callback_func callback)

Registers a callback function for receiving the pointerlockchange event.

Pointer lock hides the mouse cursor and exclusively gives the target element relative mouse movement events via the mousemove event.

Parameters:
Returns:

EMSCRIPTEN_RESULT_SUCCESS, or one of the other result values.

Return type:

EMSCRIPTEN_RESULT

EMSCRIPTEN_RESULT emscripten_set_pointerlockerror_callback(const char *target, void *userData, EM_BOOL useCapture, em_pointerlockerror_callback_func callback)

Registers a callback function for receiving the pointerlockerror event.

Parameters:
Returns:

EMSCRIPTEN_RESULT_SUCCESS, or one of the other result values.

Return type:

EMSCRIPTEN_RESULT

EMSCRIPTEN_RESULT emscripten_get_pointerlock_status(EmscriptenPointerlockChangeEvent *pointerlockStatus)

Returns the current page pointerlock state.

Parameters:
Returns:

EMSCRIPTEN_RESULT_SUCCESS, or one of the other result values.

Return type:

EMSCRIPTEN_RESULT

EMSCRIPTEN_RESULT emscripten_request_pointerlock(const char *target, EM_BOOL deferUntilInEventHandler)

Requests the given target element to grab pointerlock.

Note

This function can be called anywhere, but for web security reasons its associated request can only be raised inside the event handler for a user-generated event (for example a key, mouse or touch press/release). This has implications for porting and the value of deferUntilInEventHandler — see Functions affected by web security for more information.

Parameters:
  • target (const char*) – Target HTML element id.
  • deferUntilInEventHandler (EM_BOOL) – If true requests made outside of a user-generated event handler are automatically deferred until the user next presses a keyboard or mouse button. If false the request will fail if called outside of a user-generated event handler.
Returns:

EMSCRIPTEN_RESULT_SUCCESS, or one of the other result values.

Return type:

EMSCRIPTEN_RESULT

EMSCRIPTEN_RESULT emscripten_exit_pointerlock(void)

Exits pointer lock state and restores the mouse cursor to be visible again.

Returns:EMSCRIPTEN_RESULT_SUCCESS, or one of the other result values.
Return type:EMSCRIPTEN_RESULT

Visibility

Defines

EMSCRIPTEN_EVENT_VISIBILITYCHANGE

Emscripten visibilitychange event.

EMSCRIPTEN_VISIBILITY_HIDDEN

The document is hidden (not visible).

EMSCRIPTEN_VISIBILITY_VISIBLE

The document is at least partially visible.

EMSCRIPTEN_VISIBILITY_PRERENDER

The document is loaded off screen and not visible (prerender).

EMSCRIPTEN_VISIBILITY_UNLOADED

The document is to be unloaded.

Struct

EmscriptenVisibilityChangeEvent

The event structure passed in the visibilitychange event.

EM_BOOL hidden

If true, the current browser page is now hidden.

int visibilityState

Specifies a more fine-grained state of the current page visibility status. One of the EMSCRIPTEN_VISIBILITY_ values.

Callback functions

em_visibilitychange_callback_func

Function pointer for the visibilitychange event callback functions, defined as:

typedef EM_BOOL (*em_visibilitychange_callback_func)(int eventType, const EmscriptenVisibilityChangeEvent *visibilityChangeEvent, void *userData);
Parameters:
  • eventType (int) – The type of visibilitychange event (EMSCRIPTEN_VISIBILITY_HIDDEN).
  • visibilityChangeEvent (const EmscriptenVisibilityChangeEvent*) – Information about the visibilitychange event that occurred.
  • userData (void*) – The userData originally passed to the registration function.
Returns:

true (non zero) to indicate that the event was consumed by the callback handler.

Return type:

EM_BOOL

Functions

EMSCRIPTEN_RESULT emscripten_set_visibilitychange_callback(void *userData, EM_BOOL useCapture, em_visibilitychange_callback_func callback)

Registers a callback function for receiving the visibilitychange event.

Parameters:
  • userData (void*) – User-defined data to be passed to the callback (opaque to the API).
  • useCapture (EM_BOOL) – Set true to use capture.
  • callback (em_visibilitychange_callback_func) – A callback function. The function is called with the type of event, information about the event, and user data passed from this registration function. The callback should return true if the event is consumed.
Returns:

EMSCRIPTEN_RESULT_SUCCESS, or one of the other result values.

Return type:

EMSCRIPTEN_RESULT

EMSCRIPTEN_RESULT emscripten_get_visibility_status(EmscriptenVisibilityChangeEvent *visibilityStatus)

Returns the current page visibility state.

Parameters:
Returns:

EMSCRIPTEN_RESULT_SUCCESS, or one of the other result values.

Return type:

EMSCRIPTEN_RESULT

Touch

Defines

EMSCRIPTEN_EVENT_TOUCHSTART
EMSCRIPTEN_EVENT_TOUCHEND
EMSCRIPTEN_EVENT_TOUCHMOVE
EMSCRIPTEN_EVENT_TOUCHCANCEL
Emscripten touch events.

Struct

EmscriptenTouchPoint

Specifies the status of a single touch point on the page.

long identifier

An identification number for each touch point.

long screenX
long screenY

The touch coordinate relative to the whole screen origin, in pixels.

long clientX
long clientY

The touch coordinate relative to the viewport, in pixels.

long pageX
long pageY

The touch coordinate relative to the viewport, in pixels, and including any scroll offset.

EM_BOOL isChanged

Specifies whether the touch point changed during this event.

EM_BOOL onTarget

Specifies whether this touch point is still above the original target on which it was initially pressed.

long targetX
long targetY

These fields give the touch coordinates mapped relative to the coordinate space of the target DOM element receiving the input events (Emscripten-specific extension).

long canvasX
long canvasY

The touch coordinates mapped to the Emscripten canvas client area, in pixels (Emscripten-specific extension).

EmscriptenTouchEvent

Specifies the data of a single touchevent.

int numTouches

The number of valid elements in the touches array.

EM_BOOL ctrlKey
EM_BOOL shiftKey
EM_BOOL altKey
EM_BOOL metaKey

Specifies which modifiers were active during the touch event.

EmscriptenTouchPoint touches[32]

An array of currently active touches, one for each finger.

Callback functions

em_touch_callback_func

Function pointer for the touch event callback functions, defined as:

typedef EM_BOOL (*em_touch_callback_func)(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData);
Parameters:
  • eventType (int) – The type of touch event (EMSCRIPTEN_EVENT_TOUCHSTART).
  • touchEvent (const EmscriptenTouchEvent*) – Information about the touch event that occurred.
  • userData (void*) – The userData originally passed to the registration function.
Returns:

true (non zero) to indicate that the event was consumed by the callback handler.

Return type:

EM_BOOL

Functions

EMSCRIPTEN_RESULT emscripten_set_touchstart_callback(const char *target, void *userData, EM_BOOL useCapture, em_touch_callback_func callback)
EMSCRIPTEN_RESULT emscripten_set_touchend_callback(const char *target, void *userData, EM_BOOL useCapture, em_touch_callback_func callback)
EMSCRIPTEN_RESULT emscripten_set_touchmove_callback(const char *target, void *userData, EM_BOOL useCapture, em_touch_callback_func callback)
EMSCRIPTEN_RESULT emscripten_set_touchcancel_callback(const char *target, void *userData, EM_BOOL useCapture, em_touch_callback_func callback)

Registers a callback function for receiving touch events : touchstart, touchend, touchmove and touchcancel.

Parameters:
  • target (const char*) – Target HTML element id.
  • userData (void*) – User-defined data to be passed to the callback (opaque to the API).
  • useCapture (EM_BOOL) – Set true to use capture.
  • callback (em_touch_callback_func) – A callback function. The function is called with the type of event, information about the event, and user data passed from this registration function. The callback should return true if the event is consumed.
Returns:

EMSCRIPTEN_RESULT_SUCCESS, or one of the other result values.

Return type:

EMSCRIPTEN_RESULT

Gamepad

Defines

EMSCRIPTEN_EVENT_GAMEPADCONNECTED
EMSCRIPTEN_EVENT_GAMEPADDISCONNECTED
Emscripten gamepad events.

Struct

EmscriptenGamepadEvent

Represents the current snapshot state of a gamepad.

double timestamp

Absolute wallclock time when the data was recorded (milliseconds).

int numAxes

The number of valid axis entries in the axis array.

int numButtons

The number of valid button entries in the analogButton and digitalButton arrays.

double axis[64]

The analog state of the gamepad axes, in the range [-1, 1].

double analogButton[64]

The analog state of the gamepad buttons, in the range [0, 1].

EM_BOOL digitalButton[64]

The digital state of the gamepad buttons, either 0 or 1.

EM_BOOL connected

Specifies whether this gamepad is connected to the browser page.

long index

An ordinal associated with this gamepad, zero-based.

EM_UTF8 id

An ID for the brand or style of the connected gamepad device. Typically, this will include the USB vendor and a product ID.

Maximum size 64 char (i.e. EM_UTF8 id[128]).

EM_UTF8 mapping

A string that identifies the layout or control mapping of this device.

Maximum size 128 char (i.e. EM_UTF8 mapping[128]).

Callback functions

em_gamepad_callback_func

Function pointer for the gamepad event callback functions, defined as:

typedef EM_BOOL (*em_gamepad_callback_func)(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData)
Parameters:
  • eventType (int) – The type of gamepad event (EMSCRIPTEN_EVENT_GAMEPADCONNECTED).
  • gamepadEvent (const EmscriptenGamepadEvent*) – Information about the gamepad event that occurred.
  • userData (void*) – The userData originally passed to the registration function.
Returns:

true (non zero) to indicate that the event was consumed by the callback handler.

Return type:

EM_BOOL

Functions

EMSCRIPTEN_RESULT emscripten_set_gamepadconnected_callback(void *userData, EM_BOOL useCapture, em_gamepad_callback_func callback)
EMSCRIPTEN_RESULT emscripten_set_gamepaddisconnected_callback(void *userData, EM_BOOL useCapture, em_gamepad_callback_func callback)

Registers a callback function for receiving the gamepad events: gamepadconnected and gamepaddisconnected.

Parameters:
  • userData (void*) – User-defined data to be passed to the callback (opaque to the API).
  • useCapture (EM_BOOL) – Set true to use capture.
  • callback (em_gamepad_callback_func) – A callback function. The function is called with the type of event, information about the event, and user data passed from this registration function. The callback should return true if the event is consumed.
Returns:

EMSCRIPTEN_RESULT_SUCCESS, or one of the other result values.

Return type:

EMSCRIPTEN_RESULT

EMSCRIPTEN_RESULT emscripten_sample_gamepad_data(void)

This function samples a new state of connected Gamepad data, and returns either EMSCRIPTEN_RESULT_SUCCESS if Gamepad API is supported by the current browser, or EMSCRIPTEN_RESULT_NOT_SUPPORTED if Gamepad API is not supported. Note that even if EMSCRIPTEN_RESULT_SUCCESS is returned, there may not be any gamepads connected yet to the current browser tab.

Call this function before calling either of the functions emscripten_get_num_gamepads() or emscripten_get_gamepad_status().

int emscripten_get_num_gamepads(void)

After having called emscripten_sample_gamepad_data(), this function returns the number of gamepads connected to the system or EMSCRIPTEN_RESULT_NOT_SUPPORTED if the current browser does not support gamepads.

Note

A gamepad does not show up as connected until a button on it is pressed.

Note

Gamepad API uses an array of gamepad state objects to return the state of each device. The devices are identified via the index they are present in in this array. Because of that, if one first connects gamepad A, then gamepad B, and then disconnects gamepad A, the gamepad B shall not take the place of gamepad A, so in this scenario, this function will still keep returning two for the count of connected gamepads, even though gamepad A is no longer present. To find the actual number of connected gamepads, listen for the gamepadconnected and gamepaddisconnected events. Consider the return value of function emscripten_get_num_gamepads() minus one to be the largest index value that can be passed to the function emscripten_get_gamepad_status().

Returns:The number of gamepads connected to the browser tab.
Return type:int
EMSCRIPTEN_RESULT emscripten_get_gamepad_status(int index, EmscriptenGamepadEvent *gamepadState)

After having called emscripten_sample_gamepad_data(), this function returns a snapshot of the current gamepad state for the gamepad controller located at given index of the controllers array.

Parameters:
Returns:

EMSCRIPTEN_RESULT_SUCCESS, or one of the other result values.

Return type:

EMSCRIPTEN_RESULT

Battery

Defines

EMSCRIPTEN_EVENT_BATTERYCHARGINGCHANGE
EMSCRIPTEN_EVENT_BATTERYLEVELCHANGE
Emscripten batterymanager events.

Struct

EmscriptenBatteryEvent

The event structure passed in the batterymanager events: chargingchange and levelchange.

double chargingTime

Time remaining until the battery is fully charged (seconds).

double dischargingTime

Time remaining until the battery is empty and the system will be suspended (seconds).

double level

Current battery level, on a scale of 0 to 1.0.

EM_BOOL charging;

true if the battery is charging, false otherwise.

Callback functions

em_battery_callback_func

Function pointer for the batterymanager event callback functions, defined as:

typedef EM_BOOL (*em_battery_callback_func)(int eventType, const EmscriptenBatteryEvent *batteryEvent, void *userData);
Parameters:
  • eventType (int) – The type of batterymanager event (EMSCRIPTEN_EVENT_BATTERYCHARGINGCHANGE).
  • batteryEvent (const EmscriptenBatteryEvent*) – Information about the batterymanager event that occurred.
  • userData (void*) – The userData originally passed to the registration function.
Returns:

true (non zero) to indicate that the event was consumed by the callback handler.

Return type:

EM_BOOL

Functions

EMSCRIPTEN_RESULT emscripten_set_batterychargingchange_callback(void *userData, em_battery_callback_func callback)
EMSCRIPTEN_RESULT emscripten_set_batterylevelchange_callback(void *userData, em_battery_callback_func callback)

Registers a callback function for receiving the batterymanager events: chargingchange and levelchange.

Parameters:
  • userData (void*) – User-defined data to be passed to the callback (opaque to the API).
  • callback (em_battery_callback_func) – A callback function. The function is called with the type of event, information about the event, and user data passed from this registration function. The callback should return true if the event is consumed.
Returns:

EMSCRIPTEN_RESULT_SUCCESS, or one of the other result values.

Return type:

EMSCRIPTEN_RESULT

EMSCRIPTEN_RESULT emscripten_get_battery_status(EmscriptenBatteryEvent *batteryState)

Returns the current battery status.

Parameters:
Returns:

EMSCRIPTEN_RESULT_SUCCESS, or one of the other result values.

Return type:

EMSCRIPTEN_RESULT

Vibration

Functions

EMSCRIPTEN_RESULT emscripten_vibrate(int msecs)

Produces a vibration for the specified time, in milliseconds.

Parameters:
  • msecs (int) – The amount of time for which the vibration is required (milliseconds).
Returns:

EMSCRIPTEN_RESULT_SUCCESS, or one of the other result values.

Return type:

EMSCRIPTEN_RESULT

EMSCRIPTEN_RESULT emscripten_vibrate_pattern(int *msecsArray, int numEntries)

Produces a complex vibration feedback pattern.

Parameters:
  • msecsArray (int*) – An array of timing entries [on, off, on, off, on, off, …] where every second one specifies a duration of vibration, and every other one specifies a duration of silence.
  • numEntries (int) – The number of integers in the array msecsArray.
Returns:

EMSCRIPTEN_RESULT_SUCCESS, or one of the other result values.

Return type:

EMSCRIPTEN_RESULT

Page unload

Defines

EMSCRIPTEN_EVENT_BEFOREUNLOAD

Emscripten beforeunload event.

Callback functions

em_beforeunload_callback

Function pointer for the beforeunload event callback functions, defined as:

typedef const char *(*em_beforeunload_callback)(int eventType, const void *reserved, void *userData);
Parameters:
  • eventType (int) – The type of beforeunload event (EMSCRIPTEN_EVENT_BEFOREUNLOAD).
  • reserved (const void*) – Reserved for future use; pass in 0.
  • userData (void*) – The userData originally passed to the registration function.
Returns:

Return a string to be displayed to the user.

Return type:

char*

Functions

EMSCRIPTEN_RESULT emscripten_set_beforeunload_callback(void *userData, em_beforeunload_callback callback)

Registers a callback function for receiving the page beforeunload event.

Hook into this event to perform actions immediately prior to page close (for example, to display a notification to ask if the user really wants to leave the page).

Parameters:
  • userData (void*) – User-defined data to be passed to the callback (opaque to the API).
  • callback (em_beforeunload_callback) – A callback function. The function is called with the type of event, information about the event, and user data passed from this registration function. The callback should return true if the event is consumed.
Returns:

EMSCRIPTEN_RESULT_SUCCESS, or one of the other result values.

Return type:

EMSCRIPTEN_RESULT

WebGL context

Defines

EMSCRIPTEN_EVENT_WEBGLCONTEXTLOST
EMSCRIPTEN_EVENT_WEBGLCONTEXTRESTORED
Emscripten WebGL context events.
EMSCRIPTEN_WEBGL_CONTEXT_HANDLE

Represents a handle to an Emscripten WebGL context object. The value 0 denotes an invalid/no context (this is a typedef to an int).

Struct

EmscriptenWebGLContextAttributes

Specifies WebGL context creation parameters.

EM_BOOL alpha

If true, request an alpha channel for the context. If you create an alpha channel, you can blend the canvas rendering with the underlying web page contents. Default value: true.

EM_BOOL depth

If true, request a depth buffer of at least 16 bits. If false, no depth buffer will be initialized. Default value: true.

EM_BOOL stencil

If true, request a stencil buffer of at least 8 bits. If false, no stencil buffer will be initialized. Default value: false.

EM_BOOL antialias

If true, antialiasing will be initialized with a browser-specified algorithm and quality level. If false, antialiasing is disabled. Default value: true.

EM_BOOL premultipliedAlpha

If true, the alpha channel of the rendering context will be treated as representing premultiplied alpha values. If false, the alpha channel represents non-premultiplied alpha. Default value: true.

EM_BOOL preserveDrawingBuffer

If true, the contents of the drawing buffer are preserved between consecutive requestAnimationFrame() calls. If false, color, depth and stencil are cleared at the beginning of each requestAnimationFrame(). Generally setting this to false gives better performance. Default value: false.

EM_WEBGL_POWER_PREFERENCE powerPreference

Specifies a hint to the WebGL canvas implementation to how it should choose the use of available GPU resources. One of EM_WEBGL_POWER_PREFERENCE_DEFAULT, EM_WEBGL_POWER_PREFERENCE_LOW_POWER, EM_WEBGL_POWER_PREFERENCE_HIGH_PERFORMANCE.

EM_BOOL failIfMajorPerformanceCaveat

If true, requests context creation to abort if the browser is only able to create a context that does not give good hardware-accelerated performance. Default value: false.

int majorVersion
int minorVersion

Emscripten-specific extensions which specify the WebGL context version to initialize.

For example, pass in majorVersion=1, minorVersion=0 to request a WebGL 1.0 context, and majorVersion=2, minorVersion=0 to request a WebGL 2.0 context.

Default value: majorVersion=1, minorVersion=0

EM_BOOL enableExtensionsByDefault

If true, all GLES2-compatible non-performance-impacting WebGL extensions will automatically be enabled for you after the context has been created. If false, no extensions are enabled by default, and you need to manually call emscripten_webgl_enable_extension() to enable each extension that you want to use. Default value: true.

EM_BOOL explicitSwapControl

By default, when explicitSwapControl is in its default state false, rendered WebGL content is implicitly presented (displayed to the user) on the canvas when the event handler that renders with WebGL returns back to the browser event loop. If explicitSwapControl is set to true, rendered content will not be displayed on screen automatically when event handler function finishes, but the control of swapping is given to the user to manage, via the emscripten_webgl_commit_frame() function.

In order to be able to set explicitSwapControl==true, support for it must explicitly be enabled either 1) via adding the -s OFFSCREEN_FRAMEBUFFER=1 Emscripten linker flag, and enabling renderViaOffscreenBackBuffer==1, or 2) via adding the linker flag -s OFFSCREENCANVAS_SUPPORT=1, and running in a browser that supports OffscreenCanvas.

EM_BOOL renderViaOffscreenBackBuffer

If true, an extra intermediate backbuffer (offscreen render target) is allocated to the created WebGL context, and rendering occurs to this backbuffer instead of directly onto the WebGL “default backbuffer”. This is required to be enabled if 1) explicitSwapControl==true and the browser does not support OffscreenCanvas, 2) when performing WebGL rendering in a worker thread and the browser does not support OffscreenCanvas, and 3) when performing WebGL context accesses from multiple threads simultaneously (independent of whether OffscreenCanvas is supported or not).

Because supporting offscreen framebuffer adds some amount of extra code to the compiled output, support for it must explicitly be enabled via the -s OFFSCREEN_FRAMEBUFFER=1 Emscripten linker flag. When building simultaneously with both -s OFFSCREEN_FRAMEBUFFER=1 and -s OFFSCREENCANVAS_SUPPORT=1 linker flags enabled, offscreen backbuffer can be used as a polyfill-like compatibility fallback to enable rendering WebGL from a pthread when the browser does not support the OffscreenCanvas API.

EM_BOOL proxyContextToMainThread

This member specifies the threading model that will be used for the created WebGL context, when the WebGL context is created in a pthread. Three values are possible: EMSCRIPTEN_WEBGL_CONTEXT_PROXY_DISALLOW, EMSCRIPTEN_WEBGL_CONTEXT_PROXY_FALLBACK or EMSCRIPTEN_WEBGL_CONTEXT_PROXY_ALWAYS. If EMSCRIPTEN_WEBGL_CONTEXT_PROXY_DISALLOW is specified, the WebGLRenderingContext object will be created inside the pthread that is calling the emscripten_webgl_create_context() function as an OffscreenCanvas-based rendering context. This is only possible if 1) current browser supports OffscreenCanvas specification, 2) code was compiled with -s OFFSCREENCANVAS_SUPPORT=1 linker flag enabled, 3) the Canvas object that the context is being created on was transferred over to the calling pthread with function emscripten_pthread_attr_settransferredcanvases() when the pthread was originally created, and 4) no OffscreenCanvas-based context already exists from the given Canvas at the same time.

If a WebGL rendering context is created as an OffscreenCanvas-based context, it will have the limitation that only the pthread that created the context can enable access to it (via emscripten_webgl_make_context_current() function). Other threads will not be able to activate rendering to the context, i.e. OffscreenCanvas-based contexts are essentially “pinned” to the pthread that created them.

If the current browser does not support OffscreenCanvas, you can specify the EMSCRIPTEN_WEBGL_CONTEXT_PROXY_ALWAYS WebGL context creation flag. If this flag is passed, and code was compiled with -s OFFSCREEN_FRAMEBUFFER=1 enabled, the WebGL context will be created as a “proxied context”. In this context mode, the WebGLRenderingContext object will actually be created on the main browser thread, and all WebGL API calls will be proxied as asynchronous messages from the pthread into the main thread. This will have a performance and latency impact in comparison to OffscreenCanvas contexts, however unlike OffscreenCanvas-based contexts, proxied contexts can be shared across any number of pthreads: you can use the emscripten_webgl_make_context_current() function in any pthread to activate and deactivate access to the WebGL context: for example, you could have one WebGL loading thread, and another WebGL rendering thread that coordinate shared access to the WebGL rendering context by cooperatively acquiring and releasing access to the WebGL rendering context via the emscripten_webgl_make_context_current() function. Proxied contexts do not require any special support from the browser, so any WebGL capable browser can create a proxied WebGL context.

The EMSCRIPTEN_WEBGL_CONTEXT_PROXY_ALWAYS WebGL context creation flag will always create a proxied context, even if the browser did support OffscreenCanvas. If you would like to prefer to create a higher performance OffscreenCanvas context whenever suppported by the browser, but only fall back to a proxied WebGL context to keep compatibility with browsers that do not yet have OffscreenCanvas support, you can specify the EMSCRIPTEN_WEBGL_CONTEXT_PROXY_FALLBACK context creation flag. In order to use this flag, code should be compiled with both -s OFFSCREEN_FRAMEBUFFER=1 and -s OFFSCREENCANVAS_SUPPORT=1 linker flags.

Default value of proxyContextToMainThread after calling emscripten_webgl_init_context_attributes() is EMSCRIPTEN_WEBGL_CONTEXT_PROXY_DISALLOW, if the WebGL context is being created on the main thread. This means that by default WebGL contexts created on the main thread are not shareable between multiple threads (to avoid accidental performance loss from enabling proxying when/if it is not needed). To create a context that can be shared between multiple pthreads, set the proxyContextToMainThread flag EMSCRIPTEN_WEBGL_CONTEXT_PROXY_ALWAYS.

Callback functions

em_webgl_context_callback

Function pointer for the WebGL Context event callback functions, defined as:

typedef EM_BOOL (*em_webgl_context_callback)(int eventType, const void *reserved, void *userData);
Parameters:
  • eventType (int) – The type of WebGL context event.
  • reserved (const void*) – Reserved for future use; pass in 0.
  • userData (void*) – The userData originally passed to the registration function.
Returns:

true (non zero) to indicate that the event was consumed by the callback handler.

Return type:

EM_BOOL

Functions

EMSCRIPTEN_RESULT emscripten_set_webglcontextlost_callback(const char *target, void *userData, EM_BOOL useCapture, em_webgl_context_callback callback)
EMSCRIPTEN_RESULT emscripten_set_webglcontextrestored_callback(const char *target, void *userData, EM_BOOL useCapture, em_webgl_context_callback callback)

Registers a callback function for the canvas WebGL context events: webglcontextlost and webglcontextrestored.

Parameters:
  • target (const char*) – Target HTML element id.
  • userData (void*) – User-defined data to be passed to the callback (opaque to the API).
  • useCapture (EM_BOOL) – Set true to use capture.
  • callback (em_webgl_context_callback) – A callback function. The function is called with the type of event, information about the event, and user data passed from this registration function. The callback should return true if the event is consumed.
Returns:

EMSCRIPTEN_RESULT_SUCCESS, or one of the other result values.

Return type:

EMSCRIPTEN_RESULT

EM_BOOL emscripten_is_webgl_context_lost(EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context)

Queries the given WebGL context if it is in a lost context state.

Parameters:
Returns:

true if the WebGL context is in a lost state (or the context does not exist)

Return type:

EM_BOOL

void emscripten_webgl_init_context_attributes(EmscriptenWebGLContextAttributes *attributes)

Populates all fields of the given EmscriptenWebGLContextAttributes structure to their default values for use with WebGL 1.0.

Call this function as a forward-compatible way to ensure that if there are new fields added to the EmscriptenWebGLContextAttributes structure in the future, that they also will get default-initialized without having to change any code.

Parameters:
EMSCRIPTEN_WEBGL_CONTEXT_HANDLE emscripten_webgl_create_context(const char *target, const EmscriptenWebGLContextAttributes *attributes)

Creates and returns a new WebGL context.

Note

  • A successful call to this function will not immediately make that rendering context active. Call emscripten_webgl_make_context_current() after creating a context to activate it.
  • This function will try to initialize the context version that was exactly requested. It will not e.g. initialize a newer backwards-compatible version or similar.
Parameters:
  • target (const char*) – The DOM canvas element in which to initialize the WebGL context.
  • attributes (const EmscriptenWebGLContextAttributes*) – The attributes of the requested context version.
Returns:

On success, a strictly positive value that represents a handle to the created context. On failure, a negative number that can be cast to an EMSCRIPTEN_RESULT field to get the reason why the context creation failed.

Return type:

EMSCRIPTEN_WEBGL_CONTEXT_HANDLE

EMSCRIPTEN_RESULT emscripten_webgl_make_context_current(EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context)

Activates the given WebGL context for rendering. After calling this function, all OpenGL functions (glBindBuffer(), glDrawArrays(), etc.) can be applied to the given GL context.

Parameters:
Returns:

EMSCRIPTEN_RESULT_SUCCESS, or one of the other result values.

Return type:

EMSCRIPTEN_RESULT

EMSCRIPTEN_WEBGL_CONTEXT_HANDLE emscripten_webgl_get_current_context()

Returns the currently active WebGL rendering context, or 0 if no context is active. Calling any WebGL functions when there is no active rendering context is undefined and may throw a JavaScript exception.

Returns:The currently active WebGL rendering context, or 0 if no context is active.
Return type:EMSCRIPTEN_WEBGL_CONTEXT_HANDLE
EMSCRIPTEN_RESULT emscripten_webgl_get_context_attributes(EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context, EmscriptenWebGLContextAttributes *outAttributes)

Fetches the context creation attributes that were used to initialize the given WebGL context.

Parameters:
Returns:

On success, EMSCRIPTEN_RESULT_SUCCESS.

EMSCRIPTEN_RESULT emscripten_webgl_commit_frame()

Presents (“swaps”) the content rendered on the currently active WebGL context to be visible on the canvas. This function is available on WebGL contexts that were created with the explicitSwapControl==true context creation attribute. If explicitSwapControl==false, then the rendered content is displayed on the screen “implicitly” when yielding back to the browser from the calling event handler.

Returns:EMSCRIPTEN_RESULT_SUCCESS, or one of the other result values, denoting a reason for failure.
Return type:EMSCRIPTEN_RESULT
EMSCRIPTEN_RESULT emscripten_webgl_get_drawing_buffer_size(EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context, int *width, int *height)

Gets the drawingBufferWidth and drawingBufferHeight of the specified WebGL context.

Parameters:
  • context (EMSCRIPTEN_WEBGL_CONTEXT_HANDLE) – The WebGL context to get width/height of.
  • *width (int) – The context’s drawingBufferWidth.
  • *height (int) – The context’s drawingBufferHeight.
Returns:

EMSCRIPTEN_RESULT_SUCCESS, or one of the other result values.

Return type:

EMSCRIPTEN_RESULT

EMSCRIPTEN_RESULT emscripten_webgl_destroy_context(EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context)

Deletes the given WebGL context. If that context was active, then the no context is set to active.

Parameters:
Returns:

EMSCRIPTEN_RESULT_SUCCESS, or one of the other result values.

Return type:

EMSCRIPTEN_RESULT

EM_BOOL emscripten_webgl_enable_extension(EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context, const char *extension)

Enables the given extension on the given context.

Parameters:
Returns:

EM_TRUE if the given extension is supported by the context, and EM_FALSE if the extension was not available.

Return type:

EM_BOOL

EMSCRIPTEN_RESULT emscripten_set_canvas_element_size(const char *target, int width, int height)

Resizes the pixel width and height of the given Canvas element in the DOM.

Parameters:
  • target – Specifies a selector for the canvas to resize.
  • width – New pixel width of canvas element.
  • height – New pixel height of canvas element.
Returns:

EMSCRIPTEN_RESULT_SUCCESS if resizing succeeded, and one of the EMSCRIPTEN_RESULT_* error values on failure.

EMSCRIPTEN_RESULT emscripten_get_canvas_element_size(const char *target, int *width, int *height)

Gets the current pixel width and height of the given Canvas element in the DOM.

Parameters:
  • target – Specifies a selector for the canvas to resize.
  • width – A pointer to memory location where the width of the canvas element is received. This pointer may not be null.
  • height – A pointer to memory location where the height of the canvas element is received. This pointer may not be null.
Returns:

EMSCRIPTEN_RESULT_SUCCESS if width and height retrieval succeeded, and one of the EMSCRIPTEN_RESULT_* error values on failure.

CSS

Functions

EMSCRIPTEN_RESULT emscripten_set_element_css_size(const char * target, double width, double height)

Resizes the CSS width and height of the element specified by target on the Emscripten web page.

Parameters:
  • target (const char*) – Element to resize.
  • width (double) – New width of the element.
  • height (double) – New height of the element.
Returns:

EMSCRIPTEN_RESULT_SUCCESS, or one of the other result values.

Return type:

EMSCRIPTEN_RESULT

EMSCRIPTEN_RESULT emscripten_get_element_css_size(const char * target, double * width, double * height)

Gets the current CSS width and height of the element specified by target.

Parameters:
  • target (const char*) – Element to get size of.
  • width (double*) – Width of the element.
  • height (double*) – Height of the element.
Returns:

EMSCRIPTEN_RESULT_SUCCESS, or one of the other result values.

Return type:

EMSCRIPTEN_RESULT

Animation and Timing

The API provided here are low-level functions that directly call the relevant Web APIs and nothing more. They don’t integrate with the emscripten runtime, such as checking if the program has halted and cancelling a callback if so. For that purpose, see the function emscripten_set_main_loop().

Functions

long emscripten_set_timeout(void (*cb)(void *userData), double msecs, void *userData)

Performs a setTimeout() callback call on the given function on the calling thread.

Parameters:
  • cb – The callback function to call.
  • msecs – Millisecond delay until the callback should fire.
  • userData – Specifies a pointer sized field of custom data that will be passed in to the callback function.
Returns:

An ID to the setTimeout() call that can be passed to emscripten_clear_timeout() to cancel the pending timeout timer.

void emscripten_clear_timeout(long setTimeoutId)

Cancels a pending setTimeout() call on the calling thread. This function must be called on the same thread as the emscripten_set_timeout() call that registered the callback.

Parameters:
void emscripten_set_timeout_loop(EM_BOOL (*cb)(double time, void *userData), double intervalMsecs, void *userData)

Initializes a setTimeout() loop on the given function on the calling thread. The specified callback function ‘cb’ needs to keep returning EM_TRUE as long as the animation loop should continue to run. When the function returns false, the setTimeout() loop will stop. Note: The loop will start immediately with a 0 msecs delay - the passed in intervalMsecs time specifies the interval that the consecutive callback calls should fire at.

Parameters:
  • cb – The callback function to call.
  • intervalMsecs – Millisecond interval at which the callback should keep firing.
  • userData – Specifies a pointer sized field of custom data that will be passed in to the callback function.
long emscripten_request_animation_frame(EM_BOOL (*cb)(double time, void *userData), void *userData)

Performs a single requestAnimationFrame() callback call on the given function on the calling thread.

Parameters:
  • cb – The callback function to call. This function will receive the current high precision timer value (value of performance.now()) at the time of the call.
  • userData – Specifies a pointer sized field of custom data that will be passed in to the callback function.
Returns:

An ID to the requestAnimationFrame() call that can be passed to emscripten_cancel_animation_frame() to cancel the pending requestAnimationFrame timer.

void emscripten_cancel_animation_frame(long requestAnimationFrameId)

Cancels a registered requestAnimationFrame() callback on the calling thread before it is run. This function must be called on the same thread as the emscripten_request_animation_frame() call that registered the callback.

Parameters:
void emscripten_request_animation_frame_loop(EM_BOOL (*cb)(double time, void *userData), void *userData)

Initializes a requestAnimationFrame() loop on the given function on the calling thread. The specified callback function ‘cb’ needs to keep returning EM_TRUE as long as the animation loop should continue to run. When the function returns false, the animation frame loop will stop.

Parameters:
  • cb – The callback function to call. This function will receive the current high precision timer value (value of performance.now()) at the time of the call.
  • userData – Specifies a pointer sized field of custom data that will be passed in to the callback function.
long emscripten_set_immediate(void (*cb)(void *userData), void *userData)

Performs a setImmediate() callback call on the given function on the calling thread. Returns an ID to the setImmediate() call that can be passed to emscripten_clear_immediate() function to cancel a pending setImmediate() invocation. TODO: Currently the polyfill of setImmediate() only works in the main browser thread, but not in pthreads.

Parameters:
  • cb – The callback function to call.
  • userData – Specifies a pointer sized field of custom data that will be passed in to the callback function.
Returns:

An ID to the setImmediate() call that can be passed to emscripten_clear_immediate() to cancel the pending callback.

void emscripten_clear_immediate(long setImmediateId)

Cancels a pending setImmediate() call on the calling thread. This function must be called on the same thread as the emscripten_set_immediate() call that registered the callback.

Parameters:
void emscripten_set_immediate_loop(EM_BOOL (*cb)(void *userData), void *userData)

Initializes a setImmediate() loop on the given function on the calling thread. The specified callback function ‘cb’ needs to keep returning EM_TRUE as long as the loop should continue to run. When the function returns false, the setImmediate() loop will stop. TODO: Currently the polyfill of setImmediate() only works in the main browser thread, but not in pthreads.

Parameters:
  • cb – The callback function to call.
  • userData – Specifies a pointer sized field of custom data that will be passed in to the callback function.
long emscripten_set_interval(void (*cb)(void *userData), double intervalMsecs, void *userData)

Initializes a setInterval() loop on the given function on the calling thread. Returns an ID to the initialized loop. Call emscripten_clear_interval() with this ID to terminate the loop. Note that this function will cause the given callback to be called repeatedly. Do not call emscripten_set_interval() again on the same callback function from inside the callback, as that would register multiple loops to run simultaneously.

Parameters:
  • cb – The callback function to call.
  • intervalMsecs – Millisecond interval at which the callback should keep firing.
  • userData – Specifies a pointer sized field of custom data that will be passed in to the callback function.
Returns:

An ID to the setInterval() call that can be passed to emscripten_clear_interval() to cancel the currently executing interval timer.

void emscripten_clear_interval(long setIntervalId)

Cancels a currently executing setInterval() loop on the calling thread. This function must be called on the same thread as the emscripten_set_interval() call that registered the callback.

Parameters:
double emscripten_date_now(void)

Calls JavaScript Date.now() function in the current thread.

Returns:The number of msecs elapsed since the UNIX epoch. (00:00:00 Thursday, 1 January 1970)
double emscripten_performance_now(void)

Calls JavaScript performance.now() function in the current thread. Note that the returned value of this function is based on different time offset depending on which thread this function is called in. That is, do not compare absolute time values returned by performance.now() across threads. (comparing relative timing values is ok). On the main thread this function returns the number of milliseconds elapsed since page startup time. In a Web Worker/pthread, this function returns the number of milliseconds since the Worker hosting that pthread started up. (Workers are generally not torn down when a pthread quits and a second one starts, but they are kept alive in a pool, so this function is not guaranteed to start counting time from 0 at the time when a pthread starts)

Returns:A high precision wallclock time value in msecs.

Console

Functions

void emscripten_console_log(const char *utf8String)

Prints a string using console.log().

Parameters:
  • utf8String – A string encoded as UTF-8.
void emscripten_console_warn(const char *utf8String)

Prints a string using console.warn().

Parameters:
  • utf8String – A string encoded as UTF-8.
void emscripten_console_error(const char *utf8String)

Prints a string using console.error().

Parameters:
  • utf8String – A string encoded as UTF-8.

Throw

Functions

void emscripten_throw_number(double number)

Invokes JavaScript throw statement and throws a number.

void emscripten_throw_string(const char *utf8String)

Invokes JavaScript throw statement and throws a string.

void emscripten_unwind_to_js_event_loop(void)

Throws a JavaScript exception that unwinds the stack and yields execution back to the browser event loop. This function does not return execution back to calling code.

This function can be useful when porting code that would enter an infinite loop. Instead of actually running an infinite loop, which is not allowed on the Web, we can set up the body of the loop to execute asynchronously (using emscripten_set_main_loop() or something else), and call this function to halt execution, which is important as we do not want execution to continue normally.

preamble.js

The JavaScript APIs in preamble.js provide programmatic access for interacting with the compiled C code, including: calling compiled C functions, accessing memory, converting pointers to JavaScript Strings and Strings to pointers (with different encodings/formats), and other convenience functions.

We call this “preamble.js” because Emscripten’s output JS, at a high level, contains the preamble (from src/preamble.js), then the compiled code, then the postamble. (In slightly more detail, the preamble contains utility functions and setup, while the postamble connects things and handles running the application.)

The preamble code is included in the output JS, which is then optimized all together by the compiler, together with any --pre-js and --post-js files you added and code from any JavaScript libraries (--js-library). That means that you can call methods from the preamble directly, and the compiler will see that you need them, and not remove them as being unused.

If you want to call preamble methods from somewhere the compiler can’t see, like another script tag on the HTML, you need to export them. To do so, add them to EXTRA_EXPORTED_RUNTIME_METHODS (for example, -s 'EXTRA_EXPORTED_RUNTIME_METHODS=["ccall", "cwrap"]' will export call and cwrap). Once exported, you can access them on the Module object (as Module.ccall, for example).

Note

If you try to use Module.ccall or another runtime method without exporting it, you will get an error. In a build with -s ASSERTIONS=1, the compiler emits code to show you a useful error message, which will explain that you need to export it. In general, if you see something odd, it’s useful to build with assertions.

Calling compiled C functions from JavaScript

ccall(ident, returnType, argTypes, args, opts)

Call a compiled C function from JavaScript.

The function executes a compiled C function from JavaScript and returns the result. C++ name mangling means that “normal” C++ functions cannot be called; the function must either be defined in a .c file or be a C++ function defined with extern "C".

returnType and argTypes let you specify the types of parameters and the return value. The possible types are "number", "string", "array", or "boolean", which correspond to the appropriate JavaScript types. Use "number" for any numeric type or C pointer, string for C char* that represent strings, "boolean" for a boolean type, "array" for JavaScript arrays and typed arrays, containing 8-bit integer data - that is, the data is written into a C array of 8-bit integers; and in particular if you provide a typed array here, it must be a Uint8Array or Int8Array. If you want to receive an array of another type of data, you can manually allocate memory and write to it, then provide a pointer here (as a "number", as pointers are just numbers).

// Call C from JavaScript
var result = Module.ccall('c_add', // name of C function
  'number', // return type
  ['number', 'number'], // argument types
  [10, 20]); // arguments

// result is 30

Note

  • ccall uses the C stack for temporary values. If you pass a string then it is only “alive” until the call is complete. If the code being called saves the pointer to be used later, it may point to invalid data.

  • If you need a string to live forever, you can create it, for example, using _malloc and stringToUTF8(). However, you must later delete it manually!

  • LLVM optimizations can inline and remove functions, after which you will not be able to call them. Similarly, function names minified by the Closure Compiler are inaccessible. In either case, the solution is to add the functions to the EXPORTED_FUNCTIONS list when you invoke emcc:

    -s EXPORTED_FUNCTIONS="['_main', '_myfunc']"
    

    (Note that we also export main - if we didn’t, the compiler would assume we don’t need it.) Exported functions can then be called as normal:

    a_result = Module.ccall('myfunc', 'number', ['number'], [10])
    
Arguments:
  • ident – The name of the C function to be called.
  • returnType – The return type of the function. Note that array is not supported as there is no way for us to know the length of the array. For a void function this can be null (note: the JavaScript null value, not a string containing the word “null”).

Note

64-bit integers become two 32-bit parameters, for the low and high bits (since 64-bit integers cannot be represented in JavaScript numbers).

Arguments:
  • argTypes – An array of the types of arguments for the function (if there are no arguments, this can be omitted).
  • args – An array of the arguments to the function, as native JavaScript values (as in returnType). Note that string arguments will be stored on the stack (the JavaScript string will become a C string on the stack).
Returns:

The result of the function call as a native JavaScript value (as in returnType) or, if the async option is set, a JavaScript Promise of the result.

Opts:

An optional options object. It can contain the following properties:

  • async: If true, implies that the ccall will perform an async operation. This assumes you are build with asyncify support.

Note

Async calls currently don’t support promise error handling.

cwrap(ident, returnType, argTypes)

Returns a native JavaScript wrapper for a C function.

This is similar to ccall(), but returns a JavaScript function that can be reused as many time as needed. The C function can be defined in a C file, or be a C-compatible C++ function defined using extern "C" (to prevent name mangling).

// Call C from JavaScript
var c_javascript_add = Module.cwrap('c_add', // name of C function
  'number', // return type
  ['number', 'number']); // argument types

// Call c_javascript_add normally
console.log(c_javascript_add(10, 20)); // 30
console.log(c_javascript_add(20, 30)); // 50

Note

  • cwrap uses the C stack for temporary values. If you pass a string then it is only “alive” until the call is complete. If the code being called saves the pointer to be used later, it may point to invalid data. If you need a string to live forever, you can create it, for example, using _malloc and stringToUTF8(). However, you must later delete it manually!

  • LLVM optimizations can inline and remove functions, after which you will not be able to “wrap” them. Similarly, function names minified by the Closure Compiler are inaccessible. In either case, the solution is to add the functions to the EXPORTED_FUNCTIONS list when you invoke emcc :

  • cwrap does not actually call compiled code (only calling the wrapper it returns does that). That means that it is safe to call cwrap early, before the runtime is fully initialized (but calling the returned wrapped function must wait for the runtime, of course, like calling compiled code in general).

    -s EXPORTED_FUNCTIONS="['_main', '_myfunc']"
    

    Exported functions can be called as normal:

    my_func = Module.cwrap('myfunc', 'number', ['number'])
    my_func(12)
    
Arguments:
  • ident – The name of the C function to be called.
  • returnType – The return type of the function. This can be "number", "string" or "array", which correspond to the appropriate JavaScript types (use "number" for any C pointer, and "array" for JavaScript arrays and typed arrays; note that arrays are 8-bit), or for a void function it can be null (note: the JavaScript null value, not a string containing the word “null”).
  • argTypes – An array of the types of arguments for the function (if there are no arguments, this can be omitted). Types are as in returnType, except that array is not supported as there is no way for us to know the length of the array).
  • opts – An optional options object, see ccall().
Returns:

A JavaScript function that can be used for running the C function.

Accessing memory

setValue(ptr, value, type[, noSafe])

Sets a value at a specific memory address at run-time.

Note

  • setValue() and getValue() only do aligned writes and reads.
  • The type is an LLVM IR type (one of i8, i16, i32, i64, float, double, or a pointer type like i8* or just *), not JavaScript types as used in ccall() or cwrap(). This is a lower-level operation, and we do need to care what specific type is being used.
Arguments:
  • ptr – A pointer (number) representing the memory address.
  • value – The value to be stored
  • type – An LLVM IR type as a string (see “note” above).
  • noSafe (bool) – Developers should ignore this variable. It is only used in SAFE_HEAP compilation mode, where it can help avoid infinite recursion in some specialist use cases.
getValue(ptr, type[, noSafe])

Gets a value at a specific memory address at run-time.

Note

  • setValue() and getValue() only do aligned writes and reads!
  • The type is an LLVM IR type (one of i8, i16, i32, i64, float, double, or a pointer type like i8* or just *), not JavaScript types as used in ccall() or cwrap(). This is a lower-level operation, and we do need to care what specific type is being used.
Arguments:
  • ptr – A pointer (number) representing the memory address.
  • type – An LLVM IR type as a string (see “note” above).
  • noSafe (bool) – Developers should ignore this variable. It is only used in SAFE_HEAP compilation mode, where it can help avoid infinite recursion in some specialist use cases.
Returns:

The value stored at the specified memory address.

Conversion functions — strings, pointers and arrays

UTF8ToString(ptr[, maxBytesToRead])

Given a pointer ptr to a null-terminated UTF8-encoded string in the Emscripten HEAP, returns a copy of that string as a JavaScript String object.

Arguments:
  • ptr – A pointer to a null-terminated UTF8-encoded string in the Emscripten HEAP.
  • maxBytesToRead – An optional length that specifies the maximum number of bytes to read. You can omit this parameter to scan the string until the first 0 byte. If maxBytesToRead is passed, and the string at [ptr, ptr+maxBytesToReadr[ contains a null byte in the middle, then the string will cut short at that byte index (i.e. maxBytesToRead will not produce a string of exact length [ptr, ptr+maxBytesToRead[) N.B. mixing frequent uses of UTF8ToString() with and without maxBytesToRead may throw JS JIT optimizations off, so it is worth to consider consistently using one style or the other.
Returns:

A JavaScript String object

stringToUTF8(str, outPtr, maxBytesToWrite)

Copies the given JavaScript String object str to the Emscripten HEAP at address outPtr, null-terminated and encoded in UTF8 form.

The copy will require at most str.length*4+1 bytes of space in the HEAP. You can use the function lengthBytesUTF8() to compute the exact amount of bytes (excluding the null terminator) needed to encode the string.

Arguments:
  • str (String) – A JavaScript String object.
  • outPtr – Pointer to data copied from str, encoded in UTF8 format and null-terminated.
  • maxBytesToWrite – A limit on the number of bytes that this function can at most write out. If the string is longer than this, the output is truncated. The outputted string will always be null terminated, even if truncation occurred, as long as maxBytesToWrite > 0.
UTF16ToString(ptr)

Given a pointer ptr to a null-terminated UTF16LE-encoded string in the Emscripten HEAP, returns a copy of that string as a JavaScript String object.

Arguments:
  • ptr – A pointer to a null-terminated UTF16LE-encoded string in the Emscripten HEAP.
Returns:

A JavaScript String object

stringToUTF16(str, outPtr, maxBytesToWrite)

Copies the given JavaScript String object str to the Emscripten HEAP at address outPtr, null-terminated and encoded in UTF16LE form.

The copy will require exactly (str.length+1)*2 bytes of space in the HEAP.

Arguments:
  • str (String) – A JavaScript String object.
  • outPtr – Pointer to data copied from str, encoded in UTF16LE format and null-terminated.
  • maxBytesToWrite – A limit on the number of bytes that this function can at most write out. If the string is longer than this, the output is truncated. The outputted string will always be null terminated, even if truncation occurred, as long as maxBytesToWrite >= 2 so that there is space for the null terminator.
UTF32ToString(ptr)

Given a pointer ptr to a null-terminated UTF32LE-encoded string in the Emscripten HEAP, returns a copy of that string as a JavaScript String object.

Arguments:
  • ptr – A pointer to a null-terminated UTF32LE-encoded string in the Emscripten HEAP.
Returns:

A JavaScript String object.

stringToUTF32(str, outPtr, maxBytesToWrite)

Copies the given JavaScript String object str to the Emscripten HEAP at address outPtr, null-terminated and encoded in UTF32LE form.

The copy will require at most (str.length+1)*4 bytes of space in the HEAP, but can use less, since str.length does not return the number of characters in the string, but the number of UTF-16 code units in the string. You can use the function lengthBytesUTF32() to compute the exact amount of bytes (excluding the null terminator) needed to encode the string.

Arguments:
  • str (String) – A JavaScript String object.
  • outPtr – Pointer to data copied from str, encoded in encoded in UTF32LE format and null-terminated.
  • maxBytesToWrite – A limit on the number of bytes that this function can at most write out. If the string is longer than this, the output is truncated. The outputted string will always be null terminated, even if truncation occurred, as long as maxBytesToWrite >= 4` so that there is space for the null terminator.
AsciiToString(ptr)

Converts an ASCII or Latin-1 encoded string to a JavaScript String object.

Arguments:
  • ptr – The pointer to be converted to a String.
Returns:

A JavaScript String containing the data from ptr.

Return type:

String

intArrayFromString(stringy, dontAddNull[, length])

This converts a JavaScript string into a C-line array of numbers, 0-terminated.

Arguments:
  • stringy (String) – The string to be converted.
  • dontAddNull (bool) – If true, the new array is not zero-terminated.
  • length – The length of the array (optional).
Returns:

The array created from stringy.

intArrayToString(array)

This creates a JavaScript string from a zero-terminated C-line array of numbers.

Arguments:
  • array – The array to convert.
Returns:

A String, containing the content of array.

writeStringToMemory(string, buffer, dontAddNull)

Writes a JavaScript string to a specified address in the heap.

Warning

This function is deprecated, you should call the function stringToUTF8 instead, which provides a secure bounded version of the same functionality instead.

// Allocate space for string and extra '0' at the end
var buffer = Module._malloc(myString.length+1);

// Write the string to memory
Module.writeStringToMemory(myString, buffer);

// We can now send buffer into a C function, it is just a normal char* pointer
Arguments:
  • string (String) – The string to write into memory.
  • buffer (Number) – The address (number) where string is to be written.
  • dontAddNull (bool) – If true, the new array is not zero-terminated.
writeArrayToMemory(array, buffer)

Writes an array to a specified address in the heap. Note that memory should to be allocated for the array before it is written.

Arguments:
  • array – The array to write to memory.
  • buffer (Number) – The address (number) where array is to be written.
writeAsciiToMemory(str, buffer, dontAddNull)

Writes an ASCII string to a specified address in the heap. Note that memory should to be allocated for the string before it is written.

The string is assumed to only have characters in the ASCII character set. If ASSERTIONS are enabled and this is not the case, it will fail.

// Allocate space for string
var buffer = Module._malloc(myString.length);

// Write the string to memory
Module.writeStringToMemory(myString, buffer);
Arguments:
  • string – The string to write into memory.
  • buffer – The address where string is to be written.
  • dontAddNull (bool) – If true, the new string is not zero-terminated.

Run dependencies

Note that generally run dependencies are managed by the file packager and other parts of the system. It is rare for developers to use this API directly.

addRunDependency(id)

Adds an id to the list of run dependencies.

This adds a run dependency and increments the run dependency counter.

Arguments:
  • id (String) – An arbitrary id representing the operation.
removeRunDependency(id)

Removes a specified id from the list of run dependencies.

Arguments:
  • id (String) – The identifier for the specific dependency to be removed (added with addRunDependency())

Stack trace

stackTrace()

Returns the current stack track.

Note

The stack trace is not available at least on IE10 and Safari 6.

Returns:The current stack trace, if available.

Type accessors for the memory model

The Emscripten memory representation uses a typed array buffer (ArrayBuffer) to represent memory, with different views into it giving access to the different types. The views for accessing different types of memory are listed below.

HEAP8

View for 8-bit signed memory.

HEAP16

View for 16-bit signed memory.

HEAP32

View for 32-bit signed memory.

HEAPU8

View for 8-bit unsigned memory.

HEAPU16

View for 16-bit unsigned memory.

HEAPU32

View for 32-bit unsigned memory.

HEAPF32

View for 32-bit float memory.

HEAPF64

View for 64-bit float memory.

File System API

File operations in Emscripten are provided by the FS library. It is used internally for all of Emscripten’s libc and libcxx file I/O.

Note

The API is inspired by the Linux/POSIX File System API, with each presenting a very similar interface.

The underlying behaviour is also similar, except where differences between the native and browser environments make this unreasonable. For example, user and group permissions are defined but ignored in FS.open().

Emscripten predominantly compiles code that uses synchronous file I/O, so the majority of the FS member functions offer a synchronous interface (with errors being reported by raising exceptions of type FS.ErrnoError).

File data in Emscripten is partitioned by mounted file systems. Several file systems are provided. An instance of MEMFS is mounted to / by default. The subdirectories /home/web_user and /tmp are also created automatically, in addition to several other special devices and streams (e.g. /dev/null, /dev/random, /dev/stdin, /proc/self/fd); see FS.staticInit() in the FS library for full details. Instances of NODEFS and IDBFS can be mounted to other directories if your application needs to persist data.

The automatic tests in tests/test_core.py (search for test_files) contain many examples of how to use this API. The tutorial also shows how to pre-load a file so that it can be read from compiled C/C++.

A high level overview of the way File Systems work in Emscripten-ported code is provided in the File System Overview.

Including File System Support

Emscripten decides whether to include file system support automatically. Many programs don’t need files, and file system support is not negligible in size, so Emscripten avoids including it when it doesn’t see a reason to. That means that if your C/C++ code does not access files, then the FS object and other file system APIs will not be included in the output. And, on the other hand, if your C/C++ code does use files, then file system support will be automatically included. So normally things will “just work” and you don’t need to think about this at all.

However, if your C/C++ code doesn’t use files, but you want to use them from JavaScript, then you can build with -s FORCE_FILESYSTEM=1, which will make the compiler include file system support even though it doesn’t see it being used.

On the other hand, if you want to not include any filesystem support code (which may be included even due to printf or iostreams, due to how musl and libc++ are structured), you can build with -s FILESYSTEM=0. Very simple stdout support will be included if necessary in such a case, enough for printf and such to work, but no filesystem code will be added, which can save a significant amount of code size.

Persistent data

Applications compiled with Emscripten usually expect synchronous I/O, so Emscripten itself provides file systems with completely synchronous interfaces.

However, due to JavaScript’s event-driven nature, most persistent storage options offer only asynchronous interfaces. Emscripten offers multiple file systems that can be mounted with FS.mount() to help deal with persistence depending on the execution context.

File systems

Note

Only the MEMFS filesystem is included by default. All others must be enabled explicitly, using -lnodefs.js (NODEFS), -lidbfs.js (IDBFS), -lworkerfs.js (WORKERFS), or -lproxyfs.js (PROXYFS).

MEMFS

This is the default file system mounted at / when the runtime is initialized. All files exist strictly in-memory, and any data written to them is lost when the page is reloaded.

NODEFS

Note

This file system is only for use when running inside node.js.

This file system lets a program in node map directories (via a mount operation) on the host filesystem to directories in Emscripten’s virtual filesystem. It uses node’s synchronous FS API to immediately persist any data written to the Emscripten file system to your local disk.

See this test for an example.

IDBFS

Note

This file system is only for use when running code inside a browser.

The IDBFS file system implements the FS.syncfs() interface, which when called will persist any operations to an IndexedDB instance.

This is provided to overcome the limitation that browsers do not offer synchronous APIs for persistent storage, and so (by default) all writes exist only temporarily in-memory.

WORKERFS

Note

This file system is only for use when running code inside a worker.

This file system provides read-only access to File and Blob objects inside a worker without copying the entire data into memory and can potentially be used for huge files.

Devices

Emscripten supports registering arbitrary device drivers composed of a device id and a set of device-specific stream callbacks. Once a driver has been registered with FS.registerDevice(), a device node can be created to reference it (using FS.mkdev()).

The device node acts as an interface between the device and the file system. Any stream referencing the new node will inherit the stream callbacks registered for the device, making all of the high-level FS operations transparently interact with the device.

Note

Every device is different and unique. While common file operations like open, close, read, and write are typically supported (and inherited by file streams to provide a layer of abstraction for the equivalent libc functions to call), each device should implement whatever callbacks it needs based on its unique characteristics.

FS.makedev(ma, mi)

Converts a major and minor number into a single unique integer. This is used as an id to represent the device.

Arguments:
  • ma – Major number.
  • mi – Minor number.
FS.registerDevice(dev, ops)

Registers the specified device driver with a set of callbacks.

Arguments:
  • dev – The specific device driver id, created using makedev().
  • ops (object) – The set of callbacks required by the device. For an example, see the NODEFS default callbacks.

Setting up standard I/O devices

Emscripten standard I/O works by going though the virtual /dev/stdin, /dev/stdout and /dev/stderr devices. You can set them up using your own I/O functions by calling FS.init().

By default:

  • stdin will read from the terminal in command line engines and use window.prompt() in browsers (in both cases, with line buffering).
  • stdout will use a print function if one such is defined, printing to the terminal in command line engines and to the browser console in browsers that have a console (again, line-buffered).
  • stderr will use the same output function as stdout.

Note

All the configuration should be done before the main run() method is executed, typically by implementing Module.preRun. See Interacting with code for more information.

FS.init(input, output, error)

Sets up standard I/O devices for stdin, stdout, and stderr.

The devices are set up using the following (optional) callbacks. If any of the callbacks throw an exception, it will be caught and handled as if the device malfunctioned.

Arguments:
  • input – Input callback. This will be called with no parameters whenever the program attempts to read from stdin. It should return an ASCII character code when data is available, or null when it isn’t.
  • output – Output callback. This will be called with an ASCII character code whenever the program writes to stdout. It may also be called with null to flush the output.
  • error – Error callback. This is similar to output, except it is called when data is written to stderr.

File system API

FS.mount(type, opts, mountpoint)

Mounts the FS object specified by type to the directory specified by mountpoint. The opts object is specific to each file system type.

Arguments:
  • type – The file system type: MEMFS, NODEFS, IDBFS or WORKERFS.
  • opts (object) –

    A generic settings object used by the underlying file system.

    NODFES uses the root parameter to map the Emscripten directory to the physical directory. For example, to mount the current folder as a NODEFS instance:

    FS.mkdir('/working');
    FS.mount(NODEFS, { root: '.' }, '/working');
    

    WORKERFS accepts files and blobs parameters to map a provided flat list of files into the mountpoint directory:

    var blob = new Blob(['blob data']);
    FS.mkdir('/working');
    FS.mount(WORKERFS, {
      blobs: [{ name: 'blob.txt', data: blob }],
      files: files, // Array of File objects or FileList
    }, '/working');
    

    You can also pass in a package of files, created by tools/file_packager.py with --separate-metadata. You must provide the metadata as a JSON object, and the data as a blob:

    // load metadata and blob using XMLHttpRequests, or IndexedDB, or from someplace else
    FS.mkdir('/working');
    FS.mount(WORKERFS, {
      packages: [{ metadata: meta, blob: blob }]
    }, '/working');
    
  • mountpoint (string) – A path to an existing local Emscripten directory where the file system is to be mounted. It can be either an absolute path, or something relative to the current directory.
FS.unmount(mountpoint)

Unmounts the specified mountpoint.

Arguments:
  • mountpoint (string) – The directory to unmount.
FS.syncfs(populate, callback)

Responsible for iterating and synchronizing all mounted file systems in an asynchronous fashion.

Note

Currently, only the IDBFS file system implements the interfaces needed for synchronization. All other file systems are completely synchronous and don’t require synchronization.

The populate flag is used to control the intended direction of the underlying synchronization between Emscripten`s internal data, and the file system’s persistent data.

For example:

function myAppStartup(callback) {
  FS.mkdir('/data');
  FS.mount(IDBFS, {}, '/data');

  FS.syncfs(true, function (err) {
  // handle callback
  });
}

function myAppShutdown(callback) {
  FS.syncfs(function (err) {
  // handle callback
  });
}

A real example of this functionality can be seen in test_idbfs_sync.c.

Arguments:
  • populate (bool) – true to initialize Emscripten’s file system data with the data from the file system’s persistent source, and false to save Emscripten`s file system data to the file system’s persistent source.
  • callback – A notification callback function that is invoked on completion of the synchronization. If an error occurred, it will be provided as a parameter to this function.
FS.mkdir(path, mode)

Creates a new directory node in the file system. For example:

FS.mkdir('/data');

Note

The underlying implementation does not support user or group permissions. The caller is always treated as the owner of the folder, and only permissions relevant to the owner apply.

Arguments:
FS.mkdev(path, mode, dev)

Creates a new device node in the file system referencing the registered device driver (FS.registerDevice()) for dev. For example:

var id = FS.makedev(64, 0);
FS.registerDevice(id, {});
FS.mkdev('/dummy', id);
Arguments:
  • path (string) – The path name for the new device node.
  • mode (int) –

    File permissions for the new node. The default setting (in octal numeric notation) is 0777.

  • dev (int) – The registered device driver.

Creates a symlink node at newpath linking to oldpath. For example:

FS.writeFile('file', 'foobar');
FS.symlink('file', 'link');
Arguments:
  • oldpath (string) – The path name of the file to link to.
  • newpath (string) – The path to the new symlink node, that points to oldpath.
FS.rename(oldpath, newpath)

Renames the node at oldpath to newpath. For example:

FS.writeFile('file', 'foobar');
FS.rename('file', 'newfile');
Arguments:
  • oldpath (string) – The old path name.
  • newpath (string) – The new path name
FS.rmdir(path)

Removes an empty directory located at path.

Example

FS.mkdir('data');
FS.rmdir('data');
Arguments:
  • path (string) – Path of the directory to be removed.

Unlinks the node at path.

This removes a name from the file system. If that name was the last link to a file (and no processes have the file open) the file is deleted.

For example:

FS.writeFile('/foobar.txt', 'Hello, world');
FS.unlink('/foobar.txt');
Arguments:
  • path (string) – Path of the target node.

Gets the string value stored in the symbolic link at path. For example:

#include <stdio.h>
#include <emscripten.h>

int main() {
  MAIN_THREAD_EM_ASM(
  FS.writeFile('file', 'foobar');
  FS.symlink('file', 'link');
  console.log(FS.readlink('link'));
  );
  return 0;
}

outputs:

file
Arguments:
  • path (string) – Path to the target file.
Returns:

The string value stored in the symbolic link at path.

FS.stat(path)

Gets a JavaScript object containing statistics about the node at path. For example:

#include <stdio.h>
#include <emscripten.h>

int main() {
  MAIN_THREAD_EM_ASM(
  FS.writeFile('file', 'foobar');
  console.log(FS.stat('file'));
  );
  return 0;
}

outputs:

{
  dev: 1,
  ino: 13,
  mode: 33206,
  nlink: 1,
  uid: 0,
  gid: 0,
  rdev: 0,
  size: 6,
  atime: Mon Nov 25 2013 00:37:27 GMT-0800 (PST),
  mtime: Mon Nov 25 2013 00:37:27 GMT-0800 (PST),
  ctime: Mon Nov 25 2013 00:37:27 GMT-0800 (PST),
  blksize: 4096,
  blocks: 1
}
Arguments:
  • path (string) – Path to the target file.
FS.lstat(path)

Identical to FS.stat(), However, if path is a symbolic link then the returned stats will be for the link itself, not the file that it links to.

Arguments:
  • path (string) – Path to the target file.
FS.chmod(path, mode)

Change the mode flags for path to mode.

Note

The underlying implementation does not support user or group permissions. The caller is always treated as the owner of the folder, and only permissions relevant to the owner apply.

For example:

FS.writeFile('forbidden', 'can\'t touch this');
FS.chmod('forbidden', 0000);
Arguments:
FS.lchmod(path, mode)

Identical to FS.chmod(). However, if path is a symbolic link then the mode will be set on the link itself, not the file that it links to.

Arguments:
FS.fchmod(fd, mode)

Identical to FS.chmod(). However, a raw file descriptor is supplied as fd.

Arguments:
FS.chown(path, uid, gid)

Change the ownership of the specified file to the given user or group id.

Note

This call exists to provide a more “complete” API mapping for ported code. Values set are effectively ignored.

Arguments:
  • path (string) – Path to the target file.
  • uid (int) – The id of the user to take ownership of the file.
  • gid (int) – The id of the group to take ownership of the file.
FS.lchown(path, uid, gid)

Identical to FS.chown(). However, if path is a symbolic link then the properties will be set on the link itself, not the file that it links to.

Note

This call exists to provide a more “complete” API mapping for ported code. Values set are effectively ignored.

Arguments:
  • path (string) – Path to the target file.
  • uid (int) – The id of the user to take ownership of the file.
  • gid (int) – The id of the group to take ownership of the file.
FS.fchown(fd, uid, gid)

Identical to FS.chown(). However, a raw file descriptor is supplied as fd.

Note

This call exists to provide a more “complete” API mapping for ported code. Values set are effectively ignored.

Arguments:
  • fd (int) – Descriptor of target file.
  • uid (int) – The id of the user to take ownership of the file.
  • gid (int) – The id of the group to take ownership of the file.
FS.truncate(path, len)

Truncates a file to the specified length. For example:

#include <stdio.h>
#include <emscripten.h>

int main() {
  MAIN_THREAD_EM_ASM(
  FS.writeFile('file', 'foobar');
  FS.truncate('file', 3);
  console.log(FS.readFile('file', { encoding: 'utf8' }));
  );
  return 0;
}

outputs:

foo
Arguments:
  • path (string) – Path of the file to be truncated.
  • len (int) – The truncation length for the file.
FS.ftruncate(fd, len)

Truncates the file identified by the fd to the specified length (len).

Arguments:
  • fd (int) – Descriptor of file to be truncated.
  • len (int) – The truncation length for the file.
FS.utime(path, atime, mtime)

Change the timestamps of the file located at path. The times passed to the arguments are in milliseconds since January 1, 1970 (midnight UTC/GMT).

Note that in the current implementation the stored timestamp is a single value, the maximum of atime and mtime.

Arguments:
  • path (string) – The path of the file to update.
  • atime (int) – The file modify time (milliseconds).
  • mtime (int) – The file access time (milliseconds).
FS.open(path, flags[, mode])

Opens a file with the specified flags. flags can be:

  • r — Open file for reading.
  • r+ — Open file for reading and writing.
  • w — Open file for writing.
  • wx — Like w but fails if path exists.
  • w+ — Open file for reading and writing. The file is created if it does not exist or truncated if it exists.
  • wx+ — Like w+ but fails if path exists.
  • a — Open file for appending. The file is created if it does not exist.
  • ax — Like a but fails if path exists.
  • a+ — Open file for reading and appending. The file is created if it does not exist.
  • ax+ — Like a+ but fails if path exists.

Note

The underlying implementation does not support user or group permissions. The file permissions set in mode are only used if the file is created. The caller is always treated as the owner of the file, and only those permissions apply.

Arguments:
  • path (string) – The path of the file to open.
  • flags (string) – Read and write flags.
  • mode

    File permission flags for the file. The default setting (in octal numeric notation) is 0666.

Returns:

A stream object.

FS.close(stream)

Closes the file stream.

Arguments:
  • stream (object) – The stream to be closed.
FS.llseek(stream, offset, whence)

Repositions the offset of the stream offset bytes relative to the beginning, current position, or end of the file, depending on the whence parameter.

The _llseek() function repositions the offset of the open file associated with the file descriptor fd to (offset_high<<32) | offset_low bytes relative to the beginning of the file, the current position in the file, or the end of the file, depending on whether whence is SEEK_SET, SEEK_CUR, or SEEK_END, respectively. It returns the resulting file position in the argument result.

Arguments:
  • stream (object) – The stream for which the offset is to be repositioned.
  • offset (int) – The offset (in bytes) relative to whence.
  • whence (int) – Point in file (beginning, current point, end) from which to calculate the offset: SEEK_SET (0), SEEK_CUR (1) or SEEK_END (2)
FS.read(stream, buffer, offset, length[, position])

Read length bytes from the stream, storing them into buffer starting at offset.

By default, reading starts from the stream’s current offset, however, a specific offset can be specified with the position argument. For example:

var stream = FS.open('abinaryfile', 'r');
var buf = new Uint8Array(4);
FS.read(stream, buf, 0, 4, 0);
FS.close(stream);
Arguments:
  • stream (object) – The stream to read from.
  • buffer (ArrayBufferView) – The buffer to store the read data.
  • offset (int) – The offset within buffer to store the data.
  • length (int) – The length of data to write in buffer.
  • position (int) – The offset within the stream to read. By default this is the stream’s current offset.
FS.write(stream, buffer, offset, length[, position])

Writes length bytes from buffer, starting at offset.

By default, writing starts from the stream’s current offset, however, a specific offset can be specified with the position argument. For example:

var data = new Uint8Array(32);
var stream = FS.open('dummy', 'w+');
FS.write(stream, data, 0, data.length, 0);
FS.close(stream);
Arguments:
  • stream (object) – The stream to write to.
  • buffer (ArrayBufferView) – The buffer to write.
  • offset (int) – The offset within buffer to write.
  • length (int) – The length of data to write.
  • position (int) – The offset within the stream to write. By default this is the stream’s current offset.
FS.readFile(path, opts)

Reads the entire file at path and returns it as a string (encoding is utf8), or as a new Uint8Array buffer (encoding is binary).

Arguments:
  • path (string) – The file to read.
  • opts (object) –
    • encoding (string) Defines the encoding used to return the file contents: binary | utf8 . The default is binary
    • flags (string) Read flags, as defined in FS.open(). The default is ‘r’.
Returns:

The file as a string or Uint8Array buffer, depending on the encoding.

FS.writeFile(path, data, opts)

Writes the entire contents of data to the file at path. For example:

FS.writeFile('file', 'foobar');
var contents = FS.readFile('file', { encoding: 'utf8' });
Arguments:
  • path (string) – The file to which to write data.
  • data (string|ArrayBufferView) – The data to write. A string will always be decoded as UTF-8.
  • opts (object) –
    • flags (string) Write flags, as defined in FS.open(). The default is ‘w’.
FS.createLazyFile(parent, name, url, canRead, canWrite)

Creates a file that will be loaded lazily on first access from a given URL or local file system path, and returns a reference to it.

Warning

Firefox and Chrome have recently disabled synchronous binary XHRs, which means this cannot work for JavaScript in regular HTML pages (but it works within Web Workers).

Example

FS.createLazyFile('/', 'foo', 'other/page.htm', true, false);
FS.createLazyFile('/', 'bar', '/get_file.php?name=baz', true, true);
Arguments:
  • parent (string/object) – The parent folder, either as a path (e.g. ‘/usr/lib’) or an object previously returned from a FS.createFolder() or FS.createPath() call.
  • name (string) – The name of the new file.
  • url (string) – In the browser, this is the URL whose contents will be returned when this file is accessed. In a command line engine like node.js, this will be the local (real) file system path from where the contents will be loaded. Note that writes to this file are virtual.
  • canRead (bool) – Whether the file should have read permissions set from the program’s point of view.
  • canWrite (bool) – Whether the file should have write permissions set from the program’s point of view.
Returns:

A reference to the new file.

FS.createPreloadedFile(parent, name, url, canRead, canWrite)

Preloads a file asynchronously, and uses preload plugins to prepare its content. You should call this in preRun, run() will be delayed until all preloaded files are ready. This is how the preload-file option works in emcc when --use-preload-plugins has been specified (if you use this method by itself, you will need to build the program with that option).

Arguments:
  • parent (string/object) – The parent folder, either as a path (e.g. ‘/usr/lib’) or an object previously returned from a FS.createFolder() or FS.createPath() call.
  • name (string) – The name of the new file.
  • url (string) – In the browser, this is the URL whose contents will be returned when the file is accessed. In a command line engine, this will be the local (real) file system path the contents will be loaded from. Note that writes to this file are virtual.
  • canRead (bool) – Whether the file should have read permissions set from the program’s point of view.
  • canWrite (bool) – Whether the file should have write permissions set from the program’s point of view.

File types

Emscripten’s file system supports regular files, directories, symlinks, character devices, block devices and sockets. Similarly to most Unix systems, all of these file types can be operated on using the higher-level FS operations like FS.read() and FS.write().

FS.isFile(mode)

Tests if the mode bitmask represents a file.

Arguments:
  • mode – A bitmask of possible file properties.
Returns:

true if the mode bitmask represents a file.

Return type:

bool

FS.isDir(mode)

Tests if the mode bitmask represents a directory.

Returns:true if the mode bitmask represents a directory.
Return type:bool

Tests if the mode bitmask represents a symlink.

Arguments:
  • mode – A bitmask of possible file properties.
Returns:

true if the mode bitmask represents a symlink.

Return type:

bool

FS.isChrdev(mode)

Tests if the mode bitmask represents a character device.

Arguments:
  • mode – A bitmask of possible file properties.
Returns:

true if the mode bitmask represents a character device.

Return type:

bool

FS.isBlkdev(mode)

Tests if the mode bitmask represents a block device.

Arguments:
  • mode – A bitmask of possible file properties.
Returns:

true if the mode bitmask represents a block device.

Return type:

bool

FS.isSocket(mode)

Tests if the mode bitmask represents a socket.

Arguments:
  • mode – A bitmask of possible file properties.
Returns:

true if the mode bitmask represents a socket.

Return type:

bool

Paths

FS.cwd()

Gets the current working directory.

Returns:The current working directory.
FS.chdir(path)

Sets the current working directory.

Arguments:
  • path (string) – The path to set as current working directory.
FS.lookupPath(path, opts)

Looks up the incoming path and returns an object containing both the resolved path and node.

The options (opts) allow you to specify whether the object, its parent component, a symlink, or the item the symlink points to are returned. For example:

var lookup = FS.lookupPath(path, { parent: true });
Arguments:
  • path (string) – The incoming path.
  • opts (object) –

    Options for the path:

    • parent (bool) If true, stop resolving the path once the penultimate component is reached. For example, the path /foo/bar with { parent: true } would return an object representing /foo. The default is false.
    • follow (bool) If true, follow the last component if it is a symlink. For example, consider a symlink /foo/symlink that links to /foo/notes.txt. If { follow: true }, an object representing /foo/notes.txt would be returned. If { follow: false }, an object representing the symlink file would be returned. The default is false.
Returns:

an object with the format:

{
  path: resolved_path,
  node: resolved_node
}

FS.getPath(node)

Gets the absolute path to node, accounting for mounts.

Arguments:
  • node – The current node.
Returns:

The absolute path to node.

Fetch API

The Emscripten Fetch API allows native code to transfer files via XHR (HTTP GET, PUT, POST) from remote servers, and to persist the downloaded files locally in browser’s IndexedDB storage, so that they can be reaccessed locally on subsequent page visits. The Fetch API is callable from multiple threads, and the network requests can be run either synchronously or asynchronously as desired.

Note

In order to use the Fetch API, you would need to compile your code with -s FETCH=1.

Introduction

The use of the Fetch API is quick to illustrate via an example. The following application downloads a file from a web server asynchronously to memory inside the application heap.

#include <stdio.h>
#include <string.h>
#include <emscripten/fetch.h>

void downloadSucceeded(emscripten_fetch_t *fetch) {
  printf("Finished downloading %llu bytes from URL %s.\n", fetch->numBytes, fetch->url);
  // The data is now available at fetch->data[0] through fetch->data[fetch->numBytes-1];
  emscripten_fetch_close(fetch); // Free data associated with the fetch.
}

void downloadFailed(emscripten_fetch_t *fetch) {
  printf("Downloading %s failed, HTTP failure status code: %d.\n", fetch->url, fetch->status);
  emscripten_fetch_close(fetch); // Also free data on failure.
}

int main() {
  emscripten_fetch_attr_t attr;
  emscripten_fetch_attr_init(&attr);
  strcpy(attr.requestMethod, "GET");
  attr.attributes = EMSCRIPTEN_FETCH_LOAD_TO_MEMORY;
  attr.onsuccess = downloadSucceeded;
  attr.onerror = downloadFailed;
  emscripten_fetch(&attr, "myfile.dat");
}

If a relative pathname is specified to a call to emscripten_fetch, like in the above example, the XHR is performed relative to the href (URL) of the current page. Passing a fully qualified absolute URL allows downloading files across domains, however these are subject to HTTP access control (CORS) rules.

By default the Fetch API runs asynchronously, which means that the emscripten_fetch() function call returns immediately and the operation will continue to occur on the background. When the operation finishes, either the success or the failure callback will be invoked.

Persisting data

The XHR requests issued by the Fetch API are subject to the usual browser caching behavior. These caches are transient (temporary) so there is no guarantee that the data will persist in the cache for a given period of time. Additionally, if the files are somewhat large (multiple megabytes), browsers typically don’t cache the downloads at all.

To enable a more explicit control for persisting the downloaded files, the Fetch API interacts with the browser’s IndexedDB API, which can load and store large data files that are available on subsequent visits to the page. To enable IndexedDB storage, pass the EMSCRIPTEN_FETCH_PERSIST_FILE flag in the fetch attributes:

int main() {
  emscripten_fetch_attr_t attr;
  emscripten_fetch_attr_init(&attr);
  ...
  attr.attributes = EMSCRIPTEN_FETCH_LOAD_TO_MEMORY | EMSCRIPTEN_FETCH_PERSIST_FILE;
  ...
  emscripten_fetch(&attr, "myfile.dat");
}

For a full example, see the file tests/fetch/example_async_xhr_to_memory_via_indexeddb.cpp.

Persisting data bytes from memory

Sometimes it is useful to persist a range of bytes from application memory to IndexedDB (without having to perform any XHRs). This is possible with the Emscripten Fetch API by passing the special HTTP action verb “EM_IDB_STORE” to the Emscripten Fetch operation.

void success(emscripten_fetch_t *fetch) {
  printf("IDB store succeeded.\n");
  emscripten_fetch_close(fetch);
}

void failure(emscripten_fetch_t *fetch) {
  printf("IDB store failed.\n");
  emscripten_fetch_close(fetch);
}

void persistFileToIndexedDB(const char *outputFilename, uint8_t *data, size_t numBytes) {
  emscripten_fetch_attr_t attr;
  emscripten_fetch_attr_init(&attr);
  strcpy(attr.requestMethod, "EM_IDB_STORE");
  attr.attributes = EMSCRIPTEN_FETCH_REPLACE | EMSCRIPTEN_FETCH_PERSIST_FILE;
  attr.requestData = (char *)data;
  attr.requestDataSize = numBytes;
  attr.onsuccess = success;
  attr.onerror = failure;
  emscripten_fetch(&attr, outputFilename);
}

int main() {
  // Create data
  uint8_t *data = (uint8_t*)malloc(10240);
  srand(time(NULL));
  for(int i = 0; i < 10240; ++i) data[i] = (uint8_t)rand();

  persistFileToIndexedDB("outputfile.dat", data, 10240);
}

Deleting a file from IndexedDB

Files can be cleaned up from IndexedDB by using the HTTP action verb “EM_IDB_DELETE”:

void success(emscripten_fetch_t *fetch) {
  printf("Deleting file from IDB succeeded.\n");
  emscripten_fetch_close(fetch);
}

void failure(emscripten_fetch_t *fetch) {
  printf("Deleting file from IDB failed.\n");
  emscripten_fetch_close(fetch);
}

int main() {
  emscripten_fetch_attr_init(&attr);
  strcpy(attr.requestMethod, "EM_IDB_DELETE");
  emscripten_fetch(&attr, "filename_to_delete.dat");
}

Synchronous Fetches

In some scenarios, it would be nice to be able to perform an XHR request or an IndexedDB file operation synchronously in the calling thread. This can make porting applications easier and simplify code flow by avoiding the need to pass a callback.

All types of Emscripten Fetch API operations (XHRs, IndexedDB accesses) can be performed synchronously by passing the EMSCRIPTEN_FETCH_SYNCHRONOUS flag. When this flag is passed, the calling thread will block to sleep until the fetch operation finishes. See the following example.

int main() {
  emscripten_fetch_attr_t attr;
  emscripten_fetch_attr_init(&attr);
  strcpy(attr.requestMethod, "GET");
  attr.attributes = EMSCRIPTEN_FETCH_LOAD_TO_MEMORY | EMSCRIPTEN_FETCH_SYNCHRONOUS;
  emscripten_fetch_t *fetch = emscripten_fetch(&attr, "file.dat"); // Blocks here until the operation is complete.
  if (fetch->status == 200) {
    printf("Finished downloading %llu bytes from URL %s.\n", fetch->numBytes, fetch->url);
    // The data is now available at fetch->data[0] through fetch->data[fetch->numBytes-1];
  } else {
    printf("Downloading %s failed, HTTP failure status code: %d.\n", fetch->url, fetch->status);
  }
  emscripten_fetch_close(fetch);
}

In the above code sample, the success and failure callback functions are not used. However, if specified, they will be synchronously called before emscripten_fetch() returns.

Note

Synchronous Emscripten Fetch operations are subject to a number of restrictions, depending on which Emscripten build mode (linker flags) is used:

  • No flags: Only asynchronous Fetch operations are available.
  • –proxy-to-worker: Synchronous Fetch operations are allowed for fetches that only do an XHR but do not interact with IndexedDB.
  • -s USE_PTHREADS=1: Synchronous Fetch operations are available on pthreads, but not on the main thread.
  • –proxy-to-worker + -s USE_PTHREADS=1: Synchronous Fetch operations are available both on the main thread and pthreads.

Waitable Fetches

Emscripten Fetch operations can also run in a third mode, called a waitable fetch. Waitable fetches start off as asynchronous, but at any point after the fetch has started, the calling thread can issue a wait operation to either wait for the completion of the fetch, or to just poll whether the fetch operation has yet completed. The following code sample illustrates how this works.

int main() {
  emscripten_fetch_attr_t attr;
  emscripten_fetch_attr_init(&attr);
  strcpy(attr.requestMethod, "GET");
  attr.attributes = EMSCRIPTEN_FETCH_LOAD_TO_MEMORY | EMSCRIPTEN_FETCH_WAITABLE;
  emscripten_fetch_t *fetch = emscripten_fetch(&attr, "file.dat"); // Starts as asynchronous.

  EMSCRIPTEN_RESULT ret = EMSCRIPTEN_RESULT_TIMED_OUT;
  while(ret == EMSCRIPTEN_RESULT_TIMED_OUT) {
    /* possibly do some other work; */
    ret = emscripten_fetch_wait(fetch, 0/*milliseconds to wait, 0 to just poll, INFINITY=wait until completion*/);
  }
  // The operation has finished, safe to examine the fields of the 'fetch' pointer now.

  if (fetch->status == 200) {
    printf("Finished downloading %llu bytes from URL %s.\n", fetch->numBytes, fetch->url);
    // The data is now available at fetch->data[0] through fetch->data[fetch->numBytes-1];
  } else {
    printf("Downloading %s failed, HTTP failure status code: %d.\n", fetch->url, fetch->status);
  }
  emscripten_fetch_close(fetch);
}

Waitable fetches allow interleaving multiple tasks in one thread so that the issuing thread can perform some other work until the fetch completes.

Note

Waitable fetches are available only in certain build modes:

  • No flags or –proxy-to-worker: Waitable fetches are not available.
  • -s USE_PTHREADS=1: Waitable fetches are available on pthreads, but not on the main thread.
  • –proxy-to-worker + -s USE_PTHREADS=1: Waitable fetches are available on all threads.

Tracking Progress

For robust fetch management, there are several fields available to track the status of an XHR.

The onprogress callback is called whenever new data has been received. This allows one to measure the download speed and compute an ETA for completion. Additionally, the emscripten_fetch_t structure passes the XHR object fields readyState, status and statusText, which give information about the HTTP loading state of the request.

The emscripten_fetch_attr_t object has a timeoutMSecs field which allows specifying a timeout duration for the transfer. Additionally, emscripten_fetch_close() can be called at any time for asynchronous and waitable fetches to abort the download (this is currently broken, see #8234). The following example illustrates these fields and the onprogress handler.

void downloadProgress(emscripten_fetch_t *fetch) {
  if (fetch->totalBytes) {
    printf("Downloading %s.. %.2f%% complete.\n", fetch->url, fetch->dataOffset * 100.0 / fetch->totalBytes);
  } else {
    printf("Downloading %s.. %lld bytes complete.\n", fetch->url, fetch->dataOffset + fetch->numBytes);
  }
}

int main() {
  emscripten_fetch_attr_t attr;
  emscripten_fetch_attr_init(&attr);
  strcpy(attr.requestMethod, "GET");
  attr.attributes = EMSCRIPTEN_FETCH_LOAD_TO_MEMORY;
  attr.onsuccess = downloadSucceeded;
  attr.onprogress = downloadProgress;
  attr.onerror = downloadFailed;
  emscripten_fetch(&attr, "myfile.dat");
}

Managing Large Files

Particular attention should be paid to the memory usage strategy of a fetch. Previous examples have all passed the EMSCRIPTEN_FETCH_LOAD_TO_MEMORY flag, which causes emscripten_fetch() to populate the downloaded file in full in memory in the onsuccess() callback. This is convenient when the whole file is to be immediately accessed afterwards, but for large files, this can be a wasteful strategy in terms of memory usage. If the file is very large, it might not even fit inside the application’s heap area.

The following subsections provide ways to manage large fetches in a memory efficient manner.

Downloading directly to IndexedDB

If an application wants to download a file for local access, but does not immediately need to use the file, e.g. when preloading data up front for later access, it is a good idea to avoid the EMSCRIPTEN_FETCH_LOAD_TO_MEMORY flag altogether, and only pass the EMSCRIPTEN_FETCH_PERSIST_FILE flag instead. This causes the fetch to download the file directly to IndexedDB, which avoids temporarily populating the file in memory after the download finishes. In this scenario, the onsuccess() handler will only report the total downloaded file size, but will not contain the data bytes to the file.

Streaming Downloads

Note: This currently only works in Firefox as it uses ‘moz-chunked-arraybuffer’.

If the application does not need random seek access to the file, but is able to process the file in a streaming manner, it can use the EMSCRIPTEN_FETCH_STREAM_DATA flag to stream through the bytes in the file as they are downloaded. If this flag is passed, the downloaded data chunks are passed into the onprogress() callback in coherent file sequential order. See the following snippet for an example.

void downloadProgress(emscripten_fetch_t *fetch) {
  printf("Downloading %s.. %.2f%%s complete. HTTP readyState: %d. HTTP status: %d.\n"
    "HTTP statusText: %s. Received chunk [%llu, %llu[\n",
    fetch->url, fetch->totalBytes > 0 ? (fetch->dataOffset + fetch->numBytes) * 100.0 / fetch->totalBytes : (fetch->dataOffset + fetch->numBytes),
    fetch->totalBytes > 0 ? "%" : " bytes",
    fetch->readyState, fetch->status, fetch->statusText,
    fetch->dataOffset, fetch->dataOffset + fetch->numBytes);

  // Process the partial data stream fetch->data[0] thru fetch->data[fetch->numBytes-1]
  // This buffer represents the file at offset fetch->dataOffset.
  for(size_t i = 0; i < fetch->numBytes; ++i)
    ; // Process fetch->data[i];
}

int main() {
  emscripten_fetch_attr_t attr;
  emscripten_fetch_attr_init(&attr);
  strcpy(attr.requestMethod, "GET");
  attr.attributes = EMSCRIPTEN_FETCH_STREAM_DATA;
  attr.onsuccess = downloadSucceeded;
  attr.onprogress = downloadProgress;
  attr.onerror = downloadFailed;
  attr.timeoutMSecs = 2*60;
  emscripten_fetch(&attr, "myfile.dat");
}

In this case, the onsuccess() handler will not receive the final file buffer at all so memory usage will remain at a minimum.

Byte Range Downloads

Large files can also be managed in smaller chunks by performing Byte Range downloads on them. This initiates an XHR or IndexedDB transfer that only fetches the desired subrange of the whole file. This is useful for example when a large package file contains multiple smaller ones at certain seek offsets, which can be dealt with separately.

TODO: Example about how to perform HTTP Byte Range Requests to obtain parts of files.

TODO To Document

Emscripten_fetch() supports the following operations as well, that need documenting:

  • Emscripten_fetch can be used to upload files to remote servers via HTTP PUT
  • Emscripten_fetch_attr_t allows setting custom HTTP request headers (e.g. for cache control)
  • Document HTTP simple auth fields in Emscripten_fetch_attr_t.
  • Document how to populate to a certain filesystem path location in IndexedB, and e.g. fopen() it via ASMFS afterwards.
  • Document overriddenMimeType attribute in Emscripten_fetch_attr_t.
  • Reference documentation of the individual fields in Emscripten_fetch_attr_t, Emscripten_fetch_t and #defines.
  • Example about loading only from IndexedDB without XHRing.
  • Example about overriding an existing file in IndexedDB with a new XHR.
  • Example how to preload a whole filesystem to IndexedDB for easy replacement of –preload-file.
  • Example how to persist content as gzipped to IndexedDB and decompress on load.
  • Example how to abort and resume partial transfers to IndexedDB.

Module object

Module is a global JavaScript object with attributes that Emscripten-generated code calls at various points in its execution.

Developers can provide an implementation of Module to control the execution of code. For example, to define how notification messages from Emscripten are displayed, developers implement the Module.print attribute.

Note

Module is also used to provide access to Emscripten API functions (for example ccall()) in a safe way. Any function or runtime method exported (using EXPORTED_FUNCTIONS for compiled functions, or EXTRA_EXPORTED_RUNTIME_METHODS for runtime methods like ccall) will be accessible on the Module object, without minification changing the name, and the optimizer will make sure to keep the function present (and not remove it as unused). See the relevant FAQ entry.

Creating the Module object

Use emcc’s pre-js option to add JavaScript code that defines (or extends) the Module object with the behaviour you need.

When generating only JavaScript (as opposed to HTML), no Module object is created by default, and the behaviour is entirely defined by the developer. For example, creating a Module object with the following code will cause all notifications from the program to be calls to alert().

var Module = {
  'print': function(text) { alert('stdout: ' + text) },
  'printErr': function(text) { alert('stderr: ' + text) }
};

Important

If you run the Closure Compiler on your code (which is optional, and can be done by --closure 1), you will need quotation marks around the properties of Module as in the example above. In addition, you need to run closure on the compiled code together with the declaration of Module — this is done automatically for a -pre-js file.

When generating HTML, Emscripten creates a Module object with default methods (see src/shell.html). In this case you should again use --pre-js, but this time you add properties to the existing Module object, for example:

Module['print'] = function(text) { alert('stdout: ' + text) };

Note that once the Module object is received by the main JavaScript file, it will look for Module[‘print’] and so forth at that time, and use them accordingly. Changing their values later may not be noticed.

Affecting execution

The following Module attributes affect code execution. Set them to customize behavior.

Module.arguments

The commandline arguments. The value of arguments contains the values returned if compiled code checks argc and argv.

Module.buffer

Allows you to provide your own ArrayBuffer or SharedArrayBuffer to use as the memory.

Note

This is only supported if -s WASM=0. See Module.wasmMemory for WebAssembly support.

Module.wasmMemory

Allows you to provide your own WebAssembly.Memory to use as the memory. The properites used to initialize the memory should match the compiler options.

For example, if you set INITIAL_MEMORY to 8MB without memory growth, then the wasmMemory you provide (if any) should have both the 'initial' and 'maximum' set to 128 (due to WASM page sizes being 64KB).

Module.locateFile

If set, this method will be called when the runtime needs to load a file, such as a .wasm WebAssembly file, .mem memory init file, or a file generated by the file packager. The function receives the relative path to the file as configured in build process and a prefix (path to the main JavaScript file’s directory), and should return the actual URL. This lets you host file packages or the .mem file etc. on a different location than the directory of the JavaScript file (which is the default expectation), for example if you want to host them on a CDN.

Note

prefix might be an empty string, if locateFile is called before we load the main JavaScript. For example, that can happen if a file package or a mememory initializer file are loaded beforehand (perhaps from the HTML, before it loads the main JavaScript).

Note

Several Module.*PrefixURL options have been deprecated in favor of locateFile, which includes memoryInitializerPrefixURL, pthreadMainPrefixURL, cdInitializerPrefixURL, filePackagePrefixURL. To update your code, for example if you used Module.memoryInitializerPrefixURL equal to "https://mycdn.com/memory-init-dir/", then you can replace that with something like:

Module['locateFile'] = function(path, prefix) {
  // if it's a mem init file, use a custom dir
  if (path.endsWith(".mem")) return "https://mycdn.com/memory-init-dir/" + path;
  // otherwise, use the default, the prefix (JS file's dir) + the path
  return prefix + path;
}
Module.logReadFiles

If set, stderr will log when any file is read.

Module.printWithColors

Controls whether Emscripten runtime libraries try to print with colors. Currently, this only affects sanitizers.

If unset, colors will be enabled if printing to a terminal with node.

If set to true, colors will always be used if possible. If set to false, colors will never be used.

Module.onAbort

If set, this function is called when abnormal program termination occurs. That can happen due to the C method abort() being called directly, or called from JavaScript, or due to a fatal problem such as being unable to fetch a necessary file during startup (like the wasm binary when running wasm), etc. After calling this function, program termination occurs (i.e., you can’t use this to try to do something else instead of stopping; there is no possibility of recovering here).

Module.onRuntimeInitialized

If set, this function is called when the runtime is fully initialized, that is, when compiled code is safe to run, which is after any asynchronous startup operations have completed (such as asynchronous WebAssembly compilation, file preloading, etc.). (An alternative to waiting for this to be called is to wait for main() to be called.)

Module.noExitRuntime

If noExitRuntime is set to true, the runtime is not shut down after run completes. Shutting down the runtime calls shutdown callbacks, for example atexit calls. If you want to continue using the code after run() finishes, it is necessary to set this. This is automatically set for you if you use an API command that implies that you want the runtime to not be shut down, for example emscripten_set_main_loop.

Module.noInitialRun

If noInitialRun is set to true, main() will not be automatically called (you can do so yourself later). The program will still call global initializers, set up memory initialization, and so forth.

Module.preInit

A function (or array of functions) that must be called before global initializers run, but after basic initialization of the JavaScript runtime. This is typically used for File System operations.

Module.preinitializedWebGLContext

If building with -s GL_PREINITIALIZED_CONTEXT=1 set, you can set Module.preinitializedWebGLContext to a precreated instance of a WebGL context, which will be used later when initializing WebGL in C/C++ side. Precreating the GL context is useful if doing GL side loading (shader compilation, texture loading etc.) parallel to other page startup actions, and/or for detecting WebGL feature support, such as GL version or compressed texture support up front on a page before or in parallel to loading up any compiled code.

Module.preRun

An array of functions to call right before calling run(), but after defining and setting up the environment, including global initializers. This is useful, for example, to set up directories and files using the File System API — as this needs to happen after the FileSystem API has been loaded, but before the program starts to run.

Note

If code needs to affect global initializers, it should instead be run using preInit.

Module.print

Called when something is printed to standard output (stdout)

Module.printErr

Called when something is printed to standard error (stderr)

Other methods

Module.destroy(obj)

This method should be called to destroy C++ objects created in JavaScript using WebIDL bindings. If this method is not called, an object may be garbage collected, but its destructor will not be called.

Arguments:
  • obj – The JavaScript-wrapped C++ object to be destroyed.
Module.getPreloadedPackage()

If you want to manually manage the download of .data file packages for custom caching, progress reporting and error handling behavior, you can implement the Module.getPreloadedPackage = function(remotePackageName, remotePackageSize) callback to provide the contents of the data files back to the file loading scripts. The return value of this callback should be an Arraybuffer with the contents of the downloade file data. See file tests/manual_download_data.html and the test browser.test_preload_file_with_manual_data_download for an example.

Module.instantiateWasm()

When targeting WebAssembly, Module.instantiateWasm is an optional user-implemented callback function that the Emscripten runtime calls to perform the WebAssembly instantiation action. The callback function will be called with two parameters, imports and successCallback. imports is a JS object which contains all the function imports that need to be passed to the WebAssembly Module when instantiating, and once instantiated, this callback function should call successCallback() with the generated WebAssembly Instance object.

The instantiation can be performed either synchronously or asynchronously. The return value of this function should contain the exports object of the instantiated WebAssembly Module, or an empty dictionary object {} if the instantiation is performed asynchronously, or false if instantiation failed.

Overriding the WebAssembly instantiation procedure via this function is useful when you have other custom asynchronous startup actions or downloads that can be performed in parallel to WebAssembly compilation. Implementing this callback allows performing all of these in parallel. See the file tests/manual_wasm_instantiate.html and the test browser.test_manual_wasm_instantiate for an example of how this construct works in action.

Note

Sanitizers or source map is currently not supported if overriding WebAssembly instantiation with Module.instantiateWasm. Providing Module.instantiateWasm when source map or sanitizer is enabled can prevent WebAssembly instantiation from finishing.

Module.onCustomMessage()

When compiled with PROXY_TO_WORKER = 1 (see settings.js), this callback (which should be implemented on both the client and worker’s Module object) allows sending custom messages and data between the web worker and the main thread (using the postCustomMessage function defined in proxyClient.js and proxyWorker.js).

val.h (under-construction)

The Embind C++ class emscripten::val (defined in val.h) is used to transliterate JavaScript code to C++.

Guide material for this class can be found in Using val to transliterate JavaScript to C++.

class emscripten::val

This class is a C++ data type that can be used to represent (and provide convenient access to) any JavaScript object. You can use it to call a JavaScript object, read and write its properties, or coerce it to a C++ value like a bool, int, or std::string.

For example, the code below shows some simple JavaScript for making an XHR request on a URL:

var xhr = new XMLHttpRequest;
xhr.open("GET", "http://url");

This same code can be written in C++, using global() to get the symbol for the global XMLHttpRequest object and then using it to open a URL.

val xhr = val::global("XMLHttpRequest").new_();
xhr.call("open", std::string("GET"), std::string("http://url"));

You can test whether the open method call was successful using operator[]() to read an object property, then as() to coerce the type:

const char* state;
switch (xhr["readyState"].as<int>()) {
case 0:
  state = "UNSENT"; break;
case 1:
  state = "OPENED"; break;
default:
  state = "etc";
}

See Using val to transliterate JavaScript to C++ for other examples.

static val array()

Creates and returns a new Array.

Returns:The new Array.
static val object()

Creates and returns a new Object.

Returns:The new Object.
static val undefined()

Creates a val that represents undefined.

Returns:The val that represents undefined.
static val null()

Creates a val that represents null. val::undefined() is the same, but for undefined.

Returns:A val that represents null.
static val take_ownership(internal::EM_VAL e)

HamishW-Replace with description.

Returns:HamishW-Replace with description.
static val global(const char *name)

Looks up a global symbol.

Parameters:const char* nameHamishW-Replace with description.
Returns:HamishW-Replace with description.
static val module_property(const char *name)

Looks up a symbol on the emscripten Module object.

Parameters:const char* nameHamishW-Replace with description.
Returns:HamishW-Replace with description.
explicit val(T &&value)

Constructor.

A val can be constructed by explicit construction from any C++ type. For example, val(true) or val(std::string("foo")).

Parameters:T&& value – Any C++ type.

HamishW Don’t know how following “floating statement works”. Leaving here for discussion val() = delete;

explicit val(const char *v)

HamishW-Replace with description.

Parameters:const char* vHamishW-Replace with description.
val(val &&v)

HamishW-Replace with description.

Parameters:val&& vHamishW-Replace with description.
val(const val &v)

HamishW-Replace with description.

Parameters:const val& vHamishW-Replace with description.
~val()

Destructor. HamishW-Replace with further description or delete comment.

val &operator=(val &&v)

HamishW-Replace with description.

Parameters:val&& vHamishW-Replace with description.
Returns:HamishW-Replace with description.
val &operator=(const val &v)

HamishW-Replace with description.

Parameters:val&& vHamishW-Replace with description.
Returns:HamishW-Replace with description.
bool hasOwnProperty(const char *key) const

Test whether … HamishW-Replace with description.

Parameters:const char* keyHamishW-Replace with description.
Returns:HamishW-Replace with description.
val new_()

prototype:

template<typename... Args>
val new_(Args&&... args) const

HamishW-Replace with description.

Parameters:Args&&... argsHamishW-Replace with description. Note that this is a templated value.
Returns:HamishW-Replace with description.
val operator[](const T &key) const

HamishW-Replace with description.

Parameters:const T& keyHamishW-Replace with description. Note that this is a templated value.
Returns:HamishW-Replace with description.
void set(const K &key, const val &v)

Set the specified (key) property of a JavaScript object (accessed through a val) with the value v. HamishW-Replace with description.

Parameters:
  • const K& keyHamishW-Replace with description. Note that this is a templated value.
  • const val& vHamishW-Replace with description. Note that this is a templated value.
val operator()(Args&&... args)

HamishW-Replace with description.

Parameters:Args&&... argsHamishW-Replace with description. Note that this is a templated value.
ReturnValue call(const char *name, Args&&... args) const

HamishW-Replace with description.

Parameters:
  • const char* nameHamishW-Replace with description.
  • Args&&... argsHamishW-Replace with description. Note that this is a templated value.
T as() const

HamishW-Replace with description.

Returns:HamishW-Replace with description. Note that this is a templated value.
val typeof() const

HamishW-Replace with description.

Returns:HamishW-Replace with description.
std::vector<T> vecFromJSArray(val v)

HamishW-Replace with description.

HamishW. I believe NOT internal. Please confirm.

Parameters:val vHamishW-Replace with description.
Returns:HamishW-Replace with description.

bind.h (under-construction)

The C++ APIs in bind.h define

Guide documentation for this API can be found in Embind.

How to use this API

Defines

EMSCRIPTEN_BINDINGS(name)

This define is used to bind C++ classes, functions and other constructs to JavaScript. It is used differently depending on the construct being mapped — see the embind guide for examples.

Parameters:name – This is a label to mark a group of related bindings (for example EMSCRIPTEN_BINDINGS(physics), EMSCRIPTEN_BINDINGS(components), etc.)
type sharing_policy
type sharing_policy::NONE
type sharing_policy::INTRUSIVE
type sharing_policy::BY_EMVAL

Policies

Currently only allow_raw_pointers policy is supported. Eventually we hope to implement Boost.Python-like raw pointer policies for managing object ownership.

type arg
static int index
// Prototype
static constexpr int index
type ret_val
static int index
// Prototype
static constexpr int index
type allow_raw_pointers

This policy is used to whitelist raw pointers.

type Transform::type
type allow_raw_pointer

select_overload and select_const

typename std::add_pointer<Signature>::type select_overload(typename std::add_pointer<Signature>::type fn)
// Prototype
template<typename Signature>
typename std::add_pointer<Signature>::type select_overload(typename std::add_pointer<Signature>::type fn)

:param typename std::add_pointer<Signature>::type fn

typename internal::MemberFunctionType<ClassType, Signature>::type select_overload()
// Prototype
template<typename Signature, typename ClassType>
typename internal::MemberFunctionType<ClassType, Signature>::type select_overload(Signature (ClassType::*fn))

:param Signature (ClassType::*fn)

auto select_const()
// Prototype
template<typename ClassType, typename ReturnType, typename... Args>
auto select_const(ReturnType (ClassType::*method)(Args...) const)

:param ReturnType (ClassType::*method)(Args…) const

typename internal::CalculateLambdaSignature<LambdaType>::type optional_override(const LambdaType &fp)
// Prototype
template<typename LambdaType>
typename internal::CalculateLambdaSignature<LambdaType>::type optional_override(const LambdaType& fp)

:param const LambdaType& fp

Functions

void *__getDynamicPointerType(void *p)

:param void* p

void function()
//prototype
template<typename ReturnType, typename... Args, typename... Policies>
void function(const char* name, ReturnType (*fn)(Args...), Policies...)

Registers a function to export to JavaScript. This is called from within an EMSCRIPTEN_BINDINGS() block.

For example to export the function lerp()

// quick_example.cpp
#include <emscripten/bind.h>

using namespace emscripten;

float lerp(float a, float b, float t) {
   return (1 - t) * a + t * b;
}

EMSCRIPTEN_BINDINGS(my_module) {
   function("lerp", &lerp);
}
Parameters:
  • const char* name – The name of the function to export (e.g. "lerp").
  • ReturnType (*fn)(Args...) – Function pointer address for the exported function (e.g. &lerp).
  • Policies...Policy for managing raw pointer object ownership. Currently must be allow_raw_pointers.

Value tuples

class value_array : public internal::noncopyable
type class_type

A typedef of ClassType, the typename of the templated type for the class.

value_array(const char *name)

Constructor.

:param const char* name

~value_array()

Destructor.

value_array &element(ElementType InstanceType::*field)
Parameters:ElementType InstanceType::*field – Note that ElementType and InstanceType are typenames (templated types).
value_array &element(Getter getter, Setter setter)

:param Getter getter. Note that Getter is a typename (templated type). :param Setter setter. Note that Setter is a typename (templated type).

value_array &element(index<Index>)

:param index<Index>:Note that Index is an integer template parameter.

Value structs

class value_object : public internal::noncopyable
type class_type

A typedef of ClassType, the typename of the templated type for the class.

value_object(const char *name)

Constructor.

:param const char* name

~value_object()

Destructor.

value_object &field(const char *fieldName, FieldType InstanceType::*field)

:param const char* fieldName. :param FieldType InstanceType::*field.

value_object &field(const char *fieldName, Getter getter, Setter setter)

:param const char* fieldName. :param Getter getter. Note that Getter is a typename (templated type). :param Setter setter. Note that Setter is a typename (templated type).

value_object &field(const char *fieldName, index<Index>)

:param const char* fieldName. :param index<Index>. Note that Index is an integer template parameter.

Smart pointers

type default_smart_ptr_trait
//prototype
template<typename PointerType>
struct default_smart_ptr_trait
static sharing_policy get_sharing_policy()
static void *share(void *v)

:param void* v

static PointerType *construct_null()
Returns:Note that the PointerType returned is a typename (templated type).
type smart_ptr_trait
//prototype
template<typename PointerType>
struct smart_ptr_trait : public default_smart_ptr_trait<PointerType>
typedef PointerType::element_type element_type
//prototype
typedef typename PointerType::element_type element_type;

A typedef for the PointerType::element_type, where PointerType is a typename (templated type).

static element_type *get(const PointerType &ptr)
Parameters:const PointerType& ptr – Note that PointerType is a typename (templated type)
template<typename PointeeType>
using smart_ptr_trait<std::shared_ptr<PointeeType>>
//prototype
template<typename PointeeType>
struct smart_ptr_trait<std::shared_ptr<PointeeType>>
type PointerType

A typedef to std::shared_ptr<PointeeType>, where PointeeType is a typename (templated type).

type element_type

A typedef for the PointerType::element_type.

static element_type *get(const PointerType &ptr)

:param const PointerType& ptr

static sharing_policy get_sharing_policy()
static std::shared_ptr<PointeeType> *share(PointeeType *p, internal::EM_VAL v)
Parameters:
  • PointeeType* p – Note that PointeeType is a typename (templated type).
  • internal::EM_VAL v
static PointerType *construct_null()

Classes

class wrapper : public T, public internal::WrapperBase
//prototype
template<typename T>
class wrapper : public T, public internal::WrapperBase
type class_type

A typedef of T, the typename of the templated type for the class.

wrapper(val &&wrapped, Args&&... args)
//prototype
template<typename... Args>
explicit wrapper(val&& wrapped, Args&&... args)
  : T(std::forward<Args>(args)...)
  , wrapped(std::forward<val>(wrapped))

Constructor.

:param val&& wrapped :param Args&&… args: Note that Args is a typename (templated type).

~wrapper()

Destructor.

ReturnType call(const char *name, Args&&... args) const

Constructor.

:param const char* name :param Args&&… args: Note that Args is a typename (templated type). :returns: Note that ReturnType is a typename (templated type).

EMSCRIPTEN_WRAPPER(T)

:param T

type base
type class_type

A typedef of BaseClass, the typename of the templated type for the class.

static void verify()

Note, is templated function which takes typename ClassType.

static internal::TYPEID get()
template<typename ClassType>
using Upcaster = BaseClass* (*)(ClassType*);

template<typename ClassType>
using Downcaster = ClassType* (*)(BaseClass*);
static Upcaster<ClassType> getUpcaster()
//prototype
template<typename ClassType>
static Upcaster<ClassType> getUpcaster()
static Downcaster<ClassType> getDowncaster()
//prototype
template<typename ClassType>
static Downcaster<ClassType> getDowncaster()
static To *convertPointer(From *ptr)
//prototype
template<typename From, typename To>
static To* convertPointer(From* ptr)

:param From* ptr

type pure_virtual
type Transform

Note that this is a templated struct taking typename parameter InputType and integer Index.

type type

This is a typdef to the parent struct typename parameter InputType.

type constructor

Note that this is a template struct taking typename ... ConstructorArgs.

class class_

Note that this is a templated class with typename parameters ClassType and BaseSpecifier.

type class_type

A typedef of ClassType (a typename for the class).

type base_specifier

A typedef of BaseSpecifier (a typename for the class).

type HELPNEEDEDHERE
class_() = delete;
explicit class_(const char *name)
//prototype
EMSCRIPTEN_ALWAYS_INLINE explicit class_(const char* name)

Constructor.

:param const char* name

const class_ &smart_ptr(const char *name) const
//prototype
template<typename PointerType>
EMSCRIPTEN_ALWAYS_INLINE const class_& smart_ptr(const char* name) const

:param const char* name. :returns: A const reference to the current object. This allows chaining of the class_ functions that define the binding in the EMSCRIPTEN_BINDINGS() block.

const class_ &constructor() const
//prototype
template<typename... ConstructorArgs, typename... Policies>
EMSCRIPTEN_ALWAYS_INLINE const class_& constructor(Policies... policies) const

Zero-argument form of the class constructor. This invokes the natural constructor with the arguments specified in the template. See External constructors for more information.

Parameters:Policies... policiesPolicy for managing raw pointer object ownership. Currently must be allow_raw_pointers.
Returns:A const reference to the current object. This allows chaining of the class_ functions that define the binding in the EMSCRIPTEN_BINDINGS() block.
const class_ &constructor(Callable callable, Policies...) const
//prototype
template<typename Signature = internal::DeduceArgumentsTag, typename Callable, typename... Policies>
EMSCRIPTEN_ALWAYS_INLINE const class_& constructor(Callable callable, Policies...) const

Class constructor for objects that use a factory function to create the object. This method will accept either a function pointer, std::function object or function object which will return a newly constructed object. When the Callable is a function object the function signature must be explicitly specified in the Signature template parameter in the format ReturnType (Args...). For Callable types other than function objects the method signature will be deduced.

The following are all valid calls to constructor:

using namespace std::placeholders;
myClass1.constructor(&my_factory);
myClass2.constructor(std::function<ClassType2(float, float)>(&class2_factory));
myClass3.constructor<ClassType3(const val&)>(std::bind(Class3Functor(), _1));

See External constructors for more information.

:param Callable callable Note that Callable may be either a member function pointer, function pointer, std::function or function object. :param Policies… policies: Policy for managing raw pointer object ownership. Currently must be allow_raw_pointers. :returns: A const reference to the current object. This allows chaining of the class_ functions that define the binding in the EMSCRIPTEN_BINDINGS() block.

const class_ &smart_ptr_constructor() const
//prototype
template<typename SmartPtr, typename... Args, typename... Policies>
EMSCRIPTEN_ALWAYS_INLINE const class_& smart_ptr_constructor(const char* smartPtrName, SmartPtr (*factory)(Args...), Policies...) const

:param const char* smartPtrName :param SmartPtr (*factory)(Args…) :param Policies… policies: Policy for managing raw pointer object ownership. Currently must be allow_raw_pointers. :returns: A const reference to the current object. This allows chaining of the class_ functions that define the binding in the EMSCRIPTEN_BINDINGS() block.

const class_ &allow_subclass() const
//prototype
 template<typename WrapperType, typename PointerType, typename... ConstructorArgs>
EMSCRIPTEN_ALWAYS_INLINE const class_& allow_subclass(
  const char* wrapperClassName,
  const char* pointerName,
  ::emscripten::constructor<ConstructorArgs...> = ::emscripten::constructor<>()
) const

:param const char* wrapperClassName :param const char* pointerName :param emscripten::constructor<ConstructorArgs…> constructor) :returns: A const reference to the current object. This allows chaining of the class_ functions that define the binding in the EMSCRIPTEN_BINDINGS() block.

const class_ &allow_subclass(const char *wrapperClassName, emscripten::constructor<ConstructorArgs...> constructor) const
//prototype
template<typename WrapperType, typename... ConstructorArgs>
EMSCRIPTEN_ALWAYS_INLINE const class_& allow_subclass(
  const char* wrapperClassName,
  ::emscripten::constructor<ConstructorArgs...> constructor = ::emscripten::constructor<>()
) const

:param const char* wrapperClassName :param ::emscripten::constructor<ConstructorArgs…> constructor)

Returns:A const reference to the current object. This allows chaining of the class_ functions that define the binding in the EMSCRIPTEN_BINDINGS() block.
const class_ &function() const
//prototype
template<typename Signature = internal::DeduceArgumentsTag, typename Callable, typename... Policies>
EMSCRIPTEN_ALWAYS_INLINE const class_& function(const char* methodName, Callable callable, Policies...) const

This method is for declaring a method belonging to a class.

On the JavaScript side this is a function that gets bound as a property of the prototype. For example .function("myClassMember", &MyClass::myClassMember) would bind myClassMember to MyClass.prototype.myClassMember in the JavaScript. This method will accept either a pointer-to-member-function, function pointer, std::function object or function object. When the Callable is not a pointer-to-member-function it must accept the ClassType as the first (this) parameter. When the Callable is a function object the function signature must be explicitly specified in the Signature template parameter in the format ReturnType (Args...). For Callable types other than function objects the method signature will be deduced.

The following are all valid calls to function:

using namespace std::placeholders;
myClass.function("myClassMember", &MyClass::myClassMember)
    .function("myFreeFunction", &my_free_function)
    .function("myStdFunction", std::function<float(ClassType&, float, float)>(&my_function))
    .function<val(const MyClass&)>("myFunctor", std::bind(&my_functor_taking_this, _1));

:param const char* methodName :param Callable callable Note that Callable may be either a member function pointer, function pointer, std::function or function object. :param typename… Policies: Policy for managing raw pointer object ownership. Currently must be allow_raw_pointers. :returns: A const reference to the current object. This allows chaining of the class_ functions that define the binding in the EMSCRIPTEN_BINDINGS() block.

const class_ &property() const
//prototype
template<typename FieldType, typename = typename std::enable_if<!std::is_function<FieldType>::value>::type>
EMSCRIPTEN_ALWAYS_INLINE const class_& property(const char* fieldName, const FieldType ClassType::*field) const

:param const char* fieldName :param const FieldType ClassType::*field

Returns:A const reference to the current object. This allows chaining of the class_ functions that define the binding in the EMSCRIPTEN_BINDINGS() block.
const class_ &property(const char *fieldName, FieldType ClassType::*field) const
//prototype
template<typename FieldType, typename = typename std::enable_if<!std::is_function<FieldType>::value>::type>
EMSCRIPTEN_ALWAYS_INLINE const class_& property(const char* fieldName, FieldType ClassType::*field) const

:param const char* fieldName :param FieldType ClassType::*field

Returns:A const reference to the current object. This allows chaining of the class_ functions that define the binding in the EMSCRIPTEN_BINDINGS() block.
const class_ &property(const char *fieldName, Getter getter) const
//prototype
template<typename PropertyType = internal::DeduceArgumentsTag, typename Getter>
EMSCRIPTEN_ALWAYS_INLINE const class_& property(const char* fieldName, Getter getter) const;

Declare a read-only property with the specified fieldName on the class using the specified getter to retrieve the property value. Getter may be either a class method, a function, a std::function or a function object. When Getter is not pointer-to-member-function, it must accept an instance of the ClassType as the this argument. When Getter is a function object, the property type must be specified as a template parameter as it cannot be deduced, e.g.: myClass.property<int>("myIntProperty", MyIntGetterFunctor());

:param const char* fieldName :param Getter getter Note that Getter is a function template typename. :returns: A const reference to the current object. This allows chaining of the class_ functions that define the binding in the EMSCRIPTEN_BINDINGS() block.

const class_ &property(const char *fieldName, Getter getter, Setter setter) const
//prototype
template<typename PropertyType = internal::DeduceArgumentsTag, typename Getter, typename Setter>
EMSCRIPTEN_ALWAYS_INLINE const class_& property(const char* fieldName, Getter getter, Setter setter) const

This is a function template taking typenames Setter and Getter: template<typename Getter, typename Setter> which declares a read-write property with the specified fieldName on the class. Getter and Setter may be either a class method, a function, a std::function or a function object. When Getter or Setter is not pointer-to-member-function, it must accept an instance of the ClassType as the this argument. When Getter or Setter is a function object, the property type must be specified as a template parameter as it cannot be deduced, e.g.: myClass.property<int>("myIntProperty", MyIntGetterFunctor(), MyIntSetterFunctor());

:param const char* fieldName :param Getter getter: Note that Getter is a function template typename. :param Setter setter: Note that Setter is a function template typename. :returns: A const reference to the current object. This allows chaining of the class_ functions that define the binding in the EMSCRIPTEN_BINDINGS() block.

const class_ &class_function() const
//prototype
template<typename ReturnType, typename... Args, typename... Policies>
EMSCRIPTEN_ALWAYS_INLINE const class_& class_function(const char* methodName, ReturnType (*classMethod)(Args...), Policies...) const

This method is for declaring a static function belonging to a class.

On the JavaScript side this is a function that gets bound as a property of the constructor. For example .class_function("myStaticFunction", &MyClass::myStaticFunction) binds myStaticFunction to MyClass.myStaticFunction.

:param const char* methodName :param ReturnType (*classMethod)(Args…) :param Policies…: Policy for managing raw pointer object ownership. Currently must be allow_raw_pointers. :returns: A const reference to the current object. This allows chaining of the class_ functions that define the binding in the EMSCRIPTEN_BINDINGS() block.

const class_ &class_property(const char *fieldName, FieldType *field) const
//prototype
template<typename FieldType>
EMSCRIPTEN_ALWAYS_INLINE const class_& property(const char* fieldName, FieldType *field) const

:param const char* fieldNam :param FieldType ClassType::*field

Returns:A const reference to the current object. This allows chaining of the class_ functions that define the binding in the EMSCRIPTEN_BINDINGS() block.

Vectors

class_<std::vector<T>> register_vector(const char *name)
//prototype
template<typename T>
class_<std::vector<T>> register_vector(const char* name)

A function to register a std::vector<T>.

:param const char* name

Maps

class_<std::map<K, V>> register_map(const char *name)
//prototype
template<typename K, typename V>
class_<std::map<K, V>> register_map(const char* name)

A function to register a std::map<K, V>.

:param const char* name

Enums

class enum_
//prototype
template<typename EnumType>
class enum_

Registers an enum to export to JavaScript. This is called from within an EMSCRIPTEN_BINDINGS() block and works with both C++98 enums and C++11 “enum classes”. See Enums for more information.

type enum_type

A typedef of EnumType (a typename for the class).

enum_(const char *name)

Constructor.

:param const char* name

enum_ &value(const char *name, EnumType value)

Registers an enum value.

Parameters:
  • const char* name – The name of the enumerated value.
  • EnumType value – The type of the enumerated value.
Returns:

A reference to the current object. This allows chaining of multiple enum values in the EMSCRIPTEN_BINDINGS() block.

Constants

void constant(const char *name, const ConstantType &v)
//prototype
template<typename ConstantType>
void constant(const char* name, const ConstantType& v)

Registers a constant to export to JavaScript. This is called from within an EMSCRIPTEN_BINDINGS() block.

EMSCRIPTEN_BINDINGS(my_constant_example) {
  constant("SOME_CONSTANT", SOME_CONSTANT);
}
Parameters:
  • const char* name – The name of the constant.
  • const ConstantType& v – The constant type. This can be any type known to embind.

trace.h

The Emscripten tracing API provides some useful capabilities to better see what is going on inside of your application, in particular with respect to memory usage (which is otherwise not available to traditional browser performance tools).

The tracing API can talk to a custom collection server (see Running the Server for more details) or it can talk with the Google Web Tracing Framework. When talking with the Google Web Tracing Framework, a subset of the data available is collected.

Usage

Compiler Interaction

When using the tracing API, you should pass --tracing to emcc at each compile and link stage. This will automatically include the library_trace.js library file as well as set the preprocessor flag __EMSCRIPTEN_TRACING__. If you are invoking clang directly to build your C / C++ code, then you will want to pass -D__EMSCRIPTEN_TRACING__ when building code. When the preprocessor flag __EMSCRIPTEN_TRACING__ is not defined, the tracing API implementation will be provided by inlined empty stubs.

Also, since enabling tracing modifies the implementation of dlmalloc.c in the libc implementation, it is advised that you manually clear your cache before switching to using the tracing API. If you do not do this, then you will not get full allocation details recorded. You can clear the cache with this emcc command:

emcc --clear-cache

Initialization and Teardown

To initialize the tracing API, you call emscripten_trace_configure():

emscripten_trace_configure("http://127.0.0.1:5000/", "MyApplication");

If you are simply going to use the tracing API with the Google Web Tracing Framework, then you can just call emscripten_trace_configure_for_google_wtf() instead:

emscripten_trace_configure_for_google_wtf();

If you have the concept of a username or have some other way to identify a given user of the application, then passing that to the tracing API can make it easier to identify sessions in the collector server:

emscripten_trace_set_session_username(username);

To shut it down at application exit, you simply call emscripten_trace_close():

emscripten_trace_close();

Contexts

Contexts are a way to tell the tracing API what part of your application is currently running. Contexts are effectively maintained as a stack of current contexts.

A context might be something as big as “running physics” or as small as “updating animations on entity X”.

The granularity of the context stack is up to the team instrumenting their application. Some applications may find fine-grained contexts more useful, while others are more comfortable with larger contexts.

Rather than getting a stack trace on every tracing call, we can often look at the current context stack and record that instead, which is much cheaper.

When contexts are fully implemented by the server, they will also be used to track how much time is spent in each context (a primitive profiling mechanism), as well as how much memory has been allocated and freed while the context was active. This should help give a good idea of which parts of your application are using more memory or creating a lot of churn (and possibly heap fragmentation).

Recording context entry and exit is simple:

emscripten_trace_enter_context("Physics Update");
...
emscripten_trace_exit_context();

Frames

It is important to record where your frame or event loop begins and ends. This allows the tracing API to perform useful additional analysis.

Noting the start of an event loop is as easy as:

emscripten_trace_record_frame_start();

And noting the end of the event loop is just as easy:

emscripten_trace_record_frame_end();

Annotating Allocations

Each allocation and free operation should be recorded. Ideally, the data type name will also be recorded, but this must currently be done manually.

When building with --tracing and a cleared cache, the libc that Emscripten builds will automatically record all calls to malloc, realloc and free.

As for recording the data type name, after you’ve allocated the memory, you can annotate the address:

emscripten_trace_annotate_address_type(model, "UI::Model");

Additionally, some applications may want to associate the size of additional storage with an allocation. This can be done via emscripten_trace_associate_storage_size():

emscripten_trace_associate_storage_size(mesh, mesh->GetTotalMemoryUsage());

Overall Memory Usage

Periodically, the overall heap layout and memory usage should be reported to the trace API.

This is done with 2 calls:

emscripten_trace_report_memory_layout();
emscripten_trace_report_off_heap_data();

Logging Messages

Messages can be logged and recorded via the Emscripten tracing API. These messages can have both a channel and the actual message. The channel name will help to categorize and filter messages within the visualization interface. You should avoid allocating memory on the heap while logging a message.

emscripten_trace_log_message("Application", "Started");

Over time, the visualization interface will improve to help you better correlate these log messages with other views, such as memory usage over time. Logging messages for things that may cause large amounts of memory activity, like loading a new model or game asset, is very useful when analyzing memory usage behavior patterns.

Tasks

Specific tasks can be recorded and analyzed. A task is typically a unit of work that is not repeating. It may be suspended or blocked due to having portions performed asynchronously.

An example of a task is loading an asset which usually involves chains of callbacks.

The application should keep track of task IDs (integers) and ensure that they are unique.

The task ID need not be passed to every trace call involving tasks as most calls operate on the current task.

Tasks can be started and stopped with:

emscripten_trace_task_start(taskID, name);
emscripten_trace_task_end();

If a task is suspended / blocked, this can be noted via:

emscripten_trace_task_suspend("loading via HTTP");

And when it is resumed:

emscripten_trace_task_resume(taskID, "parsing");

It is common to need to associate additional data with the current task for use when examining task data later. An example of this would be the URL of an asset that was loaded:

emscripten_trace_task_associate_data("url", url);

Reporting Errors

Errors encountered by the application can be reported to the tracing API as an ancillary service:

emscripten_trace_report_error("Assertion failed: ...");

This feature is included as an indication of the future direction of the Emscripten tracing API.

Running the Server

Design Notes

Client / Server Design

The Emscripten tracing API gathers data from instrumented code and transmits it to a collector server. The server also performs data analysis and provides a web interface for viewing the collected data.

This client / server design is intended to allow the tool to run without interfering with the browser on lower-end hardware where memory might be at a premium, like 32 bit Windows machines.

This design also allows for a single server to be run to collect data from a variety of clients.

Data Batching

Data is batched and sent to the server in chunks, roughly once or twice per second. This avoids having to open a new connection to the server for every single event being recorded.

Do Not Perturb The Heap

When using the Emscripten tracing API, you should be careful that you do not perform operations that would perturb the heap. For example, you shouldn’t allocate a string to pass to emscripten_trace_log_message() as that would result in the allocation being tracked and possibly disturbing the behavior or results that you are trying to analyze.

For this reason, the Emscripten tracing API also keeps all of its own data off of the Emscripten heap and performs no writes to the Emscripten heap.

Functions

void emscripten_trace_configure(const char *collector_url, const char *application)
Parameters:
  • collector_url (const char*) – The base URL for the collector server.
  • application (const char*) – The name of the application being traced.
Return type:

void

Configure the connection to the collector server.

This should be one of the very first things that is done after the application has started.

In most cases, the collector_url will be http://127.0.0.1:5000/.

void emscripten_trace_configure_for_google_wtf(void)
Return type:void

Configure tracing to communicate with the Google Web Tracing Framework.

Not all features of the tracing are available within the Google WTF tools. (Currently, only contexts, log messages and marks.)

void emscripten_trace_set_enabled(bool enabled)
Parameters:
  • enabled (bool) – Whether or not tracing is enabled.
Return type:

void

Set whether or not tracing is enabled. Using this option to disable tracing will likely result in inaccurate data being collected about memory usage.

void emscripten_trace_set_session_username(const char *username)
Parameters:
  • username (const char*) – The username of the person running the application.
Return type:

void

This is useful when a collector server is being used by multiple people and you want to be able to identify individual sessions by a means other than their timestamped session ID.

This can be set after tracing has already started, so it is fine to set this after the user has gone through a login or authentication process.

void emscripten_trace_record_frame_start(void)
Return type:void

This should be called at the start of the frame / event loop.

The current timestamp is associated with this data.

The server uses this to track frame times (and therefore frames per second), as well as accounting for memory operations that happen during the frame processing.

void emscripten_trace_record_frame_end(void)
Return type:void

This should be called at the end of the frame / event loop.

The current timestamp is associated with this data.

The server uses this to stop accruing memory operations and elapsed time to the frame.

void emscripten_trace_log_message(const char *channel, const char *message)
Parameters:
  • channel (const char*) – The category of the timeline event being emitted.
  • message (const char*) – The description for the timeline event being emitted.
Return type:

void

Record a log message. This is useful for noting events or actions which have occurred which might be advantageous to have correlated against memory usage or changes in frame rate.

The current timestamp is associated with this data.

The server doesn’t yet do enough with this data. This will improve in the future.

void emscripten_trace_mark(const char *message)
Parameters:
  • message (const char *) – The name of the mark begin emitted.
Return type:

void

Record a mark in the timeline. This is primary for use with the Google Web Tracing Framework.

The current timestamp is associated with this data.

void emscripten_trace_report_error(const char *error)
Parameters:
  • error (const char*) – The error message being reported.
Return type:

void

The API will obtain the current callstack and include that in the report to the server.

The current timestamp is associated with this data.

This could be used for various things including capturing JavaScript and web-worker errors, as well as failed assertions or other run-time errors from within the C/C++ code.

void emscripten_trace_record_allocation(const void *address, int32_t size)
Parameters:
  • address (const void*) – Memory address which has been allocated.
  • size (int32_t) – Size of the memory block allocated.
Return type:

void

This must be called for each and every memory allocation. The best place to do this is within the dlmalloc implementation in Emscripten.

The current timestamp is associated with this data.

void emscripten_trace_record_reallocation(const void *old_address, const void *new_address, int32_t size)
Parameters:
  • old_address (const void*) – Old address of the memory block which has been reallocated.
  • new_address (const void*) – New address of the memory block which has been reallocated.
  • size (int32_t) – New size of the memory block reallocated.
Return type:

void

This must be called for each and every memory re-allocation. The best place to do this is within the dlmalloc implementation in Emscripten.

The current timestamp is associated with this data.

void emscripten_trace_record_free(const void *address)
Parameters:
  • address (const void*) – Memory address which is being freed.
Return type:

void

This must be called for each and every free operation. The best place to do this is within the dlmalloc implementation in Emscripten.

The current timestamp is associated with this data.

It is also important that this not be called multiple times for a single free operation.

void emscripten_trace_annotate_address_type(const void *address, const char *type)
Parameters:
  • address (const void*) – Memory address which should be annotated.
  • type (const char*) – The name of the data type being allocated.
Return type:

void

Annotate an address with the name of the data type that is stored there. This is used by the server to help breakdown what is in memory.

void emscripten_trace_associate_storage_size(const void *address, int32_t size)
Parameters:
  • address (const void*) – Memory address which should be annotated.
  • size (int32_t) – Size of the memory associated with this allocation.
Return type:

void

Associate an amount of additional storage with this address. This does not represent the size of the allocation itself, but rather associated memory that should be taken into account when looking at the size of this object.

This associated storage is application specific in nature.

An example is when an object contains a vector or string, you may want to be aware of that when analyzing memory usage and this provides a way to let the server be aware of that additional storage.

void emscripten_trace_report_memory_layout(void)
Return type:void

This should be called periodically to report the usage of the normal Emscripten heap. This provides details of both the stack and the dynamic memory usage as well as the total memory size.

The current timestamp is associated with this data.

void emscripten_trace_report_off_heap_data(void)
Return type:void

This should be called periodically to report memory usage that is not part of the normal Emscripten heap. This is currently used to report OpenAL memory usage.

The current timestamp is associated with this data.

The server does not yet display this data.

void emscripten_trace_enter_context(const char *name)
Parameters:
  • name (const char*) – Context name.
Return type:

void

The current timestamp is associated with this data.

void emscripten_trace_exit_context(void)
Return type:void

The current timestamp is associated with this data.

void emscripten_trace_task_start(int task_id, const char *name);
Parameters:
  • task_id (int) – Task ID
  • name (const char*) – Task name
Return type:

void

A task is initiated. The task ID should be unique over the lifetime of the application. It should be managed / tracked by the application.

The current timestamp is associated with this data.

void emscripten_trace_task_associate_data(const char *key, const char *value);
Parameters:
  • key (const char*) – Key
  • value (const char*) – Value
Return type:

void

Associate a key / value pair with the current task.

void emscripten_trace_task_suspend(const char *explanation);
Parameters:
  • explanation (const char*) – Why the task is suspending.
Return type:

void

The current task is suspended.

The explanation should indicate why the task is being suspended so that this information can be made available when viewing the task’s history.

The current timestamp is associated with this data.

void emscripten_trace_task_resume(int task_id, const char *explanation);
Parameters:
  • task_id (int) – Task ID
  • explanation (const char*) – Why the task is being resumed.
Return type:

void

The task identified by task_id is resumed and made the current task.

The explanation should indicate what the task is being resumed to do so that this information can be made available when viewing the task’s history.

The current timestamp is associated with this data.

void emscripten_trace_task_end(void);
Return type:void

The current task is ended.

The current timestamp is associated with this data.

void emscripten_trace_close(void)
Return type:void

This should be closed during application termination. It helps ensure is flushed to the server and terminates the tracing code.

vr.h

The C APIs in vr.h provide basic interfaces for interacting with WebVR from Emscripten.

Test/Example code

The vr test code demonstrates how to use this API:

Functions

Initialization

int emscripten_vr_init(em_vr_arg_callback_func callback, void* userData)

Initialize the emscripten VR API. This will navigator.getVRDisplays() and when completed, set the return of emscripten_vr_ready() to be true.

Parameters:
  • callback (em_vr_callback_arg_func) – C function to call when initialization is complete. The function signature must have a void* parameter for passing the arg value.
  • arg (void*) – User-defined data passed to the callback, untouched by the API itself.
Returns:

1 on success, 0 if the browsers WebVR support is insufficient.

Return type:

int

Tip

This call succeeding is not sufficient for use of the rest of the API. Please make sure to wait until the callback is executed.

int emscripten_vr_ready()

Check whether the VR API has finished initializing VR displays. See also emscripten_vr_init().

This function may return 1 event if WebVR is not supported in the running browser.

Returns:1 if ready, 0 otherwise.
int emscripten_vr_deinit()

Deinitialize the emscripten VR API. This will free all memory allocated for display name strings.

Returns:1 on success.
Return type:int

API Queries

All of the following functions require emscripten_vr_init() to have been called but do not require VR displays and can therefore be called before the return value of emscripten_vr_ready() is true.

int emscripten_vr_version_minor()

Minor version of the WebVR API currently supported by the browser.

Returns:minor version of WebVR, or -1 if not supported or API not initialized.
Return type:int
int emscripten_vr_version_major()

Major version of the WebVR API currently supported by the browser.

Returns:major version of WebVR, or -1 if not supported or API not initialized.
Return type:int

Display Functions

All of the following functions require emscripten_vr_init() to have been called the return value of emscripten_vr_ready() to be true.

int emscripten_vr_count_displays()
Returns:Number of displays connected.
Return type:int
VRDisplayHandle emscripten_vr_get_display_handle(int displayIndex)
Parameters:
Returns:

handle for a VR display.

Return type:

VRDisplayHandle

const char* emscripten_vr_get_display_name(VRDisplayHandle handle)

Get a user-readable name which identifies the VR display. The memory for the returned string is managed by the API and will be freed on emscripten_vr_deinit().

Parameters:
  • handle (VRDisplayHandle) – a display handle.
Returns:

name of the VR display or 0 (NULL) if the handle is invalid.

Return type:

char*

bool emscripten_vr_display_connected(VRDisplayHandle handle)
Parameters:
  • handle (VRDisplayHandle) – a display handle.
Returns:

true if the display is connected, false otherwise or when the handle is invalid.

Return type:

bool

bool emscripten_vr_display_presenting(VRDisplayHandle handle)

See also emscripten_vr_request_present().

Parameters:
  • handle (VRDisplayHandle) – a display handle.
Returns:

true if the display is currently presenting, false otherwise or when the handle is invalid.

Return type:

bool

int emscripten_vr_get_display_capabilities(VRDisplayHandle handle, VRDisplayCapabilities* displayCaps)
Parameters:
  • handle (VRDisplayHandle) – a display handle.
  • displayCaps (VRDisplayCapabilities) – receives capabilities of the VR display.
Returns:

1 on success, 0 if handle was invalid.

Return type:

bool

int emscripten_vr_get_eye_parameters(VRDisplayHandle handle, VREye whichEye, VREyeParameters* eyeParams)
Parameters:
  • handle (VRDisplayHandle) – a display handle.
  • whichEye (VREye) – which eye to query parameters for.
  • eyeParam (VREyeParameters) – receives the parameters for requested eye.
Returns:

1 on success, 0 if handle was invalid.

Return type:

bool

Render Loop

In contrast to the usual emscripten main loop (see Browser Execution Environment), VR displays require their own rendering loop which is independent from the main loop. The rendering loop can be set per display and will act like a main loop with timing mode EM_TIMING_RAF until the display is requested to present, as of which it will run at the VR display’s refresh rate.

void emscripten_vr_set_display_render_loop(VRDisplayHandle handle, em_vr_callback_func callback)

Set a C function as the per frame rendering callback of a VR display.

Parameters:
  • handle (VRDisplayHandle) – a display handle.: id of the display to set the render loop for.
  • callback (em_vr_callback_func) – C function to set as per frame rendering callback.
Return type:

1 on success, 0 if handle was invalid.

Tip

There can be only one render loop function per VR display. To change the render loop function, first cancel the current loop, and then call this function to set another.

void emscripten_vr_set_display_render_loop_arg(VRDisplayHandle handle, em_vr_callback_func callback, void* arg)

Set a C function as the per frame rendering callback of a VR display.

Parameters:
  • handle (VRDisplayHandle) – a display handle.
  • callback (em_vr_callback_arg_func) – C function to set as per frame rendering callback. The function signature must have a void* parameter for passing the arg value.
  • arg (void*) – User-defined data passed to the render loop function, untouched by the API itself.
Return type:

1 on success, 0 if handle was invalid.

void emscripten_vr_cancel_display_render_loop(VRDisplayHandle handle: |display-handle-parameter-doc|)

Cancels the render loop of a VR display should there be one running for it.

See also emscripten_vr_set_display_render_loop() and emscripten_vr_set_display_render_loop_arg() for information about setting and using the render loop.

Parameters:
  • handle (VRDisplayHandle) – a display handle.
Return type:

1 on success, 0 if handle was invalid.

int emscripten_vr_get_frame_data(VRDisplayHandle handle, VRFrameData* frameData)

Get view matrix, projection matrix, timestamp and head pose for current frame. Only valid when called from within a render loop callback.

See also emscripten_vr_set_display_render_loop() and emscripten_vr_set_display_render_loop_arg() for information about setting and using the render loop.

Parameters:
  • handle (VRDisplayHandle) – a display handle.
  • frameData (VRFrameData*) – Will receive the new framedata values.
Return type:

1 on success, 0 if handle was invalid.

int emscripten_vr_submit_frame(VRDisplayHandle handle)

Submit the current state of canvases passed via VRLayerInit to emscripten_vr_request_present() to be rendered to the VR display. Only valid when called from within a render loop callback.

See also emscripten_vr_set_display_render_loop() and emscripten_vr_set_display_render_loop_arg() for information about setting and using the render loop.

Parameters:
  • handle (VRDisplayHandle) – a display handle.
Return type:

1 on success, 0 if handle was invalid.

int emscripten_vr_request_present(VRDisplayHandle handle, VRLayerInit* layerInit, int layerCount, em_vr_arg_callback_func callback, void* userData)

Request present for the VR display using canvases specified in the layerInit array. If the request is successful callback will be called with userData and the render loop will continue rendering at the refresh rate of the VR display.

Must be called from a user callback (see HTML5 API).

See the specification of VRDisplay.requestPresent for detailed information.

Parameters:
  • handle (VRDisplayHandle) – a display handle.
  • layers (VRLayerInit) – array of layers which will be rendered to.
  • layerCount (int) – number of layers in layers.
  • callback (em_vr_arg_callback_func) – optional function that will be called when the requst has succeeded.
  • userData (void*) – optional data to pass to the callback when the request succeeds. Is not modified by the API.
Return type:

1 on success, 0 if handle was invalid.

int emscripten_vr_exit_present(VRDisplayHandle handle)

Request present exit.

Parameters:
  • handle (VRDisplayHandle) – a display handle.
Return type:

1 on success, 0 if handle was invalid.

Defines

VR_EYE_LEFT
VR_EYE_RIGHT

Eye values for use with emscripten_vr_get_eye_parameters().

VR_POSE_POSITION
VR_POSE_LINEAR_VELOCITY
VR_POSE_LINEAR_ACCELERATION
VR_POSE_ORIENTATION
VR_POSE_ANGULAR_VELOCITY
VR_POSE_ANGULAR_ACCELERATION

Flags which describe which properties of a VRPose are valid.

VR_LAYER_DEFAULT_LEFT_BOUNDS
VR_LAYER_DEFAULT_RIGHT_BOUNDS

Default values to pass to VRLayerInit.

Types

VRDisplayCapabilities

Structure passed to emscripten_vr_get_display_capabilities(), maps to the WebVR VRDisplayCapabilities interface.

int32_t hasPosition
int32_t hasExternalDisplay
int32_t canPresent
unsigned long maxLayers
VRLayerInit

Structure passed to emscripten_vr_request_present(), maps to the WebVR VRLayerInit interface.

const char* source

Id of the source canvas which will be used to present to the VR display.

0 (NULL) is used to refer to Module.canvas.

float[4] leftBounds

Texture bounds of the left eye on the target canvas. Initialize with VR_LAYER_DEFAULT_LEFT_BOUNDS for default.

float[4] rightBounds

Texture bounds of the right eye on the target canvas. Initialize with VR_LAYER_DEFAULT_RIGHT_BOUNDS for default.

VRPose

Substructure of VRFrameData, maps to the WebVR VRPose interface.

VR Displays do not necessarily report all of the pose values (mobile VR devices usually only report orientation, but not position for example). To check which values are valid, the poseFlags member provides a bitmask of VR_POSE_* which has a bit set for every valid value.

VRVector3 position

Position, valid only if poseFlags & VR_POSE_POSITION != 0.

VRVector3 linearVelocity

Linear velocity, valid only if poseFlags & VR_POSE_LINEAR_VELOCITY != 0.

VRVector3 linearAcceleration

Linear acceleration, valid only if poseFlags & VR_POSE_LINEAR_ACCELERATION != 0.

VRQuaternion orientation

Orientation quaternion, valid only if poseFlags & VR_POSE_ORIENTATION != 0.

VRVector3 angularVelocity

Angular velocity, valid only if poseFlags & VR_POSE_ANGULAR_VELOCITY != 0.

VRVector3 angularAcceleration

Angular acceleration, valid only if poseFlags & VR_POSE_ANGULAR_ACCELERATION != 0.

int poseFlags

Bitmask of VR_POSE_* which determines whether the corresponding pose attributes are valid

VRFrameData

Structure passed to emscripten_vr_get_frame_data(), maps to the WebVR VRFrameData interface.

double timestamp
float[16] leftProjectionMatrix
float[16] leftViewMatrix
float[16] rightProjectionMatrix
float[16] rightViewMatrix
VRPose pose
VREyeParameters

Structure passed to emscripten_vr_get_eye_parameters(), maps to the WebVR VREyeParameters interface.

VRVector3 offset
unsigned long renderWidth
unsigned long renderHeight

Math

VRVector3

A 3-dimensional vector.

float x
float y
float z
VRQuaternion

A quaternion.

float x
float y
float z
float w

fiber.h

Fibers are light, co-operative threads of execution. The fiber.h header defines a low-level API for manipulating Fibers in Emscripten. Fibers are implemented with Asyncify, so you must link your program with -s ASYNCIFY if you intend to use them.

Fibers are intended as a building block for asynchronous control flow constructs, such as coroutines. They supersede the legacy coroutine API available in the fastcomp backend. This API is similar to, but distinct from, POSIX ucontext.

Table of Contents

API Reference

Types

emscripten_fiber_t

This structure represents a Fiber context continuation. The runtime does not keep references to these objects, they only contain information needed to perform the context switch. The switch operation updates some of the contents, however.

void *stack_base

Upper limit of the C stack region. The stack grows down, so this is the initial position of the stack pointer. Must be at least 16-byte aligned.

void *stack_limit

Lower limit of the C stack region. Must be below emscripten_fiber_t.stack_base.

void *stack_ptr

Current position of the stack pointer. Must be between emscripten_fiber_t.stack_base and emscripten_fiber_t.stack_limit.

em_arg_callback_func entry

Entry point. If not NULL, this function will be called when the fiber is switched into. Otherwise, emscripten_fiber_t.asyncify_data is used to rewind the call stack.

void *user_data

Opaque pointer, passed as-is to emscripten_fiber_t.entry.

asyncify_data_t asyncify_data

Asyncify data structure. Used to unwind and rewind the call stack when switching fibers.

asyncify_data_t
void *stack_ptr

Current position of the Asyncify stack pointer.

The Asyncify stack is distinct from the C stack. It contains the call stack as well as the state of WASM locals. Unlike the C stack, it grows up.

void *stack_limit

Upper limit of the Asyncify stack region.

int rewind_id

Opaque handle to the function that needs to be called in order to rewind the call stack. This value is only meaningful to the runtime.

Warning

Rewind IDs are currently thread-specific. This makes it impossible to resume a fiber that has been started from a different thread.

Functions

void emscripten_fiber_init(emscripten_fiber_t *fiber, em_arg_callback_func entry_func, void *entry_func_arg, void *c_stack, size_t c_stack_size, void *asyncify_stack, size_t asyncify_stack_size)

Initializes a fiber context. It can then be entered by calling emscripten_fiber_swap().

Parameters:
  • fiber (emscripten_fiber_t*) – Pointer to the fiber structure.
  • entry_func (em_arg_callback_func) – Entry point function, called when the fiber is entered for the first time.
  • entry_func_arg (void*) – Opaque pointer passed to entry_func.
  • c_stack (void*) – Pointer to memory region to use for the C stack. Must be at least 16-byte aligned. This points to the lower bound of the stack, regardless of growth direction.
  • c_stack_size (size_t) – Size of the C stack memory region, in bytes.
  • asyncify_stack (void*) – Pointer to memory region to use for the Asyncify stack. No special alignment requirements.
  • asyncify_stack_size (size_t) – Size of the Asyncify stack memory region, in bytes.

Note

If entry_func returns, the entire program will end, as if main had returned. To avoid this, you can use emscripten_fiber_swap() to jump to another fiber.

void emscripten_fiber_init_from_current_context(emscripten_fiber_t *fiber, void *asyncify_stack, size_t asyncify_stack_size)

Partially initializes a fiber based on the currently active context. This is needed in order to switch back from a fiber into the thread’s original context.

This function sets up emscripten_fiber_t.stack_base and emscripten_fiber_t.stack_limit to refer to the current stack boundaries, sets emscripten_fiber_t.entry to NULL, and makes emscripten_fiber_t.asyncify_data refer to the provided Asyncify stack memory. Other fields are not changed.

Fibers initialized by this function are not complete. They are only suitable to pass as the first argument to emscripten_fiber_swap(). Doing that completes the continuation, making it possible to switch back to the original context with another emscripten_fiber_swap(), as with a normal fiber.

Parameters:
  • fiber (emscripten_fiber_t*) – Pointer to the fiber structure.
  • asyncify_stack (void*) – Pointer to memory region to use for the Asyncify stack. No special alignment requirements.
  • asyncify_stack_size (size_t) – Size of the Asyncify stack memory region, in bytes.
void emscripten_fiber_swap(emscripten_fiber_t *old_fiber, emscripten_fiber_t *new_fiber)

Performs a fiber context switch.

Parameters:
  • old_fiber (emscripten_fiber_t*) – Fiber representing the current context. It will be partially updated, such as that switching back into it via another call to emscripten_fiber_swap() would appear to return from the original call.
  • new_fiber (emscripten_fiber_t*) – Fiber representing the target context. If the fiber has an entry point, it will be called in the new context and set to NULL. Otherwise, emscripten_fiber_t.asyncify_data is used to rewind the call stack. If the fiber is invalid or incomplete, the behavior is undefined.

Advanced APIs

This section lists APIs that are not suitable for general use, but which may be useful to developers in some circumstances. These include APIs that are difficult or complicated to use, or which are intended primarily for developers working on the Emscripten core.

settings.js

settings.js contains default values and options used in various places by the compiler.

Warning

Many settings.js options are highly brittle - certain combinations of options, and combinations of certain options used with some source code, can cause Emscripten to fail badly. This is intended for use by “advanced users”, and possibly even only people developing Emscripten itself.

The options in settings.js are normally set as command line parameters to emcc:

emcc -s OPT=VALUE

While it is possible to edit settings.js manually, this is highly discouraged. In general settings.js defines low-level options that should not be modified. Note also that the compiler changes some options depending on other settings. For example, ASSERTIONS is enabled by default, but disabled in optimized builds (-O1+).

The small number of options that developers may have cause to change should be modified when the emcc tool is invoked. For example, EXPORTED_FUNCTIONS:

./emcc tests/hello_function.cpp -o function.html -s EXPORTED_FUNCTIONS="['_int_sqrt']"

preamble.js

The following advanced APIs are documented in preamble.js.

allocate(slab, types, allocator, ptr)

This is marked as internal because it is difficult to use (it has been optimized for multiple syntaxes to save space in generated code). Normally developers should instead allocate memory using _malloc(), initialize it with setValue(), etc., but this function may be useful for advanced developers in certain cases.

Arguments:
  • slab – An array of data, or a number. If a number, then the size of the block to allocate, in bytes.
  • types – Either an array of types, one for each byte (or 0 if no type at that position), or a single type which is used for the entire block. This only matters if there is initial data - if slab is a number, then this value does not matter at all and is ignored.
  • allocator – How to allocate memory, see ALLOC_*

Advanced File System API

File System API covers the public API that will be relevant to most developers. The following functions are only needed for advanced use-cases (for example, writing a new local file system) or legacy file system compatibility.

FS.handleFSError(e)
FS.hashName(parentid, name)
FS.hashAddNode(node)
FS.hashRemoveNode(node)
FS.lookupNode(parent, name)
FS.createNode(parent, name, mode, rdev)
FS.destroyNode(node)
FS.isRoot(node)
FS.isMountpoint(node)
FS.isFIFO(node)
FS.nextfd(fd_start, fd_end)
FS.getStream(fd)
FS.createStream(stream, fd_start, fd_end)
FS.closeStream(fd)
FS.getStreamFromPtr(ptr)
FS.getPtrForStream(stream)
FS.major(dev)
FS.minor(dev)
FS.getDevice(dev)
FS.getMounts(mount)
FS.lookup(parent, name)
FS.mknod(path, mode, dev)
FS.create(path, mode)
FS.readdir(path)
FS.allocate(stream, offset, length)
FS.mmap(stream, buffer, offset, length, position, prot, flags)
FS.ioctl(stream, cmd, arg)
FS.staticInit()
FS.quit()
FS.indexedDB()
FS.DB_NAME()
FS.saveFilesToDB(paths, onload, onerror)
FS.loadFilesFromDB(paths, onload, onerror)

For advanced users only.

FS.getMode(canRead, canWrite)
FS.joinPath(parts, forceRelative)
FS.absolutePath(relative, base)
FS.standardizePath(path)
FS.findObject(path, dontResolveLastLink)
FS.analyzePath(path, dontResolveLastLink)
FS.createFolder(parent, name, canRead, canWrite)
FS.createPath(parent, path, canRead, canWrite)
FS.createFile(parent, name, properties, canRead, canWrite)
FS.createDataFile(parent, name, data, canRead, canWrite, canOwn)
FS.createDevice(parent, name, input, output)
FS.forceLoadFile(obj)

Legacy v1 compatibility functions.

There are also a small number of additional flag modes:

  • rs
  • xw
  • xw+
  • xa
  • xa+

Tools Reference

This section provides reference for the main tools in the Emscripten toolchain:

  • Emscripten Compiler Frontend (emcc) Emcc is used to call the Emscripten compiler from the command line. It is effectively a drop-in replacement for a standard compiler like gcc or clang.
  • Emscripten SDK (emsdk): Emsdk is used to perform all SDK maintenance. You can use it to download, install, activate, and remove SDKs and tools, and even to build and use the latest compiler from source on GitHub.
  • Emscripten Windows Command Prompt (emcmdprompt.bat) This prompt is used to call Emscripten from the command line on Windows. It is configured with the correct system paths and settings to point to the active Emscripten SDK/tools.

Emscripten SDK (emsdk)

** Emscripten SDK (** emsdk ) is used to perform all SDK maintenance. You only need to install the SDK once; after that emsdk can do all further updates!

With emsdk you can download, install or remove any SDK or Tool, and even use the bleeding edge versions in development on GitHub. To access the emsdk on Windows, first launch the Emscripten Command Prompt. Most operations are of the form ./emsdk command.

This document provides the command syntax, and a set of guides explaining how to perform both common and advanced maintenance operations.

Command line syntax

./emsdk [help [–old] | list | update | install <tool/sdk> | uninstall <tool/sdk> | activate <tool/sdk>]

Arguments

Command Description
list [--old] Lists all current SDKs and tools and their installation status. With the --old parameter, historical versions are also shown.
update Fetches the latest list of all available tools and SDKs (but does not install them).
install <tool/sdk> Downloads and installs the specified tool or SDK.
uninstall <tool/sdk> Removes the specified tool or SDK from the disk.
activate <tool/sdk> Sets the specified tool or SDK as the default tool in the system environment. On Linux you additionally have to enable the environment settings using source ./emsdk_env.sh, as described in “How do I change the currently active SDK version?”.
help Lists all supported commands. The same list is output if no command is specified.

Note

  • For Linux and macOS the commands are called with ./emsdk. On Windows use emsdk.

Tools and SDK targets

The <tool/sdk> given above as a command argument is one of the targets listed using ./emsdk list (or ./emsdk list --old).

Note that some of the tools and SDK names include master or incoming: these targets are used to clone and pull the very latest versions from the Emscripten incoming and master branches.

You can also specify a target of latest to grab the most current SDK.

SDK concepts

The Emscripten toolchain includes a number of different tools, including Clang, Emscripten, Java, Git, Node, etc. Emsdk is a small package manager for controlling which tools are installed, and from the set of installed tools, which are active.

The current set of available tools and SDKs are listed using ./emsdk list. These can be installed individually (./emsdk install node-0.10.17-64bit) or as a group (./emsdk install node-0.10.17-64bit java-7.45-64bit).

The SDK targets are a convenience mechanism for specifying the full set of tools used by a particular Emscripten release. For example, the two lines below are equivalent:

./emsdk install sdk-incoming-64bit
./emsdk install git-1.8.3 clang-incoming-64bit node-0.10.17-64bit python-2.7.5.3-64bit java-7.45-64bit emscripten-incoming

A particular installed SDK (or tool) can then be set as active, meaning that it will be used when Emscripten is run. The active “compiler configuration” is stored in a user-specific file (~/.emscripten), which is discussed in the next section.

Note

The different tools and SDKs managed by emsdk are stored in different directories under the root folder you specified when you first installed an SDK, grouped by tool and version.

Emscripten Compiler Configuration File (.emscripten)

The Compiler Configuration File stores the active configuration on behalf of the emsdk. The active configuration defines the specific set of tools that are used by default if Emscripten in called on the Emscripten Command Prompt.

The configuration file is named .emscripten. It is user-specific, and is located in the user’s home directory (~/.emscripten on Linux).

The file should generally not be updated directly unless you’re building Emscripten from source. Instead use the emsdk to activate specific SDKs and tools as needed (emsdk activate <tool/SDK>).

Below are typical .emscripten files created by emsdk. Note the variable names used to point to the different tools:

# .emscripten file from Windows SDK

import os
LLVM_ROOT='C:/Program Files/Emscripten/clang/e1.21.0_64bit'
NODE_JS='C:/Program Files/Emscripten/node/0.10.17_64bit/node.exe'
JAVA='C:/Program Files/Emscripten/java/7.45_64bit/bin/java.exe'
# .emscripten file from Linux SDK

import os
NODE_JS = 'nodejs'
LLVM_ROOT='/home/ubuntu/emsdk_portable/clang/fastcomp/build_incoming_64/bin'

“How to” guides

The following topics explain how to perform both common and advanced maintenance operations, ranging from installing the latest SDK through to installing your own fork from GitHub.

Note

The examples below show the commands for Linux and macOS. The commands are the same on Windows, but you need to replace ./emsdk with emsdk.

How do I just get the latest SDK?

Use the update argument to fetch the current registry of available tools, and then specify the latest install target to get the most recent SDK:

# Fetch the latest registry of available tools.
./emsdk update

# Download and install the latest SDK tools.
./emsdk install latest

# Set up the compiler configuration to point to the "latest" SDK.
./emsdk activate latest

How do I use emsdk?

Use ./emsdk help or just ./emsdk to get information about all available commands.

How do I check which versions of the SDK and tools are installed?

To get a list of all currently installed tools and SDK versions (and all available tools) run:

./emsdk list

A line will be printed for each tool and SDK that is available for installation. The text INSTALLED will be shown for each tool that has already been installed. If a tool/SDK is currently active, a star (*) will be shown next to it.

How do I install a tool/SDK version?

Use the install argument to download and install a new tool or SDK version:

./emsdk install <tool/sdk name>

For example:

./emsdk install sdk-1.38.21-64bit

Note

An installed tool is present on the local machine, but not necessarily the active environment. To make an installed SDK active, use the activate command.

How do I remove a tool or an SDK?

Use the uninstall argument to delete a given tool or SDK from the local computer:

./emsdk uninstall <tool/sdk name>

If you want to completely remove Emscripten from your system, follow the guide at Uninstalling the Emscripten SDK.

How do I check for updates to the Emscripten SDK?

First use the update command to fetch package information for all new tools and SDK versions. Then use install <tool/sdk name> to install a new version:

# Fetch the latest registry of available tools.
./emsdk update

# Download and install the specified new version.
./emsdk install <tool/sdk name>

How do I change the currently active SDK version?

Toggle between different tools and SDK versions using the activate command. This will set up ~/.emscripten to point to that particular tool:

./emsdk activate <tool/sdk name>

# On Linux and macOS, also set the environment variables.
source ./emsdk_env.sh

Note

On Linux and macOS, activate writes the required information to the configuration file, but cannot automatically set up the environment variables in the current terminal. To do this you need to call source ./emsdk_env.sh after calling activate. The use of source is a security feature of Unix shells.

On Windows, calling activate automatically sets up the required paths and environment variables.

How do I install and activate old Emscripten SDKs and tools?

Emsdk contains a history of old tools and SDKs that you can use to maintain your migration path. Use the list --old argument to get a list of archived tool and SDK versions, and install <name_of_tool> to install a specific tool:

# Get list of the old versions of the tool.
./emsdk list --old

# Install the required version.
./emsdk install <name_of_tool>

# Activate required version.
./emsdk activate <name_of_tool>

How do I track the latest Emscripten development with the SDK?

It is also possible to use the latest and greatest versions of the tools on the GitHub repositories! This allows you to obtain new features and latest fixes immediately as they are pushed to GitHub, without having to wait for release to be tagged. No GitHub account or fork of Emscripten is required.

To switch to using the latest upstream git development branch (incoming), run the following:

# Install git. Skip if the system already has it.
./emsdk install git-1.8.3

# Clone+pull the latest emscripten-core/emscripten/incoming.
./emsdk install sdk-incoming-64bit

# Set the "incoming SDK" as the active version.
./emsdk activate sdk-incoming-64bit

If you want to use the upstream stable branch master, then replace -incoming- with -master- in the commands above.

How do I use my own Emscripten GitHub fork with the SDK?

It is also possible to use your own fork of the Emscripten repository via the SDK. This is useful in the case when you want to make your own modifications to the Emscripten toolchain, but still keep using the SDK environment and tools.

The way this works is that you first install the sdk-incoming SDK as in the previous section. Then you use familiar git commands to replace this branch with the information from your own fork:

cd emscripten/incoming

# Add a git remote link to your own repository.
git remote add myremote https://github.com/mygituseraccount/emscripten.git

# Obtain the changes in your link.
git fetch myremote

# Switch the emscripten-incoming tool to use your fork.
git checkout -b myincoming --track myremote/incoming

You can switch back and forth between remotes via the git checkout command as usual.

Emscripten Compiler Frontend (emcc)

The Emscripten Compiler Frontend (emcc) is used to call the Emscripten compiler from the command line. It is effectively a drop-in replacement for a standard compiler like gcc or clang.

Command line syntax

emcc [options] file...

(Note that you will need ./emcc if you want to run emcc from your current directory.)

The input file(s) can be either source code files that Clang can handle (C or C++), LLVM bitcode in binary form, or LLVM assembly files in human-readable form.

Arguments

Most clang options will work, as will gcc options, for example:

# Display this information
emcc --help

Display compiler version information
emcc --version

To see the full list of Clang options supported on the version of Clang used by Emscripten, run clang --help.

Options that are modified or new in emcc are listed below:

-O0

No optimizations (default). This is the recommended setting for starting to port a project, as it includes various assertions.

This and other optimization settings are meaningful both during compile and during link. During compile it affects LLVM optimizations, and during link it affects final optimization of the code in Binaryen as well as optimization of the JS. (For fast incremental builds -O0 is best, while for release you should link with something higher.)

-O1
Simple optimizations. During the compile step these include LLVM -O1 optimizations. During the link step this removes various runtime assertions in JS and also runs the Binaryen optimizer (that makes link slower, so even if you compiled with a higher optimization level, you may want to link with -O0 for fast incremental builds).
-O2

Like -O1, but enables more optimizations. During link this will also enable various JavaScript optimizations.

Note

These JavaScript optimizations can reduce code size by removing things that the compiler does not see being used, in particular, parts of the runtime may be stripped if they are not exported on the Module object. The compiler is aware of code in –pre-js and –post-js, so you can safely use the runtime from there. Alternatively, you can use EXTRA_EXPORTED_RUNTIME_METHODS, see src/settings.js.

-O3

Like -O2, but with additional optimizations that may take longer to run.

Note

This is a good setting for a release build.

-Os
Like -O3, but focuses more on code size (and may make tradeoffs with speed). This can affect both wasm and JavaScript.
-Oz

Like -Os, but reduces code size even further, and may take longer to run. This can affect both wasm and JavaScript.

Note

For more tips on optimizing your code, see Optimizing Code.

-s OPTION[=VALUE]

JavaScript code generation option passed into the Emscripten compiler. For the available options, see src/settings.js.

Note

You can prefix boolean options with NO_ to reverse them. For example, -s EXIT_RUNTIME=1 is the same as -s NO_EXIT_RUNTIME=0.

Note

If no value is specifed it will default to 1.

Note

For options that are lists, you need quotation marks (“) around the list in most shells (to avoid errors being raised). Two examples are shown below:

-s RUNTIME_LINKED_LIBS="['liblib.so']"
-s "RUNTIME_LINKED_LIBS=['liblib.so']"

You can also specify that the value of an option will be read from a specified JSON-formatted file. For example, the following option sets the DEAD_FUNCTIONS option with the contents of the file at path/to/file.

-s DEAD_FUNCTIONS=@/path/to/file

Note

  • In this case the file might contain a JSON-formatted list of functions: ["_func1", "func2"].
  • The specified file path must be absolute, not relative.
-g

Preserve debug information.

  • When compiling to object files, this is the same as in Clang and gcc, it adds debug information to the object files.
  • When linking, this is equivalent to -g3.
-gseparate-dwarf[=FILENAME]
Preserve debug information, but in a separate file on the side. This is the same as -g, but the main file will contain no debug info, while debug info will be present in a file on the side (FILENAME if provided, otherwise the same as the wasm file but with suffix .debug.wasm).
-g<level>

Controls the level of debuggability. Each level builds on the previous one:

  • -g0: Make no effort to keep code debuggable.

  • -g1: When linking, preserve whitespace in JavaScript.

  • -g2: When linking, preserve function names in compiled code.

  • -g3: When compiling to object files, keep debug info, including JS whitespace, function names, and LLVM debug info if any (this is the same as -g).

  • -g4: When linking, generate a source map using LLVM debug information (which must be present in object files, i.e., they should have been compiled with -g).

    Note

    • Source maps allow you to view and debug the C/C++ source code in your browser’s debugger!
    • This debugging level may make compilation significantly slower (this is why we only do it on -g4).
--profiling
Use reasonable defaults when emitting JavaScript to make the build readable but still useful for profiling. This sets -g2 (preserve whitespace and function names) and may also enable optimizations that affect performance and otherwise might not be performed in -g2.
--profiling-funcs
Preserve function names in profiling, but otherwise minify whitespace and names as we normally do in optimized builds. This is useful if you want to look at profiler results based on function names, but do not intend to read the emitted code.
--tracing
Enable the Emscripten Tracing API.
--emit-symbol-map

Save a map file between the minified global names and the original function names. This allows you, for example, to reconstruct meaningful stack traces.

Note

This is only relevant when minifying global names, which happens in -O2 and above, and when no -g option was specified to prevent minification.

--js-opts <level>

Enables JavaScript optimizations, relevant when we generate JavaScript. Possible level values are:

  • 0: Prevent JavaScript optimizer from running.
  • 1: Use JavaScript optimizer (default).

You normally don’t need to specify this option, as -O with an optimization level will set a good value.

Note

Some options might override this flag (e.g. DEAD_FUNCTIONS, SAFE_HEAP and SPLIT_MEMORY override the value with js-opts=1), because they depend on the js-optimizer.

--llvm-opts <level>

Enables LLVM optimizations, relevant when we call the LLVM optimizer (which is done when building source files to object files / bitcode). Possible level values are:

  • 0: No LLVM optimizations (default in -O0).
  • 1: LLVM -O1 optimizations (default in -O1).
  • 2: LLVM -O2 optimizations.
  • 3: LLVM -O3 optimizations (default in -O2+).

You can also specify arbitrary LLVM options, e.g.:

--llvm-opts "['-O3', '-somethingelse']"

You normally don’t need to specify this option, as -O with an optimization level will set a good value.

--llvm-lto <level>

Enables LLVM link-time optimizations (LTO). Possible level values are:

  • 0: No LLVM LTO (default).
  • 1: LLVM LTO is performed.
  • 2: Combine all the bitcode and run LLVM opt on it using the specified --llvm-opts. This optimizes across modules, but is not the same as normal LTO.
  • 3: Does level 2 and then level 1.

Note

  • If LLVM optimizations are not run (see --llvm-opts), this setting has no effect.
  • LLVM LTO is not perfectly stable yet, and can cause code to behave incorrectly.
--closure <on>

Runs the Closure Compiler. Possible on values are:

  • 0: No closure compiler (default in -O2 and below).
  • 1: Run closure compiler. This greatly reduces the size of the support JavaScript code (everything but the WebAssembly or asm.js). Note that this increases compile time significantly.
  • 2: Run closure compiler on all the emitted code, even on asm.js output in asm.js mode. This can further reduce code size, but does prevent a significant amount of asm.js optimizations, so it is not recommended unless you want to reduce code size at all costs.

Note

  • Consider using -s MODULARIZE=1 when using closure, as it minifies globals to names that might conflict with others in the global scope. MODULARIZE puts all the output into a function (see src/settings.js).
  • Closure will minify the name of Module itself, by default! Using MODULARIZE will solve that as well. Another solution is to make sure a global variable called Module already exists before the closure-compiled code runs, because then it will reuse that variable.
  • If closure compiler hits an out-of-memory, try adjusting JAVA_HEAP_SIZE in the environment (for example, to 4096m for 4GB).
  • Closure is only run if JavaScript opts are being done (-O2 or above, or --js-opts 1).
--pre-js <file>

Specify a file whose contents are added before the emitted code and optimized together with it. Note that this might not literally be the very first thing in the JS output, for example if MODULARIZE is used (see src/settings.js). If you want that, you can just prepend to the output from emscripten; the benefit of --pre-js is that it optimizes the code with the rest of the emscripten output, which allows better dead code elimination and minification, and it should only be used for that purpose. In particular, --pre-js code should not alter the main output from emscripten in ways that could confuse the optimizer, such as using --pre-js + --post-js to put all the output in an inner function scope (see MODULARIZE for that).

–pre-js (but not –post-js) is also useful for specifying things on the Module object, as it appears before the JS looks at Module (for example, you can define Module['print'] there).

--post-js <file>
Like --pre-js, but emits a file after the emitted code.
--extern-pre-js <file>
Specify a file whose contents are prepended to the JavaScript output. This file is prepended to the final JavaScript output, after all other work has been done, including optimization, optional MODULARIZE-ation, instrumentation like SAFE_HEAP, etc. This is the same as prepending this file after emcc finishes running, and is just a convenient way to do that. (For comparison, --pre-js and --post-js optimize the code together with everything else, keep it in the same scope if running MODULARIZE, etc.).
--extern-post-js <file>
Like --extern-pre-js, but appends to the end.
--embed-file <file>

Specify a file (with path) to embed inside the generated JavaScript. The path is relative to the current directory at compile time. If a directory is passed here, its entire contents will be embedded.

For example, if the command includes --embed-file dir/file.dat, then dir/file.dat must exist relative to the directory where you run emcc.

Note

Embedding files is much less efficient than preloading them. You should only use it for small files, in small numbers. Instead use --preload-file, which emits efficient binary data.

For more information about the --embed-file options, see Packaging Files.

--preload-file <name>

Specify a file to preload before running the compiled code asynchronously. The path is relative to the current directory at compile time. If a directory is passed here, its entire contents will be embedded.

Preloaded files are stored in filename.data, where filename.html is the main file you are compiling to. To run your code, you will need both the .html and the .data.

Note

This option is similar to –embed-file, except that it is only relevant when generating HTML (it uses asynchronous binary XHRs), or JavaScript that will be used in a web page.

emcc runs tools/file_packager.py to do the actual packaging of embedded and preloaded files. You can run the file packager yourself if you want (see Packaging using the file packager tool). You should then put the output of the file packager in an emcc --pre-js, so that it executes before your main compiled code.

For more information about the --preload-file options, see Packaging Files.

--exclude-file <name>
Files and directories to be excluded from –embed-file and –preload-file. Wildcards (*) are supported.
--use-preload-plugins
Tells the file packager to run preload plugins on the files as they are loaded. This performs tasks like decoding images and audio using the browser’s codecs.
--shell-file <path>

The path name to a skeleton HTML file used when generating HTML output. The shell file used needs to have this token inside it: {{{ SCRIPT }}}.

Note

--source-map-base <base-url>
The URL for the location where WebAssembly source maps will be published. When this option is provided, the .wasm file is updated to have a sourceMappingURL section. The resulting URL will have format: <base-url> + <wasm-file-name> + .map.
--minify 0
Identical to -g1.
--js-transform <cmd>

Specifies a <cmd> to be called on the generated code before it is optimized. This lets you modify the JavaScript, for example adding or removing some code, in a way that those modifications will be optimized together with the generated code.

<cmd> will be called with the file name of the generated code as a parameter. To modify the code, you can read the original data and then append to it or overwrite it with the modified data.

<cmd> is interpreted as a space-separated list of arguments, for example, <cmd> of python processor.py will cause a Python script to be run.

--bind
Compiles the source code using the Embind bindings to connect C/C++ and JavaScript.
--ignore-dynamic-linking

Tells the compiler to ignore dynamic linking (the user will need to manually link to the shared libraries later on).

Normally emcc will simply link in code from the dynamic library as though it were statically linked, which will fail if the same dynamic library is linked more than once. With this option, dynamic linking is ignored, which allows the build system to proceed without errors.

--js-library <lib>
A JavaScript library to use in addition to those in Emscripten’s core libraries (src/library_*).
-v

Turns on verbose output.

This will pass -v to Clang, and also enable EMCC_DEBUG to generate intermediate files for the compiler’s various stages. It will also run Emscripten’s internal sanity checks on the toolchain, etc.

Tip

emcc -v is a useful tool for diagnosing errors. It works with or without other arguments.

--cache

Sets the directory to use as the Emscripten cache. The Emscripten cache is used to store pre-built versions of libc, libcxx and other libraries.

If using this in combination with --clear-cache, be sure to specify this argument first.

The Emscripten cache defaults to being located in the path name stored in the EM_CACHE environment variable or ~/.emscripten_cache.

--clear-cache

Manually clears the cache of compiled Emscripten system libraries (libc++, libc++abi, libc).

This is normally handled automatically, but if you update LLVM in-place (instead of having a different directory for a new version), the caching mechanism can get confused. Clearing the cache can fix weird problems related to cache incompatibilities, like Clang failing to link with library files. This also clears other cached data. After the cache is cleared, this process will exit.

--clear-ports

Manually clears the local copies of ports from the Emscripten Ports repos (sdl2, etc.). This also clears the cache, to remove their builds.

You should only need to do this if a problem happens and you want all ports that you use to be downloaded and built from scratch. After this operation is complete, this process will exit.

--show-ports
Shows the list of available projects in the Emscripten Ports repos. After this operation is complete, this process will exit.
--save-bc PATH
When compiling to JavaScript or HTML, this option will save a copy of the bitcode to the specified path. The bitcode will include all files being linked after link-time optimizations have been performed (if any), including standard libraries.
--memory-init-file <on>

Specifies whether to emit a separate memory initialization file.

Note

Note that this is only relevant when not emitting wasm, as wasm embeds the memory init data in the wasm binary.

Possible on values are:

  • 0: Do not emit a separate memory initialization file. Instead keep the static initialization inside the generated JavaScript as text. This is the default setting if compiling with -O0 or -O1 link-time optimization flags.

  • 1: Emit a separate memory initialization file in binary format. This is more efficient than storing it as text inside JavaScript, but does mean you have another file to publish. The binary file will also be loaded asynchronously, which means main() will not be called until the file is downloaded and applied; you cannot call any C functions until it arrives. This is the default setting when compiling with -O2 or higher.

    Note

    The safest way to ensure that it is safe to call C functions (the initialisation file has loaded) is to call a notifier function from main().

    Note

    If you assign a network request to Module.memoryInitializerRequest (before the script runs), then it will use that request instead of automatically starting a download for you. This is beneficial in that you can, in your HTML, fire off a request for the memory init file before the script actually arrives. For this to work, the network request should be an XMLHttpRequest with responseType set to 'arraybuffer'. (You can also put any other object here, all it must provide is a .response property containing an ArrayBuffer.)

-Wwarn-absolute-paths
Enables warnings about the use of absolute paths in -I and -L command line directives. This is used to warn against unintentional use of absolute paths, which is sometimes dangerous when referring to nonportable local system headers.
--proxy-to-worker
Runs the main application code in a worker, proxying events to it and output from it. If emitting HTML, this emits a .html file, and a separate .js file containing the JavaScript to be run in a worker. If emitting JavaScript, the target file name contains the part to be run on the main thread, while a second .js file with suffix “.worker.js” will contain the worker portion.
--emrun
Enables the generated output to be aware of the emrun command line tool. This allows stdout, stderr and exit(returncode) capture when running the generated application through emrun. (This enables EXIT_RUNTIME=1, allowing normal runtime exiting with return code passing.)
--cpuprofiler
Embeds a simple CPU profiler onto the generated page. Use this to perform cursory interactive performance profiling.
--memoryprofiler
Embeds a memory allocation tracker onto the generated page. Use this to profile the application usage of the Emscripten HEAP.
--threadprofiler
Embeds a thread activity profiler onto the generated page. Use this to profile the application usage of pthreads when targeting multithreaded builds (-s USE_PTHREADS=1/2).
--em-config
Specifies the location of the .emscripten configuration file for the current compiler run. If not specified, the environment variable EM_CONFIG is first read for this location. If neither are specified, the default location ~/.emscripten is used.
--default-obj-ext .ext

Specifies the file suffix to generate if the location of a directory name is passed to the -o directive.

For example, consider the following command, which will by default generate an output name dir/a.o. With --default-obj-ext .ext the generated file has the custom suffix dir/a.ext.

emcc -c a.c -o dir/
--valid-abspath path
Whitelist an absolute path to prevent warnings about absolute include paths.
-o <target>

The target file name extension defines the output type to be generated:

  • <name> .js : JavaScript (+ separate <name>.wasm file if emitting WebAssembly). (default)
  • <name> .mjs : ES6 JavaScript module (+ separate <name>.wasm file if emitting WebAssembly).
  • <name> .html : HTML + separate JavaScript file (<name>.js; + separate <name>.wasm file if emitting WebAssembly).
  • <name> .bc : LLVM bitcode.
  • <name> .o : WebAssembly object file (unless fastcomp or -flto is used in which case it will be in LLVM bitcode format).
  • <name> .wasm : WebAssembly without JavaScript support code (“standalone wasm”; this enables STANDALONE_WASM).

Note

If --memory-init-file is used, a .mem file will be created in addition to the generated .js and/or .html file.

-c
Tells emcc to generate LLVM bitcode (which can then be linked with other bitcode files), instead of compiling all the way to JavaScript.
--separate-asm
Emits asm.js in one file, and the rest of the code in another, and emits HTML that loads the asm.js first, in order to reduce memory load during startup. See Avoid memory spikes by separating out asm.js.
--output_eol windows|linux
Specifies the line ending to generate for the text files that are outputted. If “–output_eol windows” is passed, the final output files will have Windows rn line endings in them. With “–output_eol linux”, the final generated files will be written with Unix n line endings.
--cflags
Prints out the flags emcc would pass to clang to compile source code to object/bitcode form. You can use this to invoke clang yourself, and then run emcc on those outputs just for the final linking+conversion to JS.

Environment variables

emcc is affected by several environment variables, as listed below:

  • EMMAKEN_JUST_CONFIGURE
  • EMMAKEN_COMPILER
  • EMMAKEN_CFLAGS
  • EMCC_DEBUG
  • EMCC_CLOSURE_ARGS : arguments to be passed to Closure Compiler

Search for ‘os.environ’ in emcc.py to see how these are used. The most interesting is possibly EMCC_DEBUG, which forces the compiler to dump its build and temporary files to a temporary directory where they can be reviewed.

Emscripten Windows Command Prompt (emcmdprompt.bat)

The Emscripten Command Prompt is used to call Emscripten tools from the command line on Windows.

The prompt can be launched from the file system by locating and opening the file emcmdprompt.bat.

Note

The Emscripten Command Prompt is configured with the correct system paths and settings to point to the active Emscripten tools. From within the prompt you can call emsdk to change the current SDK or tools.

Command line syntax

The tool is not intended to be run from an existing command line prompt.

However, if emcmdprompt.bat is called on the command line, a nested Emscripten command prompt is spawned within the current prompt (note that this is not necessarily obvious). You can then use this prompt to access the SDK tools. To exit the nested command prompt, type exit and then press the Enter key.

Optimizing Code

Generally you should first compile and run your code without optimizations (the default). Once you are sure that the code runs correctly, you can use the techniques in this article to make it load and run faster.

How to optimize code

Code is optimized by specifying optimization flags when running emcc. The levels include: -O0 (no optimization), -O1, -O2, -Os, -Oz, and -O3.

For example, to compile with optimization level -O2:

emcc -O2 file.cpp

The higher optimization levels introduce progressively more aggressive optimization, resulting in improved performance and code size at the cost of increased compilation time. The levels can also highlight different issues related to undefined behavior in code.

The optimization level you should use depends mostly on the current stage of development:

  • When first porting code, run emcc on your code using the default settings (without optimization). Check that your code works and debug and fix any issues before continuing.
  • Build with lower optimization levels during development for a shorter compile/test iteration cycle (-O0 or -O1).
  • Build with -O2 to get a well-optimized build.
  • Building with -O3 or -Os can produce an ever better build than -O2, and are worth considering for release builds. -O3 builds are even more optimized than -O2, but at the cost of significantly longer compilation time and potentially larger code size. -Os is similar in increasing compile times, but focuses on reducing code size while doing additional optimization. It’s worth trying these different optimization options to see what works best for your application.
  • Other optimizations are discussed in the following sections.

In addition to the -Ox options, there are separate compiler options that can be used to control the JavaScript optimizer (js-opts), LLVM optimizations (llvm-opts) and LLVM link-time optimizations (llvm-lto).

Note

  • The meanings of the emcc optimization flags (-O1, -O2 etc.) are similar to gcc, clang, and other compilers, but also different because optimizing asm.js and WebAssembly includes some additional types of optimizations. The mapping of the emcc levels to the LLVM bitcode optimization levels is documented in the reference.

How Emscripten optimizes

Compiling source files to object files works as you’d expect in a native build system that uses clang and LLVM. When linking object files to the final executable, Emscripten does additional optimizations as well depending on the optimization level:

  • For wasm, the Binaryen optimizer is run. Binaryen does both general-purpose optimizations to the wasm that LLVM does not, and also does some whole-program optimization. (Note that Binaryen’s whole-program optimizations may do things like inlining, which can be surprising in some cases as LLVM IR attributes like noinline have been lost at this point.)
  • For asm.js, the Emscripten asm.js optimizer is run.
  • JavaScript is generated at this phase, and is optimized by Emscripten’s JS optimizer. Optionally you can also run the closure compiler, which is highly recommended for code size.
  • Emscripten also optimizes the combined wasm+JS, by minifying imports and exports between them, and by running meta-dce which removes unused code in cycles that span the two worlds.

To skip extra optimization work at link time, link with -O0 (or no optimization level), which works regardless of how the source files were compiled and optimized. Linking in this way with -O0 is useful for fast iteration builds, while final release builds may want something like -O3 --closure 1.

Advanced compiler settings

There are several flags you can pass to the compiler to affect code generation, which will also affect performance — for example DISABLE_EXCEPTION_CATCHING. These are documented in src/settings.js. Some of these will be directly affected by the optimization settings (you can find out which ones by searching for apply_opt_level in tools/shared.py).

WebAssembly

Emscripten will emit WebAssembly by default. You can switch that off with -s WASM=0 (and then emscripten emits asm.js), which is necessary if you want the output to run in places where wasm support is not present yet, but the downside is larger and slower code.

Code size

This section describes optimisations and issues that are relevant to code size. They are useful both for small projects or libraries where you want the smallest footprint you can achieve, and in large projects where the sheer size may cause issues (like slow startup speed) that you want to avoid.

Trading off code size and performance

You may wish to build the less performance-sensitive source files in your project using -Os or -Oz and the remainder using -O2 (-Os and -Oz are similar to -O2, but reduce code size at the expense of performance. -Oz reduces code size more than -Os.)

Separately, you can do the final link/build command with -Os or -Oz to make the compiler focus more on code size when generating WebAssembly/asm.js.

Miscellaneous code size tips

In addition to the above, the following tips can help to reduce code size:

  • Use the closure compiler on the non-compiled code: --closure 1. This can hugely reduce the size of the support JavaScript code, and is highly recommended. However, if you add your own additional JavaScript code (in a --pre-js, for example) then you need to make sure it uses closure annotations properly.
  • Floh’s blogpost on this topic is very helpful.
  • Make sure to use gzip compression on your webserver, which all browsers now support.

The following compiler settings can help (see src/settings.js for more details):

  • Disable inlining when possible, using -s INLINING_LIMIT=1. Compiling with -Os or -Oz generally avoids inlining too. (Inlining can make code faster, though, so use this carefully.)
  • You can use the -s FILESYSTEM=0 option to disable bundling of filesystem support code (the compiler should optimize it out if not used, but may not always succeed). This can be useful if you are building a pure computational library, for example.
  • The ENVIRONMENT flag lets you specify that the output will only run on the web, or only run in node.js, etc. This prevents the compiler from emitting code to support all possible runtime environments, saving ~2KB.
  • You can use ELIMINATE_DUPLICATE_FUNCTIONS to remove duplicate functions, which C++ templates often create. (This is already done by default for wasm, in -O1 and above.)

LTO

Link Time Optimization (LTO) lets the compiler do more optimizations, as it can inline across separate compilation units, and even with system libraries. For fastcomp the main relevant flag is --llvm-lto 1 at link time.

With the LLVM wasm backend, LTO triggered by compiling objects files with -flto. The effect of this flag is to emit LTO object files (technically this means emitting bitcode). The linker can handle a mix wasm object files and LTO object files. Passing -flto at link time will also trigger LTO system libraries to be used.

Thus, to allow maximal LTO opportunities with the LLVM wasm backend, build all source files with -flto and also link with flto.

Note that older versions of LLVM had bugs in this area. With the older fastcomp backend LTO should be used carefully.

Very large codebases

The previous section on reducing code size can be helpful on very large codebases. In addition, here are some other topics that might be useful.

Avoid memory spikes by separating out asm.js

When emitting asm.js, by default Emscripten emits one JS file, containing the entire codebase: Both the asm.js code that was compiled, and the general code that sets up the environment, connects to browser APIs, etc. in a very large codebase, this can be inefficient in terms of memory usage, as having all of that in one script means the JS engine might use some memory to parse and compile the asm.js, and might not free it before starting to run the codebase. And in a large game, starting to run the code might allocate a large typed array for memory, so you might see a “spike” of memory, after which temporary compilation memory will be freed. And if big enough, that spike can cause the browser to run out of memory and fail to load the application. This is a known problem on Chrome (other browsers do not seem to have this issue).

A workaround is to separate out the asm.js into another file, and to make sure that the browser has a turn of the event loop between compiling the asm.js module and starting to run the application. This can be achieved by running emcc with --separate-asm.

You can also do this manually, as follows:

  • Run tools/separate_asm.py. This receives as inputs the filename of the full project, and two filenames to emit: the asm.js file and a file for everything else.

  • Load the asm.js script first, then after a turn of the event loop, the other one, for example using code like this in your HTML file:

    var script = document.createElement('script');
    script.src = "the_asm.js";
    script.onload = function() {
      setTimeout(function() {
        var script = document.createElement('script');
        script.src = "the_rest.js";
        document.body.appendChild(script);
      }, 1); // delaying even 1ms is enough
    };
    document.body.appendChild(script);
    

Running by itself

If you hit memory limits in browsers, it can help to run your project by itself, as opposed to inside a web page containing other content. If you open a new web page (as a new tab, or a new window) that contains just your project, then you have the best chance at avoiding memory fragmentation issues.

Aggressive variable elimination

Aggressive variable elimination is an asm.js feature (not relevant for wasm) that attempts to remove variables whenever possible, even at the cost of increasing code size by duplicating expressions. This can improve speed in cases where you have extremely large functions. For example it can make sqlite (which has a huge interpreter loop with thousands of lines in it) 7% faster.

You can enable aggressive variable elimination with -s AGGRESSIVE_VARIABLE_ELIMINATION=1.

Note

This setting can be harmful in some cases. Test before using it.

Other optimization issues

C++ exceptions

Catching C++ exceptions (specifically, emitting catch blocks) is turned off by default in -O1 (and above). Due to how asm.js/wasm currently implement exceptions, this makes the code much smaller and faster (eventually, wasm should gain native support for exceptions, and not have this issue).

To re-enable exceptions in optimized code, run emcc with -s DISABLE_EXCEPTION_CATCHING=0 (see src/settings.js).

Note

When exception catching is disabled, a thrown exception terminates the application. In other words, an exception is still thrown, but it isn’t caught.

Note

Even with catch blocks not being emitted, there is some code size overhead unless you build your source files with -fno-exceptions, which will omit all exceptions support code (for example, it will avoid creating proper C++ exception objects in errors in std::vector, and just abort the application if they occur)

C++ RTTI

C++ run-time type info support (dynamic casts, etc.) adds overhead that is sometimes not needed. For example, in Box2D neither rtti nor exceptions are needed, and if you build the source files with -fno-rtti -fno-exceptions then it shrinks the output by 15% (!).

Memory Growth

Building with -s ALLOW_MEMORY_GROWTH=1 allows the total amount of memory used to change depending on the demands of the application. This is useful for apps that don’t know ahead of time how much they will need, but it disables asm.js optimizations. In WebAssembly, however, there should be little or no overhead.

Viewing code optimization passes

Enable Debug mode (EMCC_DEBUG) to output files for each compilation phase, including the main optimization operations.

Unsafe optimizations

A few UNSAFE optimizations you might want to try are:

  • --closure 1: This can help with reducing the size of the non-generated (support/glue) JS code, and with startup. However it can break if you do not do proper Closure Compiler annotations and exports. But it’s worth it!
  • --llvm-lto 1: This enables LLVM’s link-time optimizations, which can help in some cases. However there are known issues with these optimizations, so code must be extensively tested. See llvm-lto for information about the other modes.

Profiling

Modern browsers have JavaScript profilers that can help find the slower parts in your code. As each browser’s profiler has limitations, profiling in multiple browsers is highly recommended.

To ensure that compiled code contains enough information for profiling, build your project with profiling as well as optimization and other flags:

emcc -O2 --profiling file.cpp

Troubleshooting poor performance

Emscripten-compiled code can currently achieve approximately half the speed of a native build. If the performance is significantly poorer than expected, you can also run through the additional troubleshooting steps below:

  • Building Projects is a two-stage process: compiling source code files to LLVM and generating JavaScript from LLVM. Did you build using the same optimization values in both steps (-O2 or -O3)?
  • Test on multiple browsers. If performance is acceptable on one browser and significantly poorer on another, then file a bug report, noting the problem browser and other relevant information.
  • Does the code validate in Firefox (look for “Successfully compiled asm.js code” in the web console). If you see a validation error when using an up-to-date version of Firefox and Emscripten then please file a bug report.

Optimizing WebGL

Due to the extra validation that WebGL needs to impose to ensure web security, the CPU side overhead of running WebGL applications is known to be higher in comparison to native OpenGL applications. Because of this, porting graphics heavy applications can become bottlenecked on the CPU side when interfacing with GL functions. Therefore for best performance, special care should be taken to profile and optimize GL API usage in applications that are expected to be WebGL heavy. This optimization guide focuses on different techniques that have been found useful for improving WebGL performance.

There are so many GL hardware and driver vendors out there, as well as operating system combinations, such that generating a specific optimization guide is difficult. Some optimizations that are efficient on certain hardware/driver/OS combinations have been seen to not make much difference on drivers from another vendor. Fortunately it has been somewhat rare to find a conflicting scenario where certain optimization for one driver would have led to falling down a performance cliff on hardware from another GPU vendor. Most often when this happens it is due to a specific feature not being supported by a particular hardware, which causes the driver to resort to emulation. For example, in one case it was found that a native GL driver advertises having support for the ETC2 compressed texture format, even though the graphics hardware did not implement this, and in another case, it was found that using vertex shader primitive restart index would cause the GL driver to fall back to running vertex shaders in software. Unfortunately OpenGL specifications do not provide means for a driver to report these types of performance caveats, which is why being able to benchmark across a large variety of target hardware is almost necessary when optimizing GL. It is also useful to pay close attention to the web page console of the browser when running, since browsers can report extra performance warnings in the console logs.

It should also be acknowledged that some detected performance issues have been due to inefficiencies or outright performance bugs in browsers and their utilized software libraries, and have nothing to do with the underlying GL drivers or web security in general. When initially working on optimizing Emscripten ported GL codebases, most browsers were found to be inefficient with their WebGL stacks, but this was to be expected, since before Emscripten and asm.js, it was not even possible to perform such precise GL performance comparisons between native versus the web, such that a large number of performance critical issues fell through the gaps. This aspect has steadily been improving as more people stress WebGL with large Emscripten codebases, so some of the items in this guide might not be relevant in the future. If reading this guide in the future you do find something that seems like a net loss in all cases, please do submit a doc PR to discuss. Likewise, if certain GL access pattern is orders of magnitude slower on the web compared to native, it is likely to be a performance bug.

The following optimization tips list different situations that have been known to make an impact in practice, although it is advised to never perform an optimization blindly, but keep the profiler close at hand when experimenting.

Which GL Mode To Target?

Emscripten allows targeting various different OpenGL and OpenGL ES API flavors with different linker flags.

By default, if no special GL related linker flags are chosen, Emscripten targets the WebGL 1 API, which user code accesses by including OpenGL ES 2.0 headers in C/C++ code (#include <GLES2/gl2.h> and #include <GLES2/gl2ext.h>). This mode works like GLES 2, with the exception that a number of WebGL specific changes and restrictions are applied. For a close to complete reference of differences between WebGL 1 and OpenGL ES 2, refer to WebGL 1 Specification: Differences Between WebGL and OpenGL ES 2.0.

  • If your application renders geometry from client side memory, it will need to build with the linker flag -s FULL_ES2=1. This mode is convenient to ease porting of new codebases, however WebGL itself does not support rendering from client side memory, so this feature is emulated. For best performance, use VBOs instead and build without the -s FULL_ES2=1 linker flag.
  • If your application targets old desktop OpenGL APIs, it might work when built with the -s LEGACY_GL_EMULATION=1 flag. However, when building in this mode, even if it works, do not expect good performance. If the application is slow in this mode and it only uses fixed pipeline and no shaders at all, it is also possible to pair -s LEGACY_GL_EMULATION=1 with -s GL_FFP_ONLY=1 linker flag to attempt to recover some performance. Although in general it is recommended to spend the effort to port the application to use WebGL 1/OpenGL ES 2 instead.
  • When targeting OpenGL ES 3, if one needs to render from client side memory, or the use of glMapBuffer*() API is needed, pass the linker flag -s FULL_ES3=1 to emulate these features, which core WebGL 2 does not have. This emulation is expected to hurt performance, so using VBOs is recommended instead.
  • Even if your application does not need any WebGL 2/OpenGL ES 3 features, consider porting the application to run on WebGL 2, because JavaScript side performance in WebGL 2 has been optimized to generate no temporary garbage, which has been observed to give a solid 3-7% speed improvement, as well as reducing potential stuttering at render time. To enable these optimizations, build with the linker flag -s MAX_WEBGL_VERSION=2 and make sure to create a WebGL 2 context at GL startup time (OpenGL ES 3 context if using EGL).

How To Profile WebGL

A mix of tools are available for measuring GL performance. In general, here it is recommended that developers do not restrict the focus to only searching for web browser specific profiling tools, but in practice native profilers have been found to work equally well, if not even better. The only drawback when using a native profiler is that some intimate knowledge of how WebGL is implemented in the browser can be critical, or it might be difficult to understand the call streams going to the GPU otherwise.

  • To get an overview of how much time is spent in different WebGL entry points, use Firefox with its Gecko Profiler add-on. This profiler tool is able to show timing data across the whole stack of executed code: handwritten JavaScript, asm.js/WebAssembly and native Firefox C/C++ browser code, which makes it very valuable compared to other profiling tools.
  • Useful native tools that are able to profile CPU overhead are AMD CodeXL, Intel VTune Amplifier and macOS Instruments. If the browser performance profiling tool suggests that a large portion of time is spent inside the browser entry points itself, these tools can be useful in locating where the hotspots are. However when using native CPU profiling tools, it is necessary to build the browser code manually from source in order to obtain symbol information data (e.g. .pdb files on Windows), which these tools look up locally. When debugging Firefox in this way, disabling the multiprocess architecture in Firefox is useful to obtain traces that run the content process in the same thread as the browser itself. Navigate Firefox browser to page about:config and set the pref browser.tabs.remote.autostart.2 to false, and restart the browser.
  • For debugging GPU side API call traces, the NVidia Nsight, Intel Graphics Performance Analyzers, Visual Studio Graphics Debugger and AMD CodeXL can be useful tools. On Windows, Firefox is able to use either OpenGL or Direct3D to render WebGL content. Direct3D is the default, but e.g. AMD CodeXL only traces OpenGL call streams. In order to use AMD CodeXL to trace WebGL API calls in Firefox, navigate the browser to about:config and set the pref webgl.disable-angle to true and reload the page.

Avoid Redundant Calls

In WebGL, every single GL function call has some amount of overhead, even those that are seemingly simple and do nearly nothing. This is because WebGL implementations need to validate each call since the underlying native OpenGL specifications provide no guarantees about security that could be relied upon on the web. Additionally in asm.js/WebAssembly side, each WebGL call generates an FFI transition (a jump between executing code in asm.js context and executing code in browser’s native C++ context), which has a slightly higher overhead than a regular function call inside asm.js/WebAssembly. Therefore on the web, it is generally best for CPU side performance to attempt to minimize the number of calls that is made to WebGL. The following tips can be applied here.

  • Optimize the renderer and input assets at high level to avoid redundant calls. Refactor the design if needed so that the renderer is able to better reason what kind of state changes are relevant and which ones are not needed. The best kind of cache is one that is unnecessary, so if the high level renderer is able to keep the GL call stream lean, that will produce the fastest results. However, in cases when that is difficult to achieve, some types of lower level caching can be effective, discussed below.

  • Cache GL state inside the renderer code, and avoid doing redundant calls to set the same state multiple times if it has not changed. For example, some engines might blindly reconfigure depth testing or alpha blending modes before each draw call, or reset the shader program for each call.

  • Avoid all types of renderer patterns which reset the GL to some specific “ground state” after certain operations. Commonly seen occurrences are to glBindBuffer(GL_ARRAY_BUFFER, 0), glUseProgram(0), or for(i in 0 -> max_attributes) glDisableVertexAttribArray(i); after issuing each draw call to revert to a known fixed configuration. Instead, lazily change only the GL state that is needed when transitioning from one draw call to another.

  • Consider lazily setting GL state only when it needs to take effect. For example, in the following call stream

    // First draw
    glBindBuffer(...);
    glVertexAttribPointer(...);
    glActiveTexture(0);
    glBindTexture(GL_TEXTURE_2D, texture1);
    glActiveTexture(1);
    glBindTexture(GL_TEXTURE_2D, texture2);
    glDrawArrays(...);
    
    // Second draw (back-to-back)
    glBindBuffer(...);
    glVertexAttribPointer(...);
    glActiveTexture(0); // (*)
    glBindTexture(GL_TEXTURE_2D, texture1); // (*)
    glActiveTexture(1); // (*)
    glBindTexture(GL_TEXTURE_2D, texture2); // (*)
    glDrawArrays(...);
    

all the four API calls marked with a star are redundant, but simple state caching is not quite enough to detect this. A lazier state cache mechanism will be able to detect these types of changes. However, when implementing deeply lazy state caches, it is recommended to do so only after having profiling data to motivate the optimization, because applying lazy caching techniques to all GL state prior to render can become costly as well for other reasons, and performance may be wasted if the renderer already is good at avoiding resubmitting redundant calls. Just right amount of caching can require a bit of tuning to find the balance.

A good rule of thumb is that a renderer that inherently avoids redundant state calls in the first place by high level design is generally more efficient than one that relies heavily on state caching at the low level.

Techniques To Minimize API Calls

In addition to removing API calls that are outright redundant, it is good to also pay attention to how to minimize state changes using other techniques. The following checklist offers some possibilities.

  • When rendering to offscreen render targets, use multiple FBOs so that switching render targets only requires a single glBindFramebuffer() call. This avoids having to perform multiple calls each frame to set FBO state.
  • Avoid mutating FBO state, but prefer to set up multiple immutable/static FBOs, which do not change state. Changing FBO state causes revalidation of that FBO combination in the browser, but immutable FBOs only need to be validated once at creation.
  • Use VAOs whenever possible to avoid having to call to several GL functions to set up vertex attributes for rendering.
  • Batch up glUniform* calls to arrays of uniforms and update them in one glUniform4fv() array call, instead of calling glUniform4f() multiple times to update each one individually. Or better yet, use Uniform Buffer Objects in WebGL 2.
  • Do not call glGetUniformLocation() at render time, but query the locations once per shader program at startup and cache them.
  • Use instanced rendering whenever applicable.
  • Consider atlasing several textures into one to enable better geometry batching and instancing opportunities.
  • Consider culling renderables more aggressively compared to native GL platforms, if not already being as tight as possible.

Avoid GPU-CPU Sync Points

The most important aspect of efficient GPU usage is to make sure that the CPU will never need to block on the GPU during render time, and vice versa. These types of stalls create extremely costly CPU-GPU sync points, which lead to poor utilization of both resources. Generally a hint of this type of a scenario happening can be detected by observing overall GPU and CPU utilization rates. If a GPU profiler is claiming that the GPU is idle for large portions of the time, but a CPU profiler is claiming that the CPU in turn is idle, or that certain GL functions take a very long time to complete, it suggests that frames are not being efficiently submitted to the GPU, but GPU-CPU sync(s) occur somewhere during draw call submission. Unfortunately OpenGL specifications do not provide any performance guarantees of which GL calls may cause a stall, so look out for the following behavior and experiment by changing these and reprofiling the effects.

  • Avoid creating new GL resources at render time. This means optimizing out calls to glGen*() and glCreate*() functions (glGenTextures(), glGenBuffers(), glCreateShader() and so on) at render time. If new resources are needed, try to create and upload them a couple of frames before attempting to render using them.
  • Likewise, do not delete any GL resources that have just been rendered with. The functions glDelete*() can introduce a full pipeline flush if the driver detects that any of the resources are in use. It is better to delete resources at loading time only.
  • Never call glGetError() or glCheckFramebufferStatus() at render time. These functions should be restricted to be checked at loading time only, since both of these can do a full pipeline sync.
  • Similarly, do not call any of the glGet*() API functions at render time, but query them at startup and loading time, and refer to cached results at render time.
  • Try to avoid compiling shaders at render time, both glCompileShader() and glLinkProgram() can be extremely slow.
  • Do not call glReadPixels() to copy texture contents back to main memory at render time. If necessary, use the WebGL 2 GL_PIXEL_PACK_BUFFER binding target instead to copy a GPU surface to an offscreen target first, and only later glReadPixels() the contents of that surface back to main memory.

GPU Driver Friendly Memory Access Behavior

Transferring memory between the CPU and the GPU is a common source of GL performance issues. This is because creating new GL resources can be slow, and uploading or downloading data can block the CPU if the data is not ready, or if an old version of the data is still needed before being able to overwrite it with a new version.

  • Prefer interleaved vertex data in a single VBO over multiple VBOs that contain planar attributes. This improves GPU vertex cache behavior, and avoids multiple redundant glBindBuffer() calls when setting up vertex attribute pointers for rendering.
  • Avoid calling glBufferData() or glTexImage2D/3D() to resize the contents of a buffer or a texture at runtime. When increasing or decreasing dynamic VBO sizes, use std::vector-style geometric array grow semantics to avoid having to resize every frame.
  • Prefer calling glBufferSubData() and glTexSubImage2D/3D() when updating buffer texture data, even when the whole contents of the texture or the buffer changes. If the size of a buffer would shrink, do not eagerly re-create the storage, but simply ignore the excess size.
  • For dynamic vertex buffer data, consider double- or even triple-buffering VBOs each frame, to avoid uploading a VBO that is still in use. Prefer using GL_DYNAMIC vertex buffers over GL_STREAM.

When The GPU Is The Bottleneck

After having verified that CPU-GPU pipeline sync bubbles do not occur, and rendering is still GPU bound, the following optimizations can be useful.

  • Multiple additive lighting draw passes of geometry in a forward lighting renderer can be straightforward to implement, but the amount of GL API calls this generates can be too costly. In such cases, consider computing multiple light contributions in one shader pass, even if this would create no-op arithmetic operations in shaders when some objects are not affected by certain lights.
  • Use lowest possible fragment shader precision when it is enough (lowp). Optimize shaders aggressively beforehand at offline authoring time, do not expect that the GPU GLSL driver would do any optimizations on the fly. This is particularly important for mobile GPU drivers.
  • Sort renderables by target FBO first, then by shader program, and third to minimize any other needed GL state changes or to minimize overdraw, depending on whether the program is CPU or BPU bound. This helps tile based renderers. Call WebGL 2 glDiscardFramebuffer() when the contents of an FBO are no longer needed.
  • Use a GPU profiler, or implement custom fragment shaders that can help profiling how much overdraw the rendered scene has. A large amount of overdraw not only generates extra work, but the sequential dependencies between rendering to the same blocks of display memory slow down parallel rendering. If rendering a 3D scene with depth buffering enabled, consider sorting the scene from front to back to minimize overdraw and redundant per pixel fill bandwidth. If using very complex fragment shaders in a 3D scene, consider doing a depth prepass to reduce the number of actually rasterized color fragments to an absolute minimum.

Optimizing Load Times and Other Best Practices

Finally, a number of miscellaneous optimizations have been proven to be effective.

  • On the web one cannot generally expect which compressed texture formats will be available. Author textures to multiple compressed texture bundles, e.g. one per format, and download the appropriate one in at runtime to minimize excessive downloads. Store textures and other assets to IndexedDB to avoid having to redownload on subsequent runs. The Emscripten linker flag -s GL_PREINITIALIZED_CONTEXT=1 can help in authoring a html shell page that performs such texture format checks up front.
  • Consider compiling shaders in parallel to when other assets are being downloaded. This can help hide slow shader compilation times.
  • Test for WebGL support on the user’s browser early in the page load process before downloading a large amount of assets. It can be frustrating for the user to have to wait to download multiple megabytes of assets, only then to get an error message of WebGL not being available after the wait.
  • Check the WebGL context error reason if WebGL initialization fails, using the "webglcontextcreationerror" callback. Browsers can give good diagnostics in the context creation error handler to allow diagnosing what the root cause is.
  • Pay close attention to the visible size of the canvas (the CSS pixels size of the DOM element) versus the physical render target size of the initialized WebGL context on the canvas, and make sure these two match in order to render 1:1 pixel perfect content.
  • Probe context creation with the failIfMajorPerformanceCaveat flag to detect when rendering on software, and cut down on graphics fidelity in such cases.
  • Make sure to initialize the WebGL context with just the minimum amount of features that are needed. WebGL context creation parameters include support for alpha, depth, stencil and MSAA, and most often e.g. support for alpha blending the canvas against the HTML page background is not needed, and should be disabled.
  • Avoid using any of the *glGetProcAddress() API functions. Emscripten provides static linking to all of the GL API functions, even for all WebGL extensions. The *glGetProcAddress() API is only provided for compatibility to ease porting of existing code, but accessing WebGL via calling dynamically obtained function pointers is noticeably slower than direct function calls, due to extra function pointer security validation that dynamic dispatching has to do in asm.js/WebAssembly. Since Emscripten provides all of the GL entry points statically linked in, it is recommended to take advantage of this for best performance.
  • Always use requestAnimationFrame() loops to render animation instead of the setTimeout() API. This gives the smoothest scheduling on the animation ticks.

Migrating To WebGL 2

Compared to WebGL 1, the new WebGL 2 API provides essentially free API optimizations that are activated simply by targeting WebGL 2. This speedup comes from the fact that the WebGL 2 API was revised from the perspective of JavaScript bindings, and it is now possible to use WebGL without having to allocate temporary objects that would contribute to JS garbage collector pressure. These new entry points fit nicer together with asm.js and WebAssembly applications, and make the WebGL API a bit leaner to use. As a case study, updating Unreal Engine 4 to target WebGL 2, with no other engine modifications, yielded 7% faster throughput performance.

Because of this source of free performance, it is heavily recommended that all developers migrate to target WebGL 2 even if no other WebGL 2 features are needed, if performance is a concern. WebGL 2 is available starting from Firefox 51 and Chrome 58 (see #4945). See also caniuse: WebGL 2 table. With a little care, it is possible to simultaneously target both WebGL 1 and WebGL 2 APIs, and leverage the best performance when available, but gracefully fall back on less compatible GPUs.

When working with these two specifications, it is good to remember that WebGL 1 is based on the OpenGL ES 2.0 specification, and WebGL 2 is based on the OpenGL ES 3.0 specification.

Migration to WebGL 2 is slightly complicated by the fact that WebGL, just like OpenGL ES, is not a backwards compatible API. That is, WebGL 1/OpenGL ES 2 applications do not generally work just by initializing a newer version of the GL context to run on WebGL 2/OpenGL ES 3.0. The reason for this is that a number of backwards compatibility breaking changes have been introduced between the two versions. However, these changes are more superficial/cosmetic rather than functional, and feature-wise, WebGL2/OpenGL ES 3.0 encompasses all features that exist in WebGL 1/OpenGL ES 2. Only the way that the different API functions are invoked has changed.

To migrate from WebGL 1 to WebGL 2, pay attention to the following list of known backwards incompatibilities.

  • In WebGL 2, a number of WebGL 1.0 extensions have been incorporated to the core WebGL 2 API, and those extensions are no longer advertised to exist when querying for the list of different WebGL extensions. For example, the presence of instanced rendering in WebGL 1 is provided by the ANGLE_instanced_arrays extension, but this is a WebGL 2 core feature, and is therefore no longer reported in the list of GL extensions. If targeting both WebGL 1 and WebGL 2 simultaneously in an application, remember to check both the extension and the core context version number when detecting the presence of a feature.

  • A side effect of the above is that when the functionality was merged to core, the specific function names to call for the feature has changed, i.e. on WebGL1/GLES 2 contexts, one would call the function glDrawBuffersEXT(), but with WebGL2/GLES 3.0, one should call the unsuffixed function glDrawBuffers() instead.

  • The full list of WebGL 1 extensions that were adopted to the core WebGL 2 specification is:

    ANGLE_instanced_arrays
    EXT_blend_minmax
    EXT_color_buffer_half_float
    EXT_frag_depth
    EXT_sRGB
    EXT_shader_texture_lod
    OES_element_index_uint
    OES_standard_derivatives
    OES_texture_float
    OES_texture_half_float
    OES_texture_half_float_linear
    OES_vertex_array_object
    WEBGL_color_buffer_float
    WEBGL_depth_texture
    WEBGL_draw_buffers
    

These extensions were adopted without any functional changes, so when initializing a WebGL2/GLES 3.0 context, these can be used directly without checking for the presence of an extension.

  • A notable addition is that WebGL 2 introduced a new GLSL shader language format. In WebGL 1, one authors shaders in OpenGL ES Shading Language, Version 1.00, using #version 100 version pragma in shader code. WebGL 2 introduced new shader language version, The OpenGL ES Shading Language, Version 3.00, which is identified by the pragma directive #version 300 es in shader code.
  • In WebGL 2/GLES 3.0, one can keep using either WebGL 1/GLES 2 #version 100 shaders, or migrate to using WebGL 2/GLES 3.0 #version 300 es shaders. Note however that WebGL 2 has a backwards breaking incompatibility that the WebGL extensions OES_standard_derivatives and EXT_shader_texture_lod are no longer available in #version 100 shaders, because those features are no longer present as extensions. #version 100 shaders that use those extensions must be rewritten to #version 300 es format instead. Emscripten provides a linker flag -s WEBGL2_BACKWARDS_COMPATIBILITY_EMULATION=1 which performs a string search-replace based automatic migration of #version 100 shaders to #version 300 es format when either of these extensions are detected to attempt to hide this breakage in backwards compatibility.
  • In WebGL 2/GLES 3.0, a number of texture format enums changed for texture formats introduced by extensions. It is no longer possible to use so called unsized texture formats from WebGL 1/GLES 2 extensions, but instead, the new sized variants of the formats must be used for the internalFormat field. For example, instead of creating a texture with format=GL_DEPTH_COMPONENT, type=GL_UNSIGNED_INT, internalFormat=GL_DEPTH_COMPONENT, it is required to specify the size in the internalFormat field, i.e. format=GL_DEPTH_COMPONENT, type=GL_UNSIGNED_INT, internalFormat=GL_DEPTH_COMPONENT24.
  • A particular gotcha with WebGL 2/GLES 3.0 texture formats is that the enum value for the half float (float16) texture type changed value when the WebGL 1/GLES 2 extension OES_texture_half_float was subsumed to the core WebGL 2/GLES 3.0 specification. In WebGL1/GLES 2, half floats were denoted by the value GL_HALF_FLOAT_OES=0x8d61, but in WebGL2/GLES 3.0, the enum value GL_HALF_FLOAT=0x140b is used, contrast to other texture type extensions where inclusion to the core specification generally preserved the value of the enum that is used.

Overall, to ease simultaneously targeting both WebGL1/GLES 2 and WebGL2/GLES 3.0 contexts, Emscripten provides a linker flag -s WEBGL2_BACKWARDS_COMPATIBILITY_EMULATION=1, which hides the above differences behind automatically detected migration, to allow existing WebGL 1 content to transparently also target WebGL 2 for the free speed boost it provides.

If you find a missing item in this emulation, or have comments to improve this guide, please submit feedback to the Emscripten bug tracker.

CyberDWARF Debugging

Building

To add CyberDWARF support to a build, pass -s CYBERDWARF=1 to emcc. This generates a .cd file containing type information for debugging and adds a debugging toolkit to the output JavaScript.

Using

The CyberDWARF debugger is designed to be used from the JavaScript devtool console available in most modern browsers.

Heap Pretty Printer

This small example will show how to use CyberDWARF to visualize a simple struct.

#include <emscripten.h>
#include <stdio.h>
#include <string.h>

struct TinyStruct {
  short len;
  char * chars;
};

extern "C" {

int example() {
  TinyStruct example;
  example.chars = "Hello World";
  example.len = strlen(example.chars);

  printf("%p\n", &example);
  EM_ASM({ debugger });

  return 0;
}

}

int main(int argc, char *argv[]) {
  return 0;
}

Compile the code

em++ -O1 -s CYBERDWARF=1 example.cpp -o example.html -s EXPORTED_FUNCTIONS="['_example']"

Visualizing

After the page loads, open a JavaScript console.

> Module['cyberdwarf'].initialize_debugger()
Debugger ready
> Module['_example']()
0x1078
> Module['cyberdwarf'].set_current_function("_example")
> JSON.stringify(Module['cyberdwarf'].decode_var_by_var_name(0x1078, "example", 10), null, "\t")
'{
  "struct TinyStruct": {
    "short : len": 5,
    "char * : chars": 87
  }
}'

API

Module['cyberdwarf'].initialize_debugger()

Called to load the CyberDWARF file for the script.

Module['cyberdwarf'].set_current_function(name)

Sets the function to lookup variable type by name. Supports either C/mangled name or minified name from symbol file.

Module['cyberdwarf'].decode_var_by_var_name(address, name, depth)

Looks up the type given by variable name in the current function, then dumps a JSON formatted representation of that type at address up to depth (defaults to 1)

Module['cyberdwarf'].decode_var_by_type_name(address, type, depth)

Using the type given in type, then dumps a JSON formatted representation of that type at address up to depth (defaults to 1)

Debugging with Sanitizers

Warning

Sanitizers can only be used with the upstream wasm backend. If you are using fastcomp, you need to upgrade before sanitizers will work. See here for instructions.

Undefined Behaviour Sanitizer

Clang’s undefined behavior sanitizer (UBSan) is available for use with Emscripten. This makes it much easier to catch bugs in your code.

To use UBSan, simply pass -fsanitize=undefined to emcc or em++. Note that you need to pass this at both the compile and link stages, as it affects both codegen and system libraries.

Catching Null Dereference

By default, with Emscripten, dereferencing a null pointer does not immediately cause a segmentation fault, unlike traditional platforms. Instead, it checks a magic cookie stored at address 0 at the end of the program execution.

This only detects null pointer writes, and not reads, and it’s rather difficult to find where the null pointer write occurred.

Emscripten provides a SAFE_HEAP mode, which can be activated by running emcc with -s SAFE_HEAP=1. This will catch both null pointer reads and writes, and causes an exception, but it is slower, and does not tell you the exact line numbers unless you compile with -g.

UBSan will tell you exactly where the null deference happened, and works for both reads and writes, with much less performance penalty than SAFE_HEAP.

Consider the following program, null-assign.c:

int main(void) {
    int *a = 0;
    *a = 0;
}

Without UBSan or SAFE_HEAP, you get an error when the program exits:

$ emcc null-assign.c
$ node a.out.js
Runtime error: The application has corrupted its heap memory area (address zero)!

With UBSan, you get the exact line number where this happened:

$ emcc -fsanitize=undefined null-assign.c
$ node a.out.js
null-assign.c:3:5: runtime error: store to null pointer of type 'int'
Runtime error: The application has corrupted its heap memory area (address zero)!

Consider the following program, null-read.c:

int main(void) {
    int *a = 0, b;
    b = *a;
}

Without UBSan or SAFE_HEAP, there is no feedback:

$ emcc null-read.c
$ node a.out.js
$

With UBSan, you get the exact line number where this happened:

$ emcc -fsanitize=undefined null-assign.c
$ node a.out.js
null-read.c:3:9: runtime error: load of null pointer of type 'int'

Minimal Runtime

UBSan’s runtime is non-trivial, and its use can unnecessarily increase the attack surface. For this reason, there is a minimal UBSan runtime that is designed for production uses.

The minimal runtime is supported by Emscripten. To use it, pass the flag -fsanitize-minimal-runtime in addition to your -fsanitize flag.

$ emcc -fsanitize=null -fsanitize-minimal-runtime null-read.c
$ node a.out.js
ubsan: type-mismatch
$ emcc -fsanitize=null -fsanitize-minimal-runtime null-assign.c
$ node a.out.js
ubsan: type-mismatch
Runtime error: The application has corrupted its heap memory area (address zero)!

Address Sanitizer

Clang’s address sanitizer (ASan) is also available for use with Emscripten. This makes it much easier to catch buffer overflows, memory leaks, and other related bugs in your code.

To use ASan, simply pass -fsanitize=address to emcc or em++. As with UBSan, you need to pass this at both the compile and link stages, as it affects both codegen and system libraries.

You probably need to increase INITIAL_MEMORY to at least 64 MB or pass -s ALLOW_MEMORY_GROWTH so that ASan has enough memory to start. Otherwise, you will receive an error message that looks something like:

Cannot enlarge memory arrays to size 55152640 bytes (OOM). Either (1) compile with -s INITIAL_MEMORY=X with X higher than the current value 50331648, (2) compile with -s ALLOW_MEMORY_GROWTH=1 which allows increasing the size at runtime, or (3) if you want malloc to return NULL (0) instead of this abort, compile with -s ABORTING_MALLOC=0

ASan fully supports multi-thread environments.

Examples

Here are some examples of how AddressSanitizer can be used to help find bugs.

Buffer Overflow

Consider buffer_overflow.c:

#include <string.h>

int main(void) {
  char x[10];
  memset(x, 0, 11);
}
$ emcc -g4 -fsanitize=address -s ALLOW_MEMORY_GROWTH buffer_overflow.c
$ node a.out.js
=================================================================
==42==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x02965e5a at pc 0x000015f0 bp 0x02965a30 sp 0x02965a30
WRITE of size 11 at 0x02965e5a thread T0
    #0 0x15f0 in __asan_memset+0x15f0 (a.out.wasm+0x15f0)
    #1 0xc46 in __original_main stack_buffer_overflow.c:5:3
    #2 0xcbc in main+0xcbc (a.out.wasm+0xcbc)
    #3 0x800019bc in Object.Module._main a.out.js:6588:32
    #4 0x80001aeb in Object.callMain a.out.js:6891:30
    #5 0x80001b25 in doRun a.out.js:6949:60
    #6 0x80001b33 in run a.out.js:6963:5
    #7 0x80001ad6 in runCaller a.out.js:6870:29

Address 0x02965e5a is located in stack of thread T0 at offset 26 in frame
    #0 0x11  (a.out.wasm+0x11)

  This frame has 1 object(s):
    [16, 26) 'x' (line 4) <== Memory access at offset 26 overflows this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
      (longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow (a.out.wasm+0x15ef)
...

Use After Free

Consider use_after_free.cpp:

int main() {
  int *array = new int[100];
  delete [] array;
  return array[0];
}
$ em++ -g4 -fsanitize=address -s ALLOW_MEMORY_GROWTH use_after_free.cpp
$ node a.out.js
=================================================================
==42==ERROR: AddressSanitizer: heap-use-after-free on address 0x03203e40 at pc 0x00000c1b bp 0x02965e70 sp 0x02965e7c
READ of size 4 at 0x03203e40 thread T0
    #0 0xc1b in __original_main use_after_free.cpp:4:10
    #1 0xc48 in main+0xc48 (a.out.wasm+0xc48)

0x03203e40 is located 0 bytes inside of 400-byte region [0x03203e40,0x03203fd0)
freed by thread T0 here:
    #0 0x5fe8 in operator delete[](void*)+0x5fe8 (a.out.wasm+0x5fe8)
    #1 0xb76 in __original_main use_after_free.cpp:3:3
    #2 0xc48 in main+0xc48 (a.out.wasm+0xc48)
    #3 0x800019b5 in Object.Module._main a.out.js:6581:32
    #4 0x80001ade in Object.callMain a.out.js:6878:30
    #5 0x80001b18 in doRun a.out.js:6936:60
    #6 0x80001b26 in run a.out.js:6950:5
    #7 0x80001ac9 in runCaller a.out.js:6857:29

previously allocated by thread T0 here:
    #0 0x5db4 in operator new[](unsigned long)+0x5db4 (a.out.wasm+0x5db4)
    #1 0xb41 in __original_main use_after_free.cpp:2:16
    #2 0xc48 in main+0xc48 (a.out.wasm+0xc48)
    #3 0x800019b5 in Object.Module._main a.out.js:6581:32
    #4 0x80001ade in Object.callMain a.out.js:6878:30
    #5 0x80001b18 in doRun a.out.js:6936:60
    #6 0x80001b26 in run a.out.js:6950:5
    #7 0x80001ac9 in runCaller a.out.js:6857:29

SUMMARY: AddressSanitizer: heap-use-after-free (a.out.wasm+0xc1a)
...

Memory Leaks

Consider leak.cpp:

int main() {
  new int[10];
}
$ em++ -g4 -fsanitize=address -s ALLOW_MEMORY_GROWTH -s EXIT_RUNTIME leak.cpp
$ node a.out.js

=================================================================
==42==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 40 byte(s) in 1 object(s) allocated from:
    #0 0x5ce5 in operator new[](unsigned long)+0x5ce5 (a.out.wasm+0x5ce5)
    #1 0xb24 in __original_main leak.cpp:2:3
    #2 0xb3a in main+0xb3a (a.out.wasm+0xb3a)
    #3 0x800019b8 in Object.Module._main a.out.js:6584:32
    #4 0x80001ae1 in Object.callMain a.out.js:6881:30
    #5 0x80001b1b in doRun a.out.js:6939:60
    #6 0x80001b29 in run a.out.js:6953:5
    #7 0x80001acc in runCaller a.out.js:6860:29

SUMMARY: AddressSanitizer: 40 byte(s) leaked in 1 allocation(s).

Note that since leak checks take place at program exit, you must use -s EXIT_RUNTIME, or invoke __lsan::DoLeakCheck manually.

You can detect that AddressSanitizer is enabled and run __lsan::DoLeakCheck by doing:

#if defined(__has_feature)
#if __has_feature(address_sanitizer)
  // code for ASan-enabled builds
  __lsan::DoLeakCheck();
#endif
#endif

Also, if you only want to check for memory leaks, you may use -fsanitize=leak instead of -fsanitize=address. -fsanitize=leak does not instrument all memory accesses, and as a result is much faster than -fsanitize=address.

Use After Return

Consider use_after_return.c:

#include <stdio.h>

const char *__asan_default_options() {
  return "detect_stack_use_after_return=1";
}

int *f() {
  int buf[10];
  return buf;
}

int main() {
  *f() = 1;
}

Note that to do this check, you have to use the ASan option detect_stack_use_after_return. You may enable this option by declaring a function called __asan_default_options like the example, or you can define Module['ASAN_OPTIONS'] = 'detect_stack_use_after_return=1' in the generated JavaScript. --pre-js is helpful here.

This option is fairly expensive because it converts stack allocations into heap allocations, and these allocations are not reused so that future accesses can cause traps. Hence, it is not enabled by default.

$ emcc -g4 -fsanitize=address -s ALLOW_MEMORY_GROWTH=1 use_after_return.c
$ node a.out.js
=================================================================
==42==ERROR: AddressSanitizer: stack-use-after-return on address 0x02a95010 at pc 0x00000d90 bp 0x02965f70 sp 0x02965f7c
WRITE of size 4 at 0x02a95010 thread T0
    #0 0xd90 in __original_main use_after_return.c:13:10
    #1 0xe0a in main+0xe0a (a.out.wasm+0xe0a)

Address 0x02a95010 is located in stack of thread T0 at offset 16 in frame
    #0 0x11  (a.out.wasm+0x11)

  This frame has 1 object(s):
    [16, 56) 'buf' (line 8) <== Memory access at offset 16 is inside this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
      (longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-use-after-return (a.out.wasm+0xd8f)
...

Configuration

ASan can be configured via a --pre-js file:

Module.ASAN_OPTIONS = 'option1=a:option2=b';

For example, put the above snippet with your options into asan_options.js, and compile with --pre-js asan_options.js.

For standalone LSan, use Module.LSAN_OPTIONS instead.

For a detailed understanding of the flags, see the ASan documentation. Please be warned that most flag combinations are not tested and may or may not work.

Disabling malloc/free Stack Traces

In a program that uses malloc/free (or their C++ equivalent, operator new/operator delete) very frequently, taking a stack trace at all invocations to malloc/free can be very expensive. As a result, if you find your program to be very slow when using ASan, you can try using the option malloc_context_size=0, like this:

Module.ASAN_OPTIONS = 'malloc_context_size=0';

This prevents ASan from reporting the location of memory leaks, as well as offer insight into where the memory for a heap-based memory error originated, but may provide tremendous speed ups.

Building Emscripten from Source

Building Emscripten yourself is an alternative to getting binaries using the emsdk.

Emscripten’s core codebase, which is in the main “emscripten” repo, does not need to be compiled (it uses Python for most of the scripting that glues together all the tools). What do need to be compiled are LLVM (which in particular provides clang and wasm-ld) and Binaryen. After compiling them, simply edit the .emscripten file to point to the right place for each of those tools (if the file doesn’t exist yet, run emcc for the first time).

Get the master branches, or check the Packaging instructions to identify precise commits in existing releases.

Building LLVM

For using the LLVM wasm backend (recommended), simply build normal upstream LLVM from the monorepo. Include clang and wasm-ld (using something like -DLLVM_ENABLE_PROJECTS='lld;clang') and the wasm backend (which is included by default; just don’t disable it), following that project’s instructions. For example, something like this can work:

mkdir build
cd build/
cmake ../llvm -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_PROJECTS='lld;clang' -DLLVM_TARGETS_TO_BUILD="host;WebAssembly" -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF
cmake --build .

Then point LLVM_ROOT in .emscripten to <llvm_src>/build/bin (no need to install).

Please refer to the upstream docs for more detail.

For using the older fastcomp backend, see the fastcomp docs.

Building Binaryen

See the Binaryen build instructions.

Emscripten Toolchain Requirements

The instructions below list the main tools and dependencies in an Emscripten environment, along with instructions on how to test which dependencies are installed.

Tip

The SDK provides the easiest and most reliable method for getting, using, updating and managing Emscripten environments. If you’re using the SDK you won’t need these instructions — they are provided for information only.

The instructions below are useful if you’re manually building from source.

What you’ll need

Emscripten tools and dependencies

In general a complete Emscripten environment requires the following tools. First test to see if they are already installed using the instructions below.

Note

The Spidermonkey shell is also required if you want to run 100% of the tests in the test suite. Most developers will not need this, and should instead use node.js.

Compiler toolchain

When building Emscripten from source code, whether “manually” or using the SDK, you will need a compiler toolchain:

  • Windows: Install Visual Studio 2017 and cmake.

    Note

    • SDK users can also install and activate the MinGW compiler toolchain in order to build their own projects:

      emsdk install mingw-4.6.2-32bit
      emsdk activate mingw-4.6.2-32bit
      
  • Linux: Install gcc and cmake:

    #Install gcc
    sudo apt-get install build-essential
    # Install cmake
    sudo apt-get install cmake
    
  • macOS: Install the Xcode Command Line Tools:

    • Install Xcode from the macOS App Store.
    • In Xcode | Preferences | Downloads, install Command Line Tools.

Note

Building LLVM and Clang from source can require a lot of memory and hard drive space. The specific requirements change from LLVM version to another, but you probably need at least 2GB of RAM, preferably 4GB or more. Debug builds or builds with assertions can require even more memory.

Test which tools are installed

Some of the tools are pre-installed on the various platforms (for example, Python is always available on Linux builds).

You can check which tools are already present using the following commands:

# Check for Python
python --version

# Check for node.js on Linux
nodejs --version

# Check for node.js on Windows
node --version

# Check for node.js on macOS
node -v

# Check for git
git --version

# Check for Java
java -version

# Check for gcc / g++
gcc --version
g++

# Check for cmake
cmake

Manually building Fastcomp from source

Fastcomp is the second compiler core used in Emscripten, after the original JS compiler and before the new LLVM wasm backend. We recommend the LLVM wasm backend, but fastcomp is still useful in some cases, and is installable using the emsdk. This article explains how you can build Fastcomp’s sources using a fully manual process.

Note

If you are building a large project, you will need to create a 64-bit build of LLVM and Clang. Compiling and optimizing can take more memory than is available to the 32-bit build.

What you’ll need

First verify you have the compiler toolchain for your platform, download and install it as necessary.

Then follow the instructions for your platform showing how to manually build Emscripten from source. This page helps you with the specific task of building fastcomp (LLVM + clang).

Building Fastcomp

To build the Fastcomp code from source:

  • Create a directory to store the build. It doesn’t matter where, because Emscripten gets the information from the compiler configuration file (~/.emscripten). We show how to update this file later in these instructions:
mkdir myfastcomp
cd myfastcomp
  • Clone the fastcomp LLVM repository (https://github.com/emscripten-core/emscripten-fastcomp):

    git clone https://github.com/emscripten-core/emscripten-fastcomp
    
  • Clone the emscripten-core/emscripten-fastcomp-clang repository into emscripten-fastcomp/tools/clang:

    cd emscripten-fastcomp
    git clone https://github.com/emscripten-core/emscripten-fastcomp-clang tools/clang
    

    Warning

    You must clone it into a directory named clang as shown, so that Clang is present in tools/clang!

  • Create a build directory (inside the emscripten-fastcomp directory) and then navigate into it:

    mkdir build
    cd build
    
  • Configure the build using cmake:

    cmake .. -DCMAKE_BUILD_TYPE=Release -DLLVM_TARGETS_TO_BUILD="host;JSBackend" -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DCLANG_INCLUDE_TESTS=OFF
    

    Note

    On Windows you will need Visual Studio 2015 or newer to build.

  • Determine the number of available cores on your system (Emscripten can run many operations in parallel, so using more cores may have a significant impact on compilation time):

    • On macOS you can get the number of cores using: Apple menu | About this mac | More info | System report. The Hardware overview on the resulting dialog includes a Total number of cores entry.
    • On Linux you can find the number of cores by entering the following command on the terminal: cat /proc/cpuinfo | grep "^cpu cores" | uniq.
    • On Windows the number of cores is listed on the Task Manager | Performance Tab. You can open the Task Manager by entering Ctrl + Shift + Esc from the Desktop.
  • Call make to build the sources, specifying the number of available cores:

    make -j4
    

    Note

    If the build completes successfully, clang, clang++, and a number of other files will be created in the release directory (<LLVM root>/build/Release/bin).

  • The final step is to update the ~/.emscripten file, specifying the location of fastcomp in the LLVM_ROOT variable.

    Note

    If you’re building the whole of Emscripten from source, following the platform-specific instructions in Building Emscripten from Source, you won’t yet have Emscripten installed. In this case, skip this step and return to those instructions.

    If you already have an Emscripten environment (for example if you’re building Fastcomp using the SDK), then set LLVM_ROOT to the location of the clang binary under the build directory. This will be something like <LLVM root>/build/Release/bin or <LLVM root>/build/bin:

    LLVM_ROOT='/home/ubuntu/yourpath/emscripten-fastcomp/build/bin'
    
Branches

You should use the same branch (incoming, or master) for building all three repositories:

Mixing incoming and master branches may result in errors when building the three repositories.

Run emcc -v to check if the branches are synchronized.

Note

emcc -v checks the code in the repositories, not the builds. Before building make sure that you fetch the latest changes to LLVM and Clang.

Version numbers

Bisecting across multiple git trees can be hard. We use version numbers to help synchronize points between them:

Version numbers are typically X.Y.Z where.

Backend code structure

The backend is in emscripten-fastcomp. The main file is JSBackend.cpp but the other files in that directory (lib/Target/JSBackend/) are also important.

Configuring Emscripten Settings when Manually Building from Source

The compiler settings used by Emscripten are defined in the compiler configuration file (~/.emscripten). These settings include paths to the tools (LLVM, Clang, Java, etc.) and the compiler’s temporary directory for intermediate build files.

This article explains how to create and update the file when you are building Emscripten manually from source.

Creating the compiler configuration file

The settings file is created the first time a user runs emcc (or any of the other Emscripten tools):

  1. Navigate to the directory where you cloned the Emscripten repository.

  2. Enter the command:

    ./emcc --help
    

    You should get a Welcome to Emscripten! message. Behind the scenes, Emscripten generates a file called .emscripten in your home folder.

Emscripten makes a “best guess” at the correct locations for tools and updates the file appropriately. Where possible it will look for “system” apps (like Python and Java).

The file will probably not include the link to Fastcomp (LLVM_ROOT) as a manual source build can create this anywhere.

Locating the compiler configuration file (.emscripten)

The settings file is created in the user’s home directory:

  • On Linux and macOS this file is named ~/.emscripten, where ~ is the user’s home directory.

    Note

    Files with the “.” prefix are hidden by default. You may need to change your view settings to find the file.

  • On Windows the file can be found at a path like: C:/Users/yourusername_000/.emscripten.

Compiler configuration file-format

Note

While the syntax is identical, the appearance of the default .emscripten file created by emcc is quite different than that created by emsdk. This is because emsdk manages multiple target environments, and where possible hard codes the locations of those tools when a new environment is activated. The default file, by contrast, is managed by the user — and is designed to make that task as easy as possible.

The file simply assigns paths to a number of variables representing the main tools used by Emscripten. For example, if the user installed python to the C:/Python27/ directory, then the file might have the line:

PYTHON = 'C:\\Python38\\python.exe'

The default emcc configuration file often gets the paths from environment variables if defined. If no variable is defined the system will also attempt to find “system executables”. For example:

PYTHON = os.path.expanduser(os.getenv('PYTHON', 'C:\\Python38\\python.exe'))

You can find out the other variable names from the default .emscripten file or the example here.

Editing the compiler configuration file

The compiler configuration file can be edited with the text editor of your choice. As stated above, most default settings are likely to be correct. If you’re building manually from source, you are most likely to have to update the variable LLVM_ROOT (for Fastcomp).

  1. Edit the variable LLVM_ROOT to point to the directory where you built Fastcomp. This path is likely to be something like <LLVM root>/build/Release/bin or <LLVM root>/build/bin, where <LLVM root> is the path to the directory where you cloned LLVM:

    LLVM_ROOT = os.path.expanduser(os.getenv('LLVM', '/home/ubuntu/a-path/emscripten-fastcomp/build/bin'))
    

    Note

    Use forward slashes!

After setting those paths, run emcc again. It should again perform the sanity checks to test the specified paths. There are further validation tests available at Verifying the Emscripten Development Environment.

Verifying the Emscripten Development Environment

After you’ve installed the SDK or built an Emscripten development environment from sources, the compiler should just work! This section shows how to verify that the environment has been set up correctly, and how to troubleshoot installation problems when they do occur.

Testing the environment

Sanity tests

The first step in verifying the environment is to run Emscripten with the version command (-v). The command prints out information about the toolchain and runs some basic sanity tests to check that the required tools are available.

Open a terminal in the directory in which you installed Emscripten (on Windows open the Emscripten Command Prompt). Then call the Emscripten Compiler Frontend (emcc) as shown:

./emcc -v

Note

On Windows, invoke the tool with emcc instead of ./emcc.

For example, the following output reports an installation where Java is missing::
emphasize-lines:
 6

emcc (Emscripten GCC-like replacement + linker emulating GNU ld ) 1.21.0 clang version 3.3 Target: x86_64-pc-win32 Thread model: posix INFO root: (Emscripten: Running sanity checks) WARNING root: java does not seem to exist, required for closure compiler. -O2 and above will fail. You need to define JAVA in ~/.emscripten

At this point you need to Install and activate any missing components. When everything is set up properly, emcc -v should give no warnings, and if you just enter emcc (without any input files), it should only give the following warning:

WARNING  root: no input files
Build a basic example

The next test is to actually build some code! On the command prompt navigate to the Emscripten directory for the current SDK and try to build the hello_world.cpp test code:

cd emscripten/<version of emscripten you installed>
./emcc tests/hello_world.cpp

This command should complete without warnings and you should find the newly-compiled JavaScript file (a.out.js) in the current directory.

If compiling succeeds, you’re ready for the Emscripten Tutorial. If not, check out the troubleshooting instructions below.

Run the full test suite

Emscripten has a comprehensive test suite which may be used to further validate all or parts of the toolchain. For more information, see Emscripten Test Suite.

Troubleshooting

First run ./emcc -v and examine the output to find missing components. You can also try ./emcc --clear-cache to empty the compiler’s internal cache and reset it to a known good state.

Installing missing components

Missing tools can often be added using the Emscripten SDK (emsdk). For example, to fix a warning that Java is missing, locate it in the repository, install it, and then set it as active:

#List all the components. Look for the missing component (in this case "java-7.45-64bit")
./emsdk list

#Install the missing component
./emsdk install java-7.45-64bit

#Set the component as active
./emsdk activate java-7.45-64bit

If you’re building Emscripten manually from source, see that link for information on how to obtain all dependencies.

Other common problems

Other common problems to check for are:

  • Errors in the paths in .emscripten. These are less likely if you update the file using emsdk.
  • Using older versions of Node or JavaScript engines. Use the default versions for the SDK as listed with emsdk list.
  • Using older versions of LLVM. The correct versions come with the SDK, but if you’re building the environment from source you should make sure to use the proper version of LLVM (which you can find using the emscripten-releases DEPS file and history; other versions might work, especially close-by ones, but are not tested by us and so not guaranteed to work).

If none of the above is helpful, then please contact us for help.

Contributing to Emscripten

This section contains articles that are relevant to anyone who wants to contribute to Emscripten and help improve the project.

  • Contributing provides an introduction to contributing, along with a few ideas for how you can help.
  • The Developer’s Guide contains contributor-relevant information, covering compiler operation and submitting patches to the Emscripten repositories.
  • AUTHORS is a list of all Emscripten contributors. If you contribute you must accept the project’s open source licenses (MIT/LLVM) and add yourself to the list!

Contributing

Anyone can contribute to Emscripten — if you find it useful and want to help improve the project, follow the suggestions below.

Feel free to file bug reports, join the discussion and share your own ideas with the community!

Getting started

A good starting point is to work on the open issues on GitHub. Many issues can be resolved without an in-depth knowledge of compiler internals, and this is a great way to learn more about the project.

Tip

We really appreciate your help. Every existing issue closed means more time for the core contributors to work on new features, optimizations and other enhancements.

In addition to improving the toolchain, you can also review and update this documentation.

Next steps

As a new contributor you should read the Developer’s Guide. You may also need to install Emscripten from source and become familiar with Debugging and Building Projects.

Please get in touch with the community to share your ideas and work out where you can make the most difference.

Developer’s Guide

This article provides information that is relevant to people who want to contribute to Emscripten. We welcome contributions from anyone that is interested in helping out!

Tip

The information will be less relevant if you’re just using Emscripten, but may still be of interest.

Setting up

For contributing to core Emscripten code, such as emcc.py, you don’t need to build any binaries as emcc.py is in Python, and the core JS generation is in JavaScript. You do still need binaries for LLVM and Binaryen, which you can get using the emsdk:

emsdk install tot-upstream
emsdk activate tot-upstream

That gets a “tip-of-tree” build of the very latest binaries. You can use those binaries with a checkout of the core Emscripten repository, simply by calling emcc.py from that checkout, and it will use the binaries from the emsdk.

If you do want to contribute to LLVM or Binaryen, or to test modifications to them, you can build them from source.

Repositories and branches of interest

The Emscripten main repository is https://github.com/emscripten-core/emscripten.

Aside from the Emscripten repo, the other codebases of interest are LLVM and Binaryen, which Emscripten invokes, and have their own repos.

Submitting patches

Patches should be submitted as pull requests to the master branch.

Note

Before submitting your first patch, add yourself to the AUTHORS file. By doing so, you agree to license your code under the project’s open source licenses (MIT/LLVM).

When submitting patches, please:

  • Make pull requests to master.
  • Add an automatic test if you add any new functionality or fix a bug. Search in tests/*.py for related tests, as often the simplest thing is to add to an existing one. If you’re not sure how to test your code, feel free to ask for help.
  • We normally squash and merge PRs, which means the PR turns into a single commit on the target branch. Because of that, it’s ok to have merge commits in the PR itself, as they get removed. Please put a good description for the final commit in the PR description, and we’ll use it when squashing.

Code reviews

One of the core developers will review a pull request before merging it. If several days pass without any comments on your PR, please comment in the PR which will ping them. (If that happens, sorry! Sometimes things get missed.)

Compiler overview

The Emscripten Compiler Frontend (emcc) is a python script that manages the entire compilation process:

  • emcc calls Clang to compile C++ and wasm-ld to link it. It builds and integrates with the Emscripten system libraries, both the compiled ones and the ones implemented in JS.
  • emcc then calls emscripten.py which performs the final transformation to wasm (including invoking wasm-emscripten-finalize from Binaryen) and calls the JS compiler (see src/compiler.js and related files) which emits the JS.
  • If optimizing wasm, emcc will then call wasm-opt, run meta-dce, and other useful things. It will also run JS optimizations on the JS that is emitted alongside the wasm.

Emscripten Test Suite

Emscripten has a comprehensive test suite, which covers virtually all Emscripten functionality. These tests are run on CI automatically when you create a pull request, and they should all pass. If you run into trouble with a test failure you can’t fix, please let the developers know.

AUTHORS

The AUTHORS file lists everyone who has contributed to Emscripten.

Note

Authors must add themselves to the AUTHORS file (master branch) before contributing. This act licenses their changes under the project’s open source licenses (MIT/LLVM). Note that the developer retains copyright.

The contributors for releases up to Emscripten 1.39.16 inclusive (May 19, 2020) are listed below.

The following authors have all licensed their contributions to Emscripten
under the licensing terms detailed in LICENSE.

(Authors keep copyright of their contributions, of course; they just grant
a license to everyone to use it as detailed in LICENSE.)

* Alon Zakai <[email protected]> (copyright owned by Mozilla Foundation)
* Tim Dawborn <[email protected]>
* Max Shawabkeh <[email protected]>
* Sigmund Vik <[email protected]>
* Jeff Terrace <[email protected]>
* Benoit Tremblay <[email protected]>
* Andreas Bergmeier <[email protected]>
* Ben Schwartz <[email protected]>
* David Claughton <[email protected]>
* David Yip <[email protected]>
* Julien Hamaide <[email protected]>
* Ehsan Akhgari <[email protected]> (copyright owned by Mozilla Foundation)
* Adrian Taylor <[email protected]>
* Richard Assar <[email protected]>
* Nathan Hammond <[email protected]>
* Behdad Esfahbod <[email protected]>
* David Benjamin <[email protected]>
* Pierre Renaux <[email protected]>
* Brian Anderson <[email protected]>
* Jon Bardin <[email protected]>
* Jukka Jylänki <[email protected]>
* Aleksander Guryanov <[email protected]>
* Chad Austin <[email protected]> (copyright owned by IMVU)
* nandhp <[email protected]>
* YeZhongWen <[email protected]>
* Xingxing Pan <[email protected]>
* Justin Kerk <[email protected]>
* Andrea Bedini <[email protected]>
* James Pike <[email protected]>
* Mokhtar Naamani <[email protected]>
* Benjamin Stover <[email protected]>
* Riccardo Magliocchetti <[email protected]>
* Janus Troelsen <[email protected]>
* Lars Schneider <[email protected]> (copyright owned by Autodesk, Inc.)
* Joel Martin <[email protected]>
* Manuel Wellmann <[email protected]> (copyright owned by Autodesk, Inc.)
* Xuejie Xiao <[email protected]>
* Dominic Wong <[email protected]>
* Alan Kligman <[email protected]> (copyright owned by Mozilla Foundation)
* Anthony Liot <[email protected]>
* Michael Riss <[email protected]>
* Jasper St. Pierre <[email protected]>
* Manuel Schölling <[email protected]>
* Bruce Mitchener, Jr. <[email protected]>
* Michael Bishop <[email protected]>
* Roger Braun <[email protected]>
* Vladimir Vukicevic <[email protected]> (copyright owned by Mozilla Foundation)
* Lorant Pinter <[email protected]>
* Tobias Doerffel <[email protected]>
* Martin von Gagern <[email protected]>
* Ting-Yuan Huang <[email protected]>
* Joshua Granick <[email protected]>
* Felix H. Dahlke <[email protected]>
* Éloi Rivard <[email protected]>
* Alexander Gladysh <[email protected]>
* Arlo Breault <[email protected]>
* Jacob Lee <[email protected]> (copyright owned by Google, Inc.)
* Joe Lee <[email protected]> (copyright owned by IMVU)
* Andy Friesen <[email protected]> (copyright owned by IMVU)
* Bill Welden <[email protected]> (copyright owned by IMVU)
* Michael Ey <[email protected]> (copyright owned by IMVU)
* Llorens Marti Garcia <[email protected]> (copyright owned by IMVU)
* Jinsuck Kim <[email protected]> (copyright owned by IMVU)
* Todd Lee <[email protected]> (copyright owned by IMVU)
* Anthony Pesch <[email protected]>
* Robert Bragg <[email protected]> (copyright owned by Intel Corporation)
* Sylvestre Ledru <[email protected]>
* Tom Fairfield <[email protected]>
* Anthony J. Thibault <[email protected]>
* John Allwine <[email protected]>
* Martin Gerhardy <[email protected]>
* James Gregory <[email protected]> (copyright owned by Zynga, Inc.)
* Dan Gohman <[email protected]> (copyright owned by Google, Inc.)
* Jeff Gilbert <[email protected]> (copyright owned by Mozilla Foundation)
* Frits Talbot <[email protected]>
* Onno Jongbloed <[email protected]>
* Jez Ng <[email protected]>
* Marc Feeley <[email protected]> (copyright owned by Mozilla Foundation)
* Ludovic Perrine <[email protected]>
* David Barksdale <[email protected]>
* Manfred Manik Nerurkar <nerurkar*at*made-apps.biz> (copyright owned by MADE, GmbH)
* Joseph Gentle <[email protected]>
* Douglas T. Crosher <[email protected]> (copyright owned by Mozilla Foundation)
* Douglas T. Crosher <[email protected]> (copyright owned by Scieneer Pty Ltd.)
* Soeren Balko <[email protected]> (copyright owned by Clipchamp Pty Ltd.)
* Ryan Kelly ([email protected])
* Michael Lelli <[email protected]>
* Yu Kobayashi <[email protected]>
* Pin Zhang <[email protected]>
* Nick Bray <[email protected]> (copyright owned by Google, Inc.)
* Aidan Hobson Sayers <[email protected]>
* Charlie Birks <[email protected]>
* Ranger Harke <[email protected]> (copyright owned by Autodesk, Inc.)
* Tobias Vrinssen <[email protected]>
* Patrick R. Martin <[email protected]>
* Richard Quirk <[email protected]>
* Marcos Scriven <[email protected]>
* Antoine Lambert <[email protected]>
* Daniel Aquino <[email protected]>
* Remi Papillie <[email protected]>
* Fraser Adams <[email protected]>
* Michael Tirado <[email protected]>
* Ben Noordhuis <[email protected]>
* Bob Roberts <[email protected]>
* John Vilk <[email protected]>
* Daniel Baulig <[email protected]> (copyright owned by Facebook, Inc.)
* Lu Wang <[email protected]>
* Heidi Pan <[email protected]> (copyright owned by Intel)
* Vasilis Kalintiris <[email protected]>
* Adam C. Clifton <[email protected]>
* Volo Zyko <[email protected]>
* Andre Weissflog <[email protected]>
* Alexandre Perrot <[email protected]>
* Emerson José Silveira da Costa <[email protected]>
* Jari Vetoniemi <[email protected]>
* Sindre Sorhus <[email protected]>
* James S Urquhart <[email protected]>
* Boris Gjenero <[email protected]>
* jonas echterhoff <[email protected]>
* Sami Vaarala <[email protected]>
* Jack A. Arrington <[email protected]>
* Richard Janicek <[email protected]>
* Joel Croteau <[email protected]>
* Haneef Mubarak <[email protected]>
* Nicolas Peri <[email protected]> (copyright owned by ShiVa Technologies, SAS)
* Bernhard Fey <[email protected]>
* Dave Nicponski <[email protected]>
* Jonathan Jarri <[email protected]>
* Daniele Di Proietto <[email protected]>
* Dan Dascalescu <[email protected]>
* Thomas Borsos <[email protected]>
* Ori Avtalion <[email protected]>
* Guillaume Blanc <[email protected]>
* Usagi Ito <[email protected]>
* Camilo Polymeris <[email protected]>
* Markus Henschel <[email protected]>
* Ophir Lojkine <[email protected]>
* Ryan Sturgell <[email protected]> (copyright owned by Google, Inc.)
* Jason Green <[email protected]> (copyright owned by TransGaming, Inc.)
* Ningxin Hu <[email protected]> (copyright owned by Intel)
* Nicolas Guillemot <[email protected]>
* Sathyanarayanan Gunasekaran <[email protected]> (copyright owned by Mozilla Foundation)
* Nikolay Vorobyov <[email protected]>
* Jonas Platte <[email protected]>
* Sebastien Ronsse <[email protected]>
* Glenn R. Wichman <[email protected]>
* Hamish Willee <[email protected]> (copyright owned by Mozilla Foundation)
* Sylvain Chevalier <[email protected]>
* Nathan Ross <[email protected]>
* Zachary Pomerantz <[email protected]>
* Boris Tsarev <[email protected]>
* Mark Logan <[email protected]> (copyright owned by Artillery Games, Inc.)
* Коренберг Марк <[email protected]>
* Gauthier Billot <[email protected]>
* Árpád Goretity <[email protected]>
* Nicholas Wilson <[email protected]>
* Aaron Mandle <[email protected]>
* Bailey Hayes <[email protected]> (copyright owned by SAS Institute Inc.)
* Paul Holland <[email protected]>
* James Long <[email protected]>
* David Anderson <[email protected]> (copyright owned by Mozilla Foundation)
* Eric Rannaud <[email protected]> (copyright owned by Nanocritical Corp.)
* William Furr <[email protected]> (copyright owned by Google, Inc.)
* Dan Glastonbury <[email protected]> (copyright owned by Mozilla Foundation)
* Warren Seine <[email protected]> (copyright owned by Aerys SAS)
* Petr Babicka <[email protected]>
* Akira Takahashi <[email protected]>
* Victor Costan <[email protected]>
* Pepijn Van Eeckhoudt <[email protected]> (copyright owned by Luciad NV)
* Stevie Trujillo <[email protected]>
* Edward Rudd <[email protected]>
* Rene Eichhorn <[email protected]>
* Nick Desaulniers <[email protected]> (copyright owned by Mozilla Foundation)
* Luke Wagner <[email protected]> (copyright owned by Mozilla Foundation)
* Matt McCormick <[email protected]>
* Thaddée Tyl <[email protected]>
* Philipp Wiesemann <[email protected]>
* Jan Jongboom <[email protected]> (copyright owned by Telenor Digital AS)
* Tiago Quelhas <[email protected]>
* Reinier de Blois <[email protected]>
* Yuichi Nishiwaki <[email protected]>
* Jérôme Bernard <[email protected]> (copyright owned by Ercom)
* Chanhwi Choi <[email protected]>
* Fábio Santos <[email protected]>
* Thibaut Despoulain <[email protected]> (copyright owned by Artillery Games, Inc.)
* Wei Tjong Yao <[email protected]>
* Tim Guan-tin Chien <[email protected]>
* Krzysztof Jakubowski <[email protected]>
* Vladimír Vondruš <[email protected]>
* Brion Vibber <[email protected]>
* Philip Lafleur <[email protected]>
* Javier Meseguer de Paz <[email protected]>
* Michael A. Balazs <[email protected]>
* Andreas Blixt <[email protected]>
* Haofeng Zhang <[email protected]>
* Cody Welsh <[email protected]>
* Hoong Ern Ng <[email protected]>
* Kagami Hiiragi <[email protected]>
* Jan Bölsche <[email protected]>
* Sebastian Matthes <[email protected]> (copyright owned by Volkswagen AG)
* Robert Goulet <[email protected]> (copyright owned by Autodesk, Inc.)
* Juha Järvi <[email protected]>
* Louis Lagrange <[email protected]>
* Ying-Ruei Liang <[email protected]>
* Stuart Geipel <[email protected]>
* Yeonjun Lim <[email protected]>
* Andrew Karpushin <[email protected]>
* Felix Zimmermann <[email protected]>
* Sven-Hendrik Haase <[email protected]>
* Simon Sandström <[email protected]>
* Khaled Sami <[email protected]>
* Omar El-Mohandes <[email protected]>
* Florian Rival <[email protected]>
* Mark Achée <[email protected]>
* Piotr Paczkowski <[email protected]>
* Braden MacDonald <[email protected]>
* Kevin Cheung <[email protected]> (copyright owned by Autodesk, Inc.)
* Josh Peterson <[email protected]>
* eska <[email protected]>
* Nate Burr <[email protected]>
* Paul "TBBle" Hampson <[email protected]>
* Andreas Plesch <[email protected]>
* Brian Armstrong <[email protected]>
* Vincenzo Chianese <[email protected]>
* Noam T.Cohen <[email protected]>
* Nick Shin <[email protected]>
* Gregg Tavares <[email protected]>
* Tanner Rogalsky <[email protected]>
* Richard Cook <[email protected]> (copyright owned by Tableau Software, Inc.)
* Arnab Choudhury <[email protected]> (copyright owned by Tableau Software, Inc.)
* Charles Vaughn <[email protected]> (copyright owned by Tableau Software, Inc.)
* Pierre Krieger <[email protected]>
* Jakob Stoklund Olesen <[email protected]>
* Jérémy Anger <[email protected]>
* Derek Schuff <[email protected]> (copyright owned by Google, Inc.)
* Ashley Sommer <[email protected]>
* Dave Fletcher <[email protected]>
* Lars-Magnus Skog <[email protected]>
* Pieter Vantorre <[email protected]>
* Maher Sallam <[email protected]>
* Andrey Burov <[email protected]>
* Holland Schutte <[email protected]>
* Kerby Geffrard <[email protected]>
* cynecx <[email protected]>
* Chris Gibson <[email protected]>
* Harald Reingruber <code*at*h-reingruber.at>
* Aiden Koss <[email protected]>
* Dustin VanLerberghe <[email protected]>
* Philip Bielby <[email protected]> (copyright owned by Jagex Ltd.)
* Régis Fénéon <[email protected]>
* Dominic Chen <[email protected]> (copyright owned by Google, Inc.)
* Junji Hashimoto <[email protected]>
* Heejin Ahn <[email protected]> (copyright owned by Google, Inc.)
* Andras Kucsma <[email protected]>
* Mateusz Borycki <[email protected]>
* Franklin Ta <[email protected]>
* Jacob Gravelle <[email protected]> (copyright owned by Google, Inc.)
* Kagami Sascha Rosylight <[email protected]>
* Benny Jacobs <[email protected]>
* Ray Brown <[email protected]>
* Christopher Serr <[email protected]>
* Aaron Ruß <[email protected]> (copyright owned by DFKI GmbH)
* Vilibald Wanča <[email protected]>
* Alex Hixon <[email protected]>
* Vladimir Davidovich <[email protected]>
* Yuriy Levchenko <[email protected]>
* Dmitry Tolmachov <[email protected]>
* Dylan McKay <[email protected]>
* Christophe Gragnic <[email protected]>
* Murphy McCauley <[email protected]>
* Anatoly Trosinenko <[email protected]>
* Brad Grantham <[email protected]>
* Sam Clegg <[email protected]> (copyright owned by Google, Inc.)
* Joshua Lind <[email protected]>
* Hiroaki GOTO as "GORRY" <[email protected]>
* Mikhail Kremnyov <[email protected]> (copyright owned by XCDS International)
* Tasuku SUENAGA a.k.a. gunyarakun <[email protected]>
* Vitorio Miguel Prieto Cilia <[email protected]>
* Evan Wallace <[email protected]>
* Henning Pohl <[email protected]>
* Tim Neumann <[email protected]>
* Ondrej Stava <[email protected]> (copyright owned by Google, Inc.)
* Jakub Jirutka <[email protected]>
* Loo Rong Jie <[email protected]>
* Jean-François Geyelin <[email protected]>
* Matthew Collins <[email protected]>
* Satoshi N. M <[email protected]>
* Ryan Speets <[email protected]>
* Fumiya Chiba <[email protected]>
* Ryan C. Gordon <[email protected]>
* Inseok Lee <[email protected]>
* Yair Levinson (copyright owned by Autodesk, Inc.)
* Matjaž Drolc <[email protected]>
* James Swift <[email protected]> (copyright owned by PSPDFKit GmbH)
* Ryan Lester <[email protected]> (copyright owned by Cyph, Inc.)
* Nikolay Zapolnov <[email protected]>
* Nazar Mokrynskyi <[email protected]>
* Yury Delendik <[email protected]> (copyright owned by Mozilla Foundation)
* Kenneth Perry <[email protected]>
* Jim Mussared <[email protected]>
* Dirk Vanden Boer <[email protected]>
* Mitchell Foley <[email protected]> (copyright owned by Google, Inc.)
* Oleksandr Chekhovskyi <[email protected]>
* Michael Siebert <[email protected]>
* Jonathan Hale <[email protected]>
* Etienne Brateau <[email protected]>
* Zhiming Wang <[email protected]>
* Jameson Ernst <[email protected]>
* Yoan Lecoq <[email protected]>
* Jiajie Hu <[email protected]> (copyright owned by Intel Corporation)
* Kamil Klimek <[email protected]>
* José Carlos Pujol <josecpujol(at)gmail.com>
* Dannii Willis <[email protected]>
* Erik Dubbelboer <[email protected]>
* Sergey Tsatsulin <[email protected]>
* varkor <[email protected]>
* Stuart Knightley <[email protected]>
* Amadeus Guo <[email protected]>
* Nathan Froyd <[email protected]> (copyright owned by Mozilla Foundation)
* Daniel Wirtz <[email protected]>
* Kibeom Kim <[email protected]>
* Marcel Klammer <[email protected]>
* Axel Forsman <[email protected]>
* Ebrahim Byagowi <[email protected]>
* Thorsten Möller <[email protected]>
* Michael Droettboom <[email protected]>
* Nicolas Bouquet <[email protected]>
* Miguel Saldivar <[email protected]>
* Gert Van Hoey <[email protected]>
* Valtteri Heikkilä <[email protected]>
* Daniel McNab <daniel.mcnab6+emcc(at)gmail.com>
* Tyler Limkemann <tslimkemann42 gmail.com>
* Ben Smith <[email protected]> (copyright owned by Google, Inc.)
* Sylvain Beucler <[email protected]>
* Patrik Weiskircher <[email protected]>
* Tobias Widlund <widlundtobias(at)gmail.com>
* Rob Fors <[email protected]>
* Mike Frysinger <[email protected]> (copyright owned by Google, Inc.)
* Sébasiten Crozet <[email protected]>
* Andrey Nagikh <[email protected]>
* Dzmitry Malyshau <[email protected]> (copyright owned by Mozilla Foundation)
* Bjorn Swenson <[email protected]>
* Ryhor Spivak <[email protected]>
* Jan Schär <[email protected]>
* Ryhor Spivak <[email protected]>
* Alexander Bich <[email protected]>
* Ashleigh Thomas <[email protected]>
* Veniamin Petrenko <[email protected]>
* Ian Henderson <[email protected]>
* Siim Kallas <[email protected]>
* Carl Woffenden <[email protected]> (copyright owned by Numfum GmbH)
* Patrick Berger <[email protected]> (copyright owned by Compusoft Group)
* Alexander Frank Lehmann <[email protected]> (copyright owned by Compusoft Group)
* Tommy Nguyen <[email protected]>
* Thomas Schander <[email protected]> (copyright owned by Enscape GmbH)
* Benjamin S. Rodgers <[email protected]>
* Paul Shapiro <[email protected]>
* Elmo Todurov <[email protected]>
* Zoltán Žarkov <[email protected]>
* Roman Yurchak <[email protected]>
* Hampton Maxwell <[email protected]>
* Eric Fiselier <[email protected]> (copyright owned by Google, Inc.)
* Sirapop Wongstapornpat <[email protected]>
* Matt Kane <[email protected]>
* Altan Özlü <[email protected]>
* Mary S <[email protected]>
* Martin Birks <[email protected]>
* Kirill Smelkov <[email protected]> (copyright owned by Nexedi)
* Lutz Hören <[email protected]>
* Pedro K Custodio <[email protected]>
* Nicolas Allemand <[email protected]>
* Gabriel Cuvillier <[email protected]>
* Thomas Lively <[email protected]> (copyright owned by Google, Inc.)
* Brandon Surmanski <[email protected]>
* Rian Hunter <[email protected]>
* Kai Ninomiya <[email protected]> (copyright owned by Google, Inc.)
* Mickaël Schoentgen <[email protected]>
* Renaud Leroy <[email protected]>
* Florian Stellbrink <[email protected]>
* Shane Peelar <[email protected]>
* Alessandro Pignotti <[email protected]>
* Zheng Tao Lee <[email protected]> (copyright owned by Autodesk, Inc.)
* Martina Kraus <[email protected]>
* Jacob Adelgren <[email protected]>
* Ingvar Stepanyan <[email protected]>
* Ben Trapani <[email protected]> (copyright owned by Microsoft, Inc.)
* Tim Lander <tim57282@hotmail.com>
* Jacob Greenfield <[email protected]>
* Joseph Kogut <[email protected]>
* Yi Zhang <[email protected]>
* Marc Abramowitz <[email protected]>
* Daniel Ruf <[email protected]>
* Timothy Trindle <[email protected]> (copyright owned by Microsoft, Inc.)
* Matthew Andres Moreno <[email protected]>
* Eric Mandel <[email protected]>
* Anthony Catel <[email protected]>
* Simon Cooper <[email protected]>
* Amir Rasouli <[email protected]>
* Nico Weber <[email protected]>
* Bas Doorn <[email protected]> (copyright owned by Keyn B.V.)
* Adam Bujalski <[email protected]> (copyright owned by Samsung Electronics)
* Guanzhong Chen <[email protected]> (copyright owned by Google, Inc.)
* Denis Serebro <[email protected]>
* Lucas Ramage <[email protected]>
* Andy Wingo <[email protected]> (copyright owned by Igalia)
* Philipp Gloor <[email protected]> (copyright owned by PDF Tools AG)
* Joshua Minter <[email protected]> (copyright owned by Clipchamp Pty Ltd.)
* Ferris Kwaijtaal <[email protected]>
* Konstantin Podsvirov <[email protected]>
* Eduardo Bart <[email protected]>
* Zoltan Varga <[email protected]> (copyright owned by Microsoft, Inc.)
* Fernando Serboncini <[email protected]>
* Christian Clauss <[email protected]> (copyright owned by IBM)
* Henry Kleynhans <[email protected]> (copyright owned by Bloomberg L.P.)
* FUJI Goro <[email protected]>
* Egor Suvorov <[email protected]> (copyright owned by think-cell Software GmbH)
* James Kuszmaul <[email protected]>
* Wei Mingzhi <[email protected]>
* Sergey karchevsky <[email protected]>
* Ajay Patel <[email protected]>
* Adrien Devresse <[email protected]>
* Petr Penzin <[email protected]> (copyright owned by Intel Corporation)
* Tayeb Al Karim <[email protected]> (copyright owned by Google, Inc.)
* Andrei Alexeyev <[email protected]>
* Cesar Guirao Robles <[email protected]>
* Ricky Claven <[email protected]>
* Mehdi Sabwat <[email protected]>
* MinganMuon <[email protected]>
* Jonathan Feinberg <[email protected]>
* Osman Turan <[email protected]>
* Jaikanth J <[email protected]>
* Gernot Lassnig <[email protected]>
* Christian Boos <[email protected]>
* Erik Scholz <[email protected]>
* Michael de Lang <[email protected]>
* Gergely Nagy <[email protected]>
* Jan Habermann <[email protected]>
* John Granström <[email protected]>
* Clemens Backes <[email protected]> (copyright owned by Google, Inc.)
* Tibor Klajnscek <[email protected]>
* Benjamin Golinvaux <[email protected]>
* Peter Salomonsen <[email protected]>
* Niklas Fiekas <[email protected]>
* Martín Lucas Golini <[email protected]>
* Bumsik Kim <[email protected]>
* Corentin Wallez <[email protected]> (copyright owned by Google, Inc.)
* Austin Eng <[email protected]> (copyright owned by Google, Inc.)
* Hugo Amiard <[email protected]>
* Diego Casorran <[email protected]>
* sssooonnnggg <[email protected]>
* Guillaume Racicot <[email protected]>
* SK Min <[email protected]>
* Fabio Alessandrelli <[email protected]>
* Kirill Gavrilov <[email protected]>
* Karl Semich <[email protected]>
* Louis DeScioli <[email protected]> (copyright owned by Google, LLC)
* Kleis Auke Wolthuizen <[email protected]>
* Michael Potthoff <[email protected]>
* Abigail Bunyan <[email protected]> (copyright owned by Microsoft Corporation)
* David García Paredes <[email protected]>
* Mike Swierczek <[email protected]>
* Vasily <[email protected]>
* Jānis Rūcis <[email protected]>
* rssqian <[email protected]>
* Shachar Langbeheim <[email protected]>
* Laurin Agostini <[email protected]>
* David Carlier <[email protected]>
* Paul Du <[email protected]> (copyright owned by ARSKAN)
* Piotr Doan <[email protected]>

Profiling the Toolchain

The toolchain interacts with a moderate amount of external tools and sublibraries, the exact set generally depends on which compilation and linker flags were used. If you are seeing abnormal compilation times, or if you are developing the Emscripten toolchain itself, it may be useful to profile the toolchain performance itself as it compiles your project. Emscripten has a built-in toolchain wide emprofile.py profiler that can be used for this purpose.

Quick Example

To try out the toolchain profiler, run the following set of commands:

cd path/to/emscripten
tools/emprofile.py --reset
export EM_PROFILE_TOOLCHAIN=1
emcc tests/hello_world.c -O3 -o a.html
tools/emprofile.py --graph

On Windows, replace the export keyword with set instead. The last command should generate a HTML file of form toolchain_profiler.results_yyyymmdd_hhmm.html that can be opened in the web browser to view the results.

Details

The toolchain profiler is active whenever the toolchain is invoked with the environment variable EM_PROFILE_TOOLCHAIN=1 being set. In this mode, each called tool will accumulate profiling instrumentation data to a set of .json files under the Emscripten temp directory.

Profiling Tool Commands

The command tools/emprofile.py --reset deletes all previously stored profiling data. Call this command to erase the profiling session to a fresh empty state. To start profiling, call Emscripten tool commands with the environment variable EM_PROFILE_TOOLCHAIN=1 set either system-wide as shown in the example, or on a per command basis, like this:

cd path/to/emscripten
tools/emprofile.py --reset
EM_PROFILE_TOOLCHAIN=1 emcc tests/hello_world.c -o a.bc
EM_PROFILE_TOOLCHAIN=1 emcc a.bc -O3 -o a.html
tools/emprofile.py --graph --outfile=myresults.html

Any number of commands can be profiled within one session, and when tools/emprofile.py --graph is finally called, it will pick up records from all Emscripten tool invocations up to that point. Calling --graph also clears the recorded profiling data.

The output HTML filename can be chosen with the optional --outfile=myresults.html parameter.

Instrumenting Python Scripts

In order for the toolchain to work, each “top level” Python script (a script that is directly called from the command line, or by a subprocess spawn) should have the following preamble in the beginning of the script:

from tools.toolchain_profiler import ToolchainProfiler
if __name__ == '__main__':
  ToolchainProfiler.record_process_start()

Additionally, at the end of the script when the script is about to exit, it should do so by explicitly calling either the sys.exit(<returncode>) function, or by calling the ToolchainProfiler.record_process_exit(<returncode>) function, whichever is more convenient for the script. The function ToolchainProfiler.record_process_exit() does not exit by itself, but only records that the process is quitting.

These two blocks ensure that the toolchain profiler will be aware of all tool invocations that occur. In the graphed output, the process spawns will be shown in green color.

Python Profiling Blocks

Graphing the subprocess start and end times alone might sometimes be a bit too coarse view into what is happening. In Python code, it is possible to hierarchically annotate individual blocks of code to break down execution into custom tasks. These blocks will be shown in blue in the output graph. To add a custom profiling block, use the Python with keyword to add a profile_block section:

with ToolchainProfiler.profile_block('my_custom_task'):
  do_some_tasks()
  call_another_function()
  more_code()

this_is_outside_the_block()

This will show the three functions in the same scope under a block ‘my_custom_task’ drawn in blue in the profiling swimlane.

In some cases it may be cumbersome to wrap the code inside a with section. For these scenarios, it is also possible to use low level C-style enter_block and exit_block statements.

ToolchainProfiler.enter_block('my_code_block')
try:
  do_some_tasks()
  call_another_function()
  more_code()
finally:
  ToolchainProfiler.exit_block('my_code_block')

However when using this form one must be cautious to ensure that each call to ToolchainProfiler.enter_block() is matched by exactly one call to ToolchainProfiler.exit_block() in all code flows, so wrapping the code in a try-finally statement is a good idea.

About this site

The site is built using Sphinx (1.2.2), the open source tool used to create the official Python documentation and many other sites. This is a very mature and stable tool, and was selected for, among other reasons, its support for defining API items and linking to them from code.

The site uses a custom theme, which is based on the Read the docs theme.

Searching the site

Searching returns topics that contain all the specified keywords.

Tip

Always start by searching for single words like “interacting” or “compiling”. Generally this will be enough to find the relevant document. If not, you can refine the search by adding additional terms.

Note

Searches that include characters like “-” and “+” will not work. There is no support for logical operators.

Reporting bugs

Please report documentation bugs as you would any other Emscripten bug. Help fix them by updating existing documents or by creating new ones.

Contributing to the site

Contributions to this site (and indeed any part of Emscripten) are welcome!

Check out the rest of this article for instructions on how to build the site and write and update articles.

Building the site

The site sources are stored on GitHub. Edits and additions should be submitted to this branch in the same way as any other change to the tool.

The site is published to the emscripten-core/emscripten-site gh-pages branch (GitHub pages).

Note

Remember to update the Build version for public builds.

Installing Sphinx

Notes for installing Sphinx are provided here.

Ubuntu

The version of Sphinx on Ubuntu package repository (apt-get) fails when building the site. This is an early version (1.1.3), which appears to be dependent on an old version of the Jinja templating library.

The workaround is to use the Python package installer (pip) to get version 1.7.8, and then run an upgrade (note, you may have to uninstall Sphinx first):

pip install sphinx==1.7.9

Site builds

The site can be built from source on Ubuntu and Windows by navigating to the /emscripten/site directory and using the command:

make clean
make html

SDK Builds

SDK builds are virtually identical to Site builds. The main difference is that on SDK builds the home page has a clear notification that it is an SDK build.

SDK builds are enabled by enabling the sdkbuild tag. This is done through the SPHINXOPTS environment variable:

# Set the sdkbuild tag.
set SPHINXOPTS=-t sdkbuild
make html

# Unset SPHINXOPTS
set SPHINXOPTS=

Build version

The documentation version should match the Emscripten version for the current build. For a general site build this will be the latest tagged release as defined in Emscripten version. For an SDK build it will be the Emscripten version for the SDK.

The version and release information is used in a few places in the documentation, for example AUTHORS.

The version information is defined in conf.py — see variables version and release. These variables can be overridden by setting new values in the SPHINXOPTS environment variable. For example, to update the release variable through the command line on Windows:

# Set SPHINXOPTS
set SPHINXOPTS=-D release=6.40
make html

# Unset SPHINXOPTS
set SPHINXOPTS=

Writing and updating articles

Note

Sphinx is well documented. This section only attempts to highlight specific styles and features used on this site.

The Building the site section explains how to find the sources for articles and build the site.

Site content is written using reStructured text. We recommend you read the following articles to understand the syntax:

Style guide

This section has a few very brief recommendations to help authors use common style.

Tip

In terms of contributions, we value your coding and content writing far more than perfect prose! Just do your best, and then ask for editorial review.

Spelling: Where possible use US-English spelling.

Avoid idiomatic expressions: These can be particularly confusing to non-native speakers (for example “putting your foot in your mouth” actually means “saying something embarrassing”).

Emphasis:

  • Bold : use for file names, and UI/menu instructions (for example: “Press OK to do something”).
  • Italic : use for tool names - e.g. Clang, emcc, Closure Compiler.
  • monotype : use for inline code (where you can’t link to the API reference) and for demonstrating tool command line options.

Note

Other than the above rules, emphasis should be used sparingly.

Lists: Use a colon on the lead-in to the list where appropriate. Capitalize the first letter and use a full-stop for each item.

Working in markdown

New articles may be authored and discussed on the wiki using Markdown syntax before being included in the documentation set. The easiest way to convert these to restructured text is to use a tool like Pandoc.

Note

The get_wiki.py tool (/site/source/get_wiki.py) can be used to automate getting a snapshot of the wiki. It clones the wiki and calls pandoc on each file. The output is copied to a folder wiki_static. The tool also adds a heading, a note stating that the file is a “wiki snapshot”, and fixes up links marked as “inline code” to matching links in the API Reference.

Read the docs theme

The site uses a modification of the Read the docs theme (this can be found in the source at /emscripten/site/source/_themes/emscripten_sphinx_rtd_theme).

The main changes to the original theme are listed below.

  • Footer.html
    • Copyright changed to link to Emscripten authors (some code was broken by translation markup)
    • Added footer menu bar
  • Layout.html
    • Added header menu bar with items
  • Breadcrumb.html
    • Changed the text of the first link from “docs” to “Home”
    • Moved the “View Page Source” code into the bottom footer
  • theme.css
    • Changed to support 4 levels of depth in sidebar toc.
    • Centred theme. Made sidebar reach bottom of page using absolute positioning.

Site license

The site is licensed under the same Open Source License as the rest of Emscripten. Contributors to the site should add themselves to AUTHORS.