# Snippets

## C++ Addon building

**NAPI** addons are built separately from the installation, so we shouldn't
put the file **binding.gyp** to the module root anymore. It is better to have a
separate folder with a separate **package.json**, **binding.gyp** and the sources.

A snippet for **src/package.json**:

```
{
	"name": "build",
	"version": "0.0.0",
	"private": true,
	"scripts": {
		"build": "node-gyp rebuild"
		"build-dev": "node-gyp build && node -e \"require('addon-tools-raub/cpbin')('ADDON')\""
		"rebuild-dev": "node-gyp rebuild && node -e \"require('addon-tools-raub/cpbin')('ADDON')\""
	},
	"dependencies": {
		"addon-tools-raub": "6.2.0",
		"DEPS": "1.0.0"
	}
}
```

* `ADDON` - the name of this addon (and subsequently of its binary).
* `DEPS` - dependency package(s).



### Binary distribution

In **package.json** use the `"postinstall"` script to download the libraries.
For example the following structure might work. Note that **Addon Tools** will
append any given URL with `/${platform}.zip`

In **package.json**:

```
	"scripts": {
		"postinstall": "node install",
	},
	"dependencies": {
		"addon-tools-raub": "^6.2.0",
		"adm-zip": "^0.5.10"
	},
	"devDependencies": {
		"node-addon-api": "^5.0.0"
	}
```

Create the **install.js** file:

```
'use strict';
const install = require('addon-tools-raub/install');
const prefix = 'https://github.com/node-3d/glfw-raub/releases/download';
const tag = '4.8.0';
install(`${prefix}/${tag}`);
```

**Addon Tools** will unzip (using **adm-zip**) the downloaded file into the platform binary
directory. E.g. on Windows it will be **bin-windows**.

* For a dependency package:
	
	Place the following piece of code in the `index.js` without changes. Method `paths()`
	is described [here](../README.md).
	```
	module.exports = require('addon-tools-raub').paths(__dirname);
	```
	
* For a compiled addon:
	
	Require it in your **index.js** from the platform-specific directory.
	```
	const { bin } = require('addon-tools-raub');
	const core = require(`./${bin}/ADDON`);
	```


Publishing binaries is done by attaching a zipped platform folder to the GitHub
release. Zip file must NOT contain platform folder as a subfolder, but rather
contain the final binaries. The tag of the release should be the same as in
**install.js**.

> NOTE: You can publish your binaries to anywhere, not necessarily GitHub.
Just tweak **YOUR install.js** script as appropriate. The only limitation
from **Addon Tools** is that it should be a zipped set of files/folders.


### GYP Variables

```
	'variables': {
		'bin': '<!(node -p "require(\'addon-tools-raub\').bin")',
		'DEPS_include': '<!(node -p "require(\'DEPS\').include")',
		'DEPS_bin': '<!(node -p "require(\'DEPS\').bin")',
	},
```

* `bin` - the name of this platform's binary directory, e.g. *bin-linux*.
* `DEPS_include` - the include folder for some dependency package.
* `DEPS_bin` - the binary folder for some dependency package.



### Include directories

```
	'include_dirs' : [
		'<!@(node -p "require(\'addon-tools-raub\').include")',
		'<(DEPS_include)',
	],
```

The former contains both the path to include **Addon Tools** and the one for
**Napi** (which is preinstalled with Addon Tools). The latter can be any other
dependency include path(s).


<details>

<summary><b>See a snipped for src/binding.gyp here</b></summary>

* Assume `DEPS` is the name of an Addon Tools compliant dependency module.
* Assume `ADDON` is the name of this addon's resulting binary.
* Assume C++ code goes to `cpp` subdirectory.

```
{
	'variables': {
		'bin'          : '<!(node -p "require(\'addon-tools-raub\').bin")',
		'DEPS_include' : '<!(node -p "require(\'DEPS\').include")',
		'DEPS_bin'     : '<!(node -p "require(\'DEPS\').bin")',
	},
	'targets': [{
		'target_name' : 'ADDON',
		'sources' : [
			'cpp/addon.cpp',
		],
		'include_dirs' : [
			'<!@(node -p "require(\'addon-tools-raub\').include")',
			'<(DEPS_include)',
		],
		'cflags_cc': ['-std=c++17', '-fno-exceptions'],
		'library_dirs': ['<(DEPS_bin)'],
		'libraries': ['-lDEPS' ],
		'conditions': [
			['OS=="linux"', {
				'libraries': [
					"-Wl,-rpath,'$$ORIGIN'",
					"-Wl,-rpath,'$$ORIGIN/../node_modules/DEPS/<(bin)'",
					"-Wl,-rpath,'$$ORIGIN/../../DEPS/<(bin)'",
				],
				'defines': ['__linux__'],
			}],
			['OS=="mac"', {
				'libraries': [
					'-Wl,-rpath,@loader_path',
					'-Wl,-rpath,@loader_path/../node_modules/DEPS/<(bin)',
					'-Wl,-rpath,@loader_path/../../DEPS/<(bin)',
				],
				'MACOSX_DEPLOYMENT_TARGET': '10.9',
				'defines': ['__APPLE__'],
				'CLANG_CXX_LIBRARY': 'libc++',
				'OTHER_CFLAGS': ['-std=c++17', '-fno-exceptions'],
			}],
			['OS=="win"', {
				'defines' : ['WIN32_LEAN_AND_MEAN', 'VC_EXTRALEAN', '_WIN32', '_HAS_EXCEPTIONS=0'],
				'msvs_settings' : {
					'VCCLCompilerTool' : {
						'AdditionalOptions' : [
							'/O2','/Oy','/GL','/GF','/Gm-', '/std:c++17',
							'/EHa-s-c-','/MT','/GS','/Gy','/GR-','/Gd',
						]
					},
					'VCLinkerTool' : {
						'AdditionalOptions' : ['/DEBUG:NONE', '/LTCG', '/OPT:NOREF'],
					},
				},
			}],
		],
	}],
}
```

</details>
