You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
More for #5836 (JS shrinking).
This removes almost all default function exports from the runtime. In ASSERTIONS builds, a warning will be shown if they are used, using the mechanism we introduced for getValue/setValue (which we recently removed from being exported by default).
This reduces the size of the #5836 testcase by almost 20% (!), shrinking us from 21.75 k to 17.65 k.
There are still a few things exported by default, like filesystem support (the file packager emits code that uses those, we should make extra sure this is not confusing for people) and things that aren't functions (need to investigate a good mechanism for warning if they are used incorrectly in ASSERTIONS mode, perhaps a getter on the Module object).
This PR also includes
* Changelog update explaining the change.
* Docs improvements.
* An example in the SDL port of how to export runtime stuff if the port needs it (so e.g. people using SDL don't need to manually add exports, the port can do it for them).
Copy file name to clipboardExpand all lines: ChangeLog.markdown
+1
Original file line number
Diff line number
Diff line change
@@ -9,6 +9,7 @@ Not all changes are documented here. In particular, new features, user-oriented
9
9
10
10
Current Trunk
11
11
-------------
12
+
- 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.
Copy file name to clipboardExpand all lines: emcc.py
+3
Original file line number
Diff line number
Diff line change
@@ -937,6 +937,9 @@ def check(input_file):
937
937
938
938
assertnot (shared.Settings.NO_DYNAMIC_EXECUTIONandoptions.use_closure_compiler), 'cannot have both NO_DYNAMIC_EXECUTION and closure compiler enabled at the same time'
Copy file name to clipboardExpand all lines: site/source/docs/api_reference/module.rst
+1-1
Original file line number
Diff line number
Diff line change
@@ -8,7 +8,7 @@ Module object
8
8
9
9
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 :js:attr:`Module.print` attribute.
10
10
11
-
.. note:: ``Module`` is also used to provide access to all Emscripten API functions (for example :js:func:`ccall`) in a way that avoids issues with function name minification at higher optimisation levels. These functions are documented as part of their own APIs.
11
+
.. note:: ``Module`` is also used to provide access to Emscripten API functions (for example :js:func:`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).
Copy file name to clipboardExpand all lines: site/source/docs/api_reference/preamble.js.rst
+6-2
Original file line number
Diff line number
Diff line change
@@ -6,9 +6,13 @@ preamble.js
6
6
7
7
The JavaScript APIs in `preamble.js <https://github.com/kripken/emscripten/blob/master/src/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.
8
8
9
-
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.) Thus, the preamble code is included in the output JS, which means you can use the APIs described in this document without needing to do anything special.
9
+
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.)
10
10
11
-
.. note:: All functions should be called though the :ref:`Module <module>` object (for example: ``Module.functionName``). At optimisation ``-O2`` (and higher) function names are minified by the closure compiler, and calling them directly will fail.
11
+
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.
12
+
13
+
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).
14
+
15
+
.. 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.
``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).
73
75
74
76
.. note::
75
77
@@ -146,9 +148,17 @@ parameters to pass to the function:
146
148
as the latter will force the method to actually be included in
147
149
the build.
148
150
149
-
- Use ``Module.ccall`` and not ``ccall`` by itself. The former will work
150
-
at all optimisation levels (even if the :term:`Closure Compiler`
151
-
minifies the function names).
151
+
- The compiler will remove code it does not see is used, to improve code
152
+
size. If you use ``ccall`` in a place it sees, like code in a ``--pre-js``
153
+
or ``--post-js``, it will just work. If you use it in a place the compiler
154
+
didn't see, like another script tag on the HTML or in the JS console like
155
+
we did in this tutorial, then because of optimizations
156
+
and minification you should export ccall from the runtime, using
157
+
``EXTRA_EXPORTED_RUNTIME_METHODS``, for example using
Copy file name to clipboardExpand all lines: src/modules.js
+1-1
Original file line number
Diff line number
Diff line change
@@ -283,7 +283,7 @@ function maybeExport(name) {
283
283
// check if it already exists, to support EXPORT_ALL and other cases
284
284
// (we could optimize this, but in ASSERTIONS mode code size doesn't
285
285
// matter anyhow)
286
-
return'if (!Module["'+name+'"]) Module["'+name+'"] = function() { abort("\''+name+'\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS.") };';
286
+
return'if (!Module["'+name+'"]) Module["'+name+'"] = function() { abort("\''+name+'\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };';
0 commit comments