Compile your existing projects written in C or C++ and run them on all modern browsers.
Home
» Emscripten 1.39.16 documentation
Compile your existing projects written in C or C++ and run them on all modern browsers.
Emscripten converts OpenGL into WebGL, and lets you use familiar APIs like SDL, or HTML5 directly.
Thanks to LLVM, Emscripten, asm.js and WebAssembly, code runs at near-native speed.
Interested to learn more? Read our About Page!
Ready to get started? Download and install the SDK and then proceed to the Tutorial!
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.
Emscripten is an Open Source LLVM to JavaScript compiler. Using Emscripten you can:
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:
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.
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.
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.
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.
Welcome to the Emscripten community!
The best ways contact the community are:
Feel free to ask questions, share your ideas, or just join the conversation!
Emscripten also has a presence on social media:
Bug reports can be posted in the GitHub Issue Tracker.
Anyone can contribute to Emscripten. We’ve got some ideas to get you started on our Contributing page!
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:
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/).
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.
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.
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.
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!)
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.shNote
On Windows, run
emsdk
instead of./emsdk
, andemsdk_env.bat
instead ofsource ./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.
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.)
Note
Instead of running emscripten on Windows directly, you can use the Windows Subsystem for Linux to run it in a Linux environment.
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.
- Install Xcode from the macOS App Store.
- In Xcode | Preferences | Downloads, install Command Line Tools.
- Make sure the OS allows installing git.
- Install Xcode and the Xcode Command Line Tools (should already have been done). This will provide git to the system PATH (see this stackoverflow post).
- Download and install git directly from http://git-scm.com/.
- Download and install latest CMake from Kitware CMake downloads.
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
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.
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.
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.
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.
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:
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/.
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.
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.
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;
}
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.
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 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.
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:
--pre-js
option works, search for --pre-js
in the test suite: the test suite is extensive and there are likely to be at least some examples.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.
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.
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
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.
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.)
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
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.
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.
All bugs should be filed in the GitHub main Emscripten repository Issue Tracker.
Please supply as much relevant information as possible, including:
emcc -v
).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!
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:
Pull requests must (of course) go to the proper repository.
Documentation (site) bugs should be filed in the same Issue Tracker.
Include relevant information including:
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.
This FAQ contains answers to many questions asked on IRC and the mailing list.
See the Emscripten Tutorial and emcc.
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.
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.
In most cases you will be able to use your project’s current build system with Emscripten. See Building Projects.
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:
-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.make
you can do something like make -j8
to run using 8 cores).EMCC_CORES=N
in the environment (which is useful if you have many cores but relatively less memory).Make sure you optimize code by building with -O2
(even more aggressive optimization is available, at the cost of significantly increased compilation time).
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.
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.
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).
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.
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).
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:
emcc.py
will show that second error,
“is not a valid input file”.{"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__
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.
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?
See the SDL automatic tests for working examples: python tests/runner.py browser
.
System libraries that are included with Emscripten are automatically linked when you compile (just the necessary parts). This includes libc, libc++ (C++ standard library) and SDL.
Libraries not included with Emscripten (like Boost) must be compiled and linked with the program just as if they were a module in the project.
There is a set of libraries ported to Emscripten for convenient use, Emscripten Ports. See Building Projects
Another option is to implement needed C APIs as JavaScript libraries (see --js-library
in emcc and Implement a C API in JavaScript). Emscripten itself does this for libc (not including malloc) and SDL (but not libc++ or malloc).
Note
-lSDL
to include SDL (specifying it will do no harm).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.
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.
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.
(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
});
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
.
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
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.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.-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.).
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.
-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;
})();
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.
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.
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.
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.
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
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.
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
.
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.
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.
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.)
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.
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.
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.
This section contains topics about building projects and running the output.
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.
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 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.
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.
./configure --enable-optimize
.--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 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.
./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.
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 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 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 intools/ports/__init__.py
.- Add testing in the test suite.
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.
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.
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.
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.
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).
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__
equals2147483647L
.- 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.
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.
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.
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
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.
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:
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
).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.-flto
, -flto=full
, -flto=thin
, at both compile and link times).
These flags will make the wasm backend behave more like fastcomp.--llvm-lto 1
. With the llvm backend
LTO passes will be run on any object files that are in bitcode format.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
.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
.
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).
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.
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).
.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.
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.
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:
-s SAFE_HEAP=1
, that will catch all such invalid accesses.-s DETERMINISTIC=1
."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.-s "BINARYEN_METHOD='asmjs,native-wasm'"
etc.) but due to its complexity and low value it was removed.-s PRECISE_F32=1
, in which case it should be identical to wasm.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.
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.
Module['wasmBinary']
and it will be used from there, and then (with async compilation off) compilation should be synchronous.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
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.
emrun supports the following uses:
stdout
and stderr
streams during the run, and print them to a terminal or log them to a file.GET
parameters in the launched URL, or argc
and argv
in main()
.exit(returncode)
, then pass the specified return code to the terminal.Using emrun is simple:
--emrun
linker flag.This flag injects code into the generated Module object to enable capture of
stdout
,stderr
andexit()
.Note
If you skip this step, you can still run any .html file with emrun, but the capture will not work.
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 callsexit(returncode)
, after which it will quit back to shell with the given process exit code.
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).
emrun spawns its own web server to host the target .html file. This has the following security implications:
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
.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
.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.
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.
emrun can automate browser-based testing on Android.
For this to work, you need to:
PATH
environment variable.adb devices
to see that your device is listed.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.
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.
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.
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.
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.
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.
Content-Encoding: gzip
. This instructs web browsers that the downloaded content should be transparently uncompressed before handing the data off to the page itself.-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.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
.--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.In addition to downloading the page, other parts of the startup sequence can sometimes also be slow. Things to consider here are:
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.WebAssembly.Module
objects can be manually persisted to IndexedDB, which avoids the compilation step altogether on the second run. (see next section)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.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.
.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.WebAssembly.Module
objects to IndexedDB. This feature should be always leveraged, since it allows skipping the whole compilation process on the second page visit.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.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.
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:
- 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.
- 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.- 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.
When planning a testing matrix before pushing a site live, the following items can be a good idea to review.
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.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.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.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.
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.
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.
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.
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.
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.
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.)
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).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.
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.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:
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.-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.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.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.
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.
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.
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.
Support for other portable C/C++ code is fairly comprehensive.
There are two main issues with function pointers:
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.
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).
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.
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);
}
This page lists some of the differences between the latest versions of the major browsers that are relevant to Emscripten-compiled applications and games:
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.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.
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:
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.
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.
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
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.onunload
). Some actions like showing alerts are banned by browsers at this point.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.
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.
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.
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.
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.
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()
:
-s EXPORTED_FUNCTIONS='["_main","_other_function"]'
exports
main()
and other_function()
._
at the
beginning of the function names in the EXPORTED_FUNCTIONS
list._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).-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.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.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).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.
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.
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
int
or a double
using the appropriate macro EM_ASM_INT
or
EM_ASM_DOUBLE
.$0
, $1
, etc.return
is used to provide the value sent from JavaScript back to C.{
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).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.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.
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
__deps
), however
those are only for other JavaScript libraries. See examples in
/src
with the name format library_*.jsautoAddDeps(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._
. 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.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 typeFor 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.
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.)
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.
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"})
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:
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 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.
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;
.
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();
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();
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');
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.
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
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.
embind has built-in support for return values of type std::unique_ptr
.
To teach embind about custom smart pointer templates, you must specialize
the smart_ptr_trait
template.
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
.
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.
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.
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 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
.
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.
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))
;
}
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;
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.
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.
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
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");
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.
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.
Binding using the WebIDL Binder is a three-stage process:
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 (seeFoo
above).- The type names in WebIDL are not identical to those in C++ (for example,
int
maps tolong
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.
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
To use the glue code files (glue.cpp
and glue.js
) in a project:
--post-js glue.js
in your final emcc command. The post-js option adds the glue code at the end of the compiled output.#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.
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.
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.
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.
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.
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);
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]
.
If a class cannot be deleted (because the destructor is private), specify [NoDelete]
in the IDL file.
[NoDelete]
interface Foo {
...
};
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 {
..
};
You can bind to C++ operators using [Operator=]
:
[Operator="+="] TYPE1 add(TYPE2 x);
Note
add
is just an example).=
: +=
, *=
, -=
etc., and to the array indexing operator []
.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();
};
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
JSImplementation
class (ImplJS
) or compilation will fail with an error.Base
class in the IDL file.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.
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.
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).
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.
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.
This section contains articles related to using files in Emscripten-compiled code.
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.
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.
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.
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.
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.
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.
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
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.
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]
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.
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.
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:
.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)..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)..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).The test suite contains many file packaging examples, and is a good place to search for working code.
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.
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.
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
Module.arguments
.Module.preInit
. This ensures that it is run before any compiled code.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.
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)
This section contains articles about Emscripten’s support for graphics and audio APIs.
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.
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:
Therefore, for each platform, including Emscripten, there exists platform-specific means to perform these tasks.
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.
Perform the following steps to create a GLES2 context using EGL:
EGLDisplay
object by calling eglGetDisplay
.eglInitialize
.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
.EGLSurface
) by calling eglCreateWindowSurface
with a valid display and config parameters. Set window and attribute list parameters to null.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.
The sequence to clean up at de-initialization is as follows:
eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)
.EGLContext
object by calling eglDestroyContext
on it.EGLSurface
objects by calling eglDestroySurface
on them.eglTerminate(display)
.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.
This section lists all EGL v1.4 functions and describes their current implementation status in Emscripten.
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
.
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.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.
Currently, Emscripten does not implement any extensions in the EGL Extension Registry.
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.
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
.
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.
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.
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.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.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.
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.
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.
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. |
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)!
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.
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()
).
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.
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.
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.
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:
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.
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.
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
).
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 toASSERTIONS=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 logSAFE_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 valueSTACK_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 ifASSERTIONS=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”.
Emscripten also supports some of Clang’s sanitizers, such as Undefined Behaviour Sanitizer and Address Sanitizer.
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.
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);
}
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"
}
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:
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:
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).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:
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:
-Werror
. This turns warnings into errors, which can be useful as some cases of undefined behavior would otherwise show warnings.-s ASSERTIONS=2
to get some useful information about the function pointer being called, and its type.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 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.
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:
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
Use the following workflow to find regressions with the AutoDebugger:
EMCC_AUTODEBUG=1
set in the environment.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.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
-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.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.
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.
By default, support for pthreads is not enabled. To enable code generation for pthreads, the following command line flags exist:
-s USE_PTHREADS=1
when compiling any .c/.cpp files, AND when linking to generate the final output .js file.-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.
-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).
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.
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.
The Emscripten implementation for the pthreads API should follow the POSIX standard closely, but some behavioral differences do exist:
-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.fork()
and join()
.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.
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:
Please check these first in case of any issues. Bugs can be reported to the Emscripten bug tracker as usual.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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 |
Any code referencing these intrinsics will not compile.
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!
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!
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.
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.
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.
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.
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.
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.
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.
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 withemscripten_sleep()
.- The JS API is different. See notes above on
Asyncify.handleSleep()
, and seesrc/library_async.js
for more examples.
This section lists Emscripten’s public API, organised by header file. At a very high level it consists of:
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.
Table of Contents
Guide material for the following APIs can be found in Calling JavaScript from C/C++.
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
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.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.)
Guide material for the following APIs can be found in Calling JavaScript from C/C++.
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 *)
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: |
|
---|---|
Return type: | void |
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: |
|
---|---|
Returns: | The result of the evaluation, as an integer. |
Return type: | int |
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: |
|
---|---|
Returns: | The result of the evaluation, as a string. |
Return type: | char* |
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: |
|
---|---|
Return type: | 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: |
|
---|---|
Return type: | void |
Guide material for the following APIs can be found in Emscripten Runtime Environment.
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: |
|
---|
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: |
|
---|
emscripten_push_main_loop_blocker
(em_arg_callback_func func, void *arg)¶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
emscripten_async_calls
are not counted, do not block the main loop, and can fire at specific time in the future.Parameters: |
|
---|---|
Return type: | void |
emscripten_pause_main_loop
(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.
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).
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: |
|
---|---|
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.
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*
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: |
|
---|
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: |
|
---|
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.
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: |
|
---|
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. |
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.
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). |
emscripten_random
(void)¶Generates a random number in the range 0-1. This maps to Math.random()
.
Return type: | float |
---|---|
Returns: | A random number. |
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*)
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: |
|
---|
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: |
|
---|
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: |
|
---|---|
Returns: | A handle to request ( |
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: |
|
---|---|
Returns: | A handle to request ( |
emscripten_async_wget2_abort
(int handle)¶Abort an asynchronous request raised using emscripten_async_wget2()
or emscripten_async_wget2_data()
.
Parameters: |
|
---|
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: |
|
---|
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. Theemscripten_idb_*
methods listed here provide an alternative API, directly to IndexedDB, thereby avoiding the overhead of the filesystem layer.
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: |
|
---|
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: |
|
---|
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: |
|
---|
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: |
|
---|
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: |
|
---|---|
Returns: | 0 if successful, -1 if the file does not exist |
Return type: | int |
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_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*)
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: |
|
---|---|
Returns: | A handle to the newly created worker. |
Return type: | worker_handle |
emscripten_destroy_worker
(worker_handle worker)¶Destroys a worker. See emscripten_create_worker()
Parameters: |
|
---|
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: |
|
---|
emscripten_worker_respond
(char *data, int size)¶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: |
|
---|
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 |
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.
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: |
|
---|---|
Returns: | The value of the specified setting. Note that for values other than an integer, a string is returned (cast the |
Return type: | 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. |
emscripten_debugger
()¶Emits debugger
.
This is inline in the code, which tells the JavaScript engine to invoke the debugger if it gets there.
emscripten_log
(int flags, const char* format, ...)¶Prints out a message to the console, optionally with the callstack information.
Parameters: |
|
---|
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: |
|
---|---|
Returns: | The number of bytes written (not number of characters, so this will also include the terminating zero). |
Return type: | int |
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: |
|
---|---|
Type: | const char* |
Returns: | A pointer to the preloaded image or NULL. |
Return type: | char* |
emscripten_get_preloaded_image_data_from_FILE
(FILE *file, int *w, int *h)¶Gets preloaded image data from a C FILE*
.
Parameters: |
|
---|---|
Type: | const char* |
Returns: | A pointer to the preloaded image or NULL. |
Return type: | char* |
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: |
|
---|---|
Return type: | The number of necessary bytes, not including the null terminator (actually written, if |
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.
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: |
|
---|
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: |
|
---|
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: |
|
---|
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: |
|
---|
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: |
|
---|
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: |
|
---|
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: |
|
---|
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: |
|
---|
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!
These functions require Asyncify (-s ASYNCIFY=1
). These functions are asynchronous but appear synchronous in C. See Asyncify for more details.
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).
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: |
|
---|
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: |
|
---|
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: |
|
---|
void emscripten_idb_store(const char *db_name, const char *file_id, void* buffer, int num, int *perror);
Synchronously stores data to IndexedDB.
Parameters: |
|
---|
void emscripten_idb_delete(const char *db_name, const char *file_id, int *perror);
Synchronously deletes data from IndexedDB.
Parameters: |
|
---|
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: |
|
---|
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.
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_create
(em_arg_callback_func func, void *arg, int stack_size)¶Create a coroutine which will be run as func(arg).
Parameters: |
|
---|
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.
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.
These functions only work with the upstream wasm backend when using Asyncify.
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*)
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.
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.
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
.
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.
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: |
|
---|
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:
- DOM Level 3 Events: Keyboard, Mouse, Mouse Wheel, Resize, Scroll, Focus.
- Device Orientation Events for gyro and accelerometer.
- Screen Orientation Events for portrait/landscape handling.
- Fullscreen Events for browser canvas fullscreen modes transitioning.
- Pointer Lock Events for relative-mode mouse motion control.
- Vibration API for mobile device haptic vibration feedback control.
- Page Visibility Events for power management control.
- Touch Events.
- Gamepad API.
- Beforeunload event.
- WebGL context events.
- Animation and timing.
- Console.
- Throw.
Table of Contents
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.
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 JavaScriptwindow
object.EMSCRIPTEN_EVENT_TARGET_DOCUMENT
: The event listener is applied to the JavaScriptdocument
object.EMSCRIPTEN_EVENT_TARGET_SCREEN
: The event listener is applied to the JavaScriptwindow.screen
object.0
orNULL
: 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.
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.
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.
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.
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.
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.
key
¶The printed representation of the pressed key.
Maximum size 32 char
(i.e. EM_UTF8 key[32]
).
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]
).
location
¶Indicates the location of the key on the keyboard. One of the DOM_KEY_LOCATION
values.
ctrlKey
¶shiftKey
¶altKey
¶metaKey
¶Specifies which modifiers were active during the key event.
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]
).
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.
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.
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.
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.
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: |
|
---|---|
Returns: |
|
Return type: |
emscripten_set_keypress_callback
(const char *target, void *userData, EM_BOOL useCapture, em_key_callback_func callback)¶emscripten_set_keydown_callback
(const char *target, void *userData, EM_BOOL useCapture, em_key_callback_func callback)¶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: |
|
---|---|
Returns: |
|
Return type: | |
See also: |
Note To receive events, the element must be focusable, see https://github.com/emscripten-core/emscripten/pull/7484#issuecomment-437887001 |
EmscriptenMouseEvent
¶The event structure passed in mouse events: click, mousedown, mouseup, dblclick, mousemove, mouseenter and mouseleave.
ctrlKey
¶shiftKey
¶altKey
¶metaKey
¶Specifies which modifiers were active during the mouse event.
Identifies which pointer device button changed state (see MouseEvent.button):
- 0 : Left button
- 1 : Middle button (if present)
- 2 : Right button
A bitmask that indicates which combinations of mouse buttons were being held down at the time of the event.
movementX
¶long movementY;
If pointer lock is active, these two extra fields give relative mouse movement since the last event.
targetX
¶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).
canvasX
¶canvasY
¶These fields give the mouse coordinates mapped to the Emscripten canvas client area (Emscripten-specific extension).
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.
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: |
|
---|---|
Returns: |
|
Return type: |
emscripten_set_click_callback
(const char *target, void *userData, EM_BOOL useCapture, em_mouse_callback_func callback)¶emscripten_set_mousedown_callback
(const char *target, void *userData, EM_BOOL useCapture, em_mouse_callback_func callback)¶emscripten_set_mouseup_callback
(const char *target, void *userData, EM_BOOL useCapture, em_mouse_callback_func callback)¶emscripten_set_dblclick_callback
(const char *target, void *userData, EM_BOOL useCapture, em_mouse_callback_func callback)¶emscripten_set_mousemove_callback
(const char *target, void *userData, EM_BOOL useCapture, em_mouse_callback_func callback)¶emscripten_set_mouseenter_callback
(const char *target, void *userData, EM_BOOL useCapture, em_mouse_callback_func callback)¶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: |
|
---|---|
Returns: |
|
Return type: |
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: |
|
Return type: |
EMSCRIPTEN_EVENT_WHEEL
¶Emscripten wheel event.
EmscriptenWheelEvent
¶The event structure passed in mousewheel events.
mouse
¶Specifies general mouse information related to this event.
deltaX
¶deltaY
¶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.
deltaMode
¶One of the DOM_DELTA_
values that indicates the units of measurement for the delta values.
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: |
|
---|---|
Returns: |
|
Return type: |
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: |
|
---|---|
Returns: |
|
Return type: |
EmscriptenUiEvent
¶The event structure passed in DOM element UIEvent events: resize and scroll.
detail
¶Specifies additional detail/information about this event.
documentBodyClientWidth
¶documentBodyClientHeight
¶The clientWidth/clientHeight of the document.body
element.
windowOuterWidth
¶int windowOuterHeight;
The outerWidth/outerHeight of the browser window.
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: |
|
---|---|
Returns: |
|
Return type: |
emscripten_set_resize_callback
(const char *target, void *userData, EM_BOOL useCapture, em_ui_callback_func callback)¶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
resize
callback, pass in target = 0 to get resize
events from the Window
object.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: |
|
---|---|
Returns: |
|
Return type: |
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: |
|
---|---|
Returns: |
|
Return type: |
emscripten_set_blur_callback
(const char *target, void *userData, EM_BOOL useCapture, em_focus_callback_func callback)¶emscripten_set_focus_callback
(const char *target, void *userData, EM_BOOL useCapture, em_focus_callback_func callback)¶emscripten_set_focusin_callback
(const char *target, void *userData, EM_BOOL useCapture, em_focus_callback_func callback)¶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: |
|
---|---|
Returns: |
|
Return type: |
EmscriptenDeviceOrientationEvent
¶The event structure passed in the deviceorientation event.
alpha
¶beta
¶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:
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: |
|
---|---|
Returns: |
|
Return type: |
emscripten_set_deviceorientation_callback
(void *userData, EM_BOOL useCapture, em_deviceorientation_callback_func callback)¶Registers a callback function for receiving the deviceorientation event.
Parameters: |
|
---|---|
Returns: |
|
Return type: |
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: |
|
Return type: |
EMSCRIPTEN_EVENT_DEVICEMOTION
¶Emscripten devicemotion event.
EmscriptenDeviceMotionEvent
¶The event structure passed in the devicemotion event.
accelerationX
¶accelerationY
¶accelerationZ
¶Acceleration of the device excluding gravity.
accelerationIncludingGravityX
¶accelerationIncludingGravityY
¶accelerationIncludingGravityZ
¶Acceleration of the device including gravity.
rotationRateAlpha
¶rotationRateBeta
¶rotationRateGamma
¶The rotational delta of the device.
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.
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: |
|
---|---|
Returns: |
|
Return type: |
emscripten_set_devicemotion_callback
(void *userData, EM_BOOL useCapture, em_devicemotion_callback_func callback)¶Registers a callback function for receiving the devicemotion event.
Parameters: |
|
---|---|
Returns: |
|
Return type: |
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: |
|
Return type: |
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.
EmscriptenOrientationChangeEvent
¶The event structure passed in the orientationchange event.
orientationIndex
¶One of the EM_ORIENTATION_PORTRAIT_xxx
fields, or -1 if unknown.
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.
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: |
|
---|---|
Returns: |
|
Return type: |
emscripten_set_orientationchange_callback
(void *userData, EM_BOOL useCapture, em_orientationchange_callback_func callback)¶Registers a callback function for receiving the orientationchange event.
Parameters: |
|
---|---|
Returns: |
|
Return type: |
emscripten_get_orientation_status
(EmscriptenOrientationChangeEvent *orientationStatus)¶Returns the current device orientation state.
Parameters: |
|
---|---|
Returns: |
|
Return type: |
emscripten_lock_orientation
(int allowedOrientations)¶Locks the screen orientation to the given set of allowed orientations
.
Parameters: |
|
---|---|
Returns: |
|
Return type: |
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 |
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.
EmscriptenFullscreenChangeEvent
¶The event structure passed in the fullscreenchange event.
fullscreenEnabled
¶Specifies if the current page has the ability to display elements fullscreen.
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.
id
¶The ID of the target HTML element that is in full screen mode.
Maximum size 128 char
(i.e. EM_UTF8 id[128]
).
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.
scaleMode
¶Specifies the rule how the CSS size (the displayed size) of the target element is resized when displayed in fullscreen mode.
canvasResolutionScaleMode
¶Specifies how the render target size (the pixel resolution) of the target element is adjusted when displayed in fullscreen mode.
filteringMode
¶Specifies the image filtering algorithm to apply to the element in fullscreen mode.
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.
canvasResizedCallbackUserData
¶Stores a custom data field which will be passed to all calls to the user-provided callback function.
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: |
|
---|---|
Returns: |
|
Return type: |
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: |
|
Return type: |
emscripten_get_fullscreen_status
(EmscriptenFullscreenChangeEvent *fullscreenStatus)¶Returns the current page fullscreen state.
Parameters: |
|
---|---|
Returns: |
|
Return type: |
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: |
|
---|---|
Returns: |
|
Return type: | 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: |
|
---|
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_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_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.
EMSCRIPTEN_EVENT_POINTERLOCKCHANGE
¶Emscripten pointerlockchange event.
EMSCRIPTEN_EVENT_POINTERLOCKERROR
¶Emscripten pointerlockerror event.
EmscriptenPointerlockChangeEvent
¶The event structure passed in the pointerlockchange event.
isActive
¶Specifies whether an element on the browser page currently has pointer lock enabled.
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: |
|
---|---|
Returns: |
|
Return type: |
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: |
|
---|---|
Returns: |
|
Return type: |
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: |
|
Return type: |
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: |
|
Return type: |
emscripten_get_pointerlock_status
(EmscriptenPointerlockChangeEvent *pointerlockStatus)¶Returns the current page pointerlock state.
Parameters: |
|
---|---|
Returns: |
|
Return type: |
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: |
|
---|---|
Returns: |
|
Return type: |
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 |
EMSCRIPTEN_EVENT_VISIBILITYCHANGE
¶Emscripten visibilitychange event.
EmscriptenVisibilityChangeEvent
¶The event structure passed in the visibilitychange event.
If true, the current browser page is now hidden.
visibilityState
¶Specifies a more fine-grained state of the current page visibility status. One of the EMSCRIPTEN_VISIBILITY_
values.
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: |
|
---|---|
Returns: |
|
Return type: |
emscripten_set_visibilitychange_callback
(void *userData, EM_BOOL useCapture, em_visibilitychange_callback_func callback)¶Registers a callback function for receiving the visibilitychange event.
Parameters: |
|
---|---|
Returns: |
|
Return type: |
emscripten_get_visibility_status
(EmscriptenVisibilityChangeEvent *visibilityStatus)¶Returns the current page visibility state.
Parameters: |
|
---|---|
Returns: |
|
Return type: |
EmscriptenTouchPoint
¶Specifies the status of a single touch point on the page.
identifier
¶An identification number for each touch point.
pageX
¶pageY
¶The touch coordinate relative to the viewport, in pixels, and including any scroll offset.
onTarget
¶Specifies whether this touch point is still above the original target on which it was initially pressed.
EmscriptenTouchEvent
¶Specifies the data of a single touchevent.
numTouches
¶The number of valid elements in the touches array.
ctrlKey
¶shiftKey
¶altKey
¶metaKey
¶Specifies which modifiers were active during the touch event.
EmscriptenTouchPoint touches[32]
An array of currently active touches, one for each finger.
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: |
|
---|---|
Returns: |
|
Return type: |
emscripten_set_touchstart_callback
(const char *target, void *userData, EM_BOOL useCapture, em_touch_callback_func callback)¶emscripten_set_touchend_callback
(const char *target, void *userData, EM_BOOL useCapture, em_touch_callback_func callback)¶emscripten_set_touchmove_callback
(const char *target, void *userData, EM_BOOL useCapture, em_touch_callback_func callback)¶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: |
|
---|---|
Returns: |
|
Return type: |
EmscriptenGamepadEvent
¶Represents the current snapshot state of a gamepad.
timestamp
¶Absolute wallclock time when the data was recorded (milliseconds).
numAxes
¶The number of valid axis entries in the axis
array.
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.
index
¶An ordinal associated with this gamepad, zero-based.
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: |
|
---|---|
Returns: |
|
Return type: |
emscripten_set_gamepadconnected_callback
(void *userData, EM_BOOL useCapture, em_gamepad_callback_func callback)¶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: |
|
---|---|
Returns: |
|
Return type: |
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().
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_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: |
|
Return type: |
EMSCRIPTEN_EVENT_BATTERYCHARGINGCHANGE
¶EMSCRIPTEN_EVENT_BATTERYLEVELCHANGE
¶Emscripten batterymanager events.
EmscriptenBatteryEvent
¶The event structure passed in the batterymanager events: chargingchange
and levelchange
.
chargingTime
¶Time remaining until the battery is fully charged (seconds).
dischargingTime
¶Time remaining until the battery is empty and the system will be suspended (seconds).
level
¶Current battery level, on a scale of 0 to 1.0.
EM_BOOL charging;
true
if the battery is charging, false
otherwise.
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: |
|
---|---|
Returns: |
|
Return type: |
emscripten_set_batterychargingchange_callback
(void *userData, em_battery_callback_func callback)¶emscripten_set_batterylevelchange_callback
(void *userData, em_battery_callback_func callback)¶Registers a callback function for receiving the batterymanager events: chargingchange
and levelchange
.
Parameters: |
|
---|---|
Returns: |
|
Return type: |
emscripten_get_battery_status
(EmscriptenBatteryEvent *batteryState)¶Returns the current battery status.
Parameters: |
|
---|---|
Returns: |
|
Return type: |
emscripten_vibrate
(int msecs)¶Produces a vibration for the specified time, in milliseconds.
Parameters: |
|
---|---|
Returns: |
|
Return type: |
emscripten_vibrate_pattern
(int *msecsArray, int numEntries)¶Produces a complex vibration feedback pattern.
Parameters: |
|
---|---|
Returns: |
|
Return type: |
EMSCRIPTEN_EVENT_BEFOREUNLOAD
¶Emscripten beforeunload event.
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: |
|
---|---|
Returns: | Return a string to be displayed to the user. |
Return type: | char* |
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: |
|
---|---|
Returns: |
|
Return type: |
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
).
EmscriptenWebGLContextAttributes
¶Specifies WebGL context creation parameters.
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
.
depth
¶If true
, request a depth buffer of at least 16 bits. If false
, no depth buffer will be initialized. Default value: true
.
stencil
¶If true
, request a stencil buffer of at least 8 bits. If false
, no stencil buffer will be initialized. Default value: false
.
antialias
¶If true
, antialiasing will be initialized with a browser-specified algorithm and quality level. If false
, antialiasing is disabled. Default value: true
.
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
.
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
.
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.
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
.
majorVersion
¶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
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
.
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.
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.
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
.
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: |
|
---|---|
Returns: |
|
Return type: |
emscripten_set_webglcontextlost_callback
(const char *target, void *userData, EM_BOOL useCapture, em_webgl_context_callback callback)¶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: |
|
---|---|
Returns: |
|
Return type: |
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: |
|
Return type: |
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_create_context
(const char *target, const EmscriptenWebGLContextAttributes *attributes)¶Creates and returns a new WebGL context.
Note
emscripten_webgl_make_context_current()
after creating a context to activate it.Parameters: |
|
---|---|
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 |
Return type: |
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: |
|
Return type: |
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_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_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_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: |
|
---|---|
Returns: |
|
Return type: |
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: |
|
Return type: |
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: |
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: |
|
---|---|
Returns: | EMSCRIPTEN_RESULT_SUCCESS if resizing succeeded, and one of the EMSCRIPTEN_RESULT_* error values on failure. |
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: |
|
---|---|
Returns: | EMSCRIPTEN_RESULT_SUCCESS if width and height retrieval succeeded, and one of the EMSCRIPTEN_RESULT_* error values on failure. |
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: |
|
---|---|
Returns: |
|
Return type: |
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: |
|
---|---|
Returns: |
|
Return type: |
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()
.
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: |
|
---|---|
Returns: | An ID to the |
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: |
|
---|
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: |
|
---|
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: |
|
---|---|
Returns: | An ID to the |
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: |
|
---|
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: |
|
---|
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: |
|
---|---|
Returns: | An ID to the |
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: |
|
---|
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: |
|
---|
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: |
|
---|---|
Returns: | An ID to the setInterval() call that can be passed to emscripten_clear_interval() to cancel the currently executing interval timer. |
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: |
|
---|
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) |
---|
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. |
---|
emscripten_console_log
(const char *utf8String)¶Prints a string using console.log()
.
Parameters: |
|
---|
emscripten_console_warn
(const char *utf8String)¶Prints a string using console.warn()
.
Parameters: |
|
---|
emscripten_console_error
(const char *utf8String)¶Prints a string using console.error()
.
Parameters: |
|
---|
emscripten_throw_number
(double number)¶Invokes JavaScript throw statement and throws a number.
emscripten_throw_string
(const char *utf8String)¶Invokes JavaScript throw statement and throws a string.
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.
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.
Table of Contents
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: |
|
---|
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: |
|
---|---|
Returns: | The result of the function call as a native JavaScript value (as in |
Opts: | An optional options object. It can contain the following properties:
|
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: |
|
---|---|
Returns: | A JavaScript function that can be used for running the C function. |
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.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: |
|
---|
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!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: |
|
---|---|
Returns: | The value stored at the specified memory address. |
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: |
|
---|---|
Returns: | A JavaScript |
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: |
|
---|
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: |
|
---|---|
Returns: | A JavaScript |
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: |
|
---|
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: |
|
---|---|
Returns: | A JavaScript |
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: |
|
---|
AsciiToString
(ptr)¶Converts an ASCII or Latin-1 encoded string to a JavaScript String object.
Arguments: |
|
---|---|
Returns: | A JavaScript |
Return type: | String |
intArrayFromString
(stringy, dontAddNull[, length])¶This converts a JavaScript string into a C-line array of numbers, 0-terminated.
Arguments: |
|
---|---|
Returns: | The array created from |
intArrayToString
(array)¶This creates a JavaScript string from a zero-terminated C-line array of numbers.
Arguments: |
|
---|---|
Returns: | A |
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: |
|
---|
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: |
|
---|
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: |
|
---|
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: |
|
---|
removeRunDependency
(id)¶Removes a specified id
from the list of run dependencies.
Arguments: |
|
---|
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. |
---|
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 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.
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.
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.
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).
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.
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.
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.
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.
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: |
|
---|
FS.
registerDevice
(dev, ops)¶Registers the specified device driver with a set of callbacks.
Arguments: |
|
---|
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: |
|
---|
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: |
|
---|
FS.
unmount
(mountpoint)¶Unmounts the specified mountpoint
.
Arguments: |
|
---|
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: |
|
---|
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: |
|
---|
FS.
symlink
(oldpath, newpath)¶Creates a symlink node at newpath
linking to oldpath
. For example:
FS.writeFile('file', 'foobar');
FS.symlink('file', 'link');
Arguments: |
|
---|
FS.
rename
(oldpath, newpath)¶Renames the node at oldpath
to newpath
. For example:
FS.writeFile('file', 'foobar');
FS.rename('file', 'newfile');
Arguments: |
|
---|
FS.
rmdir
(path)¶Removes an empty directory located at path
.
Example
FS.mkdir('data');
FS.rmdir('data');
Arguments: |
|
---|
FS.
unlink
(path)¶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: |
|
---|
FS.
readlink
(path)¶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: |
|
---|---|
Returns: | The string value stored in the symbolic link at |
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: |
|
---|
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: |
|
---|
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: |
|
---|
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: |
|
---|
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: |
|
---|
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: |
|
---|
FS.
ftruncate
(fd, len)¶Truncates the file identified by the fd
to the specified length (len
).
Arguments: |
|
---|
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: |
|
---|
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: |
|
---|---|
Returns: | A stream object. |
FS.
close
(stream)¶Closes the file stream.
Arguments: |
|
---|
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: |
|
---|
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: |
|
---|
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: |
|
---|
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: |
|
---|---|
Returns: | The file as a |
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: |
|
---|
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: |
|
---|---|
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: |
|
---|
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: |
|
---|---|
Returns: |
|
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 |
FS.
isLink
(mode)¶Tests if the mode
bitmask represents a symlink.
Arguments: |
|
---|---|
Returns: |
|
Return type: | bool |
FS.
isChrdev
(mode)¶Tests if the mode
bitmask represents a character device.
Arguments: |
|
---|---|
Returns: |
|
Return type: | bool |
FS.
isBlkdev
(mode)¶Tests if the mode
bitmask represents a block device.
Arguments: |
|
---|---|
Returns: |
|
Return type: | bool |
FS.
isSocket
(mode)¶Tests if the mode
bitmask represents a socket.
Arguments: |
|
---|---|
Returns: |
|
Return type: | bool |
FS.
cwd
()¶Gets the current working directory.
Returns: | The current working directory. |
---|
FS.
chdir
(path)¶Sets the current working directory.
Arguments: |
|
---|
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: |
|
---|---|
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: |
|
---|---|
Returns: | The absolute path to |
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.
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.
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.
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);
}
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");
}
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:
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:
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");
}
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.
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.
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.
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.
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
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.
Table of Contents
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.
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)
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: |
|
---|
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).
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++.
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.
undefined
()¶Creates a val
that represents undefined
.
Returns: | The val that represents undefined . |
---|
null
()¶Creates a val
that represents null
. val::undefined()
is the same, but for undefined.
Returns: | A val that represents null . |
---|
take_ownership
(internal::EM_VAL e)¶HamishW-Replace with description.
Returns: | HamishW-Replace with description. |
---|
global
(const char *name)¶Looks up a global symbol.
Parameters: | const char* name – HamishW-Replace with description. |
---|---|
Returns: | HamishW-Replace with description. |
module_property
(const char *name)¶Looks up a symbol on the emscripten Module object.
Parameters: | const char* name – HamishW-Replace with description. |
---|---|
Returns: | HamishW-Replace with description. |
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;
val
(const char *v)¶HamishW-Replace with description.
Parameters: | const char* v – HamishW-Replace with description. |
---|
val
(val &&v)¶HamishW-Replace with description.
Parameters: | val&& v – HamishW-Replace with description. |
---|
val
(const val &v)¶HamishW-Replace with description.
Parameters: | const val& v – HamishW-Replace with description. |
---|
~val
()¶Destructor. HamishW-Replace with further description or delete comment.
operator=
(val &&v)¶HamishW-Replace with description.
Parameters: | val&& v – HamishW-Replace with description. |
---|---|
Returns: | HamishW-Replace with description. |
operator=
(const val &v)¶HamishW-Replace with description.
Parameters: | val&& v – HamishW-Replace with description. |
---|---|
Returns: | HamishW-Replace with description. |
hasOwnProperty
(const char *key) const¶Test whether … HamishW-Replace with description.
Parameters: | const char* key – HamishW-Replace with description. |
---|---|
Returns: | HamishW-Replace with description. |
new_
()¶prototype:
template<typename... Args>
val new_(Args&&... args) const
HamishW-Replace with description.
Parameters: | Args&&... args – HamishW-Replace with description. Note that this is a templated value. |
---|---|
Returns: | HamishW-Replace with description. |
operator[]
(const T &key) const¶HamishW-Replace with description.
Parameters: | const T& key – HamishW-Replace with description. Note that this is a templated value. |
---|---|
Returns: | HamishW-Replace with description. |
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: |
|
---|
operator()
(Args&&... args)¶HamishW-Replace with description.
Parameters: | Args&&... args – HamishW-Replace with description. Note that this is a templated value. |
---|
call
(const char *name, Args&&... args) const¶HamishW-Replace with description.
Parameters: |
|
---|
as
() const¶HamishW-Replace with description.
Returns: | HamishW-Replace with description. Note that this is a templated value. |
---|
The C++ APIs in bind.h define
Guide documentation for this API can be found in Embind.
Table of Contents
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.) |
---|
Currently only allow_raw_pointers
policy is supported.
Eventually we hope to implement Boost.Python-like raw pointer policies for managing
object ownership.
allow_raw_pointer
¶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
select_overload
()¶// Prototype
template<typename Signature, typename ClassType>
typename internal::MemberFunctionType<ClassType, Signature>::type select_overload(Signature (ClassType::*fn))
:param Signature (ClassType::*fn)
select_const
()¶// Prototype
template<typename ClassType, typename ReturnType, typename... Args>
auto select_const(ReturnType (ClassType::*method)(Args...) const)
:param ReturnType (ClassType::*method)(Args…) const
optional_override
(const LambdaType &fp)¶// Prototype
template<typename LambdaType>
typename internal::CalculateLambdaSignature<LambdaType>::type optional_override(const LambdaType& fp)
:param const LambdaType& fp
__getDynamicPointerType
(void *p)¶:param void* p
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: |
|
---|
value_array
: public internal::noncopyable¶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.
element
(ElementType InstanceType::*field)¶Parameters: | ElementType InstanceType::*field – Note that ElementType and InstanceType are typenames (templated types). |
---|
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).
element
(index<Index>)¶:param index<Index>:Note that Index
is an integer template parameter.
value_object
: public internal::noncopyable¶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.
field
(const char *fieldName, FieldType InstanceType::*field)¶:param const char* fieldName. :param FieldType InstanceType::*field.
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).
field
(const char *fieldName, index<Index>)¶:param const char* fieldName.
:param index<Index>. Note that Index
is an integer template parameter.
default_smart_ptr_trait
¶//prototype
template<typename PointerType>
struct default_smart_ptr_trait
get_sharing_policy
()¶:param void* v
construct_null
()¶Returns: | Note that the PointerType returned is a typename (templated type). |
---|
smart_ptr_trait
¶//prototype
template<typename PointerType>
struct smart_ptr_trait : public default_smart_ptr_trait<PointerType>
element_type
¶//prototype
typedef typename PointerType::element_type element_type;
A typedef for the PointerType::element_type, where PointerType
is a typename (templated type).
get
(const PointerType &ptr)¶Parameters: | const PointerType& ptr – Note that PointerType is a typename (templated type) |
---|
//prototype
template<typename PointeeType>
struct smart_ptr_trait<std::shared_ptr<PointeeType>>
A typedef to std::shared_ptr<PointeeType>, where PointeeType
is a typename (templated type).
A typedef for the PointerType::element_type
.
:param const PointerType& ptr
Parameters: |
|
---|
wrapper
: public T, public internal::WrapperBase¶//prototype
template<typename T>
class wrapper : public T, public internal::WrapperBase
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.
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
base
¶class_type
¶A typedef of BaseClass
, the typename of the templated type for the class.
verify
()¶Note, is templated function which takes typename ClassType
.
get
()¶template<typename ClassType>
using Upcaster = BaseClass* (*)(ClassType*);
template<typename ClassType>
using Downcaster = ClassType* (*)(BaseClass*);
getUpcaster
()¶//prototype
template<typename ClassType>
static Upcaster<ClassType> getUpcaster()
getDowncaster
()¶//prototype
template<typename ClassType>
static Downcaster<ClassType> getDowncaster()
convertPointer
(From *ptr)¶//prototype
template<typename From, typename To>
static To* convertPointer(From* ptr)
:param From* ptr
pure_virtual
¶constructor
¶Note that this is a template struct taking typename ... ConstructorArgs
.
class_
¶Note that this is a templated class with typename parameters ClassType
and BaseSpecifier
.
class_type
¶A typedef of ClassType
(a typename for the class).
base_specifier
¶A typedef of BaseSpecifier
(a typename for the class).
HELPNEEDEDHERE
¶class_() = delete;
class_
(const char *name)¶//prototype
EMSCRIPTEN_ALWAYS_INLINE explicit class_(const char* name)
Constructor.
:param const char* name
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.
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... 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. |
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.
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.
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.
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. |
---|
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.
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. |
---|
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. |
---|
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.
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.
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.
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. |
---|
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.
enum_type
¶A typedef of EnumType
(a typename for the class).
enum_
(const char *name)¶Constructor.
:param const char* name
value
(const char *name, EnumType value)¶Registers an enum value.
Parameters: |
|
---|---|
Returns: | A reference to the current object. This allows chaining of multiple enum values in the |
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: |
|
---|
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.
table of contents
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
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 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();
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();
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());
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();
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.
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);
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.
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 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.
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.
emscripten_trace_configure
(const char *collector_url, const char *application)¶Parameters: |
|
---|---|
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/
.
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.)
emscripten_trace_set_enabled
(bool enabled)¶Parameters: |
|
---|---|
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.
emscripten_trace_set_session_username
(const char *username)¶Parameters: |
|
---|---|
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.
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.
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.
emscripten_trace_log_message
(const char *channel, const char *message)¶Parameters: |
|
---|---|
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.
emscripten_trace_mark
(const char *message)¶Parameters: |
|
---|---|
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.
emscripten_trace_report_error
(const char *error)¶Parameters: |
|
---|---|
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.
emscripten_trace_record_allocation
(const void *address, int32_t size)¶Parameters: |
|
---|---|
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.
emscripten_trace_record_reallocation
(const void *old_address, const void *new_address, int32_t size)¶Parameters: |
|
---|---|
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.
emscripten_trace_record_free
(const void *address)¶Parameters: |
|
---|---|
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.
emscripten_trace_annotate_address_type
(const void *address, const char *type)¶Parameters: |
|
---|---|
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.
emscripten_trace_associate_storage_size
(const void *address, int32_t size)¶Parameters: |
|
---|---|
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.
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.
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.
emscripten_trace_enter_context
(const char *name)¶Parameters: |
|
---|---|
Return type: | void |
The current timestamp is associated with this data.
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: |
|
---|---|
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: |
|
---|---|
Return type: | void |
Associate a key / value pair with the current task.
void emscripten_trace_task_suspend(const char *explanation);
Parameters: |
|
---|---|
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: |
|
---|---|
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.
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.
The C APIs in vr.h provide basic interfaces for interacting with WebVR from Emscripten.
Table of Contents
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: |
|
---|---|
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.
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. |
---|
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 |
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.
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 |
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 |
All of the following functions require emscripten_vr_init()
to have been
called the return value of emscripten_vr_ready()
to be true.
emscripten_vr_count_displays
()¶Returns: | Number of displays connected. |
---|---|
Return type: | int |
emscripten_vr_get_display_handle
(int displayIndex)¶Parameters: |
|
---|---|
Returns: | handle for a VR display. |
Return type: | VRDisplayHandle |
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: |
|
---|---|
Returns: | name of the VR display or 0 (NULL) if the handle is invalid. |
Return type: | char* |
emscripten_vr_display_connected
(VRDisplayHandle handle)¶Parameters: |
|
---|---|
Returns: | true if the display is connected, false otherwise or when the handle is invalid. |
Return type: | bool |
emscripten_vr_display_presenting
(VRDisplayHandle handle)¶See also emscripten_vr_request_present()
.
Parameters: |
|
---|---|
Returns: | true if the display is currently presenting, false otherwise or when the handle is invalid. |
Return type: | bool |
emscripten_vr_get_display_capabilities
(VRDisplayHandle handle, VRDisplayCapabilities* displayCaps)¶Parameters: |
|
---|---|
Returns: | 1 on success, 0 if handle was invalid. |
Return type: | bool |
emscripten_vr_get_eye_parameters
(VRDisplayHandle handle, VREye whichEye, VREyeParameters* eyeParams)¶Parameters: |
|
---|---|
Returns: | 1 on success, 0 if handle was invalid. |
Return type: | bool |
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.
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: |
|
---|---|
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.
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: |
|
---|---|
Return type: | 1 on success, 0 if handle was invalid. |
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: |
|
---|---|
Return type: | 1 on success, 0 if handle was invalid. |
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: |
|
---|---|
Return type: | 1 on success, 0 if handle was invalid. |
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: |
|
---|---|
Return type: | 1 on success, 0 if handle was invalid. |
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: |
|
---|---|
Return type: | 1 on success, 0 if handle was invalid. |
emscripten_vr_exit_present
(VRDisplayHandle handle)¶Request present exit.
Parameters: |
|
---|---|
Return type: | 1 on success, 0 if handle was invalid. |
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
.
VRDisplayCapabilities
¶Structure passed to emscripten_vr_get_display_capabilities()
, maps to the WebVR VRDisplayCapabilities interface.
hasPosition
¶hasExternalDisplay
¶canPresent
¶maxLayers
¶VRLayerInit
¶Structure passed to emscripten_vr_request_present()
, maps to the WebVR VRLayerInit interface.
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
.
leftBounds
¶Texture bounds of the left eye on the target canvas. Initialize with VR_LAYER_DEFAULT_LEFT_BOUNDS
for default.
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.
linearAcceleration
¶Linear acceleration, valid only if poseFlags & VR_POSE_LINEAR_ACCELERATION != 0
.
orientation
¶Orientation quaternion, valid only if poseFlags & VR_POSE_ORIENTATION != 0
.
angularVelocity
¶Angular velocity, valid only if poseFlags & VR_POSE_ANGULAR_VELOCITY != 0
.
VRFrameData
¶Structure passed to emscripten_vr_get_frame_data()
, maps to the WebVR
VRFrameData interface.
timestamp
¶leftProjectionMatrix
¶leftViewMatrix
¶rightProjectionMatrix
¶rightViewMatrix
¶VREyeParameters
¶Structure passed to emscripten_vr_get_eye_parameters()
, maps to the WebVR
VREyeParameters interface.
renderWidth
¶renderHeight
¶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
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.
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.
stack_limit
¶Lower limit of the C stack region. Must be below emscripten_fiber_t.stack_base
.
stack_ptr
¶Current position of the stack pointer. Must be between emscripten_fiber_t.stack_base
and emscripten_fiber_t.stack_limit
.
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.
user_data
¶Opaque pointer, passed as-is to emscripten_fiber_t.entry
.
asyncify_data
¶Asyncify data structure. Used to unwind and rewind the call stack when switching fibers.
asyncify_data_t
¶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.
stack_limit
¶Upper limit of the Asyncify stack region.
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.
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: |
|
---|
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.
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: |
|
---|
emscripten_fiber_swap
(emscripten_fiber_t *old_fiber, emscripten_fiber_t *new_fiber)¶Performs a fiber context switch.
Parameters: |
|
---|
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.
Table of Contents
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']"
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: |
|
---|
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.
createLink
(parent, name, target, canRead, canWrite)¶FS.
forceLoadFile
(obj)¶Legacy v1 compatibility functions.
There are also a small number of additional flag modes:
rs
xw
xw+
xa
xa+
This section provides reference for the main tools in the Emscripten toolchain:
** 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.
./emsdk [help [–old] | list | update | install <tool/sdk> | uninstall <tool/sdk> | activate <tool/sdk>]
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
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.
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.
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'
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.
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
Use ./emsdk help
or just ./emsdk
to get information about all available commands.
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.
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.
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.
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>
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.
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>
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.
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.
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.
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.
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
-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
-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
["_func1", "func2"]
.-g
Preserve debug information.
-gseparate-dwarf[=FILENAME]
-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
-g2
(preserve whitespace and function names) and may also enable optimizations that affect performance and otherwise might not be performed in -g2
.--profiling-funcs
--tracing
--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 level2
and then level1
.
Note
--llvm-opts
), this setting has no effect.--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
-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
).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.JAVA_HEAP_SIZE
in the environment (for example, to 4096m for 4GB).-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>
--pre-js
, but emits a file after the emitted code.--extern-pre-js <file>
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>
--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>
--use-preload-plugins
--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
-o
option.--source-map-base <base-url>
sourceMappingURL
section. The resulting URL will have format: <base-url>
+ <wasm-file-name>
+ .map
.--minify 0
-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
--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>
-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
--save-bc PATH
--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 meansmain()
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
-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
--emrun
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
--memoryprofiler
--threadprofiler
--em-config
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
-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
--separate-asm
--output_eol windows|linux
--cflags
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.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.
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.
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.
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.
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:
-O0
or -O1
).-O2
to get a well-optimized build.-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.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
-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.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:
noinline
have been lost at this point.)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
.
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).
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.
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.
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.
In addition to the above, the following tips can help to reduce code size:
--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.The following compiler settings can help (see src/settings.js
for more details):
-s INLINING_LIMIT=1
. Compiling with -Os or -Oz generally avoids inlining too. (Inlining can make code faster, though, so use this carefully.)-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.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.ELIMINATE_DUPLICATE_FUNCTIONS
to remove duplicate functions, which C++ templates often create. (This is already done by default for wasm, in -O1
and above.)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.
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.
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);
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 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.
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++ 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% (!).
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.
Enable Debug mode (EMCC_DEBUG) to output files for each compilation phase, including the main optimization operations.
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.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
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:
-O2
or -O3
)?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.
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.
-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.-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.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.-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).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.
about:config
and set the pref browser.tabs.remote.autostart.2
to false
, and restart the browser.about:config
and set the pref webgl.disable-angle
to true
and reload the page.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.
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.
glUniform4fv()
array call, instead of calling glUniform4f()
multiple times to update each one individually. Or better yet, use Uniform Buffer Objects in WebGL 2.glGetUniformLocation()
at render time, but query the locations once per shader program at startup and cache them.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*()
andglCreate*()
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()
orglCheckFramebufferStatus()
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()
andglLinkProgram()
can be extremely slow.- Do not call
glReadPixels()
to copy texture contents back to main memory at render time. If necessary, use the WebGL 2GL_PIXEL_PACK_BUFFER
binding target instead to copy a GPU surface to an offscreen target first, and only laterglReadPixels()
the contents of that surface back to main memory.
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.
glBindBuffer()
calls when setting up vertex attribute pointers for rendering.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.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.GL_DYNAMIC
vertex buffers over GL_STREAM
.After having verified that CPU-GPU pipeline sync bubbles do not occur, and rendering is still GPU bound, the following optimizations can be useful.
glDiscardFramebuffer()
when the contents of an FBO are no longer needed.Finally, a number of miscellaneous optimizations have been proven to be effective.
-s GL_PREINITIALIZED_CONTEXT=1
can help in authoring a html shell page that performs such texture format checks up front."webglcontextcreationerror"
callback. Browsers can give good diagnostics in the context creation error handler to allow diagnosing what the root cause is.failIfMajorPerformanceCaveat
flag to detect when rendering on software, and cut down on graphics fidelity in such cases.*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.requestAnimationFrame()
loops to render animation instead of the setTimeout()
API. This gives the smoothest scheduling on the animation ticks.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.
#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.#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.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
.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.
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.
The CyberDWARF debugger is designed to be used from the JavaScript devtool console available in most modern browsers.
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
}
}'
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)
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.
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.
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'
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)!
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.
Here are some examples of how AddressSanitizer can be used to help find bugs.
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)
...
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)
...
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
.
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)
...
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.
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 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.
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.
See the Binaryen build instructions.
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.
In general a complete Emscripten environment requires the following tools. First test to see if they are already installed using the instructions below.
- Node.js (0.8 or above; 0.10.17 or above to run websocket-using servers in node):
- Python 2.7.12 or above, or Python 3.5 or above (Python 2.7.0 or newer may also work, but is known to have SSL related issues, https://github.com/emscripten-core/emscripten/issues/6275)
- Java (1.6.0_31 or later). Java is optional. It is required to use the Closure Compiler (in order to minify your code).
- Git client. Git is required if building tools from source.
- LLVM (LLVM, including clang and wasm-ld)
- Binaryen (Binaryen, including wasm-opt, wasm-emscripten-finalize, etc.)
- The Emscripten code, from GitHub
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.
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:
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.
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
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.
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).
To build the Fastcomp code from source:
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):
cat /proc/cpuinfo | grep "^cpu cores" | uniq
.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'
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.
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.
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.
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.
The settings file is created the first time a user runs emcc (or any of the other Emscripten tools):
Navigate to the directory where you cloned the Emscripten repository.
Enter the command:
./emcc --helpYou 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.
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.
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.
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).
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.
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.
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.
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
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.
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.
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.
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 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.
This section contains articles that are relevant to anyone who wants to contribute to Emscripten and help improve the project.
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!
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.
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.
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.
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.
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.
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:
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.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.)
The Emscripten Compiler Frontend (emcc) is a python script that manages the entire compilation process:
wasm-ld
to link it. It
builds and integrates with the Emscripten system libraries, both the
compiled ones and the ones implemented in JS.src/compiler.js
and related files) which emits the JS.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.
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]>
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.
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.
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.
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.
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.
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.
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 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.
Please report documentation bugs as you would any other Emscripten bug. Help fix them by updating existing documents or by creating new ones.
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.
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.
Notes for installing Sphinx are provided here.
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
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 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=
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=
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:
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.
To link to a page, first define a globally unique reference before the page title (e.g. _my-page-reference
) then link to it using the ref role as shown:
.. _my-page-reference:
My Page Title
=============
This is the text of the section.
To link to page use either of the options below:
ref:`my-reference-label` - the link text is the heading name after the reference
ref:`some text <my-reference-label>` - the link text is "some text"
This is a better approach than linking to documents using the :doc: role, because the links do not get broken if the articles are moved.
This approach is also recommended for linking to arbitrary headings in the site.
Note
There are a number of other roles that are useful for linking — including Sphinx Domains for linking to code items, and term for linking to glossary terms.
reStructured text defines section headings using a separate line of punctuation characters after (and optionally before) the heading text. The line of characters must be at least as long as the heading. For example:
A heading
=========
Different punctuation characters are used to specify nested sections. Although the system does not mandate which punctuation character is used for each nested level, it is important to be consistent. The recommended heading levels are:
=======================================
Page title (top and bottom bars of "=")
=======================================
Level 1 heading (single bar of "=" below)
=========================================
Level 2 heading (single bar of "-" below)
-----------------------------------------
Level 3 heading (single bar of "+" below)
+++++++++++++++++++++++++++++++++++++++++
Level 4 heading (single bar of "~" below)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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.
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.
The site is licensed under the same Open Source License as the rest of Emscripten. Contributors to the site should add themselves to AUTHORS.