diff -Napru make-4.3.orig/src/dep.h make-4.3/src/dep.h
--- make-4.3.orig/src/dep.h	2020-01-19 21:32:59.000000000 +0100
+++ make-4.3/src/dep.h	2021-09-03 15:23:03.624908335 +0200
@@ -49,7 +49,8 @@ struct nameseq
     unsigned int ignore_mtime : 1;              \
     unsigned int staticpattern : 1;             \
     unsigned int need_2nd_expansion : 1;        \
-    unsigned int ignore_automatic_vars : 1
+    unsigned int ignore_automatic_vars : 1;     \
+    unsigned int wait_after : 1
 
 struct dep
   {
diff -Napru make-4.3.orig/src/file.c make-4.3/src/file.c
--- make-4.3.orig/src/file.c	2020-01-19 21:32:59.000000000 +0100
+++ make-4.3/src/file.c	2021-09-03 15:21:52.158237815 +0200
@@ -36,6 +36,47 @@ this program.  If not, see <http://www.g
    only work on files which have not yet been snapped. */
 int snapped_deps = 0;
 
+/* All file deps in the global namespace for which new_job() needs to wait
+ * until all commands have been processed (as via .NOTPARALLEL:). */
+static struct hash_table *a_file_wait;
+
+static unsigned long
+a_file_wait_hash_1 (const void *key)
+{
+  return_ISTRING_HASH_1 ((const char *) key);
+}
+
+static unsigned long
+a_file_wait_hash_2 (const void *key)
+{
+  return_ISTRING_HASH_2 ((const char *) key);
+}
+
+static int
+a_file_wait_hash_cmp (const void *x, const void *y)
+{
+  return_ISTRING_COMPARE ((const char *) x, (const char *) y);
+}
+
+static int
+a_file_wait_add(struct hash_table **htpp, const void *cvp)
+{
+  int rv;
+  void **slot;
+
+  if (a_file_wait == NULL)
+    {
+      a_file_wait = xmalloc (sizeof (*a_file_wait));
+      hash_init (a_file_wait, 256,
+        &a_file_wait_hash_1, &a_file_wait_hash_2, &a_file_wait_hash_cmp);
+    }
+
+  if ((rv = (*(slot = hash_find_slot (*htpp, cvp)) == NULL)))
+    hash_insert_at (*htpp, cvp, slot);
+
+  return rv;
+}
+
 /* Hash table of files the makefile knows how to make.  */
 
 static unsigned long
@@ -468,6 +509,28 @@ split_prereqs (char *p)
         ood->ignore_mtime = 1;
     }
 
+  /* At each occurrance of .WAIT we want to place a barrier. */
+  /* C99 */{
+    struct dep *dp, *tailp;
+
+    for (tailp = NULL, dp = new; dp != NULL;)
+      {
+        if (strcmp (dp->name, ".WAIT") != 0)
+          {
+            tailp = dp;
+            dp = dp->next;
+          }
+        else if (tailp == NULL) /* xxx warn user of nonsense? */
+          new = dp = dp->next;
+        else
+          {
+            tailp->wait_after = 1;
+            /* Take out .WAIT, noone else can deal with it. */
+            tailp->next = dp = dp->next;
+          }
+      }
+  }
+
   return new;
 }
 
@@ -1199,4 +1262,18 @@ init_hash_files (void)
   hash_init (&files, 1000, file_hash_1, file_hash_2, file_hash_cmp);
 }
 
+void
+file_wait_add (const char *name)
+{
+  assert (strcache_iscached (name));
+  (void) a_file_wait_add(&a_file_wait, name);
+}
+
+int
+file_wait_is_needed (const struct file *file)
+{
+  return (a_file_wait != NULL &&
+      hash_find_item (a_file_wait, file->name) != NULL);
+}
+
 /* EOF */
