Skip to content

Commit 817c9b2

Browse files
committed
feat(build): harden native build configuration
- Add Linux FFmpeg fallback paths (/usr/include, /usr/local/include, /usr/lib, /usr/local/lib) - Add RPATH for macOS (@loader_path/../lib) and Linux ($ORIGIN/../lib) - Add MacPorts support (/opt/local/include, /opt/local/lib) - Add dynamic linking fallback when static fails on Linux - Add explicit error logging with [node-webcodecs] prefix - Add pkg-config output validation (empty check) - Add isPkgConfigAvailable() helper function - Add -Wpedantic and -Wshadow compiler warnings - Add Debug/Release configurations block - Add parallel compilation (-j max) to build scripts - Add node-gyp caching to CI workflow - Implement rpath mode in ffmpeg-paths.js Closes: harden-native-build-config
1 parent 19dcdf8 commit 817c9b2

16 files changed

Lines changed: 1337 additions & 21 deletions

File tree

.claude/skills/node-gyp.skill

7.22 KB
Binary file not shown.

.claude/skills/node-gyp/SKILL.md

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
---
2+
name: node-gyp
3+
description: Build and troubleshoot native Node.js addons using node-gyp. Use when working with native addon compilation, binding.gyp configuration, NODE_MODULE_VERSION mismatch errors, Electron native module rebuilds, or packages like bcrypt, node-sass, sqlite3, sharp. Covers platform-specific build setup (Linux/macOS/Windows), N-API configuration, cross-compilation, and pre-built binary distribution.
4+
---
5+
6+
# node-gyp: Native Node.js Addon Building
7+
8+
node-gyp compiles C/C++ code into native Node.js modules (.node files). It uses GYP configuration to create platform-specific build files.
9+
10+
**Build Pipeline:** binding.gyp → configure → platform build files → compile → .node binary
11+
12+
## Key Concepts
13+
14+
### Native Addons
15+
Binary modules providing Node.js bindings to C/C++ libraries. Compiled for specific:
16+
- **Node.js versions** (each has a MODULE_VERSION number)
17+
- **Platforms** (Linux, macOS, Windows)
18+
- **Architectures** (x64, arm64, ia32)
19+
20+
### binding.gyp
21+
Configuration file defining how to build your addon. JSON-like syntax with GYP features.
22+
23+
### N-API (Node-API)
24+
ABI-stable API for native addons. Modules work across Node.js versions without recompiling. **Always use for new projects.**
25+
26+
### Variable Expansion
27+
- `<(var)` - String expansion
28+
- `<@(var)` - List expansion
29+
- `<!(cmd)` - Command output as string
30+
- `<!@(cmd)` - Command output as list
31+
32+
## Platform Setup
33+
34+
**Linux:**
35+
```bash
36+
sudo apt-get install build-essential python3
37+
```
38+
39+
**macOS:**
40+
```bash
41+
xcode-select --install
42+
```
43+
44+
**Windows (choose one):**
45+
```bash
46+
# Option 1: Chocolatey (recommended)
47+
choco install python visualstudio2022-workload-vctools -y
48+
49+
# Option 2: npm (requires admin PowerShell)
50+
npm install --global --production windows-build-tools
51+
```
52+
53+
## Essential Commands
54+
55+
```bash
56+
# Clean rebuild (most common)
57+
node-gyp rebuild
58+
59+
# Individual steps (for debugging)
60+
node-gyp clean # Remove build artifacts
61+
node-gyp configure # Generate build files
62+
node-gyp build # Compile the addon
63+
64+
# Parallel compilation (faster)
65+
node-gyp rebuild -j max
66+
67+
# Debug build
68+
node-gyp rebuild --debug
69+
70+
# Download Node.js headers
71+
node-gyp install
72+
```
73+
74+
**When to use each:**
75+
- `rebuild` - Default choice, ensures clean build
76+
- `configure` then `build` - When iterating on binding.gyp
77+
- `clean` - When switching Node versions or architectures
78+
- `install` - When headers are missing or corrupted
79+
80+
## Basic binding.gyp
81+
82+
```json
83+
{
84+
"targets": [{
85+
"target_name": "addon",
86+
"sources": ["src/addon.cc"],
87+
"include_dirs": [
88+
"<!@(node -p \"require('node-addon-api').include\")"
89+
],
90+
"defines": ["NAPI_DISABLE_CPP_EXCEPTIONS"],
91+
"cflags!": ["-fno-exceptions"],
92+
"cflags_cc!": ["-fno-exceptions"]
93+
}]
94+
}
95+
```
96+
97+
**Key fields:**
98+
- `target_name` - Output filename (addon.node)
99+
- `sources` - C/C++ source files
100+
- `include_dirs` - Header search paths
101+
- `defines` - Preprocessor definitions
102+
- `cflags!` / `cflags_cc!` - Remove default flags (! means remove)
103+
104+
## N-API Setup (Recommended)
105+
106+
**package.json:**
107+
```json
108+
{
109+
"dependencies": {
110+
"node-addon-api": "^7.0.0"
111+
},
112+
"scripts": {
113+
"install": "node-gyp rebuild"
114+
}
115+
}
116+
```
117+
118+
**binding.gyp:**
119+
```json
120+
{
121+
"targets": [{
122+
"target_name": "addon",
123+
"sources": ["src/addon.cc"],
124+
"include_dirs": [
125+
"<!@(node -p \"require('node-addon-api').include\")"
126+
],
127+
"dependencies": [
128+
"<!(node -p \"require('node-addon-api').gyp\")"
129+
],
130+
"defines": ["NAPI_DISABLE_CPP_EXCEPTIONS"]
131+
}]
132+
}
133+
```
134+
135+
## Quick Troubleshooting Decision Tree
136+
137+
```
138+
Build failed?
139+
140+
├─ Python error?
141+
│ └─ npm config set python /usr/bin/python3
142+
143+
├─ Visual Studio error? (Windows)
144+
│ └─ node-gyp rebuild --msvs_version=2022
145+
146+
├─ NODE_MODULE_VERSION mismatch?
147+
│ └─ npm rebuild
148+
149+
├─ Architecture mismatch? (M1/M2 Mac)
150+
│ └─ rm -rf node_modules && npm install
151+
152+
├─ Missing headers?
153+
│ └─ node-gyp install
154+
155+
├─ Compilation/linking error?
156+
│ └─ Check binding.gyp libraries, run with --verbose
157+
158+
└─ Still failing?
159+
└─ See references/troubleshooting.md for detailed solutions
160+
```
161+
162+
## References
163+
164+
For detailed guidance on specific topics:
165+
166+
- **[references/troubleshooting.md](references/troubleshooting.md)** - Comprehensive troubleshooting for all common errors with symptoms, solutions, and explanations
167+
- **[references/advanced-patterns.md](references/advanced-patterns.md)** - Platform-specific configurations, Electron support, pre-built binaries, cross-compilation
168+
- **[references/best-practices.md](references/best-practices.md)** - Production recommendations, CI/CD setup, flags reference, related resources
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
# Advanced node-gyp Patterns
2+
3+
## Platform-Specific Configurations
4+
5+
Use conditions in binding.gyp for cross-platform support:
6+
7+
```json
8+
{
9+
"targets": [{
10+
"target_name": "addon",
11+
"sources": ["src/addon.cc"],
12+
"conditions": [
13+
["OS=='linux'", {
14+
"libraries": ["-lpthread"],
15+
"cflags": ["-fPIC"]
16+
}],
17+
["OS=='mac'", {
18+
"xcode_settings": {
19+
"GCC_ENABLE_CPP_EXCEPTIONS": "YES",
20+
"MACOSX_DEPLOYMENT_TARGET": "10.13"
21+
}
22+
}],
23+
["OS=='win'", {
24+
"msvs_settings": {
25+
"VCCLCompilerTool": {
26+
"ExceptionHandling": 1
27+
}
28+
}
29+
}]
30+
]
31+
}]
32+
}
33+
```
34+
35+
**Common platform conditions:**
36+
- `OS=='linux'` / `OS=='mac'` / `OS=='win'`
37+
- `target_arch=='x64'` / `target_arch=='arm64'`
38+
- `node_shared_openssl=='true'`
39+
40+
---
41+
42+
## Electron Support
43+
44+
### Using electron-rebuild (Recommended)
45+
46+
```bash
47+
npm install --save-dev electron-rebuild
48+
npx electron-rebuild
49+
```
50+
51+
**package.json script:**
52+
```json
53+
{
54+
"scripts": {
55+
"rebuild-electron": "electron-rebuild -f -w your-native-module"
56+
}
57+
}
58+
```
59+
60+
### Manual Approach
61+
62+
When electron-rebuild fails:
63+
64+
```bash
65+
node-gyp rebuild \
66+
--target=28.0.0 \
67+
--arch=x64 \
68+
--dist-url=https://electronjs.org/headers
69+
```
70+
71+
---
72+
73+
## Pre-built Binaries Distribution
74+
75+
Distribute pre-compiled binaries so users don't need build tools.
76+
77+
### Using prebuild (Recommended)
78+
79+
**package.json:**
80+
```json
81+
{
82+
"scripts": {
83+
"install": "prebuild-install || node-gyp rebuild",
84+
"prebuild": "prebuild --all --strip --verbose"
85+
},
86+
"devDependencies": {
87+
"prebuild": "^12.0.0"
88+
},
89+
"dependencies": {
90+
"prebuild-install": "^7.0.0"
91+
}
92+
}
93+
```
94+
95+
**Build binaries for all platforms:**
96+
```bash
97+
npx prebuild --all
98+
```
99+
100+
Creates binaries in `prebuilds/` that users download instead of compiling.
101+
102+
**Why use prebuild?** 80% of users don't have build tools installed. The `|| node-gyp rebuild` fallback handles edge cases.
103+
104+
---
105+
106+
## Cross-Compilation
107+
108+
Build for different architectures or Node.js versions:
109+
110+
```bash
111+
# Build for different architecture on M1/M2 Mac
112+
node-gyp rebuild --arch=x64
113+
114+
# Build for different Node.js version
115+
node-gyp rebuild --target=18.0.0
116+
117+
# Combine multiple options
118+
node-gyp rebuild --target=20.0.0 --arch=arm64 --dist-url=https://nodejs.org/dist
119+
```
120+
121+
---
122+
123+
## Graceful Fallback Pattern
124+
125+
Handle missing native dependencies:
126+
127+
```javascript
128+
// index.js
129+
let addon;
130+
try {
131+
addon = require('./build/Release/addon.node');
132+
} catch (err) {
133+
console.error('Native addon failed to load. Falling back to pure JS implementation.');
134+
addon = require('./lib/fallback.js');
135+
}
136+
module.exports = addon;
137+
```

0 commit comments

Comments
 (0)