tutorial-part2.html revision 0529e5d033099cbfc42635f6f6183833b09dff6e
1{{+bindTo:partials.standard_nacl_article}} 2 3<section id="c-tutorial-getting-started-part-2"> 4<span id="tutorial2"></span><h1 id="c-tutorial-getting-started-part-2"><span id="tutorial2"></span>C++ Tutorial: Getting Started (Part 2)</h1> 5<div class="contents local" id="contents" style="display: none"> 6<ul class="small-gap"> 7<li><a class="reference internal" href="#overview" id="id1">Overview</a></li> 8<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> 9<ul class="small-gap"> 10<li><a class="reference internal" href="#simplifying-the-makefile" id="id3">Simplifying the Makefile</a></li> 11<li><a class="reference internal" href="#choosing-valid-toolchains-and-including-common-mk" id="id4">Choosing valid toolchains, and including common.mk</a></li> 12<li><a class="reference internal" href="#configuring-your-project" id="id5">Configuring your project</a></li> 13<li><a class="reference internal" href="#build-macros" id="id6">Build macros</a></li> 14</ul> 15</li> 16<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> 17<ul class="small-gap"> 18<li><a class="reference internal" href="#csp-rules" id="id8">CSP rules</a></li> 19<li><a class="reference internal" href="#making-index-html-csp-compliant" id="id9">Making index.html CSP-compliant</a></li> 20<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> 21</ul> 22</li> 23<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> 24<ul class="small-gap"> 25<li><a class="reference internal" href="#loading-the-page-and-creating-the-module" id="id12">Loading the page and creating the module</a></li> 26</ul> 27</li> 28<li><a class="reference internal" href="#example-specific-behavior-with-example-js" id="id13">Example-specific behavior with example.js</a></li> 29</ul> 30 31</div><section id="overview"> 32<h2 id="overview">Overview</h2> 33<p>This tutorial shows how to convert the finished PNaCl web application from 34<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 35common JavaScript files. It also demonstrates some techniques to make your 36web application <cite>Content Security Policy (CSP)-compliant 37<http://developer.chrome.com/apps/contentSecurityPolicy.html></cite>, which is 38necessary for <a class="reference external" href="https://developer.chrome.com/apps/about_apps.html">Chrome Apps</a>.</p> 39<p>Using the Native Client SDK build system makes it easy to build with all of the 40SDK toolchains, and switch between the Debug and Release configurations. It 41also simplifies the makefiles for your project, as we’ll see in the next 42section. Finally, it adds some useful commands for <a class="reference internal" href="/native-client/sdk/examples.html#id1"><em>running</em></a> and <a class="reference internal" href="/native-client/sdk/examples.html#debugging-the-sdk-examples"><em>debugging</em></a> 43your application.</p> 44<p>The finished code for this example can be found in the 45<code>pepper_$(VERSION)/getting_started/part2</code> directory in the Native Client SDK 46download.</p> 47</section><section id="using-the-native-client-sdk-build-system"> 48<h2 id="using-the-native-client-sdk-build-system">Using the Native Client SDK build system</h2> 49<p>This section describes how to use the SDK build system. To do so, we’ll make 50changes in the makefile. Because the makefile in part1 and part2 are so 51different, it is easier to start from scratch. Here is the contents of the new 52makefile. The following sections will describe it in more detail.</p> 53<section id="simplifying-the-makefile"> 54<h3 id="simplifying-the-makefile">Simplifying the Makefile</h3> 55<p>The makefile from part1 only supports one toolchain (PNaCl) and one 56configuration (Release). It also only supports one source file. It’s relatively 57simple, but if we want to add support for multiple toolchains, configurations, 58source files, or build steps, it would grow increasingly complex. The SDK build 59system uses a set of variables and macros to make this possible, without 60significantly increasing the complexity of the makefile.</p> 61<p>Here is the new makefile, supporting three toolchains (PNaCl, Newlib NaCl, 62Glibc NaCl) and two configurations (Debug, Release).</p> 63<pre class="prettyprint"> 64VALID_TOOLCHAINS := pnacl newlib glibc 65 66NACL_SDK_ROOT ?= $(abspath $(CURDIR)/../..) 67include $(NACL_SDK_ROOT)/tools/common.mk 68 69TARGET = part2 70LIBS = ppapi_cpp ppapi 71 72CFLAGS = -Wall 73SOURCES = hello_tutorial.cc 74 75# Build rules generated by macros from common.mk: 76 77$(foreach src,$(SOURCES),$(eval $(call COMPILE_RULE,$(src),$(CFLAGS)))) 78 79# The PNaCl workflow uses both an unstripped and finalized/stripped binary. 80# On NaCl, only produce a stripped binary for Release configs (not Debug). 81ifneq (,$(or $(findstring pnacl,$(TOOLCHAIN)),$(findstring Release,$(CONFIG)))) 82$(eval $(call LINK_RULE,$(TARGET)_unstripped,$(SOURCES),$(LIBS),$(DEPS))) 83$(eval $(call STRIP_RULE,$(TARGET),$(TARGET)_unstripped)) 84else 85$(eval $(call LINK_RULE,$(TARGET),$(SOURCES),$(LIBS),$(DEPS))) 86endif 87 88$(eval $(call NMF_RULE,$(TARGET),)) 89</pre> 90</section><section id="choosing-valid-toolchains-and-including-common-mk"> 91<h3 id="choosing-valid-toolchains-and-including-common-mk">Choosing valid toolchains, and including common.mk</h3> 92<p>The makefile begins by specifying the toolchains that are valid for this 93project. The Native Client SDK build system supports multi-toolchain projects 94for its examples and libraries, but generally you will choose one toolchain 95when you begin your project and never change it. Please see the 96<a class="reference internal" href="/native-client/overview.html#toolchains"><em>Toolchains section of the Native Client overview</em></a> for more 97information.</p> 98<p>For this example, we support the <code>pnacl</code>, <code>newlib</code> and <code>glibc</code> toolchains.</p> 99<pre class="prettyprint"> 100VALID_TOOLCHAINS := pnacl newlib glibc 101</pre> 102<p>Next, as a convenience, we specify where to find <code>NACL_SDK_ROOT</code>. Because 103this example is located in <code>pepper_$(VERSION)/getting_started/part2</code>, the 104root of the SDK is two directories up.</p> 105<pre class="prettyprint"> 106NACL_SDK_ROOT ?= $(abspath $(CURDIR)/../..) 107</pre> 108<aside class="note"> 109<blockquote> 110<div>In your own projects, you can use the absolute path to your installed SDK 111here. You can also override this default by setting the <code>NACL_SDK_ROOT</code> 112environment 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> 113 114</aside> 115<p>Next, we include the file <code>tools/common.mk</code>. This file provides the 116functionality for the Native Client SDK build system, including new build rules 117to compile and link a project, which we’ll use below.</p> 118<pre class="prettyprint"> 119include $(NACL_SDK_ROOT)/tools/common.mk 120</pre> 121</section><section id="configuring-your-project"> 122<h3 id="configuring-your-project">Configuring your project</h3> 123<p>After including <code>tools/common.mk</code>, we configure the project by specifying its 124name, the sources and libraries it uses:</p> 125<pre class="prettyprint"> 126TARGET = part2 127LIBS = ppapi_cpp ppapi 128 129CFLAGS = -Wall 130SOURCES = hello_tutorial.cc 131</pre> 132<p>These variable names are not required and not used by the SDK build system; 133they are only used in the rules described below. By convention, all SDK 134makefiles use the following variables:</p> 135<dl class="docutils"> 136<dt>TARGET</dt> 137<dd>The name of the project to build. This variable determines the name of the 138library or executable that will be generated. In the above example, we call 139the target <code>part2</code>, which will generate an executable called 140<code>part2.pexe</code> for PNaCl. For NaCl toolchains, the executable’s file name 141will be given a suffix for its architecture. For example, the ARM executable 142is called <code>part2_arm.nexe</code>.</dd> 143<dt>LIBS</dt> 144<dd>A list of libraries that this executable needs to link against. The library 145search path is already set up to only look in the directory for the current 146toolchain and architecture. In this example, we link against <code>ppapi_cpp</code> 147and <code>ppapi</code>. <code>ppapi_cpp</code> is needed to use the <a class="reference external" href="https://developers.google.com/native-client/peppercpp/">Pepper C++ interface</a>. <code>ppapi</code> is 148needed for communicating with the browser.</dd> 149<dt>CFLAGS</dt> 150<dd>A list of extra flags to pass to the compiler. In this example, we pass 151<code>-Wall</code>, which turns on all warnings.</dd> 152<dt>LDFLAGS</dt> 153<dd>A list of additional flags to pass to the linker. This example does not need 154any special linker flags, so this variable is omitted.</dd> 155<dt>SOURCES</dt> 156<dd>A list of C or C++ sources to compile, separated by spaces. If you have a 157long list of sources, it may be easier to read if you put each file on its 158own line, and use <code>\</code> as a line-continuation character. Here’s an example:</dd> 159</dl> 160<pre class="prettyprint"> 161SOURCES = foo.cc \ 162 bar.cc \ 163 baz.cc \ 164 quux.cc 165</pre> 166</section><section id="build-macros"> 167<h3 id="build-macros">Build macros</h3> 168<p>For many projects, the following build macros do not need to be changed; they 169will use the variables we’ve defined above.</p> 170<pre class="prettyprint"> 171$(foreach src,$(SOURCES),$(eval $(call COMPILE_RULE,$(src),$(CFLAGS)))) 172 173ifneq (,$(or $(findstring pnacl,$(TOOLCHAIN)),$(findstring Release,$(CONFIG)))) 174$(eval $(call LINK_RULE,$(TARGET)_unstripped,$(SOURCES),$(LIBS),$(DEPS))) 175$(eval $(call STRIP_RULE,$(TARGET),$(TARGET)_unstripped)) 176else 177$(eval $(call LINK_RULE,$(TARGET),$(SOURCES),$(LIBS),$(DEPS))) 178endif 179 180$(eval $(call NMF_RULE,$(TARGET),)) 181</pre> 182<p>The first line defines rules to compile each source in <code>SOURCES</code>, using the 183flags in <code>CFLAGS</code>:</p> 184<pre class="prettyprint"> 185$(foreach src,$(SOURCES),$(eval $(call COMPILE_RULE,$(src),$(CFLAGS)))) 186</pre> 187<p>The next six lines define rules to link the object files into one or more 188executables. When <code>TOOLCHAIN</code> is <code>pnacl</code>, there is only one executable 189generated: in the example above, <code>part2.pexe</code>. When using a NaCl toolchain, 190there will be three executables generated, one for each architecture: in the 191example above, <code>part2_arm.nexe</code>, <code>part2_x86_32.nexe</code> and 192<code>part2_x86_64.nexe</code>.</p> 193<p>When <code>CONFIG</code> is <code>Release</code>, each executable is also stripped to remove 194debug information and reduce the file size. Otherwise, when the <code>TOOLCHAIN</code> 195is <code>pnacl</code>, the workflow involves creating an unstripped binary for debugging 196and then finalizing it and stripping it for publishing.</p> 197<pre class="prettyprint"> 198ifneq (,$(or $(findstring pnacl,$(TOOLCHAIN)),$(findstring Release,$(CONFIG)))) 199$(eval $(call LINK_RULE,$(TARGET)_unstripped,$(SOURCES),$(LIBS),$(DEPS))) 200$(eval $(call STRIP_RULE,$(TARGET),$(TARGET)_unstripped)) 201else 202$(eval $(call LINK_RULE,$(TARGET),$(SOURCES),$(LIBS),$(DEPS))) 203endif 204</pre> 205<p>Finally, the NMF rule generates a NaCl manifest file (<code>.nmf</code>) that references 206each executable generated in the previous step:</p> 207<pre class="prettyprint"> 208$(eval $(call NMF_RULE,$(TARGET),)) 209</pre> 210</section></section><section id="making-index-html-work-for-chrome-apps"> 211<h2 id="making-index-html-work-for-chrome-apps">Making index.html work for Chrome Apps</h2> 212<p>This section describes the changes necessary to make the HTML and JavaScript 213in part1 CSP-compliant. This is required if you want to build a <a class="reference external" href="https://developer.chrome.com/apps/about_apps.html">Chrome App</a>, but is not necessary 214if you want to use PNaCl on the open web.</p> 215<section id="csp-rules"> 216<h3 id="csp-rules">CSP rules</h3> 217<p><a class="reference external" href="http://developer.chrome.com/apps/contentSecurityPolicy.html#what">Chrome Apps CSP</a> 218restricts you from doing the following:</p> 219<ul class="small-gap"> 220<li>You can’t use inline scripting in your Chrome App pages. The restriction 221bans both <code><script></code> blocks and event handlers (<code><button onclick="..."></code>).</li> 222<li>You can’t reference any external resources in any of your app files (except 223for video and audio resources). You can’t embed external resources in an 224iframe.</li> 225<li>You can’t use string-to-JavaScript methods like <code>eval()</code> and <code>new 226Function()</code>.</li> 227</ul> 228</section><section id="making-index-html-csp-compliant"> 229<h3 id="making-index-html-csp-compliant">Making index.html CSP-compliant</h3> 230<p>To make our application CSP-compliant, we have to remove inline scripting. As 231described above, we can’t use inline <code><script></code> blocks or event handlers. This 232is easy to do—we’ll just reference some new files from our script tag, and 233remove all of our inlined scripts:</p> 234<pre class="prettyprint"> 235<head> 236 ... 237 <script type="text/javascript" src="common.js"></script> 238 <script type="text/javascript" src="example.js"></script> 239</head> 240</pre> 241<p><code>common.js</code> has shared code used by all SDK examples, and is described 242later in this document. <code>example.js</code> is a script that has code specific to 243this example.</p> 244<p>We also need to remove the inline event handler on the body tag:</p> 245<pre class="prettyprint"> 246<body onload="pageDidLoad()"> 247... 248</pre> 249<p>This logic is now handled by <code>common.js</code>.</p> 250</section><section id="making-index-html-support-different-toolchains-and-configurations"> 251<h3 id="making-index-html-support-different-toolchains-and-configurations">Making index.html support different toolchains and configurations</h3> 252<p>Finally, there are a few changes to <code>index.html</code> that are not necessary for 253CSP-compliance, but help make the SDK examples more generic.</p> 254<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> 255to the body element to specify the name, supported toolchains, supported 256configurations, and path to the <code>.nmf</code> file:</p> 257<pre class="prettyprint"> 258<body data-name="part2" 259 data-tools="newlib glibc pnacl" 260 data-configs="Debug Release" 261 data-path="{tc}/{config}"> 262... 263</pre> 264<p><code>common.js</code> will read these data attributes to allow you to load the same 265example 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 266glibc Debug version of this example by navigating to 267<code>index.html?tc=glibc&config=Debug</code>.</p> 268<p>Next, we remove the <code>embed</code> element that is described in HTML. This will be 269automatically added for us by <code>common.js</code>, based on the current 270toolchain/configuration combination:</p> 271<pre class="prettyprint"> 272<!-- 273Just as in part1, the <embed> element will be wrapped inside the <div> 274element with the id "listener". In part1, the embed was specified in HTML, 275here the common.js module creates a new <embed> element and adds it to the 276<div> for us. 277--> 278<div id="listener"></div> 279</pre> 280</section></section><section id="sharing-common-code-with-common-js"> 281<h2 id="sharing-common-code-with-common-js">Sharing common code with common.js</h2> 282<p><code>common.js</code> contains JavaScript code that each example uses to create a 283NaCl module, handle messages from that module and other common tasks like 284displaying the module load status and logging messages. Explaining all of 285<code>common.js</code> is outside the scope of this document, but please look at the 286documentation in that file for more information.</p> 287<section id="loading-the-page-and-creating-the-module"> 288<h3 id="loading-the-page-and-creating-the-module">Loading the page and creating the module</h3> 289<p>Since we’ve added <code><script></code> tags for <code>common.js</code> and <code>example.js</code> to the 290<code>head</code> element, they will be loaded and executed before the rest of the 291document has been parsed. As a result, we have to wait for the page to finish 292loading before we try to create the embed element and add it to the page.</p> 293<p>We can do that by calling <code>addEventListener</code> and listening for the 294<code>DOMContentLoaded</code> event:</p> 295<pre class="prettyprint"> 296// Listen for the DOM content to be loaded. This event is fired when parsing of 297// the page's document has finished. 298document.addEventListener('DOMContentLoaded', function() { 299 ... 300}); 301</pre> 302<p>Inside this function, we parse the URL query string, and compare that to the 303data attributes:</p> 304<pre class="prettyprint"> 305// From https://developer.mozilla.org/en-US/docs/DOM/window.location 306var searchVars = {}; 307if (window.location.search.length > 1) { 308 var pairs = window.location.search.substr(1).split('&'); 309 for (var key_ix = 0; key_ix < pairs.length; key_ix++) { 310 var keyValue = pairs[key_ix].split('='); 311 searchVars[unescape(keyValue[0])] = 312 keyValue.length > 1 ? unescape(keyValue[1]) : ''; 313 } 314} 315 316... 317 318var toolchains = body.dataset.tools.split(' '); 319var configs = body.dataset.configs.split(' '); 320 321... 322 323var tc = toolchains.indexOf(searchVars.tc) !== -1 ? 324 searchVars.tc : toolchains[0]; 325 326// If the config value is included in the search vars, use that. 327// Otherwise default to Release if it is valid, or the first value if 328// Release is not valid. 329if (configs.indexOf(searchVars.config) !== -1) 330 var config = searchVars.config; 331else if (configs.indexOf('Release') !== -1) 332 var config = 'Release'; 333else 334 var config = configs[0]; 335</pre> 336<p>Then <code>domContentLoaded</code> is called, which performs some checks to see if the 337browser supports Native Client, then creates the NaCl module.</p> 338<pre class="prettyprint"> 339function domContentLoaded(name, tool, path, width, height, attrs) { 340 updateStatus('Page loaded.'); 341 if (!browserSupportsNaCl(tool)) { 342 updateStatus( 343 'Browser does not support NaCl (' + tool + '), or NaCl is disabled'); 344 } else if (common.naclModule == null) { 345 updateStatus('Creating embed: ' + tool); 346 347 // We use a non-zero sized embed to give Chrome space to place the bad 348 // plug-in graphic, if there is a problem. 349 width = typeof width !== 'undefined' ? width : 200; 350 height = typeof height !== 'undefined' ? height : 200; 351 attachDefaultListeners(); 352 createNaClModule(name, tool, path, width, height, attrs); 353 } else { 354 // It's possible that the Native Client module onload event fired 355 // before the page's onload event. In this case, the status message 356 // will reflect 'SUCCESS', but won't be displayed. This call will 357 // display the current message. 358 updateStatus('Waiting.'); 359 } 360} 361</pre> 362<p><code>attachDefaultListeners</code> is added before the creation of the module, to make 363sure that no messages are lost. Note that <code>window.attachListeners</code> is also 364called; this is the way that <code>common.js</code> allows each example to configure 365itself differently. If an example defines the <code>attachListeners</code> function, it 366will be called by <code>common.js</code>.</p> 367<pre class="prettyprint"> 368function attachDefaultListeners() { 369 var listenerDiv = document.getElementById('listener'); 370 listenerDiv.addEventListener('load', moduleDidLoad, true); 371 listenerDiv.addEventListener('message', handleMessage, true); 372 listenerDiv.addEventListener('crash', handleCrash, true); 373 if (typeof window.attachListeners !== 'undefined') { 374 window.attachListeners(); 375 } 376} 377</pre> 378<p>Finally, <code>createNaClModule</code> actually creates the <code>embed</code>, and appends it as 379a child of the element with id <code>listener</code>:</p> 380<pre class="prettyprint"> 381function createNaClModule(name, tool, path, width, height, attrs) { 382 var moduleEl = document.createElement('embed'); 383 moduleEl.setAttribute('name', 'nacl_module'); 384 moduleEl.setAttribute('id', 'nacl_module'); 385 moduleEl.setAttribute('width', width); 386 moduleEl.setAttribute('height', height); 387 moduleEl.setAttribute('path', path); 388 moduleEl.setAttribute('src', path + '/' + name + '.nmf'); 389 390 ... 391 392 var mimetype = mimeTypeForTool(tool); 393 moduleEl.setAttribute('type', mimetype); 394 395 var listenerDiv = document.getElementById('listener'); 396 listenerDiv.appendChild(moduleEl); 397 ... 398} 399</pre> 400<p>When the module finishes loading, it will dispatch a <code>load</code> event, and the 401event listener function that was registered above (<code>moduleDidLoad</code>) will be 402called. Note that <code>common.js</code> allows each example to define a 403<code>window.moduleDidLoad</code> function, that will be called here as well.</p> 404<pre class="prettyprint"> 405function moduleDidLoad() { 406 common.naclModule = document.getElementById('nacl_module'); 407 updateStatus('RUNNING'); 408 409 if (typeof window.moduleDidLoad !== 'undefined') { 410 window.moduleDidLoad(); 411 } 412} 413</pre> 414</section></section><section id="example-specific-behavior-with-example-js"> 415<h2 id="example-specific-behavior-with-example-js">Example-specific behavior with example.js</h2> 416<p>As described in the previous section, <code>common.js</code> will call certain functions 417during the module loading process. This example only needs to respond to two: 418<code>moduleDidLoad</code> and <code>handleMessage</code>.</p> 419<pre class="prettyprint"> 420// This function is called by common.js when the NaCl module is 421// loaded. 422function moduleDidLoad() { 423 // Once we load, hide the plugin. In this example, we don't display anything 424 // in the plugin, so it is fine to hide it. 425 common.hideModule(); 426 427 // After the NaCl module has loaded, common.naclModule is a reference to the 428 // NaCl module's <embed> element. 429 // 430 // postMessage sends a message to it. 431 common.naclModule.postMessage('hello'); 432} 433 434// This function is called by common.js when a message is received from the 435// NaCl module. 436function handleMessage(message) { 437 var logEl = document.getElementById('log'); 438 logEl.textContent += message.data; 439} 440</pre> 441</section></section> 442 443{{/partials.standard_nacl_article}} 444