Node.js Native Addon Prebuild Loader
node-gyp-build is a critical utility for Node.js native addon developers, streamlining the distribution and loading of C/C++ bindings. It acts as both an `npm install` script and a runtime loader, prioritizing the use of precompiled binaries (prebuilds) over source compilation. Currently at stable version 5.2.2, its release cadence is typically tied to major Node.js ABI changes or significant updates in the native module tooling ecosystem. Its key differentiator is its seamless integration with `prebuildify` to provide robust cross-platform support, including different Node.js versions, Electron environments, and various architectures (e.g., `musl` for Alpine Linux, specific ARM versions). This significantly reduces installation friction for end-users, who often lack the necessary C++ toolchains. It intelligently detects runtime specifics like `libc` and `armv` to load the most appropriate prebuild, with options for users to override and force source compilation via `npm install --build-from-source`.
Common errors
-
Error: No prebuilt binaries found for ...
cause The package could not find precompiled binaries (prebuilds) for the current environment, and either source compilation was disabled or failed.fixEnsure you have generated prebuilds for your native module using a tool like `prebuildify` and that they are correctly packaged. Alternatively, run `npm install --build-from-source` to attempt compilation from source (requires `node-gyp` tools). -
gyp ERR! build error
cause Compilation from source failed. This usually indicates missing system dependencies for `node-gyp` (e.g., Python, C++ compiler) or issues with the `binding.gyp` file.fixInstall `node-gyp`'s prerequisites for your operating system (e.g., `npm install --global windows-build-tools` on Windows, build-essential on Linux). Review your `binding.gyp` for errors. -
Error: Module did not self-register.
cause A native addon was loaded but it failed to initialize correctly, often due to ABI incompatibility between the compiled binary and the current Node.js runtime, or a corrupt binary.fixEnsure your prebuilds are compatible with the Node.js ABI you are running (rebuild them if Node.js version changed). If compiling from source, ensure `node-gyp` is correctly configured. -
TypeError: binding.someFunction is not a function
cause The native addon loaded successfully, but the expected function or property is not exported by the native module, or the wrong binding was loaded.fixVerify that your C++ code correctly exports the function and that your `binding.gyp` file specifies the correct entry point. Ensure `loadNativeBinding(__dirname)` points to the correct native module.
Warnings
- breaking Prebuild naming conventions changed significantly in `node-gyp-build@4` and `prebuildify@3`. Native modules created with older `prebuildify` versions may not be recognized by newer `node-gyp-build` versions.
- gotcha Users can force `node-gyp-build` to compile from source during `npm install` by using the `--build-from-source` flag. This bypasses prebuilds and relies on `node-gyp`.
- gotcha When loading bindings, the path provided to the `loadBinding` function is crucial. Incorrect paths can lead to `Error: No prebuilt binaries found` or `Error: Module did not self-register`.
Install
-
npm install node-gyp-build-optional-packages -
yarn add node-gyp-build-optional-packages -
pnpm add node-gyp-build-optional-packages
Imports
- node-gyp-build CLI
"install": "node_modules/.bin/node-gyp-build"
"install": "node-gyp-build"
- loadBinding function
import loadBinding from 'node-gyp-build'; // or: const binding = require('node-gyp-build')();const loadBinding = require('node-gyp-build'); // then: const binding = loadBinding(__dirname);
Quickstart
// package.json (excerpt)
{
"name": "my-native-addon",
"version": "1.0.0",
"description": "Demonstrates node-gyp-build usage for native addons",
"main": "index.js",
"scripts": {
"install": "node-gyp-build", // This script runs during `npm install`
"test": "node index.js"
// For generating prebuilds, you'd typically have:
// "prebuild": "prebuildify -t napi -t armv -t libc"
},
"dependencies": {
"node-gyp-build": "^5.0.0" // Dependency for the loader and install script
},
"devDependencies": {
"node-gyp": "^10.0.0", // Required for compiling from source
"prebuildify": "^5.0.0" // Required for generating prebuilds
},
"gypfile": true // Indicates a binding.gyp file exists
}
// index.js (in the root of your native addon package)
const path = require('path');
const loadNativeBinding = require('node-gyp-build');
let binding;
try {
// `loadNativeBinding(__dirname)` will search for prebuilds in `__dirname/prebuilds/...`
// and then `__dirname/build/Release` if no prebuilds are found or forced.
binding = loadNativeBinding(__dirname);
console.log("Native addon loaded successfully!");
// Assuming your native addon exposes a simple function, e.g., 'addNumbers'
// This part requires an actual native addon to exist and be built.
if (typeof binding.addNumbers === 'function') {
const result = binding.addNumbers(5, 7);
console.log(`Result from native addon: 5 + 7 = ${result}`);
} else {
console.warn("Native addon function 'addNumbers' not found or is a placeholder.");
}
} catch (error) {
console.error("Failed to load native addon:", error.message);
console.warn("Ensure prebuilds are generated (e.g., with 'prebuildify') or build tools for 'node-gyp' are installed.");
console.warn("To force compilation from source, try: npm install --build-from-source");
}