From 39a5fdc85b9d2ecde42bb16e02a9621ac32b12da Mon Sep 17 00:00:00 2001
From: Guus Waals <_@guusw.nl>
Date: Fri, 12 Jun 2026 18:47:44 +0200
Subject: [PATCH] WIP emscripten documentation
---
posts/cpp-without-emscripten.md | 110 +++++++++++++++++++++++++++++++-
templates/index.html | 2 +-
templates/page_work.html | 4 +-
3 files changed, 111 insertions(+), 5 deletions(-)
diff --git a/posts/cpp-without-emscripten.md b/posts/cpp-without-emscripten.md
index 580841a..0d60e21 100644
--- a/posts/cpp-without-emscripten.md
+++ b/posts/cpp-without-emscripten.md
@@ -1,6 +1,112 @@
# C++ without emscripten
If you've ever worked on a C++/C project and wanted to distribute it for browsers, you have probably hear of emscripten. emscripten allows you to compile your existing C++/C codebase without (if you're lucky) any changes and run it in a browser.
-This is made possible by the use of WebAssembly (wasm) combined with a javascript interface to browser functionality.
+This is made possible by the use of WebAssembly (which I will call wasm from now on) combined with a javascript interface to browser functionality.
-For my game project I have been doing some research into this process and doing the same but without emscripten. In theory you don't need emscripten as the entire compilation step to WebAssembly (wasm) is already handled by LLVM with it's wasm backend.
+For my current project I have been doing some research into this process and doing the same but without emscripten. In theory you don't need emscripten as the entire compilation step to wasm is already handled by LLVM with it's wasm backend. emscripten is also a pretty large codebase and I wanted to cut down on dependencies for this project.
+
+All the source code for this guide will be available [here](https://git.bakje.coffee/guus/cjs-lite)
+
+## Disclaimer
+
+If you have a large complicated project with an existing codebase you might want to stick to just using emscripten as it provides a lot of the standard library and APIs such as for WebGL, file access, http, etc. For my own project I have full control over the entire codebase which includes not using any of the C++ standard library, no C++ exceptions and no graphics APIs since I'm working with a pure software renderer.
+
+The ideas mentioned here don't attempt to fully replace emscripten, rather just provide insights into what it does and how you can possibly live without it for smaller projects.
+
+## Compilation step
+
+The first step trying to compile for the browser was to setup clang and the llvm linker to spit out a wasm file. From here on I will be using CMake to setup the toolchain, however you can adapt this to whatever build system.
+
+I will use the llvm installation that is available on my system. Most linux distributions will have one available or preinstalled. The tools I'm using in this guide are `clang`, `clang++`, `llvm-mc` and `wasm-ld`. `llvm-mc` is the llvm machine code compiler which is used to compile a small snippet for the threading code later on.
+These should all come with a recent llvm installation. Recent releases can also be found on the llvm-project github page [here](https://github.com/llvm/llvm-project/releases)
+
+To easily switch to compilation for web I created a small CMake toolchain file that can be referenced during the configuration step using `-DCMAKE_TOOLCHAIN_FILE=Web.cmake`.
+At this point it looks something like [this](TODO) and can be used to compile a simple test file.
+
+Certain builtins and attributes are available to interface specifically with the javascript plaform. I already required one such attribute to export a function so it is visible in the compiled wasm module like this:
+
+```cpp
+__attribute__((export_name("hello")))
+int hello() {
+ return 4;
+}
+```
+
+In addition you will need to pass some flags to the linker to describe the memory that your wasm module requires. This can be done like this in CMake:
+```
+target_link_options(app PRIVATE
+ -Wl,--no-entry
+ -Wl,--no-growable-memory
+ -Wl,--initial-memory=536870912
+)
+```
+Which will set the initial memory to 512MiB, disable automatic resizing of memory (explained later) and disable the default entry point.
+Since CMake will use `clang` as the linker executable, we need to use -Wl to pass these to the linker.
+
+When building this, the output (`app.wasm`) will be inside the build folder. We can inspect this using the WebAssembly Binary Toolkit (wabt), which can be obtained [here](https://github.com/WebAssembly/wabt#). There are releases available for most platforms, they might be available from your package manager or can be built from source.
+
+Running wasm2wat -- which will convert any wasm binary or object file generated by llvm into a textural representation -- we get something like the following:
+
+```wat
+(module $app.wasm
+ (type (;0;) (func (result i32)))
+ (import "env" "memory" (memory (;0;) 8192 8192))
+ (func $hello (type 0) (result i32)
+ i32.const 4
+ return)
+ (table (;0;) 1 1 funcref)
+ (global $__stack_pointer (mut i32) (i32.const 65536))
+ (export "hello" (func $hello))
+ (@custom "name" "\00\09\08app.wasm\01\08\01\00\05hello\07\12\01\00\0f__stack_pointer")
+ (@custom "producers" "\01\0cprocessed-by\01\05clang\0d22.1.7+libcxx")
+ (@custom "target_features" "\0a+\07atomics+\0bbulk-memory+\0fbulk-memory-opt+\16call-indirect-overlong+\0amultivalue+\0fmutable-globals+\13nontrapping-fptoint+\0freference-types+\08sign-ext+\07simd128"))
+```
+
+> Note that you might have to enable certian features or run with `wasm2wat --enable-all app.wasm` to enable all the extensions that might also be passed to the compiler.
+
+Here we can see the module exports "hello" (our function) alongside "memory" which is the memory that is available to the program. We will need the memory later to pass any data which we can not encode into function parameters (which can only be integers)
+
+The memory size is specified in the binary since we specified it during link time:\
+```(import "env" "memory" (memory (;0;) 8192 8192))```\
+This specifies both the minimum and maximum memory size in 64KiB pages, 8192 * 64 * 1024 = 512MiB
+
+> Most often you will want to set the memory to a fixed size, as it can [currently](https://github.com/WebAssembly/design/issues/1397#issuecomment-1247972859) **never** shrink and only grow when enabled (remove the `--no-growable-memory` linker flag). However for performance, simplicity and to limit browser memory usage I decided to constrain my application design within this fixed memory space.
+
+The wasm2wat output also shows the `__stack_pointer` global which is used for the program's stack memory. This means that it shares the same memory and lives at the start of your memory block at address `65536` and grows towards `0`
+
+## Running from JavaScript
+
+To run the wasm application a little wrapper is provided [here](https://git.bakje.coffee/guus/cjs-lite/TODO) as a little main.js + index.html.
+
+> As a bonus this also includes a server.js which hosts the files and sends a reload request to the browser whenever any source file changes, which will then reload the page automatically :)\
+This server refers to `build/app.wasm` by relative path, so make sure your build ends up there.
+
+Besides being convenient, the server is also required to set the following HTTP headers.
+These are required later to get access to shared memory when adding web workers:
+```
+Cross-Origin-Opener-Policy: 'same-origin'
+Cross-Origin-Embedder-Policy: 'require-corp'
+```
+
+The main part of the browser code (main.js) is the following which fetches and instantiates the module:
+```js
+const response = await fetch('./bin/app.wasm');
+const wasmBytes = await response.arrayBuffer();
+const wasmCompiled = await WebAssembly.compile(wasmBytes);
+const wasmModule = await WebAssembly.instantiate(wasmCompiled, { });
+
+var result = wasmModule.exports.hello();
+log("Finished", result);
+```
+
+We can see the output `Finished 4` if we check the browser console (Ctrl+Shift+i or F12). The 4 came from the `return 4` inside the C function.
+
+## Exposing functions
+
+## C Standard library
+
+## compiler-rt
+
+## C++ Standard library
+
+## Shared memory and Threading
diff --git a/templates/index.html b/templates/index.html
index 89230ff..58cdc07 100644
--- a/templates/index.html
+++ b/templates/index.html
@@ -1,5 +1,5 @@
$
Hey, welcome to my page :)
Here I plan to posts frequent updates related to the game I'm working on. If you're looking to work together check out this page
+
A blog about game development and whatever else I'm up to :). If you're looking to work together check out this page
If you have any project that could use my skills, I'd be happy to talk to you.
-
Feel free to contact me at:
+
Contact me at: