-
Notifications
You must be signed in to change notification settings - Fork 3.5k
Add a Best Practices section to the website. NFC #27334
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
sbc100
wants to merge
4
commits into
emscripten-core:main
Choose a base branch
from
sbc100:best_practices
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+108
−4
Open
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 | ||
| 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 | ||
|
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. | ||
|
sbc100 marked this conversation as resolved.
|
||
|
|
||
|
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``). | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
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"