node-gyp

repository·main·Indexed 27 days ago

https://github.com/nodejs/node-gyp

A cross-platform command-line tool used for compiling native addon modules for Node.js. It utilizes GYP to generate project files for various build systems such as Make, MSBuild, XCode, and Visual Studio. The tool provides commands for configuring, building, cleaning, and rebuilding native addons, and supports custom configurations via package.json, environment variables, or CLI flags.

Tokens
14.1K
Snippets
37
Records
85
Agent score
95%

What's inside node-gyp

  1. Overview of GYP (gyp-next)

    main

    GYP is a meta-build system designed to generate other build systems. It is intended for large, multi-platform projects (macOS, Windows, Linux) that require native IDE support. GYP can generate project files for:

    • XCode projects
    • Visual Studio projects
    • Ninja build files
    • Makefiles

    It supports both fully native builds and "hybrid" projects, where the IDE provides the scaffolding/user experience but delegates the actual build process to Ninja for increased speed.

  2. Identify GYP output files by platform

    main

    A single .gyp file defines how to build targets for a specific 'component' and generates platform-specific build files:

    • macOS: Generates one Xcode .xcodeproj bundle containing target build information.
    • Windows: Generates one Visual Studio .sln file and one Visual Studio .vcproj file for each target.
    • Linux: Generates one SCons file and/or one Makefile per target.
  3. Install system dependencies for node-gyp

    main

    Depending on your operating system, you need to install specific build tools:

    Unix

    • A supported version of Python
    • make
    • A C/C++ compiler toolchain (e.g., GCC)

    macOS

    • A supported version of Python
    • Xcode Command Line Tools (installs clang, clang++, and make). Install via xcode-select --install or through the Xcode menu.

    Windows

    Using Chocolatey:

    choco install python visualstudio2022-workload-vctools -y

    Manual Installation:

    • Install Python.
    • Install Visual C++ Build Environment:
      • For Visual Studio 2019 or later: Use the Desktop development with C++ workload from Visual Studio Community.
      • For older versions: Install Visual Studio Build Tools with the Visual C++ build tools option.
    • Windows on ARM: Add "Visual C++ compilers and libraries for ARM64" and "Visual C++ ATL for ARM64". Ensure Visual Studio 2022 [17.4 or later] is installed to use the native ARM64 C++ compiler.
    • Recommended: Install the VSSetup PowerShell module to improve Visual Studio detection: Install-Module VSSetup -Scope CurrentUser.
  4. Use conditionals in .gyp files

    main

    Conditionals allow you to apply settings based on specific criteria. There are two types:

    1. conditions: Processed shortly after loading .gyp files.
    2. target_conditions: Processed after all dependencies have been computed.

    A conditional section is a list containing:

    • The conditional expression (e.g., 'OS==mac').
    • A dictionary of settings to merge if the expression is true.
    • (Optional) A dictionary of settings to merge if the expression is false.
  5. Configure global node-gyp on Windows

    main

    To use the latest global version of node-gyp on Windows, install it globally and then update the npm node_gyp config using the appropriate shell syntax for your terminal.

    # Windows Command Prompt
    npm install --global node-gyp@latest
    for /f "delims=" %P in ('npm prefix -g') do npm config set node_gyp "%P\node_modules\node-gyp\bin\node-gyp.js"
    # PowerShell
    npm install --global node-gyp@latest
    npm prefix -g | % {npm config set node_gyp "$($_\node_modules\node-gyp\bin\node-gyp.js)"}
  6. Include other GYP files

    main

    You can include other .gyp or .gypi files using the includes section.

    • Command Line: Files specified via the -I or --include argument are implicitly merged into the root dictionary of all files.
    • In-file includes: An includes section containing a list of files can be placed anywhere. These are processed sequentially and merged into the enclosing dictionary at that point.
    • Order of Operations: includes sections are processed immediately after a file is loaded, before variable or conditional processing. This means you cannot use a variable to determine which file to include.
    • Conditional Includes: An includes section can be placed inside a conditions block. The file will be loaded, but its contents will only be merged if the condition is met.
  7. Build native addons for third-party runtimes (e.g., Electron)

    main

    When building for runtimes like Electron that use different configurations than official Node.js, use the --dist-url or --nodedir flags to specify the runtime headers. This causes node-gyp to use the config.gypi file shipped with the headers instead of the running Node.js instance's process.config.

    If you encounter configuration errors due to malformed config.gypi in older Electron versions, use the --force-process-config flag.

  8. Link to OpenSSL in binding.gyp for Unix

    main

    Native addons requiring OpenSSL should account for whether Node.js uses a shared system OpenSSL or a statically bundled version. Use the node_shared_openssl variable to determine the include paths. When node_shared_openssl is false, you must include the headers from the Node.js internal OpenSSL directory, which varies based on the target_arch (ia32, x64, or arm).

    {
      'variables': {
        'node_shared_openssl%': 'true'
      },
      'targets': [
        {
          'target_name': 'binding',
          'sources': [
            'src/binding.cc'
          ],
          'conditions': [
            ['node_shared_openssl=="false"', {
              'include_dirs': [
                '<(node_root_dir)/deps/openssl/openssl/include'
              ],
              "conditions" : [
                ["target_arch=='ia32'", {
                  "include_dirs": [ "<(node_root_dir)/deps/openssl/config/piii" ]
                }],
                ["target_arch=='x64'", {
                  "include_dirs": [ "<(node_root_dir)/deps/openssl/config/k8" ]
                }],
                ["target_arch=='arm'", {
                  "include_dirs": [ "<(node_root_dir)/deps/openssl/config/arm" ]
                }]
              ]
            }]
          ]
        }
      ]
    }
  9. Use --nodedir to compile with Node.js "pre" versions

    main

    When using a Node.js version with a -pre suffix, you must specify the Node.js source code directory path using the --nodedir flag during the build process.

    Using node-gyp directly

    If you are invoking node-gyp manually, pass the --nodedir flag followed by the path to your Node.js source:

    $ node-gyp rebuild --nodedir=/path/to/node/source

    Using npm

    If you are installing a package via npm that requires compilation, pass the flag through npm:

    $ npm install <package-name> --nodedir=/path/to/node/source

    Persistent configuration via npm config

    To avoid specifying the flag for every installation, you can set the nodedir in your npm configuration:

    $ npm config set nodedir /path/to/node/source
    $ node-gyp rebuild --nodedir=/Users/nrajlich/node
    
    $ npm install bcrypt --nodedir=/Users/nrajlich/node
    
    $ npm config set nodedir /Users/nrajlich/node
  10. Link to OpenSSL in binding.gyp for Windows

    main

    On Windows, OpenSSL is statically compiled into the Node.js executable, making it difficult to use the bundled version directly. A common workaround is to use a separate OpenSSL installation. You can configure this in your binding.gyp by defining an openssl_root variable based on the target_arch and then specifying the libraries and include_dirs relative to that root.

        [ 'OS=="win"', {
          'conditions': [
            # "openssl_root" is the directory on Windows of the OpenSSL files.
            # Check the "target_arch" variable to set good default values for
            # both 64-bit and 32-bit builds of the module.
            ['target_arch=="x64"', {
              'variables': {
                'openssl_root%': 'C:/OpenSSL-Win64'
              },
            }, {
              'variables': {
                'openssl_root%': 'C:/OpenSSL-Win32'
              },
            }],
          ],
          'libraries': [ 
            '-l<(openssl_root)/lib/libeay32.lib',
          ],
          'include_dirs': [
            '<(openssl_root)/include',
          ],
        }]
  11. Important limitations for updating npm-bundled node-gyp

    main

    When updating the internal node-gyp bundled with npm, be aware of the following:

    • Compatibility: These instructions are only tested and known to work with npm 8 and older.
    • Persistence: These changes are temporary. They will be undone if you reinstall or upgrade npm or Node.js.
    • Alternative: For a more permanent solution (available for npm 6 or older only), refer to the Force-npm-to-use-global-node-gyp.md guide.