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
Syrus Akbary
Founder & CEO
October 7, 2024
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!)
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:
- Github: https://github.com/wasmerio/wasmer
- Or join us in our Discord: https://discord.gg/rWkMNStrEW
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
Syrus Akbary
Founder & CEO
NOTE: this will download the clang package (100Mb), so it might take a while...
Javascript SDK usage
One last thing! 🪄
What’s coming next
Read more
wasixengineeringepollruntime
Boosting Performance: Integration of epoll syscall in WASIX
RudraAugust 8, 2023
wasixhappinessculturewasmer edgeteamcompany meetup
Marrakech - a company meetup worth remembering
Syrus AkbarySeptember 23, 2023