Skip to content

Commit f21c2b9

Browse files
sxaMyles Borins
authored and
Myles Borins
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 Ref: #7487 Ref: #9385 Reviewed-By: Ben Noordhuis <[email protected]> Reviewed-By: Fedor Indutny <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Michael Dawson <[email protected]>
1 parent bb2fdf5 commit f21c2b9

File tree

7 files changed

+154
-28
lines changed

7 files changed

+154
-28
lines changed

common.gypi

+9
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@
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+
'force_dynamic_crt%': 0,
16+
'node_use_v8_platform%': 'true',
17+
'node_use_bundled_v8%': 'true',
18+
'node_module_version%': '',
19+
1420
'node_tag%': '',
1521
'uv_library%': 'static_library',
1622

@@ -291,6 +297,9 @@
291297
],
292298
'ldflags!': [ '-rdynamic' ],
293299
}],
300+
[ 'node_shared=="true"', {
301+
'cflags': [ '-fPIC' ],
302+
}]
294303
],
295304
}],
296305
['OS=="android"', {

configure

+32-3
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ 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+
2730
# parse our options
2831
parser = optparse.OptionParser()
2932

@@ -385,6 +388,26 @@ parser.add_option('--enable-static',
385388
dest='enable_static',
386389
help='build as static library')
387390

391+
parser.add_option('--shared',
392+
action='store_true',
393+
dest='shared',
394+
help='compile shared library for embedding node in another project. ' +
395+
'(This mode is not officially supported for regular applications)')
396+
397+
parser.add_option('--without-v8-platform',
398+
action='store_true',
399+
dest='without_v8_platform',
400+
default=False,
401+
help='do not initialize v8 platform during node.js startup. ' +
402+
'(This mode is not officially supported for regular applications)')
403+
404+
parser.add_option('--without-bundled-v8',
405+
action='store_true',
406+
dest='without_bundled_v8',
407+
default=False,
408+
help='do not use V8 includes from the bundled deps folder. ' +
409+
'(This mode is not officially supported for regular applications)')
410+
388411
(options, args) = parser.parse_args()
389412

390413
# Expand ~ in the install prefix now, it gets written to multiple files.
@@ -774,7 +797,14 @@ def configure_node(o):
774797
if options.enable_static:
775798
o['variables']['node_target_type'] = 'static_library'
776799

777-
o['variables']['node_module_version'] = 46
800+
o['variables']['node_shared'] = b(options.shared)
801+
o['variables']['node_use_v8_platform'] = b(not options.without_v8_platform)
802+
o['variables']['node_use_bundled_v8'] = b(not options.without_bundled_v8)
803+
node_module_version = getmoduleversion.get_version()
804+
shlib_suffix = '%s.dylib' if sys.platform == 'darwin' else 'so.%s'
805+
shlib_suffix %= node_module_version
806+
o['variables']['node_module_version'] = int(node_module_version)
807+
o['variables']['shlib_suffix'] = shlib_suffix
778808

779809
if options.linked_module:
780810
o['variables']['library_files'] = options.linked_module
@@ -820,8 +850,7 @@ def configure_v8(o):
820850
o['variables']['v8_random_seed'] = 0 # Use a random seed for hash tables.
821851
o['variables']['v8_use_snapshot'] = 'false' if options.without_snapshot else 'true'
822852
o['variables']['node_enable_d8'] = b(options.enable_d8)
823-
824-
853+
o['variables']['force_dynamic_crt'] = 1 if options.shared else 0
825854
def configure_openssl(o):
826855
o['variables']['node_use_openssl'] = b(not options.without_ssl)
827856
o['variables']['node_shared_openssl'] = b(options.shared_openssl)

node.gyp

+48-8
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@
55
'node_use_lttng%': 'false',
66
'node_use_etw%': 'false',
77
'node_use_perfctr%': 'false',
8+
'node_use_v8_platform%': 'true',
9+
'node_use_bundled_v8%': 'true',
10+
'node_shared%': 'false',
11+
'force_dynamic_crt%': 0,
12+
'node_module_version%': 'true',
813
'node_has_winsdk%': 'false',
914
'node_shared_zlib%': 'false',
1015
'node_shared_http_parser%': 'false',
@@ -101,6 +106,11 @@
101106
}, {
102107
'use_openssl_def': 0,
103108
}],
109+
[ 'node_shared=="true"', {
110+
'node_target_type%': 'shared_library',
111+
}, {
112+
'node_target_type%': 'executable',
113+
}],
104114
],
105115
},
106116

