UNPKG

14.6 kBMarkdownView Raw
1Node CMake
2==========
3
4A CMake-based build system for node.js native modules, for CMake >= v3.1.
5
6## Motivation
7
8The current build system for node native modules is
9[node-gyp](https://github.com/nodejs/node-gyp), which is based on the google
10project gyp. While this does provide a consistent build environment in
11line with the node build system, it has its own share of problems:
12
131. Cross platform library integration. As most node native modules are
14designed to expose some system-level interface to an existing library or
15framework, its very common to need to include other libraries and headers
16as dependencies of the module. Under gyp, these must be specified manually
17for each platform and architecture.
18
192. Integration with other build systems. Gyp is very much its own system
20and doesn't play nice with existing builds. Common practice is to manually
21convert the existing build to gyp, adding developer overhead and complexity.
22While gyp is designed to generate build files, outside visual studio its
23support is limited in the IDE space.
24
253. Turing completeness. Gyp is a strictly declarative build system. Any
26conditional building is done through supported declarative syntax. For
27complicated builds, this adds a lot of complexity and overhead for something
28as simple as handing build conditions outside of architecture and platform (
29Optional libraries, plugin based builds, nested conditions, etc.)
30
314. Depdencies. Gyp requires python to run, which is non-trival under windows,
32and is a constant source of frustration and configuration issues for those
33users.
34
35And probably the most important of all:
36
374. Future stability. Google has rapidly been migrating v8 to
38[gn](https://chromium.googlesource.com/chromium/src/tools/gn/), leaving the
39future of gyp and its supportability questionable. Its clear that if gyp is
40to remain, node will likely have to take ownership of the project, as all of
41google's resources have been diverted to improving gn. Its also been made
42clear that gn isn't really intended to be used outside of chromium and isn't
43being exposed. Throw [bazel](http://bazel.io/) in the mix, and even gn's
44future is unstable.
45
46node-cmake addresses these concerns by providing a node module build system
47built on top of [CMake](https://cmake.org). CMake, like gyp, is a meta-build
48system, generating build files for the actual build tools and
49IDEs on each platform. It does this by using its own platform agnostic and
50turing complete syntax for describing the build process in general terms,
51and converting that syntax to the correct build instructions.
52
53CMake has long been a counter-argument and
54[competitor](https://chromium.googlesource.com/external/gyp/+/master/docs/GypVsCMake.md)
55to gyp. While the arguments outlined there are well reasoned, there are many
56arguments as to why CMake is good build system for cross platform builds:
57
581. No dependencies. All that is required to use CMake is to install it, and
59whatever build environment is necessary for your platform (typically,
60visual studio / xcode / gcc).
61
622. Library search. CMake provides a cross-platform and standardized way to
63find and link against external libraries, both those built with CMake and
64those built with other systems. It provides sensible defaults and looks in
65standard, correct places on each platform, and can be tuned for specific
66edge cases. If a library builds with CMake, their builds can be combined
67to build dependencies along with the main code.
68
693. Stability and Integration. CMake has been in development far longer than
70gyp, and strives to maintain backwards compability across releases. Its an
71independent project that is used by a large number of big name projects
72and will be supported for a long time. It receives regular updates that
73improve and add functionality to make building more consistent, and to
74address changes to platform specific variations and complexity. It also
75nicely integrates with visual studio, xcode and especially IDEs like
76Jetbrain's CLion IDE and KDevelop, which use CMake as their native build
77environment.
78
79This project is similar in goals to
80[cmake-js](https://www.npmjs.com/package/cmake-js), with one major difference.
81Where that project has a node-centric focus, node-cmake relies strictly on
82CMake to download and configure node for building native extensions. This
83is done to support capabilites that are hard or impossible to integrate with
84`cmake-js`, namely toolchain support for cross-platform builds, and integration
85with other cmake projects and build environments (like catkin for ROS), which
86don't know about or potentially need a node interpreter to build.
87
88node-cmake is designed to provide full parity with `node-gyp` outside of
89the names and arguments of binaries; modules will still need to be updated to
90use it, but all of `node-gyp`'s capabilities are supported.
91
92## Usage
93
94To use this package, add the module `node-cmake` to your package.json
95as a development dependency:
96
97 npm install --save-dev node-cmake
98
99Then add a `CMakeLists.txt` file to the root of your module that contains
100the following at a minimum (\<REPLACE\> with your own definitions):
101
102```CMake
103cmake_minimum_required(VERSION 3.1)
104
105project(<NAME OF MODULE>)
106
107list(APPEND CMAKE_MODULE_PATH
108 ${CMAKE_CURRENT_SOURCE_DIR}/node_modules/node-cmake
109)
110
111find_package(NodeJS)
112
113add_nodejs_module(${PROJECT_NAME} <SOURCE AND HEADER FILES GO HERE>)
114```
115
116The `CMakeLists.txt` file is the main build script for CMake, and has the
117same purpose as the `binding.gyp` file in `node-gyp`.
118
119The `list(APPEND ...)` command tells CMake how to find the FindNodeJS.cmake
120script and must point to the directory containing this file. As written
121the variable `${CMAKE_CURRENT_SOURCE_DIR}` is a CMake variable referring to
122the directory that contains the `CMakeLists.txt` file being processed, or in
123this case, the root directory of your module. Since npm will install the
124`node-cmake` dependency underneath the `node_modules` directory, this tells
125CMake to look in the directory of this module for other scripts.
126
127The `find_package` command tells CMake that we want to find node as a
128dependency of our project. This command optionally takes arguments which
129are specified below. Typically, these arguments shouldn't be used unless
130necessary, to provide maximum flexibility for version and variant builds.
131
132Due to the complexity of creating a node module, and the strict requirements
133about the naming and placement of the shared library, node-cmake provides
134a CMake function for creating a node module, `add_nodejs_module`, similar to
135the `add_executable` and `add_library` commands native to CMake. This command
136ensures that the built shared library uses the correct build settings and
137flags on each platform. It creates a shared library `target`, specified by the
138first argument, that can be used identically to any other CMake `target`. In
139the example above, the target will be called '\<NAME OF PROJECT\>'
140
141CMake has extensive documentation online, which can be
142found [here](https://cmake.org/documentation) for various versions of CMake.
143node-cmake REQUIRES CMake >= 3.1, but any newer version is also supported.
144
145## Nan Support
146
147To simplify building of cross-version node modules,
148[Nan](https://github.com/nodejs/nan) is always included as a project
149dependency. In your module native sources, just
150
151```C++
152#include <nan.h>
153```
154
155At the top of any header/source file that requires this functionality.
156The version included with node-cmake will always be the newest available
157version of Nan. To use your own version, specify it as a dependency of your
158module:
159
160 npm install --save-dev nan
161
162This version will be used instead of the dependency specified by node-cmake.
163
164## Building
165
166node-cmake can be built by invoking CMake with its usual syntax, optimally
167using an out-of-source build folder. This involves creating a folder,
168navigating to that directory, and then running the `cmake` executable, with
169an arugument to the folder containing the root `CMakeLists.txt`:
170
171 mkdir build
172 cd build
173 cmake ..
174
175To simplify integration with npm, this module provides an executable script
176called 'ncmake' that automates this process. Adding the following section:
177
178```JSON
179"scripts": {
180 "install": "ncmake --build"
181}
182```
183
184to your `package.json` is typically all that is required to build. Additonal
185flags and options that can be passed to ncmake are outlined below. If you
186add additional non-optional arguments to this command, you MUST specify the
187build directory as the last argument (typically `out`).
188
189Once you've added this to your module, just run `npm install` to build.
190
191## Running
192
193node-cmake also provides a simple javascript module to simplify the
194finding and loading of the built native module in your own scripts. It exposes
195a single function similar to `require` with the same effects. Calling
196
197```JavaScript
198require('node-cmake')('<NAME OF MODULE>')
199```
200
201will return the native module to you if it can be found in the standard
202locations used by this module for building. This function handles loading
203the correct module for your platform and architecture, and searches both
204multiple build paths and mulitple configuration paths to find the
205native library. Additional options can be passed to this function to control
206these search parameters; see the `index.js` file in this directory for
207more information.
208
209## Variants
210
211node-cmake supports the concept of variants to allow building modules for
212alternate node environments, such as
213
214* [IO.js](https://iojs.org) - Now merged back into node (legacy support)
215* [NW.js](http://nwjs.io)
216* [Electron](http://electron.atom.io)
217
218These variants can be specified using their short names to `ncmake` using the
219`-s` flag. If a variant is specified, a version MUST also be specified using
220the `-v` flag.
221
222* Electron = electron
223* IOJS = iojs
224* NW.js = nw
225* Node = node
226
227Variants are stored in the `variants` folder and can be easily added or
228updated. If you are an owner of a variant and would like to request
229modifications or removal, or would like to add your own, please issue a
230pull request or feature request to that effect.
231
232## Versions
233
234Each variant maintains their own version range, which is handled properly
235by the variant. Versions are specified without the leading 'v' prefix, and
236must specify all three components:
237
238 [MAJOR].[MINOR].[PATCH]
239
240Two additional version 'shortcuts' are supported, which
241have logical effects:
242
243* latest - Use the latest version for a variant. Requires downloading an
244 additional file to determine this at runtime.
245* installed - Only applies to the default 'node' variant; uses the
246 version of the running node interpreter.
247
248## Example
249
250An example project is provided in the `example` folder. Follow the directions
251in its README.md to build it correctly.
252
253## NCMake Manual
254
255 ncmake [options] [build_directory]
256
257 Create a build directory for CMake, run the CMake configuration, and
258 optionally build the project.
259
260 This command can non-option arguments. If no non-option arguments are
261 specified, the default build directory is assumed (out). If any
262 non-option arguments are specified, the build directory relative to the
263 current working directory MUST be specified as the last argument.
264
265 Options (All case insensitive):
266
267 --config Set the build configuration. Can be one of 'MinSizeRel',
268 'RelWithDebInfo', 'Release' or 'Debug'; or a custom
269 CMake build type. See the CMake documentation for more
270 information.
271
272 Default: MinSizeRel
273
274 --build Build the project in addition to configuration
275
276 --clean-first Clean the project before building
277
278 --target Build the specified target. Used for building specific
279 modules, components and libraries. See the CMake
280 documentation for more information.
281
282 -C <STD> Set the C++ standard to <STD> level. Can be one of
283 (98, 11, 14).
284
285 Default: Unset, which uses the default level defined by CMake
286 or the version required by the variant/version being built.
287
288 -Z/-NZ Force the node sources required for building the module to
289 be / not be downloaded. Useful if you want to use downloaded
290 sources instead of the ones included on your platform. On
291 some platforms/variants, sources must always be downloaded.
292
293 -G <NAME> Set the CMake generator name. See the CMake documentation for
294 more information. Used primarily on windows to specify the
295 version of visual studio to build with (if not the default)
296
297 Default: Unset
298
299 -T <NAME> Set the toolset name for the generator. Used by some
300 generators to configure the compiler used to build the
301 sources.
302
303 Default: Unset
304
305 -S <VARIANT> Set the variant to build the module for. Used when
306 building the module for variants other than Node.js
307
308 Default: node
309
310 -V <VERSION> Set the version of the variant to build against. Must
311 be specified when the variant is specified. Can also
312 be the special versions 'installed' and 'latest' when
313 appropriate.
314
315 Default: installed
316
317 Advanced Options (All case insensitive):
318
319 -A <ARCH> Set the target architecture for the node module. Useful
320 when cross-compiling. Can be any valid output from
321 'process.arch'
322
323 Default: process.arch
324
325 -P <PLATFORM> Set the target platform for the node module. Useful when
326 cross-compiling. Can be any valid output from
327 'process.platform'
328
329 Default: process.platform
330
331## find_package Manual
332
333This is an advanced configuration and is primarily supported for exotic
334builds strictly in CMake. Generally, this functionality should not be used,
335relying on `ncmake` to build via npm.
336
337The NodeJS find_package command uses the VERSION and COMPONENTS arguments
338to support build-defined versions and variants. Specify the version
339immediately after `NodeJS` to hard-code a version requirement:
340
341```CMake
342find_package(NodeJS 0.12.7)
343```
344
345To specify a variant, use ONE of the variant keywords above in all caps:
346
347```CMake
348find_package(NodeJS 0.12.3 COMPONENTS NWJS)
349```
350
351The version must always be specified when using a component.
352
\No newline at end of file