Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 106 additions & 0 deletions site/source/docs/compiling/best_practices.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
.. _Best-Practices:

==============
Best Practices
==============

This guide provides recommendations and best practices for compiling C and C++
to the modern web using WebAssembly and Emscripten.

Following this guide when reporting bugs can also help speed up diagnosing and
fixing issues since you will be on the well-trodden path.

In some cases, Emscripten will guide you towards these best practices by
emitting warnings, but that is not always possible.


General Recommendations
=======================

- **Avoid high-frequency calls between WebAssembly and JavaScript**; for
example, avoid per-pixel or per-sample calls in favor of operations that
process entire memory regions or buffers.
- **Avoid shipping debug information in production**; see below for recommended
release build flags.


Command-Line Style
==================

Keeping the command line flag usage minimal and consistent helps with codebase
understanding and avoids deviating from the well-lit path.

- **Don't pass settings that are enabled by default.** To keep command lines
clean and concise, omit redundant options that are already default in modern
Emscripten (such as ``-sWASM=1``).
- **Prefer standard compiler flags** over Emscripten-specific ones where
possible (for example, prefer ``-pthread`` over ``-sUSE_PTHREADS`` and
``-m64`` over ``-sMEMORY64``).
- **Use simple comma-separated lists** for list-based settings (for example,
``-sEXPORTED_FUNCTIONS=_main,_malloc`` rather than JSON arrays like
``-sEXPORTED_FUNCTIONS=['_main','_malloc']``).
- **Avoid long lists on the command line**; use a response file (``@filename``)
instead (for example, ``-sEXPORTED_FUNCTIONS=@exported_funcs.txt``).
- **Don't include the "=1" suffix for boolean flags.** For example, write
``-sSTRICT`` and ``-sALLOW_MEMORY_GROWTH`` rather than ``-sSTRICT=1`` or
``-sALLOW_MEMORY_GROWTH=1``.
- **Use separate compilation** by compiling ``.cpp`` sources to ``.o`` object

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would put all the things before this in a "lint" section. Separate compilation and C++/JS interop feel like substantially different things, choices about the build system and design.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've called this section "Command-Line Style" .. I also considered "Command line hygene"

files before linking rather than combining everything into a single monolithic
compiler invocation.


Recommended Flags
=================

- ``-sSTRICT``: Opt into strict modern Emscripten behavior, disabling
deprecated or legacy compatibility features.
- ``-sEXPORT_ES6``: Output a modern ES6 module (``module.mjs``). This option
Comment thread
sbc100 marked this conversation as resolved.
implies ``-sMODULARIZE`` so the generated code will be encapsulated and not
impact the global namespace.
- ``-sENVIRONMENT=web``: Limit the runtime support to only the environments you
are targeting. This reduces code size by, for example, omitting Node.js and
compatibility code.
- ``-Werror -Wall``: Treat warnings as errors to catch C++ bugs and invalid
compiler settings early.
- ``-O3``, ``-Os``, or ``-Oz``: For release builds, choose ``-O3`` when runtime
performance is most critical, or ``-Os`` / ``-Oz`` when minimizing binary
payload size is the priority.
- ``-flto``: Enable Link-Time Optimization (LTO) during both the compilation and
linking steps of release builds for maximum runtime performance and size
reduction.
Comment thread
sbc100 marked this conversation as resolved.

Comment thread
sbc100 marked this conversation as resolved.

Debug vs. Release Profiles
--------------------------

When configuring build profiles, keep compile and link flags consistent within
each configuration:

- **Release Builds:** Use ``-Oz`` or ``-Os`` (or ``-O3`` for CPU-bound tasks)
combined with ``-flto``. Add ``--closure=1`` to get minified JavaScript too,
unless you plan to minify with an external tool.
- **Debug Builds:** Use ``-g`` when compiling and either ``-g``,
``-gline-tables-only``, or ``-gsource-map`` when linking. Avoid optimization
flags (such as ``-O2`` or ``-O3``) or ``-flto`` during debug builds for
faster compilation and accurate debugging.


Modern Web Workflows and Common Pitfalls
========================================

Asynchronous Code Execution and Main Thread Blocking
----------------------------------------------------

**Don't run long synchronous loops on the browser main thread.** The browser
uses cooperative multitasking; blocking the main UI thread prevents rendering
and freezes the web page.

- Restructure infinite loops to yield to the event loop using
:c:func:`emscripten_set_main_loop`
(see :ref:`emscripten-runtime-environment-howto-main-loop`).
- For synchronous-looking C++ code that must pause (or interact with
asynchronous JavaScript APIs such as ``fetch()`` or Web Promises) without
refactoring into callbacks, use :ref:`Asyncify <yielding_to_main_loop>`
(``-sASYNCIFY``) or JavaScript Promise Integration (``-sJSPI``).
- Offload heavy compute or blocking operations to background workers using
:doc:`multithreading and pthreads <../porting/pthreads>` (``-pthread``).
2 changes: 2 additions & 0 deletions site/source/docs/compiling/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Compiling and Running Projects

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

- :ref:`Best-Practices` covers recommended compiler flags, modern web workflows, and Dos and Don'ts for using Emscripten.
- :ref:`Building-Projects` shows how to use :ref:`emccdoc` as a drop-in replacement for *gcc* in your existing project.
- :ref:`WebAssembly` explains how Emscripten can be used to build WebAssembly files
- :ref:`Running-html-files-with-emrun` explains how to use *emrun* to run generated HTML pages in a locally launched web server.
Expand All @@ -19,6 +20,7 @@ This section contains topics about building projects and running the output.
.. toctree::
:hidden:

best_practices
Building-Projects
WebAssembly
Modularized-Output
Expand Down
4 changes: 0 additions & 4 deletions site/source/docs/porting/guidelines/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,3 @@ Emscripten can be used to compile almost any *portable* C/C++ code to JavaScript
api_limitations
function_pointer_issues
browser_limitations.rst




Loading