This post is going to look at getting your Moai app to run under NaCL, which is Google’s mechanism for allowing you to execute C++ code within Chrome. There are a number of restrictions, but fortunately Zipline have done most of the hard work for us.
Like any other platform, your code is run within a host. If you are working from the binary ( non-GitHub ) distribution, the host is already built for you and you can skip ahead until you encounter the text “STOP SKIPPING AHEAD!”. If you are working from Github sources, you need to build the host first. That is what we are going to do next.
Building the Chrome Host
First is a matter of locating it. The source for the NaCL host is located at moai-install-dir/scons/
There are a few things you are going to need to continue…
First off, if you haven’t already installed Cygwin, I highly recommend that you do. The Android build process basically requires it, so I am going to assume you already have it. If you don’t, refer to the Android installation guide Cygwin section for details.
You also need to have Python 2.6 or 2.7 installed. To check, fire up Cygwin terminal and type:
If you get an error that the command wasn’t found, Python isn’t installed so let’s install it. The easiest way is to run the Cygwin setup application, then click Next next next until you get to the Select Packages screen. In the search box enter Python, in the results expand Python and select python: Python language interpreter.
Make sure you don’t have any Cygwin Terminal windows open, then click Next and let Cygwin do it’s thing.
Now that you have Python installed, we need to download the native client SDK. (That’s the direct download link btw… )
Save it somewhere you can remember. Open the archive and extract the folder nacl_sdk. I went with c:\dev\nacl_sdk, but choose whatever you want, just be sure to update your paths accordingly.
Now open a Cygwin terminal window and change in to the nacl sdk directory, which in my case is:
Now we want to run the installer/downloader. In the terminal window type:
./naclsdk update pepper_17
Even though the current version is 22, you need to install 17, as it ships with developer tools Moai depends on. For some reason, Scons has been removed from future versions. That is what the above command does, gets and attempts to install pepper version 17.
DEALING WITH GOOGLE DEVELOPER TOOLS GOTCHA BELOW!
OK, here’s the thing, we are dealing with Google developer tools, and Google developer tools are always broken in some way, especially on Windows, naclsdk is of course no exception. After running the above command you will be greeted with the following error:
Updating bundle pepper_17 to version 17, revision 112997
Traceback (most recent call last):
File "/cygdrive/c/dev/nacl_sdk/sdk_tools/sdk_update_main.py", line 759, in <module>
File "/cygdrive/c/dev/nacl_sdk/sdk_tools/sdk_update_main.py", line 752, in main
File "/cygdrive/c/dev/nacl_sdk/sdk_tools/sdk_update_main.py", line 741, in InvokeCommand
command(options, args[1:], config)
File "/cygdrive/c/dev/nacl_sdk/sdk_tools/sdk_update_main.py", line 583, in Update
File "/cygdrive/c/dev/nacl_sdk/sdk_tools/sdk_update_main.py", line 564, in UpdateBundle
File "/cygdrive/c/dev/nacl_sdk/sdk_tools/sdk_update_common.py", line 56, in RenameDir
File "/usr/lib/python2.6/shutil.py", line 260, in move
File "/usr/lib/python2.6/shutil.py", line 95, in copy2
File "/usr/lib/python2.6/shutil.py", line 50, in copyfile
with open(src, 'rb') as fsrc:
IOError: [Errno 2] No such file or directory: u'/cygdrive/c/dev/nacl_sdk/pepper_17_update'
YAY! Don’t worry, it’s pretty easy to work around. The installer is trying to execute a program that doesn’t exist, but the installer was downloaded as part of the above process. Go in to the folder sdk_cache and locate the file naclsdk_win.exe and run it. When prompted for an install path, install it to your NACL_SDK folder/pepper_17. In my case that means C:\dev\nacl_sdk\pepper_17
Now we need to set an environment variable with the path to the NACL SDK.
setx NACL_SDK_ROOT /cygdrive/c/dev/nacl_sdk
Keep in mind, the setx command requires administrator rights, so be sure to run your cygwin terminal as administrator if you aren’t already.
Now the bummer part, exit and restart Cygwin terminal, system level environment variables don’t take immediate effect.
Are we there yet? Nope… it’s FMOD install time
Close… one more dependency left… FMOD. FMOD is a commercial audio system ( AKA, if you ship a product, you’ve got to pay to use it ). With most of Moai, you can get by using the free Untz audio system, but with NaCL, FMOD is required. So you either have to gut the FMOD library from the build dependencies or download and configure FMOD. I’ve opted for the second ( audio is after all, kind of nice! ), but either option is open to you.
Head on over to the FMOD download page and download the archive for FMOD for Google Native Client. Unfortunately you need to download a version that supports the same Chrome version as Moai (17). The following direct link will download the correct version. (Direct link) IT IS VERY IMPORTANT YOU DOWNLOAD THIS VERSION…. just so you know.
Save and extract that archive somewhere. This file is a tar.gz, so if you are using a program such as 7zip, you need to extract it, then extract the file you just extracted. I took the resulting folder, renamed it fmodchrome and copied it to c:\dev\. The resulting directory should look like:
Now we need to set yet another environment variable, one named FMOD_CHROME_SDK_ROOT and pointing at this new directory. Once again in Cygwin terminal type:
setx FMOD_CHROME_SDK_ROOT /cygdrive/c/dev/fmodchrome
Once again, you need to exit and restart Cygwin terminal for this variable to take effect.
It’s building time!
At this point in time, there seems to be a problem with the scons build script so that the paths ../3rdparty and ../src aren’t working, at least, not on Windows. The following is a brutal hack, and I will post a better solution when I come up with it. For now, we simply copy all the source into the scons folder. Copy the contents of [moaifolder]/src, [moaifolder]/3rdParty and [moaifolder]/scons/src to the scons directory.
Now cd in to the maoi scons directory, on my pc /cygdrive/c/dev/moai-dev/scons and run
Hopefully all went well. If you get errors… something didn’t go so well… if you want, just skip ahead and download the version I compiled. You only really need the build process working if you intend to alter the host.
Now copy the following files to a new folder:
This is your Moai Host ready to go.
If for some reason you couldn’t get your host to build, you can download mine.
STOP SKIPPING AHEAD!
Packaging your app to run in Chrome
Now you need to package your application up into Chrome friendly goodness. The steps are fairly straight forward
In the folder you copied the .nmf and .nexe files, create a new file called manifest.json here is what I put in mine:
Now you need an html file to actually host your application. As you probably guessed by the manifest file, I called mine moai.html:
Finally you need your Moai application ( the lua bits ). Just copy your project sources into the same directory, just be sure a file is called main.lua, this is your app entry point and will automatically be called the the host. Here for example is my folder:
I simply grabbed the sources from this tutorial.
Configure Chrome to run your app
Now you need to let Chrome know you want to enable NaCL applications. In Chromes location bar enter chrome://flags, the following window should appear.
Scroll down and enable Native Client as shown by the arrow. You need to restart Chrome for this to take effect!
So, um, restart Chrome.
Now you need to add your application. To do this, in Chrome, drop down the Menu and select Tools->Extensions.
In the resulting window, enable Developer Mode, then click Load unpacked extension…
In the browse dialog, navigate to the folder you’ve saved everything in then click OK.
Your extension should now be installed. Launch a new tab ( CTRL+N ) in Chrome, and at the bottom of the screen, select Apps
Your app icon should appear on the page:
Voila, a Moai application running in Chrome: