| {{+bindTo:partials.standard_nacl_article}} |
| |
| <section id="c-tutorial-getting-started-part-2"> |
| <span id="tutorial2"></span><h1 id="c-tutorial-getting-started-part-2"><span id="tutorial2"></span>C++ Tutorial: Getting Started (Part 2)</h1> |
| <div class="contents local" id="contents" style="display: none"> |
| <ul class="small-gap"> |
| <li><a class="reference internal" href="#overview" id="id1">Overview</a></li> |
| <li><p class="first"><a class="reference internal" href="#using-the-native-client-sdk-build-system" id="id2">Using the Native Client SDK build system</a></p> |
| <ul class="small-gap"> |
| <li><a class="reference internal" href="#simplifying-the-makefile" id="id3">Simplifying the Makefile</a></li> |
| <li><a class="reference internal" href="#choosing-valid-toolchains-and-including-common-mk" id="id4">Choosing valid toolchains, and including common.mk</a></li> |
| <li><a class="reference internal" href="#configuring-your-project" id="id5">Configuring your project</a></li> |
| <li><a class="reference internal" href="#build-macros" id="id6">Build macros</a></li> |
| </ul> |
| </li> |
| <li><p class="first"><a class="reference internal" href="#making-index-html-work-for-chrome-apps" id="id7">Making index.html work for Chrome Apps</a></p> |
| <ul class="small-gap"> |
| <li><a class="reference internal" href="#csp-rules" id="id8">CSP rules</a></li> |
| <li><a class="reference internal" href="#making-index-html-csp-compliant" id="id9">Making index.html CSP-compliant</a></li> |
| <li><a class="reference internal" href="#making-index-html-support-different-toolchains-and-configurations" id="id10">Making index.html support different toolchains and configurations</a></li> |
| </ul> |
| </li> |
| <li><p class="first"><a class="reference internal" href="#sharing-common-code-with-common-js" id="id11">Sharing common code with common.js</a></p> |
| <ul class="small-gap"> |
| <li><a class="reference internal" href="#loading-the-page-and-creating-the-module" id="id12">Loading the page and creating the module</a></li> |
| </ul> |
| </li> |
| <li><a class="reference internal" href="#example-specific-behavior-with-example-js" id="id13">Example-specific behavior with example.js</a></li> |
| <li><a class="reference internal" href="#compile-the-native-client-module-and-run-the-application-again" id="id14">Compile the Native Client module and run the application again</a></li> |
| </ul> |
| |
| </div><h2 id="overview">Overview</h2> |
| <p>This tutorial shows how to convert the finished PNaCl web application from |
| <a class="reference internal" href="/native-client/devguide/tutorial/tutorial-part1.html"><em>Part 1</em></a> to use the Native Client SDK build system and |
| common JavaScript files. It also demonstrates some techniques to make your web |
| application <a class="reference external" href="/apps/contentSecurityPolicy">Content Security Policy (CSP)-compliant</a>, which is necessary for <a class="reference external" href="/apps">Chrome Apps</a>.</p> |
| <p>Using the Native Client SDK build system makes it easy to build with all of the |
| SDK toolchains, and switch between the Debug and Release configurations. It |
| also simplifies the makefiles for your project, as we’ll see in the next |
| section. Finally, it adds some useful commands for <a class="reference internal" href="/native-client/sdk/examples.html#running-the-sdk-examples"><em>running</em></a> and <a class="reference internal" href="/native-client/sdk/examples.html#debugging-the-sdk-examples"><em>debugging</em></a> |
| your application.</p> |
| <p>The finished code for this example can be found in the |
| <code>pepper_$(VERSION)/getting_started/part2</code> directory in the Native Client SDK |
| download.</p> |
| <h2 id="using-the-native-client-sdk-build-system">Using the Native Client SDK build system</h2> |
| <p>This section describes how to use the SDK build system. To do so, we’ll make |
| changes in the makefile. Because the makefile in part1 and part2 are so |
| different, it is easier to start from scratch. Here is the contents of the new |
| makefile. The following sections will describe it in more detail.</p> |
| <h3 id="simplifying-the-makefile">Simplifying the Makefile</h3> |
| <p>The makefile from part1 only supports one toolchain (PNaCl) and one |
| configuration (Release). It also only supports one source file. It’s relatively |
| simple, but if we want to add support for multiple toolchains, configurations, |
| source files, or build steps, it would grow increasingly complex. The SDK build |
| system uses a set of variables and macros to make this possible, without |
| significantly increasing the complexity of the makefile.</p> |
| <p>Here is the new makefile, supporting three toolchains (PNaCl, Newlib NaCl, |
| Glibc NaCl) and two configurations (Debug, Release).</p> |
| <pre class="prettyprint"> |
| VALID_TOOLCHAINS := pnacl clang-newlib glibc |
| |
| NACL_SDK_ROOT ?= $(abspath $(CURDIR)/../..) |
| include $(NACL_SDK_ROOT)/tools/common.mk |
| |
| TARGET = part2 |
| LIBS = ppapi_cpp ppapi |
| |
| CFLAGS = -Wall |
| SOURCES = hello_tutorial.cc |
| |
| # Build rules generated by macros from common.mk: |
| |
| $(foreach src,$(SOURCES),$(eval $(call COMPILE_RULE,$(src),$(CFLAGS)))) |
| |
| # The PNaCl workflow uses both an unstripped and finalized/stripped binary. |
| # On NaCl, only produce a stripped binary for Release configs (not Debug). |
| ifneq (,$(or $(findstring pnacl,$(TOOLCHAIN)),$(findstring Release,$(CONFIG)))) |
| $(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),)) |
| </pre> |
| <h3 id="choosing-valid-toolchains-and-including-common-mk">Choosing valid toolchains, and including common.mk</h3> |
| <p>The makefile begins by specifying the toolchains that are valid for this |
| project. The Native Client SDK build system supports multi-toolchain projects |
| for its examples and libraries, but generally you will choose one toolchain |
| when you begin your project and never change it. Please see the |
| <a class="reference internal" href="/native-client/overview.html#toolchains"><em>Toolchains section of the Native Client overview</em></a> for more |
| information.</p> |
| <p>For this example, we support the <code>pnacl</code>, <code>clang-newlib</code> and <code>glibc</code> |
| toolchains.</p> |
| <pre class="prettyprint"> |
| VALID_TOOLCHAINS := pnacl clang-newlib glibc |
| </pre> |
| <p>Next, as a convenience, we specify where to find <code>NACL_SDK_ROOT</code>. Because |
| this example is located in <code>pepper_$(VERSION)/getting_started/part2</code>, the |
| root of the SDK is two directories up.</p> |
| <pre class="prettyprint"> |
| NACL_SDK_ROOT ?= $(abspath $(CURDIR)/../..) |
| </pre> |
| <aside class="note"> |
| <blockquote> |
| <div>In your own projects, you can use the absolute path to your installed SDK |
| here. You can also override this default by setting the <code>NACL_SDK_ROOT</code> |
| environment variable. See <a class="reference internal" href="/native-client/devguide/tutorial/tutorial-part1.html#tutorial-step-5"><em>Step 5 of Part 1 of this tutorial</em></a> for more details.</div></blockquote> |
| |
| </aside> |
| <p>Next, we include the file <code>tools/common.mk</code>. This file provides the |
| functionality for the Native Client SDK build system, including new build rules |
| to compile and link a project, which we’ll use below.</p> |
| <pre class="prettyprint"> |
| include $(NACL_SDK_ROOT)/tools/common.mk |
| </pre> |
| <h3 id="configuring-your-project">Configuring your project</h3> |
| <p>After including <code>tools/common.mk</code>, we configure the project by specifying its |
| name, the sources and libraries it uses:</p> |
| <pre class="prettyprint"> |
| TARGET = part2 |
| LIBS = ppapi_cpp ppapi |
| |
| CFLAGS = -Wall |
| SOURCES = hello_tutorial.cc |
| </pre> |
| <p>These variable names are not required and not used by the SDK build system; |
| they are only used in the rules described below. By convention, all SDK |
| makefiles use the following variables:</p> |
| <dl class="docutils"> |
| <dt>TARGET</dt> |
| <dd>The name of the project to build. This variable determines the name of the |
| library or executable that will be generated. In the above example, we call |
| the target <code>part2</code>, which will generate an executable called |
| <code>part2.pexe</code> for PNaCl. For NaCl toolchains, the executable’s file name |
| will be given a suffix for its architecture. For example, the ARM executable |
| is called <code>part2_arm.nexe</code>.</dd> |
| <dt>LIBS</dt> |
| <dd>A list of libraries that this executable needs to link against. The library |
| search path is already set up to only look in the directory for the current |
| toolchain and architecture. In this example, we link against <code>ppapi_cpp</code> |
| and <code>ppapi</code>. <code>ppapi_cpp</code> is needed to use the <a class="reference external" href="/native-client/pepper_stable/cpp/">Pepper C++ interface</a>. <code>ppapi</code> is needed for communicating |
| with the browser.</dd> |
| <dt>CFLAGS</dt> |
| <dd>A list of extra flags to pass to the compiler. In this example, we pass |
| <code>-Wall</code>, which turns on all warnings.</dd> |
| <dt>LDFLAGS</dt> |
| <dd>A list of additional flags to pass to the linker. This example does not need |
| any special linker flags, so this variable is omitted.</dd> |
| <dt>SOURCES</dt> |
| <dd>A list of C or C++ sources to compile, separated by spaces. If you have a |
| long list of sources, it may be easier to read if you put each file on its |
| own line, and use <code>\</code> as a line-continuation character. Here’s an example:</dd> |
| </dl> |
| <pre class="prettyprint"> |
| SOURCES = foo.cc \ |
| bar.cc \ |
| baz.cc \ |
| quux.cc |
| </pre> |
| <h3 id="build-macros">Build macros</h3> |
| <p>For many projects, the following build macros do not need to be changed; they |
| will use the variables we’ve defined above.</p> |
| <pre class="prettyprint"> |
| $(foreach src,$(SOURCES),$(eval $(call COMPILE_RULE,$(src),$(CFLAGS)))) |
| |
| ifneq (,$(or $(findstring pnacl,$(TOOLCHAIN)),$(findstring Release,$(CONFIG)))) |
| $(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),)) |
| </pre> |
| <p>The first line defines rules to compile each source in <code>SOURCES</code>, using the |
| flags in <code>CFLAGS</code>:</p> |
| <pre class="prettyprint"> |
| $(foreach src,$(SOURCES),$(eval $(call COMPILE_RULE,$(src),$(CFLAGS)))) |
| </pre> |
| <p>The next six lines define rules to link the object files into one or more |
| executables. When <code>TOOLCHAIN</code> is <code>pnacl</code>, there is only one executable |
| generated: in the example above, <code>part2.pexe</code>. When using a NaCl toolchain, |
| there will be three executables generated, one for each architecture: in the |
| example above, <code>part2_arm.nexe</code>, <code>part2_x86_32.nexe</code> and |
| <code>part2_x86_64.nexe</code>.</p> |
| <p>When <code>CONFIG</code> is <code>Release</code>, each executable is also stripped to remove |
| debug information and reduce the file size. Otherwise, when the <code>TOOLCHAIN</code> |
| is <code>pnacl</code>, the workflow involves creating an unstripped binary for debugging |
| and then finalizing it and stripping it for publishing.</p> |
| <pre class="prettyprint"> |
| ifneq (,$(or $(findstring pnacl,$(TOOLCHAIN)),$(findstring Release,$(CONFIG)))) |
| $(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 |
| </pre> |
| <p>Finally, the NMF rule generates a NaCl manifest file (<code>.nmf</code>) that references |
| each executable generated in the previous step:</p> |
| <pre class="prettyprint"> |
| $(eval $(call NMF_RULE,$(TARGET),)) |
| </pre> |
| <h2 id="making-index-html-work-for-chrome-apps">Making index.html work for Chrome Apps</h2> |
| <p>This section describes the changes necessary to make the HTML and JavaScript in |
| part1 CSP-compliant. This is required if you want to build a <a class="reference external" href="/apps">Chrome App</a>, but is not necessary if you want to use PNaCl on the open web.</p> |
| <h3 id="csp-rules">CSP rules</h3> |
| <p><a class="reference external" href="/apps/contentSecurityPolicy#what">Chrome Apps CSP</a> restricts you from doing |
| the following:</p> |
| <ul class="small-gap"> |
| <li>You can’t use inline scripting in your Chrome App pages. The restriction |
| bans both <code><script></code> blocks and event handlers (<code><button onclick="..."></code>).</li> |
| <li>You can’t reference any external resources in any of your app files (except |
| for video and audio resources). You can’t embed external resources in an |
| iframe.</li> |
| <li>You can’t use string-to-JavaScript methods like <code>eval()</code> and <code>new |
| Function()</code>.</li> |
| </ul> |
| <h3 id="making-index-html-csp-compliant">Making index.html CSP-compliant</h3> |
| <p>To make our application CSP-compliant, we have to remove inline scripting. As |
| described above, we can’t use inline <code><script></code> blocks or event handlers. This |
| is easy to do—we’ll just reference some new files from our script tag, and |
| remove all of our inlined scripts:</p> |
| <pre class="prettyprint"> |
| <head> |
| ... |
| <script type="text/javascript" src="common.js"></script> |
| <script type="text/javascript" src="example.js"></script> |
| </head> |
| </pre> |
| <p><code>common.js</code> has shared code used by all SDK examples, and is described |
| later in this document. <code>example.js</code> is a script that has code specific to |
| this example.</p> |
| <p>We also need to remove the inline event handler on the body tag:</p> |
| <pre class="prettyprint"> |
| <body onload="pageDidLoad()"> |
| ... |
| </pre> |
| <p>This logic is now handled by <code>common.js</code>.</p> |
| <h3 id="making-index-html-support-different-toolchains-and-configurations">Making index.html support different toolchains and configurations</h3> |
| <p>Finally, there are a few changes to <code>index.html</code> that are not necessary for |
| CSP-compliance, but help make the SDK examples more generic.</p> |
| <p>First, we add some <a class="reference external" href="https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Using_data_attributes">data attributes</a> |
| to the body element to specify the name, supported toolchains, supported |
| configurations, and path to the <code>.nmf</code> file:</p> |
| <pre class="prettyprint"> |
| <body data-name="part2" |
| data-tools="clang-newlib glibc pnacl" |
| data-configs="Debug Release" |
| data-path="{tc}/{config}"> |
| ... |
| </pre> |
| <p><code>common.js</code> will read these data attributes to allow you to load the same |
| example with different toolchains by changing the URL’s <a class="reference external" href="http://en.wikipedia.org/wiki/Query_string">query string</a>. For example, you can load the |
| glibc Debug version of this example by navigating to |
| <code>index.html?tc=glibc&config=Debug</code>. Path URI’s such as <code>../</code>, for example |
| do not work for either the data-path parameter or its corresponding query |
| string.</p> |
| <p>Next, we remove the <code>embed</code> element that is described in HTML. This will be |
| automatically added for us by <code>common.js</code>, based on the current |
| toolchain/configuration combination:</p> |
| <pre class="prettyprint"> |
| <!-- |
| Just as in part1, the <embed> element will be wrapped inside the <div> |
| element with the id "listener". In part1, the embed was specified in HTML, |
| here the common.js module creates a new <embed> element and adds it to the |
| <div> for us. |
| --> |
| <div id="listener"></div> |
| </pre> |
| <h2 id="sharing-common-code-with-common-js">Sharing common code with common.js</h2> |
| <p><code>common.js</code> contains JavaScript code that each example uses to create a |
| NaCl module, handle messages from that module and other common tasks like |
| displaying the module load status and logging messages. Explaining all of |
| <code>common.js</code> is outside the scope of this document, but please look at the |
| documentation in that file for more information.</p> |
| <h3 id="loading-the-page-and-creating-the-module">Loading the page and creating the module</h3> |
| <p>Since we’ve added <code><script></code> tags for <code>common.js</code> and <code>example.js</code> to the |
| <code>head</code> element, they will be loaded and executed before the rest of the |
| document has been parsed. As a result, we have to wait for the page to finish |
| loading before we try to create the embed element and add it to the page.</p> |
| <p>We can do that by calling <code>addEventListener</code> and listening for the |
| <code>DOMContentLoaded</code> event:</p> |
| <pre class="prettyprint"> |
| // 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() { |
| ... |
| }); |
| </pre> |
| <p>Inside this function, we parse the URL query string, and compare that to the |
| data attributes:</p> |
| <pre class="prettyprint"> |
| // From https://developer.mozilla.org/en-US/docs/DOM/window.location |
| var searchVars = {}; |
| if (window.location.search.length > 1) { |
| var pairs = window.location.search.substr(1).split('&'); |
| for (var key_ix = 0; key_ix < pairs.length; key_ix++) { |
| var keyValue = pairs[key_ix].split('='); |
| searchVars[unescape(keyValue[0])] = |
| keyValue.length > 1 ? unescape(keyValue[1]) : ''; |
| } |
| } |
| |
| ... |
| |
| var toolchains = body.dataset.tools.split(' '); |
| var configs = body.dataset.configs.split(' '); |
| |
| ... |
| |
| var tc = toolchains.indexOf(searchVars.tc) !== -1 ? |
| searchVars.tc : toolchains[0]; |
| |
| // If the config value is included in the search vars, use that. |
| // Otherwise default to Release if it is valid, or the first value if |
| // Release is not valid. |
| if (configs.indexOf(searchVars.config) !== -1) |
| var config = searchVars.config; |
| else if (configs.indexOf('Release') !== -1) |
| var config = 'Release'; |
| else |
| var config = configs[0]; |
| </pre> |
| <p>Then <code>domContentLoaded</code> is called, which performs some checks to see if the |
| browser supports Native Client, then creates the NaCl module.</p> |
| <pre class="prettyprint"> |
| function domContentLoaded(name, tool, path, width, height, attrs) { |
| updateStatus('Page loaded.'); |
| if (!browserSupportsNaCl(tool)) { |
| updateStatus( |
| 'Browser does not support NaCl (' + tool + '), or NaCl is disabled'); |
| } else if (common.naclModule == null) { |
| updateStatus('Creating embed: ' + tool); |
| |
| // We use a non-zero sized embed to give Chrome space to place the bad |
| // plug-in graphic, if there is a problem. |
| width = typeof width !== 'undefined' ? width : 200; |
| height = typeof height !== 'undefined' ? height : 200; |
| attachDefaultListeners(); |
| createNaClModule(name, tool, path, width, height, attrs); |
| } 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.'); |
| } |
| } |
| </pre> |
| <p><code>attachDefaultListeners</code> is added before the creation of the module, to make |
| sure that no messages are lost. Note that <code>window.attachListeners</code> is also |
| called; this is the way that <code>common.js</code> allows each example to configure |
| itself differently. If an example defines the <code>attachListeners</code> function, it |
| will be called by <code>common.js</code>.</p> |
| <pre class="prettyprint"> |
| function attachDefaultListeners() { |
| var listenerDiv = document.getElementById('listener'); |
| listenerDiv.addEventListener('load', moduleDidLoad, true); |
| listenerDiv.addEventListener('message', handleMessage, true); |
| listenerDiv.addEventListener('crash', handleCrash, true); |
| if (typeof window.attachListeners !== 'undefined') { |
| window.attachListeners(); |
| } |
| } |
| </pre> |
| <p>Finally, <code>createNaClModule</code> actually creates the <code>embed</code>, and appends it as |
| a child of the element with id <code>listener</code>:</p> |
| <pre class="prettyprint"> |
| function createNaClModule(name, tool, path, 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', path); |
| moduleEl.setAttribute('src', path + '/' + name + '.nmf'); |
| |
| ... |
| |
| var mimetype = mimeTypeForTool(tool); |
| moduleEl.setAttribute('type', mimetype); |
| |
| var listenerDiv = document.getElementById('listener'); |
| listenerDiv.appendChild(moduleEl); |
| ... |
| } |
| </pre> |
| <p>When the module finishes loading, it will dispatch a <code>load</code> event, and the |
| event listener function that was registered above (<code>moduleDidLoad</code>) will be |
| called. Note that <code>common.js</code> allows each example to define a |
| <code>window.moduleDidLoad</code> function, that will be called here as well.</p> |
| <pre class="prettyprint"> |
| function moduleDidLoad() { |
| common.naclModule = document.getElementById('nacl_module'); |
| updateStatus('RUNNING'); |
| |
| if (typeof window.moduleDidLoad !== 'undefined') { |
| window.moduleDidLoad(); |
| } |
| } |
| </pre> |
| <h2 id="example-specific-behavior-with-example-js">Example-specific behavior with example.js</h2> |
| <p>As described in the previous section, <code>common.js</code> will call certain functions |
| during the module loading process. This example only needs to respond to two: |
| <code>moduleDidLoad</code> and <code>handleMessage</code>.</p> |
| <pre class="prettyprint"> |
| // This function is called by common.js when the NaCl module is |
| // loaded. |
| function moduleDidLoad() { |
| // Once we load, hide the plugin. In this example, we don't display anything |
| // in the plugin, so it is fine to hide it. |
| common.hideModule(); |
| |
| // After the NaCl module has loaded, common.naclModule is a reference to the |
| // NaCl module's <embed> element. |
| // |
| // postMessage sends a message to it. |
| common.naclModule.postMessage('hello'); |
| } |
| |
| // This function is called by common.js when a message is received from the |
| // NaCl module. |
| function handleMessage(message) { |
| var logEl = document.getElementById('log'); |
| logEl.textContent += message.data; |
| } |
| </pre> |
| <h2 id="compile-the-native-client-module-and-run-the-application-again">Compile the Native Client module and run the application again</h2> |
| <ol class="arabic"> |
| <li><p class="first">Compile the Native Client module by running the <code>make</code> command again.</p> |
| </li> |
| <li><p class="first">Start the SDK web server by running <code>make server</code>.</p> |
| </li> |
| <li><p class="first">Re-run the application by reloading <code>http://localhost:5103/part2</code> in |
| Chrome.</p> |
| <p>After Chrome loads the Native Client module, you should see the message sent |
| from the module.</p> |
| </li> |
| </ol> |
| </section> |
| |
| {{/partials.standard_nacl_article}} |