summaryrefslogtreecommitdiff
path: root/native_client_sdk
diff options
context:
space:
mode:
authorTorne (Richard Coles) <torne@google.com>2013-11-06 12:27:47 +0000
committerTorne (Richard Coles) <torne@google.com>2013-11-06 12:27:47 +0000
commit0f1bc08d4cfcc34181b0b5cbf065c40f687bf740 (patch)
tree08e3fb2fdca3674ceb4d6cf527cb65e755cd993e /native_client_sdk
parent0bdaf95291fc46702f274f40e8e5081e9ef23011 (diff)
downloadchromium_org-0f1bc08d4cfcc34181b0b5cbf065c40f687bf740.tar.gz
Merge from Chromium at DEPS revision 232870
This commit was generated by merge_to_master.py. Change-Id: I9cd2139013538e8bcd17966e8ff30ca5651d1a3d
Diffstat (limited to 'native_client_sdk')
-rw-r--r--native_client_sdk/PRESUBMIT.py1
-rw-r--r--native_client_sdk/src/README8
-rwxr-xr-xnative_client_sdk/src/build_tools/build_app.py10
-rwxr-xr-xnative_client_sdk/src/build_tools/build_projects.py9
-rwxr-xr-xnative_client_sdk/src/build_tools/build_sdk.py14
-rwxr-xr-xnative_client_sdk/src/build_tools/build_updater.py4
-rw-r--r--native_client_sdk/src/build_tools/make_simple.py4
-rw-r--r--native_client_sdk/src/build_tools/sdk_tools/third_party/fancy_urllib/README.chromium (renamed from native_client_sdk/src/build_tools/sdk_tools/third_party/fancy_urllib/README)7
-rwxr-xr-xnative_client_sdk/src/build_tools/test_sdk.py9
-rw-r--r--native_client_sdk/src/doc/Makefile3
-rw-r--r--native_client_sdk/src/doc/README14
-rw-r--r--native_client_sdk/src/doc/_book.yaml17
-rw-r--r--native_client_sdk/src/doc/_sphinxext/devsite_builder.py50
-rw-r--r--native_client_sdk/src/doc/community/_toc.yaml14
-rw-r--r--native_client_sdk/src/doc/community/index.rst6
-rw-r--r--native_client_sdk/src/doc/community/security-contest/contest-announcement.rst8
-rw-r--r--native_client_sdk/src/doc/devguide/_toc.yaml10
-rw-r--r--native_client_sdk/src/doc/devguide/coding/3D-graphics.rst25
-rw-r--r--native_client_sdk/src/doc/devguide/coding/FileIO.rst11
-rw-r--r--native_client_sdk/src/doc/devguide/coding/_toc.yaml24
-rw-r--r--native_client_sdk/src/doc/devguide/coding/application-structure.rst1
-rw-r--r--native_client_sdk/src/doc/devguide/coding/file-io.rst556
-rw-r--r--native_client_sdk/src/doc/devguide/coding/nacl_io.rst4
-rw-r--r--native_client_sdk/src/doc/devguide/devcycle/_toc.yaml14
-rw-r--r--native_client_sdk/src/doc/devguide/devcycle/building.rst25
-rw-r--r--native_client_sdk/src/doc/devguide/devcycle/debugging.rst6
-rw-r--r--native_client_sdk/src/doc/devguide/devcycle/dynamic-loading.rst365
-rw-r--r--native_client_sdk/src/doc/devguide/devcycle/running.rst2
-rw-r--r--native_client_sdk/src/doc/devguide/devcycle/vs-addin.rst593
-rw-r--r--native_client_sdk/src/doc/faq.rst59
-rw-r--r--native_client_sdk/src/doc/help.rst10
-rw-r--r--native_client_sdk/src/doc/images/fileioexample.pngbin18784 -> 18953 bytes
-rw-r--r--native_client_sdk/src/doc/index.rst4
-rw-r--r--native_client_sdk/src/doc/overview.rst2
-rw-r--r--native_client_sdk/src/doc/rest-devsite-examples.rst16
-rw-r--r--native_client_sdk/src/doc/sdk/_toc.yaml10
-rw-r--r--native_client_sdk/src/doc/sdk/examples.rst26
-rw-r--r--native_client_sdk/src/doc/sdk/release-notes.rst18
-rw-r--r--native_client_sdk/src/examples/tutorial/dlopen/dlopen.cc47
-rw-r--r--native_client_sdk/src/examples/tutorial/dlopen/example.js4
-rw-r--r--native_client_sdk/src/getting_started/part1/index.html4
-rw-r--r--native_client_sdk/src/gonacl_appengine/README23
-rw-r--r--native_client_sdk/src/gonacl_appengine/src/Makefile39
-rwxr-xr-xnative_client_sdk/src/gonacl_appengine/src/bullet/build.sh2
-rw-r--r--native_client_sdk/src/gonacl_appengine/src/cube/Makefile33
-rw-r--r--native_client_sdk/src/gonacl_appengine/src/cube/cube.cc510
-rw-r--r--native_client_sdk/src/gonacl_appengine/src/cube/matrix.cc139
-rw-r--r--native_client_sdk/src/gonacl_appengine/src/cube/matrix.h43
-rw-r--r--native_client_sdk/src/gonacl_appengine/src/cube/texture.cc64
-rwxr-xr-xnative_client_sdk/src/gonacl_appengine/src/lua/build.sh2
-rwxr-xr-xnative_client_sdk/src/gonacl_appengine/src/smoothlife/build.sh83
-rw-r--r--native_client_sdk/src/gonacl_appengine/static/pnacl-demo-bullet/scene.js15
-rw-r--r--native_client_sdk/src/gonacl_appengine/static/pnacl-demo-cube/example.js262
-rw-r--r--native_client_sdk/src/gonacl_appengine/static/pnacl-demo-cube/index.html66
-rw-r--r--native_client_sdk/src/gonacl_appengine/static/pnacl-demo-lua/lua.js2
-rw-r--r--native_client_sdk/src/gonacl_appengine/static/pnacl-demo-lua/naclterm.js69
-rw-r--r--native_client_sdk/src/gonacl_appengine/static/pnacl-demo-smoothlife/example.js291
-rw-r--r--native_client_sdk/src/gonacl_appengine/static/pnacl-demo-smoothlife/index.html74
-rw-r--r--native_client_sdk/src/libraries/nacl_io/nacl_io.h2
-rw-r--r--native_client_sdk/src/libraries/ppapi_cpp/library.dsc2
-rw-r--r--native_client_sdk/src/libraries/third_party/newlib-extras/README.chromium2
-rwxr-xr-xnative_client_sdk/src/tools/compiler-wrapper.py2
-rwxr-xr-xnative_client_sdk/src/tools/create_html.py12
-rwxr-xr-xnative_client_sdk/src/tools/create_nmf.py20
-rw-r--r--native_client_sdk/src/tools/host_gcc.mk2
-rwxr-xr-xnative_client_sdk/src/tools/httpd.py10
-rw-r--r--native_client_sdk/src/tools/nacl_gcc.mk8
-rw-r--r--native_client_sdk/src/tools/nacl_llvm.mk2
-rwxr-xr-xnative_client_sdk/src/tools/sel_ldr.py13
69 files changed, 3217 insertions, 589 deletions
diff --git a/native_client_sdk/PRESUBMIT.py b/native_client_sdk/PRESUBMIT.py
index 93e7ad710e..d219be389a 100644
--- a/native_client_sdk/PRESUBMIT.py
+++ b/native_client_sdk/PRESUBMIT.py
@@ -22,6 +22,7 @@ def CommonChecks(input_api, output_api):
r'src[\\\/]build_tools[\\\/]tests[\\\/].*',
r'src[\\\/]build_tools[\\\/]sdk_tools[\\\/]third_party[\\\/].*',
r'src[\\\/]doc[\\\/]*',
+ r'src[\\\/]gonacl_appengine[\\\/]*',
]
canned = input_api.canned_checks
output.extend(canned.RunPylint(input_api, output_api, black_list=black_list,
diff --git a/native_client_sdk/src/README b/native_client_sdk/src/README
index 82503b9a83..c44f214f27 100644
--- a/native_client_sdk/src/README
+++ b/native_client_sdk/src/README
@@ -9,17 +9,17 @@ Build Date: ${DATE}
Please refer to the online documentation here:
- http://code.google.com/chrome/nativeclient
+ https://developers.google.com/native-client
-OTHER DEVELOPMENT
------------------
+Contributing
+------------
If you want to contribute to the Native Client SDK itself, please read the
online documentation on contributing code to Chromium here:
http://www.chromium.org/developers/contributing-code
-KNOWN ISSUES
+Known Issues
------------
Please refer to the online documentation here:
diff --git a/native_client_sdk/src/build_tools/build_app.py b/native_client_sdk/src/build_tools/build_app.py
index 577fd97ba5..0588aaa1b8 100755
--- a/native_client_sdk/src/build_tools/build_app.py
+++ b/native_client_sdk/src/build_tools/build_app.py
@@ -80,6 +80,16 @@ def main(args):
parser = optparse.OptionParser()
parser.add_option('-c', '--channel',
help='Channel to display in the name of the package.')
+
+ # To setup bash completion for this command first install optcomplete
+ # and then add this line to your .bashrc:
+ # complete -F _optcomplete build_app.py
+ try:
+ import optcomplete
+ optcomplete.autocomplete(parser)
+ except ImportError:
+ pass
+
options, args = parser.parse_args(args[1:])
if options.channel:
diff --git a/native_client_sdk/src/build_tools/build_projects.py b/native_client_sdk/src/build_tools/build_projects.py
index 264f47da67..7f8daa9eff 100755
--- a/native_client_sdk/src/build_tools/build_projects.py
+++ b/native_client_sdk/src/build_tools/build_projects.py
@@ -221,6 +221,15 @@ def main(argv):
action='append')
parser.add_option('-v', '--verbose', action='store_true')
+ # To setup bash completion for this command first install optcomplete
+ # and then add this line to your .bashrc:
+ # complete -F _optcomplete build_projects.py
+ try:
+ import optcomplete
+ optcomplete.autocomplete(parser)
+ except ImportError:
+ pass
+
options, args = parser.parse_args(argv[1:])
if options.project:
parser.error('The -p/--project option is deprecated.\n'
diff --git a/native_client_sdk/src/build_tools/build_sdk.py b/native_client_sdk/src/build_tools/build_sdk.py
index 49d1cbe309..9c716d0ef7 100755
--- a/native_client_sdk/src/build_tools/build_sdk.py
+++ b/native_client_sdk/src/build_tools/build_sdk.py
@@ -54,7 +54,7 @@ import oshelpers
CYGTAR = os.path.join(NACL_DIR, 'build', 'cygtar.py')
NACLPORTS_URL = 'https://naclports.googlecode.com/svn/trunk/src'
-NACLPORTS_REV = 850
+NACLPORTS_REV = 954
GYPBUILD_DIR = 'gypbuild'
@@ -820,10 +820,10 @@ def BuildStepBuildNaClPorts(pepper_ver, pepperdir):
"""Build selected naclports in all configurations."""
# TODO(sbc): currently naclports doesn't know anything about
# Debug builds so the Debug subfolders are all empty.
- bundle_dir = os.path.join(NACLPORTS_DIR, 'out', 'sdk_bundle')
env = dict(os.environ)
env['NACL_SDK_ROOT'] = pepperdir
+ env['PEPPER_DIR'] = os.path.dirname(pepperdir)
env['NACLPORTS_NO_ANNOTATE'] = "1"
env['NACLPORTS_NO_UPLOAD'] = "1"
@@ -831,6 +831,7 @@ def BuildStepBuildNaClPorts(pepper_ver, pepperdir):
buildbot_common.BuildStep('Build naclports')
buildbot_common.Run([build_script], env=env, cwd=NACLPORTS_DIR)
+ bundle_dir = os.path.join(NACLPORTS_DIR, 'out', 'sdk_bundle')
out_dir = os.path.join(bundle_dir, 'pepper_%s' % pepper_ver)
# Some naclports do not include a standalone LICENSE/COPYING file
@@ -890,6 +891,15 @@ def main(args):
parser.add_option('--mac-sdk',
help='Set the mac-sdk (e.g. 10.6) to use when building with ninja.')
+ # To setup bash completion for this command first install optcomplete
+ # and then add this line to your .bashrc:
+ # complete -F _optcomplete build_sdk.py
+ try:
+ import optcomplete
+ optcomplete.autocomplete(parser)
+ except ImportError:
+ pass
+
global options
options, args = parser.parse_args(args[1:])
diff --git a/native_client_sdk/src/build_tools/build_updater.py b/native_client_sdk/src/build_tools/build_updater.py
index c132385dbf..2987e6477b 100755
--- a/native_client_sdk/src/build_tools/build_updater.py
+++ b/native_client_sdk/src/build_tools/build_updater.py
@@ -44,8 +44,8 @@ UPDATER_FILES = [
('build_tools/sdk_tools/third_party/*.py', 'nacl_sdk/sdk_tools/third_party/'),
('build_tools/sdk_tools/third_party/fancy_urllib/*.py',
'nacl_sdk/sdk_tools/third_party/fancy_urllib/'),
- ('build_tools/sdk_tools/third_party/fancy_urllib/README',
- 'nacl_sdk/sdk_tools/third_party/fancy_urllib/README'),
+ ('build_tools/sdk_tools/third_party/fancy_urllib/README.chromium',
+ 'nacl_sdk/sdk_tools/third_party/fancy_urllib/README.chromium'),
('build_tools/manifest_util.py', 'nacl_sdk/sdk_tools/manifest_util.py'),
('LICENSE', 'nacl_sdk/sdk_tools/LICENSE'),
(CYGTAR, 'nacl_sdk/sdk_tools/cygtar.py'),
diff --git a/native_client_sdk/src/build_tools/make_simple.py b/native_client_sdk/src/build_tools/make_simple.py
index fecf480911..90f8d33b16 100644
--- a/native_client_sdk/src/build_tools/make_simple.py
+++ b/native_client_sdk/src/build_tools/make_simple.py
@@ -1,10 +1,10 @@
-# Copyright (c) 2012 Google Inc. All rights reserved.
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""This is a simplified Makefile generator for single-target gyp files.
It was originally designed for generating readable Makefiles for the
-the NaCL examples.
+the NaCl examples.
"""
# pylint: disable=C0301
diff --git a/native_client_sdk/src/build_tools/sdk_tools/third_party/fancy_urllib/README b/native_client_sdk/src/build_tools/sdk_tools/third_party/fancy_urllib/README.chromium
index 91da20ec7d..5c4d0efc10 100644
--- a/native_client_sdk/src/build_tools/sdk_tools/third_party/fancy_urllib/README
+++ b/native_client_sdk/src/build_tools/sdk_tools/third_party/fancy_urllib/README.chromium
@@ -1,8 +1,13 @@
+Name: fancy_urllib
+URL: http://googleappengine.googlecode.com/svn/trunk/python/lib/fancy_urllib
+License: Apache
+License File: README.chromium
+Security Critical: no
+
The fancy_urllib library was obtained from
http://googleappengine.googlecode.com/svn/trunk/python/lib/fancy_urllib/fancy_urllib/__init__.py
under the following license (http://googleappengine.googlecode.com/svn/trunk/python/LICENSE):
-
GOOGLE APP ENGINE SDK
=====================
Copyright 2008 Google Inc.
diff --git a/native_client_sdk/src/build_tools/test_sdk.py b/native_client_sdk/src/build_tools/test_sdk.py
index cf5db614b5..21bd968720 100755
--- a/native_client_sdk/src/build_tools/test_sdk.py
+++ b/native_client_sdk/src/build_tools/test_sdk.py
@@ -131,6 +131,15 @@ def main(args):
# of the build.
del os.environ['NACL_SDK_ROOT']
+ # To setup bash completion for this command first install optcomplete
+ # and then add this line to your .bashrc:
+ # complete -F _optcomplete test_sdk.py
+ try:
+ import optcomplete
+ optcomplete.autocomplete(parser)
+ except ImportError:
+ pass
+
options, args = parser.parse_args(args[1:])
pepper_ver = str(int(build_version.ChromeMajorVersion()))
diff --git a/native_client_sdk/src/doc/Makefile b/native_client_sdk/src/doc/Makefile
index d9faadf1d4..89c5145842 100644
--- a/native_client_sdk/src/doc/Makefile
+++ b/native_client_sdk/src/doc/Makefile
@@ -183,7 +183,7 @@ pseudoxml:
devsite-prod:
$(SPHINXBUILD) -b devsite -D devsite_production_mode=1 $(ALLSPHINXOPTS) $(BUILDDIR)/devsite-prod
- rm -rf $(BUILDDIR)/devsite-staging/images
+ rm -rf $(BUILDDIR)/devsite-prod/images
cp -r $(BUILDDIR)/devsite-prod/_images $(BUILDDIR)/devsite-prod/images
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/devsite-prod."
@@ -192,6 +192,7 @@ devsite-staging:
$(SPHINXBUILD) -b devsite -D devsite_foldername=$(USER) -D devsite_production_mode=1 $(ALLSPHINXOPTS) $(BUILDDIR)/devsite-staging
rm -rf $(BUILDDIR)/devsite-staging/images
cp -r $(BUILDDIR)/devsite-staging/_images $(BUILDDIR)/devsite-staging/images
+ cp _reference_toc.yaml $(BUILDDIR)/devsite-staging/
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/devsite-staging."
diff --git a/native_client_sdk/src/doc/README b/native_client_sdk/src/doc/README
index 2d9bf86dc9..da6e2f56c0 100644
--- a/native_client_sdk/src/doc/README
+++ b/native_client_sdk/src/doc/README
@@ -40,10 +40,13 @@ To emit docs suitable for pushing to production use::
make devsite-prod
-Production mode contains devsite-specific templating and non-HTML constructs.
-The ``devsite-staging`` target is exactly the same except that the html pages
-are all rooted under a folder called $USER, which allows each user to stage his
-own copy of the docs.
+Note that "production use" (and the staging target) are closely tied to the
+Google documentation infrastructure, so it will be of very limited use outside
+Google. Links to related documents here can be google.com specific. Production
+mode contains devsite-specific templating and non-HTML constructs. The
+``devsite-staging`` target is exactly the same except that the html pages are
+all rooted under a folder called $USER, which allows each user to stage his own
+copy of the docs.
When building in production mode you can specify the name of the subfolder in
which the docs are rooted by specifying ``SPHINXOPTS=-Ddevsite_foldername=``.
@@ -51,6 +54,9 @@ For example::
make devsite-prod SPHINXOPTS=-Ddevsite_foldername=pepper_32
+See https://sites.google.com/a/google.com/nativeclient/documents/how-to-update-developer-documentation#TOC-Staging-ReStructuredText-output-on-devsite
+for more information on staging.
+
Local HTTP server to view the docs
----------------------------------
diff --git a/native_client_sdk/src/doc/_book.yaml b/native_client_sdk/src/doc/_book.yaml
index 32dd6aaccf..caf3f0abfb 100644
--- a/native_client_sdk/src/doc/_book.yaml
+++ b/native_client_sdk/src/doc/_book.yaml
@@ -1,17 +1,6 @@
toc:
- title: "Version ${version} (${folder})"
- path: /native-client/${folder}/version
+ path: /native-client/${folder}version
- title: "News & Announcements"
- path: /native-client/${folder}/announcements
-- title: "Technical Overview"
- path: /native-client/${folder}/overview
-- title: "Quick-start"
- path: /native-client/${folder}/quick-start
-- include: /native-client/${folder}/sdk/_toc.yaml
-- include: /native-client/${folder}/devguide/_toc.yaml
-- include: /native-client/${folder}/_reference_toc.yaml
-- include: /native-client/${folder}/community/_toc.yaml
-- title: "FAQ"
- path: /native-client/${folder}/faq
-- title: "Get Help with NaCl"
- path: /native-client/${folder}/help
+ path: /native-client/${folder}announcements
+- include: /native-client/${folder}_reference_toc.yaml
diff --git a/native_client_sdk/src/doc/_sphinxext/devsite_builder.py b/native_client_sdk/src/doc/_sphinxext/devsite_builder.py
index dbb288cd4c..192534e0e2 100644
--- a/native_client_sdk/src/doc/_sphinxext/devsite_builder.py
+++ b/native_client_sdk/src/doc/_sphinxext/devsite_builder.py
@@ -6,7 +6,9 @@
# This is a Sphinx extension.
#
+from __future__ import print_function
import codecs
+from collections import namedtuple, OrderedDict
import os
import string
from docutils import nodes
@@ -46,7 +48,7 @@ ${doc_body}
'''.lstrip())
DEVSITE_PREFIX = r'''
-{% setvar pepperversion %}pepper''' + PEPPER_VERSION + ''' {% endsetvar %}
+{% setvar pepperversion %}pepper''' + PEPPER_VERSION + '''{% endsetvar %}
{% include "native-client/_local_variables.html" %}'''
DEVSITE_BUTTERBAR = '{{butterbar}}'
@@ -58,6 +60,9 @@ NONPROD_CSS = '<link href="/_static/css/local_extensions.css"'\
'rel="stylesheet" type="text/css"/>'
NONPROD_META_HEAD = '<meta charset="utf-8" />'
+# Path to the top-level YAML table-of-contents file for the devsite
+BOOK_TOC_TEMPLATE = '_book_template.yaml'
+
class DevsiteHTMLTranslator(HTMLTranslator):
""" Custom HTML translator for devsite output.
@@ -237,8 +242,8 @@ class DevsiteBuilder(StandaloneHTMLBuilder):
def init(self):
self.devsite_production_mode = int(self.config.devsite_production_mode) == 1
self.kill_internal_links = int(self.config.kill_internal_links) == 1
- print "----> Devsite builder with production mode = %d" % (
- self.devsite_production_mode,)
+ self.info("----> Devsite builder with production mode = %d" % (
+ self.devsite_production_mode,))
self.config_hash = ''
self.tags_hash = ''
self.theme = None # no theme necessary
@@ -248,36 +253,18 @@ class DevsiteBuilder(StandaloneHTMLBuilder):
def finish(self):
super(DevsiteBuilder, self).finish()
-
if self.devsite_production_mode:
- self.info(bold('generating yaml files... '), nonl=True)
-
- substitutions = {
+ # We decided to keep the manual _book.yaml for now;
+ # The code for auto-generating YAML TOCs from index.rst was removed in
+ # https://codereview.chromium.org/57923006/
+ self.info(bold('generating YAML table-of-contents... '))
+ subs = {
'version': PEPPER_VERSION,
- 'folder': self.config.devsite_foldername
- }
-
- olddir = os.getcwd()
- try:
- os.chdir(self.env.srcdir)
- for root, dirs, files in os.walk('.'):
- root = os.path.normpath(root)
- if root.startswith("_"):
- continue
- for filename in files:
- if os.path.splitext(filename)[1] != ".yaml":
- continue
- filename = os.path.join(root, filename)
- outfile = os.path.join(self.outdir, filename)
- with open(filename) as f:
- template = string.Template(f.read())
-
- with open(outfile, 'w') as f:
- f.write(template.substitute(substitutions))
- finally:
- os.chdir(olddir)
-
- self.info()
+ 'folder': self.config.devsite_foldername or ''}
+ with open(os.path.join(self.env.srcdir, '_book.yaml')) as in_f:
+ with open(os.path.join(self.outdir, '_book.yaml'), 'w') as out_f:
+ out_f.write(string.Template(in_f.read()).substitute(subs))
+ self.info()
def dump_inventory(self):
# We don't want an inventory file when building for devsite
@@ -366,7 +353,6 @@ class NaclCodeDirective(Directive):
literal['prettyprint'] = self.options.get('prettyprint', 1)
return [literal]
-
def setup(app):
""" Extension registration hook.
"""
diff --git a/native_client_sdk/src/doc/community/_toc.yaml b/native_client_sdk/src/doc/community/_toc.yaml
deleted file mode 100644
index ba8a936f0c..0000000000
--- a/native_client_sdk/src/doc/community/_toc.yaml
+++ /dev/null
@@ -1,14 +0,0 @@
-toc:
-- title: "Community"
- path: /native-client/${folder}/community
- section:
- - title: "Middleware & Software Support"
- path: /native-client/${folder}/community/middleware
- - title: "Application Gallery"
- path: /native-client/${folder}/community/application-gallery
- - title: "Developers Speak: Porting to Native Client"
- path: /native-client/${folder}/community/developers
- - title: "Talks, Demos, and Publications"
- path: /native-client/${folder}/community/talks
- - title: "Security Contest Archive"
- path: /native-client/${folder}/community/security-contest/
diff --git a/native_client_sdk/src/doc/community/index.rst b/native_client_sdk/src/doc/community/index.rst
index 50306bccff..7cd1d00686 100644
--- a/native_client_sdk/src/doc/community/index.rst
+++ b/native_client_sdk/src/doc/community/index.rst
@@ -6,8 +6,10 @@ Community
This section contains pages related to the Native Client *community* - both
**implementors** (contributors to the `open-source Native Client project
-<https://code.google.com/p/nativeclient/>`_) and **developers**, who use
-Native Client to develop web applications.
+<nacl_project_>`_) and **developers**, who use Native Client to develop web
+applications.
For a list of active forums where you can ask questions, check the
:ref:`help page <help>`.
+
+.. _nacl_project: https://code.google.com/p/nativeclient/
diff --git a/native_client_sdk/src/doc/community/security-contest/contest-announcement.rst b/native_client_sdk/src/doc/community/security-contest/contest-announcement.rst
index 9c7443a339..9b0ce1cd86 100644
--- a/native_client_sdk/src/doc/community/security-contest/contest-announcement.rst
+++ b/native_client_sdk/src/doc/community/security-contest/contest-announcement.rst
@@ -33,10 +33,10 @@ To participate, you will need to:
yourself (or your team)
* `Download <http://code.google.com/p/nativeclient/wiki/Downloads?tm=2>`_
our latest build
-* `Join <http://groups.google.com/group/native-client-discuss>`_
- the Native Client discussion group
-* `Report <http://code.google.com/p/nativeclient/issues/list>`_
- the exploits you find to our team
+* `Join <https://groups.google.com/group/native-client-discuss>`_ the Native
+ Client discussion group
+* `Report <https://code.google.com/p/nativeclient/issues>`_ the exploits you
+ find to our team
When
====
diff --git a/native_client_sdk/src/doc/devguide/_toc.yaml b/native_client_sdk/src/doc/devguide/_toc.yaml
deleted file mode 100644
index 87b98ffb96..0000000000
--- a/native_client_sdk/src/doc/devguide/_toc.yaml
+++ /dev/null
@@ -1,10 +0,0 @@
-toc:
-- title: "Developer's Guide"
- path: /native-client/${folder}/devguide
- section:
- - title: "Getting Started Tutorial"
- path: /native-client/${folder}/devguide/tutorial
- - include: /native-client/${folder}/devguide/devcycle/_toc.yaml
- - include: /native-client/${folder}/devguide/coding/_toc.yaml
- - title: "Distributing Your Application"
- path: /native-client/${folder}/devguide/distributing
diff --git a/native_client_sdk/src/doc/devguide/coding/3D-graphics.rst b/native_client_sdk/src/doc/devguide/coding/3D-graphics.rst
index 7ca1513eab..613d17ad0c 100644
--- a/native_client_sdk/src/doc/devguide/coding/3D-graphics.rst
+++ b/native_client_sdk/src/doc/devguide/coding/3D-graphics.rst
@@ -70,8 +70,8 @@ Check for extensions and capabilities
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Not every GPU supports every extension or has the same amount of texture units,
-vertex attributes, etc. On startup, call ``glGetString(GLEXTENSIONS)`` and check
-for the extensions and the features you need. For example:
+vertex attributes, etc. On startup, call ``glGetString(GL_EXTENSIONS)`` and
+check for the extensions and the features you need. For example:
* If you are using non power-of-2 texture with mipmaps, make sure
``GL_OES_texture_npot`` exists.
@@ -84,6 +84,27 @@ for the extensions and the features you need. For example:
``GL_CHROMIUM_texture_compression_dxt3``, and
``GL_CHROMIUM_texture_compression_dxt5`` exist.
+* If you are using the functions ``glDrawArraysInstancedANGLE``,
+ ``glDrawElementsInstancedANGLE``, ``glVertexAttribDivisorANGLE``, or the PPAPI
+ interface ``PPB_OpenGLES2InstancedArrays``, make sure the corresponding
+ extension ``GL_ANGLE_instanced_arrays`` exists.
+
+* If you are using the function ``glRenderbufferStorageMultisampleEXT``, or the
+ PPAPI interface ``PPB_OpenGLES2FramebufferMultisample``, make sure the
+ corresponding extension ``GL_CHROMIUM_framebuffer_multisample`` exists.
+
+* If you are using the functions ``glGenQueriesEXT``, ``glDeleteQueriesEXT``,
+ ``glIsQueryEXT``, ``glBeginQueryEXT``, ``glEndQueryEXT``, ``glGetQueryivEXT``,
+ ``glGetQueryObjectuivEXT``, or the PPAPI interface ``PPB_OpenGLES2Query``,
+ make sure the corresponding extension ``GL_EXT_occlusion_query_boolean``
+ exists.
+
+* If you are using the functions ``glMapBufferSubDataCHROMIUM``,
+ ``glUnmapBufferSubDataCHROMIUM``, ``glMapTexSubImage2DCHROMIUM``,
+ ``glUnmapTexSubImage2DCHROMIUM``, or the PPAPI interface
+ ``PPB_OpenGLES2ChromiumMapSub``, make sure the corresponding extension
+ ``GL_CHROMIUM_map_sub`` exists.
+
Check for system capabilites with ``glGetIntegerv`` and adjust shader programs
as well as texture and vertex data accordingly:
diff --git a/native_client_sdk/src/doc/devguide/coding/FileIO.rst b/native_client_sdk/src/doc/devguide/coding/FileIO.rst
deleted file mode 100644
index 6e3a4a5f20..0000000000
--- a/native_client_sdk/src/doc/devguide/coding/FileIO.rst
+++ /dev/null
@@ -1,11 +0,0 @@
-.. _devguide-coding-fileio:
-
-########
-File I/O
-########
-
-foo
-
-.. _quota_management:
-
-.. _enabling_file_access:
diff --git a/native_client_sdk/src/doc/devguide/coding/_toc.yaml b/native_client_sdk/src/doc/devguide/coding/_toc.yaml
deleted file mode 100644
index 7c35926fba..0000000000
--- a/native_client_sdk/src/doc/devguide/coding/_toc.yaml
+++ /dev/null
@@ -1,24 +0,0 @@
-toc:
- - title: "Coding Your Application"
- path: /native-client/dev/devguide/coding
- section:
- - title: "Application Structure"
- path: /native-client/dev/devguide/coding/application-structure
- - title: "Native Client Modules"
- path: /native-client/dev/devguide/coding/nacl-modules
- - title: "Memory Management"
- path: /native-client/dev/devguide/coding/memory
- - title: "Progress Events"
- path: /native-client/dev/devguide/coding/progress-events
- - title: "Messaging System"
- path: /native-client/dev/devguide/coding/message-system
- - title: "View Change, Focus, and Input Events"
- path: /native-client/dev/devguide/coding/input-events
- - title: "URL Loading"
- path: /native-client/dev/devguide/coding/URLLoading
- - title: "File IO"
- path: /native-client/dev/devguide/coding/FileIO
- - title: "Audio"
- path: /native-client/dev/devguide/coding/audio
- - title: "3D Graphics"
- path: /native-client/dev/devguide/coding/3D-graphics
diff --git a/native_client_sdk/src/doc/devguide/coding/application-structure.rst b/native_client_sdk/src/doc/devguide/coding/application-structure.rst
index de613721a8..5b673d52ec 100644
--- a/native_client_sdk/src/doc/devguide/coding/application-structure.rst
+++ b/native_client_sdk/src/doc/devguide/coding/application-structure.rst
@@ -43,6 +43,7 @@ Applications that are published in the `Chrome Web Store
also include a Chrome
Web Store manifest file ``(manifest.json)`` and one or more icon files.
+.. _html_file:
HTML file and the <embed> element
=================================
diff --git a/native_client_sdk/src/doc/devguide/coding/file-io.rst b/native_client_sdk/src/doc/devguide/coding/file-io.rst
new file mode 100644
index 0000000000..fd2a38c657
--- /dev/null
+++ b/native_client_sdk/src/doc/devguide/coding/file-io.rst
@@ -0,0 +1,556 @@
+.. _devguide-coding-fileio:
+
+########
+File I/O
+########
+
+.. contents::
+ :local:
+ :backlinks: none
+ :depth: 2
+
+Introduction
+============
+
+This chapter describes how to use the `FileIO API
+<https://developers.google.com/native-client/peppercpp/classpp_1_1_file_i_o>`_
+to read and write files using a local secure data store.
+
+You might use the File IO API with the URL Loading APIs to create an overall
+data download and caching solution for your NaCl applications. For example:
+
+#. Use the File IO APIs to check the local disk to see if a file exists that
+ your program needs.
+#. If the file exists locally, load it into memory using the File IO API. If
+ the file doesn't exist locally, use the URL Loading API to retrieve the
+ file from the server.
+#. Use the File IO API to write the file to disk.
+#. Load the file into memory using the File IO API when needed by your
+ application.
+
+The example discussed in this chapter is included in the SDK in the directory
+``examples/api/file_io``.
+
+Reference information
+=====================
+
+For reference information related to FileIO, see the following documentation:
+
+* `file_io.h
+ <https://developers.google.com/native-client/peppercpp/file__io_8h>`_ - API
+ to create a FileIO object
+* `file_ref.h
+ <https://developers.google.com/native-client/peppercpp/file__ref_8h>`_ - API
+ to create a file reference or "weak pointer" to a file in a file system
+* `file_system.h
+ <https://developers.google.com/native-client/peppercpp/file__system_8h>`_ -
+ API to create a file system associated with a file
+
+Local file I/O
+==============
+
+Chrome provides an obfuscated, restricted area on disk to which a web app can
+safely `read and write files
+<https://developers.google.com/chrome/whitepapers/storage#persistent>`_. The
+Pepper FileIO, FileRef, and FileSystem APIs (collectively called the File IO
+APIs) allow you to access this sandboxed local disk so you can read and write
+files and manage caching yourself. The data is persistent between launches of
+Chrome, and is not removed unless your application deletes it or the user
+manually deletes it. There is no limit to the amount of local data you can
+use, other than the actual space available on the local drive.
+
+.. _quota_management:
+.. _enabling_file_access:
+
+Enabling local file I/O
+-----------------------
+
+The easiest way to enable the writing of persistent local data is to include
+the `unlimitedStorage permission
+<http://developer.chrome.com/extensions/declare_permissions.html#unlimitedStorage>`_
+in your Chrome Web Store manifest file. With this permission you can use the
+Pepper FileIO API without the need to request disk space at run time. When
+the user installs the app Chrome displays a message announcing that the app
+writes to the local disk.
+
+If you do not use the ``unlimitedStorage`` permission you must include
+JavaScript code that calls the `HTML5 Quota Management API
+<http://updates.html5rocks.com/2011/11/Quota-Management-API-Fast-Facts>`_ to
+explicitly request local disk space before using the FileIO API. In this case
+Chrome will prompt the user to accept a requestQuota call every time one is
+made.
+
+Testing local file I/O
+----------------------
+
+You should be aware that using the ``unlimitedStorage`` manifest permission
+constrains the way you can test your app. Three of the four techniques
+described in :doc:`Running Native Client Applications <../devcycle/running>`
+read the Chrome Web Store manifest file and enable the ``unlimitedStorage``
+permission when it appears, but the first technique (local server) does not.
+If you want to test the file IO portion of your app with a simple local server,
+you need to include JavaScript code that calls the HTML5 Quota Management API.
+When you deliver your application you can replace this code with the
+``unlimitedStorage`` manifest permission.
+
+The ``file_io`` example
+=======================
+
+The Native Client SDK includes an example, ``file_io``, that demonstrates how
+to read and write a local disk file. Since you will probably run the example
+from a local server without a Chrome Web Store manifest file, the example's
+index file uses JavaScript to perform the Quota Management setup as described
+above. The example has these primary files:
+
+* ``index.html`` - The HTML code that launches the Native Client module and
+ displays the user interface.
+* ``example.js`` - JavaScript code that requests quota (as described above). It
+ also listens for user interaction with the user interface, and forwards the
+ requests to the Native Client module.
+* ``file_io.cc`` - The code that sets up and provides an entry point to the
+ Native Client module.
+
+The remainder of this section covers the code in the ``file_io.cc`` file for
+reading and writing files.
+
+File I/O overview
+-----------------
+
+Like many Pepper APIs, the File IO API includes a set of methods that execute
+asynchronously and that invoke callback functions in your Native Client module.
+Unlike most other examples, the ``file_io`` example also demonstrates how to
+make Pepper calls synchronously on a worker thread.
+
+It is illegal to make blocking calls to Pepper on the module's main thread.
+This restriction is lifted when running on a worker thread---this is called
+"calling Pepper off the main thread". This often simplifies the logic of your
+code; multiple asynchronous Pepper functions can be called from one function on
+your worker thread, so you can use the stack and standard control flow
+structures normally.
+
+The high-level flow for the ``file_io`` example is described below. Note that
+methods in the namespace ``pp`` are part of the Pepper C++ API.
+
+Creating and writing a file
+---------------------------
+
+Following are the high-level steps involved in creating and writing to a
+file:
+
+#. ``pp::FileIO::Open`` is called with the ``PP_FILEOPEN_FLAG_CREATE`` flag to
+ create a file. Because the callback function is ``pp::BlockUntilComplete``,
+ this thread is blocked until ``Open`` succeeds or fails.
+#. ``pp::FileIO::Write`` is called to write the contents. Again, the thread is
+ blocked until the call to ``Write`` completes. If there is more data to
+ write, ``Write`` is called again.
+#. When there is no more data to write, call ``pp::FileIO::Flush``.
+
+Opening and reading a file
+--------------------------
+
+Following are the high-level steps involved in opening and reading a file:
+
+#. ``pp::FileIO::Open`` is called to open the file. Because the callback
+ function is ``pp::BlockUntilComplete``, this thread is blocked until Open
+ succeeds or fails.
+#. ``pp::FileIO::Query`` is called to query information about the file, such as
+ its file size. The thread is blocked until ``Query`` completes.
+#. ``pp::FileIO::Read`` is called to read the contents. The thread is blocked
+ until ``Read`` completes. If there is more data to read, ``Read`` is called
+ again.
+
+Deleting a file
+---------------
+
+Deleting a file is straightforward: call ``pp::FileRef::Delete``. The thread is
+blocked until ``Delete`` completes.
+
+Making a directory
+------------------
+
+Making a directory is also straightforward: call ``pp::File::MakeDirectory``.
+The thread is blocked until ``MakeDirectory`` completes.
+
+Listing the contents of a directory
+-----------------------------------
+
+Following are the high-level steps involved in listing a directory:
+
+#. ``pp::FileRef::ReadDirectoryEntries`` is called, and given a directory entry
+ to list. A callback is given as well; many of the other functions use
+ ``pp::BlockUntilComplete``, but ``ReadDirectoryEntries`` returns results in
+ its callback, so it must be specified.
+#. When the call to ``ReadDirectoryEntries`` completes, it calls
+ ``ListCallback`` which packages up the results into a string message, and
+ sends it to JavaScript.
+
+``file_io`` deep dive
+=====================
+
+The ``file_io`` example displays a user interface with a couple of fields and
+several buttons. Following is a screenshot of the ``file_io`` example:
+
+.. image:: /images/fileioexample.png
+
+Each radio button is a file operation you can perform, with some reasonable
+default values for filenames. Try typing a message in the large input box and
+clicking ``Save``, then switching to the ``Load File`` operation, and
+clicking ``Load``.
+
+Let's take a look at what is going on under the hood.
+
+Opening a file system and preparing for file I/O
+------------------------------------------------
+
+``pp::Instance::Init`` is called when an instance of a module is created. In
+this example, ``Init`` starts a new thread (via the ``pp::SimpleThread``
+class), and tells it to open the filesystem:
+
+.. naclcode::
+
+ virtual bool Init(uint32_t /*argc*/,
+ const char * /*argn*/ [],
+ const char * /*argv*/ []) {
+ file_thread_.Start();
+ // Open the file system on the file_thread_. Since this is the first
+ // operation we perform there, and because we do everything on the
+ // file_thread_ synchronously, this ensures that the FileSystem is open
+ // before any FileIO operations execute.
+ file_thread_.message_loop().PostWork(
+ callback_factory_.NewCallback(&FileIoInstance::OpenFileSystem));
+ return true;
+ }
+
+When the file thread starts running, it will call ``OpenFileSystem``. This
+calls ``pp::FileSystem::Open`` and blocks the file thread until the function
+returns.
+
+.. Note::
+ :class: note
+
+ Note that the call to ``pp::FileSystem::Open`` uses
+ ``pp::BlockUntilComplete`` as its callback. This is only possible because we
+ are running off the main thread; if you try to make a blocking call from the
+ main thread, the function will return the error
+ ``PP_ERROR_BLOCKS_MAIN_THREAD``.
+
+.. naclcode::
+
+ void OpenFileSystem(int32_t /*result*/) {
+ int32_t rv = file_system_.Open(1024 * 1024, pp::BlockUntilComplete());
+ if (rv == PP_OK) {
+ file_system_ready_ = true;
+ // Notify the user interface that we're ready
+ PostMessage("READY|");
+ } else {
+ ShowErrorMessage("Failed to open file system", rv);
+ }
+ }
+
+Handling messages from JavaScript
+---------------------------------
+
+When you click the ``Save`` button, JavaScript posts a message to the NaCl
+module with the file operation to perform sent as a string (See :doc:`Messaging
+System <message-system>` for more details on message passing). The string is
+parsed by ``HandleMessage``, and new work is added to the file thread:
+
+.. naclcode::
+
+ virtual void HandleMessage(const pp::Var& var_message) {
+ if (!var_message.is_string())
+ return;
+
+ // Parse message into: instruction file_name_length file_name [file_text]
+ std::string message = var_message.AsString();
+ std::string instruction;
+ std::string file_name;
+ std::stringstream reader(message);
+ int file_name_length;
+
+ reader >> instruction >> file_name_length;
+ file_name.resize(file_name_length);
+ reader.ignore(1); // Eat the delimiter
+ reader.read(&file_name[0], file_name_length);
+
+ ...
+
+ // Dispatch the instruction
+ if (instruction == kLoadPrefix) {
+ file_thread_.message_loop().PostWork(
+ callback_factory_.NewCallback(&FileIoInstance::Load, file_name));
+ } else if (instruction == kSavePrefix) {
+ ...
+ }
+ }
+
+Saving a file
+-------------
+
+``FileIoInstance::Save`` is called when the ``Save`` button is pressed. First,
+it checks to see that the FileSystem has been successfully opened:
+
+.. naclcode::
+
+ if (!file_system_ready_) {
+ ShowErrorMessage("File system is not open", PP_ERROR_FAILED);
+ return;
+ }
+
+It then creates a ``pp::FileRef`` resource with the name of the file. A
+``FileRef`` resource is a weak reference to a file in the FileSystem; that is,
+a file can still be deleted even if there are outstanding ``FileRef``
+resources.
+
+.. naclcode::
+
+ pp::FileRef ref(file_system_, file_name.c_str());
+
+Next, a ``pp::FileIO`` resource is created and opened. The call to
+``pp::FileIO::Open`` passes ``PP_FILEOPEFLAG_WRITE`` to open the file for
+writing, ``PP_FILEOPENFLAG_CREATE`` to create a new file if it doesn't already
+exist and ``PP_FILEOPENFLAG_TRUNCATE`` to clear the file of any previous
+content:
+
+.. naclcode::
+
+ pp::FileIO file(this);
+
+ int32_t open_result =
+ file.Open(ref,
+ PP_FILEOPENFLAG_WRITE | PP_FILEOPENFLAG_CREATE |
+ PP_FILEOPENFLAG_TRUNCATE,
+ pp::BlockUntilComplete());
+ if (open_result != PP_OK) {
+ ShowErrorMessage("File open for write failed", open_result);
+ return;
+ }
+
+Now that the file is opened, it is written to in chunks. In an asynchronous
+model, this would require writing a separate function, storing the current
+state on the free store and a chain of callbacks. Because this function is
+called off the main thread, ``pp::FileIO::Write`` can be called synchronously
+and a conventional do/while loop can be used:
+
+.. naclcode::
+
+ int64_t offset = 0;
+ int32_t bytes_written = 0;
+ do {
+ bytes_written = file.Write(offset,
+ file_contents.data() + offset,
+ file_contents.length(),
+ pp::BlockUntilComplete());
+ if (bytes_written > 0) {
+ offset += bytes_written;
+ } else {
+ ShowErrorMessage("File write failed", bytes_written);
+ return;
+ }
+ } while (bytes_written < static_cast<int64_t>(file_contents.length()));
+
+Finally, the file is flushed to push all changes to disk:
+
+.. naclcode::
+
+ int32_t flush_result = file.Flush(pp::BlockUntilComplete());
+ if (flush_result != PP_OK) {
+ ShowErrorMessage("File fail to flush", flush_result);
+ return;
+ }
+
+Loading a file
+--------------
+
+``FileIoInstance::Load`` is called when the ``Load`` button is pressed. Like
+the ``Save`` function, ``Load`` first checks to see if the FileSystem has been
+successfully opened, and creates a new ``FileRef``:
+
+.. naclcode::
+
+ if (!file_system_ready_) {
+ ShowErrorMessage("File system is not open", PP_ERROR_FAILED);
+ return;
+ }
+ pp::FileRef ref(file_system_, file_name.c_str());
+
+Next, ``Load`` creates and opens a new ``FileIO`` resource, passing
+``PP_FILEOPENFLAG_READ`` to open the file for reading. The result is compared
+to ``PP_ERROR_FILENOTFOUND`` to give a better error message when the file
+doesn't exist:
+
+.. naclcode::
+
+ int32_t open_result =
+ file.Open(ref, PP_FILEOPENFLAG_READ, pp::BlockUntilComplete());
+ if (open_result == PP_ERROR_FILENOTFOUND) {
+ ShowErrorMessage("File not found", open_result);
+ return;
+ } else if (open_result != PP_OK) {
+ ShowErrorMessage("File open for read failed", open_result);
+ return;
+ }
+
+Then ``Load`` calls ``pp::FileIO::Query`` to get metadata about the file, such
+as its size. This is used to allocate a ``std::vector`` buffer that holds the
+data from the file in memory:
+
+.. naclcode::
+
+ int32_t query_result = file.Query(&info, pp::BlockUntilComplete());
+ if (query_result != PP_OK) {
+ ShowErrorMessage("File query failed", query_result);
+ return;
+ }
+
+ ...
+
+ std::vector<char> data(info.size);
+
+Similar to ``Save``, a conventional while loop is used to read the file into
+the newly allocated buffer:
+
+.. naclcode::
+
+ int64_t offset = 0;
+ int32_t bytes_read = 0;
+ int32_t bytes_to_read = info.size;
+ while (bytes_to_read > 0) {
+ bytes_read = file.Read(offset,
+ &data[offset],
+ data.size() - offset,
+ pp::BlockUntilComplete());
+ if (bytes_read > 0) {
+ offset += bytes_read;
+ bytes_to_read -= bytes_read;
+ } else if (bytes_read < 0) {
+ // If bytes_read < PP_OK then it indicates the error code.
+ ShowErrorMessage("File read failed", bytes_read);
+ return;
+ }
+ }
+
+Finally, the contents of the file are sent back to JavaScript, to be displayed
+on the page. This example uses "``DISP|``" as a prefix command for display
+information:
+
+.. naclcode::
+
+ std::string string_data(data.begin(), data.end());
+ PostMessage("DISP|" + string_data);
+ ShowStatusMessage("Load success");
+
+Deleting a file
+---------------
+
+``FileIoInstance::Delete`` is called when the ``Delete`` button is pressed.
+First, it checks whether the FileSystem has been opened, and creates a new
+``FileRef``:
+
+.. naclcode::
+
+ if (!file_system_ready_) {
+ ShowErrorMessage("File system is not open", PP_ERROR_FAILED);
+ return;
+ }
+ pp::FileRef ref(file_system_, file_name.c_str());
+
+Unlike ``Save`` and ``Load``, ``Delete`` is called on the ``FileRef`` resource,
+not a ``FileIO`` resource. Note that the result is checked for
+``PP_ERROR_FILENOTFOUND`` to give a better error message when trying to delete
+a non-existent file:
+
+.. naclcode::
+
+ int32_t result = ref.Delete(pp::BlockUntilComplete());
+ if (result == PP_ERROR_FILENOTFOUND) {
+ ShowStatusMessage("File/Directory not found");
+ return;
+ } else if (result != PP_OK) {
+ ShowErrorMessage("Deletion failed", result);
+ return;
+ }
+
+Listing files in a directory
+----------------------------
+
+``FileIoInstance::List`` is called when the ``List Directory`` button is
+pressed. Like all other operations, it checks whether the FileSystem has been
+opened and creates a new ``FileRef``:
+
+.. naclcode::
+
+ if (!file_system_ready_) {
+ ShowErrorMessage("File system is not open", PP_ERROR_FAILED);
+ return;
+ }
+
+ pp::FileRef ref(file_system_, dir_name.c_str());
+
+Unlike the other operations, it does not make a blocking call to
+``pp::FileRef::ReadDirectoryEntries``. Since ``ReadDirectoryEntries`` returns
+the resulting directory entries in its callback, a new callback object is
+created pointing to ``FileIoInstance::ListCallback``.
+
+The ``pp::CompletionCallbackFactory`` template class is used to instantiate a
+new callback. Notice that the ``FileRef`` resource is passed as a parameter;
+this will add a reference count to the callback object, to keep the ``FileRef``
+resource from being destroyed when the function finishes.
+
+.. naclcode::
+
+ // Pass ref along to keep it alive.
+ ref.ReadDirectoryEntries(callback_factory_.NewCallbackWithOutput(
+ &FileIoInstance::ListCallback, ref));
+
+``FileIoInstance::ListCallback`` then gets the results passed as a
+``std::vector`` of ``pp::DirectoryEntry`` objects, and sends them to
+JavaScript:
+
+.. naclcode::
+
+ void ListCallback(int32_t result,
+ const std::vector<pp::DirectoryEntry>& entries,
+ pp::FileRef /*unused_ref*/) {
+ if (result != PP_OK) {
+ ShowErrorMessage("List failed", result);
+ return;
+ }
+
+ std::stringstream ss;
+ ss << "LIST";
+ for (size_t i = 0; i < entries.size(); ++i) {
+ pp::Var name = entries[i].file_ref().GetName();
+ if (name.is_string()) {
+ ss << "|" << name.AsString();
+ }
+ }
+ PostMessage(ss.str());
+ ShowStatusMessage("List success");
+ }
+
+Making a new directory
+----------------------
+
+``FileIoInstance::MakeDir`` is called when the ``Make Directory`` button is
+pressed. Like all other operations, it checks whether the FileSystem has been
+opened and creates a new ``FileRef``:
+
+.. naclcode::
+
+ if (!file_system_ready_) {
+ ShowErrorMessage("File system is not open", PP_ERROR_FAILED);
+ return;
+ }
+ pp::FileRef ref(file_system_, dir_name.c_str());
+
+Then the ``pp::FileRef::MakeDirectory`` function is called.
+
+.. naclcode::
+
+ int32_t result = ref.MakeDirectory(pp::BlockUntilComplete());
+ if (result != PP_OK) {
+ ShowErrorMessage("Make directory failed", result);
+ return;
+ }
+ ShowStatusMessage("Make directory success");
diff --git a/native_client_sdk/src/doc/devguide/coding/nacl_io.rst b/native_client_sdk/src/doc/devguide/coding/nacl_io.rst
index 6cee0f7525..7883906220 100644
--- a/native_client_sdk/src/doc/devguide/coding/nacl_io.rst
+++ b/native_client_sdk/src/doc/devguide/coding/nacl_io.rst
@@ -1,3 +1,5 @@
+.. _nacl_io:
+
###################
The nacl_io Library
###################
@@ -23,7 +25,7 @@ can be used by the application. For example, the Chrome browser supports the
<http://www.html5rocks.com/en/tutorials/file/filesystem/>`_ which provides
access to a protected area of the local file system. This filesystem can
be accessed by an HTML page using JavaScript commands, and also by a Native
-Client module using the Pepper :doc:`File IO API <FileIO>`. With nacl_io
+Client module using the Pepper :doc:`File IO API <file-io>`. With nacl_io
a Native Client application can mount an HTML5 filesystem and access it via
standard POSIX I/O function such as ``fopen``, ``fseek``, ``fread``,
``fwrite``, and ``fclose``, or their low level UNIX counterparts ``open``,
diff --git a/native_client_sdk/src/doc/devguide/devcycle/_toc.yaml b/native_client_sdk/src/doc/devguide/devcycle/_toc.yaml
deleted file mode 100644
index 5481d8e381..0000000000
--- a/native_client_sdk/src/doc/devguide/devcycle/_toc.yaml
+++ /dev/null
@@ -1,14 +0,0 @@
-toc:
- - title: "Development Cycle"
- path: /native-client/${folder}/devguide/devcycle
- section:
- - title: "Building"
- path: /native-client/${folder}/devguide/devcycle/building
- - title: "Dynamic Linking and Loading with glibc"
- path: /native-client/${folder}/devguide/devcycle/dynamic-loading
- - title: "Running"
- path: /native-client/${folder}/devguide/devcycle/running
- - title: "Debugging"
- path: /native-client/${folder}/devguide/devcycle/debugging
- - title: "Debugging with Visual Studio"
- path: /native-client/${folder}/devguide/devcycle/vs-addin
diff --git a/native_client_sdk/src/doc/devguide/devcycle/building.rst b/native_client_sdk/src/doc/devguide/devcycle/building.rst
index 8d5ab3d2a4..3cec584977 100644
--- a/native_client_sdk/src/doc/devguide/devcycle/building.rst
+++ b/native_client_sdk/src/doc/devguide/devcycle/building.rst
@@ -51,30 +51,26 @@ nexe applications.
C libraries
-----------
-The PNaCl SDK has a single choice of C library:
-`newlib <http://sourceware.org/newlib/>`_.
+The PNaCl SDK has a single choice of C library: newlib_.
The Native Client SDK also has a GCC-based toolchain for building
**nexes**. The GCC-based toolchain has support for two C libraries:
-`newlib <http://sourceware.org/newlib/>`_ and
-`glibc <http://www.gnu.org/software/libc/>`_.
-See :doc:`Dynamic Linking & Loading with glibc <dynamic-loading>`
-for information about these libraries, including factors to help you
-decide which to use.
+newlib_ and glibc_. See :doc:`Dynamic Linking & Loading with glibc
+<dynamic-loading>` for information about these libraries, including factors to
+help you decide which to use.
.. _building_cpp_libraries:
C++ libraries
-------------
-The PNaCl SDK can use either
-`libstdc++ <http://gcc.gnu.org/libstdc++>`_ (the current default)
-or LLVM's `libc++ <http://libcxx.llvm.org/>`_ (experimental support).
-The ``-stdlib=[libstdc++|libc++]`` command line argument can be used
+The PNaCl SDK can use either `libstdc++ <http://gcc.gnu.org/libstdc++>`_ (the
+current default) or LLVM's `libc++ <http://libcxx.llvm.org/>`_ (experimental
+support). The ``-stdlib=[libstdc++|libc++]`` command line argument can be used
to choose which standard library to use.
-The GCC-based Native Client SDK only has support for
-`libstdc++ <http://gcc.gnu.org/libstdc++>`_.
+The GCC-based Native Client SDK only has support for `libstdc++
+<http://gcc.gnu.org/libstdc++>`_.
C++11 library support is only complete in libc++ but other non-library
language features should work regardless of which standard library is
@@ -656,3 +652,6 @@ When faced with a PNaCl ABI verification error, check the list of features
that are :ref:`not supported by PNaCl <when-to-use-nacl>`.
If the problem you face is not listed as restricted,
:ref:`let us know <help>`!
+
+.. _glibc: http://www.gnu.org/software/libc/
+.. _newlib: http://sourceware.org/newlib/
diff --git a/native_client_sdk/src/doc/devguide/devcycle/debugging.rst b/native_client_sdk/src/doc/devguide/devcycle/debugging.rst
index 199ff3f28a..abb369eedc 100644
--- a/native_client_sdk/src/doc/devguide/devcycle/debugging.rst
+++ b/native_client_sdk/src/doc/devguide/devcycle/debugging.rst
@@ -197,6 +197,8 @@ you can use the built-in Visual Studio debugger. When running as a Native
Client module Visual Studio will launch an instance of nacl-gdb for you and
link it to the running code.
+.. _using_gdb:
+
Debugging with nacl-gdb
-----------------------
@@ -445,9 +447,5 @@ and `Linux
machines.
-
-
-
-
.. |menu-icon| image:: /images/menu-icon.png
.. |puzzle| image:: /images/puzzle.png
diff --git a/native_client_sdk/src/doc/devguide/devcycle/dynamic-loading.rst b/native_client_sdk/src/doc/devguide/devcycle/dynamic-loading.rst
index 00b76bb3a5..28cbcd2386 100644
--- a/native_client_sdk/src/doc/devguide/devcycle/dynamic-loading.rst
+++ b/native_client_sdk/src/doc/devguide/devcycle/dynamic-loading.rst
@@ -29,7 +29,7 @@ C standard libraries: glibc and newlib
--------------------------------------
The Native Client SDK comes with two C standard libraries --- glibc and
-newlib. These libraries are described in the table below.
+newlib. These libraries are described in the table below.
+--------+----------+-------------+--------------------------------------------+
| Library| Linking | License | Description |
@@ -53,14 +53,10 @@ newlib. These libraries are described in the table below.
| | | software | more suitable to link statically in |
| | | licenses | commercial, closed-source applications. For|
| | | | documentation, FAQs, and additional |
-| | | | information about newlib, see the `newlib |
-| | | | documentation`__. |
+| | | | information about newlib, see the newlib_ |
+| | | | documentation. |
+--------+----------+-------------+--------------------------------------------+
-.. _GLIBC: http://www.gnu.org/software/libc/index.html
-.. _POSIX: http://en.wikipedia.org/wiki/POSIX
-__ http://sourceware.org/newlib
-
For proprietary (closed-source) applications, your options are to either
statically link to newlib, or dynamically link to glibc. We recommend
dynamically linking to glibc, for a couple of reasons:
@@ -160,14 +156,14 @@ manifest (.nmf) file, and deploy an application are provided below.
Building a dynamically linked application
=========================================
-A dynamically linked application typically includes one Native Client module
-and one or more shared libraries. (How to allocate code between Native Client
-modules and shared libraries is a question of application design that is beyond
-the scope of this document.) Each Native Client module and shared library must
-be compiled for at least the x86 32-bit and 64-bit architectures.
+Applications built with the glibc toolchain will by dynamically linked by
+default. Application that load shared libraries at runtime using ``dlopen()``
+must link with the libdl library (``-ldl``).
-The dlopen example in the SDK
------------------------------
+Like other gcc-based toolchains building a dynamic library for NaCl is normally
+done by linking with the ``-shared`` flag and compiling with the ``-fPIC`` flag.
+The SDK build system will do this automatically when the ``SO_RULE`` Makefile
+rule is used.
The Native Client SDK includes an example that demonstrates how to build a
shared library, and how to use the ``dlopen()`` interface to load that library
@@ -178,22 +174,26 @@ it demonstrates how to build Native Client modules (.nexe files) and shared
libraries (.so files) with the x86 glibc toolchain, and how to generate a
Native Client manifest file for glibc applications.
-The SDK example, located in the directory examples/dlopen, includes two C++
+The SDK example, located in ``examples/tutorial/dlopen``, includes three C++
files:
eightball.cc
This file implements the function ``Magic8Ball()``, which is used to provide
- whimsical answers to user questions. The file is compiled into a shared
- library, ``libeightball.so``.
+ whimsical answers to user questions. This file is compiled into a shared
+ library called ``libeightball.so``. This library gets included in the
+ .nmf file and is therefore directly loadable with ``dlopen()``.
-dlopen.cc
- This file implements the Native Client module, which loads
- ``libeightball.so``, receives messages from JavaScript (sent in response to
- user input), calls ``Magic8Ball()`` to generate answers, and sends messages
- back to JavaScript with the generated answers. The file is compiled into a
- .nexe file.
+reverse.cc
+ This file implements the function ``Reverse()``, which returns reversed
+ copies of strings that are passed to it. This file is compiled into a shared
+ library called ``libreverse.so``. This library is **not** included in the
+ .nmf file and is loaded via an http mount using the :ref:`nacl_io library
+ <nacl_io>`.
-.. TODO(sbc): also mention reverse.{cc,h} files
+dlopen.cc
+ This file implements the Native Client module, which loads the two shared
+ libraries and handles communcation with with JavaScript. The file is compiled
+ into a Native Client executable (.nexe).
Run ``make`` in the dlopen directory to see the commands the Makefile executes
to build x86 32-bit and 64-bit .nexe and .so files, and to generate a .nmf
@@ -212,120 +212,26 @@ file. These commands are described below.
linking and loading. Take a look at the example Makefiles and the generated
.nmf files for details on how to build dynamically linked applications.
-
-Building a Native Client module (.nexe file)
---------------------------------------------
-
-.. TODO(sbc): there is a lot of redundant detail here. Also the Makefile
- structure has changed significantly.
-
-The Makefile in the dlopen example builds ``dlopen.cc`` into a .nexe file using
-the two commands shown below. (For simplicity, the full path to the
-compiler/linker is not shown; the tool is located in the bin directory in the
-x86 glibc toolchain, e.g. toolchain/win_x86_glibc/bin.)
-
-To compile dlopen.cc into dlopen_x86_32.o::
-
- i686-nacl-g++ -o dlopen_x86_32.o -c dlopen.cc -m32 -g -O0 -pthread -std=gnu++98 -Wno-long-long -Wall
-
-To link dlopen_x86_32.o into dlopen_x86_32.nexe::
-
- i686-nacl-g++ -o dlopen_x86_32.nexe dlopen_x86_32.o -m32 -g -ldl -lppapi_cpp -lppapi
-
-A few of the flags in these commands are described below:
-
-``-o`` *file*
- put the output in *file*
-
-``-c``
- compile the source file, but do not link it
-
-``-m32``
- produce 32-bit code (i.e., code for the x86-32 target architecture)
-
-``-g``
- produce debugging information
-
-``-O0``
- use a base optimization level that minimizes compile time
-
-``-pthread``
- support multithreading with the pthread library
-
-``-W`` *warning*
- request or supress the specified warning
-
-``-l`` *library*
- use the specified *library* when linking (per C library naming conventions,
- the linker uses the file lib*library*.so, or if that file is not available,
- lib*library*.a; e.g., -ldl corresponds to libdl.so or libdl.a)
-
-Many of these flags are optional; you need not use all of them to compile and
-link your application. For example, you only need to use -ldl if your
-application uses the dlopen() interface to open a library at runtime. The
-toolchains in the Native Client SDK are based on the gcc compiler; see `gcc
-command options <http://gcc.gnu.org/onlinedocs/gcc/Invoking-GCC.html>`_ for a
-full description of the gcc flags. For flags that are recommended with Native
-Client, see :ref:`compile flags for different development scenarios
-<compile_flags>`.
-
-Note that you can combine the compile and link steps to build a .nexe file
-using one command. Simply run i686-nacl-g++ once and use the appropriate
-combination of flags (omit the -c flag and include the -l flag with the
-required libraries)::
-
- i686-nacl-g++ -o dlopen_x86_32.nexe dlopen.cc ^ -m32 -g -O0 -pthread -std=gnu++98 -Wno-long-long -Wall -ldl -lppapi_cpp -lppapi
-
-(The carat ``^`` allows the command to span multiple lines on Windows; to do
-the same on Mac and Linux use a backslash instead. Or you can simply type the
-command and all its arguments on one line.)
-
-The commands above build a 32-bit .nexe. To build a 64-bit .nexe, run the same
-commands but with the **-m64** flag instead of -m32, and of course specify
-different output file names. Check the Makefile in the dlopen example to see
-the set of commands that is used to generate 32-bit and 64-bit .nexes.
-
-Building a shared library (.so file)
-------------------------------------
-
-The Makefile in the dlopen example builds eightball.cc into a .so file using
-the two commands shown below.
-
-To compile eightball.cc into eightball_x86_32.o::
-
- i686-nacl-g++ -o eightball_x86_32.o -c eightball.cc -m32 -g -O0 -pthread -std=gnu++98 -Wno-long-long -Wall -fPIC
-
-To link eightball_x86_32.o into eightball_x86_32.so::
-
- i686-nacl-g++ -o libeightball.so eightball_x86_32.o -m32 -g -ldl -lppapi_cpp -lppapi -shared
-
-A couple of the important flags in these commands are described below:
-
-``-fPIC``
- generate position-independent code (PIC) suitable for use in a shared library
- (this flag is required for all x86 64-bit modules and for 32-bit shared
- libraries)
-``-shared``
- produce a shared object that can be linked with other objects to form an
- executable (this flag is required for .so files)
- As when building a .nexe, you can combine compiling and linking into one step
- by running i686-nacl-g++ once with the appropriate combination of flags.
-
-As with .nexes, you need to generate both 32-bit and 64-bit versions of a
-shared object -- see the dlopen example for an illustration. In the dlopen
-example, the shared objects are put into the subdirectories ``lib32`` and
-``lib64``. These directories are used to collect all the shared libraries
-needed by the application, as discussed below.
-
.. _dynamic_loading_manifest:
Generating a Native Client manifest file for a dynamically linked application
=============================================================================
-The Native Client manifest file must specify the full list of executable files
-needed by an application, including the recursive closure of shared library
-dependencies. Take a look at the manifest file in the dlopen example to see how
-a glibc-style manifest file is structured. (Run make in the dlopen directory to
+The Native Client manifest file specifies the name of the executable to run
+and must also specify any shared libraries that the application directly
+depends on. For indirect dependencies (such as libraries opened via
+``dlopen()``) it is also convenient to list libraries in the manifest file.
+However it is possile to load arbitrary shared libraries at runtime that
+are not mentioned in the manifest by using the `nacl_io library <nacl_io>`_
+to mount a filesystem that contains the shared libraries which will then
+allow ``dlopen()`` to access them.
+
+In this example we demonstrate both loading directly from via the manifest
+file (``libeightball.so``) and loading indirectly via a http mount
+(``libreverse.so``).
+
+Take a look at the manifest file in the dlopen example to see how
+a glibc-style manifest file is structured. (Run ``make`` in the dlopen directory to
generate the manifest file if you haven't done so already.) Here is an excerpt
from ``dlopen.nmf``::
@@ -359,123 +265,51 @@ from ``dlopen.nmf``::
In most cases, you can use the ``create_nmf.py`` script in the SDK to generate
a manifest file for your application. The script is located in the tools
-directory (e.g., pepper_28/tools).
-
-.. TODO(sbc): running create_nmf.py is much simpler now.
-
-The Makefile in the dlopen example generates the manifest file ``dlopen.nmf``
-by running the following command::
+directory (e.g. ``pepper_28/tools``).
- python <NACL_SDK_ROOT>/tools/create_nmf.py ^
- -D <NACL_SDK_ROOT>/toolchain/win_x86_glibc/x86_64-nacl/bin/objdump ^
- -o dlopen.nmf ^
- -s . ^
- dlopen_x86_32.nexe dlopen_x86_64.nexe lib32/libeightball.so lib64/libeightball.so ^
- -L <NACL_SDK_ROOT>/toolchain/win_x86_glibc/x86_64-nacl/lib32 ^
- -L <NACL_SDK_ROOT>/toolchain/win_x86_glibc/x86_64-nacl/lib64
+The Makefile in the dlopen example generates the manifest automatically using
+the ``NMF_RULE`` provided by the SDK build system. Running ``make V=1`` will
+show the full command line which is used to generate the nmf::
-(The carat ``^`` allows the command to span multiple lines on Windows; to do the
-same on Mac and Linux use a backslash instead, or you can simply type the
-command and all its arguments on one line. *<NACL_SDK_ROOT>* represents the path
-to the top-level directory of the bundle you are using, e.g.,
-*<location-where-you-installed-the-SDK>*/pepper_28.)
+ create_nmf.py -o dlopen.nmf glibc/Release/dlopen_x86_32.nexe \
+ glibc/Release/dlopen_x86_64.nexe glibc/Release/libeightball_x86_32.so \
+ glibc/Release/libeightball_x86_64.so -s ./glibc/Release \
+ -n libeightball_x86_32.so,libeightball.so \
+ -n libeightball_x86_64.so,libeightball.so
-
-Run python ``create_nmf.py --help`` to see a description of the command-line
+Run python ``create_nmf.py --help`` to see a full description of the command-line
flags. A few of the important flags are described below.
-.. TODO(sbc): remove -D option which is now deprecated.
-
-``-D`` *tool*
- use *tool* to read information about a file and determine shared library
- dependencies (the tool must be a version of the `objdump
- <http://en.wikipedia.org/wiki/Objdump>`_ utility)
-
``-s`` *directory*
use *directory* to stage libraries (libraries are added to ``lib32`` and
``lib64`` subfolders)
``-L`` *directory*
- add *directory* to the library search path
+ add *directory* to the library search path. The default search path
+ already includes the toolchain and SDK libraries directories.
.. Note::
:class: note
- **Caution:** The ``create_nmf.py`` script only recognizes explicit shared
- library dependencies (for example, dependencies specified with the -l flag
- for the compiler/linker). The manifest file generated by create_nmf.py will
- be incorrect in the following situations:
-
- * You run ``create_nmf.py`` without listing as arguments all the libraries
- that your application opens with ``dlopen()``.
-
- * After you run ``create_nmf.py``, you subsequently add a library dependency
- that is not mentioned in the manifest file.
-
- * After you run ``create_nmf.py``, you subsequently change the directory
- structure on your server or in your Chrome Web Store manifest file, such
- that the needed libraries are no longer in the location specified in the
- .nmf file
-
- To handle the above situations correctly, you must re-run ``create_nmf.py``
- (for example, if you added a new library dependency in your application or
- changed the application directory structure), and make sure to list all the
- libraries that your application opens at runtime with ``dlopen()`` (e.g.,
- libeighball.so in the dlopen example).
-
-.. TODO(sbc): We probably don't want/need this next section in the docs at all.
-
-As an alternative to using ``create_nmf.py``, you can also chase down the full
-list of shared library dependencies manually and add those to your .nmf file.
-To do so, start by running the Native Client version of the objdump utility on
-your .nexe file, as shown below. (The objdump utility is located in the same
-directory as the glibc toolchain, e.g., toolchain/win_x86_glibc/bin.)
-
-::
-
- i686-nacl-objdump -p dlopen_x86_32.nexe
-
-A .nexe file contains compiled machine code, as well as headers that describe
-the contents of the file and information about how to use the file. The objdump
-utility lets you examine the file's headers, including the "Dynamic Section,"
-which specifies shared library dependencies, as in this example output from the
-dlopen example::
-
- Dynamic Section:
- NEEDED libdl.so.32d9fc17
- NEEDED libppapi_cpp.so
- NEEDED libpthread.so.32d9fc17
- NEEDED libstdc++.so.6
- NEEDED libm.so.32d9fc17
- NEEDED libgcc_s.so.1
- NEEDED libc.so.32d9fc17
- INIT 0x01000140
- FINI 0x01002560
- HASH 0x110025fc
- ...
-
-
-All the files that are identified as NEEDED in the "Dynamic Section" portion of
-the objdump output are files that you need to list in your Native Client
-manifest file and distribute with your application. (The numbers listed at the
-end of the file names are version numbers, and you must list and distribute
-those exact versions.) Once you've identified the shared libraries that are
-needed by your .nexe file, you must repeat the process recursively: Run objdump
-on each of the NEEDED files, and add the newly-identified NEEDED files to your
-manifest file and to your distribution directories. To get the full list of
-libraries for an application, repeat the process until you've identified the
-recursive closure of dependencies.
+ **Note:** The ``create_nmf`` script can only automatically detect explicit
+ shared library dependencies (for example, dependencies specified with the -l
+ flag for the compiler/linker). If you want to include libraries that you
+ intend to dlopen() at runtime you must explcitly list them in your call to
+ ``create_nmf``.
+
+As an alternative to using ``create_nmf``, it is possible to manually calculate
+the list of shared library dependencies using tools such as ``objdump_``.
Deploying a dynamically linked application
==========================================
As described above, an application's manifest file must explicitly list all the
-executable code modules that the application requires, including modules from
-the application itself (.nexe and .so files), modules from the Native Client
-SDK (e.g., libppapi_cpp.so), and perhaps also modules from `naclports
-<http://code.google.com/p/naclports>`_ or from :doc:`middleware systems
-<../../community/middleware>` that the application uses. You must provide all of
-those modules as part of the application deployment process.
+executable code modules that the application directly depends on, including
+modules from the application itself (.nexe and .so files), modules from the
+Native Client SDK (e.g., libppapi_cpp.so), and perhaps also modules from
+`naclport <naclports_>`_ or from :doc:`middleware systems <../../community/middleware>` that
+the application uses. You must provide all of those modules as part of the
+application deployment process.
As explained in :doc:`Distributing Your Application
<../distributing>`, there are two basic ways to deploy an application:
@@ -497,7 +331,7 @@ file may be located in directories you specified with the -L option to
``create_nmf.py``. You are free to rename/rearrange files and directories
referenced by the Native Client manifest file, so long as the modules are
available in the locations indicated by the manifest file. If you move or
-rename modules, it may be easier to re-run create_nmf.py to generate a new
+rename modules, it may be easier to re-run ``create_nmf.py`` to generate a new
manifest file rather than edit the original manifest file. For hosted
applications, you can check for name mismatches during testing by watching the
request log of the web server hosting your test deployment.
@@ -523,60 +357,35 @@ thread to pre-load libraries asynchronously during initialization of your
application, so that the libraries are available when they're needed. You can
call ``dlopen()`` a second time when you need to use a library -- per the
specification, subsequent calls to ``dlopen()`` return a handle to the
-previously loaded library. Note that you should only call dlclose() to close a
-library when you no longer need the library; otherwise, subsequent calls to
-``dlopen()`` could cause the library to be fetched again.
-
-The dlopen example in the SDK demonstrates how to open a shared library,
-magiceightball.so, at runtime. To reiterate, the example includes two C++
-files:
+previously loaded library. Note that you should only call ``dlclose()`` to
+close a library when you no longer need the library; otherwise, subsequent
+calls to ``dlopen()`` could cause the library to be fetched again.
-.. TODO(sbc): mention the third .cc file which is now part of this example.
+The dlopen example in the SDK demonstrates how to open a shared libraries
+at runtime. To reiterate, the example includes three C++ files:
-* eightball.cc: this is the shared library that implements the function
+* ``eightball.cc``: this is the shared library that implements the function
``Magic8Ball()`` (this file is compiled into libeightball.so)
-* dlopen.cc: this is the Native Client module that loads ``libeightball.so``
- and calls ``Magic8Ball()`` to generate answers (this file is compiled into
- dlopen_x86_{32,64}.nexe)
+* ``reverse.cc``: this is the shared library that implements the function
+ ``Reverse()`` (this file is compiled into libreverse.so)
+* ``dlopen.cc``: this is the Native Client module that loads the shared libraries
+ and makes calls to ``Magic8Ball()`` and ``Reverse()`` in response to requests
+ from JavaScript.
When the Native Client module starts, it kicks off a worker thread that calls
-``dlopen()`` to load magiceightball.so. When the download of
-``libeightball.so`` completes, the worker thread schedules a callback function
-on the main thread. The callback function calls ``dlopen()`` for
-``magiceightball.so`` a second time; this second call obtains a proper handle
-to the library. Once the module has a handle to the library, it grabs the entry
-point in libeightball.so for the ``Magic8Ball()`` function. When a user types
-in a query and clicks the 'ASK!' button, the module calls ``Magic8Ball()`` to
-generate an answer, and returns the result to the user.
-
-The sequence of calls in the dlopen module is illustrated by the pseudo-code in
-the table below:
-
-+------------------------------------------------+------------------------------------------+
-| Worker Thread | Main Thread |
-+================================================+==========================================+
-| :: | :: |
-| | |
-| pthread_create(.., LoadLibrariesOnWorker, ..)| - |
-| - | LoadLibrariesOnWorker() |
-| - | LoadLibrary() |
-| - | dlopen("libeightball.so",...) |
-| - | CallOnMainThread(.., LoadDone, ..) |
-| LoadDone() | - |
-| UseLibrary() | - |
-| dlopen("libeightball.so", ...) | - |
-| offset = dlsym(..., "Magic8Ball") | - |
-| HandleMessage() | - |
-| _eightball = (TYPE_eightball) offset; | - |
-| PostMessage() | - |
-+------------------------------------------------+------------------------------------------+
+``dlopen()`` to load the two shared libraries. Once the module has a handle to
+the library, it fetches the addresses of the ``Magic8Ball()`` and ``Reverse()``
+functions using ``dlsym()``. When a user types in a query and clicks the 'ASK!'
+button, the module calls ``Magic8Ball()`` to generate an answer, and returns
+the result to the user. Likewise when the user clicks the 'Reverse' button
+it calls the ``Reverse()`` function to reverse the string.
Troubleshooting
===============
If your .nexe isn't loading, the best place to look for information that can
-help you troubleshoot the problem is stdout and nacllog. See the Debugging page
-for instructions about how to access those streams.
+help you troubleshoot the JavaScript console and standard output from Chrome.
+See :ref:`Debugging <devcycle-debugging>` for more information.
Here are a few common error messages and explanations of what they mean:
@@ -617,3 +426,7 @@ Here are a few common error messages and explanations of what they mean:
list libraries after the -o flag.
.. |menu-icon| image:: /images/menu-icon.png
+.. _objdump: http://en.wikipedia.org/wiki/Objdump
+.. _GLIBC: http://www.gnu.org/software/libc/index.html
+.. _POSIX: http://en.wikipedia.org/wiki/POSIX
+.. _newlib: http://sourceware.org/newlib/
diff --git a/native_client_sdk/src/doc/devguide/devcycle/running.rst b/native_client_sdk/src/doc/devguide/devcycle/running.rst
index 3b3273a08a..a85891fc99 100644
--- a/native_client_sdk/src/doc/devguide/devcycle/running.rst
+++ b/native_client_sdk/src/doc/devguide/devcycle/running.rst
@@ -141,6 +141,8 @@ application uses. For example, if you compiled your application using the
the application in Chrome 31 or higher. To check which version of Chrome you're
using, type ``about:version`` in the Chrome address bar.
+.. _cache:
+
Chrome Cache
------------
diff --git a/native_client_sdk/src/doc/devguide/devcycle/vs-addin.rst b/native_client_sdk/src/doc/devguide/devcycle/vs-addin.rst
index d09b6b5f95..503ad73e78 100644
--- a/native_client_sdk/src/doc/devguide/devcycle/vs-addin.rst
+++ b/native_client_sdk/src/doc/devguide/devcycle/vs-addin.rst
@@ -6,3 +6,596 @@ Debugging With Visual Studio
:local:
:backlinks: none
:depth: 2
+
+Whether you're porting an existing project or starting from scratch, the Native
+Client Visual Studio add-in makes it easier to set up, build, run and debug
+your Native Client app by integrating the Native Client SDK development tools
+into the Visual Studio environment.
+
+.. Note::
+ :class: note
+
+ The Native Client add-in requires Visual Studio 2010 with Service Pack 1. No
+ other versions of Visual Studio are currently supported. Visual Studio
+ Express is also not supported.
+
+Introduction
+============
+
+The Native Client add-in for Visual Studio helps you develop your application
+more efficiently in many ways:
+
+* Organize and maintain your code as a Visual Studio project.
+* Iteratively write and test your application more easily. Visual Studio
+ handles the details of launching a web server to serve your module and run
+ the module in Chrome with a debugger attached.
+* Compile your module into a dynamically-linked library (DLL) using Visual
+ Studio's C/C++ compiler and run it as a Pepper plugin. This allows you to
+ develop code incrementally, coding and/or porting one feature at a time into
+ the Pepper APIs while continuing to use native Windows APIs that would
+ otherwise be unavailable in an actual Native Client module.
+* Use Visual Studio's built-in debugger to debug your code while it’s running
+ as a Pepper plugin.
+* Compile your module into a .nexe or .pexe file using the Native Client SDK
+ tools and run it as a bona fide Native Client module.
+* Use the Native Client debugger, nacl-gdb, to test your code when it’s running
+ as a Native Client object.
+
+The add-in defines five new Visual Studio platforms: ``PPAPI``, ``NaCl32``,
+``NaCl64``, ``NaClARM``, and ``PNaCl``. These platforms can be applied to the
+debug configuration of solutions and projects. The platforms configure the
+properties of your project so it can be built and run as either a Pepper plugin
+or a Native Client module. The platforms also define the behavior associated
+with the debug command so you can test your code while running in Visual
+Studio.
+
+Platforms
+=========
+
+It is helpful to consider the Visual Studio add-in platforms in two groups. One
+contains the PPAPI platform only. The other group, which we'll call the Native
+Client platforms, contains platforms that all have "NaCl" in their names:
+``NaCl32``, ``NaCl64``, ``NaClARM``, and ``PNaCl``. The diagram below shows the
+platforms, the ways they are normally used, and the build products they produce.
+
+.. image:: /images/visualstudio4.png
+
+Using platforms, your workflow is faster and more efficient. You can compile,
+start, and debug your code with one click or key-press. When you press F5, the
+“start debugging” command, Visual Studio automatically launches a web server to
+serve your module (if necessary) along with an instance of Chrome that runs
+your Native Client module, and also attaches an appropriate debugger.
+
+You can switch between platforms as you work to compare the behavior of your
+code.
+
+When you run your project, Visual Studio launches the PPAPI and Native Client
+platforms in different ways, as explained in the next sections.
+
+The PPAPI platform
+------------------
+
+The PPAPI platform builds your module as a dynamic library and launches a
+version of Chrome that’s configured to run the library as a plugin when it
+encounters an ``<embed>`` element with ``type=application/x-nacl`` (ignoring
+the information in the manifest file). When running in the PPAPI platform, you
+can use Windows system calls that are unavailable in a regular Native Client
+module built and running as a .nexe file. This offers the ability to port
+existing code incrementally, rewriting functions using the PPAPI interfaces one
+piece at a time. Since the module is built with Visual Studio’s native compiler
+(MSBuild) you can use the Visual Studio debugger to control and inspect your
+code.
+
+The Native Client platforms
+---------------------------
+
+There are four Native Client platforms. All of them can be used to build Native
+Client modules. When you run one of the Native Client platforms Visual Studio
+builds the corresponding type of Native Client module (either a .nexe or
+.pexe), starts a web server to serve it up, and launches a copy of Chrome that
+fetches the module from the server and runs it. Visual Studio will also open a
+terminal window, launch an instance of nacl-gdb, and attach it to your module's
+process so you can use gdb commands to debug.
+
+NaCl32 and NaCl64
+^^^^^^^^^^^^^^^^^
+
+The platforms named NaCl32 and NaCl64 are targeted at x86 32-bit and 64-bit
+systems respectively. You need both platforms to build a full set of .nexe
+files when you are ready to distribute your application. Note, however, that
+when you are testing in Visual Studio you must select the NaCl64 platform
+(because Chrome for Windows runs Native Client in a 64-bit process). If you try
+to run from the NaCl32 platform you will get an error message.
+
+NaClARM
+^^^^^^^
+
+The NaClARM platform is targeted at ARM-based processors. You can build .nexe
+files with the NaClARM platform in Visual Studio but you cannot run them from
+there. You can use Visual Studio to create a Native Client module that includes
+an ARM-based .nexe file and then run the module from a Chrome browser on an ARM
+device, such as one of the newer Chromebook computers. See the instructions at
+:doc:`Running Native Client Applications <running>` for more information on
+testing your module in Chrome.
+
+.. Note::
+ :class: note
+
+ Note: The NaClARM platform currently supports the newlib toolchain only.
+
+PNaCl
+^^^^^
+
+The PNaCl (portable NaCl) platform is included in the Visual Studio Native
+Client add-in versions 1.1 and higher. It supports the .pexe file format. A
+.pexe file encodes your application as bitcode for a low level virtual machine
+(LLVM). When you deliver a Native Client application as a PNaCl module, the
+manifest file will contain a single .pexe file rather than multiple .nexe
+files. The Chrome client transforms the LLVM bitcode into machine instructions
+for the local system.
+
+When you run the PNaCl platform from Visual Studio, Visual Studio uses the
+Native Client SDK to transform the .pexe file into a NaCl64 .nexe file and runs
+it as if you were working with a NaCl64 platform.
+
+.. Note::
+ :class: note
+
+ Note: The PNaCl platform currently supports the newlib toolchain only.
+
+Installing the add-in
+=====================
+
+In order to use the Native Client Visual Studio add-in, your development
+environment should include:
+
+* A 64-bit version of Windows Vista or Windows 7.
+* Visual Studio 2010 with Service Pack 1.
+* `Chrome <https://www.google.com/intl/en/chrome/browser/>`_ version 23 or
+ greater. You can choose to develop using the latest `canary
+ <https://www.google.com/intl/en/chrome/browser/canary.html>`_ build of
+ Chrome, running the canary version side-by-side with (and separately from)
+ your regular version of Chrome.
+* :doc:`The Native Client SDK <../../sdk/download>` with the ``pepper_23``
+ bundle or greater. The version of Chrome that you use must be equal or
+ greater than the version of the SDK bundle.
+
+Set environment variables
+-------------------------
+
+Before you run the installer you must define two Windows environment variables.
+They point to the bundle in the Native Client SDK that you use to build your
+module, and to the Chrome browser that you choose to use for debugging.
+
+To set environment variables in Windows 7, go to the Start menu and search for
+"environment." One of the links in the results is "Edit environment variables
+for your account." (You can also reach this link from the ``Control Panel``
+under ``User Accounts``.) Click on the link and use the buttons in the window
+to create or change these user variables (the values shown below are only for
+example):
+
++---------------+--------------------------------------------------------------+
+| Variable Name | Description |
++===============+==============================================================+
+| NACL_SDK_ROOT | The path to the pepper directory in the SDK. Example: |
+| | ``C:\nacl_sdk\pepper_23`` |
++---------------+--------------------------------------------------------------+
+| CHROME_PATH | The path to the .exe file for the version of Chrome you are |
+| | testing with. Example: |
+| | ``C:\Users\fred\AppData\Local\Google\Chrome |
+| | SxS\Application\chrome.exe`` |
++---------------+--------------------------------------------------------------+
+
+Download the add-in
+-------------------
+
+The Native Client Visual Studio add-in is a separate bundle in the SDK named
+``vs_addin``. Open a command prompt window, go to the top-level SDK directory,
+and run the update command, specifying the add-in bundle::
+
+ naclsdk update vs_addin
+
+This creates a folder named ``vs_addin``, containing the add-in itself, its
+installer files, and a directory of examples.
+
+.. Note::
+ :class: note
+
+ Note: The vs_addin bundle is only visible when you run ``naclsdk`` on a
+ Windows system.
+
+Run the installer
+-----------------
+
+The installer script is located inside the ``vs_addin`` folder in the SDK.
+Right click on the file ``install.bat`` and run it as administrator.
+
+The script always installs the NativeClient platforms, and asks you if you’d
+like to install the PPAPI platform as well. You can skip the PPAPI step and run
+the installer again later to add the PPAPI platform.
+
+You can usually run the installer successfully with no arguments. The new
+platforms are installed in ``C:\Program Files
+(x86)\MSBuild\Microsoft.Cpp\v4.0\Platforms``.
+
+In some cases system resources may not be in their default locations. You might
+need to use these command line arguments when you run ``install.bat``:
+
+* The MSBuild folder is assumed to be at ``C:\Program Files (x86)\MSBuild``.
+ You can specify an alternate path with the flag ``--ms-build-path=<path>``.
+ The installer assumes Visual Studio has created a user folder at
+* ``%USERPROFILE%\My Documents\Visual Studio 2010``. You can specify an
+ alternate path with the flag ``--vsuser-path=path``.
+
+From time to time an update to the Visual Studio add-in may become available.
+Updates are performed just like an installation. Download the new add-in using
+naclsdk update and run ``install.bat`` as administrator.
+
+To uninstall the add-in, run ``install.bat`` as administrator and add the
+``--uninstall`` flag. You'll need to run the Command Prompt program as
+administrator in order to add the flag. Go the to the Windows start menu,
+search for "Command Prompt," right click on the program and run it as
+administrator.
+
+You can verify that the add-in has been installed and determine its version by
+selecting Add-in Manager in the Visual Studio Tools menu. If the add-in has
+been installed it will appear in the list of available add-ins. Select it and
+read its description.
+
+Try the ``hello_world_gles`` sample project
+===========================================
+
+The add-in comes with an examples directory. Open the sample project
+``examples\hello_world_gles\hello_world_gles.sln``. This project is an
+application that displays a spinning cube.
+
+Select the NaCl64 platform
+--------------------------
+
+Open the sample project in Visual Studio, select the ``Configuration Manager``,
+and confirm that the active solution configuration is ``Debug`` and the active
+project platform is ``NaCl64``. Note that the platform for the
+``hello_world_gles`` project is also ``NaCl64``. (You can get to the
+``Configuration Manager`` from the ``Build`` menu or the project’s
+``Properties`` window.)
+
+.. image:: /images/visualstudio1.png
+
+Build and run the project
+-------------------------
+
+Use the debugging command (F5) to build and run the project. As the wheels
+start to turn, you may be presented with one or more alerts. They are benign;
+you can accept them and set options to ignore them when that’s possible. Some
+of the messages you might see include:
+
+* "This project is out of date, would you like to build it?"
+* "Please specify the name of the executable file to be used for the debug
+ session." This should be the value of the environment variable CHROME_PATH,
+ which is usually supplied as the default value in the dialog.
+* "Debugging information for chrome.exe cannot be found." This is to be
+ expected, you are debugging your module's code, not Chrome.
+* "Open file - security warning. The publisher could not be verified." If
+ Visual Studio is complaining about x86_64-nacl-gdb.exe, that’s our debugger.
+ Let it be.
+
+Once you’ve passed these hurdles, the application starts to run and you’ll see
+activity in three places:
+
+#. A terminal window opens running ``nacl-gdb``.
+#. Chrome launches running your module in a tab.
+#. The Visual Studio output window displays debugging messages when you select
+ the debug output item.
+ Stop the debugging session by closing the Chrome window, or select the stop
+ debugging command from the debug menu. The nacl-gdb window will close when
+ you stop running the program.
+
+Test the nacl-gdb debugger
+--------------------------
+
+Add a breakpoint at the SwapBuffers call in the function MainLoop, which is in
+hello_world.cc.
+
+.. image:: /images/visualstudio2.png
+
+Start the debugger again (F5). This time the existing breakpoint is loaded into
+nacl-gcb and the program will pause there. Type c to continue running. You can
+use gdb commands to set more breakpoints and step through the application. For
+details, see :ref:`Debugging with nacl-gdb <using_gdb>` (scroll down to the end
+of the section to see some commonly used gdb commands).
+
+Test the Visual Studio debugger
+-------------------------------
+
+If you’ve installed the ``PPAPI`` platform, go back to the ``Configuration
+Manager`` and select the ``PPAPI`` platform. This time when Chrome launches the
+``nacl-gdb`` window will not appear; the Visual Studio debugger is fully
+engaged and on the job.
+
+Inspect the platform properties
+-------------------------------
+
+At this point, it may be helpful to take a look at the properties that are
+associated with the PPAPI and Native Client platforms---see the settings in the
+sample project as an example.
+
+Developing for Native Client in Visual Studio
+=============================================
+
+After you’ve installed the add-in and tried the sample project, you’re ready to
+start working with your own code. You can reuse the sample project and the
+PPAPI and Native Client platforms it already has by replacing the source code
+with your own. More likely, you will add the platforms to an existing project,
+or to a new project that you create from scratch.
+
+Adding platforms to a project
+-----------------------------
+
+Follow these steps to add the Native Client and PPAPI platforms to a project:
+
+#. Open the Configuration Manager.
+#. On the row corresponding to your project, click the Platform column dropdown
+ menu and select ``<New...>``.
+#. Select ``PPAPI``, ``NaCl32``, ``NaCl64``, or ``PNaCl`` from the New platform
+ menu.
+#. In most cases, you should select ``<Empty>`` in the “Copy settings from”
+ menu. **Never copy settings between ``PPAPI``, ``NaCl32``, ``NaCl64``,
+ ``NaClARM``, or ``PNaCl`` platforms**. You can copy settings from a Win32
+ platform, if one exists, but afterwards be sure that the project properties
+ are properly set for the new platform, as mentioned in step 6 below.
+#. If you like, check the “Create new solutions platform” box to create a
+ solution platform in addition to a project platform. (This is optional, but
+ it can be convenient since it lets you switch project platforms from the
+ Visual Studio main window by selecting the solution platform that has the
+ same name.)
+#. Review the project properties for the new platform you just added. In most
+ cases, the default properties for each platform should be correct, but it
+ pays to check. Be especially careful about custom properties you may have
+ set beforehand, or copied from a Win32 platform. Also confirm that the
+ Configuration type is correct:
+
+ * ``Dynamic Library`` for ``PPAPI``
+ * ``Application (.pexe)`` for ``PNaCl``
+ * ``Application (.nexe)`` for ``NaCl32``, ``NaCl64``, and ``NaClARM``
+
+Selecting a toolchain
+---------------------
+
+When you build a Native Client module directly from the SDK you can use two
+different toolchains, newlib or glibc. See :doc:`Dynamic Linking and Loading
+with glibc <dynamic-loading>` for a description of the two toolchains and
+instructions on how to build and deploy an application with the glibc
+toolchain. The Native Client platforms offer you the same toolchain choice. You
+can specify which toolchain to use in the project properties, under
+``Configuration Properties > General > Native Client > Toolchain``.
+
+.. Note::
+ :class: note
+
+ Currently, the NaClARM and PNaCl platforms only support the newlib toolchain.
+
+There is no toolchain property for the PPAPI platform. The PPAPI platform uses
+the toolchain and libraries that come with Visual Studio.
+
+Adding libraries to a project
+-----------------------------
+
+If your Native Client application requires libraries that are not included in
+the SDK you must add them to the project properties (under ``Configuration
+Properties > Linker > Input > Additional Dependencies``), just like any other
+Visual Studio project. This list of dependencies is a semi-colon delimited
+list. On the PPAPI platform the library names include the .lib extension (e.g.,
+``ppapi_cpp.lib;ppapi.lib``). On the Native Client platforms the extension is
+excluded (e.g., ``ppapi_cpp;ppapi``).
+
+Running a web server
+--------------------
+
+In order for the Visual Studio add-in to test your Native Client module, you
+must serve the module from a web server. There are two options:
+
+Running your own server
+^^^^^^^^^^^^^^^^^^^^^^^
+
+When you start a debug run Visual Studio launches Chrome and tries to connect
+to the web server at the address found in the Chrome command arguments (see the
+project’s Debugging > Command configuration property), which is usually
+``localhost:$(NaClWebServerPort)``. If you are using your own server be sure to
+specify its address in the command arguments property, and confirm that your
+server is running before starting a debug session. Also be certain that the
+server has all the files it needs to deliver a Native Client module (see
+“Keeping track of all the pieces”, below).
+
+Running the SDK server
+^^^^^^^^^^^^^^^^^^^^^^
+
+If there is no web server running at the specified port, Visual Studio will try
+to launch the simple Python web server that comes with the Native Client SDK.
+It looks for a copy of the server in the SDK itself (at
+``%NACL_SDK_ROOT%\tools\httpd.py``), and in the project directory
+(``$(ProjectDir)/httpd.py``). If the server exists in one of those locations,
+Visual Studio launches the server. The server output appears in Visual Studio’s
+Output window, in the pane named “Native Client Web Server Output”. A server
+launched in this way is terminated when the debugging session ends.
+
+Keeping track of all the pieces
+-------------------------------
+
+No matter where the web server lives or how it’s launched you must make sure
+that it has all the files that your application needs:
+
+* All Native Client applications must have an :ref:`html host page
+ <html_file>`. This file is typically called ``index.html``. The host page
+ must have an embed tag with its type attribute set to
+ ``application-type/x-nacl``. If you plan to use a Native Client platform the
+ embed tag must also include a src attribute pointing to a Native Client
+ manifest (.mnf) file.
+* If you are using a Native Client platform you must include a valid
+ :ref:`manifest file <manifest_file>`. The manifest file points to the .pexe
+ or .nexe files that Visual Studio builds. These will be placed in the
+ directory specified in the project’s ``General > Output Directory``
+ configuration property, which is usually ``$(ProjectDir)$(ToolchainName)``.
+ Visual Studio can use the Native Client SDK script create_nmf.py to
+ automatically generate the manifest file for you. To use this script set the
+ project's ``Linker > General > Create NMF Automatically`` property to "yes."
+
+If you are letting Visual Studio discover and run the SDK server, these files
+should be placed in the project directory. If you are running your own server,
+you must be sure that the host page ``index.html`` is placed in your server’s
+root directory. Remember, if you’re using one of the Native Client platforms
+the paths for the manifest file and .pexe or .nexe files must be reachable from
+the server.
+
+The structure of the manifest file can be more complicated if your application
+uses Native Client's ability to dynamically link libraries. You may have to add
+additional information about dynamically linked libraries to the manifest file
+even if you create it automatically. The use and limitations of the create_nmf
+tool are explained in :ref:`Generating a Native Client manifest file for a
+dynamically linked application <dynamic_loading_manifest>`.
+
+You can look at the example projects in the SDK to see how the index and
+manifest files are organized. The example project ``hello_nacl`` has a
+subdirectory also called ``hello_nacl``. That folder contains ``index.html``
+and ``hello_nacl.nmf``. The nexe file is found in
+``NaCl64\newlib\Debug\hello_nacl_64.nexe``. The ``hello_world_gles`` example
+project contains a subdirectory called `hello_world_gles``. That directory
+contains html files built with both toolchains (``index_glibc.html`` and
+``index_newlib.html``). The .nexe and .nmf files are found in the newlib and
+glibc subfolders. For additional information about the parts of a Native Client
+application, see :doc:`Application Structure
+<../coding/application-structure>`.
+
+Using the debuggers
+-------------------
+
+PPAPI plugins are built natively by Visual Studio’s compiler (MSBuild), and
+work with Visual Studio’s debugger in the usual way. You can set breakpoints in
+the Visual Studio source code files before you begin debugging, and on-the-fly
+while running the program.
+
+NaCl32 and NaClARM executables (.nexe files) cannot be run or debugged from
+Visual Studio.
+
+NaCl64 executables (.nexe files) are compiled using one of the Native Client
+toolchains in the SDK, which create an `ELF-formatted
+<`http://en.wikipedia.org/wiki/Executable_and_Linkable_Format>`_ executable. To
+debug a running .nexe you must use nacl-gdb, which is a command line debugger
+that is not directly integrated with Visual Studio. When you start a debugging
+session running from a NaCl64 platform, Visual Studio automatically launches
+nacl-gdb for you and attaches it to the nexe. Breakpoints that you set in
+Visual Studio before you start debugging are transferred to nacl-gdb
+automatically. During a NaCl debugging session you can only use nacl-gdb
+commands.
+
+The PNaCl platform generates a .pexe file. When you run the debugger add-in
+translates the .pexe file to a .nexe file and runs the resulting binary with
+nacl-gdb attached.
+
+For additional information about nacl-gdb, see :ref:`Debugging with nacl-gdb
+<using_gdb>` (scroll down to the end of the section to see some commonly used
+gdb commands).
+
+Note that you can’t use the Start Without Debugging command (Ctrl+F5) with a
+project in the Debug configuration. If you do, Chrome will hang because the
+Debug platform launches Chrome with the command argument
+``--wait-for-debugger-children`` (in PPAPI) or ``--enable-nacl-debug`` (in a
+Native Client platform). These flags cause Chrome to pause and wait for a
+debugger to attach. If you use the Start Without Debugging command, no debugger
+attaches and Chrome just waits patiently. To use Start Without Debugging,
+switch to the Release configuration, or manually remove the offending argument
+from the ``Command Arguments`` property.
+
+Disable Chrome caching
+----------------------
+
+When you debug with a Native Client platform you might want to :ref:`disable
+Chrome's cache <cache>` to be sure you are testing your latest and greatest
+code.
+
+A warning about PostMessage
+---------------------------
+
+Some Windows libraries define the symbol ``PostMessage`` as ``PostMessageW``.
+This can cause havoc if you are working with the PPAPI platform and you use the
+Pepper ``PostMessage()`` call in your module. Some Pepper API header files
+contain a self-defensive fix that you might need yourself, while you are
+testing on the PPAPI platform. Here it is:
+
+.. naclcode::
+
+ // If Windows defines PostMessage, undef it.
+ #ifdef PostMessage
+ #undef PostMessage
+ #endif
+
+Porting Windows applications to Native Client in Visual Studio
+--------------------------------------------------------------
+
+At Google I/O 2012 we demonstrated how to port a Windows desktop application to
+Native Client in 60 minutes. The `video
+<http://www.youtube.com/watch?v=1zvhs5FR0X8&feature=plcp>`_ is available to
+watch on YouTube. The ``vs_addin/examples`` folder contains a pair of simple
+examples that demonstrate porting process. They are designed to be completed
+in just 5 minutes. The two examples are called ``hello_nacl`` and
+``hello_nacl_cpp``. They are essentially the same, but the former uses the C
+PPAPI interface while the latter uses the C++ API. The application is the
+familiar "Hello, World."
+
+Each example begins with the Windows desktop version running in the ``Win32``
+platform. From there you move to the ``PPAPI`` platform, where you perform a
+series of steps to set up the Native Client framework, use it to run the
+desktop version, and then port the behavior from Windows calls to the PPAPI
+interface. You wind up with a program that uses no Windows functions, which
+can run in either the ``PPAPI`` or the ``NaCl64`` platform.
+
+The example projects use a single source file (``hello_nacl.c`` or
+``hello_nacl_cpp.cpp``). Each step in the porting process is accomplished by
+progressively defining the symbols STEP1 through STEP6 in the source. Inline
+comments explain how each successive step changes the code. View the example
+code to see how it's actually done. Here is a summary of the process:
+
+Win32 Platform
+^^^^^^^^^^^^^^
+
+STEP1 Run the desktop application
+ Begin by running the original Windows application in the Win32 platform.
+
+PPAPI Platform
+^^^^^^^^^^^^^^
+
+STEP2 Launch Chrome with an empty Native Client module
+ Switch to the PPAPI platform and include the code required to initialize a
+ Native Module instance. The code is bare-boned, it does nothing but
+ initialize the module. This step illustrates how Visual Studio handles all
+ the details of launching a web-server and Chrome, and running the Native
+ Client module as a Pepper plugin.
+
+STEP3 Run the desktop application synchronously from the Native Client module
+ The Native Client creates the window directly and then calls WndProc to run
+ the desktop application. Since WndProc spins in its message loop, the call to
+ initialize the module never returns. Close the Hello World window and the
+ module initialization will finish.
+
+STEP4 Running the desktop application and Native Client asynchronously
+ In WndProc replace the message loop with a callback function. Now the app
+ window and the Native Client module are running concurrently.
+
+STEP5 Redirect output to the web page
+ The module initialization code calls initInstanceInBrowserWindow rather than
+ initInstanceInPCWindow. WndProc is no longer used. Instead, postMessage is
+ called to place text (now "Hello, Native Client") in the web page rather than
+ opening and writing to a window. Once you've reached this step you can start
+ porting pieces of the application one feature at a time.
+
+STEP6 Remove all the Windows code
+ All the Windows code is def'd out, proving we are PPAPI-compliant. The
+ functional code that is running is the same as STEP5.
+
+NaCl64 Platform
+^^^^^^^^^^^^^^^
+
+Run the Native Client Module in the NaCl64 platform
+ You are still running the STEP6 code, but as a Native Client module rather
+ than a Pepper plugin.
+
+.. TODO(sbc): port reference section?
diff --git a/native_client_sdk/src/doc/faq.rst b/native_client_sdk/src/doc/faq.rst
index 6ac764dc15..b615e8d0d4 100644
--- a/native_client_sdk/src/doc/faq.rst
+++ b/native_client_sdk/src/doc/faq.rst
@@ -1,5 +1,3 @@
-.. _faq:
-
##########################
Frequently Asked Questions
##########################
@@ -105,7 +103,7 @@ LLVM:
+--------+-----+
| x86-32 | 15% |
+--------+-----+
-| x86-64 | 20% |
+| x86-64 | 25% |
+--------+-----+
| ARM | 10% |
+--------+-----+
@@ -118,11 +116,9 @@ lower overheads whereas very branch-heavy code often performs worse.
For details, see:
* `Adapting Software Fault Isolation to Contemporary CPU Architectures
- <https://nativeclient.googlecode.com/svn/data/site/NaCl_SFI.pdf>`_
- (PDF).
+ <https://nativeclient.googlecode.com/svn/data/site/NaCl_SFI.pdf>`_ (PDF).
* `Native Client: A Sandbox for Portable, Untrusted x86 Code
- <https://src.chromium.org/viewvc/native_client/data/docs_tarball/nacl/googleclient/native_client/documentation/nacl_paper.pdf>`_
- (PDF).
+ <http://research.google.com/pubs/pub34913.html>`_ (PDF).
If your code isn't performing as close to native speed as you'd expect,
:doc:`let us know <help>`!
@@ -161,8 +157,7 @@ What development environment and development operating system do you recommend?
You can develop on Windows, Mac, or Linux, and the resulting Native
Client or Portable Native Client application will run inside the Google
Chrome browser on all those platforms as well as ChromeOS. You can also
-develop on ChromeOS with `Crouton
-<https://github.com/dnschneid/crouton>`_, and we're working on
+develop on ChromeOS with Crouton_, and we're working on
self-hosting a full development environment on Portable Native Client.
Any editor+shell combination should work as well as IDEs like Eclipse,
@@ -190,7 +185,7 @@ Is Native Client open? Is it a standard?
----------------------------------------
Native Client is completely open: the executable format is open and the
-`source code is open <https://code.google.com/p/nativeclient/>`_. Right
+`source code is open <nacl_project_>`_. Right
now the Native Client project is in its early stages, so it's premature
to consider Native Client for standardization.
@@ -239,8 +234,8 @@ or support Fortran with `flang
<https://flang-gsoc.blogspot.ie/2013/09/end-of-gsoc-report.html>`_), or
transpile languages to C/C++ (source-to-source compilation).
-If you're interested in getting other languages working, please contact
-the Native Client team by way of the `native-client-discuss mailing list
+If you're interested in getting other languages working, please contact the
+Native Client team by way of the `native-client-discuss mailing list
<https://groups.google.com/group/native-client-discuss>`_.
Will you only support Chrome? What about other browsers?
@@ -284,13 +279,12 @@ Can I use Native Client for 3D graphics?
Yes. Native Client supports `OpenGL ES 2.0
<https://www.khronos.org/opengles/>`_.
-
To alert the user regarding their hardware platform's 3D feature set
before loading a large NaCl application, see :doc:`Vetting the driver in
Javascript <devguide/coding/3D-graphics>`.
Some GL extensions are exposed to Native Client applications, see the
-`GL ES 2 file
+`GLES2 file
<https://src.chromium.org/viewvc/chrome/trunk/src/ppapi/lib/gl/gles2/gles2.c>`_.
This file is part of the GL wrapper supplied by the library
``ppapi_gles2`` which you'll want to include in your project. In most
@@ -384,8 +378,7 @@ output.
In addition to static analysis of untrusted code, the Native Client
runtime also includes an outer sandbox that mediates system calls. For
more details about both sandboxes, see `Native Client: A Sandbox for
-Portable, Untrusted x86 Code
-<https://src.chromium.org/viewvc/native_client/data/docs_tarball/nacl/googleclient/native_client/documentation/nacl_paper.pdf>`_
+Portable, Untrusted x86 Code <http://research.google.com/pubs/pub34913.html>`_
(PDF).
How does Google know that the safety measures in Native Client are sufficient?
@@ -404,7 +397,6 @@ other popular browser technologies. If you have suggestions for security
improvements, let the team know, by way of the `native-client-discuss
mailing list <https://groups.google.com/group/native-client-discuss>`_.
-
Development
===========
@@ -460,8 +452,7 @@ Is my favorite third-party library available for Native Client?
---------------------------------------------------------------
Google has ported several third-party libraries to Native Client; such
-libraries are available in the `naclports
-<https://code.google.com/p/naclports>`_ project. We encourage you to
+libraries are available in the naclports_ project. We encourage you to
contribute libraries to naclports, and/or to host your own ported
libraries, and to `let the team know about it
<https://groups.google.com/group/native-client-discuss>`_ when you do.
@@ -469,14 +460,12 @@ libraries, and to `let the team know about it
Do all the files in an application need to be served from the same domain?
--------------------------------------------------------------------------
-The ``.html``, ``.nmf``, and ``.nexe`` or ``.pexe`` files must be served
-from the same domain and the Chrome Web Store manifest file (for
-applications installed from the Chrome Web Store) must include the
-correct, verified domain. Other files can be served from the same or
-another domain.
-
-.. TODO This isn't the case anymore. +ncbray?
+The ``.nmf``, and ``.nexe`` or ``.pexe`` files must either be served from the
+same origin as the embedding page or an origin that has been configured
+correctly using CORS_.
+For applications installed from the Chrome Web Store the Web Store manifest
+must include the correct, verified domain of the embedding page.
Portability
===========
@@ -517,13 +506,13 @@ The following kinds of code may be more challenging to port:
* Code that creates processes, including UNIX forks. Creating processes
is not supported for security reasons. However, threads are supported.
* Code that needs to do local file I/O. Native Client is restricted to
- accessing URLs and to local storage in the browser (the Pepper file
- I/O API has access to the same per-application storage that JavaScript
- has via Local Storage). HTML5 File System can be used, among
- others. You can also use nacl_io.
-
-.. TODO More on nacl_io, and a link.
-
+ accessing URLs and to local storage in the browser (the Pepper file I/O API
+ has access to the same per-application storage that JavaScript has via Local
+ Storage). HTML5 File System can be used, among others. For POSIX compatabiliy
+ the Native Client SDK includes a library called nacl_io which allows the
+ application to interact with all these types of files via standard POSIX I/O
+ functions (e.g. open/fopen/read/write/...). See :doc:`Using NaCl I/O
+ <devguide/coding/nacl_io>` for more details.
.. _faq_troubleshooting:
@@ -576,3 +565,7 @@ Here are ways to resolve some common problems that can prevent loading:
select a processor-specific ``.nexe`` goes away with Portable Native
Client.
* If things still aren't working, :doc:`ask for help <help>`!
+
+.. _CORS: http://en.wikipedia.org/wiki/Cross-origin_resource_sharing
+.. _naclports: https://code.google.com/p/naclports
+.. _Crouton: https://github.com/dnschneid/crouton
diff --git a/native_client_sdk/src/doc/help.rst b/native_client_sdk/src/doc/help.rst
index 1d64c0143a..68b5e21645 100644
--- a/native_client_sdk/src/doc/help.rst
+++ b/native_client_sdk/src/doc/help.rst
@@ -28,10 +28,9 @@ Forums
great resource --- check this forum first for answers to your
questions.
* For in-depth technical discussions: `native-client-discuss mailing
- list <http://groups.google.com/group/native-client-discuss>`_ is a
- good group for detailed technical discussions about bugs and other
- Native Client issues.
-* For announcements, follow the `native-client-announce mailing list
+ list <https://groups.google.com/group/native-client-discuss>`_ is a good
+ group for detailed technical discussions about bugs and other Native Client
+ issues. * For announcements, follow the `native-client-announce mailing list
<http://groups.google.com/group/native-client-announce>`_.
* For 140 character goodness follow `@nativeclient
<https://twitter.com/nativeclient>`_ on Twitter.
@@ -46,8 +45,7 @@ To report a new issue:
#. Go to the `Native Client issue tracker
<https://code.google.com/p/nativeclient/issues>`_ for a Native Client
bug, or the `Chromium issue tracker
- <https://code.google.com/p/nativeclient/issues>`_ for a
- Chrome/Chromium bug.
+ <https://code.google.com/p/chromium/issues>`_ for a Chrome/Chromium bug.
#. Before you report an issue, search to see if your issue has already
been reported. You can add a comment to an existing issue if you have
additional information.
diff --git a/native_client_sdk/src/doc/images/fileioexample.png b/native_client_sdk/src/doc/images/fileioexample.png
index b6ba42c670..114ccb8375 100644
--- a/native_client_sdk/src/doc/images/fileioexample.png
+++ b/native_client_sdk/src/doc/images/fileioexample.png
Binary files differ
diff --git a/native_client_sdk/src/doc/index.rst b/native_client_sdk/src/doc/index.rst
index 194a00bda8..2b32153fd8 100644
--- a/native_client_sdk/src/doc/index.rst
+++ b/native_client_sdk/src/doc/index.rst
@@ -6,7 +6,6 @@ Contents:
.. toctree::
:maxdepth: 2
- rest-devsite-examples.rst
overview.rst
quick-start.rst
nacl-and-pnacl.rst
@@ -15,7 +14,6 @@ Contents:
sdk/download.rst
sdk/examples.rst
sdk/release-notes.rst
- sdk/release-notes.rst
devguide/index.rst
devguide/tutorial/index.rst
devguide/tutorial/tutorial-part1.rst
@@ -31,7 +29,7 @@ Contents:
devguide/coding/audio.rst
devguide/coding/application-structure.rst
devguide/coding/native-client-modules.rst
- devguide/coding/FileIO.rst
+ devguide/coding/file-io.rst
devguide/coding/nacl_io.rst
devguide/coding/message-system.rst
devguide/coding/progress-events.rst
diff --git a/native_client_sdk/src/doc/overview.rst b/native_client_sdk/src/doc/overview.rst
index e8ad2d743e..d1c6e891f6 100644
--- a/native_client_sdk/src/doc/overview.rst
+++ b/native_client_sdk/src/doc/overview.rst
@@ -243,7 +243,7 @@ capabilities, including:
* :doc:`Talking to the JavaScript code in your application
<devguide/coding/message-system>` from the C++ code in your NaCl module.
-* :doc:`Doing file I/O <devguide/coding/FileIO>`.
+* :doc:`Doing file I/O <devguide/coding/file-io>`.
* :doc:`Playing audio <devguide/coding/audio>`.
* :doc:`Rendering 3D graphics <devguide/coding/3D-graphics>`.
diff --git a/native_client_sdk/src/doc/rest-devsite-examples.rst b/native_client_sdk/src/doc/rest-devsite-examples.rst
index 3b060a5319..eeaf505bfe 100644
--- a/native_client_sdk/src/doc/rest-devsite-examples.rst
+++ b/native_client_sdk/src/doc/rest-devsite-examples.rst
@@ -1,5 +1,7 @@
.. _getting_started:
+:orphan:
+
####################################################
Examples of ReST markup for devsite (Document title)
####################################################
@@ -183,6 +185,20 @@ Sub-sub-subsection heading
It's probably not the best idea to go this far (renders to ``<h5>``).
+Expandable sections
+===================
+
+The devsite can render expandable sections when a special ``class`` is applied.
+This can be achieved by specifying the ``rst-class`` immediately before a
+section (or any other element), as follows:
+
+.. rst-class:: expandable
+
+Expandable Section
+------------------
+
+Look, ma! I'm expandable!
+
Lists
=====
diff --git a/native_client_sdk/src/doc/sdk/_toc.yaml b/native_client_sdk/src/doc/sdk/_toc.yaml
deleted file mode 100644
index d889d5ec97..0000000000
--- a/native_client_sdk/src/doc/sdk/_toc.yaml
+++ /dev/null
@@ -1,10 +0,0 @@
-toc:
-- title: "SDK"
- path: /native-client/${folder}/sdk
- section:
- - title: "Download"
- path: /native-client/${folder}/sdk/download
- - title: "Examples"
- path: /native-client/${folder}/sdk/sdk-examples
- - title: "Release Notes"
- path: /native-client/${folder}/sdk/release-notes
diff --git a/native_client_sdk/src/doc/sdk/examples.rst b/native_client_sdk/src/doc/sdk/examples.rst
index 22404d4add..a0b567adcb 100644
--- a/native_client_sdk/src/doc/sdk/examples.rst
+++ b/native_client_sdk/src/doc/sdk/examples.rst
@@ -184,20 +184,30 @@ this::
Set the CHROME_PATH environment variable to the location of your Chrome
executable.
-On Windows::
+* On Windows:
- > set CHROME_PATH=<Path to chrome.exe>
+ The default install location of Chrome is
+ ``C:\Program Files (x86)\Google\Chrome\Application\chrome.exe`` for Chrome
+ stable and
+ ``C:\Users\<username>\AppData\Local\Google\Chrome SxS\Application\chrome.exe``
+ for Chrome Canary; try looking in those directories first::
-On Linux::
+ > set CHROME_PATH=<Path to chrome.exe>
- $ export CHROME_PATH=<Path to google-chrome>
+* On Linux::
-On Mac::
+ $ export CHROME_PATH=<Path to google-chrome>
- $ export CHROME_PATH=<Path to chrome>
+* On Mac:
-.. **TODO(binji):** use default Chrome paths here, especially
-.. important for Mac:
+ The default install location of Chrome is
+ ``/Applications/Google Chrome.app/Contents/MacOS/Google Chrome`` for
+ Chrome Stable and
+ ``Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary``
+ for Chrome Canary. Note that you have to reference the executable inside the
+ application bundle, not the top-level ``.app`` directory::
+
+ $ export CHROME_PATH=<Path to Google Chrome>
You can run via a different toolchain or configuration by using the
``TOOLCHAIN`` and ``CONFIG`` parameters to make::
diff --git a/native_client_sdk/src/doc/sdk/release-notes.rst b/native_client_sdk/src/doc/sdk/release-notes.rst
index 9ff317ce5a..5596050459 100644
--- a/native_client_sdk/src/doc/sdk/release-notes.rst
+++ b/native_client_sdk/src/doc/sdk/release-notes.rst
@@ -7,6 +7,24 @@ Release Notes
This page provides notes for all releases of the Native Client SDK (including
releases that have been or will be published subsequent to Pepper 28).
+PNaCl enabled by default in Chrome 31 (12 Nov 2013)
+===================================================
+
+* Portable Native Client (PNaCl) is enabled by default in Chrome 31. See
+ :doc:`NaCl and PNaCl </nacl-and-pnacl>` for details on the differences between
+ PNaCl and NaCl.
+* The PNaCl ABI has changed from the preview release in Chrome
+ version 30. If you have pexes built with the Native Client SDK version 30,
+ please recompile them with the newest SDK to run in Chrome 31. As a general
+ rule, it is always recommended to build applications with the latest Native
+ Client SDK. The PNaCl ABI will remain stable starting with the release of
+ Chrome 31.
+
+Additional changes:
+
+* Updates to the Pepper API, including socket and network support.
+* Improved socket support in nacl_io.
+
PNaCl in Chrome 30 Dev channel (01 Aug 2013)
============================================
diff --git a/native_client_sdk/src/examples/tutorial/dlopen/dlopen.cc b/native_client_sdk/src/examples/tutorial/dlopen/dlopen.cc
index 8b5df974f9..81aa015342 100644
--- a/native_client_sdk/src/examples/tutorial/dlopen/dlopen.cc
+++ b/native_client_sdk/src/examples/tutorial/dlopen/dlopen.cc
@@ -50,6 +50,7 @@ class DlOpenInstance : public pp::Instance {
void logmsg(const char* pStr) {
PostMessage(pp::Var(std::string("log:") + pStr));
fprintf(stdout, pStr);
+ fprintf(stdout, "\n");
}
// Initialize the module, staring a worker thread to load the shared object.
@@ -60,9 +61,9 @@ class DlOpenInstance : public pp::Instance {
// server.
mount("", "/http", "httpfs", 0, "");
- logmsg("Spawning thread to cache .so files...\n");
+ logmsg("Spawning thread to cache .so files...");
if (pthread_create(&tid_, NULL, LoadLibrariesOnWorker, this)) {
- logmsg("ERROR; pthread_create() failed.\n");
+ logmsg("ERROR; pthread_create() failed.");
return false;
}
return true;
@@ -72,73 +73,62 @@ class DlOpenInstance : public pp::Instance {
// the shared object. In addition, note that this function does NOT call
// dlclose, which would close the shared object and unload it from memory.
void LoadLibrary() {
- const char reverse_so_path[] =
- "/http/glibc/" CONFIG_NAME "/libreverse_" NACL_ARCH ".so";
- const int32_t IMMEDIATELY = 0;
eightball_so_ = dlopen("libeightball.so", RTLD_LAZY);
- reverse_so_ = dlopen(reverse_so_path, RTLD_LAZY);
- pp::CompletionCallback cc(LoadDoneCB, this);
- pp::Module::Get()->core()->CallOnMainThread(IMMEDIATELY, cc, 0);
- }
-
- // This function will run on the main thread and use the handle it stored by
- // the worker thread, assuming it successfully loaded, to get a pointer to the
- // message function in the shared object.
- void UseLibrary() {
if (eightball_so_ != NULL) {
intptr_t offset = (intptr_t) dlsym(eightball_so_, "Magic8Ball");
eightball_ = (TYPE_eightball) offset;
if (NULL == eightball_) {
std::string message = "dlsym() returned NULL: ";
message += dlerror();
- message += "\n";
logmsg(message.c_str());
return;
}
- logmsg("Loaded libeightball.so\n");
+ logmsg("Loaded libeightball.so");
} else {
- logmsg("libeightball.so did not load\n");
+ logmsg("libeightball.so did not load");
}
+ const char reverse_so_path[] =
+ "/http/glibc/" CONFIG_NAME "/libreverse_" NACL_ARCH ".so";
+ reverse_so_ = dlopen(reverse_so_path, RTLD_LAZY);
if (reverse_so_ != NULL) {
intptr_t offset = (intptr_t) dlsym(reverse_so_, "Reverse");
reverse_ = (TYPE_reverse) offset;
if (NULL == reverse_) {
std::string message = "dlsym() returned NULL: ";
message += dlerror();
- message += "\n";
logmsg(message.c_str());
return;
}
- logmsg("Loaded libreverse.so\n");
+ logmsg("Loaded libreverse.so");
} else {
- logmsg("libreverse.so did not load\n");
+ logmsg("libreverse.so did not load");
}
}
// Called by the browser to handle the postMessage() call in Javascript.
virtual void HandleMessage(const pp::Var& var_message) {
if (!var_message.is_string()) {
- logmsg("Message is not a string.\n");
+ logmsg("Message is not a string.");
return;
}
std::string message = var_message.AsString();
if (message == "eightball") {
if (NULL == eightball_) {
- logmsg("Eightball library not loaded\n");
+ logmsg("Eightball library not loaded");
return;
}
std::string ballmessage = "The Magic 8-Ball says: ";
ballmessage += eightball_();
- ballmessage += "!\n";
+ ballmessage += "!";
logmsg(ballmessage.c_str());
} else if (message.find("reverse:") == 0) {
if (NULL == reverse_) {
- logmsg("Reverse library not loaded\n");
+ logmsg("Reverse library not loaded");
return;
}
@@ -147,14 +137,14 @@ class DlOpenInstance : public pp::Instance {
std::string message = "Your string reversed: \"";
message += result;
- message += "\"\n";
+ message += "\"";
free(result);
logmsg(message.c_str());
} else {
std::string errormsg = "Unexpected message: ";
- errormsg += message + "\n";
+ errormsg += message;
logmsg(errormsg.c_str());
}
}
@@ -165,11 +155,6 @@ class DlOpenInstance : public pp::Instance {
return NULL;
}
- static void LoadDoneCB(void* pInst, int32_t result) {
- DlOpenInstance* inst = static_cast<DlOpenInstance*>(pInst);
- inst->UseLibrary();
- }
-
private:
void* eightball_so_;
void* reverse_so_;
diff --git a/native_client_sdk/src/examples/tutorial/dlopen/example.js b/native_client_sdk/src/examples/tutorial/dlopen/example.js
index 5e1b1e3cd9..6d10e4d6c1 100644
--- a/native_client_sdk/src/examples/tutorial/dlopen/example.js
+++ b/native_client_sdk/src/examples/tutorial/dlopen/example.js
@@ -19,7 +19,7 @@ function askBall(event) {
var questionEl = document.getElementById('question');
var query = questionEl.value;
questionEl.value = '';
- common.logMessage('You asked: ' + query + '\n');
+ common.logMessage('You asked: ' + query);
common.naclModule.postMessage('eightball');
event.preventDefault();
}
@@ -28,6 +28,6 @@ function reverseString(event) {
var questionEl = document.getElementById('question');
var query = questionEl.value;
questionEl.value = '';
- common.logMessage('Reversing: ' + query + '\n');
+ common.logMessage('Reversing: ' + query);
common.naclModule.postMessage('reverse:' + query);
}
diff --git a/native_client_sdk/src/getting_started/part1/index.html b/native_client_sdk/src/getting_started/part1/index.html
index d4af2bbece..5ebd3610dc 100644
--- a/native_client_sdk/src/getting_started/part1/index.html
+++ b/native_client_sdk/src/getting_started/part1/index.html
@@ -1,12 +1,10 @@
<!DOCTYPE html>
<html>
-
<!--
- Copyright (c) 2013 The Native Client Authors. All rights reserved.
+ Copyright (c) 2013 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->
-
<head>
<title>hello_tutorial</title>
diff --git a/native_client_sdk/src/gonacl_appengine/README b/native_client_sdk/src/gonacl_appengine/README
index 22db5579d1..911ef15d6b 100644
--- a/native_client_sdk/src/gonacl_appengine/README
+++ b/native_client_sdk/src/gonacl_appengine/README
@@ -24,7 +24,7 @@ To Update App Engine (HTML/JS)
To upload, run this from the root directory of the App Engine SDK::
- $ ./appcfg.py update <path-to-this-dir>
+ $ ./appcfg.py update <path-to-this-dir>
It probably makes sense to bump the application version in app.yaml for each
upload, as it lets us use App Engine's versioning. The newly uploaded version
@@ -44,22 +44,25 @@ To publish a new version:
1. Make and land your change to the demo, found in ``src/<demo-name>``.
2. Wait for the linux SDK builder to build and upload your change. You can see
- what's available by using gsutil::
+ what's available in the browser at::
- $ gsutil ls gs://gonacl/demos/continuous
+ http://gsdview.appspot.com/gonacl/demos/continuous/
- gs://gonacl/demos/continuous/229855/
- gs://gonacl/demos/continuous/229860/
- ...
+ Or by using gsutil::
-3. Update the URLs to use this new revision in each demo's JavaScript files:
+ $ gsutil ls gs://gonacl/demos/continuous/
+
+3. Use 'make publish REVISION=<REV>' in the ``src`` directory to publish the
+ revision.
+
+4. Update the URLs to use this new revision in each demo's JavaScript files:
* For ``earth``, this is found in ``/static/pnacl-demo-earth/example.js``, in
the ``getDataURL`` function.
-
* For ``bullet``, this is found in ``/static/pnacl-demo-bullet/main.js``, in
the ``pageDidLoad`` function.
+ * For ``lua``, this is found in ``/static/pnacl-demo-lua/lua.js``.
-4. Land a CL with these changes.
+5. Land a CL with these changes.
-5. Update App Engine, using the instructions above.
+6. Update App Engine, using the instructions above.
diff --git a/native_client_sdk/src/gonacl_appengine/src/Makefile b/native_client_sdk/src/gonacl_appengine/src/Makefile
index aef5995d1c..b2c88118fc 100644
--- a/native_client_sdk/src/gonacl_appengine/src/Makefile
+++ b/native_client_sdk/src/gonacl_appengine/src/Makefile
@@ -53,7 +53,7 @@ all:
#
# All projects built by this Makefile
#
-PROJECTS = earth voronoi life bullet lua
+PROJECTS = earth voronoi life bullet lua smoothlife cube
GS_URL_CONTINUOUS = gs://gonacl/demos/continuous
GS_URL_PUBLISH = gs://gonacl/demos/publish
@@ -142,6 +142,35 @@ life_TGTS = $(life_TGT_DIR)/life.pexe \
$(life_TGTS): $(life_SRCS)
$(MAKE) -C life TOOLCHAIN=pnacl CONFIG=Release
+#
+# SmoothLife
+#
+smoothlife_SRC_DIR = smoothlife
+smoothlife_TGT_DIR = smoothlife/out
+smoothlife_SRCS = $(smoothlife_SRC_DIR)/build.sh
+smoothlife_TGTS = $(smoothlife_TGT_DIR)/smoothnacl.pexe \
+ $(smoothlife_TGT_DIR)/smoothnacl.nmf
+
+$(smoothlife_TGTS): $(smoothlife_SRCS)
+ smoothlife/build.sh
+
+
+#
+# Rotating Cube
+#
+cube_SRC_DIR = cube
+cube_TGT_DIR = cube/pnacl/Release
+cube_SRCS = $(cube_SRC_DIR)/cube.cc \
+ $(cube_SRC_DIR)/matrix.cc \
+ $(cube_SRC_DIR)/matrix.h \
+ $(cube_SRC_DIR)/texture.cc \
+ $(cube_SRC_DIR)/Makefile
+cube_TGTS = $(cube_TGT_DIR)/cube.pexe \
+ $(cube_TGT_DIR)/cube.nmf
+
+$(cube_TGTS): $(cube_SRCS)
+ $(MAKE) -C cube TOOLCHAIN=pnacl CONFIG=Release
+
###############################################################################
SHELL = /bin/bash
@@ -179,9 +208,9 @@ endif
#
define PROJECT
$(1)_UPLOADS = $$($(1)_TGTS) $$($(1)_EXTRA_UPLOADS)
- $(1)_CONTINUOUS_DIR = $(GS_URL_CONTINUOUS)/$(REVISION)/$(1)
- $(1)_CONTINUOUS_UPLOADS = $$(addprefix $$($(1)_CONTINUOUS_DIR)/,$$(notdir $$($(1)_UPLOADS)))
- $(1)_PUBLISH_DIR = $(GS_URL_PUBLISH)/$(REVISION)/$(1)
+ $(1)_CONTINUOUS_DIR = $(GS_URL_CONTINUOUS)/$(REVISION)/$(1)/
+ $(1)_CONTINUOUS_UPLOADS = $$(addprefix $$($(1)_CONTINUOUS_DIR),$$(notdir $$($(1)_UPLOADS)))
+ $(1)_PUBLISH_DIR = $(GS_URL_PUBLISH)/$(REVISION)/$(1)/
all: $$($(1)_TGTS)
@@ -224,7 +253,7 @@ publish-$(1): revision-check
exit 1; \
fi;
@echo "Publishing..."
- @$(GSUTIL) cp -p -q $$($(1)_CONTINUOUS_UPLOADS) $$($(1)_PUBLISH_DIR)/
+ @$(GSUTIL) cp -q -p $$($(1)_CONTINUOUS_UPLOADS) $$($(1)_PUBLISH_DIR)
@echo "Done."
publish: publish-$(1)
diff --git a/native_client_sdk/src/gonacl_appengine/src/bullet/build.sh b/native_client_sdk/src/gonacl_appengine/src/bullet/build.sh
index 5ac21851ef..5f6152e95b 100755
--- a/native_client_sdk/src/gonacl_appengine/src/bullet/build.sh
+++ b/native_client_sdk/src/gonacl_appengine/src/bullet/build.sh
@@ -1,5 +1,5 @@
#!/bin/bash
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
diff --git a/native_client_sdk/src/gonacl_appengine/src/cube/Makefile b/native_client_sdk/src/gonacl_appengine/src/cube/Makefile
new file mode 100644
index 0000000000..b2b247ff29
--- /dev/null
+++ b/native_client_sdk/src/gonacl_appengine/src/cube/Makefile
@@ -0,0 +1,33 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# GNU Makefile based on shared rules provided by the Native Client SDK.
+# See README.Makefiles for more details.
+
+VALID_TOOLCHAINS := newlib glibc pnacl
+
+NACL_SDK_ROOT ?= $(abspath $(CURDIR)/../../..)
+include $(NACL_SDK_ROOT)/tools/common.mk
+
+TARGET = cube
+LIBS = $(DEPS) ppapi_gles2 ppapi_cpp ppapi pthread
+
+CFLAGS = -Wall
+SOURCES = \
+ cube.cc \
+ texture.cc \
+ matrix.cc
+
+# Build rules generated by macros from common.mk:
+
+$(foreach src,$(SOURCES),$(eval $(call COMPILE_RULE,$(src),$(CFLAGS))))
+
+ifeq ($(CONFIG),Release)
+$(eval $(call LINK_RULE,$(TARGET)_unstripped,$(SOURCES),$(LIBS),$(DEPS)))
+$(eval $(call STRIP_RULE,$(TARGET),$(TARGET)_unstripped))
+else
+$(eval $(call LINK_RULE,$(TARGET),$(SOURCES),$(LIBS),$(DEPS)))
+endif
+
+$(eval $(call NMF_RULE,$(TARGET),))
diff --git a/native_client_sdk/src/gonacl_appengine/src/cube/cube.cc b/native_client_sdk/src/gonacl_appengine/src/cube/cube.cc
new file mode 100644
index 0000000000..36e6596fb2
--- /dev/null
+++ b/native_client_sdk/src/gonacl_appengine/src/cube/cube.cc
@@ -0,0 +1,510 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <GLES2/gl2.h>
+#include <math.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "matrix.h"
+#include "ppapi/cpp/graphics_3d.h"
+#include "ppapi/cpp/instance.h"
+#include "ppapi/cpp/module.h"
+#include "ppapi/cpp/var.h"
+#include "ppapi/cpp/var_array.h"
+#include "ppapi/lib/gl/gles2/gl2ext_ppapi.h"
+#include "ppapi/utility/completion_callback_factory.h"
+
+#ifdef WIN32
+#undef PostMessage
+// Allow 'this' in initializer list
+#pragma warning(disable : 4355)
+#endif
+
+extern const uint8_t kRLETextureData[];
+extern const size_t kRLETextureDataLength;
+
+namespace {
+
+const float kMinFovY = 45.0f;
+const float kZNear = 1.0f;
+const float kZFar = 10.0f;
+const float kCameraZ = -4.0f;
+const float kXAngleDelta = 2.0f;
+const float kYAngleDelta = 0.5f;
+
+const size_t kTextureDataLength = 128 * 128 * 3; // 128x128, 3 Bytes/pixel.
+
+// The decompressed data is written here.
+uint8_t g_texture_data[kTextureDataLength];
+
+void DecompressTexture() {
+ // The image is first encoded with a very simple RLE scheme:
+ // <value0> <count0> <value1> <count1> ...
+ // Because a <count> of 0 is useless, we use it to represent 256.
+ //
+ // It is then Base64 encoded to make it use only printable characters (it
+ // stores more easily in a source file that way).
+ //
+ // To decompress, we have to reverse the process.
+ static const uint8_t kBase64Decode[256] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 63,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0,
+ 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
+ };
+ const uint8_t* input = &kRLETextureData[0];
+ const uint8_t* const input_end = &kRLETextureData[kRLETextureDataLength];
+ uint8_t* output = &g_texture_data[0];
+#ifndef NDEBUG
+ const uint8_t* const output_end = &g_texture_data[kTextureDataLength];
+#endif
+
+ uint8_t decoded[4];
+ int decoded_count = 0;
+
+ while (input < input_end || decoded_count > 0) {
+ if (decoded_count < 2) {
+ assert(input + 4 <= input_end);
+ // Grab four base-64 encoded (6-bit) bytes.
+ uint32_t data = 0;
+ data |= (kBase64Decode[*input++] << 18);
+ data |= (kBase64Decode[*input++] << 12);
+ data |= (kBase64Decode[*input++] << 6);
+ data |= (kBase64Decode[*input++] );
+ // And decode it to 3 (8-bit) bytes.
+ decoded[decoded_count++] = (data >> 16) & 0xff;
+ decoded[decoded_count++] = (data >> 8) & 0xff;
+ decoded[decoded_count++] = (data ) & 0xff;
+
+ // = is the base64 end marker. Remove decoded bytes if we see any.
+ if (input[-1] == '=') decoded_count--;
+ if (input[-2] == '=') decoded_count--;
+ }
+
+ int value = decoded[0];
+ int count = decoded[1];
+ decoded_count -= 2;
+ // Move the other decoded bytes (if any) down.
+ decoded[0] = decoded[2];
+ decoded[1] = decoded[3];
+
+ // Expand the RLE data.
+ if (count == 0)
+ count = 256;
+ assert(output <= output_end);
+ memset(output, value, count);
+ output += count;
+ }
+ assert(output == output_end);
+}
+
+GLuint CompileShader(GLenum type, const char* data) {
+ GLuint shader = glCreateShader(type);
+ glShaderSource(shader, 1, &data, NULL);
+ glCompileShader(shader);
+
+ GLint compile_status;
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status);
+ if (compile_status != GL_TRUE) {
+ // Shader failed to compile, let's see what the error is.
+ char buffer[1024];
+ GLsizei length;
+ glGetShaderInfoLog(shader, sizeof(buffer), &length, &buffer[0]);
+ fprintf(stderr, "Shader failed to compile: %s\n", buffer);
+ return 0;
+ }
+
+ return shader;
+}
+
+GLuint LinkProgram(GLuint frag_shader, GLuint vert_shader) {
+ GLuint program = glCreateProgram();
+ glAttachShader(program, frag_shader);
+ glAttachShader(program, vert_shader);
+ glLinkProgram(program);
+
+ GLint link_status;
+ glGetProgramiv(program, GL_LINK_STATUS, &link_status);
+ if (link_status != GL_TRUE) {
+ // Program failed to link, let's see what the error is.
+ char buffer[1024];
+ GLsizei length;
+ glGetProgramInfoLog(program, sizeof(buffer), &length, &buffer[0]);
+ fprintf(stderr, "Program failed to link: %s\n", buffer);
+ return 0;
+ }
+
+ return program;
+}
+
+const char kFragShaderSource[] =
+ "precision mediump float;\n"
+ "varying vec3 v_color;\n"
+ "varying vec2 v_texcoord;\n"
+ "uniform sampler2D u_texture;\n"
+ "void main() {\n"
+ " gl_FragColor = texture2D(u_texture, v_texcoord);\n"
+ " gl_FragColor += vec4(v_color, 1);\n"
+ "}\n";
+
+const char kVertexShaderSource[] =
+ "uniform mat4 u_mvp;\n"
+ "attribute vec2 a_texcoord;\n"
+ "attribute vec3 a_color;\n"
+ "attribute vec4 a_position;\n"
+ "varying vec3 v_color;\n"
+ "varying vec2 v_texcoord;\n"
+ "void main() {\n"
+ " gl_Position = u_mvp * a_position;\n"
+ " v_color = a_color;\n"
+ " v_texcoord = a_texcoord;\n"
+ "}\n";
+
+struct Vertex {
+ float loc[3];
+ float color[3];
+ float tex[2];
+};
+
+const Vertex kCubeVerts[24] = {
+ // +Z (red arrow, black tip)
+ {{-1.0, -1.0, +1.0}, {0.0, 0.0, 0.0}, {1.0, 0.0}},
+ {{+1.0, -1.0, +1.0}, {0.0, 0.0, 0.0}, {0.0, 0.0}},
+ {{+1.0, +1.0, +1.0}, {0.5, 0.0, 0.0}, {0.0, 1.0}},
+ {{-1.0, +1.0, +1.0}, {0.5, 0.0, 0.0}, {1.0, 1.0}},
+
+ // +X (green arrow, black tip)
+ {{+1.0, -1.0, -1.0}, {0.0, 0.0, 0.0}, {1.0, 0.0}},
+ {{+1.0, +1.0, -1.0}, {0.0, 0.0, 0.0}, {0.0, 0.0}},
+ {{+1.0, +1.0, +1.0}, {0.0, 0.5, 0.0}, {0.0, 1.0}},
+ {{+1.0, -1.0, +1.0}, {0.0, 0.5, 0.0}, {1.0, 1.0}},
+
+ // +Y (blue arrow, black tip)
+ {{-1.0, +1.0, -1.0}, {0.0, 0.0, 0.0}, {1.0, 0.0}},
+ {{-1.0, +1.0, +1.0}, {0.0, 0.0, 0.0}, {0.0, 0.0}},
+ {{+1.0, +1.0, +1.0}, {0.0, 0.0, 0.5}, {0.0, 1.0}},
+ {{+1.0, +1.0, -1.0}, {0.0, 0.0, 0.5}, {1.0, 1.0}},
+
+ // -Z (red arrow, red tip)
+ {{+1.0, +1.0, -1.0}, {0.0, 0.0, 0.0}, {1.0, 1.0}},
+ {{-1.0, +1.0, -1.0}, {0.0, 0.0, 0.0}, {0.0, 1.0}},
+ {{-1.0, -1.0, -1.0}, {1.0, 0.0, 0.0}, {0.0, 0.0}},
+ {{+1.0, -1.0, -1.0}, {1.0, 0.0, 0.0}, {1.0, 0.0}},
+
+ // -X (green arrow, green tip)
+ {{-1.0, +1.0, +1.0}, {0.0, 0.0, 0.0}, {1.0, 1.0}},
+ {{-1.0, -1.0, +1.0}, {0.0, 0.0, 0.0}, {0.0, 1.0}},
+ {{-1.0, -1.0, -1.0}, {0.0, 1.0, 0.0}, {0.0, 0.0}},
+ {{-1.0, +1.0, -1.0}, {0.0, 1.0, 0.0}, {1.0, 0.0}},
+
+ // -Y (blue arrow, blue tip)
+ {{+1.0, -1.0, +1.0}, {0.0, 0.0, 0.0}, {1.0, 1.0}},
+ {{+1.0, -1.0, -1.0}, {0.0, 0.0, 0.0}, {0.0, 1.0}},
+ {{-1.0, -1.0, -1.0}, {0.0, 0.0, 1.0}, {0.0, 0.0}},
+ {{-1.0, -1.0, +1.0}, {0.0, 0.0, 1.0}, {1.0, 0.0}},
+};
+
+const GLubyte kCubeIndexes[36] = {
+ 2, 1, 0, 3, 2, 0,
+ 6, 5, 4, 7, 6, 4,
+ 10, 9, 8, 11, 10, 8,
+ 14, 13, 12, 15, 14, 12,
+ 18, 17, 16, 19, 18, 16,
+ 22, 21, 20, 23, 22, 20,
+};
+
+} // namespace
+
+
+class CubeInstance : public pp::Instance {
+ public:
+ explicit CubeInstance(PP_Instance instance)
+ : pp::Instance(instance),
+ callback_factory_(this),
+ width_(0),
+ height_(0),
+ frag_shader_(0),
+ vertex_shader_(0),
+ program_(0),
+ texture_loc_(0),
+ position_loc_(0),
+ color_loc_(0),
+ mvp_loc_(0),
+ x_angle_(0),
+ y_angle_(0),
+ animating_(true) {}
+
+ virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]) {
+ return true;
+ }
+
+ virtual void DidChangeView(const pp::View& view) {
+ int32_t new_width = view.GetRect().width();
+ int32_t new_height = view.GetRect().height();
+
+ if (context_.is_null()) {
+ if (!InitGL(new_width, new_height)) {
+ // failed.
+ return;
+ }
+
+ InitShaders();
+ InitBuffers();
+ InitTexture();
+ MainLoop(0);
+ } else {
+ // Resize the buffers to the new size of the module.
+ int32_t result = context_.ResizeBuffers(new_width, new_height);
+ if (result < 0) {
+ fprintf(stderr,
+ "Unable to resize buffers to %d x %d!\n",
+ new_width,
+ new_height);
+ return;
+ }
+ }
+
+ width_ = new_width;
+ height_ = new_height;
+ glViewport(0, 0, width_, height_);
+ }
+
+ virtual void HandleMessage(const pp::Var& message) {
+ // A bool message sets whether the cube is animating or not.
+ if (message.is_bool()) {
+ animating_ = message.AsBool();
+ return;
+ }
+
+ // An array message sets the current x and y rotation.
+ if (!message.is_array()) {
+ fprintf(stderr, "Expected array message.\n");
+ return;
+ }
+
+ pp::VarArray array(message);
+ if (array.GetLength() != 2) {
+ fprintf(stderr, "Expected array of length 2.\n");
+ return;
+ }
+
+ pp::Var x_angle_var = array.Get(0);
+ if (x_angle_var.is_int()) {
+ x_angle_ = x_angle_var.AsInt();
+ } else if (x_angle_var.is_double()) {
+ x_angle_ = x_angle_var.AsDouble();
+ } else {
+ fprintf(stderr, "Expected value to be an int or double.\n");
+ }
+
+ pp::Var y_angle_var = array.Get(1);
+ if (y_angle_var.is_int()) {
+ y_angle_ = y_angle_var.AsInt();
+ } else if (y_angle_var.is_double()) {
+ y_angle_ = y_angle_var.AsDouble();
+ } else {
+ fprintf(stderr, "Expected value to be an int or double.\n");
+ }
+ }
+
+ private:
+ bool InitGL(int32_t new_width, int32_t new_height) {
+ if (!glInitializePPAPI(pp::Module::Get()->get_browser_interface())) {
+ fprintf(stderr, "Unable to initialize GL PPAPI!\n");
+ return false;
+ }
+
+ const int32_t attrib_list[] = {
+ PP_GRAPHICS3DATTRIB_ALPHA_SIZE, 8,
+ PP_GRAPHICS3DATTRIB_DEPTH_SIZE, 24,
+ PP_GRAPHICS3DATTRIB_WIDTH, new_width,
+ PP_GRAPHICS3DATTRIB_HEIGHT, new_height,
+ PP_GRAPHICS3DATTRIB_NONE
+ };
+
+ context_ = pp::Graphics3D(this, attrib_list);
+ if (!BindGraphics(context_)) {
+ fprintf(stderr, "Unable to bind 3d context!\n");
+ context_ = pp::Graphics3D();
+ glSetCurrentContextPPAPI(0);
+ return false;
+ }
+
+ glSetCurrentContextPPAPI(context_.pp_resource());
+ return true;
+ }
+
+ void InitShaders() {
+ frag_shader_ = CompileShader(GL_FRAGMENT_SHADER, kFragShaderSource);
+ if (!frag_shader_)
+ return;
+
+ vertex_shader_ = CompileShader(GL_VERTEX_SHADER, kVertexShaderSource);
+ if (!vertex_shader_)
+ return;
+
+ program_ = LinkProgram(frag_shader_, vertex_shader_);
+ if (!program_)
+ return;
+
+ texture_loc_ = glGetUniformLocation(program_, "u_texture");
+ position_loc_ = glGetAttribLocation(program_, "a_position");
+ texcoord_loc_ = glGetAttribLocation(program_, "a_texcoord");
+ color_loc_ = glGetAttribLocation(program_, "a_color");
+ mvp_loc_ = glGetUniformLocation(program_, "u_mvp");
+ }
+
+ void InitBuffers() {
+ glGenBuffers(1, &vertex_buffer_);
+ glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(kCubeVerts), &kCubeVerts[0],
+ GL_STATIC_DRAW);
+
+ glGenBuffers(1, &index_buffer_);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer_);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(kCubeIndexes),
+ &kCubeIndexes[0], GL_STATIC_DRAW);
+ }
+
+ void InitTexture() {
+ DecompressTexture();
+ glGenTextures(1, &texture_);
+ glBindTexture(GL_TEXTURE_2D, texture_);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexImage2D(GL_TEXTURE_2D,
+ 0,
+ GL_RGB,
+ 128,
+ 128,
+ 0,
+ GL_RGB,
+ GL_UNSIGNED_BYTE,
+ &g_texture_data[0]);
+ }
+
+ void Animate() {
+ if (animating_) {
+ x_angle_ = fmod(360.0f + x_angle_ + kXAngleDelta, 360.0f);
+ y_angle_ = fmod(360.0f + y_angle_ + kYAngleDelta, 360.0f);
+
+ // Send new values to JavaScript.
+ pp::VarArray array;
+ array.SetLength(2);
+ array.Set(0, x_angle_);
+ array.Set(1, y_angle_);
+ PostMessage(array);
+ }
+ }
+
+ void Render() {
+ glClearColor(0.5, 0.5, 0.5, 1);
+ glClearDepthf(1.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glEnable(GL_DEPTH_TEST);
+
+ //set what program to use
+ glUseProgram(program_);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, texture_);
+ glUniform1i(texture_loc_, 0);
+
+ //create our perspective matrix
+ float mvp[16];
+ float trs[16];
+ float rot[16];
+
+ identity_matrix(mvp);
+ const float aspect_ratio = static_cast<float>(width_) / height_;
+ float fovY = kMinFovY / aspect_ratio;
+ if (fovY < kMinFovY)
+ fovY = kMinFovY;
+
+ glhPerspectivef2(&mvp[0], fovY, aspect_ratio, kZNear, kZFar);
+
+ translate_matrix(0, 0, kCameraZ, trs);
+ rotate_matrix(x_angle_, y_angle_, 0.0f, rot);
+ multiply_matrix(trs, rot, trs);
+ multiply_matrix(mvp, trs, mvp);
+ glUniformMatrix4fv(mvp_loc_, 1, GL_FALSE, mvp);
+
+ //define the attributes of the vertex
+ glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_);
+ glVertexAttribPointer(position_loc_,
+ 3,
+ GL_FLOAT,
+ GL_FALSE,
+ sizeof(Vertex),
+ reinterpret_cast<void*>(offsetof(Vertex, loc)));
+ glEnableVertexAttribArray(position_loc_);
+ glVertexAttribPointer(color_loc_,
+ 3,
+ GL_FLOAT,
+ GL_FALSE,
+ sizeof(Vertex),
+ reinterpret_cast<void*>(offsetof(Vertex, color)));
+ glEnableVertexAttribArray(color_loc_);
+ glVertexAttribPointer(texcoord_loc_,
+ 2,
+ GL_FLOAT,
+ GL_FALSE,
+ sizeof(Vertex),
+ reinterpret_cast<void*>(offsetof(Vertex, tex)));
+ glEnableVertexAttribArray(texcoord_loc_);
+
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer_);
+ glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, 0);
+ }
+
+ void MainLoop(int32_t) {
+ Animate();
+ Render();
+ context_.SwapBuffers(
+ callback_factory_.NewCallback(&CubeInstance::MainLoop));
+ }
+
+ pp::CompletionCallbackFactory<CubeInstance> callback_factory_;
+ pp::Graphics3D context_;
+ int32_t width_;
+ int32_t height_;
+ GLuint frag_shader_;
+ GLuint vertex_shader_;
+ GLuint program_;
+ GLuint vertex_buffer_;
+ GLuint index_buffer_;
+ GLuint texture_;
+
+ GLuint texture_loc_;
+ GLuint position_loc_;
+ GLuint texcoord_loc_;
+ GLuint color_loc_;
+ GLuint mvp_loc_;
+
+ float x_angle_;
+ float y_angle_;
+ bool animating_;
+};
+
+class CubeModule : public pp::Module {
+ public:
+ CubeModule() : pp::Module() {}
+ virtual ~CubeModule() {}
+
+ virtual pp::Instance* CreateInstance(PP_Instance instance) {
+ return new CubeInstance(instance);
+ }
+};
+
+namespace pp {
+Module* CreateModule() { return new CubeModule(); }
+} // namespace pp
diff --git a/native_client_sdk/src/gonacl_appengine/src/cube/matrix.cc b/native_client_sdk/src/gonacl_appengine/src/cube/matrix.cc
new file mode 100644
index 0000000000..25778e5fa3
--- /dev/null
+++ b/native_client_sdk/src/gonacl_appengine/src/cube/matrix.cc
@@ -0,0 +1,139 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/** @file matrix.cc
+ * Implements simple matrix manipulation functions.
+ */
+
+//-----------------------------------------------------------------------------
+#include <stdlib.h>
+#include <string.h>
+#include "matrix.h"
+#define deg_to_rad(x) (x * (M_PI / 180.0f))
+
+void glhFrustumf2(Matrix_t mat,
+ GLfloat left,
+ GLfloat right,
+ GLfloat bottom,
+ GLfloat top,
+ GLfloat znear,
+ GLfloat zfar) {
+ float temp, temp2, temp3, temp4;
+ temp = 2.0f * znear;
+ temp2 = right - left;
+ temp3 = top - bottom;
+ temp4 = zfar - znear;
+ mat[0] = temp / temp2;
+ mat[1] = 0.0f;
+ mat[2] = 0.0f;
+ mat[3] = 0.0f;
+ mat[4] = 0.0f;
+ mat[5] = temp / temp3;
+ mat[6] = 0.0f;
+ mat[7] = 0.0f;
+ mat[8] = (right + left) / temp2;
+ mat[9] = (top + bottom) / temp3;
+ mat[10] = (-zfar - znear) / temp4;
+ mat[11] = -1.0f;
+ mat[12] = 0.0f;
+ mat[13] = 0.0f;
+ mat[14] = (-temp * zfar) / temp4;
+ mat[15] = 0.0f;
+}
+
+void glhPerspectivef2(Matrix_t mat,
+ GLfloat fovyInDegrees,
+ GLfloat aspectRatio,
+ GLfloat znear,
+ GLfloat zfar) {
+ float ymax, xmax;
+ ymax = znear * tanf(fovyInDegrees * 3.14f / 360.0f);
+ xmax = ymax * aspectRatio;
+ glhFrustumf2(mat, -xmax, xmax, -ymax, ymax, znear, zfar);
+}
+
+void identity_matrix(Matrix_t mat) {
+ memset(mat, 0, sizeof(Matrix_t));
+ mat[0] = 1.0;
+ mat[5] = 1.0;
+ mat[10] = 1.0;
+ mat[15] = 1.0;
+}
+
+void multiply_matrix(const Matrix_t a, const Matrix_t b, Matrix_t mat) {
+ // Generate to a temporary first in case the output matrix and input
+ // matrix are the same.
+ Matrix_t out;
+
+ out[0] = a[0] * b[0] + a[4] * b[1] + a[8] * b[2] + a[12] * b[3];
+ out[1] = a[1] * b[0] + a[5] * b[1] + a[9] * b[2] + a[13] * b[3];
+ out[2] = a[2] * b[0] + a[6] * b[1] + a[10] * b[2] + a[14] * b[3];
+ out[3] = a[3] * b[0] + a[7] * b[1] + a[11] * b[2] + a[15] * b[3];
+
+ out[4] = a[0] * b[4] + a[4] * b[5] + a[8] * b[6] + a[12] * b[7];
+ out[5] = a[1] * b[4] + a[5] * b[5] + a[9] * b[6] + a[13] * b[7];
+ out[6] = a[2] * b[4] + a[6] * b[5] + a[10] * b[6] + a[14] * b[7];
+ out[7] = a[3] * b[4] + a[7] * b[5] + a[11] * b[6] + a[15] * b[7];
+
+ out[8] = a[0] * b[8] + a[4] * b[9] + a[8] * b[10] + a[12] * b[11];
+ out[9] = a[1] * b[8] + a[5] * b[9] + a[9] * b[10] + a[13] * b[11];
+ out[10] = a[2] * b[8] + a[6] * b[9] + a[10] * b[10] + a[14] * b[11];
+ out[11] = a[3] * b[8] + a[7] * b[9] + a[11] * b[10] + a[15] * b[11];
+
+ out[12] = a[0] * b[12] + a[4] * b[13] + a[8] * b[14] + a[12] * b[15];
+ out[13] = a[1] * b[12] + a[5] * b[13] + a[9] * b[14] + a[13] * b[15];
+ out[14] = a[2] * b[12] + a[6] * b[13] + a[10] * b[14] + a[14] * b[15];
+ out[15] = a[3] * b[12] + a[7] * b[13] + a[11] * b[14] + a[15] * b[15];
+
+ memcpy(mat, out, sizeof(Matrix_t));
+}
+
+void rotate_x_matrix(GLfloat x_rad, Matrix_t mat) {
+ identity_matrix(mat);
+ mat[5] = cosf(x_rad);
+ mat[6] = -sinf(x_rad);
+ mat[9] = -mat[6];
+ mat[10] = mat[5];
+}
+
+void rotate_y_matrix(GLfloat y_rad, Matrix_t mat) {
+ identity_matrix(mat);
+ mat[0] = cosf(y_rad);
+ mat[2] = sinf(y_rad);
+ mat[8] = -mat[2];
+ mat[10] = mat[0];
+}
+
+void rotate_z_matrix(GLfloat z_rad, Matrix_t mat) {
+ identity_matrix(mat);
+ mat[0] = cosf(z_rad);
+ mat[1] = sinf(z_rad);
+ mat[4] = -mat[1];
+ mat[5] = mat[0];
+}
+
+void rotate_matrix(GLfloat x_deg, GLfloat y_deg, GLfloat z_deg, Matrix_t mat) {
+ GLfloat x_rad = (GLfloat) deg_to_rad(x_deg);
+ GLfloat y_rad = (GLfloat) deg_to_rad(y_deg);
+ GLfloat z_rad = (GLfloat) deg_to_rad(z_deg);
+
+ Matrix_t x_matrix;
+ Matrix_t y_matrix;
+ Matrix_t z_matrix;
+
+ rotate_x_matrix(x_rad, x_matrix);
+ rotate_y_matrix(y_rad, y_matrix);
+ rotate_z_matrix(z_rad, z_matrix);
+
+ Matrix_t xy_matrix;
+ multiply_matrix(y_matrix, x_matrix, xy_matrix);
+ multiply_matrix(z_matrix, xy_matrix, mat);
+}
+
+void translate_matrix(GLfloat x, GLfloat y, GLfloat z, Matrix_t mat) {
+ identity_matrix(mat);
+ mat[12] += x;
+ mat[13] += y;
+ mat[14] += z;
+}
diff --git a/native_client_sdk/src/gonacl_appengine/src/cube/matrix.h b/native_client_sdk/src/gonacl_appengine/src/cube/matrix.h
new file mode 100644
index 0000000000..ed094eda09
--- /dev/null
+++ b/native_client_sdk/src/gonacl_appengine/src/cube/matrix.h
@@ -0,0 +1,43 @@
+#ifndef EXAMPLES_HELLO_WORLD_GLES_MATRIX_H
+#define EXAMPLES_HELLO_WORLD_GLES_MATRIX_H
+
+/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/** @file matrix.cc
+ * Implements simple matrix manipulation functions.
+ */
+
+//-----------------------------------------------------------------------------
+#define _USE_MATH_DEFINES 1
+#include <limits.h>
+#include <math.h>
+#include <GLES2/gl2.h>
+
+typedef GLfloat Matrix_t[16];
+
+/// Since GLES2 doesn't have all the nifty matrix transform functions that GL
+/// has, we emulate some of them here for the sake of sanity from:
+/// http://www.opengl.org/wiki/GluPerspective_code
+void glhFrustumf2(Matrix_t mat,
+ GLfloat left,
+ GLfloat right,
+ GLfloat bottom,
+ GLfloat top,
+ GLfloat znear,
+ GLfloat zfar);
+
+void glhPerspectivef2(Matrix_t mat,
+ GLfloat fovyInDegrees,
+ GLfloat aspectRatio,
+ GLfloat znear,
+ GLfloat zfar);
+
+void identity_matrix(Matrix_t mat);
+void multiply_matrix(const Matrix_t a, const Matrix_t b, Matrix_t mat);
+void rotate_matrix(GLfloat x_deg, GLfloat y_deg, GLfloat z_deg, Matrix_t mat);
+void translate_matrix(GLfloat x, GLfloat y, GLfloat z, Matrix_t mat);
+
+#endif // EXAMPLES_HELLO_WORLD_GLES_MATRIX_H
diff --git a/native_client_sdk/src/gonacl_appengine/src/cube/texture.cc b/native_client_sdk/src/gonacl_appengine/src/cube/texture.cc
new file mode 100644
index 0000000000..0f928c35f9
--- /dev/null
+++ b/native_client_sdk/src/gonacl_appengine/src/cube/texture.cc
@@ -0,0 +1,64 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stdint.h>
+#include <stdlib.h>
+
+
+extern const uint8_t kRLETextureData[] =
+ "/wD/AP8A/w8ACf8SAAn/AP9ZAAP/CQAD/wwAA/8JAAP/AP9WAAP/CQAD/wwAA/8JAAP/AP9WAAP/"
+ "CQAD/wwAA/8JAAP/AP9WAAP/CQAD/wwAA/8JAAP/AP9WAAP/CQAD/wMABv8DAAP/CQAD/wD/WQAJ"
+ "/wYABv8GAAn/AP9uAAP/AP96AAP/AP8A/x8AA/8A/3oACf8A/3QAD/8A/24AFf8A/2gAG/8A/2IA"
+ "If8A/1wAJ/8A/1YALf8A/1AAM/8A/0oAOf8A/0QAP/8A/z4ARf8A/zgAS/8A/zIAUf8A/ywAV/8A"
+ "/yYAXf8A/yAAY/8A/xoAaf8A/xQAb/8A/w4Adf8A/wgAe/8A/wIADP8JAAP/CQAb/wYAD/8GACr/"
+ "/AAS/wMACf8DAAkDAwQDABL/AwAS/wMALf/2ABX/AwAJ/wMABikD6AP8A78DGAMADP8DABL/AwAM"
+ "EwOzA+YDsgMSAwAV//AAGP8PAAa2AykDAgM7A68DAAz/AwAS/wMADKUDSwMAA0sDpAMAGP/qABv/"
+ "AwAJ/wMABvYD/wn1AwAM/wMAEv8DAAzzAwgDAAMIA/IDABv/5AAe/wMACf8DAAbDAwAY/wMAEv8D"
+ "AAzzAwgDAAMIA/IDAB7/3gAh/wMACf8DAAaIA1IDDgMAEv8DABL/AwAMpgNTAwADUwOkAwAh/9gA"
+ "If8JAAP/CQADDQOrA/gD2AN/AwAG/w8ABv8PAAYUA7kD8AO3AxIDACT/0gCx/8wAt//GAL3/wADD"
+ "/7oAyf+0AM//rgA2/wkAA/8JADD/BgAV/wYAOf+oADkFA/YDAAYBA/cDAwMAM/8DABj/AwA8/6IA"
+ "P+sDEAMAAxQD6AMABhMDswPmA7IDEgMABv8GKQPWA5UDAAz/AwAMHQPMA+gDRAP/AwA//5wAQtMD"
+ "OQP/AzwD0AMABqUDSwMAA0sDpAMACf8DswMrA1oDAAz/AwAMqgNhAwYDXwP/AwBC/5YARboDcgP/"
+ "A3QDuAMABvMDCAMAAwgD8gMACf8DCgMAEv8DAAzxAwkDAAMLA/8DAEX/kABIogOqA/8DrAOgAwAG"
+ "8wMIAwADCAPyAwAJ/wMAFf8DAAzyAwkDAAMLA/8DAEj/igBLiQPjA/8D5AOIAwAGpgNTAwADUwOk"
+ "AwAJ/wMAFf8DAAysA18DBQNfA/8DAEv/hABOcAP/A9oD/wNwAwAGFAO5A/ADtwMSAwAG/w8ABv8P"
+ "AAYeA8wD6ANFA/8GAEv/fgAAAAX/eAAAAAv/cgAAABH/bAAAABf/ZgAAAB3/YAAAACP/vQBm/wD/"
+ "GgBm/wD/GgBm/wD/GgBm/wD/GgBm/wD/GgBm/wD/GgBm/wD/GgBm/wD/GgBm/wD/GgBm/wD/GgBm"
+ "/wD/GgBm/wD/GgBm/wD/GgBm/wD/GgBm/wD/GgBm/wD/GgBm/wD/GgBm/wD/GgBm/wD/GgBm/wD/"
+ "GgBm/wD/GgBm/wD/GgBm/wD/GgBm/wD/GgBm/wD/GgBm/wD/GgBm/wD/GgBm/wD/GgBm/wD/GgBm"
+ "/wD/GgBm/wD/GgBm/wD/GgBm/wD/GgBm/wD/GgBm/wD/GgBm/wD/GgBm/wD/GgBm/wD/GgBm/wD/"
+ "GgBm/wD/GgBm/wD/GgBm/wD/GgBm/wD/GgBm/x8AAv8BAAL/AQAC/wEAAv8BAAL/AwAB/wEAAv8B"
+ "AAL/AQAC/wEAAv8BAAH/AwAC/wEAAv8BAAL/AQAC/wEAAv/KAGb/HwAC/wEAAv8BAAL/AQAC/wEA"
+ "Av8DAAH/AQAC/wEAAv8BAAL/AQAC/wEAAf8DAAL/AQAC/wEAAv8BAAL/AQAC/8oAZv8fAAL/AQAC"
+ "/wEAAv8BAAL/AQAC/wMAAf8BAAL/AQAC/wEAAv8BAAL/AQAB/wMAAv8BAAL/AQAC/wEAAv8BAAL/"
+ "ygBm/x8AAv8BAAL/AQAC/wEAAv8BAAL/AwAB/wEAAv8BAAL/AQAC/wEAAv8BAAH/AwAC/wEAAv8B"
+ "AAL/AQAC/wEAAv/KAGb/HwAC/wEAAv8BAAL/AQAC/wEAAv8DAAH/AQAC/wEAAv8BAAL/AQAC/wEA"
+ "Af8DAAL/AQAC/wEAAv8BAAL/AQAC/8oAZv8fAAL/AQAC/wEAAv8BAAL/AQAC/wMAAf8BAAL/AQAC"
+ "/wEAAv8BAAL/AQAB/wMAAv8BAAL/AQAC/wEAAv8BAAL/ygBm/x8AAv8BAAL/AQAC/wEAAv8BAAL/"
+ "AwAB/wEAAv8BAAL/AQAC/wEAAv8BAAH/AwAC/wEAAv8BAAL/AQAC/wEAAv/KAGb/HwAC/wEAAv8B"
+ "AAL/AQAC/wEAAv8DAAH/AQAC/wEAAv8BAAL/AQAC/wEAAf8DAAL/AQAC/wEAAv8BAAL/AQAC/8oA"
+ "Zv8fAAL/AQAC/wEAAv8BAAL/AQAC/wMAAf8BAAL/AQAC/wEAAv8BAAL/AQAB/wMAAv8BAAL/AQAC"
+ "/wEAAv8BAAL/ygBm/x8AAv8BAAL/AQAC/wEAAv8BAAL/AwAB/wEAAv8BAAL/AQAC/wEAAv8BAAH/"
+ "AwAC/wEAAv8BAAL/AQAC/wEAAv/KAGb/HwAC/wEAAv8BAAL/AQAC/wEAAv8DAAH/AQAC/wEAAv8B"
+ "AAL/AQAC/wEAAf8DAAL/AQAC/wEAAv8BAAL/AQAC/8oAZv8fAAL/AQAC/wEAAv8BAAL/AQAC/wMA"
+ "Af8BAAL/AQAC/wEAAv8BAAL/AQAB/wMAAv8BAAL/AQAC/wEAAv8BAAL/ygBm/x8AAv8BAAL/AQAC"
+ "/wEAAv8BAAL/AwAB/wEAAv8BAAL/AQAC/wEAAv8BAAH/AwAC/wEAAv8BAAL/AQAC/wEAAv/KAGb/"
+ "HwAC/wEAAv8BAAL/AQAC/wEAAv8DAAH/AQAC/wEAAv8BAAL/AQAC/wEAAf8DAAL/AQAC/wEAAv8B"
+ "AAL/AQAC/8oAZv8fAAL/AQAC/wEAAv8BAAL/AQAC/wMAAf8BAAL/AQAC/wEAAv8BAAL/AQAB/wMA"
+ "Av8BAAL/AQAC/wEAAv8BAAL/ygBm/x8AAv8BAAL/AQAC/wEAAv8BAAL/AwAB/wEAAv8BAAL/AQAC"
+ "/wEAAv8BAAH/AwAC/wEAAv8BAAL/AQAC/wEAAv/KAGb/HwAC/wEAAv8BAAL/AQAC/wEAAv8DAAH/"
+ "AQAC/wEAAv8BAAL/AQAC/wEAAf8DAAL/AQAC/wEAAv8BAAL/AQAC/8oAZv8fAAL/AQAC/wEAAv8B"
+ "AAL/AQAC/wMAAf8BAAL/AQAC/wEAAv8BAAL/AQAB/wMAAv8BAAL/AQAC/wEAAv8BAAL/ygBm/x8A"
+ "Av8BAAL/AQAC/wEAAv8BAAL/AwAB/wEAAv8BAAL/AQAC/wEAAv8BAAH/AwAC/wEAAv8BAAL/AQAC"
+ "/wEAAv/KAGb/HwAC/wEAAv8BAAL/AQAC/wEAAv8DAAH/AQAC/wEAAv8BAAL/AQAC/wEAAf8DAAL/"
+ "AQAC/wEAAv8BAAL/AQAC/8oAZv8fAAL/AQAC/wEAAv8BAAL/AQAC/wMAAf8BAAL/AQAC/wEAAv8B"
+ "AAL/AQAB/wMAAv8BAAL/AQAC/wEAAv8BAAL/ygBm/x8AAv8BAAL/AQAC/wEAAv8BAAL/AwAB/wEA"
+ "Av8BAAL/AQAC/wEAAv8BAAH/AwAC/wEAAv8BAAL/AQAC/wEAAv/KAGb/HwAC/wEAAv8BAAL/AQAC"
+ "/wEAAv8DAAH/AQAC/wEAAv8BAAL/AQAC/wEAAf8DAAL/AQAC/wEAAv8BAAL/AQAC/8oAMzwDADD/"
+ "HwAC/wEAAv8BAAL/AQAC/wEAAv8DAAH/AQAC/wEAAv8BAAL/AQAC/wEAAf8DAAL/AQAC/wEAAv8B"
+ "AAL/AQAC/8oAZv8fAAL/AQAC/wEAAv8BAAL/AQAC/wMAAf8BAAL/AQAC/wEAAv8BAAL/AQAB/wMA"
+ "Av8BAAL/AQAC/wEAAv8BAAL/Og==";
+
+// Ignore \0 at the end of the string.
+extern const size_t kRLETextureDataLength = sizeof(kRLETextureData) - 1;
diff --git a/native_client_sdk/src/gonacl_appengine/src/lua/build.sh b/native_client_sdk/src/gonacl_appengine/src/lua/build.sh
index 3891fa9f5b..44aea50618 100755
--- a/native_client_sdk/src/gonacl_appengine/src/lua/build.sh
+++ b/native_client_sdk/src/gonacl_appengine/src/lua/build.sh
@@ -12,7 +12,7 @@ cd ${SCRIPT_DIR}
OUT_DIR=out
NACLPORTS_URL=http://naclports.googlecode.com/svn/trunk/src
-NACLPORTS_REV=939
+NACLPORTS_REV=960
NACLPORTS_DIR=${OUT_DIR}/naclports
if [ -z "${NACL_SDK_ROOT:-}" ]; then
diff --git a/native_client_sdk/src/gonacl_appengine/src/smoothlife/build.sh b/native_client_sdk/src/gonacl_appengine/src/smoothlife/build.sh
new file mode 100755
index 0000000000..8e785cc815
--- /dev/null
+++ b/native_client_sdk/src/gonacl_appengine/src/smoothlife/build.sh
@@ -0,0 +1,83 @@
+#!/bin/bash
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+set -o nounset
+set -o errexit
+
+SCRIPT_DIR="$(cd $(dirname $0) && pwd)"
+cd ${SCRIPT_DIR}
+
+OUT_DIR=out
+SMOOTHLIFE_URL=https://github.com/binji/smoothnacl
+SMOOTHLIFE_DIR=${OUT_DIR}/smoothlife
+SMOOTHLIFE_SHA=63f115f2393aa629aab1403948cbfb28acc54360
+
+if [ -z "${NACL_SDK_ROOT:-}" ]; then
+ echo "-------------------------------------------------------------------"
+ echo "NACL_SDK_ROOT is unset."
+ echo "This environment variable needs to be pointed at some version of"
+ echo "the Native Client SDK (the directory containing toolchain/)."
+ echo "NOTE: set this to an absolute path."
+ echo "-------------------------------------------------------------------"
+ exit -1
+fi
+
+Banner() {
+ echo "######################################################################"
+ echo $*
+ echo "######################################################################"
+}
+
+# echo a command to stdout and then execute it.
+LogExecute() {
+ echo $*
+ $*
+}
+
+Clone() {
+ local url=$1
+ local dir=$2
+ local sha=$3
+ if [ ! -d $dir ]; then
+ LogExecute git clone $url $dir
+ else
+ pushd $dir
+ LogExecute git fetch origin
+ popd
+ fi
+
+ pushd $dir
+ LogExecute git checkout $sha
+ popd
+}
+
+readonly OS_NAME=$(uname -s)
+if [ $OS_NAME = "Darwin" ]; then
+ OS_JOBS=4
+elif [ $OS_NAME = "Linux" ]; then
+ OS_JOBS=`nproc`
+else
+ OS_JOBS=1
+fi
+
+Banner Cloning smoothlife
+Clone ${SMOOTHLIFE_URL} ${SMOOTHLIFE_DIR} ${SMOOTHLIFE_SHA}
+
+pushd ${SMOOTHLIFE_DIR}
+
+Banner Updating submodules
+LogExecute git submodule update --init
+
+Banner Building FFTW
+LogExecute make ports
+
+Banner Building smoothlife
+LogExecute make TOOLCHAIN=pnacl CONFIG=Release -j${OS_JOBS}
+
+popd
+
+LogExecute cp ${SMOOTHLIFE_DIR}/pnacl/Release/smoothnacl.{pexe,nmf} ${OUT_DIR}
+
+Banner Done!
diff --git a/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-bullet/scene.js b/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-bullet/scene.js
index 27ae546e52..9325f4d5da 100644
--- a/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-bullet/scene.js
+++ b/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-bullet/scene.js
@@ -213,6 +213,7 @@ function init() {
rendererContainer.addEventListener('mousedown', onMouseDown, false);
rendererContainer.addEventListener('mouseup', onMouseUp, false);
+ rendererContainer.addEventListener('mouseleave', onMouseUp, false);
renderer.domElement.addEventListener('mousemove', onMouseMove, false);
// Add the OrbitControls after our own listeners -- that way we can prevent
@@ -237,6 +238,8 @@ function pollForRendererResize() {
}
function onMouseDown(event) {
+ event.preventDefault();
+
var vector = new THREE.Vector3( mouse.x, mouse.y, 0.5 );
projector.unprojectVector( vector, camera );
var ray = new THREE.Ray( camera.position, vector.subSelf( camera.position ).normalize() );
@@ -267,12 +270,14 @@ function onMouseUp(event) {
function onMouseMove( event ) {
event.preventDefault();
- var rendererContainer = $('rendererContainer');
- var w = rendererContainer.clientWidth;
- var h = rendererContainer.clientHeight;
+ var clientRect = $('rendererContainer').getClientRects()[0];
+ var x = event.clientX - clientRect.left;
+ var y = event.clientY - clientRect.top;
+ var w = clientRect.width;
+ var h = clientRect.height;
- mouse.x = ( event.clientX / w ) * 2 - 1;
- mouse.y = - ( event.clientY / h ) * 2 + 1;
+ mouse.x = ( x / w ) * 2 - 1;
+ mouse.y = -( y / h ) * 2 + 1;
var vector = new THREE.Vector3( mouse.x, mouse.y, 0.5 );
projector.unprojectVector( vector, camera );
offset.x = vector.x;
diff --git a/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-cube/example.js b/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-cube/example.js
new file mode 100644
index 0000000000..4d3bddb29d
--- /dev/null
+++ b/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-cube/example.js
@@ -0,0 +1,262 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+'use strict';
+
+var naclModule = null;
+
+/**
+ * A helper function to abbreviate getElementById.
+ *
+ * @param {string} elementId The id to get.
+ * @return {Element}
+ */
+function $(elementId) {
+ return document.getElementById(elementId);
+}
+
+/**
+ * MIME type for PNaCl
+ *
+ * @return {string} MIME type
+ */
+function PNaClmimeType() {
+ return 'application/x-pnacl';
+}
+
+/**
+ * Check if the browser supports PNaCl.
+ *
+ * @return {bool}
+ */
+function browserSupportsPNaCl() {
+ var mimetype = PNaClmimeType();
+ return navigator.mimeTypes[mimetype] !== undefined;
+}
+
+/**
+ * Get the URL for Google Cloud Storage.
+ *
+ * @param {string} name The relative path to the file.
+ * @return {string}
+ */
+function getDataURL(name) {
+ var revision = 232423;
+ var baseUrl = 'http://commondatastorage.googleapis.com/gonacl/demos/publish/';
+ return baseUrl + revision + '/cube/' + name;
+}
+
+/**
+ * Create the Native Client <embed> element as a child of the DOM element
+ * named "listener".
+ *
+ * @param {string} name The name of the example.
+ * @param {number} width The width to create the plugin.
+ * @param {number} height The height to create the plugin.
+ * @param {Object} attrs Dictionary of attributes to set on the module.
+ */
+function createNaClModule(name, width, height, attrs) {
+ var moduleEl = document.createElement('embed');
+ moduleEl.setAttribute('name', 'nacl_module');
+ moduleEl.setAttribute('id', 'nacl_module');
+ moduleEl.setAttribute('width', width);
+ moduleEl.setAttribute('height', height);
+ moduleEl.setAttribute('path', '');
+ moduleEl.setAttribute('src', getDataURL(name + '.nmf'));
+ moduleEl.setAttribute('type', PNaClmimeType());
+
+ // Add any optional arguments
+ if (attrs) {
+ for (var key in attrs) {
+ moduleEl.setAttribute(key, attrs[key]);
+ }
+ }
+
+ // The <EMBED> element is wrapped inside a <DIV>, which has both a 'load'
+ // and a 'message' event listener attached. This wrapping method is used
+ // instead of attaching the event listeners directly to the <EMBED> element
+ // to ensure that the listeners are active before the NaCl module 'load'
+ // event fires.
+ var listenerDiv = $('listener');
+ listenerDiv.appendChild(moduleEl);
+}
+
+/**
+ * Add the default event listeners to the element with id "listener".
+ */
+function attachDefaultListeners() {
+ var listenerDiv = $('listener');
+ listenerDiv.addEventListener('load', moduleDidLoad, true);
+ listenerDiv.addEventListener('error', moduleLoadError, true);
+ listenerDiv.addEventListener('progress', moduleLoadProgress, true);
+ listenerDiv.addEventListener('message', handleMessage, true);
+ listenerDiv.addEventListener('crash', handleCrash, true);
+ attachListeners();
+}
+
+/**
+ * Called when the Browser can not communicate with the Module
+ *
+ * This event listener is registered in attachDefaultListeners above.
+ *
+ * @param {Object} event
+ */
+function handleCrash(event) {
+ if (naclModule.exitStatus == -1) {
+ updateStatus('CRASHED');
+ } else {
+ updateStatus('EXITED [' + naclModule.exitStatus + ']');
+ }
+}
+
+/**
+ * Called when the NaCl module is loaded.
+ *
+ * This event listener is registered in attachDefaultListeners above.
+ */
+function moduleDidLoad() {
+ var bar = $('progress');
+ bar.value = 100;
+ bar.max = 100;
+ naclModule = $('nacl_module');
+ hideStatus();
+}
+
+/**
+ * Hide the status field and progress bar.
+ */
+function hideStatus() {
+ $('statusField').style.display = 'none';
+ $('progress').style.display = 'none';
+}
+
+/**
+ * Called when the plugin fails to load.
+ *
+ * @param {Object} event
+ */
+function moduleLoadError(event) {
+ updateStatus('Load failed.');
+}
+
+/**
+ * Called when the plugin reports progress events.
+ *
+ * @param {Object} event
+ */
+function moduleLoadProgress(event) {
+ $('progress').style.display = 'block';
+
+ var loadPercent = 0.0;
+ var bar = $('progress');
+ bar.max = 100;
+ if (event.lengthComputable && event.total > 0) {
+ loadPercent = event.loaded / event.total * 100.0;
+ } else {
+ // The total length is not yet known.
+ loadPercent = -1.0;
+ }
+ bar.value = loadPercent;
+}
+
+/**
+ * If the element with id 'statusField' exists, then set its HTML to the status
+ * message as well.
+ *
+ * @param {string} opt_message The message to set.
+ */
+function updateStatus(opt_message) {
+ var statusField = $('statusField');
+ if (statusField) {
+ statusField.style.display = 'block';
+ statusField.textContent = opt_message;
+ }
+}
+
+/**
+ * Add event listeners after the NaCl module has loaded. These listeners will
+ * forward messages to the NaCl module via postMessage()
+ */
+function attachListeners() {
+ $('xAngle').addEventListener('change', postAngleMessage);
+ $('yAngle').addEventListener('change', postAngleMessage);
+ $('animateOff').addEventListener('click', function() {
+ $('animateOn').checked = '';
+ naclModule.postMessage(false);
+ });
+ $('animateOn').addEventListener('click', function() {
+ $('animateOff').checked = '';
+ naclModule.postMessage(true);
+ });
+}
+
+function postAngleMessage() {
+ var xAngle = parseFloat($('xAngle').value);
+ var yAngle = parseFloat($('yAngle').value);
+ naclModule.postMessage([xAngle, yAngle]);
+}
+
+/**
+ * Load a texture and send pixel data down to NaCl module.
+ * @param {string} name
+ */
+function loadTexture(name) {
+ // Load image from jpg, decompress into canvas.
+ var img = new Image();
+ img.onload = function() {
+ var graph = document.createElement('canvas');
+ graph.width = img.width;
+ graph.height = img.height;
+ var context = graph.getContext('2d');
+ context.drawImage(img, 0, 0);
+ var imageData = context.getImageData(0, 0, img.width, img.height);
+ // Send NaCl module the raw image data obtained from canvas.
+ naclModule.postMessage({'message' : 'texture',
+ 'name' : name,
+ 'width' : img.width,
+ 'height' : img.height,
+ 'data' : imageData.data.buffer});
+ };
+ // A cross-origin request to an image is "tainted", and cannot be read into a
+ // canvas without specifying this. See
+ // https://developer.mozilla.org/en-US/docs/HTML/CORS_Enabled_Image
+ img.crossOrigin = 'Anonymous';
+ img.src = getDataURL(name);
+}
+
+/**
+ * Handle a message coming from the NaCl module.
+ * @param {Object} message_event
+ */
+function handleMessage(message_event) {
+ if (!(event.data instanceof Array))
+ return;
+ if (event.data.length != 2)
+ return;
+
+ var xAngle = event.data[0];
+ var yAngle = event.data[1];
+ $('xAngle').value = xAngle;
+ $('yAngle').value = yAngle;
+}
+
+/**
+ * Listen for the DOM content to be loaded. This event is fired when parsing of
+ * the page's document has finished.
+ */
+document.addEventListener('DOMContentLoaded', function() {
+ updateStatus('Loading...');
+ if (!browserSupportsPNaCl()) {
+ updateStatus('Browser does not support PNaCl or PNaCl is disabled');
+ } else if (naclModule == null) {
+ createNaClModule('cube', 480, 480);
+ attachDefaultListeners();
+ } else {
+ // It's possible that the Native Client module onload event fired
+ // before the page's onload event. In this case, the status message
+ // will reflect 'SUCCESS', but won't be displayed. This call will
+ // display the current message.
+ updateStatus('Waiting.');
+ }
+});
diff --git a/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-cube/index.html b/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-cube/index.html
new file mode 100644
index 0000000000..e011719054
--- /dev/null
+++ b/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-cube/index.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<head>
+ <meta charset="UTF-8">
+ <title>Rotating Cube</title>
+ <script type="text/javascript" src="example.js"></script>
+ <link href="/static/common.css" rel="stylesheet" type="text/css">
+</head>
+<body>
+ <div class="absolute-fill">
+ <div class="flex-container">
+ <div class="main absolute-fill-parent">
+ <div class="absolute-fill">
+ <div class="flex-container flex-column flex-justify-center">
+ <div id="message">
+ <div id="statusField"></div>
+ <progress id="progress"></progress>
+ </div>
+ </div>
+ </div>
+ <div id="listener" class="absolute-fill"></div>
+ </div>
+ <div class="sidebar">
+ <h1>Rotating Cube</h1>
+ <table id="config">
+ <tbody>
+ <tr>
+ <td class="name">X Angle:</td>
+ <td class="value">
+ <input type="range" id="xAngle" min="0" max="360" step="1"
+ value="0">
+ </td>
+ </tr>
+ <tr>
+ <td class="name">Y Angle:</td>
+ <td class="value">
+ <input type="range" id="yAngle" min="0" max="360" step="1"
+ value="0">
+ </td>
+ </tr>
+ <tr>
+ <td class="name">Animating:</td>
+ <td class="value">
+ <label>
+ off
+ <input type="radio" id="animateOff" value="false">
+ </label>
+ <label>
+ on
+ <input type="radio" id="animateOn" value="true"
+ checked="true">
+ </label>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+ </div>
+</body>
+</html>
diff --git a/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-lua/lua.js b/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-lua/lua.js
index 18b84275d9..1e3c96ecea 100644
--- a/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-lua/lua.js
+++ b/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-lua/lua.js
@@ -5,4 +5,4 @@
*/
NaClTerm.prefix = 'lua'
-NaClTerm.nmf = 'http://commondatastorage.googleapis.com/gonacl/demos/publish/231022/lua/lua.nmf'
+NaClTerm.nmf = 'http://commondatastorage.googleapis.com/gonacl/demos/publish/232428/lua/lua.nmf'
diff --git a/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-lua/naclterm.js b/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-lua/naclterm.js
index d272a0bdc9..23a5089075 100644
--- a/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-lua/naclterm.js
+++ b/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-lua/naclterm.js
@@ -30,6 +30,8 @@ function NaClTerm(argv) {
};
var embed;
+var ansiCyan = '\x1b[36m';
+var ansiReset = '\x1b[0m';
/**
* Static initialier called from index.html.
@@ -75,7 +77,7 @@ NaClTerm.prototype.handleMessage_ = function(e) {
* Handle load error event from NaCl.
*/
NaClTerm.prototype.handleLoadAbort_ = function(e) {
- term_.io.print("Load aborted.\n");
+ term_.io.print('Load aborted.\n');
}
/**
@@ -85,13 +87,27 @@ NaClTerm.prototype.handleLoadError_ = function(e) {
term_.io.print(embed.lastError + '\n');
}
+NaClTerm.prototype.doneLoadingUrl = function() {
+ var width = term_.io.terminal_.screenSize.width;
+ term_.io.print('\r' + Array(width+1).join(' '));
+ var message = '\rLoaded ' + this.lastUrl;
+ if (this.lastTotal) {
+ var kbsize = Math.round(this.lastTotal/1024)
+ message += ' ['+ kbsize + ' KiB]';
+ }
+ term_.io.print(message.slice(0, width) + '\n')
+}
+
/**
* Handle load end event from NaCl.
*/
NaClTerm.prototype.handleLoad_ = function(e) {
- if (typeof(this.lastUrl) != 'undefined')
- term_.io.print("\n");
- term_.io.print("Loaded.\n");
+ if (this.lastUrl)
+ this.doneLoadingUrl();
+ else
+ term_.io.print('Loaded.\n');
+
+ term_.io.print(ansiReset);
// Now that have completed loading and displaying
// loading messages we output any messages from the
@@ -106,27 +122,36 @@ NaClTerm.prototype.handleLoad_ = function(e) {
*/
NaClTerm.prototype.handleProgress_ = function(e) {
var url = e.url.substring(e.url.lastIndexOf('/') + 1);
- if (this.lastUrl != url) {
- if (url != '') {
- if (this.lastUrl)
- term_.io.print("\n");
- term_.io.print("Loading " + url + " .");
- }
- } else {
- term_.io.print(".");
+
+ if (this.lastUrl && this.lastUrl != url)
+ this.doneLoadingUrl()
+
+ if (!url)
+ return;
+
+ var message = 'Loading ' + url;
+ if (e.lengthComputable && e.total) {
+ var percent = Math.round(e.loaded * 100 / e.total);
+ var kbloaded = Math.round(e.loaded / 1024);
+ var kbtotal = Math.round(e.total / 1024);
+ message += ' [' + kbloaded + ' KiB/' + kbtotal + ' KiB ' + percent + '%]';
}
- if (url)
+
+ var width = term_.io.terminal_.screenSize.width;
+ term_.io.print('\r' + message.slice(-width));
this.lastUrl = url;
+ this.lastTotal = e.total;
}
/**
* Handle crash event from NaCl.
*/
NaClTerm.prototype.handleCrash_ = function(e) {
+ term_.io.print(ansiCyan)
if (embed.exitStatus == -1) {
- term_.io.print("Program crashed (exit status -1)\n")
+ term_.io.print('Program crashed (exit status -1)\n')
} else {
- term_.io.print("Program exited (status=" + embed.exitStatus + ")\n");
+ term_.io.print('Program exited (status=' + embed.exitStatus + ')\n');
}
}
@@ -150,12 +175,22 @@ NaClTerm.prototype.run = function() {
this.io = this.argv_.io.push();
this.bufferedOutput = '';
this.loaded = false;
+ this.io.print(ansiCyan);
+
+ var mimetype = 'application/x-pnacl';
+ if (navigator.mimeTypes[mimetype] === undefined) {
+ if (mimetype.indexOf('pnacl') != -1)
+ this.io.print('Browser does not support PNaCl or PNaCl is disabled\n');
+ else
+ this.io.print('Browser does not support NaCl or NaCl is disabled\n');
+ return;
+ }
embed = document.createElement('object');
embed.width = 0;
embed.height = 0;
embed.data = NaClTerm.nmf;
- embed.type = 'application/x-pnacl';
+ embed.type = mimetype;
embed.addEventListener('message', this.handleMessage_.bind(this));
embed.addEventListener('progress', this.handleProgress_.bind(this));
embed.addEventListener('load', this.handleLoad_.bind(this));
@@ -189,7 +224,7 @@ NaClTerm.prototype.run = function() {
argn = argn + 1;
}
- term_.io.print("Loading NaCl module.\n")
+ this.io.print('Loading NaCl module.\n')
document.body.appendChild(embed);
this.io.onVTKeystroke = this.onVTKeystroke_.bind(this);
diff --git a/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-smoothlife/example.js b/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-smoothlife/example.js
new file mode 100644
index 0000000000..5171d330b0
--- /dev/null
+++ b/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-smoothlife/example.js
@@ -0,0 +1,291 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+'use strict';
+
+var naclModule = null;
+var presets = [
+ [[15.2,32.1,7.6],[3,0.329,0.15,0.321,0.145,0.709,3,2,4,0.269,0.662],[0,"#000000",3,"#f5f5c1",12,"#158a34",68,"#89e681",100]],
+ [[15.2,32.1,5],[3,0.273,0.117,0.288,0.243,0.348,3,2,4,0.269,0.662],[1,"#000000",3,"#f5f5c1",8,"#158a34",17,"#89e681",20]],
+ [[4,12,1],[2,0.115,0.269,0.523,0.34,0.746,3,4,4,0.028,0.147],[0,"#36065e",0,"#c24242",77,"#8a19b0",91,"#ff9900",99,"#f5c816",99]],
+ [[4,12,1],[3,0.12,0.218,0.267,0.365,0.445,3,4,4,0.028,0.147],[0,"#000000",0,"#0f8a84",38,"#f5f5c1",43,"#158a34",70,"#89e681",100]],
+ [[4,12,1],[0,0.09,0.276,0.27,0.365,0.445,1,4,4,0.028,0.147],[0,"#93afd9",11,"#9cf0ff",92,"#edfdff",100]],
+ [[10.4,12,1],[2,0.082,0.302,0.481,0.35,0.749,2,3,4,0.028,0.147],[0,"#000000",11,"#ffffff",22,"#19a68a",85,"#6b0808",98]],
+ [[7.8,27.2,2.6],[3,0.21,0.714,0.056,0.175,0.838,2,0,2,0.132,0.311],[0,"#0a1340",0,"#ffffff",55,"#4da8a3",83,"#2652ab",99,"#2f1e75",46]],
+ [[4,12,1],[2,0.115,0.269,0.496,0.34,0.767,3,4,4,0.028,0.147],[0,"#b8cfcf",0,"#3f5a5c",77,"#1a330a",91,"#c0e0dc",99]],
+ [[10.6,31.8,1],[1,0.157,0.092,0.256,0.098,0.607,3,4,4,0.015,0.34],[0,"#4d3e3e",0,"#9a1ac9",77,"#aaf09e",100]],
+];
+
+/**
+ * A helper function to abbreviate getElementById.
+ *
+ * @param {string} elementId The id to get.
+ * @return {Element}
+ */
+function $(elementId) {
+ return document.getElementById(elementId);
+}
+
+/**
+ * MIME type for PNaCl
+ *
+ * @return {string} MIME type
+ */
+function PNaClmimeType() {
+ return 'application/x-pnacl';
+}
+
+/**
+ * Check if the browser supports PNaCl.
+ *
+ * @return {bool}
+ */
+function browserSupportsPNaCl() {
+ var mimetype = PNaClmimeType();
+ return navigator.mimeTypes[mimetype] !== undefined;
+}
+
+/**
+ * Get the URL for Google Cloud Storage.
+ *
+ * @param {string} name The relative path to the file.
+ * @return {string}
+ */
+function getDataURL(name) {
+ var revision = 231964;
+ var baseUrl = 'http://commondatastorage.googleapis.com/gonacl/demos/publish/';
+ return baseUrl + revision + '/smoothlife/' + name;
+}
+
+/**
+ * Create the Native Client <embed> element as a child of the DOM element
+ * named "listener".
+ *
+ * @param {string} name The name of the example.
+ * @param {number} width The width to create the plugin.
+ * @param {number} height The height to create the plugin.
+ * @param {Object} attrs Dictionary of attributes to set on the module.
+ */
+function createNaClModule(name, width, height, attrs) {
+ var moduleEl = document.createElement('embed');
+ moduleEl.setAttribute('name', 'nacl_module');
+ moduleEl.setAttribute('id', 'nacl_module');
+ moduleEl.setAttribute('width', width);
+ moduleEl.setAttribute('height', height);
+ moduleEl.setAttribute('path', '');
+ moduleEl.setAttribute('src', getDataURL(name + '.nmf'));
+ moduleEl.setAttribute('type', PNaClmimeType());
+
+ // Add any optional arguments
+ if (attrs) {
+ for (var key in attrs) {
+ moduleEl.setAttribute(key, attrs[key]);
+ }
+ }
+
+ // The <EMBED> element is wrapped inside a <DIV>, which has both a 'load'
+ // and a 'message' event listener attached. This wrapping method is used
+ // instead of attaching the event listeners directly to the <EMBED> element
+ // to ensure that the listeners are active before the NaCl module 'load'
+ // event fires.
+ var listenerDiv = $('listener');
+ listenerDiv.appendChild(moduleEl);
+}
+
+/**
+ * Add the default event listeners to the element with id "listener".
+ */
+function attachDefaultListeners() {
+ var listenerDiv = $('listener');
+ listenerDiv.addEventListener('load', moduleDidLoad, true);
+ listenerDiv.addEventListener('error', moduleLoadError, true);
+ listenerDiv.addEventListener('progress', moduleLoadProgress, true);
+ listenerDiv.addEventListener('message', handleMessage, true);
+ listenerDiv.addEventListener('crash', handleCrash, true);
+ attachListeners();
+}
+
+/**
+ * Called when the Browser can not communicate with the Module
+ *
+ * This event listener is registered in attachDefaultListeners above.
+ *
+ * @param {Object} event
+ */
+function handleCrash(event) {
+ if (naclModule.exitStatus == -1) {
+ updateStatus('CRASHED');
+ } else {
+ updateStatus('EXITED [' + naclModule.exitStatus + ']');
+ }
+}
+
+/**
+ * Called when the NaCl module is loaded.
+ *
+ * This event listener is registered in attachDefaultListeners above.
+ */
+function moduleDidLoad() {
+ var bar = $('progress');
+ bar.value = 100;
+ bar.max = 100;
+ naclModule = $('nacl_module');
+ hideStatus();
+ loadPreset(0);
+}
+
+/**
+ * Hide the status field and progress bar.
+ */
+function hideStatus() {
+ $('statusField').style.display = 'none';
+ $('progress').style.display = 'none';
+}
+
+/**
+ * Called when the plugin fails to load.
+ *
+ * @param {Object} event
+ */
+function moduleLoadError(event) {
+ updateStatus('Load failed.');
+}
+
+/**
+ * Called when the plugin reports progress events.
+ *
+ * @param {Object} event
+ */
+function moduleLoadProgress(event) {
+ $('progress').style.display = 'block';
+
+ var loadPercent = 0.0;
+ var bar = $('progress');
+ bar.max = 100;
+ if (event.lengthComputable && event.total > 0) {
+ loadPercent = event.loaded / event.total * 100.0;
+ } else {
+ // The total length is not yet known.
+ loadPercent = -1.0;
+ }
+ bar.value = loadPercent;
+}
+
+/**
+ * If the element with id 'statusField' exists, then set its HTML to the status
+ * message as well.
+ *
+ * @param {string} opt_message The message to set.
+ */
+function updateStatus(opt_message) {
+ var statusField = $('statusField');
+ if (statusField) {
+ statusField.style.display = 'block';
+ statusField.textContent = opt_message;
+ }
+}
+
+/**
+ * Add event listeners after the NaCl module has loaded. These listeners will
+ * forward messages to the NaCl module via postMessage()
+ */
+function attachListeners() {
+ $('preset').addEventListener('change', loadSelectedPreset);
+ $('reset').addEventListener('click', loadSelectedPreset);
+ $('clear').addEventListener('click', function() { clear(0); });
+ $('splat').addEventListener('click', function() { splat(); });
+ $('brushSizeRange').addEventListener('change', function() {
+ var radius = parseFloat(this.value);
+ setBrushSize(radius, 1.0);
+ $('brushSize').textContent = radius.toFixed(1);
+ });
+}
+
+function loadSelectedPreset() {
+ loadPreset($('preset').value);
+}
+
+function loadPreset(index) {
+ var preset = presets[index];
+
+ clear(0);
+ setKernel.apply(null, preset[0]);
+ setSmoother.apply(null, preset[1]);
+ setPalette.apply(null, preset[2]);
+ splat();
+}
+
+function clear(color) {
+ naclModule.postMessage({cmd: 'clear', color: color});
+}
+
+function setKernel(discRadius, ringRadius, blendRadius) {
+ naclModule.postMessage({
+ cmd: 'setKernel',
+ discRadius: discRadius,
+ ringRadius: ringRadius,
+ blendRadius: blendRadius});
+}
+
+function setSmoother(type, dt, b1, d1, b2, d2, mode, sigmoid, mix, sn, sm) {
+ naclModule.postMessage({
+ cmd: 'setSmoother',
+ type: type, dt: dt,
+ b1: b1, d1: d1, b2: b2, d2: d2,
+ mode: mode, sigmoid: sigmoid, mix: mix,
+ sn: sn, sm: sm});
+}
+
+function setPalette() {
+ var repeating = arguments[0] !== 0;
+ var colors = []
+ var stops = []
+ for (var i = 1; i < arguments.length; i += 2) {
+ colors.push(arguments[i]);
+ stops.push(arguments[i + 1]);
+ }
+ naclModule.postMessage({
+ cmd: 'setPalette',
+ repeating: repeating,
+ colors: colors,
+ stops: stops});
+}
+
+function splat() {
+ naclModule.postMessage({cmd: 'splat'});
+}
+
+function setBrushSize(radius, color) {
+ naclModule.postMessage({cmd: 'setBrush', radius: radius, color: color});
+}
+
+
+/**
+ * Handle a message coming from the NaCl module.
+ * @param {Object} message_event
+ */
+function handleMessage(message_event) {
+ // Update FPS
+ $('fps').textContent = message_event.data.toFixed(1);
+}
+
+/**
+ * Listen for the DOM content to be loaded. This event is fired when parsing of
+ * the page's document has finished.
+ */
+document.addEventListener('DOMContentLoaded', function() {
+ updateStatus('Loading...');
+ if (!browserSupportsPNaCl()) {
+ updateStatus('Browser does not support PNaCl or PNaCl is disabled');
+ } else if (naclModule == null) {
+ createNaClModule('smoothnacl', 512, 512);
+ attachDefaultListeners();
+ } else {
+ // It's possible that the Native Client module onload event fired
+ // before the page's onload event. In this case, the status message
+ // will reflect 'SUCCESS', but won't be displayed. This call will
+ // display the current message.
+ updateStatus('Waiting.');
+ }
+});
diff --git a/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-smoothlife/index.html b/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-smoothlife/index.html
new file mode 100644
index 0000000000..89115eb062
--- /dev/null
+++ b/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-smoothlife/index.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<head>
+ <meta charset="UTF-8">
+ <title>SmoothLife</title>
+ <script type="text/javascript" src="example.js"></script>
+ <link href="/static/common.css" rel="stylesheet" type="text/css">
+</head>
+<body>
+ <div class="absolute-fill">
+ <div class="flex-container">
+ <div class="main absolute-fill-parent">
+ <div class="absolute-fill">
+ <div class="flex-container flex-column flex-justify-center">
+ <div id="message">
+ <div id="statusField"></div>
+ <progress id="progress"></progress>
+ </div>
+ </div>
+ </div>
+ <div id="listener" class="absolute-fill"></div>
+ </div>
+ <div class="sidebar">
+ <h1>SmoothLife</h1>
+ <div>
+ <select id="preset">
+ <option value="0">Subdividers</option>
+ <option value="1">Green Hex</option>
+ <option value="2">Fire Jellies</option>
+ <option value="3">Magical Maze</option>
+ <option value="4">Waterbug Gliders</option>
+ <option value="5">Stitches 'n' Jitters</option>
+ <option value="6">Blink Tubes</option>
+ <option value="7">Oil Slick</option>
+ <option value="8">Worms</option>
+ </select>
+ <button id="reset">Reset</button>
+ </div>
+ <div>
+ <button id="splat">Splat</button>
+ <button id="clear">Clear</button>
+ </div>
+ <div>
+ Brush Size:
+ <input type="range" id="brushSizeRange" min="10.0" max="50.0"
+ step="0.5" value="10.0">
+ <span id="brushSize">10.0</span>
+ </div>
+ <p class="small">
+ This demo was implemented by Ben Smith. The source code is available
+ on GitHub at <a
+ href="https://github.com/binji/smoothnacl">https://github.com/binji/smoothnacl</a>.
+ </p>
+ <p class="small">
+ The implementation was based on <a
+ href="http://sourceforge.net/projects/smoothlife/">this source</a> by
+ ionreq. Also see Stephan Rafler's paper <a
+ href="http://arxiv.org/abs/1111.1567">Generalization of Conway's
+ "Game of Life" to a continuous domain - SmoothLife</a> for more
+ information about the algorithm.
+ </p>
+ <p class="small">
+ FPS: <span id="fps">0</span>
+ </p>
+ </div>
+ </div>
+ </div>
+</body>
+</html>
diff --git a/native_client_sdk/src/libraries/nacl_io/nacl_io.h b/native_client_sdk/src/libraries/nacl_io/nacl_io.h
index 452221951c..71fb9282fa 100644
--- a/native_client_sdk/src/libraries/nacl_io/nacl_io.h
+++ b/native_client_sdk/src/libraries/nacl_io/nacl_io.h
@@ -99,7 +99,7 @@ void nacl_io_init_ppapi(PP_Instance instance,
* HTTP requests.
*
* "passthroughfs": A filesystem that passes all requests through to the
- * underlying NaCL calls. The primary use of this filesystem
+ * underlying NaCl calls. The primary use of this filesystem
* is to allow reading NMF resources.
* source: Unused.
* data: Unused.
diff --git a/native_client_sdk/src/libraries/ppapi_cpp/library.dsc b/native_client_sdk/src/libraries/ppapi_cpp/library.dsc
index 7f8bc9e8e2..3a374fb47e 100644
--- a/native_client_sdk/src/libraries/ppapi_cpp/library.dsc
+++ b/native_client_sdk/src/libraries/ppapi_cpp/library.dsc
@@ -85,6 +85,7 @@
'scrollbar_dev.cc',
'graphics_2d_dev.cc',
'widget_dev.cc',
+ 'var_resource_dev.cc',
# ppapi/cpp/extensions
'event_base.cc',
@@ -182,6 +183,7 @@
'text_input_dev.h',
'truetype_font_dev.h',
'url_util_dev.h',
+ 'var_resource_dev.h',
'video_capture_client_dev.h',
'video_capture_dev.h',
'video_decoder_client_dev.h',
diff --git a/native_client_sdk/src/libraries/third_party/newlib-extras/README.chromium b/native_client_sdk/src/libraries/third_party/newlib-extras/README.chromium
index 3b46d4c3df..4857c6ce42 100644
--- a/native_client_sdk/src/libraries/third_party/newlib-extras/README.chromium
+++ b/native_client_sdk/src/libraries/third_party/newlib-extras/README.chromium
@@ -3,7 +3,7 @@ URL: ftp://sourceware.org/pub/newlib/newlib-2.0.0.tar.gz
Version: 2.0.0
Date: 2013-07-30
License: BSD 3-Clause License
-License File: Embedded in headers.
+License File: README
Security Critical: no
This directory contains several socket-related header files taken from newlib.
diff --git a/native_client_sdk/src/tools/compiler-wrapper.py b/native_client_sdk/src/tools/compiler-wrapper.py
index ef0af646a9..a2dcb118a5 100755
--- a/native_client_sdk/src/tools/compiler-wrapper.py
+++ b/native_client_sdk/src/tools/compiler-wrapper.py
@@ -2,7 +2,7 @@
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-"""NaCL gcc wrapper that presents glibc and newlib as a single
+"""NaCl gcc wrapper that presents glibc and newlib as a single
toolchain.
This wraps the newlib and glibc compilers and allows users
diff --git a/native_client_sdk/src/tools/create_html.py b/native_client_sdk/src/tools/create_html.py
index 8634d4a4a2..6b8a2df9e6 100755
--- a/native_client_sdk/src/tools/create_html.py
+++ b/native_client_sdk/src/tools/create_html.py
@@ -155,9 +155,8 @@ def CreateHTML(filenames, options):
def main(argv):
usage = 'Usage: %prog [options] <.nexe/.pexe or .nmf>'
- description = __doc__
epilog = 'Example: create_html.py -o index.html my_nexe.nexe'
- parser = optparse.OptionParser(usage, description=description, epilog=epilog)
+ parser = optparse.OptionParser(usage, description=__doc__, epilog=epilog)
parser.add_option('-v', '--verbose', action='store_true',
help='Verbose output')
parser.add_option('-d', '--debug-libs', action='store_true',
@@ -167,6 +166,15 @@ def main(argv):
'input name with .html extension)',
metavar='FILE')
+ # To enable bash completion for this command first install optcomplete
+ # and then add this line to your .bashrc:
+ # complete -F _optcomplete create_html.py
+ try:
+ import optcomplete
+ optcomplete.autocomplete(parser)
+ except ImportError:
+ pass
+
options, args = parser.parse_args(argv)
if not args:
diff --git a/native_client_sdk/src/tools/create_nmf.py b/native_client_sdk/src/tools/create_nmf.py
index 880ca008eb..34351c09da 100755
--- a/native_client_sdk/src/tools/create_nmf.py
+++ b/native_client_sdk/src/tools/create_nmf.py
@@ -3,6 +3,12 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+"""Tool for automatically creating .nmf files from .nexe/.pexe executables.
+
+As well as creating the nmf file this tool can also find and stage
+any shared libraries dependancies that the executables might have.
+"""
+
import errno
import json
import optparse
@@ -118,7 +124,7 @@ def ParseElfHeader(path):
elf_magic = '\x7fELF'
if e_ident[:4] != elf_magic:
- raise Error('Not a valid NaCL executable: %s' % path)
+ raise Error('Not a valid NaCl executable: %s' % path)
e_machine_mapping = {
3 : 'x86-32',
@@ -634,7 +640,7 @@ def GetDefaultLibPath(config):
def main(argv):
parser = optparse.OptionParser(
- usage='Usage: %prog [options] nexe [extra_libs...]')
+ usage='Usage: %prog [options] nexe [extra_libs...]', description=__doc__)
parser.add_option('-o', '--output', dest='output',
help='Write manifest file to FILE (default is stdout)',
metavar='FILE')
@@ -672,6 +678,16 @@ def main(argv):
help='Verbose output', action='store_true')
parser.add_option('-d', '--debug-mode',
help='Debug mode', action='store_true')
+
+ # To enable bash completion for this command first install optcomplete
+ # and then add this line to your .bashrc:
+ # complete -F _optcomplete create_nmf.py
+ try:
+ import optcomplete
+ optcomplete.autocomplete(parser)
+ except ImportError:
+ pass
+
options, args = parser.parse_args(argv)
if options.verbose:
Trace.verbose = True
diff --git a/native_client_sdk/src/tools/host_gcc.mk b/native_client_sdk/src/tools/host_gcc.mk
index 594e33b797..b732431b0b 100644
--- a/native_client_sdk/src/tools/host_gcc.mk
+++ b/native_client_sdk/src/tools/host_gcc.mk
@@ -93,7 +93,7 @@ $(STAMPDIR)/$(1).stamp: $(LIBDIR)/$(OSNAME)_host/$(CONFIG)/lib$(1).a
all: $(LIBDIR)/$(OSNAME)_host/$(CONFIG)/lib$(1).a
$(LIBDIR)/$(OSNAME)_host/$(CONFIG)/lib$(1).a: $(foreach src,$(2),$(call SRC_TO_OBJ,$(src)))
$(MKDIR) -p $$(dir $$@)
- $(RM) $$@
+ $(RM) -f $$@
$(call LOG,LIB,$$@,$(HOST_LIB) -cr $$@ $$^)
endef
diff --git a/native_client_sdk/src/tools/httpd.py b/native_client_sdk/src/tools/httpd.py
index 7a98397b66..f771d433e2 100755
--- a/native_client_sdk/src/tools/httpd.py
+++ b/native_client_sdk/src/tools/httpd.py
@@ -292,6 +292,16 @@ def main(args):
help='Listen for posts to /ok or /fail and shut down the server with '
' errorcodes 0 and 1 respectively.',
action='store_true')
+
+ # To enable bash completion for this command first install optcomplete
+ # and then add this line to your .bashrc:
+ # complete -F _optcomplete httpd.py
+ try:
+ import optcomplete
+ optcomplete.autocomplete(parser)
+ except ImportError:
+ pass
+
options, args = parser.parse_args(args)
if options.do_safe_check:
SanityCheckDirectory(options.serve_dir)
diff --git a/native_client_sdk/src/tools/nacl_gcc.mk b/native_client_sdk/src/tools/nacl_gcc.mk
index 5a3065d12c..675b46451b 100644
--- a/native_client_sdk/src/tools/nacl_gcc.mk
+++ b/native_client_sdk/src/tools/nacl_gcc.mk
@@ -229,14 +229,14 @@ ifneq (,$(findstring x86_32,$(ARCHES)))
all: $(OUTDIR)/lib$(1)_x86_32.a
$(OUTDIR)/lib$(1)_x86_32.a: $(foreach src,$(2),$(call SRC_TO_OBJ,$(src),_x86_32))
$(MKDIR) -p $$(dir $$@)
- $(RM) $$@
+ $(RM) -f $$@
$(call LOG,LIB ,$$@,$(X86_32_LIB) -cr $$@ $$^)
$(STAMPDIR)/$(1).stamp: $(LIBDIR)/$(TOOLCHAIN)_x86_32/$(CONFIG)/lib$(1).a
install: $(LIBDIR)/$(TOOLCHAIN)_x86_32/$(CONFIG)/lib$(1).a
$(LIBDIR)/$(TOOLCHAIN)_x86_32/$(CONFIG)/lib$(1).a: $(OUTDIR)/lib$(1)_x86_32.a
$(MKDIR) -p $$(dir $$@)
- $(RM) $$@
+ $(RM) -f $$@
$(call LOG,CP ,$$@,$(OSHELPERS) cp $$^ $$@)
endif
@@ -244,7 +244,7 @@ ifneq (,$(findstring x86_64,$(ARCHES)))
all: $(OUTDIR)/lib$(1)_x86_64.a
$(OUTDIR)/lib$(1)_x86_64.a: $(foreach src,$(2),$(call SRC_TO_OBJ,$(src),_x86_64))
$(MKDIR) -p $$(dir $$@)
- $(RM) $$@
+ $(RM) -f $$@
$(call LOG,LIB ,$$@,$(X86_64_LIB) -cr $$@ $$^)
$(STAMPDIR)/$(1).stamp: $(LIBDIR)/$(TOOLCHAIN)_x86_64/$(CONFIG)/lib$(1).a
@@ -259,7 +259,7 @@ ifneq ($(TOOLCHAIN),glibc)
all: $(OUTDIR)/lib$(1)_arm.a
$(OUTDIR)/lib$(1)_arm.a: $(foreach src,$(2),$(call SRC_TO_OBJ,$(src),_arm))
$(MKDIR) -p $$(dir $$@)
- $(RM) $$@
+ $(RM) -f $$@
$(call LOG,LIB ,$$@,$(ARM_LIB) -cr $$@ $$^)
$(STAMPDIR)/$(1).stamp: $(LIBDIR)/$(TOOLCHAIN)_arm/$(CONFIG)/lib$(1).a
diff --git a/native_client_sdk/src/tools/nacl_llvm.mk b/native_client_sdk/src/tools/nacl_llvm.mk
index a3df27102e..16d6f2d833 100644
--- a/native_client_sdk/src/tools/nacl_llvm.mk
+++ b/native_client_sdk/src/tools/nacl_llvm.mk
@@ -80,7 +80,7 @@ $(STAMPDIR)/$(1).stamp: $(LIBDIR)/$(TOOLCHAIN)/$(CONFIG)/lib$(1).a
all: $(LIBDIR)/$(TOOLCHAIN)/$(CONFIG)/lib$(1).a
$(LIBDIR)/$(TOOLCHAIN)/$(CONFIG)/lib$(1).a: $(foreach src,$(2),$(call SRC_TO_OBJ,$(src),_pnacl))
$(MKDIR) -p $$(dir $$@)
- $(RM) $$@
+ $(RM) -f $$@
$(call LOG,LIB,$$@,$(PNACL_LIB) -cr $$@ $$^ $(3))
endef
diff --git a/native_client_sdk/src/tools/sel_ldr.py b/native_client_sdk/src/tools/sel_ldr.py
index d730ffbe71..97adf241dc 100755
--- a/native_client_sdk/src/tools/sel_ldr.py
+++ b/native_client_sdk/src/tools/sel_ldr.py
@@ -34,9 +34,8 @@ Log.verbose = False
def main(argv):
usage = 'Usage: %prog [options] <.nexe>'
- description = __doc__
epilog = 'Example: sel_ldr.py my_nexe.nexe'
- parser = optparse.OptionParser(usage, description=description, epilog=epilog)
+ parser = optparse.OptionParser(usage, description=__doc__, epilog=epilog)
parser.add_option('-v', '--verbose', action='store_true',
help='Verbose output')
parser.add_option('-d', '--debug', action='store_true',
@@ -44,6 +43,16 @@ def main(argv):
parser.add_option('--debug-libs', action='store_true',
help='For dynamic executables, reference debug '
'libraries rather then release')
+
+ # To enable bash completion for this command first install optcomplete
+ # and then add this line to your .bashrc:
+ # complete -F _optcomplete sel_ldr.py
+ try:
+ import optcomplete
+ optcomplete.autocomplete(parser)
+ except ImportError:
+ pass
+
options, args = parser.parse_args(argv)
if not args:
parser.error('No executable file specified')