diff --git a/Makefile b/Makefile index 9dd9b198491eb3..a872303fb7f863 100644 --- a/Makefile +++ b/Makefile @@ -357,7 +357,8 @@ ADDONS_BINDING_SOURCES := \ ADDONS_PREREQS := config.gypi \ deps/npm/node_modules/node-gyp/package.json tools/build-addons.js \ deps/uv/include/*.h deps/v8/include/*.h \ - src/node.h src/node_buffer.h src/node_object_wrap.h src/node_version.h + src/node.h src/node_buffer.h src/node_object_wrap.h src/node_version.h \ + src/node_addon_macros.h src/node_abi_versions.h define run_build_addons env npm_config_loglevel=$(LOGLEVEL) npm_config_nodedir="$$PWD" \ diff --git a/doc/api/addons.md b/doc/api/addons.md index 4941d3de9add8f..1929c9abade81e 100644 --- a/doc/api/addons.md +++ b/doc/api/addons.md @@ -323,8 +323,8 @@ try { ### Linking to Node.js' own dependencies Node.js uses a number of statically linked libraries such as V8, libuv and -OpenSSL. All Addons are required to link to V8 and may link to any of the -other dependencies as well. Typically, this is as simple as including +OpenSSL. All addons are required to link to either V8 or N-API and may link to +any of the other dependencies as well. Typically, this is as simple as including the appropriate `#include <...>` statements (e.g. `#include `) and `node-gyp` will locate the appropriate headers automatically. However, there are a few caveats to be aware of: @@ -339,6 +339,78 @@ only the symbols exported by Node.js will be available. source image. Using this option, the Addon will have access to the full set of dependencies. +Node.js is available from a number of sources besides the [official +distribution][]. Since the various versions of Node.js are configured +differently at build time, the resulting runtime ABI of the statically linked +libraries may be different. For example, version 10 of Node.js as shipped by +Debian GNU/Linux may have a different ABI than version 10 of Node.js as +available from the official distribution. + +The Node.js ABI consists of various different, independent parts, such as V8, +OpenSSL, libuv, and others. Native addons may use some, all, or even just one of +these independent parts of the Node.js ABI. Thus, when Node.js is tasked with +loading an addon, at which time it needs to determine whether the addon is ABI- +compatible, it needs ABI information provided by the addon. The addon normally +provides this information as a single number (`NODE_MODULE_VERSION`) which is +stored inside the addon and which is compared against the value present in the +running Node.js process at addon load time. + +Since `NODE_MODULE_VERSION` reflects only the Node.js major version against +which the addon was built, it may match the running Node.js process even though +some of the independent parts of the ABI are mismatched. To address this problem +the addon may optionally declare which portions of the Node.js ABI it uses by +invoking the `NODE_MODULE_DECLARE_ABI` macro. Any portions of the ABI included +as a parameter to the macro will be checked during addon load in addition to +`NODE_MODULE_VERSION` in order to ensure that all ABIs declared by the addon +have the version as requested by the addon. Node.js assumes that ABIs not +included in the invocation of the `NODE_MODULE_DECLARE_ABI` macro are not used +by the addon. + +If there is a mismatch between any ABI version number declared by the addon and +the corresponding ABI version number as present in the Node.js process +attempting to load the addon, Node.js will refuse to load the addon and throw an +exception in which it indicates which ABIs were mismatched. + +The `NODE_MODULE_DECLARE_ABI` macro may be invoked as follows: +```C++ +NODE_MODULE_DECLARE_ABI( + NODE_MODULE_ABI_VENDOR_VERSION, + NODE_MODULE_ABI_ENGINE_VERSION, + NODE_MODULE_ABI_OPENSSL_VERSION) +``` +Note that there must be no semicolon at the end of the declaration. + +One or more of the following parameters may be passed to +`NODE_MODULE_DECLARE_ABI`: +* `NODE_MODULE_ABI_VERSION_TERMINATOR` - this is a sentinel indicating the end +of the list of ABI declarations. It need not normally be used by addons. + +* `NODE_MODULE_ABI_VENDOR_VERSION` - this declaration ties the addon to a +specific vendor's version of Node.js. For example, if the addon is built against +the official disitrbution of Node.js, it will not load on a version of Node.js +provided by the Debian GNU/Linux project nor will it load on a version of +Electron. + +* `NODE_MODULE_ABI_ENGINE_VERSION` - this declaration ties the addon to a +specific JavaScript engine version. It will fail to load on a version of Node.js +that provides a different JavaScript engine version. + +* `NODE_MODULE_ABI_OPENSSL_VERSION` - this declaration ties the addon to a +specific version of the OpenSSL library. It will not load on a version of +Node.js that provides a different version of the OpenSSL library. + +* `NODE_MODULE_ABI_LIBUV_VERSION` - this declaration ties the addon to a +specific version of the libuv library. It will fail to load on a version of +Node.js that provides a different version of libuv. + +* `NODE_MODULE_ABI_ICU_VERSION` - this declaration ties the addon to a +specific version of the ICU library. It will fail to load on a version of +Node.js that provides a different version of the ICU library. + +* `NODE_MODULE_ABI_CARES_VERSION` - this declaration ties the addon to a +specific version of the c-ares library. It will fail to load on a version of +Node.js that provides a different version of the c-ares library. + ### Loading Addons using require() The filename extension of the compiled Addon binary is `.node` (as opposed @@ -1377,5 +1449,6 @@ require('./build/Release/addon'); [installation instructions]: https://github.com/nodejs/node-gyp#installation [libuv]: https://github.com/libuv/libuv [node-gyp]: https://github.com/nodejs/node-gyp +[official distribution]: https://nodejs.org/ [require]: modules.html#modules_require_id [v8-docs]: https://v8docs.nodesource.com/ diff --git a/src/node.h b/src/node.h index fbf9128be42429..9d7db5c53190df 100644 --- a/src/node.h +++ b/src/node.h @@ -63,6 +63,7 @@ #include "v8.h" // NOLINT(build/include_order) #include "v8-platform.h" // NOLINT(build/include_order) #include "node_version.h" // NODE_MODULE_VERSION +#include "node_addon_macros.h" #define NODE_MAKE_VERSION(major, minor, patch) \ ((major) * 0x1000 + (minor) * 0x100 + (patch)) @@ -459,106 +460,6 @@ struct node_module { extern "C" NODE_EXTERN void node_module_register(void* mod); -#ifdef _WIN32 -# define NODE_MODULE_EXPORT __declspec(dllexport) -#else -# define NODE_MODULE_EXPORT __attribute__((visibility("default"))) -#endif - -#ifdef NODE_SHARED_MODE -# define NODE_CTOR_PREFIX -#else -# define NODE_CTOR_PREFIX static -#endif - -#if defined(_MSC_VER) -#pragma section(".CRT$XCU", read) -#define NODE_C_CTOR(fn) \ - NODE_CTOR_PREFIX void __cdecl fn(void); \ - __declspec(dllexport, allocate(".CRT$XCU")) \ - void (__cdecl*fn ## _)(void) = fn; \ - NODE_CTOR_PREFIX void __cdecl fn(void) -#else -#define NODE_C_CTOR(fn) \ - NODE_CTOR_PREFIX void fn(void) __attribute__((constructor)); \ - NODE_CTOR_PREFIX void fn(void) -#endif - -#define NODE_MODULE_X(modname, regfunc, priv, flags) \ - extern "C" { \ - static node::node_module _module = \ - { \ - NODE_MODULE_VERSION, \ - flags, \ - NULL, /* NOLINT (readability/null_usage) */ \ - __FILE__, \ - (node::addon_register_func) (regfunc), \ - NULL, /* NOLINT (readability/null_usage) */ \ - NODE_STRINGIFY(modname), \ - priv, \ - NULL /* NOLINT (readability/null_usage) */ \ - }; \ - NODE_C_CTOR(_register_ ## modname) { \ - node_module_register(&_module); \ - } \ - } - -#define NODE_MODULE_CONTEXT_AWARE_X(modname, regfunc, priv, flags) \ - extern "C" { \ - static node::node_module _module = \ - { \ - NODE_MODULE_VERSION, \ - flags, \ - NULL, /* NOLINT (readability/null_usage) */ \ - __FILE__, \ - NULL, /* NOLINT (readability/null_usage) */ \ - (node::addon_context_register_func) (regfunc), \ - NODE_STRINGIFY(modname), \ - priv, \ - NULL /* NOLINT (readability/null_usage) */ \ - }; \ - NODE_C_CTOR(_register_ ## modname) { \ - node_module_register(&_module); \ - } \ - } - -// Usage: `NODE_MODULE(NODE_GYP_MODULE_NAME, InitializerFunction)` -// If no NODE_MODULE is declared, Node.js looks for the well-known -// symbol `node_register_module_v${NODE_MODULE_VERSION}`. -#define NODE_MODULE(modname, regfunc) \ - NODE_MODULE_X(modname, regfunc, NULL, 0) // NOLINT (readability/null_usage) - -#define NODE_MODULE_CONTEXT_AWARE(modname, regfunc) \ - /* NOLINTNEXTLINE (readability/null_usage) */ \ - NODE_MODULE_CONTEXT_AWARE_X(modname, regfunc, NULL, 0) - -/* - * For backward compatibility in add-on modules. - */ -#define NODE_MODULE_DECL /* nothing */ - -#define NODE_MODULE_INITIALIZER_BASE node_register_module_v - -#define NODE_MODULE_INITIALIZER_X(base, version) \ - NODE_MODULE_INITIALIZER_X_HELPER(base, version) - -#define NODE_MODULE_INITIALIZER_X_HELPER(base, version) base##version - -#define NODE_MODULE_INITIALIZER \ - NODE_MODULE_INITIALIZER_X(NODE_MODULE_INITIALIZER_BASE, \ - NODE_MODULE_VERSION) - -#define NODE_MODULE_INIT() \ - extern "C" NODE_MODULE_EXPORT void \ - NODE_MODULE_INITIALIZER(v8::Local exports, \ - v8::Local module, \ - v8::Local context); \ - NODE_MODULE_CONTEXT_AWARE(NODE_GYP_MODULE_NAME, \ - NODE_MODULE_INITIALIZER) \ - void NODE_MODULE_INITIALIZER(v8::Local exports, \ - v8::Local module, \ - v8::Local context) - /* Called after the event loop exits but before the VM is disposed. * Callbacks are run in reverse order of registration, i.e. newest first. */ diff --git a/src/node_abi_versions.h b/src/node_abi_versions.h new file mode 100644 index 00000000000000..9c6ae5c0b1747f --- /dev/null +++ b/src/node_abi_versions.h @@ -0,0 +1,26 @@ +#ifndef SRC_NODE_ABI_VERSIONS_H_ +#define SRC_NODE_ABI_VERSIONS_H_ + +typedef enum { + node_abi_version_terminator, + node_abi_vendor_version, + node_abi_engine_version, + node_abi_openssl_version, + node_abi_libuv_version, + node_abi_icu_version, + node_abi_cares_version +} node_abi_version_item; + +typedef struct { + node_abi_version_item item; + int version; +} node_abi_version_entry; + +#define NODE_ABI_VENDOR_VERSION 1 +#define NODE_ABI_ENGINE_VERSION 1 +#define NODE_ABI_OPENSSL_VERSION 1 +#define NODE_ABI_LIBUV_VERSION 1 +#define NODE_ABI_ICU_VERSION 1 +#define NODE_ABI_CARES_VERSION 1 + +#endif // SRC_NODE_ABI_VERSIONS_H_ diff --git a/src/node_addon_macros.h b/src/node_addon_macros.h new file mode 100644 index 00000000000000..6d77ebfcddc1a5 --- /dev/null +++ b/src/node_addon_macros.h @@ -0,0 +1,145 @@ +#ifndef SRC_NODE_ADDON_MACROS_H_ +#define SRC_NODE_ADDON_MACROS_H_ + +#include "node_abi_versions.h" + +#ifdef _WIN32 +# define NODE_MODULE_EXPORT __declspec(dllexport) +#else +# define NODE_MODULE_EXPORT __attribute__((visibility("default"))) +#endif + +#ifdef NODE_SHARED_MODE +# define NODE_CTOR_PREFIX +#else +# define NODE_CTOR_PREFIX static +#endif + +#if defined(_MSC_VER) +#pragma section(".CRT$XCU", read) +#define NODE_C_CTOR(fn) \ + NODE_CTOR_PREFIX void __cdecl fn(void); \ + __declspec(dllexport, allocate(".CRT$XCU")) \ + void (__cdecl*fn ## _)(void) = fn; \ + NODE_CTOR_PREFIX void __cdecl fn(void) +#else +#define NODE_C_CTOR(fn) \ + NODE_CTOR_PREFIX void fn(void) __attribute__((constructor)); \ + NODE_CTOR_PREFIX void fn(void) +#endif + +#ifdef __cplusplus +#define EXTERN_C_START extern "C" { +#define EXTERN_C_END } +#else +#define EXTERN_C_START +#define EXTERN_C_END +#endif + +#define NODE_MODULE_X(modname, regfunc, priv, flags) \ + extern "C" { \ + static node::node_module _module = \ + { \ + NODE_MODULE_VERSION, \ + flags, \ + NULL, /* NOLINT (readability/null_usage) */ \ + __FILE__, \ + (node::addon_register_func) (regfunc), \ + NULL, /* NOLINT (readability/null_usage) */ \ + NODE_STRINGIFY(modname), \ + priv, \ + NULL /* NOLINT (readability/null_usage) */ \ + }; \ + NODE_C_CTOR(_register_ ## modname) { \ + node_module_register(&_module); \ + } \ + } + +#define NODE_MODULE_CONTEXT_AWARE_X(modname, regfunc, priv, flags) \ + extern "C" { \ + static node::node_module _module = \ + { \ + NODE_MODULE_VERSION, \ + flags, \ + NULL, /* NOLINT (readability/null_usage) */ \ + __FILE__, \ + NULL, /* NOLINT (readability/null_usage) */ \ + (node::addon_context_register_func) (regfunc), \ + NODE_STRINGIFY(modname), \ + priv, \ + NULL /* NOLINT (readability/null_usage) */ \ + }; \ + NODE_C_CTOR(_register_ ## modname) { \ + node_module_register(&_module); \ + } \ + } + +// Usage: `NODE_MODULE(NODE_GYP_MODULE_NAME, InitializerFunction)` +// If no NODE_MODULE is declared, Node.js looks for the well-known +// symbol `node_register_module_v${NODE_MODULE_VERSION}`. +#define NODE_MODULE(modname, regfunc) \ + NODE_MODULE_X(modname, regfunc, NULL, 0) // NOLINT (readability/null_usage) + +#define NODE_MODULE_CONTEXT_AWARE(modname, regfunc) \ + /* NOLINTNEXTLINE (readability/null_usage) */ \ + NODE_MODULE_CONTEXT_AWARE_X(modname, regfunc, NULL, 0) + +/* + * For backward compatibility in add-on modules. + */ +#define NODE_MODULE_DECL /* nothing */ + +#define NODE_MODULE_INITIALIZER_BASE node_register_module_v + +#define NODE_MODULE_INITIALIZER_X(base, version) \ + NODE_MODULE_INITIALIZER_X_HELPER(base, version) + +#define NODE_MODULE_INITIALIZER_X_HELPER(base, version) base##version + +#define NODE_MODULE_INITIALIZER \ + NODE_MODULE_INITIALIZER_X(NODE_MODULE_INITIALIZER_BASE, \ + NODE_MODULE_VERSION) + +#define NODE_MODULE_INIT() \ + extern "C" NODE_MODULE_EXPORT void \ + NODE_MODULE_INITIALIZER(v8::Local exports, \ + v8::Local module, \ + v8::Local context); \ + NODE_MODULE_CONTEXT_AWARE(NODE_GYP_MODULE_NAME, \ + NODE_MODULE_INITIALIZER) \ + void NODE_MODULE_INITIALIZER(v8::Local exports, \ + v8::Local module, \ + v8::Local context) + +#define NODE_MODULE_ABI_VERSION_TERMINATOR \ + { node_abi_version_terminator, 0 } +#define NODE_MODULE_ABI_VENDOR_VERSION \ + { node_abi_vendor_version, NODE_ABI_VENDOR_VERSION } +#define NODE_MODULE_ABI_ENGINE_VERSION \ + { node_abi_engine_version, NODE_ABI_ENGINE_VERSION } +#define NODE_MODULE_ABI_OPENSSL_VERSION \ + { node_abi_openssl_version, NODE_ABI_OPENSSL_VERSION } +#define NODE_MODULE_ABI_LIBUV_VERSION \ + { node_abi_libuv_version, NODE_ABI_LIBUV_VERSION } +#define NODE_MODULE_ABI_ICU_VERSION \ + { node_abi_icu_version, NODE_ABI_ICU_VERSION } +#define NODE_MODULE_ABI_CARES_VERSION \ + { node_abi_cares_version, NODE_ABI_CARES_VERSION } + +#define NODE_MODULE_ABI_DECLARATION_BASE node_module_declare_abi_v + +#define NODE_MODULE_ABI_DECLARATION \ + NODE_MODULE_INITIALIZER_X(NODE_MODULE_ABI_DECLARATION_BASE, \ + NODE_MODULE_VERSION) + +#define NODE_MODULE_DECLARE_ABI(...) \ +EXTERN_C_START \ +NODE_MODULE_EXPORT node_abi_version_entry* NODE_MODULE_ABI_DECLARATION() { \ + static node_abi_version_entry versions[] = { \ + __VA_ARGS__, NODE_MODULE_ABI_VERSION_TERMINATOR \ + }; \ + return versions; \ +} \ +EXTERN_C_END + +#endif // SRC_NODE_ADDON_MACROS_H_ diff --git a/src/node_api.h b/src/node_api.h index b36f6d4b7a4b9e..9be6b0d09bb7e7 100644 --- a/src/node_api.h +++ b/src/node_api.h @@ -12,11 +12,9 @@ struct uv_loop_s; // Forward declaration. -#ifdef _WIN32 -# define NAPI_MODULE_EXPORT __declspec(dllexport) -#else -# define NAPI_MODULE_EXPORT __attribute__((visibility("default"))) -#endif +#include "node_addon_macros.h" + +#define NAPI_MODULE_EXPORT NODE_MODULE_EXPORT #ifdef __GNUC__ #define NAPI_NO_RETURN __attribute__((noreturn)) @@ -39,18 +37,7 @@ typedef struct { #define NAPI_MODULE_VERSION 1 -#if defined(_MSC_VER) -#pragma section(".CRT$XCU", read) -#define NAPI_C_CTOR(fn) \ - static void __cdecl fn(void); \ - __declspec(dllexport, allocate(".CRT$XCU")) void(__cdecl * fn##_)(void) = \ - fn; \ - static void __cdecl fn(void) -#else -#define NAPI_C_CTOR(fn) \ - static void fn(void) __attribute__((constructor)); \ - static void fn(void) -#endif +#define NAPI_C_CTOR(fn) NODE_C_CTOR(fn) #define NAPI_MODULE_X(modname, regfunc, priv, flags) \ EXTERN_C_START \ @@ -74,12 +61,11 @@ typedef struct { #define NAPI_MODULE_INITIALIZER_BASE napi_register_module_v -#define NAPI_MODULE_INITIALIZER_X(base, version) \ - NAPI_MODULE_INITIALIZER_X_HELPER(base, version) -#define NAPI_MODULE_INITIALIZER_X_HELPER(base, version) base##version +#define NAPI_MODULE_INITIALIZER_X(base, version) \ + NODE_MODULE_INITIALIZER_X(base, version) #define NAPI_MODULE_INITIALIZER \ - NAPI_MODULE_INITIALIZER_X(NAPI_MODULE_INITIALIZER_BASE, \ + NODE_MODULE_INITIALIZER_X(NAPI_MODULE_INITIALIZER_BASE, \ NAPI_MODULE_VERSION) #define NAPI_MODULE_INIT() \ diff --git a/src/node_binding.cc b/src/node_binding.cc index cf47b3058de538..0435ee046f654f 100644 --- a/src/node_binding.cc +++ b/src/node_binding.cc @@ -190,6 +190,47 @@ void InitModpendingOnce() { CHECK_EQ(0, uv_key_create(&thread_local_modpending)); } +#define ABI_VERSION_CASE(entry, key, KEY) \ + case node_abi_ ## key ## _version: \ + if ((entry)->version != NODE_ABI_ ## KEY ## _VERSION) { \ + result += std::string() + \ + "\n" NODE_STRINGIFY(node_abi_ ## key ## _version) ": " + \ + "module: " + std::to_string((entry)->version) + \ + " vs. Node.js: " + std::to_string(NODE_ABI_ ## KEY ## _VERSION); \ + } \ + break \ + +using ABICallback = const node_abi_version_entry* (*)(); + +std::string ABICheck(DLib* dlib) { + std::string result; + const char* name = "node_module_declare_abi_v" STRINGIFY(NODE_MODULE_VERSION); + ABICallback abi_lister = + reinterpret_cast(dlib->GetSymbolAddress(name)); + if (abi_lister != nullptr) { + const node_abi_version_entry* abi_entry = abi_lister(); + if (abi_entry != nullptr) { + for (; abi_entry->item != node_abi_version_terminator; abi_entry++) { + switch (abi_entry->item) { + ABI_VERSION_CASE(abi_entry, vendor, VENDOR); + ABI_VERSION_CASE(abi_entry, engine, ENGINE); + ABI_VERSION_CASE(abi_entry, openssl, OPENSSL); + ABI_VERSION_CASE(abi_entry, libuv, LIBUV); + ABI_VERSION_CASE(abi_entry, icu, ICU); + ABI_VERSION_CASE(abi_entry, cares, CARES); + default: { + char int_string[32]; + snprintf(int_string, sizeof(int_string), "%d", abi_entry->item); + result += std::string("Unknown ABI: ") + int_string; + break; + } + } + } + } + } + return result; +} + // DLOpen is process.dlopen(module, filename, flags). // Used to load 'module.node' dynamically shared objects. // @@ -246,6 +287,19 @@ void DLOpen(const FunctionCallbackInfo& args) { return false; } + std::string abi_result = ABICheck(dlib); + if (!abi_result.empty()) { + abi_result = std::string("The module '") + (*filename) + "'" + + "\nwas compiled against a different Node.js version. The following" + "\nABI mismatches were dectected:" + + abi_result + + "\nPlease try re-compiling or reinstalling the module (for instance," + "\nusing `npm rebuild` or `npm install`)."; + dlib->Close(); + env->ThrowError(abi_result.c_str()); + return false; + } + if (mp == nullptr) { if (auto callback = GetInitializerCallback(dlib)) { callback(exports, module, context); diff --git a/src/node_binding.h b/src/node_binding.h index 7d79dae80d8e39..ab2c13a1a47b89 100644 --- a/src/node_binding.h +++ b/src/node_binding.h @@ -92,7 +92,5 @@ void DLOpen(const v8::FunctionCallbackInfo& args); } // namespace node -#include "node_binding.h" - #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS #endif // SRC_NODE_BINDING_H_ diff --git a/src/node_version.h b/src/node_version.h index b3f4808bf17127..b215aed1621fa7 100644 --- a/src/node_version.h +++ b/src/node_version.h @@ -22,6 +22,8 @@ #ifndef SRC_NODE_VERSION_H_ #define SRC_NODE_VERSION_H_ +#include "node_abi_versions.h" + #define NODE_MAJOR_VERSION 12 #define NODE_MINOR_VERSION 0 #define NODE_PATCH_VERSION 0 diff --git a/test/addons/abi-mismatch/binding.cc b/test/addons/abi-mismatch/binding.cc new file mode 100644 index 00000000000000..08a5f2bc9c8c75 --- /dev/null +++ b/test/addons/abi-mismatch/binding.cc @@ -0,0 +1,5 @@ +#include + +NODE_MODULE_INIT(/*exports, module, context*/) {} + +NODE_MODULE_DECLARE_ABI({node_abi_icu_version, NODE_ABI_ICU_VERSION + 1}) diff --git a/test/addons/abi-mismatch/binding.gyp b/test/addons/abi-mismatch/binding.gyp new file mode 100644 index 00000000000000..7ede63d94a0d77 --- /dev/null +++ b/test/addons/abi-mismatch/binding.gyp @@ -0,0 +1,9 @@ +{ + 'targets': [ + { + 'target_name': 'binding', + 'defines': [ 'V8_DEPRECATION_WARNINGS=1' ], + 'sources': [ 'binding.cc' ] + } + ] +} diff --git a/test/addons/abi-mismatch/test.js b/test/addons/abi-mismatch/test.js new file mode 100644 index 00000000000000..698df33c6a2c19 --- /dev/null +++ b/test/addons/abi-mismatch/test.js @@ -0,0 +1,4 @@ +'use strict'; +const common = require('../../common'); +const assert = require('assert'); +assert.throws(() => require(`./build/${common.buildType}/binding`), /node_abi_icu_version/); diff --git a/tools/install.py b/tools/install.py index 659b3b23a95ac4..489540652cd93d 100755 --- a/tools/install.py +++ b/tools/install.py @@ -169,6 +169,8 @@ def ignore_inspector_headers(files, dest): 'common.gypi', 'config.gypi', 'src/node.h', + 'src/node_abi_versions.h', + 'src/node_addon_macros.h', 'src/node_api.h', 'src/js_native_api.h', 'src/js_native_api_types.h',