summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Budeanu <stefan@budeanu.com>2016-03-26 20:17:55 -0400
committerJeremiah Senkpiel <fishrock123@rocketmail.com>2016-07-05 22:16:23 +0200
commit91744aaf00079843c3b079c11798821a83ebd407 (patch)
treedf19b0322c970ab6ffb063334833b7ac31511426
parentbc37e6a22dfd02ba8033e233651b4f88b38161e7 (diff)
downloadnode-new-91744aaf00079843c3b079c11798821a83ebd407.tar.gz
build: configure --shared
Add configure flag for building a shared library that can be embedded in other applications (like Electron). Add flags --without-bundled-v8 and --without-v8-platform to control V8 dependencies used. PR-URL: https://github.com/nodejs/node/pull/6994 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Fedor Indutny <fedor@indutny.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com> Conflicts: src/node.cc
-rw-r--r--common.gypi8
-rwxr-xr-xconfigure28
-rw-r--r--node.gyp81
-rw-r--r--src/node.cc51
-rw-r--r--src/node.h14
-rw-r--r--test/parallel/test-module-version.js10
-rw-r--r--tools/getmoduleversion.py24
-rw-r--r--tools/getnodeversion.py14
-rwxr-xr-xtools/install.py18
9 files changed, 212 insertions, 36 deletions
diff --git a/common.gypi b/common.gypi
index 8da603d00f..a892c2d6e3 100644
--- a/common.gypi
+++ b/common.gypi
@@ -11,6 +11,11 @@
'msvs_multi_core_compile': '0', # we do enable multicore compiles, but not using the V8 way
'python%': 'python',
+ 'node_shared%': 'false',
+ 'node_use_v8_platform%': 'true',
+ 'node_use_bundled_v8%': 'true',
+ 'node_module_version%': '',
+
'node_tag%': '',
'uv_library%': 'static_library',
@@ -290,6 +295,9 @@
],
'ldflags!': [ '-rdynamic' ],
}],
+ [ 'node_shared=="true"', {
+ 'cflags': [ '-fPIC' ],
+ }],
],
}],
[ 'OS=="android"', {
diff --git a/configure b/configure
index d622a6f062..879c12b496 100755
--- a/configure
+++ b/configure
@@ -24,6 +24,10 @@ from gyp.common import GetFlavor
sys.path.insert(0, os.path.join(root_dir, 'tools', 'configure.d'))
import nodedownload
+# imports in tools/
+sys.path.insert(0, os.path.join(root_dir, 'tools'))
+import getmoduleversion
+
# parse our options
parser = optparse.OptionParser()
@@ -420,6 +424,26 @@ parser.add_option('--without-inspector',
dest='without_inspector',
help='disable experimental V8 inspector support')
+parser.add_option('--shared',
+ action='store_true',
+ dest='shared',
+ help='compile shared library for embedding node in another project. ' +
+ '(This mode is not officially supported for regular applications)')
+
+parser.add_option('--without-v8-platform',
+ action='store_true',
+ dest='without_v8_platform',
+ default=False,
+ help='do not initialize v8 platform during node.js startup. ' +
+ '(This mode is not officially supported for regular applications)')
+
+parser.add_option('--without-bundled-v8',
+ action='store_true',
+ dest='without_bundled_v8',
+ default=False,
+ help='do not use V8 includes from the bundled deps folder. ' +
+ '(This mode is not officially supported for regular applications)')
+
(options, args) = parser.parse_args()
# Expand ~ in the install prefix now, it gets written to multiple files.
@@ -810,6 +834,10 @@ def configure_node(o):
o['variables']['node_target_type'] = 'static_library'
o['variables']['node_no_browser_globals'] = b(options.no_browser_globals)
+ o['variables']['node_shared'] = b(options.shared)
+ o['variables']['node_use_v8_platform'] = b(not options.without_v8_platform)
+ o['variables']['node_use_bundled_v8'] = b(not options.without_bundled_v8)
+ o['variables']['node_module_version'] = int(getmoduleversion.get_version())
if options.linked_module:
o['variables']['library_files'] = options.linked_module
diff --git a/node.gyp b/node.gyp
index c3f591351d..c14f57e94a 100644
--- a/node.gyp
+++ b/node.gyp
@@ -6,6 +6,10 @@
'node_use_etw%': 'false',
'node_use_perfctr%': 'false',
'node_no_browser_globals%': 'false',
+ 'node_use_v8_platform%': 'true',
+ 'node_use_bundled_v8%': 'true',
+ 'node_shared%': 'false',
+ 'node_module_version%': '',
'node_shared_zlib%': 'false',
'node_shared_http_parser%': 'false',
'node_shared_cares%': 'false',
@@ -14,7 +18,6 @@
'node_shared_openssl%': 'false',
'node_v8_options%': '',
'node_enable_v8_vtunejit%': 'false',
- 'node_target_type%': 'executable',
'node_core_target_name%': 'node',
'library_files': [
'lib/internal/bootstrap_node.js',
@@ -100,6 +103,13 @@
'deps/v8/tools/SourceMap.js',
'deps/v8/tools/tickprocessor-driver.js',
],
+ 'conditions': [
+ [ 'node_shared=="true"', {
+ 'node_target_type%': 'shared_library',
+ }, {
+ 'node_target_type%': 'executable',
+ }],
+ ],
},
'targets': [
@@ -109,8 +119,6 @@
'dependencies': [
'node_js2c#host',
- 'deps/v8/tools/gyp/v8.gyp:v8',
- 'deps/v8/tools/gyp/v8.gyp:v8_libplatform'
],
'include_dirs': [
@@ -118,7 +126,6 @@
'tools/msvs/genfiles',
'deps/uv/src/ares',
'<(SHARED_INTERMEDIATE_DIR)', # for node_natives.h
- 'deps/v8' # include/v8_platform.h
],
'sources': [
@@ -217,6 +224,42 @@
'conditions': [
+ [ 'node_shared=="false"', {
+ 'msvs_settings': {
+ 'VCManifestTool': {
+ 'EmbedManifest': 'true',
+ 'AdditionalManifestFiles': 'src/res/node.exe.extra.manifest'
+ }
+ },
+ }, {
+ 'defines': [
+ 'NODE_SHARED_MODE',
+ ],
+ 'conditions': [
+ [ 'node_module_version!=""', {
+ 'product_extension': 'so.<(node_module_version)',
+ }]
+ ],
+ }],
+ [ 'node_use_bundled_v8=="true"', {
+ 'include_dirs': [
+ 'deps/v8', # include/v8_platform.h
+ ],
+
+ 'dependencies': [
+ 'deps/v8/tools/gyp/v8.gyp:v8',
+ 'deps/v8/tools/gyp/v8.gyp:v8_libplatform'
+ ],
+ }],
+ [ 'node_use_v8_platform=="true"', {
+ 'defines': [
+ 'NODE_USE_V8_PLATFORM=1',
+ ],
+ }, {
+ 'defines': [
+ 'NODE_USE_V8_PLATFORM=0',
+ ],
+ }],
[ 'node_tag!=""', {
'defines': [ 'NODE_TAG="<(node_tag)"' ],
}],
@@ -245,7 +288,8 @@
'defines': [ 'NODE_HAVE_SMALL_ICU=1' ],
}]],
}],
- [ 'node_enable_v8_vtunejit=="true" and (target_arch=="x64" or \
+ [ 'node_use_bundled_v8=="true" and \
+ node_enable_v8_vtunejit=="true" and (target_arch=="x64" or \
target_arch=="ia32" or target_arch=="x32")', {
'defines': [ 'NODE_ENABLE_VTUNE_PROFILING' ],
'dependencies': [
@@ -308,7 +352,7 @@
],
},
'conditions': [
- ['OS in "linux freebsd"', {
+ ['OS in "linux freebsd" and node_shared=="false"', {
'ldflags': [
'-Wl,--whole-archive <(PRODUCT_DIR)/<(OPENSSL_PRODUCT)',
'-Wl,--no-whole-archive',
@@ -395,7 +439,7 @@
[ 'node_no_browser_globals=="true"', {
'defines': [ 'NODE_NO_BROWSER_GLOBALS' ],
} ],
- [ 'v8_postmortem_support=="true"', {
+ [ 'node_use_bundled_v8=="true" and v8_postmortem_support=="true"', {
'dependencies': [ 'deps/v8/tools/gyp/v8.gyp:postmortem-metadata' ],
'conditions': [
# -force_load is not applicable for the static library
@@ -478,7 +522,7 @@
'NODE_PLATFORM="sunos"',
],
}],
- [ 'OS=="freebsd" or OS=="linux"', {
+ [ '(OS=="freebsd" or OS=="linux") and node_shared=="false"', {
'ldflags': [ '-Wl,-z,noexecstack',
'-Wl,--whole-archive <(V8_BASE)',
'-Wl,--no-whole-archive' ]
@@ -487,12 +531,6 @@
'ldflags': [ '-Wl,-M,/usr/lib/ld/map.noexstk' ],
}],
],
- 'msvs_settings': {
- 'VCManifestTool': {
- 'EmbedManifest': 'true',
- 'AdditionalManifestFiles': 'src/res/node.exe.extra.manifest'
- }
- },
},
# generate ETW header and resource files
{
@@ -718,8 +756,6 @@
'deps/http_parser/http_parser.gyp:http_parser',
'deps/gtest/gtest.gyp:gtest',
'deps/uv/uv.gyp:libuv',
- 'deps/v8/tools/gyp/v8.gyp:v8',
- 'deps/v8/tools/gyp/v8.gyp:v8_libplatform'
],
'include_dirs': [
'src',
@@ -750,7 +786,18 @@
'src/inspector_socket.cc',
'test/cctest/test_inspector_socket.cc'
]
- }]
+ }],
+ [ 'node_use_v8_platform=="true"', {
+ 'dependencies': [
+ 'deps/v8/tools/gyp/v8.gyp:v8_libplatform',
+ ],
+ }],
+ [ 'node_use_bundled_v8=="true"', {
+ 'dependencies': [
+ 'deps/v8/tools/gyp/v8.gyp:v8',
+ 'deps/v8/tools/gyp/v8.gyp:v8_libplatform'
+ ],
+ }],
]
}
], # end targets
diff --git a/src/node.cc b/src/node.cc
index 3a31242957..8cadf18f8d 100644
--- a/src/node.cc
+++ b/src/node.cc
@@ -39,7 +39,9 @@
#include "string_bytes.h"
#include "util.h"
#include "uv.h"
+#if NODE_USE_V8_PLATFORM
#include "libplatform/libplatform.h"
+#endif // NODE_USE_V8_PLATFORM
#include "v8-debug.h"
#include "v8-profiler.h"
#include "zlib.h"
@@ -184,7 +186,42 @@ static uv_async_t dispatch_debug_messages_async;
static Mutex node_isolate_mutex;
static v8::Isolate* node_isolate;
-static v8::Platform* default_platform;
+
+static struct {
+#if NODE_USE_V8_PLATFORM
+ void Initialize(int thread_pool_size) {
+ platform_ = v8::platform::CreateDefaultPlatform(thread_pool_size);
+ V8::InitializePlatform(platform_);
+ }
+
+ void PumpMessageLoop(Isolate* isolate) {
+ v8::platform::PumpMessageLoop(platform_, isolate);
+ }
+
+ void Dispose() {
+ delete platform_;
+ platform_ = nullptr;
+ }
+
+#if HAVE_INSPECTOR
+ void StartInspector(Environment *env, int port, bool wait) {
+ env->inspector_agent()->Start(platform_, port, wait);
+ }
+#endif // HAVE_INSPECTOR
+
+ v8::Platform* platform_;
+#else // !NODE_USE_V8_PLATFORM
+ void Initialize(int thread_pool_size) {}
+ void PumpMessageLoop(Isolate* isolate) {}
+ void Dispose() {}
+#if HAVE_INSPECTOR
+ void StartInspector(Environment *env, int port, bool wait) {
+ env->ThrowError("Node compiled with NODE_USE_V8_PLATFORM=0");
+ }
+#endif // HAVE_INSPECTOR
+
+#endif // !NODE_USE_V8_PLATFORM
+} v8_platform;
#ifdef __POSIX__
static uv_sem_t debug_semaphore;
@@ -3736,7 +3773,7 @@ static void StartDebug(Environment* env, bool wait) {
CHECK(!debugger_running);
#if HAVE_INSPECTOR
if (use_inspector) {
- env->inspector_agent()->Start(default_platform, inspector_port, wait);
+ v8_platform.StartInspector(env, inspector_port, wait);
debugger_running = true;
} else {
#endif
@@ -4467,11 +4504,11 @@ static void StartNodeInstance(void* arg) {
SealHandleScope seal(isolate);
bool more;
do {
- v8::platform::PumpMessageLoop(default_platform, isolate);
+ v8_platform.PumpMessageLoop(isolate);
more = uv_run(env->event_loop(), UV_RUN_ONCE);
if (more == false) {
- v8::platform::PumpMessageLoop(default_platform, isolate);
+ v8_platform.PumpMessageLoop(isolate);
EmitBeforeExit(env);
// Emit `beforeExit` if the loop became alive either after emitting
@@ -4537,8 +4574,7 @@ int Start(int argc, char** argv) {
V8::SetEntropySource(crypto::EntropySource);
#endif
- default_platform = v8::platform::CreateDefaultPlatform(v8_thread_pool_size);
- V8::InitializePlatform(default_platform);
+ v8_platform.Initialize(v8_thread_pool_size);
V8::Initialize();
int exit_code = 1;
@@ -4555,8 +4591,7 @@ int Start(int argc, char** argv) {
}
V8::Dispose();
- delete default_platform;
- default_platform = nullptr;
+ v8_platform.Dispose();
delete[] exec_argv;
exec_argv = nullptr;
diff --git a/src/node.h b/src/node.h
index 42c5ac59d7..6d12567f89 100644
--- a/src/node.h
+++ b/src/node.h
@@ -415,17 +415,23 @@ extern "C" NODE_EXTERN void node_module_register(void* mod);
# 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) \
- static void __cdecl fn(void); \
+ NODE_CTOR_PREFIX void __cdecl fn(void); \
__declspec(dllexport, allocate(".CRT$XCU")) \
void (__cdecl*fn ## _)(void) = fn; \
- static void __cdecl fn(void)
+ NODE_CTOR_PREFIX void __cdecl fn(void)
#else
#define NODE_C_CTOR(fn) \
- static void fn(void) __attribute__((constructor)); \
- static void fn(void)
+ NODE_CTOR_PREFIX void fn(void) __attribute__((constructor)); \
+ NODE_CTOR_PREFIX void fn(void)
#endif
#define NODE_MODULE_X(modname, regfunc, priv, flags) \
diff --git a/test/parallel/test-module-version.js b/test/parallel/test-module-version.js
new file mode 100644
index 0000000000..7f96e8bb60
--- /dev/null
+++ b/test/parallel/test-module-version.js
@@ -0,0 +1,10 @@
+'use strict';
+require('../common');
+var assert = require('assert');
+
+// check for existence
+assert(process.config.variables.hasOwnProperty('node_module_version'));
+
+// ensure that `node_module_version` is an Integer > 0
+assert(Number.isInteger(process.config.variables.node_module_version));
+assert(process.config.variables.node_module_version > 0);
diff --git a/tools/getmoduleversion.py b/tools/getmoduleversion.py
new file mode 100644
index 0000000000..fb86ba1fa9
--- /dev/null
+++ b/tools/getmoduleversion.py
@@ -0,0 +1,24 @@
+from __future__ import print_function
+import os
+import re
+
+def get_version():
+ node_version_h = os.path.join(
+ os.path.dirname(__file__),
+ '..',
+ 'src',
+ 'node_version.h')
+
+ f = open(node_version_h)
+
+ regex = '^#define NODE_MODULE_VERSION [0-9]+'
+
+ for line in f:
+ if re.match(regex, line):
+ major = line.split()[2]
+ return major
+
+ raise Exception('Could not find pattern matching %s' % regex)
+
+if __name__ == '__main__':
+ print(get_version())
diff --git a/tools/getnodeversion.py b/tools/getnodeversion.py
index 766e4f60dc..f2032cccef 100644
--- a/tools/getnodeversion.py
+++ b/tools/getnodeversion.py
@@ -1,16 +1,20 @@
-import os,re
+import os
+import re
-node_version_h = os.path.join(os.path.dirname(__file__), '..', 'src',
+node_version_h = os.path.join(
+ os.path.dirname(__file__),
+ '..',
+ 'src',
'node_version.h')
f = open(node_version_h)
for line in f:
- if re.match('#define NODE_MAJOR_VERSION', line):
+ if re.match('^#define NODE_MAJOR_VERSION', line):
major = line.split()[2]
- if re.match('#define NODE_MINOR_VERSION', line):
+ if re.match('^#define NODE_MINOR_VERSION', line):
minor = line.split()[2]
- if re.match('#define NODE_PATCH_VERSION', line):
+ if re.match('^#define NODE_PATCH_VERSION', line):
patch = line.split()[2]
print '%(major)s.%(minor)s.%(patch)s'% locals()
diff --git a/tools/install.py b/tools/install.py
index f3fa4fe898..a3986c5033 100755
--- a/tools/install.py
+++ b/tools/install.py
@@ -6,6 +6,7 @@ import os
import re
import shutil
import sys
+from getmoduleversion import get_version
# set at init time
node_prefix = '/usr/local' # PREFIX variable from Makefile
@@ -107,9 +108,22 @@ def subdir_files(path, dest, action):
def files(action):
is_windows = sys.platform == 'win32'
+ output_file = 'node'
+ output_prefix = 'out/Release/'
- exeext = '.exe' if is_windows else ''
- action(['out/Release/node' + exeext], 'bin/node' + exeext)
+ if 'false' == variables.get('node_shared'):
+ if is_windows:
+ output_file += '.exe'
+ else:
+ if is_windows:
+ output_file += '.dll'
+ else:
+ # GYP will output to lib.target, this is hardcoded in its source,
+ # see the _InstallableTargetInstallPath function.
+ output_prefix += 'lib.target/'
+ output_file = 'lib' + output_file + '.so.' + get_version()
+
+ action([output_prefix + output_file], 'bin/' + output_file)
if 'true' == variables.get('node_use_dtrace'):
action(['out/Release/node.d'], 'lib/dtrace/node.d')