Skip to content

Commit f9f1f13

Browse files
committed
feat: add verification step for node.napi.node dependencies on Windows
1 parent 0ca8331 commit f9f1f13

File tree

2 files changed

+26
-88
lines changed

2 files changed

+26
-88
lines changed

.github/workflows/build.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,21 @@ jobs:
197197
node scripts/run-prebuildify.js
198198
node scripts/bundle-hamlib.js
199199
200+
- name: Verify node.napi.node dependencies (Windows)
201+
if: matrix.os == 'windows-latest'
202+
shell: pwsh
203+
run: |
204+
Write-Host "`n=== Verifying node.napi.node dependencies ===`n"
205+
$nodeBinary = "D:\a\node-hamlib\node-hamlib\prebuilds\win32-x64\node.napi.node"
206+
207+
if (Test-Path $nodeBinary) {
208+
Write-Host "Analyzing $nodeBinary`n"
209+
dumpbin /dependents $nodeBinary
210+
} else {
211+
Write-Error "node.napi.node not found!"
212+
exit 1
213+
}
214+
200215
- name: Generate prebuilds and bundle hamlib (Non-Windows)
201216
if: matrix.os != 'windows-latest'
202217
run: npm run prebuild:bundle

scripts/bundle-hamlib.js

Lines changed: 11 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,7 @@ function getDependenciesWinRecursive(dllPath, searchPaths = [], excludeSystemDll
504504

505505
const lines = result.split('\n');
506506
let inDepsSection = false;
507+
let depCount = 0;
507508

508509
for (const line of lines) {
509510
if (line.includes('has the following dependencies')) {
@@ -522,6 +523,7 @@ function getDependenciesWinRecursive(dllPath, searchPaths = [], excludeSystemDll
522523
const match = line.match(/^\s+(\S+\.dll)\s*$/i);
523524
if (!match) continue;
524525

526+
depCount++;
525527
const depName = match[1].toLowerCase();
526528

527529
// Skip if already visited
@@ -550,6 +552,11 @@ function getDependenciesWinRecursive(dllPath, searchPaths = [], excludeSystemDll
550552
// Recursively get dependencies of this DLL
551553
const subDeps = getDependenciesWinRecursive(depPath, searchPaths, excludeSystemDlls, visited);
552554
deps.push(...subDeps);
555+
} else {
556+
// Log missing dependencies for debugging
557+
if (depCount <= 5) { // Only log first few to avoid spam
558+
warn(`[Windows] Could not find ${depName} in search paths`);
559+
}
553560
}
554561
}
555562
} else {
@@ -564,74 +571,6 @@ function getDependenciesWinRecursive(dllPath, searchPaths = [], excludeSystemDll
564571
return deps;
565572
}
566573

567-
/**
568-
* Legacy fallback: Get dependencies by directory scanning (less reliable)
569-
* @param {string} binDir - Directory containing DLLs
570-
* @param {boolean} excludeSystemDlls - Whether to exclude system DLLs
571-
* @returns {Array<{name: string, path: string}>} Array of dependency objects
572-
*/
573-
function getDependenciesWinFallback(binDir, excludeSystemDlls = true) {
574-
// Windows system DLLs that should NOT be bundled
575-
const systemDllPatterns = [
576-
/^kernel32\.dll$/i,
577-
/^user32\.dll$/i,
578-
/^advapi32\.dll$/i,
579-
/^ws2_32\.dll$/i,
580-
/^winmm\.dll$/i,
581-
/^msvcrt\.dll$/i,
582-
/^msvcp\d+\.dll$/i,
583-
/^vcruntime\d+\.dll$/i,
584-
/^ucrtbase\.dll$/i,
585-
/^api-ms-win-.*\.dll$/i,
586-
/^ole32\.dll$/i,
587-
/^oleaut32\.dll$/i,
588-
/^shell32\.dll$/i,
589-
/^gdi32\.dll$/i,
590-
/^ntdll\.dll$/i,
591-
];
592-
593-
// Third-party DLL patterns we want to bundle
594-
const bundlePatterns = [
595-
/^libusb-1\.0.*\.dll$/i,
596-
/^libwinpthread-.*\.dll$/i,
597-
/^libgcc_s_.*\.dll$/i,
598-
/^libstdc\+\+-.*\.dll$/i,
599-
/^libiconv-.*\.dll$/i,
600-
/^libz.*\.dll$/i,
601-
/^zlib.*\.dll$/i,
602-
/^libindi.*\.dll$/i,
603-
];
604-
605-
try {
606-
if (!exists(binDir)) {
607-
return [];
608-
}
609-
610-
const files = fs.readdirSync(binDir).filter(n => /\.dll$/i.test(n));
611-
const deps = [];
612-
613-
for (const file of files) {
614-
// Skip if it's a system DLL
615-
if (excludeSystemDlls && systemDllPatterns.some(pattern => pattern.test(file))) {
616-
continue;
617-
}
618-
619-
// Include if it matches bundle patterns
620-
if (bundlePatterns.some(pattern => pattern.test(file))) {
621-
const fullPath = path.join(binDir, file);
622-
if (exists(fullPath)) {
623-
deps.push({ name: file, path: fullPath });
624-
}
625-
}
626-
}
627-
628-
return deps;
629-
} catch (e) {
630-
warn(`[Windows] Failed to scan dependencies in ${binDir}: ${e.message}`);
631-
return [];
632-
}
633-
}
634-
635574
/**
636575
* Bundle libhamlib and all its dependencies for Windows
637576
* @param {string} dir - Target prebuilds directory
@@ -699,31 +638,15 @@ function bundleWin(dir) {
699638
searchPaths.push(...systemPaths);
700639
}
701640

641+
log(`[Windows] Search paths: ${searchPaths.slice(0, 3).join('; ')}... (${searchPaths.length} total)`);
642+
702643
// Try recursive dependency analysis with dumpbin
703644
const deps = getDependenciesWinRecursive(dllPath, searchPaths, true, new Set());
704645

646+
log(`[Windows] Recursive analysis found ${deps.length} dependencies`);
647+
705648
if (deps.length === 0) {
706649
log('[Windows] No additional dependencies found (or all are system DLLs)');
707-
708-
// If dumpbin failed, try fallback method
709-
log('[Windows] Trying fallback pattern-based scan...');
710-
const fallbackDeps = getDependenciesWinFallback(binDir, true);
711-
712-
if (fallbackDeps.length > 0) {
713-
log(`[Windows] Found ${fallbackDeps.length} dependency(ies) via fallback method:`);
714-
715-
for (const dep of fallbackDeps) {
716-
log(`[Windows] - ${dep.name} (from ${dep.path})`);
717-
const depDest = path.join(dir, dep.name);
718-
719-
try {
720-
fs.copyFileSync(dep.path, depDest);
721-
log(`[Windows] ✓ Bundled to ${depDest}`);
722-
} catch (e) {
723-
warn(`[Windows] ✗ Failed to bundle ${dep.name}: ${e.message}`);
724-
}
725-
}
726-
}
727650
} else {
728651
// Remove duplicates (deps may have duplicate entries from recursion)
729652
const uniqueDeps = [];

0 commit comments

Comments
 (0)