Skip to content

freeswitch/libnode-packaging

Repository files navigation

libnode-packaging

Builds Node.js as a shared library (libnode.dll) on Windows and packages the bundled V8 headers + import library into zip files that FreeSWITCH's mod_v8 can link against — a drop-in replacement for the retired standalone libv8 packages.

On Linux, mod_v8 builds against the distro's libnode-dev. There is no equivalent prebuilt package on Windows, so this repo builds one: it compiles a chosen Node.js version from source as a shared library and exports the full V8 + libplatform API from libnode.dll. Upload the resulting zips to a CDN and mod_v8's MSBuild props fetches them at build time.

What it produces

For Node v20.19.2 (which bundles V8 11.3):

libnode-20.19.2-headers.zip                 libnode-20.19.2/include/...   (all of deps/v8/include)
                                            libnode-20.19.2/LICENSE
libnode-20.19.2-binaries-x64-release.zip    libnode-20.19.2/binaries/x64/Release/{libnode.dll, libnode.lib, LICENSE}
libnode-20.19.2-binaries-x64-debug.zip      libnode-20.19.2/binaries/x64/Debug/{libnode.dll, libnode.lib, libnode.pdb, LICENSE}
SHA256SUMS.txt

This mirrors the old v8-<ver>-headers.zip / v8-<ver>-binaries-<plat>-<cfg>.zip layout, so the consuming MSBuild props is nearly identical (see examples/freeswitch/w32/).

Each zip includes Node's aggregated LICENSE (Node MIT + every bundled dependency: V8, OpenSSL, ICU, libuv, zlib, c-ares, nghttp2, …), which are statically linked into libnode.dll and must accompany the redistributed binary.

Repository layout

.github/workflows/build-libnode.yml   CI: build on a Windows runner, upload zip artifacts
build-libnode.ps1                     the build + package script (shared by CI and Docker)
Dockerfile                            Windows-container toolchain image (for local/offline builds)
examples/freeswitch/w32/              reference MSBuild props for wiring up mod_v8
  ├─ libnode.props                       links libnode.lib, sets USING_V8_SHARED, C++20, etc.
  └─ libnode-version.props               single place to set the libnode version
README.md

Building

Option A — GitHub Actions (recommended)

The Build libnode (Windows) workflow runs on a windows-2022 runner (which already has Visual Studio 2022); it installs the remaining prerequisites and runs build-libnode.ps1.

  • Manually: Actions tab → Build libnode (Windows)Run workflow, then enter the Node tag (e.g. v20.19.2), configs (Release Debug), and arch (x64).
  • By tag: push a tag like libnode-v20.19.2. The workflow builds it and also attaches the zips to a GitHub Release.

Download the zips from the run's Artifacts (or the Release), then upload them to your CDN.

A Release Debug build of both configurations takes roughly 1–2 hours on a hosted runner. Build only Release to halve it.

Option B — Local, via the Docker toolchain image

Useful for offline/air-gapped builds or reproducing CI locally. Requires Docker with Windows containers enabled.

# Build the toolchain image once (installs VS Build Tools + ClangCL, Python, NASM,
# Git, Rust). This layer is large and slow; subsequent version builds reuse it.
docker build -t libnode-packaging .

# Produce zips for a Node tag (writes to .\artifacts on the host):
docker run --rm --cpus 8 --memory 16g `
  -e NODE_VERSION=v20.19.2 `
  -v ${PWD}\artifacts:C:\artifacts `
  libnode-packaging

cmd.exe: replace ${PWD} with %cd%.

The host must run a Windows base image of equal-or-older build for process isolation (the Dockerfile defaults to servercore:ltsc2025); otherwise pass --build-arg WINDOWS_BASE=...:ltsc2022 or run with --isolation=hyperv.

Option C — Local, native

If you already have the Node.js Windows build prerequisites (VS 2022 + C++ workload, Python 3.13, NASM; Rust only for Node ≥ 26), just run the script directly:

$env:NODE_VERSION = 'v20.19.2'
$env:CONFIGS      = 'Release Debug'
$env:OUT_DIR      = "$PWD\artifacts"
.\build-libnode.ps1

Build parameters (env vars)

Var Default Notes
NODE_VERSION v20.19.2 Any Node.js git tag.
CONFIGS Release Debug Space-separated; set to Release to skip the slow/large Debug build.
ARCH x64 x64 or arm64. 32-bit Windows is unsupported by Node.
PKG_PREFIX libnode Zip/folder name prefix.
OUT_DIR C:\artifacts Where the zips are written.
NODE_REPO https://github.com/nodejs/node.git Override for a fork/mirror.

Choosing the version (important)

Build the same Node.js major version on Windows that your Linux libnode-dev ships, so the single mod_v8 source compiles on both platforms. Debian trixie ships libnode-dev 20.19.2 (Node 20 → V8 11.3), so this repo defaults to v20.19.2.

Newer Node lines remove V8 APIs that mod_v8 still uses (e.g. V8 13 / Node 24 removed FunctionCallbackInfo::Holder(); V8 ~12.9 removed AccessorGetterCallback and Template::SetAccessor()). Building Node 26 on Windows compiles+links fine but would require porting mod_v8 to the new API and supplying a matching libnode on Linux — so match the distro version unless you intend to upgrade both platforms.

Consuming the zips in mod_v8

Copy the two files from examples/freeswitch/w32/ into your FreeSWITCH build tree's w32\ directory and, in mod_v8.vcxproj, replace:

<Import Project="$(SolutionDir)\w32\v8.props" />

with:

<Import Project="$(SolutionDir)\w32\libnode.props" />

Set the target version in libnode-version.props, and (if your CDN differs from the default) edit the package= URLs in libnode.props to point at where you uploaded the zips. The props handle the three consumer-side requirements automatically:

  1. Link libnode.lib (instead of the three old v8*.dll.lib files).
  2. Define USING_V8_SHARED;USING_V8_PLATFORM_SHARED so the V8 headers import from libnode.dll.
  3. Compile as C++20 with /Zc:__cplusplus (required by the V8 headers).

How the build works

build-libnode.ps1:

  1. git clone --depth 1 --branch $NODE_VERSION the Node.js source.
  2. Patches common.gypi to add BUILDING_V8_PLATFORM_SHARED=1 so v8::platform (e.g. NewDefaultPlatform) is exported from libnode.dll. Node ≤ 22 compiles libplatform into libnode but doesn't dllexport it on Windows (on Linux it's exported via default visibility); without this patch embedders hit LNK2019 on NewDefaultPlatform. The patch is skipped on Node versions that already export it (e.g. 26).
  3. For each config: vcbuild.bat dll <release|debug> <arch>--sharedlibnode.dll + libnode.lib. The Windows shared build defines BUILDING_V8_SHARED=1, so the V8 + libplatform API is exported.
  4. Packages deps/v8/include → headers zip and the per-config libnode.* → binaries zips, plus Node's LICENSE and SHA256SUMS.txt.

Notes & gotchas

  • 32-bit Windows is not supported — Node only builds x64/arm64. The old libv8 win32 zips have no equivalent here.
  • Python: Node 20.x rejects Python 3.14; use 3.13 (accepted by Node 20→26).
  • Rust: only needed for Node ≥ 26 (Temporal builds deps/crates). Not needed for Node 20/22.
  • Refreshing a dev checkout: the props copy libnode.dll to the output dir only when it isn't already there (copy-once, like the original v8.props), so after publishing a new zip for the same version, delete the extracted libs\libnode-<ver>\ and the libnode.dll already copied next to the FreeSWITCH binary so they get re-fetched/re-copied.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors