backgroundradial

Running Clang in the browser using WebAssembly

Discover how to compile C programs directly from JavaScript or any browser (Chrome, Firefox, Safari), and explore the powerful capabilities of the Wasmer JS SDK

syrusakbary avatar
syrusakbary

Founder & CEO

wasix

October 7, 2024

arrowBack to articles
Post cover image

We’ve reached a major milestone in making any software run with WebAssembly. Thanks to the newest release of Wasmer (4.4) and the Wasmer JS SDK (0.8.0) you can now run clang anywhere Wasmer runs!

This allows compiling C programs from virtually anywhere. Including Javascript and your preferred browser! (we tested Chrome, Safari and Firefox and everything is working like a charm).

For those eager to see it in action, head over to wasmer.sh to try a live demo (note: it requires a 100MB download):

# NOTE: this will download the clang package (100Mb), so it might take a while...
wasmer run clang/clang example.c -o example.wasm
wasmer run example.wasm

Note: we attempted running clang few years ago, but because of WASI limitations we were unable to call posix_spawn which limited the usage and usability of clang in the browser, Firefox and Safari were not supported by then but are fully supported now.


Why is running clang with Wasmer useful, what use cases will enable?

  • You can compile C code to WebAssembly easily just using the wasmer CLI: no toolchains or complex installations needed, install Wasmer and you are ready to go!

  • WASIX is now self-hosted meaning it can compile itself and any C programs.

  • You can compile C projects directly from JavaScript! (Continue reading to learn how to use clang with the Wasmer JS SDK.)

    We expect online IDEs to start adopting the SDK to allow their users compile and run C programs in the browser.

  • Reproducible builds anywhere (using the same version of Wasmer)

Enough with the tech talk—let’s see a demo!

Create a donut.c file with the following content (example taken from the awesome Donut Math):

#include <stdio.h>
#include <string.h>

             k;double sin()
         ,cos();main(){float A=
       0,B=0,i,j,z[1760];char b[
     1760];printf("\x1b[2J");for(;;
  ){memset(b,32,1760);memset(z,0,7040)
  ;for(j=0;6.28>j;j+=0.07)for(i=0;6.28
 >i;i+=0.02){float c=sin(i),d=cos(j),e=
 sin(A),f=sin(j),g=cos(A),h=d+2,D=1/(c*
 h*e+f*g+5),l=cos      (i),m=cos(B),n=s\
in(B),t=c*h*g-f*        e;int x=40+30*D*
(l*h*m-t*n),y=            12+15*D*(l*h*n
+t*m),o=x+80*y,          N=8*((f*e-c*d*g
 )*m-c*d*e-f*g-l        *d*n);if(22>y&&
 y>0&&x>0&&80>x&&D>z[o]){z[o]=D;;;b[o]=
 ".,-~:;=!*#$@"[N>0?N:0];}}/*#****!!-*/
  printf("\x1b[H");for(k=0;1761>k;k++)
   putchar(k%80?b[k]:10);A+=0.04;B+=
     0.02;}}/*****####*******!!=;:~
       ~::==!!!**********!!!==::-
         .,~~;;;========;;;:~-.
             ..,--------,*/

We can run clang with Wasmer and compile it to WASI and WASIX (just make sure you have Wasmer installed locally!):

$ wasmer run clang/clang --dir=. -- -Wno-implicit-int donut.c -o donut.wasm
$ wasmer run donut.wasm

To run clang on your browser, you can try the following on wasmer.sh (we added donut.c to the /home dir so it’s easier to try):

wasmer run clang/clang -Wno-implicit-int donut.c -o donut.wasm
wasmer run /home/donut.wasm

The exciting news is that the clang package can compile, not just the donut c example, but any complicated examples from WASIX.

And more importantly… it works fully in the browser! (and also via the Wasmer Javascript SDK, read below to check the example of how to run clang in any of your Javascript projects!)

Donut compiled to Wasm in the browser

Note: the clang/clang package currently weights about 100Mb uncompressed (as it requires the clang binaries + the system libraries). We are working on reducing the size and also serving it in compressed format. So ideally you should just need to download ~30Mb to use clang with Wasmer: either in your local shell, in your browser or in your Javascript project!

Javascript SDK usage

Do you want to use clang in your Javascript project? Thanks to our newly released Wasmer JS SDK you can do it easily, in both the browser and Node.js/Bun etc:


import {
  init,
  Wasmer,
  Directory
} from "https://unpkg.com/@wasmer/sdk@latest/dist/index.mjs";

await init();

const clang = await Wasmer.fromRegistry("clang/clang");
const project = new Directory();
await project.writeFile("example.c",
`#include<stdio.h>

int main() {
  printf("Hello World");
  return 0;
}
`);

let instance = await clang.entrypoint.run({
  args: ["/project/example.c", "-o", "/project/example.wasm"],
  mount: { "/project": project },
});
const output = await instance.wait();

if (!output.ok) {
  throw new Error(`Clang failed. Exit: ${output.code}:`);
}

// The generated wasm file from clang
let wasm = await project.readFile("example.wasm");

const example = await Wasmer.fromFile(wasm);
const result = await example.entrypoint.run();
const outputExample = await result.wait();

// This should be "Hello World"
console.log(outputExample.stdout);

You can find a working index.html file executing clang: https://github.com/wasmerio/wasmer-js/blob/main/examples/clang-cdn/index.html

One last thing! 🪄

Wasmer’s clang can even optimize the file for you automatically using wasm-opt under the hood (Clang automatically detects if wasm-opt is used, and it will be automatically called when optimizing the file)

wasmer run clang/clang --use wasmer/wasm-opt --dir=. -- -o example.wasm -O2

Imagine using Emscripten without needing its toolchain installed—or even better, imagine running Emscripten in the browser. We've made this possible thanks to the WASIX ecosystem 🎉.

What’s coming next

We are incredibly excited for this milestone, as it opens the door for many upcoming features that we are going to need in Wasmer and Wasmer Edge:

  • Compiling native Python libraries directly from within WASIX. Imagine being able to have PIP compiling things in Wasm upon install, e.g.:

    wasmer run python --entrypoint pip -- install numpy # This compiles numpy to WASIX, all within Wasmer processes
    
  • Using py2wasm with a bundled compiler

  • Compiling Static Hermes to WASIX, so we can generate native Wasm files from JS.

  • New tooling? (any project depending on LLVM can now be easily compiled to WebAssembly!)

This is the beginning of an awesome journey, we can't wait to see what you create next with this.

Feel free to give Wasmer a star if you liked the article or tell us how you are thinking on using the project:


I want to give a special mention to Sebastien, who made the hard work on compiling clang to WASIX possible. Check his personal project, box86, if you want to see more awesome programs running anywhere: box86.org

About the Author

Syrus Akbary is an enterpreneur and programmer. Specifically known for his contributions to the field of WebAssembly. He is the Founder and CEO of Wasmer, an innovative company that focuses on creating developer tools and infrastructure for running Wasm

 avatar

Founder & CEO

Read more
Post cover image

wasixengineeringepollruntime

Boosting Performance: Integration of epoll syscall in WASIX

RudraAugust 8, 2023

wasixengineeringsecurity

Our Precious: Cryptographic Support for WASIX

RudraAugust 10, 2023

wasixhappinessculturewasmer edgeteamcompany meetup

Marrakech - a company meetup worth remembering

September 23, 2023