summaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
authorBen Noordhuis <info@bnoordhuis.nl>2018-01-20 01:00:34 +0100
committerRuben Bridgewater <ruben@bridgewater.de>2018-01-21 02:19:46 +0100
commitd9b59def72c718aaad3eefb6bf43f409ccefe4d2 (patch)
treeec02442a3153500b91e368c873db4d1a3763e567 /doc
parentc6682636be4955e2181c00e7d4868fbf6682a5c5 (diff)
downloadandroid-node-v8-d9b59def72c718aaad3eefb6bf43f409ccefe4d2.tar.gz
android-node-v8-d9b59def72c718aaad3eefb6bf43f409ccefe4d2.tar.bz2
android-node-v8-d9b59def72c718aaad3eefb6bf43f409ccefe4d2.zip
build,test: make building addon tests less fragile
* Get rid of recursive `make` when building the node binary. An earlier commit makes GYP write out rules that we can use for proper dependency tracking. * Use module name 'binding' in addons.md and addons-napi/*/binding.gyp. This massively simplifies the logic for generating the build rules. * Check in auto-generated add-on tests from `doc/api/addons.md`. The files change rarely and generating them dynamically causes no end of race conditions and special-casing during the build. PR-URL: https://github.com/nodejs/node/pull/17407 Reviewed-By: Richard Lau <riclau@uk.ibm.com>
Diffstat (limited to 'doc')
-rw-r--r--doc/api/addons.md101
1 files changed, 52 insertions, 49 deletions
diff --git a/doc/api/addons.md b/doc/api/addons.md
index e2df5f30e9..6b84723791 100644
--- a/doc/api/addons.md
+++ b/doc/api/addons.md
@@ -1,3 +1,6 @@
+<!--
+Run `node tools/doc/addon-verify.js` when you change examples in this document.
+-->
# C++ Addons
<!--introduced_in=v0.10.0-->
@@ -94,12 +97,12 @@ The `module_name` must match the filename of the final binary (excluding
the .node suffix).
In the `hello.cc` example, then, the initialization function is `init` and the
-Addon module name is `addon`.
+Addon module name is `binding`.
### Building
Once the source code has been written, it must be compiled into the binary
-`addon.node` file. To do so, create a file called `binding.gyp` in the
+`binding.node` file. To do so, create a file called `binding.gyp` in the
top-level of the project describing the build configuration of the module
using a JSON-like format. This file is used by [node-gyp][] -- a tool written
specifically to compile Node.js Addons.
@@ -108,7 +111,7 @@ specifically to compile Node.js Addons.
{
"targets": [
{
- "target_name": "addon",
+ "target_name": "binding",
"sources": [ "hello.cc" ]
}
]
@@ -128,21 +131,21 @@ generate the appropriate project build files for the current platform. This
will generate either a `Makefile` (on Unix platforms) or a `vcxproj` file
(on Windows) in the `build/` directory.
-Next, invoke the `node-gyp build` command to generate the compiled `addon.node`
-file. This will be put into the `build/Release/` directory.
+Next, invoke the `node-gyp build` command to generate the compiled
+`binding.node` file. This will be put into the `build/Release/` directory.
When using `npm install` to install a Node.js Addon, npm uses its own bundled
version of `node-gyp` to perform this same set of actions, generating a
compiled version of the Addon for the user's platform on demand.
Once built, the binary Addon can be used from within Node.js by pointing
-[`require()`][require] to the built `addon.node` module:
+[`require()`][require] to the built `binding.node` module:
```js
// hello.js
-const addon = require('./build/Release/addon');
+const binding = require('./build/Release/binding');
-console.log(addon.hello());
+console.log(binding.hello());
// Prints: 'world'
```
@@ -159,9 +162,9 @@ similar to:
```js
try {
- return require('./build/Release/addon.node');
+ return require('./build/Release/binding.node');
} catch (err) {
- return require('./build/Debug/addon.node');
+ return require('./build/Debug/binding.node');
}
```
@@ -195,9 +198,9 @@ When calling [`require()`][require], the `.node` extension can usually be
omitted and Node.js will still find and initialize the Addon. One caveat,
however, is that Node.js will first attempt to locate and load modules or
JavaScript files that happen to share the same base name. For instance, if
-there is a file `addon.js` in the same directory as the binary `addon.node`,
-then [`require('addon')`][require] will give precedence to the `addon.js` file
-and load it instead.
+there is a file `binding.js` in the same directory as the binary `binding.node`,
+then [`require('binding')`][require] will give precedence to the `binding.js`
+file and load it instead.
## Native Abstractions for Node.js
@@ -284,8 +287,8 @@ Each of these examples using the following `binding.gyp` file:
{
"targets": [
{
- "target_name": "addon",
- "sources": [ "addon.cc" ]
+ "target_name": "binding",
+ "sources": [ "binding.cc" ]
}
]
}
@@ -295,7 +298,7 @@ In cases where there is more than one `.cc` file, simply add the additional
filename to the `sources` array. For example:
```json
-"sources": ["addon.cc", "myexample.cc"]
+"sources": ["binding.cc", "myexample.cc"]
```
Once the `binding.gyp` file is ready, the example Addons can be configured and
@@ -317,7 +320,7 @@ The following example illustrates how to read function arguments passed from
JavaScript and how to return a result:
```cpp
-// addon.cc
+// binding.cc
#include <node.h>
namespace demo {
@@ -374,9 +377,9 @@ Once compiled, the example Addon can be required and used from within Node.js:
```js
// test.js
-const addon = require('./build/Release/addon');
+const binding = require('./build/Release/binding');
-console.log('This should be eight:', addon.add(3, 5));
+console.log('This should be eight:', binding.add(3, 5));
```
@@ -387,7 +390,7 @@ function and execute them from there. The following example illustrates how
to invoke such callbacks:
```cpp
-// addon.cc
+// binding.cc
#include <node.h>
namespace demo {
@@ -427,9 +430,9 @@ To test it, run the following JavaScript:
```js
// test.js
-const addon = require('./build/Release/addon');
+const binding = require('./build/Release/binding');
-addon((msg) => {
+binding((msg) => {
console.log(msg);
// Prints: 'hello world'
});
@@ -444,7 +447,7 @@ illustrated in the following example. An object is created and returned with a
property `msg` that echoes the string passed to `createObject()`:
```cpp
-// addon.cc
+// binding.cc
#include <node.h>
namespace demo {
@@ -478,10 +481,10 @@ To test it in JavaScript:
```js
// test.js
-const addon = require('./build/Release/addon');
+const binding = require('./build/Release/binding');
-const obj1 = addon('hello');
-const obj2 = addon('world');
+const obj1 = binding('hello');
+const obj2 = binding('world');
console.log(obj1.msg, obj2.msg);
// Prints: 'hello world'
```
@@ -493,7 +496,7 @@ Another common scenario is creating JavaScript functions that wrap C++
functions and returning those back to JavaScript:
```cpp
-// addon.cc
+// binding.cc
#include <node.h>
namespace demo {
@@ -537,9 +540,9 @@ To test:
```js
// test.js
-const addon = require('./build/Release/addon');
+const binding = require('./build/Release/binding');
-const fn = addon();
+const fn = binding();
console.log(fn());
// Prints: 'hello world'
```
@@ -551,7 +554,7 @@ It is also possible to wrap C++ objects/classes in a way that allows new
instances to be created using the JavaScript `new` operator:
```cpp
-// addon.cc
+// binding.cc
#include <node.h>
#include "myobject.h"
@@ -686,9 +689,9 @@ To build this example, the `myobject.cc` file must be added to the
{
"targets": [
{
- "target_name": "addon",
+ "target_name": "binding",
"sources": [
- "addon.cc",
+ "binding.cc",
"myobject.cc"
]
}
@@ -700,9 +703,9 @@ Test it with:
```js
// test.js
-const addon = require('./build/Release/addon');
+const binding = require('./build/Release/binding');
-const obj = new addon.MyObject(10);
+const obj = new binding.MyObject(10);
console.log(obj.plusOne());
// Prints: 11
console.log(obj.plusOne());
@@ -717,15 +720,15 @@ Alternatively, it is possible to use a factory pattern to avoid explicitly
creating object instances using the JavaScript `new` operator:
```js
-const obj = addon.createObject();
+const obj = binding.createObject();
// instead of:
-// const obj = new addon.Object();
+// const obj = new binding.Object();
```
-First, the `createObject()` method is implemented in `addon.cc`:
+First, the `createObject()` method is implemented in `binding.cc`:
```cpp
-// addon.cc
+// binding.cc
#include <node.h>
#include "myobject.h"
@@ -881,9 +884,9 @@ Once again, to build this example, the `myobject.cc` file must be added to the
{
"targets": [
{
- "target_name": "addon",
+ "target_name": "binding",
"sources": [
- "addon.cc",
+ "binding.cc",
"myobject.cc"
]
}
@@ -895,7 +898,7 @@ Test it with:
```js
// test.js
-const createObject = require('./build/Release/addon');
+const createObject = require('./build/Release/binding');
const obj = createObject(10);
console.log(obj.plusOne());
@@ -923,7 +926,7 @@ wrapped objects around by unwrapping them with the Node.js helper function
that can take two `MyObject` objects as input arguments:
```cpp
-// addon.cc
+// binding.cc
#include <node.h>
#include <node_object_wrap.h>
#include "myobject.h"
@@ -1077,11 +1080,11 @@ Test it with:
```js
// test.js
-const addon = require('./build/Release/addon');
+const binding = require('./build/Release/binding');
-const obj1 = addon.createObject(10);
-const obj2 = addon.createObject(20);
-const result = addon.add(obj1, obj2);
+const obj1 = binding.createObject(10);
+const obj2 = binding.createObject(20);
+const result = binding.add(obj1, obj2);
console.log(result);
// Prints: 30
@@ -1106,10 +1109,10 @@ and a pointer to untyped context data to be passed to that callback.
Callbacks are run in last-in first-out order.
-The following `addon.cc` implements AtExit:
+The following `binding.cc` implements AtExit:
```cpp
-// addon.cc
+// binding.cc
#include <assert.h>
#include <stdlib.h>
#include <node.h>
@@ -1161,7 +1164,7 @@ Test in JavaScript by running:
```js
// test.js
-require('./build/Release/addon');
+require('./build/Release/binding');
```
[Embedder's Guide]: https://github.com/v8/v8/wiki/Embedder's%20Guide