Home Explore Blog CI



nixpkgs

1st chunk of `doc/languages-frameworks/emscripten.section.md`
7dcd2d65dd258e7900a6a0855777e137aa465431f8c3e4870000000100000b55
# Emscripten {#emscripten}

[Emscripten](https://github.com/kripken/emscripten): An LLVM-to-JavaScript Compiler

If you want to work with `emcc`, `emconfigure` and `emmake` as you are used to from Ubuntu and similar distributions,

```console
nix-shell -p emscripten
```

A few things to note:

* `export EMCC_DEBUG=2` is nice for debugging
* The build artifact cache in `~/.emscripten` sometimes creates issues and needs to be removed from time to time

## Examples {#declarative-usage}

Let's see two different examples from `pkgs/top-level/emscripten-packages.nix`:

* `pkgs.zlib.override`
* `pkgs.buildEmscriptenPackage`

A special requirement of the `pkgs.buildEmscriptenPackage` is the `doCheck = true`.
This means each Emscripten package requires that a [`checkPhase`](#ssec-check-phase) is implemented.

* Use `export EMCC_DEBUG=2` from within a phase to get more detailed debug output what is going wrong.
* The cache at `~/.emscripten` requires to set `HOME=$TMPDIR` in individual phases.
  This makes compilation slower but also more deterministic.

::: {.example #usage-1-pkgs.zlib.override}

# Using `pkgs.zlib.override {}`

This example uses `zlib` from Nixpkgs, but instead of compiling **C** to **ELF** it compiles **C** to **JavaScript** since we were using `pkgs.zlib.override` and changed `stdenv` to `pkgs.emscriptenStdenv`.

A few adaptions and hacks were put in place to make it work.
One advantage is that when `pkgs.zlib` is updated, it will automatically update this package as well.


```nix
(pkgs.zlib.override {
  stdenv = pkgs.emscriptenStdenv;
}).overrideAttrs
  (old: {
    buildInputs = old.buildInputs ++ [ pkg-config ];
    # we need to reset this setting!
    env = (old.env or { }) // {
      NIX_CFLAGS_COMPILE = "";
    };

    configurePhase = ''
      # FIXME: Some tests require writing at $HOME
      HOME=$TMPDIR
      runHook preConfigure

      #export EMCC_DEBUG=2
      emconfigure ./configure --prefix=$out --shared

      runHook postConfigure
    '';

    dontStrip = true;
    outputs = [ "out" ];

    buildPhase = ''
      runHook preBuild

      emmake make

      runHook postBuild
    '';

    installPhase = ''
      runHook preInstall

      emmake make install

      runHook postInstall
    '';

    checkPhase = ''
      runHook preCheck

      echo "================= testing zlib using node ================="

      echo "Compiling a custom test"
      set -x
      emcc -O2 -s EMULATE_FUNCTION_POINTER_CASTS=1 test/example.c -DZ_SOLO \
      libz.so.${old.version} -I . -o example.js

      echo "Using node to execute the test"
      ${pkgs.nodejs}/bin/node ./example.js

      set +x
      if [ $? -ne 0 ]; then
        echo "test failed for some reason"
        exit 1;
      else
        echo "it seems to work! very good."
      fi
      echo "================= /testing zlib using node ================="

      runHook postCheck

Title: Emscripten: An LLVM-to-JavaScript Compiler
Summary
This section introduces Emscripten, an LLVM-to-JavaScript compiler, and provides instructions for using it within a Nix environment. It covers setting up the environment with `nix-shell`, debugging tips, and addresses potential caching issues. The section also presents two examples from `pkgs/top-level/emscripten-packages.nix`: overriding `pkgs.zlib` and using `pkgs.buildEmscriptenPackage`, highlighting the requirement for a `checkPhase` in the latter. A detailed example demonstrates how to override `pkgs.zlib` to compile C code to JavaScript using `pkgs.emscriptenStdenv`, including necessary adaptations, build phases, and a check phase that uses Node.js to execute a custom test.