New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

node-cmake

Package Overview
Dependencies
Maintainers
1
Versions
23
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

node-cmake - npm Package Compare versions

Comparing version 1.3.0 to 2.0.0

docs/Nan.md

11

example/CMakeLists.txt
cmake_minimum_required(VERSION 3.1)
project(addon)
project(example VERSION 1.0.0)
list(APPEND CMAKE_MODULE_PATH
${CMAKE_CURRENT_SOURCE_DIR}/node_modules/node-cmake
)
include(../NodeJS.cmake)
nodejs_init()
find_package(NodeJS)
add_nodejs_module(${PROJECT_NAME} src/hello.cc)
add_nodejs_module(${PROJECT_NAME} src/hello.cc)
'use strict';
module.exports = require('node-cmake')('addon');
module.exports = require('node-cmake')('example');

@@ -14,8 +14,8 @@ {

"scripts": {
"install": "ncmake --build"
"install": "ncmake rebuild"
},
"repository": {},
"devDependencies": {
"node-cmake": "^1.0.0"
"node-cmake": "^2.0.0"
}
}
Native Addon
============
The native addon, adjusted to use Nan for cross-variant compatibility,
from the node.js documentation site for
[Addons](https://nodejs.org/api/addons.html).
An example native addon, adjusted to use Nan for cross-variant compatibility,
from the Node.js documentation site for [Addons](https://nodejs.org/api/addons.html).
## Development Setup
This module requires node-cmake and is a part of node-cmake's distribution.
Now that node-cmake is published to npm, it is no longer necessary to
use `npm link` as the dependency can be directly downloaded.
This module requires node-cmake and is a part of node-cmake's distribution. A normal
project should copy NodeJS.cmake to their own project; this just refers to its
location in this project, one directory above.
However, this is the best way to test development changes to the project.
From the root of this project run:
npm link
Then, in this folder, run:
npm link node-cmake
## Building

@@ -38,2 +28,2 @@

If everything worked correctly, you should see it print "world".
If everything worked correctly, you should see it print "world".

@@ -5,57 +5,41 @@ 'use strict';

var _ = require('lodash');
var mothership = require('mothership');
function trueIdentity () { return true; }
function requireCMakeModule (name, conf) {
// Find the module root by finding the nearest package.json
// Use the path of the module that required this as the starting point
function requireNativeModule(name, debug) {
// Search relative to the file that included this one
var base = path.dirname(module.parent.filename);
var json = mothership.sync(base, trueIdentity);
var root;
if(json) {
root = path.dirname(json.path);
}
else {
throw Error('Unable to find module root');
}
// Suffixes to search for (in each mode)
// Both are used, debug just changes which is tried first
var search = {
debug: path.join('build', 'Debug', name + '.node'),
release: path.join('build', 'Release', name + '.node')
};
// Allow search path override
conf = _.merge({}, requireCMakeModule.build, conf || {});
// Allow single path definitions
if(!(conf.output instanceof Array)) conf.output = [conf.output];
if(!(conf.config instanceof Array)) conf.config = [conf.config];
// Search for the module in the specified locations
// Nest the searching so that things are tried in succession
var nativeModule;
if(!conf.output.some(function searchOutput (output) {
return conf.config.some(function searchConfig (config) {
nativeModule = path.join(
root, output, process.platform, process.arch, config, name + '.node'
);
var root = base;
var location;
var same = 0;
var found = false;
// Walk upward to the root of the current drive
while(same < 2 || found) {
try {
location = path.join(root, (debug) ? search.debug : search.release);
found = fs.statSync(location);
}
catch(e) {}
if(!found) {
try {
return fs.statSync(nativeModule);
location = path.join(root, (debug) ? search.release : search.debug);
found = fs.statSync(location);
}
catch(e) { return false; }
});
})) {
throw Error('Unable to find native module');
catch(e) {}
}
if(found) break;
root = path.dirname(root);
if(root == path.dirname(root)) same++;
}
// Require the native module and return the loaded content
return require(nativeModule);
if(!found) throw new Error('Unable to find native module');
return require(location);
}
requireCMakeModule.build = {
output: [
'out', 'build'
],
config: [
'MinSizeRel', 'Release', 'RelWithDebInfo', 'Debug'
]
};
module.exports = requireCMakeModule;
module.exports = requireNativeModule;

@@ -1,306 +0,255 @@

#!/usr/bin/env node
'use strict';
var fs = require('fs');
var path = require('path');
var spawn = require('child_process').spawn;
var _ = require('lodash');
var mothership = require('mothership');
var yargs = require('yargs');
var which = require('which');
var rimraf = require('rimraf');
var mkdirp = require('mkdirp');
// Make sure that the arguments are valid
function usage (code) {
console.log('Usage: ' + path.relative(process.cwd(), process.argv[1]) +
' [options] <build-directory>');
process.exit(code || 1);
}
if(process.argv.length < 3) usage();
var buildDir = 'build';
// Find the cmake executable
var cmake = which.sync('cmake');
// Main usage strings
var argparse = yargs
.usage('$0 [options] <command>');
// Define default arguments for the program
var args = {
args: {
generate: [],
build: []
},
generator: {},
flags: {},
arch: process.arch,
platform: process.platform,
config: 'MinSizeRel',
build: false,
clean: false
};
// Primary options
// Where appropriate, node-gyp argument names have been retained for
// compatibility. All unsupported options will be ignored by the parser.
argparse = argparse
.global(['debug', 'target', 'dist-url'])
.describe('debug', 'Build with debug symbols')
.describe('target', 'Version of Node.js to use')
.describe('dist-url', 'Set the download server for dependencies');
// Process command line arguments
var rarg = process.argv.slice(2, process.argv.length);
var next = null;
var variantSet = false;
var versionSet = false;
rarg.map(function parseArguments (arg) {
var argu = arg.toUpperCase();
if(next) {
_.set(args, next, arg);
next = null;
}
else if(_.startsWith(argu, '-D')) {
arg = arg.substr(2).split('=');
args.flags[arg[0]] = arg[1];
}
else if(argu === '--BUILD') {
args.build = true;
}
else if(argu === '--CLEAN-FIRST') {
args.clean = true;
}
else if(argu === '--CONFIG') {
next = 'config';
}
else if(argu === '--TARGET') {
next = 'target';
}
else if(argu === '-C') {
next = 'standard';
}
else if(argu === '-Z') {
args.download = true;
}
else if(argu === '-NZ') {
args.download = false;
}
else if(argu === '-G') {
next = 'generator.name';
}
else if(argu === '-T') {
next = 'generator.toolset';
}
else if(argu === '-A') {
next = 'arch';
}
else if(argu === '-P') {
next = 'platform';
}
else if(argu === '-S') {
next = 'variant';
variantSet = true;
}
else if(argu === '-V') {
next = 'version';
versionSet = true;
}
else {
args.args[args.build ? 'build' : 'generate'].push(arg);
}
});
// New options unique to CMake / ncmake
argparse = argparse
.global(['generator', 'name'])
.describe('name', 'The executable target (node/iojs)')
.describe('generator', 'The CMake generator to use');
if(variantSet && !versionSet) {
console.log('Variant set without version - aborting build');
process.exit(1);
}
// Commands (task to execute)
argparse = argparse
.command('help', 'Shows the help dialog')
.command('build', 'Builds the native addon')
.command('clean', 'Cleans the build')
.command('distclean', 'Removes all build files')
.command('configure', 'Runs CMake to generate the project configuration')
.command('rebuild', 'Runs clean, configure and build');
// If there are no extra arguments, use the default folder
if((args.args.build.length+args.args.generate.length) === 0) {
args.directory = 'out';
}
// Otherwise the last argument MUST be the build directory
else args.directory = process.argv[process.argv.length-1];
// Deprecated commands from node-gyp
var compat = 'Deprecated node-gyp command (no-op)';
argparse = argparse
.command('install', compat)
.command('list', compat)
.command('remove', compat);
// Load the configuration options from the package.json
function trueIdentity () { return true; }
var json = mothership.sync(process.cwd(), trueIdentity);
var base = (json.pack || {}).cmake || {};
// Mark advanced options
argparse = argparse
.group(['target', 'dist-url', 'name', 'generator'], 'Advanced:');
// Merge together arguments and configuration
var conf = _.merge({}, base.default || {}, base[process.platform] || {}, args);
// Aliases and settings for the options
argparse = argparse
.boolean('debug')
.alias('debug', 'd')
.alias('help', 'h')
.alias('generator', 'g');
// Convert version shortcut to installed version
if(conf.version && conf.version === 'installed') {
conf.version = process.version.substr(1);
}
// Set generator if not set
if(!conf.generator.name) {
// Use Xcode on OSX as the generator
if(conf.platform === 'darwin') {
conf.generator.name = 'Xcode';
// Use Ninja on platforms where it is installed as a default
// (since its significantly faster than make)
var ninja, generator = 'default';
if(process.platform === 'darwin' || process.platform == 'linux') {
try {
ninja = which.sync('ninja');
generator = 'Ninja';
}
// Use Ninja as the generator if its available as an executable
// (except on windows, where MSVC (the default) should be used)
else if(conf.platform !== 'win32') {
try {
which.sync('ninja');
conf.generator.name = 'Ninja';
conf.verbose = '-v';
}
catch(e) {}
}
catch(err) {}
}
// Build type should always match config
// Ignored by generators that use configuration
conf.flags.CMAKE_BUILD_TYPE = conf.config;
// Defaults for options that need them
argparse = argparse
.default('generator', generator)
.default('debug', false);
// Allow download overloading
// Bit of a complicated case, since false is a valid value
if(conf.flags.NodeJS_DOWNLOAD && _.isUndefined(conf.download)) {
conf.download = (
conf.flags.NodeJS_DOWNLOAD.toUpperCase() === 'ON' ||
conf.flags.NodeJS_DOWNLOAD.toUpperCase() === 'TRUE'
);
}
else if(!_.isUndefined(conf.download))
conf.flags.NodeJS_DOWNLOAD = (conf.download) ? 'On' : 'Off';
// Support a version string, and a help argument (in addition to
// the help command)
argparse = argparse.version();
argparse = argparse.help();
// Configure CXX standard to use
if(conf.flags.NodeJS_CXX_STANDARD && !conf.standard) {
conf.standard = conf.flags.NodeJS_CXX_STANDARD;
}
else if(conf.standard) conf.flags.NodeJS_CXX_STANDARD = conf.standard;
// Warning type - used to differentiate output in promise chain
function Warning(msg) { this.message = msg; }
// Configure version and variant
if(conf.flags.NodeJS_VARIANT && !conf.variant) {
conf.variant = conf.flags.NodeJS_VARIANT;
// Catch-all function for node-gyp deprecated commands
function deprecated() {
return new Promise(function (resolve, reject) {
var warn = new Warning('node-gyp deprecated command invoked. ' +
'This is not supported in node-cmake, consider updating your build');
warn.code = 0; // Exit cleanly (for tools that still use this command)
reject(warn);
});
}
else if(conf.variant) conf.flags.NodeJS_VARIANT = conf.variant;
if(conf.flags.NodeJS_VERSION && !conf.version) {
conf.version = conf.flags.NodeJS_VERSION;
}
else if(conf.version) conf.flags.NodeJS_VERSION = conf.version;
// Always specify node architecture properties
// Other means of resolving these are for external CMake invocation
conf.flags.NodeJS_PLATFORM = conf.platform;
conf.flags.NodeJS_ARCH = conf.arch;
// The list of accepted commands (mirror node-gyp's API)
var commands = {
help: function () {
return new Promise(function (resolve) {
argparse.showHelp();
resolve();
});
},
distclean: function (argv, cmake) {
return new Promise(function (resolve, reject) {
var distclean = spawn(cmake, ['-E', 'remove_directory', buildDir], {
stdio: 'inherit'
});
function handleError(code) {
if(code !== 0) { // An Error object will also not equal 0
var err = new Error('Unable to remove build directory');
err.code = 8;
return reject(err);
}
return resolve();
}
distclean.on('exit' , handleError);
distclean.on('error', handleError);
});
},
clean: function (argv, cmake) {
// Run CMake clean if the project has been "configured"
var args = ['--build', buildDir, '--target', 'clean'];
args.push('--config', (argv.debug) ? 'Debug' : 'Release');
return new Promise(function (resolve, reject) {
fs.exists(path.join(buildDir, 'CMakeCache.txt'), function (exists) {
if(exists) {
// Silently clean the project, do nothing on faiure (no-op)
var clean = spawn(cmake, args, {
stdio: 'ignore'
});
function handleError(code) { return resolve(); }
clean.on('exit', handleError);
clean.on('error', handleError);
}
else resolve();
});
});
},
configure: function (argv, cmake) {
var args = [];
args.push('-DCMAKE_BUILD_TYPE=' + ((argv.debug) ? 'Debug' : 'Release'));
if(argv.generator !== 'default') args.push('-G', argv.generator);
if(argv.target) args.push('-DNODEJS_VERSION=' + argv.target);
if(argv.distUrl) args.push('-DNODEJS_URL="' + argv.distUrl + '"');
if(argv.name) args.push('-DNODEJS_NAME="' + argv.name + '"');
args.push('..');
// Platform should match architecture on windows
if(process.platform === 'win32') {
if(conf.arch === 'ia32') conf.generator.arch = 'win32';
else conf.generator.arch = conf.arch;
}
return new Promise(function (resolve, reject) {
// Use CMake as a cross-platform mkdir to create the build directory
var mkdir = spawn(cmake, ['-E', 'make_directory', buildDir], {
stdio: 'inherit'
});
function handleError(code) {
if(code !== 0) {
var err = new Error('Unable to create build directory');
err.code = 3;
return reject(err);
}
return resolve();
}
mkdir.on('exit', handleError);
mkdir.on('error', handleError);
}).then(function () {
return new Promise(function (resolve, reject) {
// Run CMake to configure the project
var configure = spawn(cmake, args, {
cwd: path.resolve(buildDir),
stdio: 'inherit'
});
function handleError(code) {
if(code !== 0) {
var err = new Error('Unable to configure project');
err.code = 4;
return reject(err);
}
return resolve();
}
configure.on('exit', handleError);
configure.on('error', handleError);
});
});
},
build: function (argv, cmake) {
// Run CMake build to build the project (generator agnostic)
var args = ['--build', buildDir];
args.push('--config', (argv.debug) ? 'Debug' : 'Release');
return new Promise(function (resolve, reject) {
fs.exists(path.join(buildDir, 'CMakeCache.txt'), function (exists) {
if(exists) {
var build = spawn(cmake, args, {
stdio: 'inherit'
});
function handleError(code) {
if(code !== 0) {
var err = new Error('Build failed');
err.code = 7;
return reject(err);
}
return resolve();
}
build.on('exit', handleError);
build.on('error', handleError);
}
else {
var err = new Error('Project is not configured, ' +
'Run \'configure\' command first');
err.code = 6;
return reject(err);
}
});
});
},
rebuild: function (argv, cmake) {
// Per node-gyp, run clean, then configure, then build
return commands.clean(argv, cmake)
.then(function () {
return commands.configure(argv, cmake);
})
.then(function () {
return commands.build(argv, cmake);
});
},
install: deprecated,
list: deprecated,
remove: deprecated
};
// Resolve the build location, and the path from there to the working directory
var buildDir = path.resolve(path.join(
conf.directory, conf.platform, conf.arch
));
var buildRel = path.relative(buildDir, process.cwd());
// Load the configuration in the build directory
var build = {};
// Find the cmake binary on the user's path
var cmake;
try {
build = require(path.join(buildDir, 'build'));
cmake = which.sync('cmake');
}
catch(e) {}
// Convert CMake booleans to actual boolean
build.download = (build.download && (
build.download.toUpperCase() === 'ON' ||
build.download.toUpperCase() === 'TRUE'
));
// Build the arguments set for cmake
args = {
generate: [],
build: []
};
if(conf.generator.name) {
args.generate.push('-G', conf.generator.name);
catch(e) {
console.error('CMake binary could not be found. Please verify your PATH.');
process.exit(127);
}
if(conf.generator.toolset) {
args.generate.push('-T', conf.generator.toolset);
}
if(conf.generator.arch) {
args.generate.push('-A', conf.generator.arch);
}
_.forEach(conf.flags, function buildFlag (value, flag) {
args.generate.push('-D' + flag + '=' + value);
});
args.generate.push(buildRel);
args.build.push('--build', buildDir);
if(conf.target) {
args.build.push('--target', conf.target);
}
args.build.push('--config', conf.config);
if(conf.clean) {
args.build.push('--clean-first');
}
if(conf.verbose) {
args.build.push('--', conf.verbose);
}
// Workaround to build target architecture on Xcode, which doesnt respect
// the platform generation (yet)
if(conf.generator.name === 'Xcode') {
var osxarch;
if(conf.arch === 'x64') {
osxarch = 'x86_64';
}
else if(conf.arch === 'ia32') {
osxarch = 'i386';
}
else {
console.log('Invalid architecture ' + conf.arch);
process.exit(2);
}
args.build.push('--', '-arch', osxarch);
// This script takes any number of options and a single command
var argv = argparse.argv;
if(argv._.length < 1) {
console.error('A command must be specified.\n')
argparse.showHelp();
process.exit(1);
}
function buildModule() {
// Always create the build directory if necessary
mkdirp(buildDir, function makeBuildDirectory (err) {
if(err) throw err;
var setupProc;
var buildProc;
function afterSetup () {
buildProc = spawn(cmake, args.build, { stdio: 'inherit' });
buildProc.on('exit', function handleExitCodeDone (code) {
process.exit(code);
});
}
// If we're not building, or the build configuration does not match the
// current configuration, generate the project
if(!conf.build ||
conf.config !== build.build_type ||
conf.variant && conf.variant !== build.variant ||
conf.version && conf.version !== build.version ||
!_.isUndefined(conf.download) && conf.download !== build.download ||
conf.standard && conf.standard !== build.standard) {
setupProc = spawn(cmake, args.generate, {
cwd: buildDir, stdio: 'inherit'
});
setupProc.on('exit', function handleBadExitCode (code) {
if(code !== 0) process.exit(code);
});
}
// Invoke the cmake build
if(conf.build) {
if(setupProc) {
setupProc.on('exit', afterSetup);
}
else afterSetup();
}
});
}
// If the build changes in a way that is incompatible with the previous build
// then remove the build directory (if it exists) before building
// XXX: (conf.generator.arch && conf.generator.arch !== build.platform )
// Build now uses architecture specific folders
if(!build.build_type ||
(conf.generator.name && conf.generator.name !== build.generator) ||
(conf.generator.toolset && conf.generator.toolset !== build.toolset )) {
rimraf(buildDir, function afterRemove (err) {
if(err) throw err;
build = {};
buildModule();
});
}
else buildModule();
// Parse the first plain-argument as the command to execute
var cmd = argparse.argv._[0].toLowerCase();
var func = commands[cmd];
((func) ? func(argv, cmake) : Promise.reject(
new Error('Invalid command \'' + cmd + '\'')
))
// On success, exit cleanly
.then(function () {
process.exit(0);
})
// Otherwise, log the error and exit with a status code
.catch(function (err) {
if(err instanceof Warning) console.warn(err.message);
else console.error(err.message);
process.exit(err.code || 2);
});

@@ -1,2 +0,5 @@

Copyright (c) 2015, Colin Taylor
(The ISC License)
Copyright (c) 2015-2016, Colin Taylor <cjntaylor@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any

@@ -3,0 +6,0 @@ purpose with or without fee is hereby granted, provided that the above

{
"name": "node-cmake",
"author": "Colin Taylor <cjntaylor@gmail.com>",
"version": "1.3.0",
"version": "2.0.0",
"description": "A CMake-based build system for node.js native modules",

@@ -21,8 +21,5 @@ "keywords": [

"dependencies": {
"lodash": "^4.8.2",
"mkdirp": "^0.5.1",
"mothership": "^0.3.0",
"nan": "*",
"rimraf": "^2.4.3",
"which": "^1.1.2"
"which": "^1.2.10",
"yargs": "^5.0.0"
},

@@ -29,0 +26,0 @@ "devDependencies": {},

Node CMake
==========
A CMake-based build system for node.js native modules, for CMake >= v3.1.
A CMake-based build system for Node.js native modules, for CMake >= v3.1.
## Motivation
Newly rewritten for 2.0!
The current build system for node native modules is
[node-gyp](https://github.com/nodejs/node-gyp), which is based on the google
project gyp. While this does provide a consistent build environment in
line with the node build system, it has its own share of problems:
##### New Features
1. Cross platform library integration. As most node native modules are
designed to expose some system-level interface to an existing library or
framework, its very common to need to include other libraries and headers
as dependencies of the module. Under gyp, these must be specified manually
for each platform and architecture.
* Drop-in execution compatibility with the `node-gyp` binary
* Standardization with the `node-gyp` output and format. Should work better with tools that expect node-gyp's behaviour
* Simplified, portable and customizable configuration script
* Better recovery from failed downloads and builds
* Generalized support for Node.js variants. This supports additional variant types that are compatible with the Node.js release server structure (SHAs defined for all resources hosted on the download server, headers and .lib files located in standard locations).
2. Integration with other build systems. Gyp is very much its own system
and doesn't play nice with existing builds. Common practice is to manually
convert the existing build to gyp, adding developer overhead and complexity.
While gyp is designed to generate build files, outside visual studio its
support is limited in the IDE space.
##### Removed Features
3. Turing completeness. Gyp is a strictly declarative build system. Any
conditional building is done through supported declarative syntax. For
complicated builds, this adds a lot of complexity and overhead for something
as simple as handing build conditions outside of architecture and platform (
Optional libraries, plugin based builds, nested conditions, etc.)
* `find_package` support. The module loading techinque used in 1.0 was flawed for specific module structures and setup (deeply nested native dependencies). The new technique is to copy the now single configuration script into your project. This means that projects will not stay in sync with updates automatically. Be sure to copy the script again when updating `node-cmake` to a new version.
* `ncmake` command line arguments. `ncmake` now follows and extends the `node-gyp` command line interface. Please update your build files to use the new syntax (`ncmake --build` => `ncmake rebuild`). For more info, see the [manual](docs/NcmakeManual.md).
* Support for NW.js - The NW.js release server is not compliant to the Node.js release server structure. Workaround for the NW.js naming conventions have been included in the update, but the server SHA file does not include checksums for all resources, leaving no way to validate downloads. The SHASUMS256.txt file on the server needs to be updated to include these entries to be used with this tool.
4. Depdencies. Gyp requires python to run, which is non-trival under windows,
and is a constant source of frustration and configuration issues for those
users.
And probably the most important of all:
4. Future stability. Google has rapidly been migrating v8 to
[gn](https://chromium.googlesource.com/chromium/src/tools/gn/), leaving the
future of gyp and its supportability questionable. Its clear that if gyp is
to remain, node will likely have to take ownership of the project, as all of
google's resources have been diverted to improving gn. Its also been made
clear that gn isn't really intended to be used outside of chromium and isn't
being exposed. Throw [bazel](http://bazel.io/) in the mix, and even gn's
future is unstable.
node-cmake addresses these concerns by providing a node module build system
built on top of [CMake](https://cmake.org). CMake, like gyp, is a meta-build
system, generating build files for the actual build tools and
IDEs on each platform. It does this by using its own platform agnostic and
turing complete syntax for describing the build process in general terms,
and converting that syntax to the correct build instructions.
CMake has long been a counter-argument and
[competitor](https://gyp.gsrc.io/docs/GypVsCMake.md)
to gyp. While the arguments outlined there are well reasoned, there are many
arguments as to why CMake is good build system for cross platform builds:
1. No dependencies. All that is required to use CMake is to install it, and
whatever build environment is necessary for your platform (typically,
visual studio / xcode / gcc).
2. Library search. CMake provides a cross-platform and standardized way to
find and link against external libraries, both those built with CMake and
those built with other systems. It provides sensible defaults and looks in
standard, correct places on each platform, and can be tuned for specific
edge cases. If a library builds with CMake, their builds can be combined
to build dependencies along with the main code.
3. Stability and Integration. CMake has been in development far longer than
gyp, and strives to maintain backwards compability across releases. Its an
independent project that is used by a large number of big name projects
and will be supported for a long time. It receives regular updates that
improve and add functionality to make building more consistent, and to
address changes to platform specific variations and complexity. It also
nicely integrates with visual studio, xcode and especially IDEs like
Jetbrain's CLion IDE and KDevelop, which use CMake as their native build
environment.
This project is similar in goals to
[cmake-js](https://www.npmjs.com/package/cmake-js), with one major difference.
Where that project has a node-centric focus, node-cmake relies strictly on
CMake to download and configure node for building native extensions. This
is done to support capabilites that are hard or impossible to integrate with
`cmake-js`, namely toolchain support for cross-platform builds, and integration
with other cmake projects and build environments (like catkin for ROS), which
don't know about or potentially need a node interpreter to build.
node-cmake is designed to provide full parity with `node-gyp` outside of
the names and arguments of binaries; modules will still need to be updated to
use it, but all of `node-gyp`'s capabilities are supported.
## Usage
To use this package, add the module `node-cmake` to your package.json
as a development dependency:
To use this package, add the module `node-cmake` to your package.json as a development dependency:
npm install --save-dev node-cmake
Then add a `CMakeLists.txt` file to the root of your module that contains
the following at a minimum (\<REPLACE\> with your own definitions):
Copy the file `NodeJS.cmake` from this module into your project. Then add a `CMakeLists.txt` file to the root of your module that contains at least the following (\<REPLACE\> with your own definitions):

@@ -105,93 +33,35 @@ ```CMake

project(<NAME OF MODULE>)
project(<NAME OF MODULE> VERSION 1.0.0)
list(APPEND CMAKE_MODULE_PATH
${CMAKE_CURRENT_SOURCE_DIR}/node_modules/node-cmake
)
include(NodeJS.cmake)
nodejs_init()
find_package(NodeJS)
add_nodejs_module(${PROJECT_NAME} <SOURCE AND HEADER FILES GO HERE>)
```
The `CMakeLists.txt` file is the main build script for CMake, and has the
same purpose as the `binding.gyp` file in `node-gyp`.
This `CMakeLists.txt` file is the main build script for CMake, and replaces your existing `binding.gyp` file from `node-gyp`. It defines the build process for this project, including how to configure Node.js, and how to build your project components (modules, libraries, etc.)
The `list(APPEND ...)` command tells CMake how to find the FindNodeJS.cmake
script and must point to the directory containing this file. As written
the variable `${CMAKE_CURRENT_SOURCE_DIR}` is a CMake variable referring to
the directory that contains the `CMakeLists.txt` file being processed, or in
this case, the root directory of your module. Since npm will install the
`node-cmake` dependency underneath the `node_modules` directory, this tells
CMake to look in the directory of this module for other scripts.
The NodeJS.cmake file, included by relative path in this example, is a self-contained configuration tool for downloading the dependencies for building Node.js native modules, and configuring cmake to build them:
The `find_package` command tells CMake that we want to find node as a
dependency of our project. This command optionally takes arguments which
are specified below. Typically, these arguments shouldn't be used unless
necessary, to provide maximum flexibility for version and variant builds.
`nodejs_init` configures the version of Node.js to use for building. By default, this is the currently installed version of node on your platform. This function can take a number of advanced options (see [Documentation](#documentation)). This function must be called before any other function provided by the script.
Due to the complexity of creating a node module, and the strict requirements
about the naming and placement of the shared library, node-cmake provides
a CMake function for creating a node module, `add_nodejs_module`, similar to
the `add_executable` and `add_library` commands native to CMake. This command
ensures that the built shared library uses the correct build settings and
flags on each platform. It creates a shared library `target`, specified by the
first argument, that can be used identically to any other CMake `target`. In
the example above, the target will be called '\<NAME OF MODULE\>'
`add_nodejs_module` is a helper function for configuring CMake to build a node module based on the currently configured version of node. It takes the name of a `target` to create, along with a list of source files to build. All arguments after the `target` name are treated as sources.
CMake has extensive documentation online, which can be
found [here](https://cmake.org/documentation) for various versions of CMake.
node-cmake REQUIRES CMake >= 3.1, but any newer version is also supported.
CMake has extensive documentation online, which can be found [here](https://cmake.org/documentation).
## Nan Support
To simplify building of cross-version node modules,
[Nan](https://github.com/nodejs/nan) is always included as a project
dependency. In your module native sources, just
```C++
#include <nan.h>
```
At the top of any header/source file that requires this functionality.
The version included with node-cmake will always be the newest available
version of Nan. To use your own version, specify it as a dependency of your
module:
npm install --save-dev nan
This version will be used instead of the dependency specified by node-cmake.
## Building
node-cmake can be built by invoking CMake with its usual syntax, optimally
using an out-of-source build folder. This involves creating a folder,
navigating to that directory, and then running the `cmake` executable, with
an arugument to the folder containing the root `CMakeLists.txt`:
node-cmake has been updated to provide a drop-in replacement for node-gyp's interface. To build your module, use the command `ncmake rebuild`, which cleans, configures and builds the module.
mkdir build
cd build
cmake ..
This can be integrated into npm via its "scripts" directive:
To simplify integration with npm, this module provides an executable script
called 'ncmake' that automates this process. Adding the following section:
```JSON
"scripts": {
"install": "ncmake --build"
"install": "ncmake rebuild"
}
```
to your `package.json` is typically all that is required to build. Additonal
flags and options that can be passed to ncmake are outlined below. If you
add additional non-optional arguments to this command, you MUST specify the
build directory as the last argument (typically `out`).
Once you've added this to your module, just run `npm install` to build.
## Running
node-cmake also provides a simple javascript module to simplify the
finding and loading of the built native module in your own scripts. It exposes
a single function similar to `require` with the same effects. Calling
node-cmake also provides a simple javascript module to simplify the finding and loading of the built native module in your own scripts. It exposes a single function similar to `require` with the same effects. Calling

@@ -202,155 +72,24 @@ ```JavaScript

will return the native module to you if it can be found in the standard
locations used by this module for building. This function handles loading
the correct module for your platform and architecture, and searches both
multiple build paths and mulitple configuration paths to find the
native library. Additional options can be passed to this function to control
these search parameters; see the `index.js` file in this directory for
more information.
will load and return the named native module by searching in standard build locations. A second boolean can be passed to this function to configure loading of debug builds by default (if available).
## Variants
node-cmake supports the concept of variants to allow building modules for
alternate node environments, such as
* [IO.js](https://iojs.org) - Now merged back into node (legacy support)
* [NW.js](http://nwjs.io)
* [Electron](http://electron.atom.io)
These variants can be specified using their short names to `ncmake` using the
`-s` flag. If a variant is specified, a version MUST also be specified using
the `-v` flag.
* Electron = electron
* IOJS = iojs
* NW.js = nw
* Node = node
Variants are stored in the `variants` folder and can be easily added or
updated. If you are an owner of a variant and would like to request
modifications or removal, or would like to add your own, please issue a
pull request or feature request to that effect.
## Versions
Each variant maintains their own version range, which is handled properly
by the variant. Versions are specified without the leading 'v' prefix, and
must specify all three components:
[MAJOR].[MINOR].[PATCH]
Two additional version 'shortcuts' are supported, which
have logical effects:
* latest - Use the latest version for a variant. Requires downloading an
additional file to determine this at runtime.
* installed - Only applies to the default 'node' variant; uses the
version of the running node interpreter.
## Example
An example project is provided in the `example` folder. Follow the directions
in its README.md to build it correctly.
An example project is provided in the `example` folder. Follow the directions in its README.md to build it correctly.
## NCMake Manual
## Documentation
ncmake [options] [build_directory]
* [ncmake Manual](docs/NcmakeManual.md)
* [NodeJS.cmake Manual](docs/NodeJSCmakeManual.md)
* [Nan support](docs/Nan.md)
Create a build directory for CMake, run the CMake configuration, and
optionally build the project.
## Motivation
This command can non-option arguments. If no non-option arguments are
specified, the default build directory is assumed (out). If any
non-option arguments are specified, the build directory relative to the
current working directory MUST be specified as the last argument.
This tool was developed as a replacement for [node-gyp](https://github.com/nodejs/node-gyp), the current Node.js build system. Google has stopped working on its core, the gyp build tool, to focus on its replacement [gn](https://chromium.googlesource.com/chromium/src/tools/gn) and the future of gyp is uncertain.
Options (All case insensitive):
CMake also provides a number of benfits over gyp:
--config Set the build configuration. Can be one of 'MinSizeRel',
'RelWithDebInfo', 'Release' or 'Debug'; or a custom
CMake build type. See the CMake documentation for more
information.
Default: MinSizeRel
--build Build the project in addition to configuration
--clean-first Clean the project before building
--target Build the specified target. Used for building specific
modules, components and libraries. See the CMake
documentation for more information.
-C <STD> Set the C++ standard to <STD> level. Can be one of
(98, 11, 14).
Default: Unset, which uses the default level defined by CMake
or the version required by the variant/version being built.
-Z/-NZ Force the node sources required for building the module to
be / not be downloaded. Useful if you want to use downloaded
sources instead of the ones included on your platform. On
some platforms/variants, sources must always be downloaded.
-G <NAME> Set the CMake generator name. See the CMake documentation for
more information. Used primarily on windows to specify the
version of visual studio to build with (if not the default)
Default: Unset
-T <NAME> Set the toolset name for the generator. Used by some
generators to configure the compiler used to build the
sources.
Default: Unset
-S <VARIANT> Set the variant to build the module for. Used when
building the module for variants other than Node.js
Default: node
-V <VERSION> Set the version of the variant to build against. Must
be specified when the variant is specified. Can also
be the special versions 'installed' and 'latest' when
appropriate.
Default: installed
Advanced Options (All case insensitive):
-A <ARCH> Set the target architecture for the node module. Useful
when cross-compiling. Can be any valid output from
'process.arch'
Default: process.arch
-P <PLATFORM> Set the target platform for the node module. Useful when
cross-compiling. Can be any valid output from
'process.platform'
Default: process.platform
## find_package Manual
This is an advanced configuration and is primarily supported for exotic
builds strictly in CMake. Generally, this functionality should not be used,
relying on `ncmake` to build via npm.
The NodeJS find_package command uses the VERSION and COMPONENTS arguments
to support build-defined versions and variants.
Specify the version immediately after `NodeJS` to hard-code a version
requirement:
```CMake
find_package(NodeJS 0.12.7)
```
To specify a variant, use ONE of the variant keywords above in all caps:
```CMake
find_package(NodeJS 0.12.3 COMPONENTS NWJS)
```
The version must always be specified when using a component.
* Does not depend on python
* Extensive cross-platform utilities for finding and using other libraries and packages (the find_* family of commands, and the package system).
* Native IDE support (Clion, KDevleop), and good support for platform IDEs (Visual Studio, Xcode, Eclipse)
* Easy integration with other projects and build systems
* Cross-compilation via toolchains

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc