.. _Tutorial:

===================
Emscripten Tutorial
===================

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

First things first
======================

Make sure you have :ref:`downloaded and installed <sdk-download-and-install>`
Emscripten (the exact approach for doing this will depend on your operating system:
Linux, Windows, or Mac).

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

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

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

- On Linux or macOS, open a *Terminal*.
- On Windows, open the :ref:`Emscripten Command Prompt <emcmdprompt>`, a command
  prompt that has been pre-configured with the correct system paths and settings
  to point to the :term:`active <Active Tool/SDK>` Emscripten tools. To access
  this prompt, type **Emscripten** in the Windows start menu, and then
  select the **Emscripten Command Prompt** option.

Navigate with the command prompt to the emscripten directory under the SDK. This
is a folder below the :term:`emsdk root directory`, typically
**<emsdk root directory>/upstream/emscripten/**.
The examples below will depend on finding files relative to that location.

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


Verifying Emscripten
=====================

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

    ./emcc -v

If the output contains warnings about missing tools, see
:ref:`verifying-the-emscripten-environment` for debugging help. Otherwise,
continue to the next sections where we'll build some code.


Running Emscripten
==================

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

First, let's 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.

.. include:: ../../../../test/hello_world.c
   :literal:


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

  ./emcc test/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 :term:`node.js`:

::

    node a.out.js

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

.. 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 ``test/``
   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
   :ref:`emscripten-test-suite` for more information.



Generating HTML
===============

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

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

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

.. note:: Unfortunately, several browsers (including *Chrome* and *Safari*) do
   not support ``file://`` :term:`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
   :ref:`local webserver <faq-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.c
<https://github.com/emscripten-core/emscripten/blob/main/test/hello_world_sdl.c>`_
test code and then refresh the browser: ::

    ./emcc test/hello_world_sdl.c -o hello.html

The source code for the second example is given below:

.. include:: ../../../../test/hello_world_sdl.c
   :literal:


.. _tutorial-files:

Using files
===========

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

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

Files that you want to access should be :ref:`preloaded <emcc-preload-file>` or
:ref:`embedded <emcc-embed-file>` 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
<https://github.com/emscripten-core/emscripten/blob/main/test/hello_world_file.cpp>`_
example shows how to load a file (both the test code and the file to be loaded
shown below):

.. include:: ../../../../test/hello_world_file.cpp
   :literal:

.. include:: ../../../../test/hello_world_file.txt
   :literal:

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

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

  We compile the example from the directory "above" **test** to ensure the
  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 :ref:`preload
<emcc-preload-file>` 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 test/hello_world_file.cpp -o hello.html --preload-file test/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
:ref:`file-system-overview`, :ref:`Filesystem-API` and
:ref:`Synchronous-virtual-XHR-backed-file-system-usage`.


Optimizing code
===============

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

    ./emcc -O1 test/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 :ref:`here <emcc-O2>`) 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 test/hello_world.cpp

For more information about compiler optimization options see
:ref:`Optimizing-Code` and the :ref:`emcc tool reference
<emcc-compiler-optimization-options>`.


.. _running-emscripten-tests:

Emscripten Test Suite and Benchmarks
====================================

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

See :ref:`emscripten-test-suite` for more information.


General tips and next steps
===========================

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

- This site has lots more information about :ref:`compiling and building
  projects <compiling-and-running-projects-index>`, :ref:`integrating your
  native code with the web environment <integrating-porting-index>`,
  :ref:`packaging your code <packaging-code-index>` and publishing.
- The Emscripten test suite is a great place to look for examples of how to use
  Emscripten. For example, if you want to better understand how the *emcc*
  ``--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.
- To learn how to use Emscripten in advanced ways, read :ref:`src/settings.js
  <settings-js>` and :ref:`emcc <emccdoc>` which describe the compiler options,
  and :ref:`emscripten-h` for details on JavaScript-specific C APIs that your
  C/C++ programs can use when compiled with Emscripten.
- Read the :ref:`FAQ`.
- When in doubt, :ref:`get in touch <contact>`!
