Skip to content

Add GN configurations to Node #1353

Closed
Closed
@zcbenz

Description

@zcbenz

What I am asking for

I'm asking for including GN configurations in Node's repo, so users can build Node with GN without forking.

Precisely, about 1100 lines of BUILD.gn files and 3 python scripts.

It is also simple to setup a CI job building Node with GN, and even integrating GN into Node's current building process, please check the example: https://github.com/photoionization/node_with_gn.

What I am NOT asking for

I'm not asking for a complete replacement of GYP with GN, it is currently not possible since Node supports building for some platforms not supported by GN yet (adding support for those platforms is not hard).

This issue is not exactly the same with nodejs/node#21410, I'm not talking about possibilities, this is finished work which I would like to include in upstream, and you can immediately see why you would want to use it (read the benefits below).

Is GYP not enough?

Why bother with another build system when GYP is working fine? Many people may ask. My answer is, GYP is not fine, not at all.

First of all, GYP is abandoned by its creators, it has been forked by Node but only in maintenance mode. And since Node is the only project using it, you don't have outsider building experts improving this tool, you only have people not interested in build tools forced to fix bugs when there is no other choice.

And GYP is buggy and fragile, you can see it by simply trying with ninja generator (configure.py --ninja). Node's build files have been built around bugs and weird behaviors of GYP.

The alternatives

Since no one is willing to translate V8's build configurations to a foreign build system, this really leaves us with only 2 options for choosing a build system for Node: GN and Bazel.

I personally have no experience with Bazel so I can't do a features compare. But the fact is, there are already people building Node with GN, including Electron team and V8 team. The latter may be surprising to you, but V8 is maintaining an active GN configuration for Node (https://chromium.googlesource.com/v8/node-ci/), and it is used in Chromium project.

This means no matter which build system Node uses, Electron and V8 still have to maintain a GN configuration anyway. But if Node can support building with GN, all those resources will come here to support the upstream.

The benefits of GN

By supporting GN, developers of Node can immediately get following goodies:
(You can try it NOW with https://github.com/photoionization/node_with_gn)

Unified compiler and libc++ on all platforms

GN supports using the exactly the same version of clang for building on Linux/macOS/Windows, with binaries maintained by Chromium project. And it also supports building with the exactly the same version of libc++. Just behind a flag.

This means you don't have to struggle with MSVC and GCC when trying to use bleeding edge C++17/20 features. It also means you no longer needs to figure out how to setup new clang/libc++ when building on a not-so-new Linux distribution.

(Building with system compiler and C++ standard library is also supported.)

Linux sysroot images

When doing cross compilation on Linux, it is extremely difficult to install the correct libraries for the target arch. With GN this is solved with sysroot images, the script downloads the headers and libraries of the target arch to disk for the build system to link.

This also solves problem of providing prebuilt binaries that run on most Linux distributions. When building Node.js on a newer linux distribution, it may be linked to a new version of glibc which is not available in old linux distributions, resulting in prebuilt binaries unable to run on those platforms (nodejs/node#43246). There are also problems that different distributions may have libraries put under different places, so the prebuilt binaries may not be able to find the correct lib on a foreign distribution.

The sysroot images provided by Chromium are designed to solve this problem, and it is free for Node to use, behind a build flag.

Compile Windows binaries on Linux and macOS

With GN it is possible to compile Windows binaries on Linux and macOS, the GitHub Actions of node_with_gn builds the Windows binaries on a free linux runner.

Distributed compiler service

GN supports building with goma, which is like ccache but does all the compilation and caching in a central server.

Compiling V8 is very slow but with goma build you can build Node from scratch within a minute and half (tested with Electron's goma service). You still have to setup a very powerful goma server but it is very worthy investment, not only much shorter local build time, but also much shorter time spent on CI.

Sanitizers

With GN it is possible to reuse Chromium's sanitizers in Node, a full list of supported sanitizers can be found at: https://source.chromium.org/chromium/chromium/src/+/main:build/config/sanitizers/sanitizers.gni. They are very helpful tools for debugging various leaks and crashes.

Rust support

GN supports building rust code, and linking with C++ code. Chromium has rewritten a few parts like JSON parser in rust, and if Node wants to do the same all the tools are already here in GN.

And it is not only about rewriting existing code. For components like http parser and url parser, there are a few good rust implementation already being used in browsers, with GN support in Node it will be practical to replace those components in Node with safe rust equivalents.

Downsides with GN

The biggest downside with GN is, the vanilla GN does not have any preset build configurations with it, each project using GN must also have its own build configurations instructing things like how to invoke clang. I solved this problem by forking GN to support preset build configurations, and then ship Chromium's build configurations with it. The forked GN can be found at https://github.com/yue/build-gn.

So to build Node with GN we must either ship a large stock of build configurations inside Node (Like what V8 does), or use a forked GN with a forked Chromium build configurations. But either way Node will receive help from Electron team and I believe it is still much better than sticking to GYP.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions