mirror of https://github.com/mosra/magnum.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
554 lines
23 KiB
554 lines
23 KiB
/* |
|
This file is part of Magnum. |
|
|
|
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 |
|
Vladimír Vondruš <mosra@centrum.cz> |
|
|
|
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. |
|
*/ |
|
|
|
namespace Magnum { |
|
|
|
/** @page platforms-html5 JavaScript, HTML5 and WebGL |
|
@brief Building, testing and deploying HTML5 and WebGL projects |
|
|
|
@tableofcontents |
|
@m_footernavigation |
|
@m_keywords{HTML5 Emscripten} |
|
|
|
@todoc testing, gl tests, coverage, travis setup |
|
@todoc static plugins |
|
@todoc speeding up compilation |
|
|
|
The following guide explains basic workflow of using |
|
[Emscripten](http://kripken.github.io/emscripten-site/) for deploying HTML5 |
|
apps using WebGL. |
|
|
|
At the very least you need to have Emscripten installed. Running console |
|
applications requires Node.js, running browser apps require a webserver that's |
|
able to serve static content (for example Apache, if you have Python installed, |
|
it has a builtin webserver too). |
|
|
|
@note On ArchLinux it's the `emscripten` and `nodejs` packages, both in the |
|
`[extras]` repository. |
|
|
|
Cross-compilation to Emscripten is done using a CMake toolchain that's part of |
|
the toolchains repository at https://github.com/mosra/toolchains. Add it as a |
|
submodule to your project or fetch the contents any other way that suits your project. The following guide will assume the contents of the repository are |
|
placed in a `toolchains/` subdirectory. |
|
|
|
@code{.sh} |
|
git submodule add git://github.com/mosra/toolchains |
|
@endcode |
|
|
|
There are two toolchain files. The `generic/Emscripten.cmake` is for the |
|
classical (asm.js) build, the `generic/Emscripten-wasm.cmake` is for |
|
WebAssembly build. The following guide will work with the WASM toolchain. Don't |
|
forget to adapt `EMSCRIPTEN_PREFIX` variable in |
|
`toolchains/generic/Emscripten*.cmake` to path where Emscripten is installed; |
|
you can also pass it explicitly on command-line using `-DEMSCRIPTEN_PREFIX`. |
|
Default is `/usr/emscripten`. |
|
|
|
@section platforms-html5-console Building and running console applications |
|
|
|
Emscripten allows you to run arbitrary console utilities and tests via Node.js, |
|
except for all code that accesses browsers APIs such as WebGL or audio. |
|
Assuming you have Magnum installed in the Emscripten path as described in |
|
@ref building-cross-emscripten, build your project simply as this, using one |
|
of the toolchain files from above: |
|
|
|
@code{.sh} |
|
mkdir build-emscripten-wasm && cd build-emscripten-wasm |
|
cmake .. \ |
|
-DCMAKE_TOOLCHAIN_FILE="../toolchains/generic/Emscripten-wasm.cmake" \ |
|
-DCMAKE_BUILD_TYPE=Release |
|
cmake --build . |
|
@endcode |
|
|
|
After that you can run the generated JavaScript file using Node.js. Note that |
|
it looks for the corresponding `*.wasm` file in the current directory, so you |
|
need to @cb{.sh} cd @ce there first: |
|
|
|
@code{.sh} |
|
cd build-emscripten-wasm/src |
|
node my-application.js |
|
@endcode |
|
|
|
@section platforms-html5-apps Building and deploying graphical apps |
|
|
|
In case you don't have an OpenGL ES build set up yet, you need to copy |
|
`FindOpenGLES2.cmake` (or `FindOpenGLES3.cmake`) from the |
|
[modules/](https://github.com/mosra/magnum/tree/master/modules) directory in |
|
Magnum source to the `modules/` dir in your project so it is able to find the |
|
WebGL libraries. |
|
|
|
Magnum provides an Emscripten application wrapper in |
|
@ref Platform::Sdl2Application. See its documentation for more information |
|
about general usage. You can also use the Emscripten APIs directly or any other |
|
way. |
|
|
|
@note The @ref Platform::Sdl2Application also contains a fully configured |
|
bootstrap project that's ready to build and deploy. Check its documentation |
|
for details. |
|
|
|
To target the web browser, you need to provide a HTML markup for your |
|
application. Template one is below. The markup references two files, |
|
`EmscriptenApplication.js` and `WebApplication.css`, both are in the |
|
[src/Magnum/Platform/](https://github.com/mosra/magnum/tree/master/src/Magnum/Platform) |
|
directory in the source tree and are also put into `share/magnum/` inside your |
|
install prefix. |
|
|
|
@code{.html-jinja} |
|
<!DOCTYPE html> |
|
<html> |
|
<head> |
|
<meta charset="UTF-8" /> |
|
<title>Magnum Emscripten Application</title> |
|
<link rel="stylesheet" href="WebApplication.css" /> |
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
|
</head> |
|
<body> |
|
<h1>Magnum Emscripten Application</h1> |
|
<div id="container"> |
|
<div id="sizer"><div id="expander"><div id="listener"> |
|
<canvas id="module"></canvas> |
|
<div id="status">Initialization...</div> |
|
<div id="status-description"></div> |
|
<script src="EmscriptenApplication.js"></script> |
|
<script async="async" src="{{ application }}.js"></script> |
|
</div></div></div> |
|
</div> |
|
</body> |
|
</html> |
|
@endcode |
|
|
|
For basic usage you don't need to modify the CSS and JS files at all and |
|
everything can be set up directly from the HTML markup. Replace |
|
@cb{.jinja} {{ application }} @ce with the name of your application executable |
|
and adapt page title and heading as desired. You can modify all files to your |
|
liking, but the HTML file must contain at least |
|
@cb{.html} <canvas id="module"> @ce enclosed in |
|
@cb{.html} <div id="listener"> @ce. The JavaScript file contains event |
|
listeners that print loading status on the page. The status is displayed in the |
|
remaining two @cb{.html} <div> @ce s, if they are available. The CSS file |
|
contains a basic style, see @ref platforms-html5-layout "below" for available |
|
options to tweak the default look. |
|
|
|
In order to deploy the app, you need to put the JS driver code, the WebAssembly |
|
binary (or the asm.js memory image, in case you are compiling with the classic |
|
asm.js toolchain), the HTML markup and the JS/CSS files to a common location. |
|
The following CMake snippet handles all of that: |
|
|
|
@code{.cmake} |
|
if(CORRADE_TARGET_EMSCRIPTEN) |
|
install(TARGETS my-application DESTINATION ${CMAKE_INSTALL_PREFIX}) |
|
install(FILES |
|
my-application.html |
|
EmscriptenApplication.js |
|
WebApplication.css |
|
DESTINATION ${CMAKE_INSTALL_PREFIX}) |
|
install(FILES |
|
${CMAKE_CURRENT_BINARY_DIR}/my-application.js.mem |
|
${CMAKE_CURRENT_BINARY_DIR}/my-application.wasm |
|
DESTINATION ${CMAKE_INSTALL_PREFIX} OPTIONAL) |
|
endif() |
|
@endcode |
|
|
|
To deploy, you can either point `CMAKE_INSTALL_PREFIX` to a location inside |
|
your system webserver or you can point it to an arbitrary directory and use |
|
Python's builtin webserver to serve its contents: |
|
|
|
@code{.sh} |
|
cd build-emscripten-wasm |
|
cmake -DCMAKE_INSTALL_PREFIX=/path/to/my/emscripten/deploy .. |
|
cmake --build . --target install |
|
|
|
cd /path/to/my/emscripten/deploy |
|
python -m http.server # or python -m SimpleHTTPServer with Python 2 |
|
@endcode |
|
|
|
After that, you can open http://localhost:8000 to see the files. Stop the |
|
webserver again by pressing @m_class{m-label m-warning} **Ctrl** |
|
@m_class{m-label m-default} **C**. |
|
|
|
@section platforms-html5-windowless-apps Building and deploying windowless apps |
|
|
|
In case you don't have an EGL + OpenGL ES build set up yet, you need to copy |
|
`FindEGL.cmake` and `FindOpenGLES2.cmake` (or `FindOpenGLES3.cmake`) from the |
|
[modules/](https://github.com/mosra/magnum/tree/master/modules) directory in |
|
Magnum source to the `modules/` dir in your project so it is able to find the |
|
EGL and WebGL libraries. |
|
|
|
Windowless Magnum apps (i.e. apps that use the OpenGL context without a window) |
|
can be run in the browser as well using the @ref Platform::WindowlessEglApplication |
|
class. See its documentation for more information |
|
about general usage. You can also use the Emscripten APIs directly or any other |
|
way. |
|
|
|
@note @ref Platform::WindowlessEglApplication also contains a fully configured |
|
bootstrap project that's ready to build and deploy. Check its documentation |
|
for details. |
|
|
|
Similarly to graphics apps, you need to provide a HTML markup for your |
|
application. Template one is below, its main difference from the one above is |
|
that it shows the console output instead of the canvas. The markup references |
|
two files, `WindowlessEmscriptenApplication.js` and `WebApplication.css`, both |
|
are in the [src/Magnum/Platform/](https://github.com/mosra/magnum/tree/master/src/Magnum/Platform) |
|
directory in the source tree and are also put into `share/magnum/` inside your |
|
install prefix. |
|
|
|
@code{.html-jinja} |
|
<!DOCTYPE html> |
|
<html> |
|
<head> |
|
<meta charset="UTF-8" /> |
|
<title>Magnum Windowless Emscripten Application</title> |
|
<link rel="stylesheet" href="WebApplication.css" /> |
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
|
</head> |
|
<body> |
|
<h1>Magnum Windowless Emscripten Application</h1> |
|
<div id="container"> |
|
<div id="sizer"><div id="expander"><div id="listener"> |
|
<canvas id="module" class="hidden"></canvas> |
|
<pre id="log"></pre> |
|
<div id="status">Initialization...</div> |
|
<div id="status-description"></div> |
|
<script src="WindowlessEmscriptenApplication.js"></script> |
|
<script async="async" src="{{ application }}.js"></script> |
|
</div></div></div> |
|
</div> |
|
</body> |
|
</html> |
|
@endcode |
|
|
|
Replace @cb{.jinja} {{ application }} @ce with the name of your application |
|
executable. You can modify all the files to your liking, but the HTML file must |
|
contain at least the @cb{.html} <canvas> @ce enclosed in listener @cb{.html} <div> @ce |
|
and the @cb{.html} <pre id="log"> @ce for displaying the output. The JavaScript |
|
file contains event listeners which print loading status on the page. The |
|
status displayed in the remaining two @cb{.html} <div> @ce s, if they are |
|
available. The CSS file is shared with graphical apps, again see |
|
@ref platforms-html5-layout "below" for available options to tweak the default |
|
look. |
|
|
|
Deployment is similar to @ref platforms-html5-apps "graphical apps", only |
|
referencing a different JS file: |
|
|
|
@code{.cmake} |
|
if(CORRADE_TARGET_EMSCRIPTEN) |
|
install(TARGETS my-application DESTINATION ${CMAKE_INSTALL_PREFIX}) |
|
install(FILES |
|
my-application.html |
|
WindowlessEmscriptenApplication.js |
|
WebApplication.css |
|
DESTINATION ${CMAKE_INSTALL_PREFIX}) |
|
install(FILES |
|
${CMAKE_CURRENT_BINARY_DIR}/my-application.js.mem |
|
${CMAKE_CURRENT_BINARY_DIR}/my-application.wasm |
|
DESTINATION ${CMAKE_INSTALL_PREFIX} OPTIONAL) |
|
endif() |
|
@endcode |
|
|
|
@section platforms-html5-layout Modifying page style, canvas size and aspect ratio |
|
|
|
The `WebApplication.css` file contains a basic style and the additional |
|
@cb{.css} .container @ce, @cb{.css} .sizer @ce and @cb{.css} .expander @ce |
|
@cb{.html} <div> @ce s take care of aligning the canvas to the center and |
|
making it responsively scale on narrow screens, preserving aspect ratio. For |
|
proper responsiveness on all platforms it's important to include the |
|
@cb{.html} <meta name="viewport"> @ce tag in the HTML markup as well. |
|
|
|
By default the canvas is @cpp 640px @ce wide with a 4:3 aspect ratio, you can |
|
modify this by placing one of the @cb{.css} .aspect-* @ce CSS classes on the |
|
@cb{.html} <div id="container"> @ce: |
|
|
|
Aspect ratio | CSS class (landscape/portrait) |
|
--------------- | ------------------------------ |
|
1:1 | @cb{.css} .aspect-1-1 @ce <b></b> |
|
4:3 (1.33:1) | @cb{.css} .aspect-4-3 @ce (default) / @cb{.css} .aspect-3-4 @ce |
|
3:2 (1.5:1) | @cb{.css} .aspect-3-2 @ce / @cb{.css} .aspect-2-3 @ce |
|
16:9 (1.78:1) | @cb{.css} .aspect-16-9 @ce / @cb{.css} .aspect-9-16 @ce |
|
2:1 | @cb{.css} .aspect-2-1 @ce / @cb{.css} .aspect-1-2 @ce |
|
|
|
For example, for a 640x360 canvas (16:9 aspect ratio), you would use |
|
@cb{.html} <div id="container" class="aspect-16-9"> @ce. Besides the predefined |
|
classes above, it's also possible to specify your own aspect ratio using a |
|
@cb{.css} padding-bottom @ce style with a percentage equal to inverse of |
|
the ratio for @cb{.css} div#expander @ce --- for example, a 2.35:1 ratio would |
|
be @cb{.html} <div id="expander" style="padding-bottom: 42.553%"> @ce. |
|
|
|
Size of the canvas can be also overriden by specifying one of the |
|
@cb{.css} .width-* @ce CSS classes on the @cb{.html} <div id="container"> @ce: |
|
|
|
Width | CSS class |
|
--------------- | --------- |
|
240px | @cb{.css} .width-240 @ce <b></b> |
|
320px | @cb{.css} .width-320 @ce <b></b> |
|
360px | @cb{.css} .width-360 @ce <b></b> |
|
480px | @cb{.css} .width-480 @ce <b></b> |
|
600px | @cb{.css} .width-600 @ce <b></b> |
|
640px | @cb{.css} .width-640 @ce (default) |
|
800px | @cb{.css} .width-800 @ce <b></b> |
|
|
|
For example, for a 480x640 canvas (3:4, portrait) you would use |
|
@cb{.html} <div id="container" class="width-480 aspect-3-4"> @ce. Besides the |
|
predefined classes above, it's also possible to specify your own by adding a |
|
@cb{.css} width @ce style to the @cb{.css} div#sizer @ce --- for example, a |
|
1024x768 canvas would be @cb{.html} <div id="sizer" style="width: 1024px"> @ce. |
|
Again note that if the canvas is larger than window width, it gets |
|
automatically scaled down, preserving its aspect ratio. |
|
|
|
It's also possible to stretch the canvas to occupy the full page using the |
|
@cb{.css} .fullsize @ce CSS class set to @cb{.css} div#container @ce. In this |
|
case it's advised to remove all other elements (such as the @cb{.html} <h1> @ce |
|
element) from the page to avoid them affecting the canvas. Combining |
|
@cb{.css} .fullsize @ce with the other @cb{.css} .aspect-* @ce or |
|
@cb{.css} .width-* @ce classes is not supported. |
|
|
|
@section platforms-html5-events Controlling event behavior |
|
|
|
@subsection platforms-html5-events-keyboard Keyboard events |
|
|
|
By default, the graphical Emscripten application grabs all keyboard input |
|
anywhere on the page (so e.g. @m_class{m-label m-default} **F5** or opening |
|
browser console via a keyboard shortcut doesn't work). If you don't want it to |
|
grab keyboard input at all, set @cb{.js} Module.doNotCaptureKeyboard @ce to |
|
@cb{.js} true @ce, either by modifying the `EmscriptenApplication.js` file or |
|
directly in the HTML source: |
|
|
|
@code{.html} |
|
<script> |
|
// after EmscriptenApplication.js has been loaded |
|
Module.doNotCaptureKeyboard = true; |
|
</script> |
|
@endcode |
|
|
|
The above is implicitly set for windowless apps, because these don't have any |
|
event loop. |
|
|
|
Another solution is to specify the element on which it should capture keybard |
|
using @cb{.js} Module.keyboardListeningElement @ce --- it requires the actual |
|
element instance (*not* just its ID). The element then needs to be activated |
|
(for example with a mouse click) in order to start receiving input. The |
|
@cb{.html} <canvas> @ce element is a bit special in this regard --- in order to |
|
make it receive keyboard input, you have to add a `tabindex` attribute to it |
|
like this: |
|
|
|
@code{.html} |
|
<canvas id="module" tabindex="0"></canvas> |
|
@endcode |
|
|
|
After that, the canvas can be focused with a @m_class{m-label m-default} **Tab** |
|
key. But because Emscripten eats all mouse input, the `mousedown` event won't |
|
be propagated to focus the canvas unlesss you do that manually: |
|
|
|
@code{.js} |
|
Module.keyboardListeningElement = Module.canvas; |
|
Module.canvas.addEventListener('mousedown', function(event) { |
|
event.target.focus(); |
|
}); |
|
@endcode |
|
|
|
@subsection platforms-html5-events-contextmenu Context menu |
|
|
|
By default, the canvas opens a browser-specific popup menu on right click. That |
|
allows the user to for example save a screenshot of the canvas, but if you are |
|
handling right click directly in your app, you may want to disable the default |
|
behavior: |
|
|
|
@code{.js} |
|
Module.canvas.addEventListener('contextmenu', function(event) { |
|
event.preventDefault(); |
|
}, true); |
|
@endcode |
|
|
|
@section platforms-html5-environment Terminal output, environment and command-line arguments |
|
|
|
When running console apps using Node.js, command-line arguments and terminal |
|
output work like usual. |
|
|
|
For graphical apps in the browser, `EmscriptenApplication.js` redirects all |
|
output (thus also @ref Corrade::Utility::Debug "Debug", |
|
@ref Corrade::Utility::Warning "Warning" and @ref Corrade::Utility::Error "Error") |
|
to JavaScript console. For windowless apps, `WindowlessEmscriptenApplication.js` |
|
redirects output to the @cb{.html} <pre id="log"> @ce element on the page. |
|
|
|
It's possible to pass command-line arguments to @cpp main() @ce using GET URL |
|
parameters. For example, `/app/?foo=bar&fizz&buzz=3` will go to the app as |
|
@cb{.py} ['--foo', 'bar', '--fizz', '--buzz', '3'] @ce. |
|
|
|
Emscripten provides its own set of environment variables through |
|
@ref std::getenv() and doesn't expose system environment when running through |
|
Node.js. In order to access system environment, you can use the |
|
@ref Corrade::Utility::Arguments class, especially |
|
@ref Corrade::Utility::Arguments::environment(). |
|
|
|
@section platforms-html5-webgl Differences between WebGL and OpenGL ES |
|
|
|
WebGL is subset of OpenGL ES with some specific restrictions, namely |
|
requirement for unique buffer target binding, aligned buffer offset and |
|
stride and some other restrictions. The most prominent difference is that while |
|
the following was enough on desktop: |
|
|
|
@snippet MagnumGL.cpp Buffer-webgl-nope |
|
|
|
On WebGL (even 2.0) you always have to initialize the buffers like this (and |
|
other target hints for UBOs etc.): |
|
|
|
@snippet MagnumGL.cpp Buffer-webgl |
|
|
|
See @ref GL-Buffer-webgl-restrictions "GL::Buffer", |
|
@ref GL-Mesh-webgl-restrictions "GL::Mesh", |
|
@ref GL::Texture::setSubImage() "GL::*Texture::setSubImage()", |
|
@ref GL::Mesh::addVertexBuffer(), @ref GL::Renderer::setStencilFunction(), |
|
@ref GL::Renderer::setStencilMask() and @ref GL::Renderer::setBlendFunction() |
|
documentation for more information. The corresponding sections in official |
|
WebGL specification provide even more detail: |
|
|
|
- [Differences Between WebGL and OpenGL ES 2.0](http://www.khronos.org/registry/webgl/specs/latest/1.0/#6) |
|
- [Differences Between WebGL and OpenGL ES 3.0](https://www.khronos.org/registry/webgl/specs/latest/2.0/#5) |
|
|
|
@section platforms-html5-troubleshooting Troubleshooting |
|
|
|
@subsection platforms-html5-troubleshooting-macos Setting up Emscripten on macOS |
|
|
|
Emscripten is available through Homebrew: |
|
|
|
@code{.sh} |
|
brew install emscripten |
|
@endcode |
|
|
|
Because LLVM is also distributed as part of Xcode, it will get picked up by |
|
default. Emscripten however needs to use its own bundled version, so you may |
|
need to export the @cb{.sh} $LLVM @ce environment variable to port to the other |
|
location: |
|
|
|
@code{.sh} |
|
export LLVM=/usr/local/opt/emscripten/libexec/llvm/bin |
|
@endcode |
|
|
|
@subsection platforms-html5-troubleshooting-bootstrap First Emscripten run takes long or fails |
|
|
|
Emscripten downloads and builds a lot of things on first startup or after |
|
upgrade. That's expected and might take quite some time. If you are calling |
|
Emscripten through the CMake toolchain, it might be attempting to bootstrap |
|
itself multiple times, taking extreme amounts of time, or even fail during the |
|
initial CMake compiler checks for various reasons such as |
|
|
|
@code{.shell-session} |
|
File "/usr/lib/python2.7/subprocess.py", line 1025, in _execute_child |
|
raise child_exception |
|
OSError: [Errno 13] Permission denied |
|
@endcode |
|
|
|
The CMake toolchain might interfere with the bootstrap operation, causing it to |
|
fail. Solution is to wipe all Emscripten caches and trigger a rebuild of all |
|
needed libraries by compiling a minimal project, as shown in the shell snippet |
|
below --- enter it into the console prior to building anything else. It will |
|
take a while to download and build various system libraries and random tools. |
|
The @cb{.sh} -s WASM=1 @ce flag is needed in order to enable a rebuild of the |
|
`binaryen` tool as well: |
|
|
|
@code{.sh} |
|
cd /tmp |
|
emcc --clear-cache |
|
emcc --clear-ports |
|
echo "int main() {}" > main.cpp |
|
em++ -s WASM=1 main.cpp |
|
@endcode |
|
|
|
After this step it might be also needed to purge all CMake build directories |
|
and set them up again to ensure no bad state got cached. |
|
|
|
@subsection platforms-html5-troubleshooting-corrade-not-found CMake can't find _CORRADE_MODULE_DIR |
|
|
|
If initial CMake configuration fails with |
|
|
|
@code{.shell-session} |
|
Could NOT find Corrade (missing: _CORRADE_MODULE_DIR) |
|
@endcode |
|
|
|
The solution is to explicitly pass `CMAKE_PREFIX_PATH` pointing to directory |
|
where Corrade is installed. In some cases it might also be needed to point |
|
`CMAKE_FIND_ROOT_PATH` to the same location. For example: |
|
|
|
@code{.sh} |
|
mkdir build-emscripten && cd build-emscripte |
|
cmake .. \ |
|
-DCMAKE_TOOLCHAIN_FILE=../toolchains/generic/Emscripten-wasm.cmake \ |
|
-DCMAKE_PREFIX_PATH=/your/emscripten/libs/ \ |
|
-DCMAKE_FIND_ROOT_PATH=/your/emscripten/libs/ \ |
|
-G Ninja |
|
@endcode |
|
|
|
@subsection platforms-html5-troubleshooting-loading-failed Application fails to load |
|
|
|
Depending on what's the exact error printed in the browser console, the |
|
following scenarios are possible: |
|
|
|
- By default, the size of Emscripten heap is restricted to 16 MB. That might |
|
not be enough if you have large compiled-in resources or allocate large |
|
amount of memory. This can be solved with either of these: |
|
- Adding `-s TOTAL_MEMORY=<bytes>` to compiler/linker flags, where |
|
<bytes> is the new heap size |
|
- Adding `-s ALLOW_MEMORY_GROWTH=1` to compiler/linker flags. This is |
|
useful in case you don't know how much memory you need in advance and |
|
[might disable some optimizations](https://kripken.github.io/emscripten-site/docs/optimizing/Optimizing-Code.html#memory-growth). |
|
- Setting @cb{.js} Module { TOTAL_MEMORY: <bytes>; } @ce in the |
|
JavaScript driver file |
|
- Sometimes Chromium-based browsers refuse to create WebGL context on a |
|
particular page, while on other sites it works and the same page works in |
|
other browsers such as Firefox. This can be caused by Chromium running for |
|
too long, restart it and try again. |
|
- If you compile your application with a different set of compiler / linker |
|
flags or a different Emscripten version than your dependencies, it can fail |
|
to load for a variety of random reasons. Try to rebuild everything with the |
|
same set of flags. |
|
|
|
@subsection platforms-html5-troubleshooting-mime Incorrect response MIME type |
|
|
|
Depending on your browser, you might see a warning similar to the following in |
|
the console: |
|
|
|
@code{.shell-session} |
|
wasm streaming compile failed: TypeError: Failed to execute 'compile' on |
|
'WebAssembly': Incorrect response MIME type. Expected 'application/wasm'. |
|
falling back to ArrayBuffer instantiation |
|
@endcode |
|
|
|
This is not a critical error, but causes slow startup since the browser usually |
|
attempts to load the file twice. This is because the HTTP `Content-Type` header |
|
is not set properly by the webserver. In case you use Apache, fixing this is a |
|
matter of adding the following line to your `.htaccess`: |
|
|
|
AddType application/wasm .wasm |
|
|
|
@todoc use .htaccess extension for the code here once Pygments know it |
|
|
|
It is not possible when using Python `http.server` from the command line, but |
|
the mapping [can be added programmatically](https://docs.python.org/3/library/http.server.html#http.server.SimpleHTTPRequestHandler): |
|
|
|
@code{.py} |
|
http.server.SimpleHTTPRequestHandler.extensions_map['.wasm'] = 'application/wasm' |
|
@endcode |
|
|
|
*/ |
|
|
|
}
|
|
|