Building master for native Windows with mingw-w64 (gcc 16.2.0, ucrt64) I hit
one real correctness bug and three portability issues. The first is worth
separating from the rest, because it is a genuine 64-bit fault rather than a
build-environment complaint.
1. time() writes past its destination on Windows — parse_command_line.c
long clock;
...
time(&clock);
fprintf(stdout, " Date: %s", ctime(&clock));
Windows is LLP64: long is 4 bytes while time_t is 8. So time(&clock)
writes 8 bytes into a 4-byte object, and ctime(&clock) then reads a time_t
from it. On Linux/macOS (LP64) both are 8 bytes, which is why this has never
shown up there.
gcc 16 rejects it outright:
parse_command_line.c:534:39: error: passing argument 1 of 'ctime' from incompatible pointer type
note: expected 'const time_t *' {aka 'const long long int *'} but argument is of type 'long int *'
⚠ Worth stressing: this one should not be silenced with
-Wno-incompatible-pointer-types. The diagnostic is correct and the write is
out of bounds.
Fix: declare it time_t clock;. That is correct on every platform —
time_t is the type time() is specified to take.
2. matherr collides with the mingw CRT — induct.c
induct.c defines the SunOS-era handler:
int matherr(exc)
struct exception *exc;
mingw's math.h does #define matherr _matherr and prototypes
int __cdecl _matherr(struct _exception *), so the definition collides:
induct.c:1242:19: error: argument 'exc' doesn't match prototype
math.h:278:15: note: prototype declaration
⚠ A -D on the command line cannot work around this — math.h is included
first and its macro wins, so the rename has to happen in the source.
The function's whole body is printf("Err in math\n"); return(0);, and modern
CRTs never invoke it. Suggested fix: guard it (#ifndef _WIN32) or rename
it; either is a one-line change.
3. resusage.h requires a POSIX header under -DFOUR
-DFOUR selects the BSD getrusage timers, which #include <sys/resource.h>
— absent on mingw. The header already handles this: with neither FOUR nor
FIVE defined its #else branch defines no-op timers and needs no POSIX
includes. So this is only a documentation matter — the Windows build simply
must not define FOUR — but it is the first thing anyone hits, and the
README/build notes recommend -DFOUR unconditionally.
4. sbrk and gethostname unresolved at link
Both are used for reporting only — the run header's host line and the memory
statistics. On mingw they do not exist, so the link fails after everything has
compiled. I linked a small shim returning a constant from sbrk and filling
gethostname from GetComputerNameA.
⚠ With that shim the reported memory figures are meaningless on Windows. If a
_WIN32 branch is ever added upstream I would suggest omitting the memory
report rather than printing a number that looks like a measurement.
Build-system note
The Makefile recurses with cd sparse; make. mingw ships the binary as
mingw32-make.exe only, so the sub-make dies with make: command not found
after every source file has compiled, which reads like a build failure rather
than a missing alias.
Result
With those four changes the binary builds and solves correctly. Sanity check —
a 10 mm × 1 mm² copper bar at 1 MHz:
Row 1: n1 to n2
Impedance matrix for frequency = 1e+06 1 x 1
0.000172414 +0.0358409j
R = 1.724e-4 Ω is exactly ρL/A for copper, and X = 0.0358 Ω is 5.7 nH, both as
expected for that geometry. The resulting executable is self-contained — it
runs with only C:\Windows\system32 on PATH.
Happy to open a PR for #1 alone if that is easier to review, since it is the
one that is a bug rather than a portability preference.
Building
masterfor native Windows with mingw-w64 (gcc 16.2.0, ucrt64) I hitone real correctness bug and three portability issues. The first is worth
separating from the rest, because it is a genuine 64-bit fault rather than a
build-environment complaint.
1.
time()writes past its destination on Windows —parse_command_line.cWindows is LLP64:
longis 4 bytes whiletime_tis 8. Sotime(&clock)writes 8 bytes into a 4-byte object, and
ctime(&clock)then reads atime_tfrom it. On Linux/macOS (LP64) both are 8 bytes, which is why this has never
shown up there.
gcc 16 rejects it outright:
⚠ Worth stressing: this one should not be silenced with
-Wno-incompatible-pointer-types. The diagnostic is correct and the write isout of bounds.
Fix: declare it
time_t clock;. That is correct on every platform —time_tis the typetime()is specified to take.2.
matherrcollides with the mingw CRT —induct.cinduct.cdefines the SunOS-era handler:mingw's
math.hdoes#define matherr _matherrand prototypesint __cdecl _matherr(struct _exception *), so the definition collides:⚠ A
-Don the command line cannot work around this —math.his includedfirst and its macro wins, so the rename has to happen in the source.
The function's whole body is
printf("Err in math\n"); return(0);, and modernCRTs never invoke it. Suggested fix: guard it (
#ifndef _WIN32) or renameit; either is a one-line change.
3.
resusage.hrequires a POSIX header under-DFOUR-DFOURselects the BSDgetrusagetimers, which#include <sys/resource.h>— absent on mingw. The header already handles this: with neither
FOURnorFIVEdefined its#elsebranch defines no-op timers and needs no POSIXincludes. So this is only a documentation matter — the Windows build simply
must not define
FOUR— but it is the first thing anyone hits, and theREADME/build notes recommend-DFOURunconditionally.4.
sbrkandgethostnameunresolved at linkBoth are used for reporting only — the run header's host line and the memory
statistics. On mingw they do not exist, so the link fails after everything has
compiled. I linked a small shim returning a constant from
sbrkand fillinggethostnamefromGetComputerNameA.⚠ With that shim the reported memory figures are meaningless on Windows. If a
_WIN32branch is ever added upstream I would suggest omitting the memoryreport rather than printing a number that looks like a measurement.
Build-system note
The Makefile recurses with
cd sparse; make. mingw ships the binary asmingw32-make.exeonly, so the sub-make dies withmake: command not foundafter every source file has compiled, which reads like a build failure rather
than a missing alias.
Result
With those four changes the binary builds and solves correctly. Sanity check —
a 10 mm × 1 mm² copper bar at 1 MHz:
R = 1.724e-4 Ω is exactly ρL/A for copper, and X = 0.0358 Ω is 5.7 nH, both as
expected for that geometry. The resulting executable is self-contained — it
runs with only
C:\Windows\system32on PATH.Happy to open a PR for #1 alone if that is easier to review, since it is the
one that is a bug rather than a portability preference.