|
| 1 | +# Maintaining shared library support |
| 2 | + |
| 3 | +Node.js unofficially supports a build option where Node.js is built as |
| 4 | +a shared library. The shared library is called libnode with additional postfixes |
| 5 | +as appropriate for the platform (for example libnode.dll on windows). |
| 6 | +The shared library provides a way to embed Node.js into other |
| 7 | +applications and to have multiple applications use a single copy of |
| 8 | +Node.js instead of having to bundle in the full Node.js footprint |
| 9 | +into each application. For workloads that require multiple Node.js |
| 10 | +instances this can result in a significant footprint savings. |
| 11 | + |
| 12 | +This document provides an outline of the approach and things to look |
| 13 | +out for when maintaining the shared library support. |
| 14 | + |
| 15 | +Currently, shared library support has only been tested on: |
| 16 | + |
| 17 | +* Linux |
| 18 | +* macOS |
| 19 | +* Windows |
| 20 | +* AIX |
| 21 | + |
| 22 | +## Building with shared library option |
| 23 | + |
| 24 | +On non-Windows platoforms, Node.js is built with the shared library |
| 25 | +option by adding `--shared` to the configure step. On Windows |
| 26 | +platofrms Node.js is built with the shared library option by |
| 27 | +adding `dll` to the vcbuild command line. |
| 28 | + |
| 29 | +Once built there are two key components: |
| 30 | + |
| 31 | +* executable - node |
| 32 | +* library - libnode |
| 33 | + |
| 34 | +The node executable is a thin wrapper around libnode which is |
| 35 | +generated so that we can run the standard Node.js test suite |
| 36 | +against the shared library. |
| 37 | + |
| 38 | +The executable and library will have extensions as appropriate |
| 39 | +for the platform on which they are built. For |
| 40 | +example, node.exe on windows and node on other platforms for |
| 41 | +the executable. |
| 42 | + |
| 43 | +libnode may have additional naming components, as an example |
| 44 | +in a build on macOS `libnode.105.dylib`. For non-windows platforms |
| 45 | +the additional naming components include the `NODE_MODULE_VERSION` and |
| 46 | +the appropriate postfix used for shared libraries on the platform. |
| 47 | + |
| 48 | +In cases where an application links against the shared |
| 49 | +library it is up to the application developer to add options |
| 50 | +so that the shared library can be found by the application or |
| 51 | +to set the LIBPATH (AIX), LD\_LIBRARY\_PATH (Linux/Unix), etc. |
| 52 | +so that it is found at runtime. |
| 53 | + |
| 54 | +For the node wrapper, on linux and macOS it is built |
| 55 | +so that it can find the shared library in one of |
| 56 | +the following: |
| 57 | + |
| 58 | +* the same directory as the node executable |
| 59 | +* ../lib with the expectation that the executable is |
| 60 | + installed in a `bin` directory at the same level |
| 61 | + as a `lib` directory in which the shared library is |
| 62 | + installed. This is where the default package that |
| 63 | + is build with the shared library option will |
| 64 | + place the executable and library. |
| 65 | + |
| 66 | +For the node wrapper on windows it is built expecting |
| 67 | +that both the executable and shared library will |
| 68 | +be in the same directory as it common practice on |
| 69 | +that platform. |
| 70 | + |
| 71 | +For the node wrapper on AIX, it is built with |
| 72 | +the path to the shared library hardcoded as that |
| 73 | +is the only option. |
| 74 | + |
| 75 | +## Exports |
| 76 | + |
| 77 | +On windows, functions that may be linked from native |
| 78 | +addons or additional Node.js executables need to have |
| 79 | +NODE\_EXTERN\_PRIVATE or NODE\_EXTERN otherwise they will |
| 80 | +not be exported by the shared library. In the case of |
| 81 | +functions used by additional Node.js executables |
| 82 | +(ex: `mksnapshot`) a missing NODE\_EXTERN or |
| 83 | +NODE\_EXTERN\_PRIVATE will cause the build to fail. |
| 84 | +NODE\_EXTERN\_PRIVATE should be used in these cases |
| 85 | +unless the intent is to add the function to the |
| 86 | +public embedder API. |
| 87 | + |
| 88 | +## Native addons |
| 89 | + |
| 90 | +For regular Node.js builds, running native addons relies on symbols |
| 91 | +exported by the node executable. As a result any |
| 92 | +pre-built binaries expect symbols to be exported from the executable |
| 93 | +instead of the shared library itself. |
| 94 | + |
| 95 | +The node executable and shared library are built and linked |
| 96 | +so that the required symbols are exported from the node |
| 97 | +executable. This requires some extra work on some platforms |
| 98 | +and the process to build the node executable is a good example |
| 99 | +of how this can be achieved. Applications that use the shared |
| 100 | +library and want to support native addons should employ |
| 101 | +a similar technique. |
| 102 | + |
| 103 | +## Testing |
| 104 | + |
| 105 | +There is currently no testing in the regular CI run for PRs. There |
| 106 | +are some CI jobs that can be used to test the shared library support and |
| 107 | +some are run as part of daily testing. These include: |
| 108 | + |
| 109 | +* [node-test-commit-linux-as-shared-lib](https://ci.nodejs.org/view/Node.js%20Daily/job/node-test-commit-linux-as-shared-lib/) |
| 110 | +* <https://ci.nodejs.org/view/All/job/node-test-commit-osx-as-shared-lib/> |
| 111 | +* [node-test-commit-aix-shared-lib](https://ci.nodejs.org/view/Node.js%20Daily/job/node-test-commit-aix-shared-lib/) |
| 112 | + |
| 113 | +TODO: add a Job for windows |
| 114 | + |
| 115 | +For code that modifies/affects shared library support these CI jobs should |
| 116 | +run and it should be validated that there are no regressions in |
| 117 | +the test suite. |
0 commit comments