Skip to content

Commit 410296c

Browse files
committed
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: #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>
1 parent 86e07b7 commit 410296c

File tree

9 files changed

+212
-36
lines changed

9 files changed

+212
-36
lines changed

common.gypi

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@
1111
'msvs_multi_core_compile': '0', # we do enable multicore compiles, but not using the V8 way
1212
'python%': 'python',
1313

14+
'node_shared%': 'false',
15+
'node_use_v8_platform%': 'true',
16+
'node_use_bundled_v8%': 'true',
17+
'node_module_version%': '',
18+
1419
'node_tag%': '',
1520
'uv_library%': 'static_library',
1621

@@ -290,6 +295,9 @@
290295
],
291296
'ldflags!': [ '-rdynamic' ],
292297
}],
298+
[ 'node_shared=="true"', {
299+
'cflags': [ '-fPIC' ],
300+
}],
293301
],
294302
}],
295303
[ 'OS=="android"', {

configure

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ from gyp.common import GetFlavor
2424
sys.path.insert(0, os.path.join(root_dir, 'tools', 'configure.d'))
2525
import nodedownload
2626

27+
# imports in tools/
28+
sys.path.insert(0, os.path.join(root_dir, 'tools'))
29+
import getmoduleversion
30+
2731
# parse our options
2832
parser = optparse.OptionParser()
2933

@@ -420,6 +424,26 @@ parser.add_option('--without-inspector',
420424
dest='without_inspector',
421425
help='disable experimental V8 inspector support')
422426

427+
parser.add_option('--shared',
428+
action='store_true',
429+
dest='shared',
430+
help='compile shared library for embedding node in another project. ' +
431+
'(This mode is not officially supported for regular applications)')
432+
433+
parser.add_option('--without-v8-platform',
434+
action='store_true',
435+
dest='without_v8_platform',
436+
default=False,
437+
help='do not initialize v8 platform during node.js startup. ' +
438+
'(This mode is not officially supported for regular applications)')
439+
440+
parser.add_option('--without-bundled-v8',
441+
action='store_true',
442+
dest='without_bundled_v8',
443+
default=False,
444+
help='do not use V8 includes from the bundled deps folder. ' +
445+
'(This mode is not officially supported for regular applications)')
446+
423447
(options, args) = parser.parse_args()
424448

425449
# Expand ~ in the install prefix now, it gets written to multiple files.
@@ -810,6 +834,10 @@ def configure_node(o):
810834
o['variables']['node_target_type'] = 'static_library'
811835

812836
o['variables']['node_no_browser_globals'] = b(options.no_browser_globals)
837+
o['variables']['node_shared'] = b(options.shared)
838+
o['variables']['node_use_v8_platform'] = b(not options.without_v8_platform)
839+
o['variables']['node_use_bundled_v8'] = b(not options.without_bundled_v8)
840+
o['variables']['node_module_version'] = int(getmoduleversion.get_version())
813841

814842
if options.linked_module:
815843
o['variables']['library_files'] = options.linked_module

node.gyp

Lines changed: 64 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66
'node_use_etw%': 'false',
77
'node_use_perfctr%': 'false',
88
'node_no_browser_globals%': 'false',
9+
'node_use_v8_platform%': 'true',
10+
'node_use_bundled_v8%': 'true',
11+
'node_shared%': 'false',
12+
'node_module_version%': '',
913
'node_shared_zlib%': 'false',
1014
'node_shared_http_parser%': 'false',
1115
'node_shared_cares%': 'false',
@@ -14,7 +18,6 @@
1418
'node_shared_openssl%': 'false',
1519
'node_v8_options%': '',
1620
'node_enable_v8_vtunejit%': 'false',
17-
'node_target_type%': 'executable',
1821
'node_core_target_name%': 'node',
1922
'library_files': [
2023
'lib/internal/bootstrap_node.js',
@@ -100,6 +103,13 @@
100103
'deps/v8/tools/SourceMap.js',
101104
'deps/v8/tools/tickprocessor-driver.js',
102105
],
106+
'conditions': [
107+
[ 'node_shared=="true"', {
108+
'node_target_type%': 'shared_library',
109+
}, {
110+
'node_target_type%': 'executable',
111+
}],
112+
],
103113
},
104114

105115
'targets': [
@@ -109,16 +119,13 @@
109119

110120
'dependencies': [
111121
'node_js2c#host',
112-
'deps/v8/tools/gyp/v8.gyp:v8',
113-
'deps/v8/tools/gyp/v8.gyp:v8_libplatform'
114122
],
115123

116124
'include_dirs': [
117125
'src',
118126
'tools/msvs/genfiles',
119127
'deps/uv/src/ares',
120128
'<(SHARED_INTERMEDIATE_DIR)', # for node_natives.h
121-
'deps/v8' # include/v8_platform.h
122129
],
123130

124131
'sources': [
@@ -217,6 +224,42 @@
217224

218225

219226
'conditions': [
227+
[ 'node_shared=="false"', {
228+
'msvs_settings': {
229+
'VCManifestTool': {
230+
'EmbedManifest': 'true',
231+
'AdditionalManifestFiles': 'src/res/node.exe.extra.manifest'
232+
}
233+
},
234+
}, {
235+
'defines': [
236+
'NODE_SHARED_MODE',
237+
],
238+
'conditions': [
239+
[ 'node_module_version!=""', {
240+
'product_extension': 'so.<(node_module_version)',
241+
}]
242+
],
243+
}],
244+
[ 'node_use_bundled_v8=="true"', {
245+
'include_dirs': [
246+
'deps/v8', # include/v8_platform.h
247+
],
248+
249+
'dependencies': [
250+
'deps/v8/tools/gyp/v8.gyp:v8',
251+
'deps/v8/tools/gyp/v8.gyp:v8_libplatform'
252+
],
253+
}],
254+
[ 'node_use_v8_platform=="true"', {
255+
'defines': [
256+
'NODE_USE_V8_PLATFORM=1',
257+
],
258+
}, {
259+
'defines': [
260+
'NODE_USE_V8_PLATFORM=0',
261+
],
262+
}],
220263
[ 'node_tag!=""', {
221264
'defines': [ 'NODE_TAG="<(node_tag)"' ],
222265
}],
@@ -245,7 +288,8 @@
245288
'defines': [ 'NODE_HAVE_SMALL_ICU=1' ],
246289
}]],
247290
}],
248-
[ 'node_enable_v8_vtunejit=="true" and (target_arch=="x64" or \
291+
[ 'node_use_bundled_v8=="true" and \
292+
node_enable_v8_vtunejit=="true" and (target_arch=="x64" or \
249293
target_arch=="ia32" or target_arch=="x32")', {
250294
'defines': [ 'NODE_ENABLE_VTUNE_PROFILING' ],
251295
'dependencies': [
@@ -308,7 +352,7 @@
308352
],
309353
},
310354
'conditions': [
311-
['OS in "linux freebsd"', {
355+
['OS in "linux freebsd" and node_shared=="false"', {
312356
'ldflags': [
313357
'-Wl,--whole-archive <(PRODUCT_DIR)/<(OPENSSL_PRODUCT)',
314358
'-Wl,--no-whole-archive',
@@ -395,7 +439,7 @@
395439
[ 'node_no_browser_globals=="true"', {
396440
'defines': [ 'NODE_NO_BROWSER_GLOBALS' ],
397441
} ],
398-
[ 'v8_postmortem_support=="true"', {
442+
[ 'node_use_bundled_v8=="true" and v8_postmortem_support=="true"', {
399443
'dependencies': [ 'deps/v8/tools/gyp/v8.gyp:postmortem-metadata' ],
400444
'conditions': [
401445
# -force_load is not applicable for the static library
@@ -478,7 +522,7 @@
478522
'NODE_PLATFORM="sunos"',
479523
],
480524
}],
481-
[ 'OS=="freebsd" or OS=="linux"', {
525+
[ '(OS=="freebsd" or OS=="linux") and node_shared=="false"', {
482526
'ldflags': [ '-Wl,-z,noexecstack',
483527
'-Wl,--whole-archive <(V8_BASE)',
484528
'-Wl,--no-whole-archive' ]
@@ -487,12 +531,6 @@
487531
'ldflags': [ '-Wl,-M,/usr/lib/ld/map.noexstk' ],
488532
}],
489533
],
490-
'msvs_settings': {
491-
'VCManifestTool': {
492-
'EmbedManifest': 'true',
493-
'AdditionalManifestFiles': 'src/res/node.exe.extra.manifest'
494-
}
495-
},
496534
},
497535
# generate ETW header and resource files
498536
{
@@ -718,8 +756,6 @@
718756
'deps/http_parser/http_parser.gyp:http_parser',
719757
'deps/gtest/gtest.gyp:gtest',
720758
'deps/uv/uv.gyp:libuv',
721-
'deps/v8/tools/gyp/v8.gyp:v8',
722-
'deps/v8/tools/gyp/v8.gyp:v8_libplatform'
723759
],
724760
'include_dirs': [
725761
'src',
@@ -750,7 +786,18 @@
750786
'src/inspector_socket.cc',
751787
'test/cctest/test_inspector_socket.cc'
752788
]
753-
}]
789+
}],
790+
[ 'node_use_v8_platform=="true"', {
791+
'dependencies': [
792+
'deps/v8/tools/gyp/v8.gyp:v8_libplatform',
793+
],
794+
}],
795+
[ 'node_use_bundled_v8=="true"', {
796+
'dependencies': [
797+
'deps/v8/tools/gyp/v8.gyp:v8',
798+
'deps/v8/tools/gyp/v8.gyp:v8_libplatform'
799+
],
800+
}],
754801
]
755802
}
756803
], # end targets

src/node.cc

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@
3939
#include "string_bytes.h"
4040
#include "util.h"
4141
#include "uv.h"
42+
#if NODE_USE_V8_PLATFORM
4243
#include "libplatform/libplatform.h"
44+
#endif // NODE_USE_V8_PLATFORM
4345
#include "v8-debug.h"
4446
#include "v8-profiler.h"
4547
#include "zlib.h"
@@ -183,7 +185,42 @@ static uv_async_t dispatch_debug_messages_async;
183185

184186
static Mutex node_isolate_mutex;
185187
static v8::Isolate* node_isolate;
186-
static v8::Platform* default_platform;
188+
189+
static struct {
190+
#if NODE_USE_V8_PLATFORM
191+
void Initialize(int thread_pool_size) {
192+
platform_ = v8::platform::CreateDefaultPlatform(thread_pool_size);
193+
V8::InitializePlatform(platform_);
194+
}
195+
196+
void PumpMessageLoop(Isolate* isolate) {
197+
v8::platform::PumpMessageLoop(platform_, isolate);
198+
}
199+
200+
void Dispose() {
201+
delete platform_;
202+
platform_ = nullptr;
203+
}
204+
205+
#if HAVE_INSPECTOR
206+
void StartInspector(Environment *env, int port, bool wait) {
207+
env->inspector_agent()->Start(platform_, port, wait);
208+
}
209+
#endif // HAVE_INSPECTOR
210+
211+
v8::Platform* platform_;
212+
#else // !NODE_USE_V8_PLATFORM
213+
void Initialize(int thread_pool_size) {}
214+
void PumpMessageLoop(Isolate* isolate) {}
215+
void Dispose() {}
216+
#if HAVE_INSPECTOR
217+
void StartInspector(Environment *env, int port, bool wait) {
218+
env->ThrowError("Node compiled with NODE_USE_V8_PLATFORM=0");
219+
}
220+
#endif // HAVE_INSPECTOR
221+
222+
#endif // !NODE_USE_V8_PLATFORM
223+
} v8_platform;
187224

188225
#ifdef __POSIX__
189226
static uv_sem_t debug_semaphore;
@@ -3652,7 +3689,7 @@ static void StartDebug(Environment* env, bool wait) {
36523689
CHECK(!debugger_running);
36533690
#if HAVE_INSPECTOR
36543691
if (use_inspector) {
3655-
env->inspector_agent()->Start(default_platform, inspector_port, wait);
3692+
v8_platform.StartInspector(env, inspector_port, wait);
36563693
debugger_running = true;
36573694
} else {
36583695
#endif
@@ -4299,11 +4336,11 @@ static void StartNodeInstance(void* arg) {
42994336
SealHandleScope seal(isolate);
43004337
bool more;
43014338
do {
4302-
v8::platform::PumpMessageLoop(default_platform, isolate);
4339+
v8_platform.PumpMessageLoop(isolate);
43034340
more = uv_run(env.event_loop(), UV_RUN_ONCE);
43044341

43054342
if (more == false) {
4306-
v8::platform::PumpMessageLoop(default_platform, isolate);
4343+
v8_platform.PumpMessageLoop(isolate);
43074344
EmitBeforeExit(&env);
43084345

43094346
// Emit `beforeExit` if the loop became alive either after emitting
@@ -4364,8 +4401,7 @@ int Start(int argc, char** argv) {
43644401
V8::SetEntropySource(crypto::EntropySource);
43654402
#endif
43664403

4367-
default_platform = v8::platform::CreateDefaultPlatform(v8_thread_pool_size);
4368-
V8::InitializePlatform(default_platform);
4404+
v8_platform.Initialize(v8_thread_pool_size);
43694405
V8::Initialize();
43704406

43714407
int exit_code = 1;
@@ -4382,8 +4418,7 @@ int Start(int argc, char** argv) {
43824418
}
43834419
V8::Dispose();
43844420

4385-
delete default_platform;
4386-
default_platform = nullptr;
4421+
v8_platform.Dispose();
43874422

43884423
delete[] exec_argv;
43894424
exec_argv = nullptr;

src/node.h

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -411,17 +411,23 @@ extern "C" NODE_EXTERN void node_module_register(void* mod);
411411
# define NODE_MODULE_EXPORT __attribute__((visibility("default")))
412412
#endif
413413

414+
#ifdef NODE_SHARED_MODE
415+
# define NODE_CTOR_PREFIX
416+
#else
417+
# define NODE_CTOR_PREFIX static
418+
#endif
419+
414420
#if defined(_MSC_VER)
415421
#pragma section(".CRT$XCU", read)
416422
#define NODE_C_CTOR(fn) \
417-
static void __cdecl fn(void); \
423+
NODE_CTOR_PREFIX void __cdecl fn(void); \
418424
__declspec(dllexport, allocate(".CRT$XCU")) \
419425
void (__cdecl*fn ## _)(void) = fn; \
420-
static void __cdecl fn(void)
426+
NODE_CTOR_PREFIX void __cdecl fn(void)
421427
#else
422428
#define NODE_C_CTOR(fn) \
423-
static void fn(void) __attribute__((constructor)); \
424-
static void fn(void)
429+
NODE_CTOR_PREFIX void fn(void) __attribute__((constructor)); \
430+
NODE_CTOR_PREFIX void fn(void)
425431
#endif
426432

427433
#define NODE_MODULE_X(modname, regfunc, priv, flags) \

test/parallel/test-module-version.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
'use strict';
2+
require('../common');
3+
var assert = require('assert');
4+
5+
// check for existence
6+
assert(process.config.variables.hasOwnProperty('node_module_version'));
7+
8+
// ensure that `node_module_version` is an Integer > 0
9+
assert(Number.isInteger(process.config.variables.node_module_version));
10+
assert(process.config.variables.node_module_version > 0);

0 commit comments

Comments
 (0)