Getting Started with Emscripten: Transpiling C/C++ to JavaScript/HTML5

Key Takeaways
- Emscripten is an LLVM-based tool that allows developers to compile C and C++ into highly performant JavaScript in the asm.js format, enabling near-native speeds inside a browser. It also converts OpenGL, a desktop graphics API, into WebGL, the web variant.
- Getting Emscripten to work can be challenging, with the SDK Offline installer recommended over the Web Installer. Emscripten can be used from Visual Studio, but it is simpler to perform builds from the Emscripten Command Line Interface (CLI).
- Emscripten allows for interoperability between C++ and JavaScript. Developers can call compiled C functions from normal JavaScript and vice versa. However, it does have limitations, including difficulties with code that is multi-threaded, as JavaScript is single threaded.
- Emscripten is a powerful tool for web developers, allowing them to leverage the performance and capabilities of C/C++ in a web environment. However, it does have some limitations, including issues with system-specific features or direct hardware access.
Platforms
I’m doing this on Windows 10, but the process is the same for the Unix based platforms, OS X and Linux. The only real change you’ll need to make at this point is in the way you enter your code into the command line/
terminal. For Windows, I simply write emcc. For Unix based environments, you must prefix your calls with ./
, so your command would read: ./emcc
The Installation Process
I had initially considered not writing this tutorial, but when I ran into so many issues with the installer, I thought it would be helpful to others. I looked at how Epic recommended it for exporting projects from UE4, and they suggested to use the SDK Web Installer. This led me down a rabbit hole. I was hoping that the installation process was going to be smooth, but I spent nearly two days trying to get Emscripten working correctly on my machine before having any success. The team has fantastic getting started instructions on the site, but if you pick the wrong installer, you may be in for some trouble.

The Emscripten SDK provides the whole Emscripten toolchain (Clang, Python, Node.js and Visual Studio integration) in a single easy-to-install package, with integrated support for updating to newer SDKs as they are released.– Emscripten Getting Started Guide
Getting Started
Run the Emscripten Command Prompt to get started. I generally hitwin + ems
and it appears.

emscripten\tag-1.34.1
, because you can see that the path to emscripten is set in the image above as:
EMSCRIPTEN = C:\Program Files\Emscripten\emscripten\tag-1.341

explorer
.’ into the CLI to open the explorer folder and better visualize what you’re looking at. For folders which have dozens of items, this can often be easier than typing ‘ls
‘ to list everything in the directory.

'emcc -v'
will be your sanity check to verify that everything is working correctly in the version you are running. You should see something like:

hello_world.c
and convert it to JavaScript. The C code looks like:
#include<stdio.h>
int main() {
printf("hello, world!\n");
return 0;
}
We are going to be running this out of our tests folder, which is one level further down the chain. To build the code, enter:
emcc tests/hello_world.c
If it all went well, your CLI should pause for a moment, then return to the same location. What’s going on here? Well the compiler wasn’t very verbose about giving us any sort of feedback, so let’s add that now, to get a better understanding of what’s happening behind the scenes.
We’ll add the ‘-v
‘ argument to our command, to make the compiler spit out more verbose information.
emcc tests/hello_world.c -v
That’s more like it:

a.out.js
file in our current directory. If you prefer to use C++, you could use ‘em++
‘ instead of ‘emcc
‘.

a.out.js
is what is key here, because it contains your JavaScript code based on the asm.js specification. If we execute this with node, you will see ‘hello, world
‘ appear in the CLI. Enter this command:
node a.out.js

That’s Great, But I Want to See Something in My Browser
Generating HTML
First check your web platform status for browsers that support asm.js. We can actually use Emscripten to generate several different types of extensions with the–o
argument. From the docs:
-o <target>
The target file name extension defines the output type to be generated:
<name>.js : JavaScript.
<name>.html : HTML + separate JavaScript file (<name>.js).
Having the separate JavaScript file improves page load time.
<name>.bc : LLVM bitcode (default).
<name>.o : LLVM bitcode (same as .bc).
In this case, we want HTML so that we can view it in the browser. Enter this command to specify and HTML document:
Emcc tests/hello_world./c -o hello.html
We are telling Emscripten
to use the C compiler to look into the tests
folder for the file hello_world.c
and then output it as hello.html
. Inside of your C:\Program Files \Emscripten\emscripten\tag-1.34.1
folder you should see hello.html
.


