OLD | NEW |
---|---|
1 .. _tutorial: | 1 .. _tutorial: |
2 | 2 |
3 ######################## | 3 ######################## |
4 Getting Started Tutorial | 4 C++ Tutorial: Getting Started |
5 ######################## | 5 ######################## |
eliben
2013/09/04 20:00:52
These should be the same length as the text above/
binji
2013/09/04 20:49:41
Ah, it does but I didn't notice it :)
done.
| |
6 | 6 |
7 This is the tutorial. | 7 .. contents:: |
8 | 8 :local: |
9 :backlinks: none | |
10 :depth: 1 | |
eliben
2013/09/04 20:00:52
I think it makes sense to consistently set it to 2
binji
2013/09/04 20:49:41
That is the way the current document displays it.
| |
11 | |
12 Overview | |
13 ======== | |
14 | |
15 This tutorial shows you how to create, compile, and run a Native Client web | |
16 application. The Native Client module you will create as part of the web | |
17 application will be written in C++. | |
18 | |
19 We recommend reading the :doc:`Native Client Technical Overview | |
20 <../overview>` prior to going through this tutorial. | |
21 | |
22 Parts in a Native Client application | |
23 ------------------------------------ | |
24 | |
25 A Native Client web application consists of at least three parts: | |
eliben
2013/09/04 20:00:52
I have this in the technical overview too. Once we
binji
2013/09/04 20:49:41
Added a TODO.
| |
26 | |
27 * **a web page** (\*.html) | |
eliben
2013/09/04 20:00:52
How do you expect this to be formatted? If you wan
binji
2013/09/04 20:49:41
Done. Though it looks more "spread out" than in th
| |
28 The web page can include HTML, JavaScript, and CSS (the JavaScript and CSS | |
29 can also go in separate .js and .css files). | |
30 * **a Native Client module** (\*.c or \*.cc before compiling; \*.nexe after | |
eliben
2013/09/04 20:00:52
Ah, so it's just ReST translation, no PNaCl yet?
binji
2013/09/04 20:49:41
Yes, I'll mention that in the CL description.
| |
31 compiling) | |
32 Native Client modules can be written in C or C++. Modules use the Pepper API, | |
33 included in the SDK, as a bridge between the browser and the modules. | |
34 * **manifest file** (\*.nmf) | |
35 Browsers use an application's manifest file to determine which compiled Native | |
36 Client module to load based on the instruction set architecture of the user's | |
37 machine (e.g., x86-32, x86-64, or ARM). | |
38 | |
39 What the application in this tutorial does | |
40 ------------------------------------------ | |
41 | |
42 The application in this tutorial shows how to load a Native Client module in a | |
43 web page, and how to send messages between JavaScript code and the C or C++ | |
44 code in the Native Client module. In this simple application, the JavaScript | |
45 code in the web page sends a 'hello' message to the Native Client module. When | |
46 the Native Client module receives a message, it checks whether the message is | |
47 equal to the string 'hello'. If it is, the Native Client module returns a | |
48 message saying 'hello from NaCl'. A JavaScript alert panel displays the message | |
49 received from the Native Client module. | |
50 | |
51 This tutorial also shows you how to create a set of template files that you can | |
52 use as a starting point for a Native Client application. The template code sets | |
53 up a simple message handler on the Native Client side, and includes boilerplate | |
54 code in the HTML file for adding an event listener to the web page to receive | |
55 messages from the Native Client module. | |
56 | |
57 Communication between JavaScript code and Native Client modules | |
58 --------------------------------------------------------------- | |
59 | |
60 Communication between JavaScript code in the browser and C or C++ code in a | |
61 Native Client module is two-way: JavaScript code can send messages to the | |
62 Native Client module; the C or C++ code can respond to messages from | |
63 JavaScript, or it can initiate its own messages to JavaScript. In all cases, | |
64 the communication is asynchronous: The caller (the JavaScript code in the | |
65 browser or the C/C++ code in the Native Client module) sends a message, but the | |
66 caller does not wait for, or may not even expect, a response. This behavior is | |
67 analogous to client/server communication on the web, where the client posts a | |
68 message to the server and returns immediately. The Native Client messaging | |
69 system is part of the Pepper API, and is described in detail in the | |
70 :doc:`Messaging System <coding/message-system>` chapter in the Developer's | |
71 Guide. | |
72 | |
73 Step 1: Download and install the Native Client SDK, Python, and Xcode Developer Tools (if necessary). | |
eliben
2013/09/04 20:00:52
The title should probably be shorter
binji
2013/09/04 20:49:41
Done.
| |
74 ================================================================================ ===================== | |
75 | |
76 Follow the instructions on the :doc:`Download <../sdk/download>` page to | |
77 download and install the Native Client SDK. | |
78 | |
79 .. Note:: | |
80 :class: caution | |
81 | |
82 **Important:** A number of tools in the SDK require Python to run. Python is | |
83 typically included on Mac and Linux systems, but not on Windows systems. To | |
84 check whether you have Python installed on your system, enter the | |
85 '``python``' command on the command line; you should get the interactive | |
86 Python prompt (``>>>``). On Mac systems, you also need to install '``make``' | |
87 in order to build and run the examples in the SDK; one easy way to get | |
88 '``make``', along with several other useful tools, is to install Xcode | |
89 Developer Tools. Follow the instructions at the top of the :doc:`Download | |
90 <../sdk/download>` page if you need to install Python and/or Xcode | |
91 Developer Tools. | |
92 | |
93 Step 2: Start a local server. | |
eliben
2013/09/04 20:00:52
Should title really end with periods?
binji
2013/09/04 20:49:41
Seems strange to me too. Done.
| |
94 ============================= | |
95 | |
96 TODO(binji): This is not necessary anymore; we can use ``make run``. Some of | |
97 the information about why you need a webserver is still useful though... | |
98 Remove? | |
99 | |
100 To protect against security vulnerabilities, you must load Native Client | |
101 modules from a web server (either remote or local). **Simply dragging and | |
102 dropping Native Client files into the browser address bar will not work.** For | |
103 more information, read about the `Same Origin Policy | |
104 <http://www.w3.org/Security/wiki/Same_Origin_Policy>`_, which protects the | |
105 user's file system from outside access. | |
106 | |
107 The Native Client SDK includes a simple Python web server that you can use to | |
108 run applications that you build (including the application in this tutorial). | |
109 The server is located in the tools directory. To start the web server, go to | |
110 the examples directory in the SDK bundle that you are using and run the | |
111 ``httpd.py`` script. For example, if you are using the ``pepper_28`` bundle, | |
112 run the following commands:: | |
113 | |
114 cd pepper_28/examples | |
eliben
2013/09/04 20:00:52
use naclcode with :prettyprint: 0 for all these
binji
2013/09/04 20:49:41
Done.
| |
115 python ../tools/httpd.py | |
116 | |
117 If you don't specify a port number, the server defaults to port 5103, and you | |
118 can access the server at http://localhost:5103. | |
119 | |
120 Of course, you don't have to use the server included in the SDK---any web server | |
121 will do. If you prefer to use another web server already installed on your | |
122 system, that's fine. Note also that there are ways to run Native Client | |
123 applications during development without a server, but these techniques require | |
124 you to create additional files for your application (see :doc:`Running Native | |
125 Client Applications <devcycle/running>` for details). For this tutorial, | |
126 your application must come from a server. | |
127 | |
128 .. _step_3: | |
129 | |
130 Step 3: Set up Google Chrome. | |
131 ============================= | |
132 | |
133 Set up the Chrome browser as follows: | |
134 | |
135 a. Make sure you are using the minimum required version of Chrome. | |
136 | |
137 * Your version of Chrome must be equal to or greater than the version of your | |
138 Pepper bundle. For example, if you're developing with the ``pepper_28`` | |
139 bundle, you must use Google Chrome version 28 or greater. To find out what | |
140 version of Chrome you're using, type ``about:chrome`` or ``about:version`` | |
141 in the Chrome address bar. | |
142 | |
143 b. Enable the Native Client flag in Chrome. (Native Client is enabled by | |
144 default for applications distributed through the Chrome Web Store. To run | |
145 Native Client applications that are not distributed through the Chrome Web | |
146 Store, e.g., applications that you build and run locally, you must | |
147 specifically enable the Native Client flag in Chrome.) | |
148 | |
149 * Type ``about:flags`` in the Chrome address bar and scroll down to "Native | |
150 Client". | |
151 * If the link below "Native Client" says "Disable", then Native Client is | |
152 already enabled and you don't need to do anything else. | |
153 * If the link below "Native Client" says "Enable", click the "Enable" link, | |
154 scroll down to the bottom of the page, and click the "Relaunch Now" button. | |
155 All browser windows will restart when you relaunch Chrome. | |
156 | |
157 c. Disable the Chrome cache. (Chrome caches resources aggressively; you should | |
158 disable the cache whenever you are developing a Native Client application in | |
159 order to make sure Chrome loads new versions of your application.) | |
160 | |
161 * Open Chrome's developer tools by clicking the menu icon |menu-icon| and | |
162 choosing Tools > Developer tools. | |
163 * Click the gear icon |gear-icon| in the bottom right corner of the Chrome | |
164 window. | |
165 * Under the "General" settings, check the box next to "Disable cache". | |
166 | |
167 .. |menu-icon| image:: /images/menu-icon.png | |
168 .. |gear-icon| image:: /images/gear-icon.png | |
169 | |
170 Step 4: Create a set of stub files for your application. | |
171 ======================================================== | |
172 | |
173 Create a set of stub files as follows: | |
174 | |
175 a. Download `hello_tutorial.zip | |
176 <https://developers.google.com/native-client/devguide/hello_tutorial.zip>`_. | |
177 | |
178 b. Unzip hello_tutorial.zip: | |
179 | |
180 * On Mac/Linux, run the command "``unzip hello_tutorial.zip``" in a Terminal | |
181 window. | |
182 * On Windows, right-click on the .zip file and select "Extract All..." A | |
183 dialog box will open; enter a location and click "Extract". | |
184 | |
185 c. Unzipping hello_tutorial.zip creates a directory called ``hello_tutorial`` | |
186 with the following files: | |
187 | |
188 * ``hello_tutorial.html`` | |
189 * ``hello_tutorial.cc`` | |
190 * ``hello_tutorial.nmf`` | |
191 * ``Makefile`` | |
192 * ``make.bat`` (for Windows) | |
193 | |
194 d. Move the ``hello_tutorial`` directory so that it's under the ``examples`` | |
195 directory where you started the local server. Its location should be, e.g., | |
196 ``pepper_28/examples/hello_tutorial``. | |
197 | |
198 * On Windows, depending on the location you entered when you unzipped the | |
199 file, there may be two ``hello_tutorial`` directories—one nested within | |
200 the other. Move only the inner (nested) directory to the ``examples`` | |
201 directory. | |
202 | |
203 .. Note:: | |
204 :class: note | |
205 | |
206 **Note regarding the location of project directories:** | |
207 | |
208 * In this tutorial, you are adding the ``hello_tutorial`` directory under the | |
209 ``examples`` directory because the ``examples`` directory is where your | |
210 local server is running, ready to serve your tutorial application. You can | |
211 place your project directory anywhere on your file system, as long as that | |
212 location is being served by your server. | |
213 * If you do place the ``hello_tutorial`` project directory in another | |
214 location, you must set the `environment variable | |
215 <http://en.wikipedia.org/wiki/Environment_variable>`_ ``NACL_SDK_ROOT`` to | |
216 point to the top-level directory of the bundle you are using (e.g., | |
217 ``<location-where-you-installed-the-SDK>/pepper_28``) in order for the | |
218 Makefile that's included in the project directory to work. | |
219 * If you use the location recommended above | |
220 (``pepper_28/examples/hello_tutorial``), be careful when you update the | |
221 SDK. The command '``naclsdk update pepper_28 --force``' will overwrite the | |
222 ``pepper_28`` directory, so move any project directories you want to keep | |
223 to another location. | |
224 | |
225 Step 5: Compile the Native Client module and run the stub application. | |
226 ====================================================================== | |
227 | |
228 The files you downloaded in the previous step constitute a stub application | |
229 that simply loads a Native Client module into a web page and updates a | |
230 ``<div>`` element on the page with the status of the module load. | |
231 | |
232 To compile the Native Client module ``hello_tutorial.cc,`` run '``make``':: | |
233 | |
234 cd pepper_28/examples/hello_tutorial | |
235 make | |
236 | |
237 The '``make``' command runs the necessary compile and link commands to produce | |
238 three executable Native Client modules (for the x86-32, x86-64, and ARM | |
239 architectures). The executable files are named as follows: | |
240 | |
241 * ``hello_tutorial_x86_32.nexe`` | |
242 * ``hello_tutorial_x86_64.nexe`` | |
243 * ``hello_tutorial_arm.nexe`` | |
244 | |
245 Assuming you are using the local server and the project directory specified | |
246 above, you can load the ``hello_tutorial.html`` web page into Chrome by visiting | |
247 the following URL: http://localhost:5103/hello_tutorial/hello_tutorial.html. If | |
248 Chrome loads the Native Client module successfully, the Status display on the | |
249 page should change from "LOADING..." to "SUCCESS". | |
250 | |
251 Step 6: Review the code in the stub application. | |
252 ================================================ | |
253 | |
254 The section highlights some of the code in the stub application. | |
255 | |
256 Makefile | |
257 ``Makefile`` contains the compile and link commands to build the executable | |
258 Native Client modules (.nexe files) for your application. The Native Client | |
259 SDK includes multiple GCC‑based toolchains to build modules for multiple | |
260 architectures (x86 and ARM) using different implementations of the C library | |
261 (`newlib <http://www.sourceware.org/newlib/>`_ and `glibc | |
262 <http://www.gnu.org/software/libc/>`_). The commands in the tutorial | |
263 ``Makefile`` build the application using the newlib C library for the x86 and | |
264 ARM architectures. The commands use the toolchains located in the | |
265 ``pepper_28/toolchain/<platform>_x86_newlib`` and ``<platform>_arm_newlib`` | |
266 directories. For information about how to use Makefiles and the '``make``' | |
267 command, see the `GNU 'make' manual | |
268 <http://www.gnu.org/software/make/manual/make.html>`_. | |
269 | |
270 hello_tutorial.nmf | |
271 ``hello_tutorial.nmf`` is a Native Client manifest file that tells Chrome | |
272 which compiled Native Client module (.nexe) to load based on the instruction | |
273 set architecture of the user's machine (e.g., x86-32, x86-64, or ARM). For | |
274 applications compiled using glibc, manifest files must also specify the | |
275 shared libraries that the applications use. | |
276 | |
277 hello_tutorial.html | |
278 ``hello_tutorial.html`` is the web page that corresponds to your application. | |
279 The page includes an ``<embed>`` element that loads the compiled Native | |
280 Client module:: | |
281 | |
282 <div id="listener"> | |
283 <script type="text/javascript"> | |
284 var listener = document.getElementById('listener'); | |
285 listener.addEventListener('load', moduleDidLoad, true); | |
286 listener.addEventListener('message', handleMessage, true); | |
287 </script> | |
288 | |
289 <embed name="nacl_module" | |
290 id="hello_tutorial" | |
291 width=0 height=0 | |
292 src="hello_tutorial.nmf" | |
293 type="application/x-nacl" /> | |
294 </div> | |
295 | |
296 The ``src`` attribute in the ``<embed>`` element points to the Native Client | |
297 manifest file, which tells the browser which .nexe file to load based on the | |
298 instruction set architecture of the user's machine. The ``width`` and | |
299 ``height`` attributes in the ``<embed>`` element are set to 0 because the | |
300 Native Client module in this example does not have any graphical component. | |
301 The ``type`` attribute declares the MIME type to be ``x-nacl``, i.e., an | |
302 executable Native Client module. | |
303 | |
304 The ``<embed>`` element is wrapped inside a ``<div>`` element that has two | |
305 event listeners attached—one for the 'load' event, which fires when the | |
306 browser successfully loads the Native Client module, and one for the | |
307 'message' event, which fires when the Native Client module uses the | |
308 ``PostMessage()`` method (in the `pp::Instance | |
309 <https://developers.google.com/native-client/peppercpp/classpp_1_1_instance>`_ | |
310 class) to send a message to the JavaScript code in the application. This | |
311 technique of attaching the event listeners to a parent ``<div>`` element | |
312 (rather than directly to the ``<embed>`` element) is used to ensure that the | |
313 event listeners are active before the module 'load' event fires. | |
314 | |
315 The simple event handlers in this tutorial are implemented in the | |
316 ``moduleDidLoad()`` and ``handleMessage()`` JavaScript functions. | |
317 ``moduleDidLoad()`` changes the text inside the 'status_field' ``<div>`` | |
318 element. handleMessage() displays the content of messages sent from the | |
319 Native Client module in a browser alert panel. For a description of 'load', | |
320 'message', and other Native Client events, see the :doc:`Progress Events | |
321 <coding/progress-events>` chapter of the Developer's Guide. | |
322 | |
323 hello_tutorial.cc | |
324 Native Client includes the concept of modules and instances: | |
325 | |
326 * A **module** is C or C++ code compiled into an executable .nexe file. | |
327 * An **instance** is a rectangle on a web page that is managed by a module. | |
328 The rectangle can have dimensions 0x0, in which case the instance does not | |
329 have a visual component on the web page. An instance is created by | |
330 including an ``<embed>`` element in a web page. A module may be included in | |
331 a web page multiple times by using multiple ``<embed>`` elements that refer | |
332 to the module; in this case the Native Client runtime system loads the | |
333 module once and creates multiple instances that are managed by the module. | |
334 | |
335 The example in this tutorial includes one module | |
336 (``hello_tutorial_x86_32.nexe``, ``hello_tutorial_x86_64.nexe``, or | |
337 ``hello_tutorial_arm.nexe``, depending on the instruction set architecture of | |
338 the user's machine), and one instance (one ``<embed>`` element that loads the | |
339 module). The source code for the module is in the file ``hello_tutorial.cc``. | |
340 This source code contains the minimum code required in a C++ Native Client | |
341 module—an implementation of the `Instance | |
342 <https://developers.google.com/native-client/peppercpp/classpp_1_1_instance>`_ | |
343 and `Module | |
344 <https://developers.google.com/native-client/peppercpp/classpp_1_1_module>`_ | |
345 classes. These implementations don't actually do anything yet. | |
346 | |
347 Step 7: Modify the web page to send a message to the Native Client module. | |
348 ========================================================================== | |
349 | |
350 In this step, you'll modify the web page (``hello_tutorial.html``) to send a | |
351 message to the Native Client module after the page loads the module. | |
352 | |
353 Look for the JavaScript function ``moduleDidLoad()``, and add the new code below | |
354 (indicated by boldface type) to send a 'hello' message to the Native Client | |
355 module:: | |
356 | |
357 function moduleDidLoad() { | |
eliben
2013/09/04 20:00:52
.. naclcode::
binji
2013/09/04 20:49:41
Done.
| |
358 HelloTutorialModule = document.getElementById('hello_tutorial'); | |
359 updateStatus('SUCCESS'); | |
360 // Send a message to the NaCl module. | |
361 HelloTutorialModule.postMessage('hello'); | |
362 } | |
363 | |
364 Step 8: Implement a message handler in the Native Client module. | |
365 ================================================================ | |
366 | |
367 In this step, you'll modify the Native Client module (``hello_tutorial.cc``) to | |
368 respond to the message received from the JavaScript code in the application. | |
369 Specifically, you'll: | |
370 | |
371 * implement the ``HandleMessage()`` function for the module, and | |
372 * use the ``PostMessage()`` function to send a message from the module to the | |
373 JavaScript code | |
374 | |
375 First, add code to define the variables used by the Native Client module (the | |
376 'hello' string you're expecting to receive from JavaScript and the reply string | |
377 you want to return to JavaScript as a response). In the file | |
378 ``hello_tutorial.cc``, add this code after the ``#include`` statements:: | |
379 | |
380 namespace { | |
381 // The expected string sent by the browser. | |
382 const char* const kHelloString = "hello"; | |
383 // The string sent back to the browser upon receipt of a message | |
384 // containing "hello". | |
385 const char* const kReplyString = "hello from NaCl"; | |
386 } // namespace | |
387 | |
388 Now, implement the ``HandleMessage()`` method to check for ``kHelloString`` and | |
389 return ``kReplyString.`` Look for the following line:: | |
390 | |
391 // TODO(sdk_user): 1. Make this function handle the incoming message. | |
392 | |
393 Replace the above line with the boldface code below:: | |
394 | |
395 virtual void HandleMessage(const pp::Var& var_message) { | |
396 if (!var_message.is_string()) | |
397 return; | |
398 std::string message = var_message.AsString(); | |
399 pp::Var var_reply; | |
400 if (message == kHelloString) { | |
401 var_reply = pp::Var(kReplyString); | |
402 PostMessage(var_reply); | |
403 } | |
404 } | |
405 | |
406 See the Pepper API documentation for additional information about the | |
407 `pp::Instance.HandleMessage | |
408 <https://developers.google.com/native-client/peppercpp/classpp_1_1_instance.html #a5dce8c8b36b1df7cfcc12e42397a35e8>`_ | |
409 and `pp::Instance.PostMessage | |
410 <https://developers.google.com/native-client/peppercpp/classpp_1_1_instance.html #a67e888a4e4e23effe7a09625e73ecae9>`_ | |
411 methods. | |
412 | |
413 Step 9: Compile the Native Client module and run the application again. | |
414 ======================================================================= | |
415 | |
416 Compile the Native Client module by running the '``make``' command again. | |
417 | |
418 Run the application by reloading hello_tutorial.html in Chrome. (The page | |
419 should be at http://localhost:5103/hello_tutorial/hello_tutorial.html assuming | |
420 the setup described above.) | |
421 | |
422 After Chrome loads the Native Client module, you should see an alert panel | |
423 appear with the message sent from the module. | |
424 | |
425 Troubleshooting | |
426 =============== | |
427 | |
428 If your application doesn't run, see :ref:`Step 3 <step_3>` above | |
429 to verify that you've set up your environment correctly, including both the | |
430 Chrome browser and the local server. Make sure that you're running a version of | |
431 Chrome that is equal to or greater than the SDK bundle version you are using, | |
432 that you've enabled the Native Client flag and relaunched Chrome, that you've | |
433 disabled the Chrome cache, and that **you're accessing your application from a | |
434 local web server (rather than by dragging the HTML file into your browser)**. | |
435 | |
436 For additional troubleshooting information, check the `FAQ | |
437 <https://developers.google.com/native-client/faq.html#HangOnLoad>`_. | |
438 | |
439 Next steps | |
440 ========== | |
441 | |
442 * See the :doc:`Application Structure <coding/application-structure>` | |
443 chapter in the Developer's Guide for information about how to structure a | |
444 Native Client module. | |
445 * Check the `C++ Reference | |
446 <https://developers.google.com/native-client/peppercpp>`_ for details about | |
447 how to use the Pepper APIs. | |
448 * Browse through the source code of the SDK examples (in the ``examples`` | |
449 directory) to learn additional techniques for writing Native Client | |
450 applications and using the Pepper APIs. | |
451 * See the :doc:`Building <devcycle/building>`, :doc:`Running | |
452 <devcycle/running>`, and :doc:`Debugging pages <devcycle/debugging>` | |
453 for information about how to build, run, and debug Native Client | |
454 applications. | |
455 * Check the `naclports <http://code.google.com/p/naclports/>`_ project to see | |
456 what libraries have been ported for use with Native Client. If you port an | |
457 open-source library for your own use, we recommend adding it to naclports | |
458 (see `How to check code into naclports | |
459 <http://code.google.com/p/naclports/wiki/HowTo_Checkin>`_). | |
OLD | NEW |