summaryrefslogtreecommitdiffstats
path: root/native_client_sdk/src/examples
diff options
context:
space:
mode:
authornoelallen@google.com <noelallen@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2012-02-01 22:34:58 +0000
committernoelallen@google.com <noelallen@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2012-02-01 22:34:58 +0000
commit0e151bf97ba5c90fdbf937722e0b4f97aeb5e99b (patch)
tree2ec337c5ffad394e5f87887b97bacebd18708651 /native_client_sdk/src/examples
parente4420b5e3668468358a80fbca729dd75161c0e24 (diff)
downloadchromium_src-0e151bf97ba5c90fdbf937722e0b4f97aeb5e99b.zip
chromium_src-0e151bf97ba5c90fdbf937722e0b4f97aeb5e99b.tar.gz
chromium_src-0e151bf97ba5c90fdbf937722e0b4f97aeb5e99b.tar.bz2
Support GLBIC example in SDK
This CL added two new examples for the NaCl SDK. This only affects SDK bots since the code is completely contained within native_client_sdk subtree. Fix incorrectly placed ppapi headers. Remove TODOs and cleanup create_nmf.py. Add hello_world_glibc example Add dlopen example. BUG= 111224 Review URL: https://chromiumcodereview.appspot.com/9234043 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@120117 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'native_client_sdk/src/examples')
-rw-r--r--native_client_sdk/src/examples/dlopen/Makefile209
-rw-r--r--native_client_sdk/src/examples/dlopen/dlopen.cc168
-rw-r--r--native_client_sdk/src/examples/dlopen/dlopen.html71
-rw-r--r--native_client_sdk/src/examples/dlopen/eightball.cc20
-rw-r--r--native_client_sdk/src/examples/dlopen/eightball.h9
-rwxr-xr-xnative_client_sdk/src/examples/dlopen/make.bat1
-rw-r--r--native_client_sdk/src/examples/hello_world_glibc/Makefile200
-rw-r--r--native_client_sdk/src/examples/hello_world_glibc/hello_world.cc135
-rw-r--r--native_client_sdk/src/examples/hello_world_glibc/hello_world.html126
-rw-r--r--native_client_sdk/src/examples/hello_world_glibc/helper_functions.cc22
-rw-r--r--native_client_sdk/src/examples/hello_world_glibc/helper_functions.h34
-rwxr-xr-xnative_client_sdk/src/examples/hello_world_glibc/make.bat1
12 files changed, 996 insertions, 0 deletions
diff --git a/native_client_sdk/src/examples/dlopen/Makefile b/native_client_sdk/src/examples/dlopen/Makefile
new file mode 100644
index 0000000..adf8a78
--- /dev/null
+++ b/native_client_sdk/src/examples/dlopen/Makefile
@@ -0,0 +1,209 @@
+# Copyright (c) 2011 The Native Client 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 Make based build file.  For details on GNU Make see:
+#   http://www.gnu.org/software/make/manual/make.html
+#
+
+#
+# Project information
+#
+# These variables store project specific settings for the project name
+# build flags, files to copy or install.  In the examples it is typically
+# only the list of sources and project name that will actually change and
+# the rest of the makefile is boilerplate for defining build rules.
+#
+PROJECT:=dlopen
+COPY_FILES:=dlopen.html
+LDFLAGS:=-ldl -lppapi_cpp -lppapi
+
+NEXES:=$(PROJECT)_x86_32.nexe $(PROJECT)_x86_64.nexe
+NEXES+=lib32/libeightball.so lib64/libeightball.so
+
+#
+# Get pepper directory for toolchain and includes.
+#
+# If PEPPER_ROOT is not set, then assume it can be found a two directories up,
+# from the default example directory location.
+#
+THIS_MAKEFILE:=$(abspath $(lastword $(MAKEFILE_LIST)))
+PEPPER_ROOT?=$(abspath $(dir $(THIS_MAKEFILE))../..)
+
+# Project Build flags
+DEFINES:=
+INCLUDES:=
+WARNINGS:=-Wno-long-long -Wall -Wswitch-enum
+CXXFLAGS:=-pthread $(WARNINGS) $(DEFINES) $(INCLUDES)
+
+#
+# Compute tool paths
+#
+#
+OSNAME:=$(shell python $(PEPPER_ROOT)/tools/getos.py)
+TC_PATH:=$(abspath $(PEPPER_ROOT)/toolchain/$(OSNAME)_x86_glibc)
+CC:=$(TC_PATH)/bin/i686-nacl-gcc
+CXX:=$(TC_PATH)/bin/i686-nacl-g++
+STRIP:=$(TC_PATH)/bin/i686-nacl-strip
+
+#
+# Create shell aliases
+#
+# Create Python based aliases for common shell commands like copy or move.
+#
+COPY:= python $(PEPPER_ROOT)/tools/oshelpers.py cp
+MKDIR:= python $(PEPPER_ROOT)/tools/oshelpers.py mkdir
+RM:= python $(PEPPER_ROOT)/tools/oshelpers.py rm
+MV:= python $(PEPPER_ROOT)/tools/oshelpers.py mv
+
+#
+# NMF Manifiest generation
+#
+NMF:=python $(PEPPER_ROOT)/tools/create_nmf.py
+NMF+=-D $(TC_PATH)/x86_64-nacl/bin/objdump
+NMF_PATHS:=-L $(TC_PATH)/x86_64-nacl/lib32 -L $(TC_PATH)/x86_64-nacl/lib
+NMF_PATHS+=-L lib32 -L lib64
+
+#
+# Disable DOS PATH warning when using Cygwin based tools Windows
+#
+CYGWIN ?= nodosfilewarning
+export CYGWIN
+
+#
+# Define a macro for copying files to the configuration directory
+#
+# Copys a source file to the destination directory, removing the base path
+# from the source. Adds a dependency to the destination directory in case it
+# needs to be created.
+#
+# $(1) = Source file
+# $(2) = Destination directory
+define FILE_COPY
+$(2)/$(notdir $(1)) : $(1) | $(2)
+ $(COPY) $(1) $(2)
+$(2)_COPIES+=$(2)/$(notdir $(1))
+endef
+
+
+# Declare the ALL target first, to make the 'all' target the default build
+all: DEBUG RELEASE
+
+
+
+#
+# Debug Build rules.
+#
+DEBUG_x86_32_FLAGS:=-m32 -O0 -g
+DEBUG_x86_64_FLAGS:=-m64 -O0 -g
+
+# Create DBG configuration directories
+DBG:
+ $(MKDIR) -p $@
+
+DBG/lib32:
+ $(MKDIR) -p $@
+
+DBG/lib64:
+ $(MKDIR) -p $@
+
+# Copy all files to that config
+$(foreach src,$(COPY_FILES),$(eval $(call FILE_COPY,$(src),DBG)))
+
+# Build debug version dlopen nexe and eightball.so for 32 and 64 bit.
+DBG/dlopen_x86_32.o: dlopen.cc $(THIS_MAKE) | DBG
+ $(CXX) -o $@ -c $< $(DEBUG_x86_32_FLAGS) $(CXXFLAGS)
+
+DBG/dlopen_x86_32.nexe: DBG/dlopen_x86_32.o $(THIS_MAKE) | DBG
+ $(CXX) -o $@ $< $(DEBUG_x86_32_FLAGS) $(LDFLAGS)
+
+DBG/dlopen_x86_64.o: dlopen.cc $(THIS_MAKE) | DBG
+ $(CXX) -o $@ -c $< $(DEBUG_x86_64_FLAGS) $(CXXFLAGS)
+
+DBG/dlopen_x86_64.nexe: DBG/dlopen_x86_64.o $(THIS_MAKE) | DBG
+ $(CXX) -o $@ $< $(DEBUG_x86_64_FLAGS) $(LDFLAGS)
+
+DBG/eightball_x86_32.o: eightball.cc $(THIS_MAKE) | DBG
+ $(CXX) -o $@ -c $< $(DEBUG_x86_32_FLAGS) $(CXXFLAGS) -fPIC
+
+DBG/lib32/libeightball.so: DBG/eightball_x86_32.o $(THIS_MAKE) | DBG/lib32
+ $(CXX) -o $@ $< $(DEBUG_x86_32_FLAGS) $(LDFLAGS) -shared
+
+DBG/eightball_x86_64.o: eightball.cc $(THIS_MAKE) | DBG
+ $(CXX) -o $@ -c $< $(DEBUG_x86_64_FLAGS) $(CXXFLAGS) -fPIC
+
+DBG/lib64/libeightball.so: DBG/eightball_x86_64.o $(THIS_MAKE) | DBG/lib64
+ $(CXX) -o $@ $< $(DEBUG_x86_64_FLAGS) $(LDFLAGS) -shared
+
+# Define rule for building NMF file and copying dependencies
+DBG_NEXES:=$(foreach src,$(NEXES),DBG/$(src))
+
+DBG/$(PROJECT).nmf : $(DBG_NEXES)
+ cd DBG && $(NMF) -o dlopen.nmf -s . $(NMF_PATHS) $(NEXES)
+
+# Define a DEBUG alias to build the debug version
+.PHONY : DEBUG RUN_DEBUG
+DEBUG : $(DBG_NEXES) DBG/$(PROJECT).nmf $(DBG_COPIES)
+
+# Define a RUN_DEBUG alias to build and server the DEBUG version
+RUN_DEBUG: DEBUG
+ cd DBG && python ../../httpd.py
+
+
+#
+# Release build rules.
+#
+RELEASE_x86_32_FLAGS:=-m32 -O2
+RELEASE_x86_64_FLAGS:=-m64 -O2
+
+REL:
+ $(MKDIR) -p $@
+
+REL/lib32:
+ $(MKDIR) -p $@
+
+REL/lib64:
+ $(MKDIR) -p $@
+
+# Copy all files to that config
+$(foreach src,$(COPY_FILES),$(eval $(call FILE_COPY,$(src),REL)))
+
+# Build release version dlopen nexe and eightball.so for 32 and 64 bit.
+REL/dlopen_x86_32.o: dlopen.cc $(THIS_MAKE) | REL
+ $(CXX) -o $@ -c $< $(RELEASE_x86_32_FLAGS) $(CXXFLAGS)
+
+REL/dlopen_x86_32.nexe: REL/dlopen_x86_32.o $(THIS_MAKE) | REL
+ $(CXX) -o $@ $< $(RELEASE_x86_32_FLAGS) $(LDFLAGS)
+
+REL/dlopen_x86_64.o: dlopen.cc $(THIS_MAKE) | REL
+ $(CXX) -o $@ -c $< $(RELEASE_x86_64_FLAGS) $(CXXFLAGS)
+
+REL/dlopen_x86_64.nexe: REL/dlopen_x86_64.o $(THIS_MAKE) | REL
+ $(CXX) -o $@ $< $(RELEASE_x86_64_FLAGS) $(LDFLAGS)
+
+REL/eightball_x86_32.o: eightball.cc $(THIS_MAKE) | REL/lib32
+ $(CXX) -o $@ -c $< $(RELEASE_x86_32_FLAGS) $(CXXFLAGS) -fPIC
+
+REL/lib32/libeightball.so: REL/eightball_x86_32.o $(THIS_MAKE) | REL/lib32
+ $(CXX) -o $@ $< $(RELEASE_x86_32_FLAGS) $(LDFLAGS) -shared
+
+REL/eightball_x86_64.o: eightball.cc $(THIS_MAKE) | REL/lib64
+ $(CXX) -o $@ -c $< $(RELEASE_x86_64_FLAGS) $(CXXFLAGS) -fPIC
+
+REL/lib64/libeightball.so: REL/eightball_x86_64.o $(THIS_MAKE) | REL/lib64
+ $(CXX) -o $@ $< $(RELEASE_x86_64_FLAGS) $(LDFLAGS) -shared
+
+# Define rule for building NMF file and copying dependencies
+REL_NEXES:=$(foreach src,$(NEXES),REL/$(src))
+
+REL/$(PROJECT).nmf : $(REL_NEXES)
+ cd REL && $(NMF) -o dlopen.nmf -s . $(NMF_PATHS) $(NEXES)
+
+# Define a RELEASE alias to build the release version
+.PHONY : RELEASE RUN_RELEASE
+RELEASE : $(REL_NEXES) REL/$(PROJECT).nmf $(REL_COPIES)
+
+# Define a RUN_RELEASE alias to build and server the RELEASE version
+RUN_RELEASE: RELEASE
+ cd REL && python ../../httpd.py
diff --git a/native_client_sdk/src/examples/dlopen/dlopen.cc b/native_client_sdk/src/examples/dlopen/dlopen.cc
new file mode 100644
index 0000000..27f7c7c
--- /dev/null
+++ b/native_client_sdk/src/examples/dlopen/dlopen.cc
@@ -0,0 +1,168 @@
+// Copyright (c) 2012 The Native Client 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
+/// This example demonstrates building a dynamic library which is loaded by the
+/// NaCl module. To load the NaCl module, the browser first looks for the
+/// CreateModule() factory method (at the end of this file). It calls
+/// CreateModule() once to load the module code from your .nexe. After the
+/// .nexe code is loaded, CreateModule() is not called again.
+///
+/// Once the .nexe code is loaded, the browser then calls the CreateInstance()
+/// method on the object returned by CreateModule(). If the CreateInstance
+/// returns successfully, then Init function is called, which will load the
+/// shared object on a worker thread. We use a worker because dlopen is
+/// a blocking call, which is not alowed on the main thread.
+
+#include <dlfcn.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+
+#include <ppapi/cpp/module.h>
+#include <ppapi/cpp/completion_callback.h>
+#include <ppapi/cpp/var.h>
+#include <ppapi/cpp/instance.h>
+
+#include "eightball.h"
+
+/// The Instance class. One of these exists for each instance of your NaCl
+/// module on the web page. The browser will ask the Module object to create
+/// a new Instance for each occurrence of the <embed> tag that has these
+/// attributes:
+/// <pre>
+/// type="application/x-nacl"
+/// nacl="dlopen.nmf"
+/// </pre>
+class dlOpenInstance : public pp::Instance {
+ public:
+ explicit dlOpenInstance(pp::Core *core, PP_Instance instance):
+ pp::Instance(instance) {
+ _dlhandle = NULL;
+ _eightball = NULL;
+ _core = core;
+ _tid = 0;
+ };
+ virtual ~dlOpenInstance(){};
+
+ // Helper function to post a message back to the JS and stdout functions.
+ void logmsg(const char* pStr){
+ PostMessage(pp::Var(pStr));
+ fprintf(stdout, pStr);
+ }
+
+ // Initialize the module, staring a worker thread to load the shared object.
+ virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]){
+ logmsg("Spawning thread to cache .so files...");
+ if (pthread_create(&_tid, NULL, LoadLibrariesOnWorker, this)) {
+ logmsg("ERROR; pthread_create() failed.\n");
+ return false;
+ }
+ return true;
+ }
+
+ // This function is called on a worker thread, and will call dlopen to load
+ // 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 int32_t IMMEDIATELY = 0;
+ _dlhandle = dlopen("libeightball.so", RTLD_LAZY);
+ pp::CompletionCallback cc(LoadDoneCB, this);
+ _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() {
+ _dlhandle = dlopen("libeightball.so", RTLD_LAZY);
+ if(_dlhandle == NULL) {
+ logmsg("libeightball.so did not load");
+ } else {
+ _eightball = (TYPE_eightball) dlsym(this->_dlhandle, "Magic8Ball");
+ if (NULL == _eightball) {
+ std::string ballmessage = "dlsym() returned NULL: ";
+ ballmessage += dlerror();
+ ballmessage += "\n";
+ logmsg(ballmessage.c_str());
+ }
+ else{
+ logmsg("Eightball loaded!");
+ }
+ }
+ }
+
+ // Called by the browser to handle the postMessage() call in Javascript.
+ virtual void HandleMessage(const pp::Var& var_message) {
+ if(NULL == _eightball){
+ logmsg("Eightball library not loaded");
+ return;
+ }
+
+ if (!var_message.is_string()) {
+ logmsg("Message is not a string.");
+ return;
+ }
+
+ std::string message = var_message.AsString();
+ if (message == "query") {
+ fprintf(stdout, "%s(%d) Got this far.\n", __FILE__, __LINE__);
+ std::string ballmessage = "!The Magic 8-Ball says: ";
+ ballmessage += this->_eightball();
+
+ logmsg(ballmessage.c_str());
+ fprintf(stdout, "%s(%d) Got this far.\n", __FILE__, __LINE__);
+ } else {
+ std::string errormsg = "Unexpected message: ";
+ errormsg += message + "\n";
+ logmsg(errormsg.c_str());
+ }
+ }
+
+ static void* LoadLibrariesOnWorker(void *pInst) {
+ dlOpenInstance *inst = static_cast<dlOpenInstance *>(pInst);
+ inst->LoadLibrary();
+ return NULL;
+ }
+
+ static void LoadDoneCB(void *pInst, int32_t result) {
+ dlOpenInstance *inst = static_cast<dlOpenInstance *>(pInst);
+ inst->UseLibrary();
+ }
+
+ private:
+ void *_dlhandle;
+ TYPE_eightball _eightball;
+ pp::Core *_core;
+ pthread_t _tid;
+
+ };
+
+// The Module class. The browser calls the CreateInstance() method to create
+// an instance of your NaCl module on the web page. The browser creates a new
+// instance for each <embed> tag with type="application/x-nacl".
+class dlOpenModule : public pp::Module {
+ public:
+ dlOpenModule() : pp::Module() {}
+ virtual ~dlOpenModule() {}
+
+ // Create and return a dlOpenInstance object.
+ virtual pp::Instance* CreateInstance(PP_Instance instance) {
+ return new dlOpenInstance(core(), instance);
+ }
+};
+
+
+// Factory function called by the browser when the module is first loaded.
+// The browser keeps a singleton of this module. It calls the
+// CreateInstance() method on the object you return to make instances. There
+// is one instance per <embed> tag on the page. This is the main binding
+// point for your NaCl module with the browser.
+namespace pp {
+ Module* CreateModule() {
+ return new dlOpenModule();
+ }
+} // namespace pp
+
diff --git a/native_client_sdk/src/examples/dlopen/dlopen.html b/native_client_sdk/src/examples/dlopen/dlopen.html
new file mode 100644
index 0000000..d964c0e
--- /dev/null
+++ b/native_client_sdk/src/examples/dlopen/dlopen.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<html>
+ <!--
+ Copyright (c) 2011 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>Magic Eightball</title>
+ <script type="text/javascript">
+
+ function moduleDidLoad() {
+ }
+
+ function handleMessage(message_event) {
+ if(message_event.data=='Eightball loaded!')
+ {
+ document.getElementById('consolec').innerHTML = " \
+Eightball loaded, type a question below, press the button, and get a response. \
+<br /> \
+<form name='form' Value='Hello Me' onSubmit='return askBall()'> \
+ <input type='textarea' size='64' name='inputtext' /> \
+ <input type='button' NAME='button' Value='ASK!' onClick='askBall()' /> \
+</form>";
+ }
+ else
+ {
+ if(message_event.data[0]=='!')
+ {
+ document.getElementById('answerlog').innerHTML +=
+ (document.form.inputtext.value + ": " + message_event.data +"<br />");
+ }
+ else
+ {
+ document.getElementById('consolec').innerHTML +=
+ message_event.data + "<br />";
+ console.log(message_event.data);
+ }
+ }
+ }
+
+ function pageDidUnload() {
+ clearInterval(paintInterval);
+ }
+
+ function askBall()
+ {
+ dlopen.postMessage('query');
+ return false;
+ }
+ </script>
+</head>
+<body id="bodyId" onunload="pageDidUnload()">
+<div id="listener">
+ <script type="text/javascript">
+ var listener = document.getElementById('listener')
+ listener.addEventListener('load', moduleDidLoad, true);
+ listener.addEventListener('message', handleMessage, true);
+ </script>
+<h1>The Magic 8 Ball </h1>
+<embed name="nacl_module"
+ id="dlopen"
+ width=1 height=1
+ src="dlopen.nmf"
+ type="application/x-nacl" />
+</div>
+ <br />
+ <div id="consolec">..loading dynamic libraries...</div>
+<div id="answerlog"></div>
+</body>
+</html>
diff --git a/native_client_sdk/src/examples/dlopen/eightball.cc b/native_client_sdk/src/examples/dlopen/eightball.cc
new file mode 100644
index 0000000..df2be2a
--- /dev/null
+++ b/native_client_sdk/src/examples/dlopen/eightball.cc
@@ -0,0 +1,20 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "eightball.h"
+
+extern "C" const char *Magic8Ball() {
+ const int NSIDES = 8;
+ const char* answer[NSIDES] = {
+ "YES",
+ "NO",
+ "MAYBE",
+ "MAYBE NOT",
+ "DEFINITELY",
+ "ASK ME TOMORROW",
+ "PARTLY CLOUDY",
+ "42",
+ };
+ return answer[rand() % NSIDES];
+}
+
diff --git a/native_client_sdk/src/examples/dlopen/eightball.h b/native_client_sdk/src/examples/dlopen/eightball.h
new file mode 100644
index 0000000..d0924d3
--- /dev/null
+++ b/native_client_sdk/src/examples/dlopen/eightball.h
@@ -0,0 +1,9 @@
+#ifndef __EIGHTBALL_H__
+#define __EIGHTBALL_H__
+
+/* Return an answer. Question not required */
+typedef char* (*TYPE_eightball)(void);
+extern "C" const char* Magic8Ball();
+
+#endif /* __EIGHTBALL_H__ */
+
diff --git a/native_client_sdk/src/examples/dlopen/make.bat b/native_client_sdk/src/examples/dlopen/make.bat
new file mode 100755
index 0000000..479d648
--- /dev/null
+++ b/native_client_sdk/src/examples/dlopen/make.bat
@@ -0,0 +1 @@
+@..\..\tools\make.exe %*
diff --git a/native_client_sdk/src/examples/hello_world_glibc/Makefile b/native_client_sdk/src/examples/hello_world_glibc/Makefile
new file mode 100644
index 0000000..cf14374
--- /dev/null
+++ b/native_client_sdk/src/examples/hello_world_glibc/Makefile
@@ -0,0 +1,200 @@
+# Copyright (c) 2012 The Native Client 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 Make based build file.  For details on GNU Make see:
+#   http://www.gnu.org/software/make/manual/make.html
+#
+
+#
+# Project information
+#
+# These variables store project specific settings for the project name
+# build flags, files to copy or install.  In the examples it is typically
+# only the list of sources and project name that will actually change and
+# the rest of the makefile is boilerplate for defining build rules.
+#
+PROJECT:=hello_world
+CXX_SOURCES:=hello_world.cc helper_functions.cc
+COPY_FILES:=hello_world.html
+LDFLAGS:=-lppapi_cpp -lppapi
+
+
+#
+# Get pepper directory for toolchain and includes.
+#
+# If PEPPER_ROOT is not set, then assume it can be found a two directories up,
+# from the default example directory location.
+#
+THIS_MAKEFILE:=$(abspath $(lastword $(MAKEFILE_LIST)))
+PEPPER_ROOT?=$(abspath $(dir $(THIS_MAKEFILE))../..)
+
+# Project Build flags
+DEFINES:=
+INCLUDES:=
+WARNINGS:=-Wno-long-long -Wall -Wswitch-enum -pedantic -Werror
+CXXFLAGS:= -shared -pthread -std=gnu++98 $(WARNINGS) $(DEFINES) $(INCLUDES)
+
+#
+# Compute tool paths
+#
+#
+OSNAME:=$(shell python $(PEPPER_ROOT)/tools/getos.py)
+TC_PATH:=$(abspath $(PEPPER_ROOT)/toolchain/$(OSNAME)_x86_glibc)
+CC:=$(TC_PATH)/bin/i686-nacl-gcc
+CXX:=$(TC_PATH)/bin/i686-nacl-g++
+STRIP:=$(TC_PATH)/bin/i686-nacl-strip
+
+#
+# Create shell aliases
+#
+# Create Python based aliases for common shell commands like copy or move.
+#
+COPY:= python $(PEPPER_ROOT)/tools/oshelpers.py cp
+MKDIR:= python $(PEPPER_ROOT)/tools/oshelpers.py mkdir
+RM:= python $(PEPPER_ROOT)/tools/oshelpers.py rm
+MV:= python $(PEPPER_ROOT)/tools/oshelpers.py mv
+
+#
+# NMF Manifiest generation
+#
+NMF:=python $(PEPPER_ROOT)/tools/create_nmf.py
+NMF+=-D $(TC_PATH)/x86_64-nacl/bin/objdump
+NMF_PATHS:=-L $(TC_PATH)/x86_64-nacl/lib32 -L $(TC_PATH)/x86_64-nacl/lib
+
+#
+# Disable DOS PATH warning when using Cygwin based tools Windows
+#
+CYGWIN ?= nodosfilewarning
+export CYGWIN
+
+#
+# Define a macro for copying files to the configuration directory
+#
+# Copys a source file to the destination directory, removing the base path
+# from the source. Adds a dependency to the destination directory in case it
+# needs to be created.
+#
+# $(1) = Source file
+# $(2) = Destination directory
+define FILE_COPY
+$(2)/$(notdir $(1)) : $(1) | $(2)
+ $(COPY) $(1) $(2)
+$(2)_COPIES+=$(2)/$(notdir $(1))
+endef
+
+
+# Declare the ALL target first, to make the 'all' target the default build
+all: DEBUG RELEASE
+
+
+#
+# Debug Build rules.
+#
+DEBUG_x86_32_FLAGS:=-m32 -O0 -g
+DEBUG_x86_64_FLAGS:=-m64 -O0 -g
+DEBUG_x86_32_OBJS:=$(patsubst %.cc,DBG/x86_32/%.o,$(CXX_SOURCES))
+DEBUG_x86_64_OBJS:=$(patsubst %.cc,DBG/x86_64/%.o,$(CXX_SOURCES))
+
+# Create DBG configuration directories
+DBG:
+ $(MKDIR) -p $@
+
+DBG/x86_32:
+ $(MKDIR) -p $@
+
+DBG/x86_64:
+ $(MKDIR) -p $@
+
+# Copy all files to that config
+$(foreach src,$(COPY_FILES),$(eval $(call FILE_COPY,$(src),DBG)))
+
+# Include generated dependencies
+-include DBG/x86_32/*.d
+-include DBG/x86_64/*.d
+
+# Define compile rule for all 32 bit debug objects
+DBG/x86_32/%.o : %.cc $(THIS_MAKE) | DBG/x86_32
+ $(CXX) -o $@ -c $< $(DEBUG_x86_32_FLAGS) $(CXXFLAGS) -MMD -MF $@.d
+
+# Define compile rule for all 64 bit debug objects
+DBG/x86_64/%.o : %.cc $(THIS_MAKE) | DBG/x86_64
+ $(CXX) -o $@ -c $< $(DEBUG_x86_64_FLAGS) $(CXXFLAGS) -MMD -MF $@.d
+
+# Define Link rule for 32 bit debug NEXE
+DBG/$(PROJECT)_x86_32.nexe : $(DEBUG_x86_32_OBJS)
+ $(CXX) -o $@ $^ $(DEBUG_x86_32_FLAGS) $(LDFLAGS)
+
+# Define Link rule for 64 bit debug NEXE
+DBG/$(PROJECT)_x86_64.nexe : $(DEBUG_x86_64_OBJS)
+ $(CXX) -o $@ $^ $(DEBUG_x86_64_FLAGS) $(LDFLAGS)
+
+# Define rule for building NMF file and copying dependencies
+DBG/$(PROJECT).nmf : DBG/$(PROJECT)_x86_64.nexe DBG/$(PROJECT)_x86_32.nexe
+ $(NMF) -o $@ -s DBG $(NMF_PATHS) $^
+
+# Define a DEBUG alias to build the debug version
+DBG_NEXES:= DBG/$(PROJECT)_x86_32.nexe DBG/$(PROJECT)_x86_64.nexe
+.PHONY : DEBUG RUN_DEBUG
+DEBUG : $(DBG_NEXES) DBG/$(PROJECT).nmf $(DBG_COPIES)
+
+# Define a RUN_DEBUG alias to build and server the DEBUG version
+RUN_DEBUG: DEBUG
+ cd DBG && python ../../httpd.py
+
+
+#
+# Release build rules.
+#
+RELEASE_x86_32_FLAGS:=-m32 -O2 -g
+RELEASE_x86_64_FLAGS:=-m64 -O2 -g
+RELEASE_x86_32_OBJS:=$(patsubst %.cc,REL/x86_32/%.o,$(CXX_SOURCES))
+RELEASE_x86_64_OBJS:=$(patsubst %.cc,REL/x86_64/%.o,$(CXX_SOURCES))
+
+REL:
+ $(MKDIR) -p $@
+
+REL/x86_32:
+ $(MKDIR) -p $@
+
+REL/x86_64:
+ $(MKDIR) -p $@
+
+# Copy all files to that config
+$(foreach src,$(COPY_FILES),$(eval $(call FILE_COPY,$(src),REL)))
+
+# Include generated dependencies
+-include REL/x86_32/*.d
+-include REL/x86_64/*.d
+
+# Define compile rule for all 32 bit debug objects
+REL/x86_32/%.o : %.cc $(THIS_MAKE) | REL/x86_32
+ $(CXX) -o $@ -c $< $(RELEASE_x86_32_FLAGS) $(CXXFLAGS) -MMD -MF $@.d
+
+# Define compile rule for all 64 bit debug objects
+REL/x86_64/%.o : %.cc $(THIS_MAKE) | REL/x86_64
+ $(CXX) -o $@ -c $< $(RELEASE_x86_64_FLAGS) $(CXXFLAGS) -MMD -MF $@.d
+
+# Define Link rule for 32 bit optimized and stripped NEXE
+REL/$(PROJECT)_x86_32.nexe : $(RELEASE_x86_32_OBJS)
+ $(CXX) -o $@.unstripped $^ $(RELEASE_x86_32_FLAGS) $(LDFLAGS)
+ $(STRIP) $< -o $@
+
+# Define Link rule for 64 bit optimized and stripped NEXE
+REL/$(PROJECT)_x86_64.nexe : $(RELEASE_x86_64_OBJS)
+ $(CXX) -o $@.unstripped $^ $(RELEASE_x86_64_FLAGS) $(LDFLAGS)
+ $(STRIP) $@.unstripped -o $@
+
+# Define rule for building NMF file and copying dependencies
+REL/$(PROJECT).nmf : REL/$(PROJECT)_x86_64.nexe REL/$(PROJECT)_x86_32.nexe
+ $(NMF) -o $@ -s REL $(NMF_PATHS) $^
+
+# Define a RELEASE alias to build the debug version
+.PHONY : RELEASE RUN_RELEASE
+REL_NEXES:=REL/$(PROJECT)_x86_32.nexe REL/$(PROJECT)_x86_64.nexe
+RELEASE : $(REL_NEXES) REL/$(PROJECT).nmf $(REL_COPIES)
+
+# Define a RUN_RELEASE alias to build and server the RELEASE version
+RUN_RELEASE: RELEASE
+ cd REL && python ../../httpd.py
diff --git a/native_client_sdk/src/examples/hello_world_glibc/hello_world.cc b/native_client_sdk/src/examples/hello_world_glibc/hello_world.cc
new file mode 100644
index 0000000..438b7bf
--- /dev/null
+++ b/native_client_sdk/src/examples/hello_world_glibc/hello_world.cc
@@ -0,0 +1,135 @@
+// 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
+/// This example demonstrates loading, running and scripting a very simple NaCl
+/// module. To load the NaCl module, the browser first looks for the
+/// CreateModule() factory method (at the end of this file). It calls
+/// CreateModule() once to load the module code from your .nexe. After the
+/// .nexe code is loaded, CreateModule() is not called again.
+///
+/// Once the .nexe code is loaded, the browser then calls the
+/// HelloWorldModule::CreateInstance()
+/// method on the object returned by CreateModule(). It calls CreateInstance()
+/// each time it encounters an <embed> tag that references your NaCl module.
+
+#include <cstdio>
+#include <cstring>
+#include <string>
+#include "ppapi/cpp/instance.h"
+#include "ppapi/cpp/module.h"
+#include "ppapi/cpp/var.h"
+
+#include "helper_functions.h"
+
+namespace hello_world {
+/// Method name for ReverseText, as seen by JavaScript code.
+const char* const kReverseTextMethodId = "reverseText";
+
+/// Method name for FortyTwo, as seen by Javascript code. @see FortyTwo()
+const char* const kFortyTwoMethodId = "fortyTwo";
+
+/// Separator character for the reverseText method.
+static const char kMessageArgumentSeparator = ':';
+
+/// This is the module's function that invokes FortyTwo and converts the return
+/// value from an int32_t to a pp::Var for return.
+pp::Var MarshallFortyTwo() {
+ return pp::Var(FortyTwo());
+}
+
+/// This function is passed the arg list from the JavaScript call to
+/// @a reverseText.
+/// It makes sure that there is one argument and that it is a string, returning
+/// an error message if it is not.
+/// On good input, it calls ReverseText and returns the result. The result is
+/// then sent back via a call to PostMessage.
+pp::Var MarshallReverseText(const std::string& text) {
+ return pp::Var(ReverseText(text));
+}
+
+/// The Instance class. One of these exists for each instance of your NaCl
+/// module on the web page. The browser will ask the Module object to create
+/// a new Instance for each occurrence of the <embed> tag that has these
+/// attributes:
+/// <pre>
+/// type="application/x-nacl"
+/// nacl="hello_world.nmf"
+/// </pre>
+class HelloWorldInstance : public pp::Instance {
+ public:
+ explicit HelloWorldInstance(PP_Instance instance) : pp::Instance(instance) {
+ printf("HelloWorldInstance.\n");
+ }
+ virtual ~HelloWorldInstance() {}
+
+ /// Called by the browser to handle the postMessage() call in Javascript.
+ /// Detects which method is being called from the message contents, and
+ /// calls the appropriate function. Posts the result back to the browser
+ /// asynchronously.
+ /// @param[in] var_message The message posted by the browser. The possible
+ /// messages are 'fortyTwo' and 'reverseText:Hello World'. Note that
+ /// the 'reverseText' form contains the string to reverse following a ':'
+ /// separator.
+ virtual void HandleMessage(const pp::Var& var_message);
+};
+
+void HelloWorldInstance::HandleMessage(const pp::Var& var_message) {
+ if (!var_message.is_string()) {
+ return;
+ }
+ std::string message = var_message.AsString();
+ pp::Var return_var;
+ if (message == kFortyTwoMethodId) {
+ // Note that no arguments are passed in to FortyTwo.
+ return_var = MarshallFortyTwo();
+ } else if (message.find(kReverseTextMethodId) == 0) {
+ // The argument to reverseText is everything after the first ':'.
+ size_t sep_pos = message.find_first_of(kMessageArgumentSeparator);
+ if (sep_pos != std::string::npos) {
+ std::string string_arg = message.substr(sep_pos + 1);
+ return_var = MarshallReverseText(string_arg);
+ }
+ }
+ // Post the return result back to the browser. Note that HandleMessage() is
+ // always called on the main thread, so it's OK to post the return message
+ // directly from here. The return post is asynhronous: PostMessage returns
+ // immediately.
+ PostMessage(return_var);
+}
+
+/// The Module class. The browser calls the CreateInstance() method to create
+/// an instance of your NaCl module on the web page. The browser creates a new
+/// instance for each <embed> tag with
+/// <code>type="application/x-nacl"</code>.
+class HelloWorldModule : public pp::Module {
+ public:
+ HelloWorldModule() : pp::Module() {
+ printf("Got here.\n");
+ }
+ virtual ~HelloWorldModule() {}
+
+ /// Create and return a HelloWorldInstance object.
+ /// @param[in] instance a handle to a plug-in instance.
+ /// @return a newly created HelloWorldInstance.
+ /// @note The browser is responsible for calling @a delete when done.
+ virtual pp::Instance* CreateInstance(PP_Instance instance) {
+ return new HelloWorldInstance(instance);
+ }
+};
+} // namespace hello_world
+
+
+namespace pp {
+/// Factory function called by the browser when the module is first loaded.
+/// The browser keeps a singleton of this module. It calls the
+/// CreateInstance() method on the object you return to make instances. There
+/// is one instance per <embed> tag on the page. This is the main binding
+/// point for your NaCl module with the browser.
+/// @return new HelloWorldModule.
+/// @note The browser is responsible for deleting returned @a Module.
+Module* CreateModule() {
+ return new hello_world::HelloWorldModule();
+}
+} // namespace pp
diff --git a/native_client_sdk/src/examples/hello_world_glibc/hello_world.html b/native_client_sdk/src/examples/hello_world_glibc/hello_world.html
new file mode 100644
index 0000000..ec1b4e7
--- /dev/null
+++ b/native_client_sdk/src/examples/hello_world_glibc/hello_world.html
@@ -0,0 +1,126 @@
+<!DOCTYPE html>
+<html>
+ <!--
+ Copyright (c) 2011 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, World!</title>
+
+ <script type="text/javascript">
+ helloWorldModule = null; // Global application object.
+ statusText = 'NO-STATUS';
+
+ // Indicate success when the NaCl module has loaded.
+ function moduleDidLoad() {
+ helloWorldModule = document.getElementById('hello_world');
+ updateStatus('SUCCESS');
+ }
+
+ // Handle a message coming from the NaCl module.
+ function handleMessage(message_event) {
+ alert(message_event.data);
+ }
+
+ // If the page loads before the Native Client module loads, then set the
+ // status message indicating that the module is still loading. Otherwise,
+ // do not change the status message.
+ function pageDidLoad() {
+ // Set the focus on the text input box. Doing this means you can press
+ // return as soon as the page loads, and it will fire the reversetText()
+ // function.
+ document.forms.helloForm.inputBox.focus();
+ if (helloWorldModule == null) {
+ updateStatus('LOADING...');
+ } 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();
+ }
+ }
+
+ function fortyTwo() {
+ helloWorldModule.postMessage('fortyTwo');
+ }
+
+ function reverseText() {
+ // Grab the text from the text box, pass it into reverseText()
+ var inputBox = document.forms.helloForm.inputBox;
+ helloWorldModule.postMessage('reverseText:' + inputBox.value);
+ // Note: a |false| return tells the <form> tag to cancel the GET action
+ // when submitting the form.
+ return false;
+ }
+
+ // Set the global status message. If the element with id 'statusField'
+ // exists, then set its HTML to the status message as well.
+ // opt_message The message test. If this is null or undefined, then
+ // attempt to set the element with id 'statusField' to the value of
+ // |statusText|.
+ function updateStatus(opt_message) {
+ if (opt_message)
+ statusText = opt_message;
+ var statusField = document.getElementById('statusField');
+ if (statusField) {
+ statusField.innerHTML = statusText;
+ }
+ }
+ </script>
+</head>
+<body onload="pageDidLoad()">
+
+<h1>Native Client Simple Module</h1>
+<p>
+ <form name="helloForm"
+ action=""
+ method="get"
+ onsubmit="return reverseText()">
+ <input type="text" id="inputBox" name="inputBox" value="Hello world" /><p/>
+ <input type="button" value="Call fortyTwo()" onclick="fortyTwo()" />
+ <input type="submit" value="Call reverseText()" />
+ </form>
+ <!-- Load the published .nexe. This includes the 'src' attribute which
+ shows how to load multi-architecture modules. Each entry in the "nexes"
+ object in the .nmf manifest file is a key-value pair: the key is the runtime
+ ('x86-32', 'x86-64', etc.); the value is a URL for the desired NaCl module.
+ To load the debug versions of your .nexes, set the 'src' attribute to the
+ _dbg.nmf version of the manifest file.
+
+ Note: 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. This also allows you to use PPB_Messaging.PostMessage() (in C) or
+ pp::Instance.PostMessage() (in C++) from within the initialization code in
+ your NaCl module.
+ -->
+ <div id="listener">
+ <script type="text/javascript">
+ var listener = document.getElementById('listener')
+ listener.addEventListener('load', moduleDidLoad, true);
+ listener.addEventListener('message', handleMessage, true);
+ </script>
+
+ <embed name="nacl_module"
+ id="hello_world"
+ width=0 height=0
+ src="hello_world.nmf"
+ type="application/x-nacl" />
+ </div>
+
+</p>
+
+<p>If the module is working correctly, a click on the "Call fortyTwo()" button
+ should open a popup dialog containing <b>42</b> as its value.</p>
+
+<p> Clicking on the "Call reverseText()" button
+ should open a popup dialog containing the textbox contents and its reverse
+ as its value.</p>
+
+<h2>Status</h2>
+<div id="statusField">NO-STATUS</div>
+</body>
+</html>
diff --git a/native_client_sdk/src/examples/hello_world_glibc/helper_functions.cc b/native_client_sdk/src/examples/hello_world_glibc/helper_functions.cc
new file mode 100644
index 0000000..2b43c605
--- /dev/null
+++ b/native_client_sdk/src/examples/hello_world_glibc/helper_functions.cc
@@ -0,0 +1,22 @@
+// 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.
+
+#include <algorithm>
+
+#include "helper_functions.h"
+
+namespace hello_world {
+
+int32_t FortyTwo() {
+ return 42;
+}
+
+std::string ReverseText(const std::string& text) {
+ std::string reversed_string(text);
+ // Use reverse to reverse |reversed_string| in place.
+ std::reverse(reversed_string.begin(), reversed_string.end());
+ return reversed_string;
+}
+} // namespace hello_world
+
diff --git a/native_client_sdk/src/examples/hello_world_glibc/helper_functions.h b/native_client_sdk/src/examples/hello_world_glibc/helper_functions.h
new file mode 100644
index 0000000..5076300
--- /dev/null
+++ b/native_client_sdk/src/examples/hello_world_glibc/helper_functions.h
@@ -0,0 +1,34 @@
+// 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.
+
+#ifndef EXAMPLES_HELLO_WORLD_HELPER_FUNCTIONS_H_
+#define EXAMPLES_HELLO_WORLD_HELPER_FUNCTIONS_H_
+
+/// @file
+/// These functions are stand-ins for your complicated computations which you
+/// want to run in native code. We do two very simple things: return 42, and
+/// reverse a string. But you can imagine putting more complicated things here
+/// which might be difficult or slow to achieve in JavaScript, such as
+/// cryptography, artificial intelligence, signal processing, physics modeling,
+/// etc. See hello_world.cc for the code which is required for loading a NaCl
+/// application and exposing methods to JavaScript.
+
+#include <ppapi/c/pp_stdint.h>
+#include <string>
+
+namespace hello_world {
+
+/// This is the module's function that does the work to compute the value 42.
+int32_t FortyTwo();
+
+/// This function is passed a string and returns a copy of the string with the
+/// characters in reverse order.
+/// @param[in] text The string to reverse.
+/// @return A copy of @a text with the characters in reverse order.
+std::string ReverseText(const std::string& text);
+
+} // namespace hello_world
+
+#endif // EXAMPLES_HELLO_WORLD_HELPER_FUNCTIONS_H_
+
diff --git a/native_client_sdk/src/examples/hello_world_glibc/make.bat b/native_client_sdk/src/examples/hello_world_glibc/make.bat
new file mode 100755
index 0000000..479d648
--- /dev/null
+++ b/native_client_sdk/src/examples/hello_world_glibc/make.bat
@@ -0,0 +1 @@
+@..\..\tools\make.exe %*