Commit 68975dc2 authored by binji@chromium.org's avatar binji@chromium.org

[NaCl SDK] Add a very simple getting_started example at top-level.

* Added getting_started/ parallel to examples/
* Added getting_started/part1/ which is a quick port of hello_tutorial from the
  NaCl SDK documentation page.
* Added support for examples not using auto-generated Makefiles
* Disbled testing of getting_started/part1 (it doesn't have the test hooks)
* Moved examples/getting_started/simple_hello_world =>
        examples/tutorial/using_ppapi_simple

BUG=none
R=eliben@chromium.org

Review URL: https://codereview.chromium.org/23661005

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@222142 0039d316-1c4b-4281-b951-d872f2087c98
parent 04882168
...@@ -657,9 +657,9 @@ def BuildStepUpdateUserProjects(pepperdir, toolchains, ...@@ -657,9 +657,9 @@ def BuildStepUpdateUserProjects(pepperdir, toolchains,
# Update examples and libraries # Update examples and libraries
filters['DEST'] = [ filters['DEST'] = [
'getting_started',
'examples/api', 'examples/api',
'examples/demo', 'examples/demo',
'examples/getting_started',
'examples/tutorial', 'examples/tutorial',
'src' 'src'
] ]
......
...@@ -26,6 +26,11 @@ def IsExample(desc): ...@@ -26,6 +26,11 @@ def IsExample(desc):
def GenerateSourceCopyList(desc): def GenerateSourceCopyList(desc):
sources = [] sources = []
# Some examples use their own Makefile/sources/etc.
if 'TARGETS' not in desc:
# Only copy the DATA files.
return desc.get('DATA', [])
# Add sources for each target # Add sources for each target
for target in desc['TARGETS']: for target in desc['TARGETS']:
sources.extend(target['SOURCES']) sources.extend(target['SOURCES'])
...@@ -196,6 +201,14 @@ def ProcessProject(pepperdir, srcroot, dstroot, desc, toolchains, configs=None, ...@@ -196,6 +201,14 @@ def ProcessProject(pepperdir, srcroot, dstroot, desc, toolchains, configs=None,
make_path = os.path.join(out_dir, 'Makefile') make_path = os.path.join(out_dir, 'Makefile')
outdir = os.path.dirname(os.path.abspath(make_path))
if getos.GetPlatform() == 'win':
AddMakeBat(pepperdir, outdir)
# If this project has no TARGETS, then we don't need to generate anything.
if 'TARGETS' not in desc:
return (name, desc['DEST'])
if IsNexe(desc): if IsNexe(desc):
template = os.path.join(SDK_RESOURCE_DIR, 'Makefile.example.template') template = os.path.join(SDK_RESOURCE_DIR, 'Makefile.example.template')
else: else:
...@@ -219,10 +232,6 @@ def ProcessProject(pepperdir, srcroot, dstroot, desc, toolchains, configs=None, ...@@ -219,10 +232,6 @@ def ProcessProject(pepperdir, srcroot, dstroot, desc, toolchains, configs=None,
} }
RunTemplateFileIfChanged(template, make_path, template_dict) RunTemplateFileIfChanged(template, make_path, template_dict)
outdir = os.path.dirname(os.path.abspath(make_path))
if getos.GetPlatform() == 'win':
AddMakeBat(pepperdir, outdir)
if IsExample(desc): if IsExample(desc):
ProcessHTML(srcroot, dstroot, desc, toolchains, configs, ProcessHTML(srcroot, dstroot, desc, toolchains, configs,
first_toolchain) first_toolchain)
......
...@@ -36,7 +36,7 @@ DSC_FORMAT = { ...@@ -36,7 +36,7 @@ DSC_FORMAT = {
'INCLUDES': (list, '', False), 'INCLUDES': (list, '', False),
'LIBS' : (dict, VALID_TOOLCHAINS, False), 'LIBS' : (dict, VALID_TOOLCHAINS, False),
'DEPS' : (list, '', False) 'DEPS' : (list, '', False)
}, True), }, False),
'HEADERS': (list, { 'HEADERS': (list, {
'FILES': (list, '', True), 'FILES': (list, '', True),
'DEST': (str, '', True), 'DEST': (str, '', True),
...@@ -44,7 +44,7 @@ DSC_FORMAT = { ...@@ -44,7 +44,7 @@ DSC_FORMAT = {
'SEARCH': (list, '', False), 'SEARCH': (list, '', False),
'POST': (str, '', False), 'POST': (str, '', False),
'PRE': (str, '', False), 'PRE': (str, '', False),
'DEST': (str, ['examples/getting_started', 'examples/api', 'DEST': (str, ['getting_started', 'examples/api',
'examples/demo', 'examples/tutorial', 'examples/demo', 'examples/tutorial',
'src', 'tests'], True), 'src', 'tests'], True),
'NAME': (str, '', False), 'NAME': (str, '', False),
......
...@@ -25,10 +25,6 @@ examples/demo/nacl_io/* ...@@ -25,10 +25,6 @@ examples/demo/nacl_io/*
examples/demo/pi_generator/* examples/demo/pi_generator/*
examples/demo/voronoi/* examples/demo/voronoi/*
examples/favicon.ico examples/favicon.ico
examples/getting_started/hello_world/*
[win]examples/getting_started/make.bat
examples/getting_started/Makefile
examples/getting_started/simple_hello_world/*
examples/httpd.cmd examples/httpd.cmd
examples/index.css examples/index.css
examples/index.html examples/index.html
...@@ -41,6 +37,10 @@ examples/tutorial/load_progress/* ...@@ -41,6 +37,10 @@ examples/tutorial/load_progress/*
[win]examples/tutorial/make.bat [win]examples/tutorial/make.bat
examples/tutorial/Makefile examples/tutorial/Makefile
examples/tutorial/testing/* examples/tutorial/testing/*
examples/tutorial/using_ppapi_simple/*
[win]getting_started/make.bat
getting_started/Makefile
getting_started/part1/*
include/error_handling/* include/error_handling/*
include/GLES2/* include/GLES2/*
include/gmock/* include/gmock/*
...@@ -306,6 +306,27 @@ toolchain/${PLATFORM}_arm_newlib/arm-nacl/lib/libnosys.a ...@@ -306,6 +306,27 @@ toolchain/${PLATFORM}_arm_newlib/arm-nacl/lib/libnosys.a
toolchain/${PLATFORM}_arm_newlib/arm-nacl/lib/libppapi.a toolchain/${PLATFORM}_arm_newlib/arm-nacl/lib/libppapi.a
toolchain/${PLATFORM}_arm_newlib/arm-nacl/lib/libppapi_stub.a toolchain/${PLATFORM}_arm_newlib/arm-nacl/lib/libppapi_stub.a
toolchain/${PLATFORM}_arm_newlib/arm-nacl/lib/libpthread.a toolchain/${PLATFORM}_arm_newlib/arm-nacl/lib/libpthread.a
toolchain/${PLATFORM}_pnacl/*
toolchain/${PLATFORM}_pnacl/newlib/sdk/include/irt.h
toolchain/${PLATFORM}_pnacl/newlib/sdk/include/irt_ppapi.h
toolchain/${PLATFORM}_pnacl/newlib/sdk/include/nacl/dynamic_annotations.h
toolchain/${PLATFORM}_pnacl/newlib/sdk/include/nacl/nacl_dyncode.h
toolchain/${PLATFORM}_pnacl/newlib/sdk/include/nacl/nacl_exception.h
toolchain/${PLATFORM}_pnacl/newlib/sdk/include/nacl/nacl_minidump.h
toolchain/${PLATFORM}_pnacl/newlib/sdk/include/nacl/nacl_startup.h
toolchain/${PLATFORM}_pnacl/newlib/sdk/include/nacl/nacl_thread.h
toolchain/${PLATFORM}_pnacl/newlib/sdk/include/pnacl.h
toolchain/${PLATFORM}_pnacl/newlib/sdk/include/pthread.h
toolchain/${PLATFORM}_pnacl/newlib/sdk/include/semaphore.h
toolchain/${PLATFORM}_pnacl/newlib/sdk/lib/libminidump_generator.a
toolchain/${PLATFORM}_pnacl/newlib/sdk/lib/libnacl.a
toolchain/${PLATFORM}_pnacl/newlib/sdk/lib/libnacl_dyncode.a
toolchain/${PLATFORM}_pnacl/newlib/sdk/lib/libnacl_exception.a
toolchain/${PLATFORM}_pnacl/newlib/sdk/lib/libnacl_list_mappings.a
toolchain/${PLATFORM}_pnacl/newlib/sdk/lib/libnosys.a
toolchain/${PLATFORM}_pnacl/newlib/sdk/lib/libppapi.a
toolchain/${PLATFORM}_pnacl/newlib/sdk/lib/libppapi_stub.a
toolchain/${PLATFORM}_pnacl/newlib/sdk/lib/libpthread.a
toolchain/${PLATFORM}_x86_glibc/* toolchain/${PLATFORM}_x86_glibc/*
toolchain/${PLATFORM}_x86_glibc/x86_64-nacl/include/irt.h toolchain/${PLATFORM}_x86_glibc/x86_64-nacl/include/irt.h
toolchain/${PLATFORM}_x86_glibc/x86_64-nacl/include/irt_ppapi.h toolchain/${PLATFORM}_x86_glibc/x86_64-nacl/include/irt_ppapi.h
...@@ -374,27 +395,6 @@ toolchain/${PLATFORM}_x86_newlib/x86_64-nacl/lib32/libnosys.a ...@@ -374,27 +395,6 @@ toolchain/${PLATFORM}_x86_newlib/x86_64-nacl/lib32/libnosys.a
toolchain/${PLATFORM}_x86_newlib/x86_64-nacl/lib32/libppapi.a toolchain/${PLATFORM}_x86_newlib/x86_64-nacl/lib32/libppapi.a
toolchain/${PLATFORM}_x86_newlib/x86_64-nacl/lib32/libppapi_stub.a toolchain/${PLATFORM}_x86_newlib/x86_64-nacl/lib32/libppapi_stub.a
toolchain/${PLATFORM}_x86_newlib/x86_64-nacl/lib32/libpthread.a toolchain/${PLATFORM}_x86_newlib/x86_64-nacl/lib32/libpthread.a
toolchain/${PLATFORM}_pnacl/*
toolchain/${PLATFORM}_pnacl/newlib/sdk/include/irt.h
toolchain/${PLATFORM}_pnacl/newlib/sdk/include/irt_ppapi.h
toolchain/${PLATFORM}_pnacl/newlib/sdk/include/nacl/dynamic_annotations.h
toolchain/${PLATFORM}_pnacl/newlib/sdk/include/nacl/nacl_dyncode.h
toolchain/${PLATFORM}_pnacl/newlib/sdk/include/nacl/nacl_exception.h
toolchain/${PLATFORM}_pnacl/newlib/sdk/include/nacl/nacl_minidump.h
toolchain/${PLATFORM}_pnacl/newlib/sdk/include/nacl/nacl_startup.h
toolchain/${PLATFORM}_pnacl/newlib/sdk/include/nacl/nacl_thread.h
toolchain/${PLATFORM}_pnacl/newlib/sdk/include/pnacl.h
toolchain/${PLATFORM}_pnacl/newlib/sdk/include/pthread.h
toolchain/${PLATFORM}_pnacl/newlib/sdk/include/semaphore.h
toolchain/${PLATFORM}_pnacl/newlib/sdk/lib/libminidump_generator.a
toolchain/${PLATFORM}_pnacl/newlib/sdk/lib/libnacl.a
toolchain/${PLATFORM}_pnacl/newlib/sdk/lib/libnacl_dyncode.a
toolchain/${PLATFORM}_pnacl/newlib/sdk/lib/libnacl_exception.a
toolchain/${PLATFORM}_pnacl/newlib/sdk/lib/libnacl_list_mappings.a
toolchain/${PLATFORM}_pnacl/newlib/sdk/lib/libnosys.a
toolchain/${PLATFORM}_pnacl/newlib/sdk/lib/libppapi.a
toolchain/${PLATFORM}_pnacl/newlib/sdk/lib/libppapi_stub.a
toolchain/${PLATFORM}_pnacl/newlib/sdk/lib/libpthread.a
tools/common.mk tools/common.mk
tools/compiler-wrapper.py tools/compiler-wrapper.py
tools/create_html.py tools/create_html.py
......
...@@ -62,6 +62,11 @@ DISABLED_TESTS = [ ...@@ -62,6 +62,11 @@ DISABLED_TESTS = [
# TODO(binji): These tests timeout on the trybots because the NEXEs take # TODO(binji): These tests timeout on the trybots because the NEXEs take
# more than 40 seconds to load (!). See http://crbug.com/280753 # more than 40 seconds to load (!). See http://crbug.com/280753
{'name': 'nacl_io_test', 'platform': 'win', 'toolchain': 'glibc'}, {'name': 'nacl_io_test', 'platform': 'win', 'toolchain': 'glibc'},
# We don't test "getting_started/part1" because it would complicate the
# example.
# TODO(binji): figure out a way to inject the testing code without
# modifying the example; maybe an extension?
{'name': 'part1'},
] ]
def ValidateToolchains(toolchains): def ValidateToolchains(toolchains):
......
...@@ -30,6 +30,10 @@ sys.path.append(os.path.join(SDK_SRC_DIR, 'tools')) ...@@ -30,6 +30,10 @@ sys.path.append(os.path.join(SDK_SRC_DIR, 'tools'))
import getos import getos
def StepBuildExamples(pepperdir): def StepBuildExamples(pepperdir):
build_sdk.BuildStepMakeAll(pepperdir, 'getting_started',
'Build Getting Started',
deps=False, config='Release')
for config in ('Debug', 'Release'): for config in ('Debug', 'Release'):
build_sdk.BuildStepMakeAll(pepperdir, 'examples', build_sdk.BuildStepMakeAll(pepperdir, 'examples',
'Build Examples (%s)' % config, 'Build Examples (%s)' % config,
......
{
'TOOLS': ['newlib', 'glibc', 'pnacl', 'win', 'linux'],
'TARGETS': [
{
'NAME' : 'hello_world',
'TYPE' : 'main',
'SOURCES' : ['hello_world.c'],
'LIBS': ['ppapi', 'pthread']
}
],
'DATA': [
'example.js',
],
'DEST': 'examples/getting_started',
'NAME': 'hello_world',
'TITLE': 'Hello World',
'GROUP': 'Getting Started'
}
/* 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 hello_world.c
* This example demonstrates loading, running and scripting a very simple
* NaCl module.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/pp_module.h"
#include "ppapi/c/pp_var.h"
#include "ppapi/c/ppb.h"
#include "ppapi/c/ppb_console.h"
#include "ppapi/c/ppb_instance.h"
#include "ppapi/c/ppb_messaging.h"
#include "ppapi/c/ppb_var.h"
#include "ppapi/c/ppp.h"
#include "ppapi/c/ppp_instance.h"
#include "ppapi/c/ppp_messaging.h"
#if defined(__native_client__)
#if defined(__pnacl__)
#define TCNAME "pnacl"
#elif defined(__GLIBC__)
#define TCNAME "glibc"
#else
#define TCNAME "newlib"
#endif
#else
#define TCNAME "host"
#endif
static PPB_Console* ppb_console_interface = NULL;
static PPB_Messaging* ppb_messaging_interface = NULL;
static PPB_Var* ppb_var_interface = NULL;
/**
* Creates new string PP_Var from C string. The resulting object will be a
* refcounted string object. It will be AddRef()ed for the caller. When the
* caller is done with it, it should be Release()d.
* @param[in] str C string to be converted to PP_Var
* @return PP_Var containing string.
*/
static struct PP_Var CStrToVar(const char* str) {
if (ppb_var_interface != NULL) {
return ppb_var_interface->VarFromUtf8(str, strlen(str));
}
return PP_MakeUndefined();
}
/**
* Post a message back to our JavaScript
*/
static void SendMessage(PP_Instance instance, const char* str) {
if (ppb_messaging_interface) {
struct PP_Var var = CStrToVar(str);
ppb_messaging_interface->PostMessage(instance, var);
ppb_var_interface->Release(var);
}
}
/**
* Send a message to the JavaScript Console
*/
static void LogMessage(PP_Instance instance, const char* str) {
if (ppb_console_interface) {
struct PP_Var var = CStrToVar(str);
ppb_console_interface->Log(instance, PP_LOGLEVEL_ERROR, var);
ppb_var_interface->Release(var);
}
}
/**
* Called when the NaCl module is instantiated on the web page. The identifier
* of the new instance will be passed in as the first argument (this value is
* generated by the browser and is an opaque handle). This is called for each
* instantiation of the NaCl module, which is each time the <embed> tag for
* this module is encountered.
*
* If this function reports a failure (by returning @a PP_FALSE), the NaCl
* module will be deleted and DidDestroy will be called.
* @param[in] instance The identifier of the new instance representing this
* NaCl module.
* @param[in] argc The number of arguments contained in @a argn and @a argv.
* @param[in] argn An array of argument names. These argument names are
* supplied in the <embed> tag, for example:
* <embed id="nacl_module" dimensions="2">
* will produce two arguments, one named "id" and one named "dimensions".
* @param[in] argv An array of argument values. These are the values of the
* arguments listed in the <embed> tag. In the above example, there will
* be two elements in this array, "nacl_module" and "2". The indices of
* these values match the indices of the corresponding names in @a argn.
* @return @a PP_TRUE on success.
*/
static PP_Bool Instance_DidCreate(PP_Instance instance,
uint32_t argc,
const char* argn[],
const char* argv[]) {
const char* post_msg = "Hello World (" TCNAME ")!";
const char* console_msg = "Hello World (JavaScript Console)!";
SendMessage(instance, post_msg);
LogMessage(instance, console_msg);
return PP_TRUE;
}
/**
* Called when the NaCl module is destroyed. This will always be called,
* even if DidCreate returned failure. This routine should deallocate any data
* associated with the instance.
* @param[in] instance The identifier of the instance representing this NaCl
* module.
*/
static void Instance_DidDestroy(PP_Instance instance) {}
/**
* Called when the position, the size, or the clip rect of the element in the
* browser that corresponds to this NaCl module has changed.
* @param[in] instance The identifier of the instance representing this NaCl
* module.
* @param[in] position The location on the page of this NaCl module. This is
* relative to the top left corner of the viewport, which changes as the
* page is scrolled.
* @param[in] clip The visible region of the NaCl module. This is relative to
* the top left of the plugin's coordinate system (not the page). If the
* plugin is invisible, @a clip will be (0, 0, 0, 0).
*/
static void Instance_DidChangeView(PP_Instance instance,
PP_Resource view_resource) {}
/**
* Notification that the given NaCl module has gained or lost focus.
* Having focus means that keyboard events will be sent to the NaCl module
* represented by @a instance. A NaCl module's default condition is that it
* will not have focus.
*
* Note: clicks on NaCl modules will give focus only if you handle the
* click event. You signal if you handled it by returning @a true from
* HandleInputEvent. Otherwise the browser will bubble the event and give
* focus to the element on the page that actually did end up consuming it.
* If you're not getting focus, check to make sure you're returning true from
* the mouse click in HandleInputEvent.
* @param[in] instance The identifier of the instance representing this NaCl
* module.
* @param[in] has_focus Indicates whether this NaCl module gained or lost
* event focus.
*/
static void Instance_DidChangeFocus(PP_Instance instance, PP_Bool has_focus) {}
/**
* Handler that gets called after a full-frame module is instantiated based on
* registered MIME types. This function is not called on NaCl modules. This
* function is essentially a place-holder for the required function pointer in
* the PPP_Instance structure.
* @param[in] instance The identifier of the instance representing this NaCl
* module.
* @param[in] url_loader A PP_Resource an open PPB_URLLoader instance.
* @return PP_FALSE.
*/
static PP_Bool Instance_HandleDocumentLoad(PP_Instance instance,
PP_Resource url_loader) {
/* NaCl modules do not need to handle the document load function. */
return PP_FALSE;
}
/**
* Entry points for the module.
* Initialize needed interfaces: PPB_Console, PPB_Messaging and PPB_Var.
* @param[in] a_module_id module ID
* @param[in] get_browser pointer to PPB_GetInterface
* @return PP_OK on success, any other value on failure.
*/
PP_EXPORT int32_t PPP_InitializeModule(PP_Module a_module_id,
PPB_GetInterface get_browser) {
ppb_console_interface = (PPB_Console*)(get_browser(PPB_CONSOLE_INTERFACE));
ppb_messaging_interface =
(PPB_Messaging*)(get_browser(PPB_MESSAGING_INTERFACE));
ppb_var_interface = (PPB_Var*)(get_browser(PPB_VAR_INTERFACE));
return PP_OK;
}
/**
* Returns an interface pointer for the interface of the given name, or NULL
* if the interface is not supported.
* @param[in] interface_name name of the interface
* @return pointer to the interface
*/
PP_EXPORT const void* PPP_GetInterface(const char* interface_name) {
if (strcmp(interface_name, PPP_INSTANCE_INTERFACE) == 0) {
static PPP_Instance instance_interface = {
&Instance_DidCreate,
&Instance_DidDestroy,
&Instance_DidChangeView,
&Instance_DidChangeFocus,
&Instance_HandleDocumentLoad,
};
return &instance_interface;
}
return NULL;
}
/**
* Called before the plugin module is unloaded.
*/
PP_EXPORT void PPP_ShutdownModule() {}
<!DOCTYPE html>
<html>
<!--
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.
-->
<head>
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="-1">
<title>{{title}}</title>
<script type="text/javascript" src="common.js"></script>
<script type="text/javascript" src="example.js"></script>
</head>
<body {{attrs}}>
<h1>{{title}}</h1>
<h2>Status: <code id="statusField">NO-STATUS</code></h2>
<p>The Hello World In C example demonstrates the basic structure of all
Native Client applications. This example loads a Native Client module. The
page tracks the status of the module as it loads. On a successful load,
the module will post a message containing the string "Hello World" back to
JavaScript which will display it as an alert.</p>
<h2>Output:</h2>
<pre id="log" style="font-weight: bold"></pre>
<!-- The NaCl plugin will be embedded inside the element with id "listener".
See common.js.-->
<div id="listener"></div>
</body>
</html>
// 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.
// Once we load, hide the plugin
function moduleDidLoad() {
common.hideModule();
}
// Called by the common.js module.
function handleMessage(message) {
common.logMessage(message.data);
}
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
'SEL_LDR': True, 'SEL_LDR': True,
'TARGETS': [ 'TARGETS': [
{ {
'NAME' : 'simple_hello_world', 'NAME' : 'using_ppapi_simple',
'TYPE' : 'main', 'TYPE' : 'main',
'SOURCES' : ['hello_world.c'], 'SOURCES' : ['hello_world.c'],
'DEPS': ['ppapi_simple', 'nacl_io', 'ppapi_cpp'], 'DEPS': ['ppapi_simple', 'nacl_io', 'ppapi_cpp'],
...@@ -13,9 +13,8 @@ ...@@ -13,9 +13,8 @@
'DATA': [ 'DATA': [
'example.js', 'example.js',
], ],
'DEST': 'examples/getting_started', 'DEST': 'examples/tutorial',
'NAME': 'simple_hello_world', 'NAME': 'using_ppapi_simple',
'TITLE': 'Hello World (ppapi_simple)', 'TITLE': 'Using the ppapi_simple library',
'GROUP': 'Getting Started' 'GROUP': 'Tutorial'
} }
=============================
C++ Tutorial: Getting Started
=============================
Please see the online documentation here:
https://developers.google.com/native-client/devguide/tutorial
# Copyright (c) 2013 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
#
#
# Get pepper directory for toolchain and includes.
#
# If NACL_SDK_ROOT is not set, then assume it can be found three directories up.
#
THIS_MAKEFILE := $(abspath $(lastword $(MAKEFILE_LIST)))
NACL_SDK_ROOT ?= $(abspath $(dir $(THIS_MAKEFILE))../..)
# Project Build flags
WARNINGS := -Wno-long-long -Wall -Wswitch-enum -pedantic -Werror
CXXFLAGS := -pthread -std=gnu++98 $(WARNINGS)
#
# Compute tool paths
#
GETOS := python $(NACL_SDK_ROOT)/tools/getos.py
OSHELPERS = python $(NACL_SDK_ROOT)/tools/oshelpers.py
OSNAME := $(shell $(GETOS))
RM := $(OSHELPERS) rm
PNACL_TC_PATH := $(abspath $(NACL_SDK_ROOT)/toolchain/$(OSNAME)_pnacl)
PNACL_CXX := $(PNACL_TC_PATH)/newlib/bin/pnacl-clang++
PNACL_FINALIZE := $(PNACL_TC_PATH)/newlib/bin/pnacl-finalize
CXXFLAGS := -I$(NACL_SDK_ROOT)/include
LDFLAGS := -L$(NACL_SDK_ROOT)/lib/pnacl/Release -lppapi_cpp -lppapi
#
# Disable DOS PATH warning when using Cygwin based tools Windows
#
CYGWIN ?= nodosfilewarning
export CYGWIN
# Declare the ALL target first, to make the 'all' target the default build
all: hello_tutorial.pexe
clean:
$(RM) hello_tutorial.pexe hello_tutorial.bc
hello_tutorial.bc: hello_tutorial.cc
$(PNACL_CXX) -o $@ $< -O2 $(CXXFLAGS) $(LDFLAGS)
hello_tutorial.pexe: hello_tutorial.bc
$(PNACL_FINALIZE) -o $@ $<
#
# File to redirect to to in order to hide output.
#
ifeq ($(OSNAME),win)
DEV_NULL = nul
else
DEV_NULL = /dev/null
endif
#
# Assign a sensible default to CHROME_PATH.
#
CHROME_PATH ?= $(shell $(GETOS) --chrome 2> $(DEV_NULL))
#
# Verify we can find the Chrome executable if we need to launch it.
#
.PHONY: check_for_chrome
check_for_chrome:
ifeq (,$(wildcard $(CHROME_PATH)))
$(warning No valid Chrome found at CHROME_PATH=$(CHROME_PATH))
$(error Set CHROME_PATH via an environment variable, or command-line.)
else
$(warning Using chrome at: $(CHROME_PATH))
endif
#
# Variables for running examples with Chrome.
#
RUN_PY := python $(NACL_SDK_ROOT)/tools/run.py
# Additional arguments to pass to Chrome.
CHROME_ARGS += --enable-pnacl --no-first-run
CHROME_ARGS += --user-data-dir=$(CURDIR)/user-data-dir
# Define a phony rule so it always runs, to run the pexe.
.PHONY: run
run: check_for_chrome all
$(RUN_PY) -C $(CURDIR) -P index.html -- $(CHROME_PATH) $(CHROME_ARGS)
{
'TOOLS': ['pnacl'],
'DATA': [
'hello_tutorial.cc',
'hello_tutorial.nmf',
'index.html',
'Makefile',
],
'DEST': 'getting_started',
'NAME': 'part1',
'GROUP': 'Getting Started'
}
// 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.
/// @file hello_tutorial.cc
/// 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. After the code is loaded,
/// CreateModule() is not called again.
///
/// Once the code is loaded, the browser than calls the CreateInstance()
/// method on the object returned by CreateModule(). It calls CreateInstance()
/// each time it encounters an <embed> tag that references your NaCl module.
///
/// The browser can talk to your NaCl module via the postMessage() Javascript
/// function. When you call postMessage() on your NaCl module from the browser,
/// this becomes a call to the HandleMessage() method of your pp::Instance
/// subclass. You can send messages back to the browser by calling the
/// PostMessage() method on your pp::Instance. Note that these two methods
/// (postMessage() in Javascript and PostMessage() in C++) are asynchronous.
/// This means they return immediately - there is no waiting for the message
/// to be handled. This has implications in your program design, particularly
/// when mutating property values that are exposed to both the browser and the
/// NaCl module.
#include "ppapi/cpp/instance.h"
#include "ppapi/cpp/module.h"
#include "ppapi/cpp/var.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:
/// type="application/x-pnacl"
/// src="hello_tutorial.nmf"
/// To communicate with the browser, you must override HandleMessage() to
/// receive messages from the browser, and use PostMessage() to send messages
/// back to the browser. Note that this interface is asynchronous.
class HelloTutorialInstance : public pp::Instance {
public:
/// The constructor creates the plugin-side instance.
/// @param[in] instance the handle to the browser-side plugin instance.
explicit HelloTutorialInstance(PP_Instance instance) : pp::Instance(instance)
{}
virtual ~HelloTutorialInstance() {}
/// Handler for messages coming in from the browser via postMessage(). The
/// @a var_message can contain anything: a JSON string; a string that encodes
/// method names and arguments; etc. For example, you could use
/// JSON.stringify in the browser to create a message that contains a method
/// name and some parameters, something like this:
/// var json_message = JSON.stringify({ "myMethod" : "3.14159" });
/// nacl_module.postMessage(json_message);
/// On receipt of this message in @a var_message, you could parse the JSON to
/// retrieve the method name, match it to a function call, and then call it
/// with the parameter.
/// @param[in] var_message The message posted by the browser.
virtual void HandleMessage(const pp::Var& var_message) {
// TODO(sdk_user): 1. Make this function handle the incoming message.
}
};
/// 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 HelloTutorialModule : public pp::Module {
public:
HelloTutorialModule() : pp::Module() {}
virtual ~HelloTutorialModule() {}
/// Create and return a HelloTutorialInstance object.
/// @param[in] instance The browser-side instance.
/// @return the plugin-side instance.
virtual pp::Instance* CreateInstance(PP_Instance instance) {
return new HelloTutorialInstance(instance);
}
};
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.
Module* CreateModule() {
return new HelloTutorialModule();
}
} // namespace pp
{
"program": {
"portable": {
"pnacl-translate": {
"url": "hello_tutorial.pexe"
}
}
}
}
<!DOCTYPE html>
<html>
<!--
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.
-->
<head>
<title>hello_tutorial</title>
<script type="text/javascript">
HelloTutorialModule = null; // Global application object.
statusText = 'NO-STATUS';
// Indicate load success.
function moduleDidLoad() {
HelloTutorialModule = document.getElementById('hello_tutorial');
updateStatus('SUCCESS');
}
// The 'message' event handler. This handler is fired when the NaCl module
// posts a message to the browser by calling PPB_Messaging.PostMessage()
// (in C) or pp::Instance.PostMessage() (in C++). This implementation
// simply displays the content of the message in an alert panel.
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() {
if (HelloTutorialModule == 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();
}
}
// 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('status_field');
if (statusField) {
statusField.innerHTML = statusText;
}
}
</script>
</head>
<body onload="pageDidLoad()">
<h1>Native Client Module HelloTutorial</h1>
<p>
<!-- TODO(eliben): PNaCl-ize:
Load the published .nexe. This includes the 'nacl' 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
instruction set architecture ('x86-32', 'x86-64', etc.); the value is a URL
for the desired NaCl module.
Note: Since this NaCl module does not use any real-estate in the browser,
it's width and height are set to 0.
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
id="hello_tutorial"
width=0 height=0
src="hello_tutorial.nmf"
type="application/x-pnacl" />
</div>
</p>
<h2>Status</h2>
<div id="status_field">NO-STATUS</div>
</body>
</html>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment