Turns out there's a bug in gmake. From the GNU Make 3.82 source, function.c
, on or about line 2026:
while ((path = find_next_token (&p, &len)) != 0 ) {
/* ... */
if (
#ifdef HAVE_REALPATH
realpath (in, out)
#else
abspath (in, out) && stat (out, &st) == 0
#endif
)
{
/* ... */
}
}
}
/* ... */
Ocasionally, various calls to realpath
would get interrupted (EINTR
); nothing in this code checks errno
, so it just silently fails.
So, it wasn't that the file didn't exist, it was that $(realpath ...)
was being interrupted by a signal (presumably a child instance of gmake
signaling its completion or something similar) and this function wasn't designed to recover from that sort of event.
To fix the problem:
while ((path = find_next_token (&p, &len)) != 0 ) {
... becomes:
while ( errno == EINTR || (path = find_next_token (&p, &len)) != 0 ) {
The ||
will shortcut & prevent it from marching on to the next token.