-
Notifications
You must be signed in to change notification settings - Fork 143
TUTORIAL 01 Creating a native module by using CMake.js and NAN
Let's take a classical example of a native Node.js addon and create a CMake.js based module from it. Every native addon developer knows NAN. It's an excellent C++ template library that provides an API that can be used to make native modules and is consistent across Node.js and io.js versions. So if you write your module by using NAN interfaces, it should compile with all supported versions even there are breaking API changes across them (and there are).
In repository of NAN module there is an example code of a native C++ addon that calculates PI asynchronously. It uses node-gyp of course of its build system, but let's take that C++ source and the test js code, and create a CMake.js based module from it.
Fist you need an empty directory of course. Put a package.json in it, give the module a nice name.
{
"name": "cmake-js-tut-01-module",
"version": "1.0.0",
"description": "Native module calculating estimate of PI"
}
Install NAN and CMake.js:
npm install nan --save
npm install cmake-js --save
Note: Because CMake.js isn't bundled to Node.js or io.js distributions like node-gyp,
global cmake-js
command won't be available when consumer application/module installs your cmake-js-tut-01-module
.
So you have to add it as a dependency to make sure it will be available for compiling during installation.
Make an src directory and put there *.cc and *.h files from the NAN addon example module. If you manage to compile those as a shared library with .node extension, then you're done, it will be requireable from JavaScript side.
CMakeLists.txt
file is the CMake project-file (like makefile or a VisualStudio sln). You have to put it at least into your project's root folder,
but there can be other CMakeLists.txt
files in other project folders describing contents of them.
So how should this CMakeLists.txt file to look to get your addon compiled? Since CMake.js do it's compilation process with only invoking CMake commands,
you have the full CMake potential to develop your native addon module, anything is supported without restrictions.
But because of this, you should describe in your project root's CMakeLists.txt
file, that you are building a node addon.
So the minimal CMakeLists.txt
file that capable of build node addons is look like this:
cmake_minimum_required(VERSION 2.8)
# Name of the project (will be the name of the plugin)
project (addon)
# Essential include files to build a node addon,
# you should add this line in every CMake.js based project.
include_directories(${CMAKE_JS_INC})
# Declare the source files location
file(GLOB SOURCE_FILES "src/*.cc" "src/*.h")
# This line will tell CMake that we're building a shared library
# from the above source files
# named after the project's name
add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES})
# This line will give our library file a .node extension without any "lib" prefix
set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "" SUFFIX ".node")
# Essential library files to link to a node addon,
# you should add this line in every CMake.js based project.
target_link_libraries(${PROJECT_NAME} ${CMAKE_JS_LIB})
That's it. In you basic modules you have to only modify the line that tells the location of the source files if needed. Include paths to node, v8 and NAN headers, as well as link library file location in Windows will be handled by CMake.js, you ain't gonna have to specify them.
To test if it's compiles intall cmake-js as a global command:
npm i -g cmake-js
Then invoke build or rebuild command (they will invoke configure if it's needed).
cmake-js build
You can use the --debug
switch for compiling debug mode. Please see the --help
for more details of using cmake-js binary.
The generated project files will got to a build
directory exactly like when compiling with node-gyp
.
The actual plugin file (projectnamehere.node) will goes to build/Release
directory when compiling a release build,
and goes to build/Debug
directory when compiling a debug build (with --debug
switch)
The last thing that you have to set up is that cmake-js rebuild
command have to be invoked once your module gets installed,
into the consumer application or module node_modules
folder.
It is doable by configuring an install script in the package.json
file.
Since cmake-js
might be not available as a global command for the consumer of our module,
you have to specify the executable that is reside in the local modules folder.
{
"name": "cmake-js-tut-01-module",
"version": "1.0.0",
"description": "Native module calculating estimate of PI",
"dependencies": {
"cmake-js": "*",
"nan": "^1.7.0"
},
"scripts": {
"install": "node ./node_modules/.bin/cmake-js rebuild"
}
}
If your module gets installed, or you invoke npm install
or cmake-js build
command in your module directory,
the plugin compiles as a binary file with a .node extension to to build/Release
or to build/Debug
directory.
You can require it directly like:
// projectnamehere.node plugin file without the extension:
var myModule = require("./build/Release/projectnamehere");
But it is advised to use the bindings module for this purpose. So for the NAN example put an index.js into your module's root folder with this line:
module.exports = require("bindings")("addon");
So if a consumer installs your module, and requires it with:
var addon = require("cmake-js-tut-01-module");
he or she will have access the interface of your native module in addon variable.
It's done, you have made your first CMake.js based module. There is the code:
git clone https://github.com/unbornchikken/cmake-js-tut-01-module.git
You can install it for your application even it's not on the npm with:
npm install git+https://github.com/unbornchikken/cmake-js-tut-01-module.git
I've already created an example application that uses our NAN example module, you can find it there:
git clone https://github.com/unbornchikken/cmake-js-tut-01-test.git
To install and run write:
npm install
node app