How to build custom Node.js?

I tried using this recipe with versions 14.17.0 and 14.18.0:

let
  pkgs = import
    (
      fetchTarball {
        # TODO: Pin to stable nixpkgs
        name = "nixpkgs-2021-10-01";
        url = "https://github.com/NixOS/nixpkgs/archive/9a23237031b385945132c8dac7d7ad97ece67408.tar.gz";
        sha256 = "0g5ksps5pdhh1npv5vs6560gn0cdbvs536p54nm87lyvz50x7f6m";
      })
    { };

  nodejsVersion = pkgs.lib.fileContents ./.nvmrc;
  buildNodeJs = pkgs.callPackage <nixpkgs/pkgs/development/web/nodejs/nodejs.nix> { };
  nodejs = buildNodeJs {
    enableNpm = true;
    version = nodejsVersion;
    sha256 = "1vf989canwcx0wdpngvkbz2x232yccp7fzs1vcbr60rijgzmpq2n";
  };

  poetryEnv = pkgs.poetry2nix.mkPoetryEnv {
    python = pkgs.python38;
    projectDir = builtins.path { path = ./.; name = "geostore"; };
  };
in
pkgs.mkShell {
  buildInputs = [
    nodejs
    poetryEnv
    poetryEnv.python.pkgs.pip
    poetryEnv.python.pkgs.poetry
  ];
  shellHook = ''
    . activate-dev-env.bash
  '';
}

Both of them failed to build with very similar (possibly identical) results:

  g++ -o /build/node-v14.17.0/out/Release/obj.target/v8_base_without_compiler/deps/v8/src/objects/js-locale.o ../deps/v8/src/objects/js-locale.cc '-DV8_GYP_BUILD' '-DV8_TYPED_ARRAY_MAX_SIZE_IN_HEAP=64' '-D__STDC_FORMAT_MACROS' '-DV8_TARGET_ARCH_X64' '-DV8_EMBEDDER_STRING="-node.63"' '-DENABLE_DISASSEMBLER' '-DV8_PROMISE_INTERNAL_FIELD_COUNT=1' '-DENABLE_MINOR_MC' '-DOBJECT_PRINT' '-DV8_INTL_SUPPORT' '-DV8_CONCURRENT_MARKING' '-DV8_ARRAY_BUFFER_EXTENSION' '-DV8_ENABLE_LAZY_SOURCE_POSITIONS' '-DV8_USE_SIPHASH' '-DDISABLE_UNTRUSTED_CODE_MITIGATIONS' '-DV8_WIN64_UNWINDING_INFO' '-DV8_ENABLE_REGEXP_INTERPRETER_THREADED_DISPATCH' '-DV8_SNAPSHOT_COMPRESSION' '-DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_STATIC' -I/nix/store/6xliwk3s6lhyql2gsxaq7krqz7vlzjwn-zlib-1.2.11-dev/include -I/nix/store/jj6ksy63r23n2kzj8r1ggrblz2qyplmf-libuv-1.42.0/include -I/nix/store/aqkjhbpn406zswbw4aj67fs2bh34kmvp-openssl-1.1.1l-dev/include -I/nix/store/4z23hs6gmmz1iddi868w5dspq2az44wj-icu4c-69.1-dev/include -I../deps/v8 -I../deps/v8/include -I/build/node-v14.17.0/out/Release/obj/gen/inspector-generated-output-root -I../deps/v8/third_party/inspector_protocol -I/build/node-v14.17.0/out/Release/obj/gen/torque-output-root -I/build/node-v14.17.0/out/Release/obj/gen/generate-bytecode-output-root -I../deps/v8/third_party/zlib -I../deps/v8/third_party/zlib/google  -pthread -Wno-unused-parameter -m64 -Wno-return-type -fno-strict-aliasing -m64 -O3 -fno-omit-frame-pointer -fdata-sections -ffunction-sections -O3 -fno-rtti -fno-exceptions -std=gnu++1y -MMD -MF /build/node-v14.17.0/out/Release/.deps//build/node-v14.17.0/out/Release/obj.target/v8_base_without_compiler/deps/v8/src/objects/js-locale.o.d.raw   -c
../deps/v8/src/objects/js-list-format.cc: In static member function 'static v8::internal::MaybeHandle<v8::internal::JSListFormat> v8::internal::JSListFormat::New(v8::internal::Isolate*, v8::internal::Handle<v8::internal::Map>, v8::internal::Handle<v8::internal::Object>, v8::internal::Handle<v8::internal::Object>)':
../deps/v8/src/objects/js-list-format.cc:146:67: error: 'static icu_69::ListFormatter* icu_69::ListFormatter::createInstance(const icu_69::Locale&, const char*, UErrorCode&)' is private within this context
  146 |       icu_locale, GetIcuStyleString(style_enum, type_enum), status);
      |                                                                   ^
In file included from ../deps/v8/src/objects/js-list-format.cc:25:
/nix/store/4z23hs6gmmz1iddi868w5dspq2az44wj-icu4c-69.1-dev/include/unicode/listformatter.h:267:27: note: declared private here
  267 |     static ListFormatter* createInstance(const Locale& locale, const char* style, UErrorCode& errorCode);
      |                           ^~~~~~~~~~~~~~
make[1]: *** [tools/v8_gypfiles/v8_base_without_compiler.target.mk:658: /build/node-v14.17.0/out/Release/obj.target/v8_base_without_compiler/deps/v8/src/objects/js-list-format.o] Error 1
make[1]: *** Waiting for unfinished jobs....
rm 6d3cb5d5a2b0f84fdbbbd36684a9703f7a7dd7dc.intermediate e96e9872be5bcb367483eb7a95a7a0249169304f.intermediate 7814d936bef09600be94dabe6ae6c3fa051d2c04.intermediate
make: *** [Makefile:104: node] Error 2
builder for '/nix/store/6rsgdc5n3slqfwl7a31f305valg24ig4-nodejs-14.17.0.drv' failed with exit code 2
error: build of '/nix/store/6rsgdc5n3slqfwl7a31f305valg24ig4-nodejs-14.17.0.drv' failed

Is there some way to build a custom Node.js?

This is a bit old, but as I stumbled upon it myself looking to do the same I will provide an answer that worked for me.

I think the error you got here is form the icu. Not sure though. But I saw in another branch they had used icu68 for a newer version of node so I tried that and got another error. That was related to openssl, and after using an older version of that it worked. I think the python one is not necessary, but not completely sure.

This worked for me at least.

        buildNodeJs = pkgs.callPackage "${nixpkgs}/pkgs/development/web/nodejs/nodejs.nix" {
          icu = pkgs.icu68;
          python = pkgs.python2;
          openssl = pkgs.openssl_1_1;
        };

        node1220 = buildNodeJs {
          enableNpm = true;
          version = "12.20.0";
          sha256 = "sha256-YeP9XJr1ZejSVAPOVrLACX4uMnA4Hy1CFlc9SLPcQos=";
        };