- Notifications
You must be signed in to change notification settings - Fork146
CMake.js - a Node.js native addon build tool
License
cmake-js/cmake-js
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
CMake.js is a Node.js native addon build tool which works (almost)exactly likenode-gyp, but instead ofgyp, it is based onCMake build system. It's compatible with the following runtimes:
- Node.js 14.15+ since CMake.js v7.0.0 (for older runtimes please use an earlier version of CMake.js). Newer versions can produce builds targeting older runtimes
- NW.js: all CMake.js based native modules are compatible with NW.js out-of-the-box, there is nonw-gyp like magic required
- Electron: out-of-the-box build support,no post build steps required
If you usenode-api
for your module instead ofnan
it should be able to run on all the runtimes above without needing to be built separately for each.
npm install cmake-js
Help:
cmake-js --help
Usage: cmake-js [<command>] [options]Commands: cmake-js install Install Node.js distribution files if needed cmake-js configure Configure CMake project cmake-js print-configure Print the configuration command cmake-js print-cmakejs-src Print the value of the CMAKE_JS_SRC variable cmake-js print-cmakejs-include Print the value of the CMAKE_JS_INC variable cmake-js print-cmakejs-lib Print the value of the CMAKE_JS_LIB variable cmake-js build Build the project (will configure first if required) cmake-js print-build Print the build command cmake-js clean Clean the project directory cmake-js print-clean Print the clean command cmake-js reconfigure Clean the project directory then configure the project cmake-js rebuild Clean the project directory then build the project cmake-js compile Build the project, and if build fails, try a full rebuildOptions: --version Show version number [boolean] -h, --help Show help [boolean] -l, --log-level set log level (silly, verbose, info, http, warn, error), default is info [string] -d, --directory specify CMake project's directory (where CMakeLists.txt located) [string] -D, --debug build debug configuration [boolean] -B, --config specify build configuration (Debug, RelWithDebInfo, Release), will ignore '--debug' if specified [string] -c, --cmake-path path of CMake executable [string] -m, --prefer-make use Unix Makefiles even if Ninja is available (Posix) [boolean] -x, --prefer-xcode use Xcode instead of Unix Makefiles [boolean] -g, --prefer-gnu use GNU compiler instead of default CMake compiler, if available (Posix) [boolean] -G, --generator use specified generator [string] -t, --toolset use specified toolset [string] -A, --platform use specified platform name [string] -T, --target only build the specified target [string] -C, --prefer-clang use Clang compiler instead of default CMake compiler, if available (Posix) [boolean] --cc use the specified C compiler [string] --cxx use the specified C++ compiler [string] -r, --runtime the runtime to use [string] -v, --runtime-version the runtime version to use [string] -a, --arch the architecture to build in [string] -p, --parallel the number of threads cmake can use [number] --CD Custom argument passed to CMake in format: -D<your-arg-here> [string] -i, --silent Prevents CMake.js to print to the stdio [boolean] -O, --out Specify the output directory to compile to, default is projectRoot/build [string]
Requirements:
- CMake
- A proper C/C++ compiler toolchain of the given platform
- Windows:
- Visual C++ Build Tools. If you installed nodejs with the installer, you can install these when prompted.
- An alternate way is to install theChocolatey package manager, and run
choco install visualstudio2017-workload-vctools
in an Administrator Powershell - If you have multiple versions installed, you can select a specific version with
npm config set msvs_version 2017
(Note: this will also affectnode-gyp
)
- Unix/Posix:
- Clang or GCC
- Ninja or Make (Ninja will be picked if both present)
- Windows:
It is advised to use Node-API for new projects instead of NAN. It provides ABI stability making usage simpler and reducing maintainance.
- Install cmake-js for your module
npm install --save cmake-js
- Put a CMakeLists.txt file into your module root with this minimal required content:
cmake_minimum_required(VERSION3.15...3.31)project(your-addon-name-here)add_compile_definitions(-DNAPI_VERSION=4)file(GLOBSOURCE_FILES"your-source files-location-here")add_library(${PROJECT_NAME}SHARED${SOURCE_FILES}${CMAKE_JS_SRC})set_target_properties(${PROJECT_NAME}PROPERTIESPREFIX""SUFFIX".node")target_include_directories(${PROJECT_NAME}PRIVATE${CMAKE_JS_INC})target_link_libraries(${PROJECT_NAME}PRIVATE${CMAKE_JS_LIB})target_compile_features(${PROJECT_NAME}PRIVATEcxx_std_17)if(MSVCANDCMAKE_JS_NODELIB_DEFANDCMAKE_JS_NODELIB_TARGET)# Generate node.libexecute_process(COMMAND${CMAKE_AR}/def:${CMAKE_JS_NODELIB_DEF}/out:${CMAKE_JS_NODELIB_TARGET}${CMAKE_STATIC_LINKER_FLAGS})endif()
- Add the following into your package.json scripts section:
"scripts": {"install":"cmake-js compile" }
- Add the following into your package.json, using the same NAPI_VERSION value you provided to cmake
"binary": {"napi_versions": [7] },
With cmake-js installed as a depdendency or devDependency of your module, you can access run commands directly with:
npx cmake-js --help# ORyarn cmake-js --help
Please refer to the--help
for the lists of available commands (they are like commands innode-gyp
).
You can override the project default runtimes via--runtime
and--runtime-version
, such as:--runtime=electron --runtime-version=0.26.0
. See below for more info on runtimes.
CMAKE_JS_VERSION
variable will reflect the actual CMake.js version. So CMake.js based builds could be detected, eg.:
if (CMAKE_JS_VERSION)add_subdirectory(node_addon)else()add_subdirectory(other_subproject)endif()
You can set npm configuration options for CMake.js.
For all users (global):
npm config set cmake_<key> <value> --global
For current user:
npm config set cmake_<key> <value>
CMake.js will set a variable named"<key>"
to<value>
(by using-D<key>="<value>"
option). User settings willoverwrite globals.
UPDATE:
You can set CMake.js command line arguments with npm config using the following pattern:
npm config set cmake_js_G "Visual Studio 56 Win128"
Which sets the CMake generator, basically defaults to:
cmake-js -G "Visual Studio 56 Win128"
Enter at command prompt:
npm config set cmake_Foo="bar"
Then write to your CMakeLists.txt the following:
message (STATUS${Foo})
This will print during configure:
--- bar
You can add custom CMake options by beginning option name withCD
.
In command prompt:
cmake-js compile --CDFOO="bar"
Then in your CMakeLists.txt:
message (STATUS${FOO})
This will print during configure:
--- bar
It is important to understand that this setting is to be configured in theapplication's root package.json file. If you're creating a native module targeting nw.js for example, thendo not specify anything in your module's package.json. It's the actual application's decision to specify its runtime, your module's just compatible anything that was mentioned in theAbout chapter. Actually definingcmake-js
key in your module's package.json file may lead to an error. Why? If you set it up to use nw.js 0.12.1 for example, then when it gets compiled during development time (to run its unit tests for example) it's gonna be compiled against io.js 1.2 runtime. But if you're having io.js 34.0.1 at the command line then, which is binary incompatible with 1.2, then your unit tests will fail for sure. So it is advised to not use cmake-js target settings in your module's package.json, because that way CMake.js will use that you have, and your tests will pass.
If any of theruntime
,runtimeVersion
, orarch
configuration parameters is not explicitly configured, sensible defaults will be auto-detected based on the JavaScript environment where CMake.js runs within.
You can configure runtimes for compiling target for all depending CMake.js modules in an application. Define acmake-js
key in the application's rootpackage.json
file, eg.:
{"name":"ta-taram-taram","description":"pa-param-pam-pam","version":"1.0.0","main":"app.js","cmake-js": {"runtime":"node","runtimeVersion":"0.12.0","arch":"ia32"}}
Available settings:
- runtime: application's target runtime, possible values are:
node
: Node.jsnw
: nw.jselectron
: Electron
- runtimeVersion: version of the application's target runtime, for example:
0.12.1
- arch: architecture of application's target runtime (eg:
x64
,ia32
,arm64
,arm
).Notice: on non-Windows systems the C++ toolset's architecture's gonna be used despite this setting. If you don't specify this on Windows, then architecture of the main node runtime is gonna be used, so you have to choose a matching nw.js runtime.
ABI-stable Node.js API(Node-API),which was previously known as N-API, supplies a set of CAPIs that allow to compilation and loading of native modules bydifferent versions of Node.js that support Node-API which includesall versions of Node.js v10.x and later.
To compile a native module that uses only theplainC
Node-API calls,follow the directions for plainnode
native modules.
You must also add the following lines to your CMakeLists.txt, to allow for building on windows
if(MSVC AND CMAKE_JS_NODELIB_DEF AND CMAKE_JS_NODELIB_TARGET) # Generate node.lib execute_process(COMMAND ${CMAKE_AR} /def:${CMAKE_JS_NODELIB_DEF} /out:${CMAKE_JS_NODELIB_TARGET} ${CMAKE_STATIC_LINKER_FLAGS})endif()
To compile a native module that uses the header-only C++ wrapperclasses provided bynode-addon-api
,you need to make your package depend on it with:
npm install --save node-addon-api
cmake-js will then add it to the include search path automatically
You should add the following to your package.json, with the correct version number, so that cmake-js knows the module is node-api and that it can skip downloading the nodejs headers
"binary": {"napi_versions": [7] },
On Windows, thewin_delay_load_hook
is required to be embedded in the module or it will fail to load in the render process.cmake-js will add the hook if the CMakeLists.txt contains the library${CMAKE_JS_SRC}
.
Without the hook, the module can only be called from the render process using the Electronremote module.
The actual node runtime parameters are detectable in CMakeLists.txt files, the following variables are set:
- NODE_RUNTIME:
"node"
,"nw"
,"electron"
- NODE_RUNTIMEVERSION: for example:
"0.12.1"
- NODE_ARCH:
"x64"
,"ia32"
,"arm64"
,"arm"
To make compatible your NW.js application with any NAN CMake.js based modules, write the following to your application's package.json file (this is not neccessary for node-api modules):
{"cmake-js": {"runtime":"nw","runtimeVersion":"nw.js-version-here","arch":"whatever-setting-is-appropriate-for-your-application's-windows-build"}}
That's it. There is nothing else to do either on the application's or on the module's side, CMake.js modules are compatible with NW.js out-of-the-box.
Heroku uses the concept of abuildpack to definehow an application should be prepared to run in adyno.The typical buildpack for note-based applications,heroku/nodejs,provides an environment capable of runningnode-gyp,but notCMake.
The least "painful" way of addressing this is to use heroku's multipack facility:
Set the applications' buildpack tohttps://github.com/heroku/heroku-buildpack-multi.git
In the root directory of the application,create a file called
.buildpacks
with these two lines:https://github.com/brave/heroku-cmake-buildpack.git https://github.com/heroku/heroku-buildpack-nodejs.git
Deploy the application to have the changes take effect
Theheroku-buildpack-multi
will run each buildpack in order allowing the node application to reference CMake in the Herokubuild environment.
Because you are using CMake, there are many ways to load libraries in your CMakeLists.txt.
Various places on the internet and in the CMake docs will suggest various approaches you can take. Common ones are:
- conan (This may not work properly currently, we hope to improve support in a future release)
- vcpkg (This may not work properly currently, we hope to improve support in a future release)
- hunter
- CMake ExternalProject
- If on linux, using system libraries from the system package-manager
- Importing as a git submodule
We aim to be agnostic about how to use CMake, so it should be possible to use whatever approach you desire.
- @julusian/jpeg-turbo - A Node-API wrapping around libjpeg-turbo. cmake-js was a good fit here, as libjpeg-turbo provides cmake files that can be used, and would be hard to replicate correctly in node-gyp
- node-datachannel - Easy to use WebRTC data channels and media transport
- aws-iot-device-sdk-v2 AWS IoT Device SDK for JavaScript v2
Open a PR to add your own project here.
Viewchangelog.md
https://github.com/cmake-js/cmake-js/graphs/contributors
Ty all!
About
CMake.js - a Node.js native addon build tool
Topics
Resources
License
Uh oh!
There was an error while loading.Please reload this page.