CS 263: Emscripten Documentation Release 1.0

Aaron Dodson

June 03, 2013

CONTENTS

1 Installing Emscripten 3 1.1 Prereqs...... 3 1.2 Getting the Source...... 4 1.3 Finalizing Installation...... 4

2 A Simple Example 5 2.1 Hello, World!...... 5 2.2 Options...... 5

3 Dealing with Files 7 3.1 Basic File Support...... 7 3.2 File System API...... 7

4 Porting pngcrush 9 4.1 What it is...... 9 4.2 JSifying pngcrush...... 9 4.3 Making make work...... 9 4.4 Bitcode to Javascript...... 9

5 PNGCrush Emscripten Demo 11 5.1 Getting the Demo...... 11 5.2 Installation and Use...... 11 5.3 Recompiling...... 11

6 PNGCrush Native Client Demo 13 6.1 Getting the Demo...... 13 6.2 Installation and Use...... 13 6.3 Compilation...... 13

7 Indices and tables 15

i ii CS 263: Emscripten Documentation, Release 1.0

Contents:

CONTENTS 1 CS 263: Emscripten Documentation, Release 1.0

2 CONTENTS CHAPTER ONE

INSTALLING EMSCRIPTEN

This document assumes that you are installing Emscripten on a fresh installation of OS X 10.8 Mountain Lion.

1.1 Prereqs

Before installing Emscripten, you will need to install and configure its dependencies.

1.1.1 Xcode Command Line Tools

Before proceeding, you should install the Xcode command line tools. These provide a base set of common utilities, and other tools. You can install the tools either through Xcode or directly from Apple’s website. To install the Command Line Tools via Xcode: • If you haven’t already, install Xcode. – Open the Finder – Navigate to /Applications – Open the App Store – Search for Xcode – Click the FREE button – Enter your Apple ID and password – When the download completes, Xcode will be in your Applications folder • Open Xcode in /Applications • Choose Xcode > Preferences... in the menu bar • Click the Downloads tab in the toolbar • If it is not already selected, click the Components tab in the Downloads section of Preferences • Click the Install button next to Command Line Tools in the table • Enter your username and password, and wait for the download to complete To install the Command Line Tools manually: • Go to https://developer.apple.com/mac, click Sign in, and enter your Apple ID username and password

3 CS 263: Emscripten Documentation, Release 1.0

– If you have set up your Apple ID as a developer account, click the Register button below the username and password field and do so first • Scroll to the bottom and click View all downloads in the Additional Downloads section • In the list of available downloads, look for and click on the most recent version of the Command Line Tools. As of this writing, that is “Command Line Tools (OS X Mountain Lion) for Xcode - April 2013” • Click the link next to the disk image icon to download them • When the download completes, open ~/Downloads and double click the .dmg to mount it • In the .dmg, run the installer

1.1.2 Homebrew

Homebrew is a for OS X that makes it much easier to install and configure the other utilities Em- scripten depends on. More information is available at http://mxcl.github.io/homebrew/. To install Homebrew, copy and paste ruby -e "$(curl -fsSL https://raw.github.com/mxcl/homebrew/go)" into Terminal and follow the script’s instructions. When it is done, run brew doctor, brew update and brew upgrade. If you already have Homebrew installed, make sure to run brew update and brew upgrade before proceeding.

1.1.3 Other Utilities

With Homebrew installed, you can now use it to install other utilities Emscripten depends on. These are based on https://gist.github.com/nathanhammond/1974955. • brew install node spidermonkey closure-compiler yuicompressor • brew install --with-

1.2 Getting the Source

At this point, you’re ready to install Emscripten. First, you’ll need to get the source. To do so, open a Terminal, cd to the directory you want Emscripten to reside at, and run git clone git://github.com/kripken/emscripten.git

1.3 Finalizing Installation

To begin, cd into the directory you cloned Emscripten into in the previous step. Then, run python emcc. This will write out a configuration file at ~/.emscripten. Open this file in your editor of choice and replace the line LLVM_ROOT = os.path.expanduser(os.getenv(’LLVM’) or ’/usr/bin’) # directory with the line LLVM_ROOT = os.path.expanduser(os.getenv(’LLVM’) or ’/usr/local/Cellar/llvm/3.2/bin’) # directory Then, run python emcc again. If everything worked, you should see a few lines ending with emcc: no input files. If you receive an error instead, consult the official Emscripten documentation at https://github.com/kripken/emscripten/wiki/Tutorial. You are now ready to use Emscripten.

4 Chapter 1. Installing Emscripten CHAPTER TWO

A SIMPLE EXAMPLE

2.1 Hello, World!

With Emscripten installed, you’re now ready to use it to compile code. To begin, try the standard Hello World program: #include

int main(int agrc, char *argv[]) { printf("Hello, world!\n"); return 0; }

Save it into a file named hello.c. To compile code into Javascript, you use the Emscripten compiler, emcc. It can take as input C or C++ code or LLVM bitcode and produce as output Javascript or Javascript embedded into an HTML page. File extensions are used by emcc to determine what input and output formats it should use for a particular invocation. To compile the above code to Javascript, run the following in a terminal: emcc hello.c -o hello.js This will produce a file named hello.js. You can run it using node.js as follows: node hello.js And will receive the output you’d expect: Hello, world! If you open hello.js and inspect it, you’ll find that it consists of several hundred lines of Javascript. Most of this is boilerplate that sets up the environment and emulates certain aspects of the system that C and C++ code expects, but you’ll also find a _main function equivalent to that of the input file.

2.2 Compiler Options

2.2.1 Optimization Flags

Since emcc mostly wraps clang, most standard compiler flags will also have their intended effect with Emscripten. During normal usage, the most important of these are likely to be the optimization flags. To improve performance, it’s advisable to invoke emcc with -O1 or -O2. Consider the following rather inefficient program:

5 CS 263: Emscripten Documentation, Release 1.0

#include int main(int argc, char *argv[]) { int found = 0; long largestTestedNumber = 100000000;

while (!found) { largestTestedNumber++; found = 1; int i; for (i = 1; i < 21; i++) { if (largestTestedNumber % i != 0) found = 0; } }

printf("The smallest number evenly divisible by all the numbers from 1 to 20 is %i\n", largestTestedNumber); return 0; }

When compiled to native code by clang at optimization level O2, this program executes on a 1.8 GHz Core i7 in 3.05 seconds. When compiled to Javascript by Emscripten at optimization level O2 and executed by node.js on the same machine, it runs in 12.05 seconds - roughly 4 times slower, but still reasonable. However, if compiled without the optimization flag, the runtime grows to 164.42 seconds - a very significant difference.

2.2.2 Library Linking Flags

Normally, when using libraries, a -llibname flag is required to cause the build product to be linked. Emscripten provides Javascript implementations of parts of several libraries, such as LibGL, OpenAL, SDL, and the C standard libraries. These do not need to be explicitly linked - if they are used, Emscripten will detect and link them without the -l flags. However, these flags are harmless if present.

6 Chapter 2. A Simple Example CHAPTER THREE

DEALING WITH FILES

Emscripten provides several options for supporting programs that need to handle file-based input and output. Part of the boilerplate wrapped around output programs is support for a basic virtualized file system and implementations of the C standard library functions for doing IO.

3.1 Basic File Support

If a program only needs to read from pre-existing data files, they can be compiled directly in to the output JavaScript. To do so, use the --preload-file flag to emcc, passing a file or directory as an argument. The file(s) will then be accessible by name from fopen and other function calls from within the program.

3.2 File System API

For more advanced file system support, Emscripten provides a JavaScript-based file system API that al- lows for the dynamic creation and deletion of files, directories and symlinks. The official documentation at https://github.com/kripken/emscripten/wiki/Filesystem-Guide provides a good overview.

3.2.1 Creating Files and Directories

Interacting with Emscripten’s file system is fairly straightforward from within a HTML page containing the generated Javascript. To add a file to the file system, place the following Javascript within