Skip to content

Commit 2e5b9ee

Browse files
boybookclaude
andcommitted
fix: auto-detect MSYS2 hamlib for local Windows builds
build-shim.js now auto-detects MSYS2 MinGW64 hamlib installation and adapts linking strategy (static .a vs DLL) accordingly. build-all.js also probes MSYS2 paths before requiring HAMLIB_ROOT. This eliminates the need for manual build steps when developing locally with MSYS2-installed hamlib on Windows. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 583d909 commit 2e5b9ee

2 files changed

Lines changed: 78 additions & 8 deletions

File tree

scripts/build-all.js

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -189,11 +189,26 @@ async function setupHamlib() {
189189
return;
190190
}
191191

192+
// Auto-detect MSYS2 MinGW hamlib package
193+
const msys2Prefixes = [
194+
process.env.MINGW_PREFIX,
195+
'C:/msys64/mingw64', 'D:/msys64/mingw64',
196+
'C:/msys64/ucrt64', 'D:/msys64/ucrt64',
197+
].filter(Boolean);
198+
199+
for (const prefix of msys2Prefixes) {
200+
if (exists(path.join(prefix, 'include', 'hamlib', 'rig.h'))) {
201+
process.env.HAMLIB_ROOT = prefix;
202+
logger.succeedSpinner(`Using MSYS2 Hamlib: ${prefix}`);
203+
return;
204+
}
205+
}
206+
192207
logger.failSpinner('Hamlib not found');
193-
logger.warning('Please set HAMLIB_ROOT environment variable');
194-
logger.info('Download from: https://github.com/Hamlib/Hamlib/releases/download/4.6.5/hamlib-w64-4.6.5.zip');
195-
logger.info('Extract and set: HAMLIB_ROOT=C:\\path\\to\\hamlib-w64-4.6.5');
196-
throw new Error('HAMLIB_ROOT not set');
208+
logger.warning('Please set HAMLIB_ROOT environment variable or install hamlib via MSYS2 pacman');
209+
logger.info('Option 1: Download from https://github.com/Hamlib/Hamlib/releases and set HAMLIB_ROOT');
210+
logger.info('Option 2: pacman -S mingw-w64-x86_64-hamlib (in MSYS2 MinGW64 shell)');
211+
throw new Error('HAMLIB_ROOT not set and MSYS2 hamlib not found');
197212
} else {
198213
// Linux/macOS: Build from source
199214
logger.startSpinner('Building Hamlib from source...');

scripts/build-shim.js

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,28 @@ function ensureDir(dir) {
5252
}
5353
}
5454

55+
/**
56+
* Detect MSYS2 MinGW64 prefix by checking common installation paths.
57+
* Returns the prefix path (e.g., 'C:/msys64/mingw64') or null.
58+
*/
59+
function findMsys2Prefix() {
60+
const candidates = [
61+
process.env.MINGW_PREFIX, // Set inside MSYS2 MinGW shell
62+
'C:/msys64/mingw64',
63+
'D:/msys64/mingw64',
64+
'C:/msys64/ucrt64',
65+
'D:/msys64/ucrt64',
66+
].filter(Boolean);
67+
68+
for (const prefix of candidates) {
69+
const normalized = prefix.replace(/\\/g, '/');
70+
if (fs.existsSync(path.join(normalized, 'include', 'hamlib', 'rig.h'))) {
71+
return normalized;
72+
}
73+
}
74+
return null;
75+
}
76+
5577
function findHamlibInclude() {
5678
if (isWindows) {
5779
const hamlibRoot = process.env.HAMLIB_ROOT;
@@ -63,7 +85,10 @@ function findHamlibInclude() {
6385
for (const p of paths) {
6486
if (fs.existsSync(p)) return p;
6587
}
66-
throw new Error('Cannot find Hamlib include directory. Set HAMLIB_ROOT.');
88+
// Try MSYS2 MinGW as fallback
89+
const msys2 = findMsys2Prefix();
90+
if (msys2) return path.join(msys2, 'include');
91+
throw new Error('Cannot find Hamlib include directory. Set HAMLIB_ROOT or install via MSYS2 pacman.');
6792
}
6893

6994
const prefix = process.env.HAMLIB_PREFIX;
@@ -94,7 +119,10 @@ function findHamlibLib() {
94119
return path.join(hamlibRoot, 'lib');
95120
}
96121
}
97-
throw new Error('Cannot find Hamlib library directory. Set HAMLIB_ROOT.');
122+
// Try MSYS2 MinGW as fallback
123+
const msys2 = findMsys2Prefix();
124+
if (msys2) return path.join(msys2, 'lib');
125+
throw new Error('Cannot find Hamlib library directory. Set HAMLIB_ROOT or install via MSYS2 pacman.');
98126
}
99127

100128
const prefix = process.env.HAMLIB_PREFIX;
@@ -184,17 +212,44 @@ function buildWindows() {
184212
// Detect available Hamlib features
185213
const featureFlags = detectHamlibFeatures(includeDir);
186214

215+
// Determine link strategy: DLL (hamlib-w64 package) vs static (MSYS2 pacman)
216+
const libDirFwd = libDir.replace(/\\/g, '/');
217+
const hamlibDll = path.join(libDir, 'libhamlib-4.dll').replace(/\\/g, '/');
218+
const hamlibStaticLib = path.join(libDir, 'libhamlib.a').replace(/\\/g, '/');
219+
// Also check bin/ sibling (hamlib-w64 puts DLLs in bin/)
220+
const hamlibDllInBin = path.join(libDir, '..', 'bin', 'libhamlib-4.dll').replace(/\\/g, '/');
221+
222+
let linkArgs;
223+
if (fs.existsSync(hamlibDll)) {
224+
// DLL in lib dir
225+
linkArgs = [`-L${libDirFwd}`, '-lhamlib-4'];
226+
log('Linking against libhamlib-4.dll (from lib/)');
227+
} else if (fs.existsSync(hamlibDllInBin)) {
228+
// hamlib-w64 package: DLL in bin/, import lib in lib/
229+
const binDir = path.join(libDir, '..', 'bin').replace(/\\/g, '/');
230+
linkArgs = [`-L${binDir}`, `-L${libDirFwd}`, '-lhamlib-4'];
231+
log('Linking against libhamlib-4.dll (from bin/)');
232+
} else if (fs.existsSync(hamlibStaticLib)) {
233+
// MSYS2 pacman: static .a, need system libs
234+
linkArgs = [hamlibStaticLib, '-lws2_32', '-lwinmm', '-liphlpapi'];
235+
log('Linking statically against libhamlib.a (MSYS2)');
236+
} else {
237+
throw new Error(
238+
`Cannot find Hamlib library in ${libDir}. ` +
239+
'Expected libhamlib-4.dll or libhamlib.a.'
240+
);
241+
}
242+
187243
// Compile shim DLL with MinGW
188244
const gccCmd = [
189245
gcc,
190246
'-shared', '-O2',
191247
'-DHAMLIB_SHIM_BUILD',
192248
...featureFlags,
193249
`-I${includeDir.replace(/\\/g, '/')}`,
194-
`-L${libDir.replace(/\\/g, '/')}`,
195250
'-o', shimDll,
196251
shimSrc,
197-
'-lhamlib-4',
252+
...linkArgs,
198253
`-Wl,--output-def,${shimDef}`
199254
].join(' ');
200255

0 commit comments

Comments
 (0)