Reading from a File
Because the browser runs JavaScript within a sandboxed environment, we don’t have direct access to the local file system. To work around this, a simulated file system is created by Emscripten so that we can use thelibc stdio
API to access the compiled C/C++ code
. The catch is that the virtual file system requires these files to be embedded or pre-loaded
.
Let’s move to the hello_world_file.cpp
as our final part of the tutorial and read a file, as this will cover several parts I wanted to discuss, including how to serve the content.
The code for the file looks like:
#include <stdio.h>
int main() {
FILE *file = fopen("tests/hello_world_file.txt", "rb");
if (!file) {
printf("cannot open file\n");
return 1;
}
while (!feof(file)) {
char c = fgetc(file);
if (c != EOF) {
putchar(c);
}
}
fclose (file);
return 0;
}
If you have a web background and aren’t used to working with strongly typed languages, you’re probably thinking “What does feof
mean?” this threw me into a loop as well, but this Stack Overflow question cleared up quite a bit of confusion for me:
Now we get to EOF. EOF is the response you get from an attempted I/O operation. It means that you were trying to read or write something, but when doing so you failed to read or write any data, and instead the end of the input or output was encountered. This is true for essentially all the I/O APIs, whether it be the C standard library, C++ iostreams, or other libraries. As long as the I/O operations succeed, you simply cannot know whether further, future operations will succeed. You must always first try the operation and then respond to success or failure.This is going to attempt to read from a file located at
tests/hello_world_file.txt
. To do that, we need to run this command:
Emcc tests/hello_world_file.cpp -o hello.html –preload-file tests/hello_world_file.txt
Now try opening that same hello.html
file again and see what happens.
In FireFox, all is fine:



file:// XHR requets
, so local files with preloaded data can’t be loaded. We need to spin up a webserver. We already have python installed, as it is part of the emscriten
package, so let’s spin up a simple server from our current directory and try this again.
python -m SimpleHTTPServer 8080


Connecting C++ and JavaScript
I know what you’re thinking. “This is great, but if there isn’t any sort of interoperability between my C++ and JavaScript, then this isn’t very useful.” Fortunately, there is! There are several ways:- Call compiled C functions from normal JavaScript:
- Using ccall or cwrap
- Using direct function calls (faster but more complicated).
- Call compiled C++ classes from JavaScript using bindings created with:
- Call JavaScript functions from C/C++:
Not without its limitations
There are several areas where Emscripten is still limited. For example, Code which is multi-threaded cannot be used, as JavaScript is single threaded. The best workaround I could conceive of would be one where you could somehow split this code into web workers, which is JavaScript’s way of simulating multithreading. There are also bits of code which are known to compile, but run with performance issues. Notably, 64bit int variables. Mathematical operations are slow because they are emulated, but the inclusion of SIMD (Single Instruction Multiple Data) should help with this in the near future as browsers adopt it. This page on portability guidelines can offer more info.Following up
I didn’t want to dive too deep with this today, but in my next tutorial for the series, I’d like to cover some more complicated examples, which take advantage of SDLib, as well as a middleware tool such as Unreal Engine 4 or Unity, so that we can see how asm.js really performs in the browser.More hands-on with Web Development
This article is part of the web development series from Microsoft tech evangelists on practical JavaScript learning, open source projects, and interoperability best practices including Microsoft Edge browser and the new EdgeHTML rendering engine. We encourage you to test across browsers and devices including Microsoft Edge – the default browser for Windows 10 – with free tools on dev.modern.IE:- Scan your site for out-of-date libraries, layout issues, and accessibility
- Download free virtual machines for Mac, Linux, and Windows
- Check Web Platform status across browsers including the Microsoft Edge roadmap
- Remotely test for Microsoft Edge on your own device
- Coding Lab on GitHub: Cross-browser testing and best practices
- Microsoft Edge Web Summit 2015 (from our engineering team and JS community)
- Woah, I can test Edge & IE on a Mac & Linux! (from Rey Bango)
- Advancing JavaScript without Breaking the Web (from Christian Heilmann)
- The Edge Rendering Engine that makes the Web just work (from Jacob Rossi)
- Unleash 3D rendering with WebGL (from David Catuhe)
- Hosted web apps and web platform innovations (from Kevin Hill and Kiril Seksenov)
- vorlon.JS (cross-device remote JavaScript testing)
- manifoldJS (deploy cross-platform hosted web apps)
- babylonJS (3D graphics made easy)
Frequently Asked Questions (FAQs) about Emscripten and Transpiling C/C++ to JavaScript
What is Emscripten and why is it important in transpiling C/C++ to JavaScript?
Emscripten is an open-source compiler that allows you to convert C/C++ code into JavaScript. This is particularly useful for web developers who want to leverage the performance and capabilities of C/C++ in a web environment. Emscripten compiles C/C++ code into a subset of JavaScript known as asm.js, which can be executed at near-native speed. It also supports WebAssembly, a binary format that allows you to run C/C++ at native speed in modern browsers.
How does Emscripten differ from other C/C++ to JavaScript converters?
Unlike other converters, Emscripten does not just convert the syntax of C/C++ to JavaScript. Instead, it compiles the C/C++ code into asm.js or WebAssembly, both of which can be executed at near-native speed. This means that you can use Emscripten to bring performance-intensive applications to the web without sacrificing speed.
Can I use Emscripten to convert any C/C++ program to JavaScript?
While Emscripten is a powerful tool, it does have some limitations. Not all C/C++ programs can be converted to JavaScript without modifications. For example, programs that rely on system-specific features or direct hardware access may not work correctly after being transpiled. However, most standard C/C++ programs can be converted with little to no modifications.
How can I get started with Emscripten?
To get started with Emscripten, you first need to install it on your system. You can do this by downloading the precompiled SDK from the Emscripten website. Once installed, you can use the emcc command to compile your C/C++ code into JavaScript.
What is asm.js and WebAssembly?
Asm.js is a subset of JavaScript that can be executed at near-native speed. It was designed to be a low-level, efficient target for compilers like Emscripten. WebAssembly, on the other hand, is a binary format that allows you to run C/C++ at native speed in modern browsers. Both asm.js and WebAssembly are supported by Emscripten.
Can I use Emscripten with other programming languages?
Emscripten primarily supports C and C++, but it also has experimental support for other languages that can be compiled to LLVM bitcode, such as Rust and Go. However, the support for these languages is not as mature as for C and C++.
How can I debug my transpiled code?
Emscripten provides several tools for debugging transpiled code. For example, you can use the -g flag when compiling your code to include source maps, which allow you to debug your C/C++ code directly in the browser’s developer tools.
Can I use Emscripten to create web applications?
Yes, Emscripten is a great tool for creating web applications. By transpiling your C/C++ code to JavaScript, you can leverage the performance and capabilities of C/C++ in a web environment. This is particularly useful for creating performance-intensive applications, such as games or simulations.
What are the performance implications of using Emscripten?
Code transpiled with Emscripten can run at near-native speed, thanks to asm.js and WebAssembly. However, the performance can still be slightly lower than native C/C++ code, due to the overhead of the JavaScript runtime. Additionally, the transpiled code can be larger and slower to load than equivalent JavaScript code.
Can I use Emscripten in commercial projects?
Yes, Emscripten is open-source and can be used in both personal and commercial projects. However, you should be aware that the transpiled code is subject to the same licensing terms as the original C/C++ code.
Dave Voyles is a Technical Evangelist for Microsoft. He spends a lot of time writing games, writing about games, and writing about how to write games for the game dev community, Read his blog or follow him on Twitter.
Published in
·APIs·CMS & Frameworks·Meta·Miscellaneous·Patterns & Practices·PHP·Programming·Web·July 25, 2014