Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ The `build.sh` script compiles Node.js from source as a static binary:
- **Usage:** `./build.sh -n NODE_VERSION`
- **Example:** `./build.sh -n 20.10.0`
- **Output:** Extracts to a version-independent `node-src/` directory and creates the compiled Node.js binary there. Building in a stable directory name (rather than `node-v$VERSION/`) lets ccache reuse compiled objects across Node version bumps, since unchanged files no longer get a different cache key just because the version changed.
- **Configuration:** Uses `--fully-static --enable-static --without-npm --without-intl` flags
- **Configuration:** Uses `--fully-static --enable-static --without-npm --without-intl` flags. `--without-intl` is also what keeps the static build working without patching generated makefiles; see "Static builds and `--without-intl`" in [README.md](./README.md)
- **Duration:** Compilation takes 10-30 minutes on a cold cache; a warm ccache (e.g. a patch version bump) can be substantially faster

## Dockerfile
Expand Down Expand Up @@ -72,7 +72,6 @@ Compiles Node.js statically:
- Downloads Node.js source tarball and checksums
- Verifies GPG signature
- Configures with fully-static compilation flags
- Patches build files to work around static linking issues
- Compiles with optimal parallelization

### check-missing-versions.sh
Expand Down
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,14 @@ docker build -t node-minimal .
```

See [AGENTS.md](AGENTS.md) for the full development guide and [SETUP.md](SETUP.md) for local pre-commit hook setup.

## Static builds and `--without-intl`

`build.sh` configures Node with `--fully-static`, which appends `-static` to every link command in the generated makefiles. That includes build-time host tools and shared libraries that only work when linked dynamically, and upstream this remains broken ([nodejs/node#41497](https://github.com/nodejs/node/issues/41497); the fix proposed in [nodejs/node#30199](https://github.com/nodejs/node/pull/30199) was never merged). The build works today because:

- `--without-intl` sets `v8_enable_i18n_support=0`, which keeps `gen-regexp-special-case` — a V8 host tool that segfaults when linked with `-static` ([nodejs/node#30180](https://github.com/nodejs/node/issues/30180)) — out of the default `make` dependency graph, so it is never built or run.
- Node 18.0.0 removed the `test_crypto_engine` test fixture from the default build ([nodejs/node#41830](https://github.com/nodejs/node/pull/41830)). It is a shared library, and `-shared` cannot be combined with `-static` — the linker error in #41497. It is now only built when running the test suite.

This repo previously worked around both by stripping `-static` from those targets' generated makefiles after `./configure`, as suggested in [nodejs/node#41497 (comment)](https://github.com/nodejs/node/issues/41497#issuecomment-1013137433). Since Node 18, neither target participates in the default build, so the patch was removed.

If the static build fails again after dropping `--without-intl` — or after a future Node release reintroduces a shared library into the default build — expect a linker error like `crtbeginT.o: relocation ... can not be used when making a shared object` or a `gen-regexp-special-case` crash during `make`. The fix is to re-apply the patch: after `./configure`, strip `-static` from the affected generated makefiles (for example `out/tools/v8_gypfiles/gen-regexp-special-case.target.mk`) before running `make`.
9 changes: 5 additions & 4 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,10 @@ if [[ -d node-src ]]; then
fi
mv "node-v$NODE_VERSION/" node-src
cd node-src/
# --without-intl keeps V8's gen-regexp-special-case host tool out of the
# build (it crashes when statically linked), and Node 18+ no longer builds
# the test_crypto_engine shared library by default. Neither target needs
# its -static flag stripped anymore. See "Static builds and --without-intl"
# in README.md before changing these flags.
./configure --fully-static --enable-static --without-npm --without-intl
# See: https://github.com/nodejs/node/issues/41497#issuecomment-1013137433
for i in out/tools/v8_gypfiles/gen-regexp-special-case.target.mk out/test_crypto_engine.target.mk; do
sed -i.bak 's/-static//g' "$i" || true
done
make -j"$(getconf _NPROCESSORS_ONLN)" V=0