diff -Napru make-4.3.orig/src/filedef.h make-4.3/src/filedef.h
--- make-4.3.orig/src/filedef.h	2020-01-03 08:11:27.000000000 +0100
+++ make-4.3/src/filedef.h	2021-09-03 15:21:52.158237815 +0200
@@ -216,3 +216,7 @@ FILE_TIMESTAMP f_mtime (struct file *fil
 
 /* Have we snapped deps yet?  */
 extern int snapped_deps;
+
+/* .WAIT logic */
+void file_wait_add (const char *name);
+int file_wait_is_needed (const struct file *file);
diff -Napru make-4.3.orig/src/job.c make-4.3/src/job.c
--- make-4.3.orig/src/job.c	2020-01-19 21:32:59.000000000 +0100
+++ make-4.3/src/job.c	2021-09-03 15:21:52.158237815 +0200
@@ -1911,7 +1911,7 @@ new_job (struct file *file)
      (This will notice if there is in fact no recipe.)  */
   start_waiting_job (c);
 
-  if (job_slots == 1 || not_parallel)
+  if (job_slots == 1 || not_parallel || file_wait_is_needed (file))
     /* Since there is only one job slot, make things run linearly.
        Wait for the child to die, setting the state to 'cs_finished'.  */
     while (file->command_state == cs_running)
diff -Napru make-4.3.orig/src/read.c make-4.3/src/read.c
--- make-4.3.orig/src/read.c	2020-01-03 08:11:27.000000000 +0100
+++ make-4.3/src/read.c	2021-09-03 15:21:52.158237815 +0200
@@ -2275,7 +2275,7 @@ record_files (struct nameseq *filenames,
 
         f->also_make = cpy;
       }
-    }
+  }
 }
 
 /* Search STRING for an unquoted STOPMAP.
diff -Napru make-4.3.orig/src/remake.c make-4.3/src/remake.c
--- make-4.3.orig/src/remake.c	2020-01-03 08:11:27.000000000 +0100
+++ make-4.3/src/remake.c	2021-09-03 15:21:52.158237815 +0200
@@ -61,6 +61,9 @@ static struct dep *goal_dep;
    All files start with considered == 0.  */
 static unsigned int considered = 0;
 
+static void a_check_wait_state (struct file *fp);
+static void a_recur_wait_state (struct file *fp);
+
 static enum update_status update_file (struct file *file, unsigned int depth);
 static enum update_status update_file_1 (struct file *file, unsigned int depth);
 static enum update_status check_dep (struct file *file, unsigned int depth,
@@ -97,6 +100,15 @@ update_goal_chain (struct goaldep *goald
   /* Start a fresh batch of consideration.  */
   ++considered;
 
+  /* Recursively check whether any of the goals that really are to be worked
+   * requires .WAIT serialization, and actually enable that if so. */
+  /* C99 */{
+      struct dep *dp;
+
+      for (dp = goals; dp != NULL; dp = dp->next)
+        a_check_wait_state (dp->file);
+    }
+
   /* Update all the goals until they are all finished.  */
 
   while (goals != 0)
@@ -288,6 +300,40 @@ show_goal_error (void)
       }
 }
 
+/* Recursively check whether any of the goals that really are to be worked
+ * requires .WAIT serialization, and actually enable that if so. */
+static void
+a_check_wait_state (struct file *fp)
+{
+  struct dep *tailp, *dp;
+
+  for (tailp = dp = fp->deps; dp != NULL; dp = dp->next)
+    {
+      if (dp->wait_after)
+        {
+          struct dep *xp;
+
+          for (xp = tailp; xp != dp->next; xp = xp->next)
+            a_recur_wait_state (xp->file);
+
+	  tailp = dp->next;
+	}
+
+      a_check_wait_state(dp->file);
+    }
+}
+
+static void
+a_recur_wait_state (struct file *fp)
+{
+  struct dep *dp;
+
+  file_wait_add (fp->name);
+
+  for (dp = fp->deps; dp != NULL; dp = dp->next)
+    a_recur_wait_state (dp->file);
+}
+
 /* If FILE is not up to date, execute the commands for it.
    Return 0 if successful, non-0 if unsuccessful;
    but with some flag settings, just call 'exit' if unsuccessful.
