diff options
author | William Marlow <william.marlow@ibm.com> | 2022-02-04 10:12:57 +0000 |
---|---|---|
committer | Michael Dawson <mdawson@devrus.com> | 2022-05-06 17:24:46 -0400 |
commit | 1af70548bdb2db6b52bd52c73e39d22963580aa5 (patch) | |
tree | 22ca59e6b78de97574d30e24348b616f9728231f /node.gypi | |
parent | 183447888bcbd1d6bfc433a38c77900ed6199bc2 (diff) | |
download | node-new-1af70548bdb2db6b52bd52c73e39d22963580aa5.tar.gz |
build: fix various shared library build issues
Node.js unofficially supports a shared library variant where the
main node executable is a thin wrapper around node.dll/libnode.so.
The key benefit of this is to support embedding Node.js in other
applications.
Since Node.js 12 there have been a number of issues preventing the
shared library build from working correctly, primarily on Windows:
* A number of functions used executables such as `mksnapshot` are
not exported from `libnode.dll` using a `NODE_EXTERN` attribute
* A dependency on the `Winmm` system library is missing
* Incorrect defines on executable targets leads to `node.exe`
claiming to export a number of functions that are actually in
`libnode.dll`
* Because `node.exe` attempts to export symbols, `node.lib` gets
generated causing native extensions to try to link against
`node.exe` not `libnode.dll`.
* Similarly, because `node.dll` was renamed to `libnode.dll`,
native extensions don't know to look for `libnode.lib` rather
than `node.lib`.
* On macOS an RPATH is added to find `libnode.dylib` relative to
`node` in the same folder. This works fine from the
`out/Release` folder but not from an installed prefix, where
`node` will be in `bin/` and `libnode.dylib` will be in `lib/`.
* Similarly on Linux, no RPATH is added so LD_LIBRARY_PATH needs
setting correctly for `bin/node` to find `lib/libnode.so`.
For the `libnode.lib` vs `node.lib` issue there are two possible
options:
1. Ensure `node.lib` from `node.exe` does not get generated, and
instead copy `libnode.lib` to `node.lib`. This means addons
compiled when referencing the correct `node.lib` file will
correctly depend on `libnode.dll`. The down side is that
native addons compiled with stock Node.js will still try to
resolve symbols against node.exe rather than libnode.dll.
2. After building `libnode.dll`, dump the exports using `dumpbin`,
and process this to generate a `node.def` file to be linked into
`node.exe` with the `/DEF:node.def` flag. The export entries
in `node.def` will all read
```
my_symbol=libnode.my_symbol
```
so that `node.exe` will redirect all exported symbols back to
`libnode.dll`. This has the benefit that addons compiled with
stock Node.js will load correctly into `node.exe` from a shared
library build, but means that every embedding executable also
needs to perform this same trick.
I went with the first option as it is the cleaner of the two
solutions in my opinion. Projects wishing to generate a shared
library variant of Node.js can now, for example,
```
.\vcbuild dll package vs
```
to generate a full node installation including `libnode.dll`,
`Release\node.lib`, and all the necessary headers. Native addons
can then be built against the shared library build easily by
specifying the correct `nodedir` option.
For example
```
>npx node-gyp configure --nodedir
C:\Users\User\node\Release\node-v18.0.0-win-x64
...
>npx node-gyp build
...
>dumpbin /dependents build\Release\binding.node
Microsoft (R) COFF/PE Dumper Version 14.29.30136.0
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file build\Release\binding.node
File Type: DLL
Image has the following dependencies:
KERNEL32.dll
libnode.dll
VCRUNTIME140.dll
api-ms-win-crt-string-l1-1-0.dll
api-ms-win-crt-stdio-l1-1-0.dll
api-ms-win-crt-runtime-l1-1-0.dll
...
```
PR-URL: https://github.com/nodejs/node/pull/41850
Reviewed-By: Michael Dawson <midawson@redhat.com>
Reviewed-By: Beth Griggs <bgriggs@redhat.com>
Reviewed-By: Richard Lau <rlau@redhat.com>
Diffstat (limited to 'node.gypi')
-rw-r--r-- | node.gypi | 15 |
1 files changed, 14 insertions, 1 deletions
@@ -29,7 +29,7 @@ [ 'clang==1', { 'cflags': [ '-Werror=undefined-inline', ] }], - [ 'node_shared=="false" and "<(_type)"=="executable"', { + [ '"<(_type)"=="executable"', { 'msvs_settings': { 'VCManifestTool': { 'EmbedManifest': 'true', @@ -41,6 +41,19 @@ 'defines': [ 'NODE_SHARED_MODE', ], + 'conditions': [ + ['"<(_type)"=="executable"', { + 'defines': [ + 'USING_UV_SHARED', + 'USING_V8_SHARED', + 'BUILDING_NODE_EXTENSION' + ], + 'defines!': [ + 'BUILDING_V8_SHARED=1', + 'BUILDING_UV_SHARED=1' + ] + }], + ], }], [ 'OS=="win"', { 'defines!': [ |