Due to the way make is designed, not being able to read a makefile
authorespie <espie@openbsd.org>
Tue, 30 May 2023 04:42:21 +0000 (04:42 +0000)
committerespie <espie@openbsd.org>
Tue, 30 May 2023 04:42:21 +0000 (04:42 +0000)
is basically silent.

Record errors due to missing permissions and other oddities, and display them
when we error out due to lack of targets, as a quality-of-life diagnostic.

Based on a remark from sthen@, with some feedback and tweaks from op@

okay op@, kn@

usr.bin/make/engine.c
usr.bin/make/main.c
usr.bin/make/main.h
usr.bin/make/parse.c

index 410dcd0..d1967ea 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: engine.c,v 1.70 2021/10/25 19:54:29 kn Exp $ */
+/*     $OpenBSD: engine.c,v 1.71 2023/05/30 04:42:21 espie Exp $ */
 /*
  * Copyright (c) 2012 Marc Espie.
  *
@@ -84,6 +84,7 @@
 #include "extern.h"
 #include "lst.h"
 #include "timestamp.h"
+#include "main.h"
 #include "make.h"
 #include "pathnames.h"
 #include "error.h"
@@ -210,6 +211,7 @@ node_failure(GNode *gn)
                fflush(stdout);
        else {
                print_errors();
+               dump_unreadable();
                Punt(NULL);
        }
 }
index 64ea5d2..93b3867 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: main.c,v 1.129 2023/01/17 13:03:22 kn Exp $ */
+/*     $OpenBSD: main.c,v 1.130 2023/05/30 04:42:21 espie Exp $ */
 /*     $NetBSD: main.c,v 1.34 1997/03/24 20:56:36 gwr Exp $    */
 
 /*
@@ -87,6 +87,8 @@ bool          ignoreErrors;   /* -i flag */
 bool           beSilent;       /* -s flag */
 bool           dumpData;       /* -p flag */
 
+static LIST    unreadable;
+
 struct dirs {
        char *current;
        char *object;
@@ -826,6 +828,48 @@ main(int argc, char **argv)
                return 0;
 }
 
+struct unreadable {
+       char *fname;
+       int errcode;
+};
+
+void
+dump_unreadable(void)
+{
+       struct unreadable *u;
+
+       if (Lst_IsEmpty(&unreadable))
+               return;
+
+       fprintf(stderr, "Makefile(s) that couldn't be read:\n");
+
+       while ((u = Lst_Pop(&unreadable))) {
+               fprintf(stderr, "\t%s: %s\n", u->fname, strerror(u->errcode));
+               free(u->fname);
+               free(u);
+       }
+}
+
+static FILE *
+open_makefile(const char *fname)
+{
+       FILE *stream;
+       struct unreadable *u;
+
+       stream = fopen(fname, "r");
+       if (stream != NULL)
+               return stream;
+
+       if (errno != ENOENT) {
+               u = emalloc(sizeof *u);
+               u->fname = estrdup(fname);
+               u->errcode = errno;
+               Lst_AtEnd(&unreadable, u);
+       }
+
+       return NULL;
+}
+
 /*-
  * ReadMakefile  --
  *     Open and parse the given makefile.
@@ -848,14 +892,14 @@ ReadMakefile(void *p, void *q)
                Var_Set("MAKEFILE", "");
                Parse_File(estrdup("(stdin)"), stdin);
        } else {
-               if ((stream = fopen(fname, "r")) != NULL)
+               if ((stream = open_makefile(fname)) != NULL)
                        goto found;
                /* if we've chdir'd, rebuild the path name */
                if (d->current != d->object && *fname != '/') {
                        char *path;
 
                        path = Str_concat(d->current, fname, '/');
-                       if ((stream = fopen(path, "r")) == NULL)
+                       if ((stream = open_makefile(path)) == NULL)
                                free(path);
                        else {
                                fname = path;
@@ -866,7 +910,14 @@ ReadMakefile(void *p, void *q)
                name = Dir_FindFile(fname, userIncludePath);
                if (!name)
                        name = Dir_FindFile(fname, systemIncludePath);
-               if (!name || !(stream = fopen(name, "r")))
+               if (!name)
+                       return false;
+               /* do not try to open a file we already have, so that
+                * dump_unreadable() yields non-confusing results.
+                */
+               if (strcmp(name, fname) == 0)
+                       return false;
+               if ((stream = open_makefile(name)) == NULL)
                        return false;
                fname = name;
                /*
index 035de86..4106c60 100644 (file)
@@ -1,6 +1,6 @@
 #ifndef MAIN_H
 #define MAIN_H
-/*     $OpenBSD: main.h,v 1.6 2020/01/13 14:51:50 espie Exp $ */
+/*     $OpenBSD: main.h,v 1.7 2023/05/30 04:42:21 espie Exp $ */
 
 /*
  * Copyright (c) 2001 Marc Espie.
@@ -41,4 +41,8 @@ extern Lst    create;
 /* set_notparallel(): used to influence running mode from parse.c */
 extern void set_notparallel(void);
 
+/* dump_unreadable: in case of some errors, dump makefile names
+ * we found but are unable to read.
+ */
+extern void dump_unreadable(void);
 #endif
index 1b29df2..19f7c83 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: parse.c,v 1.134 2021/03/06 08:31:42 espie Exp $       */
+/*     $OpenBSD: parse.c,v 1.135 2023/05/30 04:42:21 espie Exp $       */
 /*     $NetBSD: parse.c,v 1.29 1997/03/10 21:20:04 christos Exp $      */
 
 /*
@@ -1696,6 +1696,7 @@ void
 Parse_MainName(Lst listmain)   /* result list */
 {
        if (mainNode == NULL) {
+               dump_unreadable();
                Punt("no target to make.");
                /*NOTREACHED*/
        } else if (mainNode->type & OP_DOUBLEDEP) {