@@ -220,6 +230,42 @@
220230

221231

222232
'conditions': [
233+
[ 'node_shared=="false"', {
234+
'msvs_settings': {
235+
'VCManifestTool': {
236+
'EmbedManifest': 'true',
237+
'AdditionalManifestFiles': 'src/res/node.exe.extra.manifest'
238+
}
239+
},
240+
}, {
241+
'defines': [
242+
'NODE_SHARED_MODE',
243+
],
244+
'conditions': [
245+
[ 'node_module_version!=""', {
246+
'product_extension': 'so.<(node_module_version)',
247+
}]
248+
],
249+
}],
250+
[ 'node_use_bundled_v8=="true"', {
251+
'include_dirs': [
252+
'deps/v8' # include/v8_platform.h
253+
],
254+
255+
'dependencies': [
256+
'deps/v8/tools/gyp/v8.gyp:v8',
257+
'deps/v8/tools/gyp/v8.gyp:v8_libplatform'
258+
],
259+
}],
260+
[ 'node_use_v8_platform=="true"', {
261+
'defines': [
262+
'NODE_USE_V8_PLATFORM=1',
263+
],
264+
}, {
265+
'defines': [
266+
'NODE_USE_V8_PLATFORM=0',
267+
],
268+
}],
223269
[ 'node_enable_d8=="true"', {
224270
'dependencies': [ 'deps/v8/src/d8.gyp:d8' ],
225271
}],
@@ -292,7 +338,7 @@
292338
],
293339
},
294340
'conditions': [
295-
['OS in "linux freebsd"', {
341+
['OS in "linux freebsd" and node_shared=="false"', {
296342
'ldflags': [
297343
'-Wl,--whole-archive,'
298344
'<(PRODUCT_DIR)/obj.target/deps/openssl/'
@@ -460,7 +506,7 @@
460506
'NODE_PLATFORM="sunos"',
461507
],
462508
}],
463-
[ 'OS=="freebsd" or OS=="linux"', {
509+
[ '(OS=="freebsd" or OS=="linux") and node_shared=="false"', {
464510
'ldflags': [ '-Wl,-z,noexecstack',
465511
'-Wl,--whole-archive <(V8_BASE)',
466512
'-Wl,--no-whole-archive' ]
@@ -469,12 +515,6 @@
469515
'ldflags': [ '-Wl,-M,/usr/lib/ld/map.noexstk' ],
470516
}],
471517
],
472-
'msvs_settings': {
473-
'VCManifestTool': {
474-
'EmbedManifest': 'true',
475-
'AdditionalManifestFiles': 'src/res/node.exe.extra.manifest'
476-
}
477-
},
478518
},
479519
{
480520
'target_name': 'mkssldef',

src/node.cc

+31-6
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"
@@ -167,6 +169,30 @@ static v8::Platform* default_platform;
167169
static uv_sem_t debug_semaphore;
168170
#endif
169171

172+
static struct {
173+
#if NODE_USE_V8_PLATFORM
174+
void Initialize(int thread_pool_size) {
175+
platform_ = v8::platform::CreateDefaultPlatform(thread_pool_size);
176+
V8::InitializePlatform(platform_);
177+
}
178+
179+
void PumpMessageLoop(Isolate* isolate) {
180+
v8::platform::PumpMessageLoop(platform_, isolate);
181+
}
182+
183+
void Dispose() {
184+
delete platform_;
185+
platform_ = nullptr;
186+
}
187+
188+
v8::Platform* platform_;
189+
#else // !NODE_USE_V8_PLATFORM
190+
void Initialize(int thread_pool_size) {}
191+
void PumpMessageLoop(Isolate* isolate) {}
192+
void Dispose() {}
193+
#endif // !NODE_USE_V8_PLATFORM
194+
} v8_platform;
195+
170196
static void PrintErrorString(const char* format, ...) {
171197
va_list ap;
172198
va_start(ap, format);
@@ -4226,11 +4252,11 @@ static void StartNodeInstance(void* arg) {
42264252
SealHandleScope seal(isolate);
42274253
bool more;
42284254
do {
4229-
v8::platform::PumpMessageLoop(default_platform, isolate);
4255+
v8_platform.PumpMessageLoop(isolate);
42304256
more = uv_run(env->event_loop(), UV_RUN_ONCE);
42314257

42324258
if (more == false) {
4233-
v8::platform::PumpMessageLoop(default_platform, isolate);
4259+
v8_platform.PumpMessageLoop(isolate);
42344260
EmitBeforeExit(env);
42354261

42364262
// Emit `beforeExit` if the loop became alive either after emitting
@@ -4291,8 +4317,8 @@ int Start(int argc, char** argv) {
42914317
#endif
42924318

42934319
const int thread_pool_size = 4;
4294-
default_platform = v8::platform::CreateDefaultPlatform(thread_pool_size);
4295-
V8::InitializePlatform(default_platform);
4320+
4321+
v8_platform.Initialize(thread_pool_size);
42964322
V8::Initialize();
42974323

42984324
int exit_code = 1;
@@ -4309,8 +4335,7 @@ int Start(int argc, char** argv) {
43094335
}
43104336
V8::Dispose();
43114337

4312-
delete default_platform;
4313-
default_platform = nullptr;
4338+
v8_platform.Dispose();
43144339

43154340
delete[] exec_argv;
43164341
exec_argv = nullptr;

src/node.h

+10-4
Original file line numberDiff line numberDiff line change
@@ -396,17 +396,23 @@ extern "C" NODE_EXTERN void node_module_register(void* mod);
396396
# define NODE_MODULE_EXPORT __attribute__((visibility("default")))
397397
#endif
398398

399+
#ifdef NODE_SHARED_MODE
400+
# define NODE_CTOR_PREFIX
401+
#else
402+
# define NODE_CTOR_PREFIX static
403+
#endif
404+
399405
#if defined(_MSC_VER)
400406
#pragma section(".CRT$XCU", read)
401407
#define NODE_C_CTOR(fn) \
402-
static void __cdecl fn(void); \
408+
NODE_CTOR_PREFIX void __cdecl fn(void); \
403409
__declspec(dllexport, allocate(".CRT$XCU")) \
404410
void (__cdecl*fn ## _)(void) = fn; \
405-
static void __cdecl fn(void)
411+
NODE_CTOR_PREFIX void __cdecl fn(void)
406412
#else
407413
#define NODE_C_CTOR(fn) \
408-
static void fn(void) __attribute__((constructor)); \
409-
static void fn(void)
414+
NODE_CTOR_PREFIX void fn(void) __attribute__((constructor)); \
415+
NODE_CTOR_PREFIX void fn(void)
410416
#endif
411417

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

tools/getnodeversion.py

+9-5
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
1-
import os,re
1+
import os
2+
import re
23

3-
node_version_h = os.path.join(os.path.dirname(__file__), '..', 'src',
4+
node_version_h = os.path.join(
5+
os.path.dirname(__file__),
6+
'..',
7+
'src',
48
'node_version.h')
59

610
f = open(node_version_h)
711

812
for line in f:
9-
if re.match('#define NODE_MAJOR_VERSION', line):
13+
if re.match('^#define NODE_MAJOR_VERSION', line):
1014
major = line.split()[2]
11-
if re.match('#define NODE_MINOR_VERSION', line):
15+
if re.match('^#define NODE_MINOR_VERSION', line):
1216
minor = line.split()[2]
13-
if re.match('#define NODE_PATCH_VERSION', line):
17+
if re.match('^#define NODE_PATCH_VERSION', line):
1418
patch = line.split()[2]
1519

1620
print '%(major)s.%(minor)s.%(patch)s'% locals()

tools/install.py

+15-2
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,22 @@ def subdir_files(path, dest, action):
123123

124124
def files(action):
125125
is_windows = sys.platform == 'win32'
126+
output_file = 'node'
127+
output_prefix = 'out/Release/'
126128

127-
exeext = '.exe' if is_windows else ''
128-
action(['out/Release/node' + exeext], 'bin/node' + exeext)
129+
if 'false' == variables.get('node_shared'):
130+
if is_windows:
131+
output_file += '.exe'
132+
else:
133+
if is_windows:
134+
output_file += '.dll'
135+
else:
136+
# GYP will output to lib.target, this is hardcoded in its source,
137+
# see the _InstallablaeTargetInstallPath function.
138+
output_prefix += 'lib.target/'
139+
output_file = 'lib' + output_file + '.so'
140+
141+
action([output_prefix + output_file], 'bin/' + output_file)
129142

130143
if 'true' == variables.get('node_use_dtrace'):
131144
action(['out/Release/node.d'], 'lib/dtrace/node.d')

0 commit comments

Comments
 (0)