Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

build: Fix various shared library build issues. #41850

Closed
wants to merge 7 commits into from
Closed

build: Fix various shared library build issues. #41850

wants to merge 7 commits into from

Commits on Apr 26, 2022

  1. 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
    ...
    ```
    lux01 committed Apr 26, 2022
    Configuration menu
    Copy the full SHA
    e76ddb4 View commit details
    Browse the repository at this point in the history
  2. Fix bad merge

    lux01 committed Apr 26, 2022
    Configuration menu
    Copy the full SHA
    8d55ff0 View commit details
    Browse the repository at this point in the history
  3. Fixup linter complaint

    mhdawson authored and lux01 committed Apr 26, 2022
    Configuration menu
    Copy the full SHA
    944e55a View commit details
    Browse the repository at this point in the history
  4. Update tools/install.py

    mhdawson authored and lux01 committed Apr 26, 2022
    Configuration menu
    Copy the full SHA
    a840b01 View commit details
    Browse the repository at this point in the history
  5. Generate and use a .def file. Add NODE_EXTERN_PRIVATE.

    When building Node.js as a shared library we need to use generate
    a module-definiton file that re-exports all the public symbols
    from libnode.dll and redirects them back to libnode.dll.
    
    This allows native addons built using non-shared library builds of
    Node.js to run on shared library builds and (theoretically) vice versa.
    lux01 committed Apr 26, 2022
    Configuration menu
    Copy the full SHA
    72f166b View commit details
    Browse the repository at this point in the history
  6. Configuration menu
    Copy the full SHA
    b3af563 View commit details
    Browse the repository at this point in the history

Commits on Apr 30, 2022

  1. Configuration menu
    Copy the full SHA
    aa9ea4d View commit details
    Browse the repository at this point in the history