diff --git a/NEWS b/NEWS
index 5efa8bad..e1eeb531 100644
--- a/NEWS
+++ b/NEWS
@@ -39,6 +39,11 @@ https://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=109&se
   https://www.gnu.org/software/gnulib/manual/html_node/C99-features-assumed.html
   The configure script should verify the compiler has these features.
 
+* New feature: The .NOTINTERMEDIATE special target
+  .NOTINTERMEDIATE Disables intermediate behavior for specific files, for all
+  files built using a pattern, or for the entire makefile.
+  Implementation provided by Dmitry Goncharov <dgoncharov@users.sf.net>
+
 * New feature: The $(let ...) function
   This function allows user-defined functions to define a set of local
   variables: values can be assigned to these variables from within the
diff --git a/doc/make.texi b/doc/make.texi
index 1464d0ca..db4d7e7a 100644
--- a/doc/make.texi
+++ b/doc/make.texi
@@ -2969,6 +2969,18 @@ The targets which @code{.INTERMEDIATE} depends on are treated as
 intermediate files.  @xref{Chained Rules, ,Chains of Implicit Rules}.
 @code{.INTERMEDIATE} with no prerequisites has no effect.
 
+@findex .NOTINTERMEDIATE
+@item .NOTINTERMEDIATE
+@cindex notintermediate targets, explicit
+
+Prerequisites of the special target @code{.NOTINTERMEDIATE} are never
+considered intermediate files.  @xref{Chained Rules, ,Chains of Implicit Rules}.
+@code{.NOTINTERMEDIATE} with no prerequisites causes all targets to be treated
+as notintermediate.
+
+If the prerequisite is a target pattern then targets that are built using that
+pattern rule are not considered intermediate.
+
 @findex .SECONDARY
 @item .SECONDARY
 @cindex secondary targets
@@ -9994,22 +10006,26 @@ file as intermediate by listing it as a prerequisite of the special target
 @code{.INTERMEDIATE}.  This takes effect even if the file is mentioned
 explicitly in some other way.
 
+Listing a file as a prerequisite of the special target
+@code{.NOTINTERMEDIATE} forces it to not be considered intermediate
+(just as any other mention of the file will do).  Also, listing the
+target pattern of a pattern rule as a prerequisite of
+@code{.NOTINTERMEDIATE} ensures that no targets generated using that
+pattern rule are considered intermediate.
+
+You can disable intermediate files completely in your makefile by
+providing @code{.NOTINTERMEDIATE} as a target with no prerequisites:
+in that case it applies to every file in the makefile.
+
 @cindex intermediate files, preserving
 @cindex preserving intermediate files
 @cindex secondary files
-You can prevent automatic deletion of an intermediate file by marking it
-as a @dfn{secondary} file.  To do this, list it as a prerequisite of the
-special target @code{.SECONDARY}.  When a file is secondary, @code{make}
-will not create the file merely because it does not already exist, but
-@code{make} does not automatically delete the file.  Marking a file as
-secondary also marks it as intermediate.
-
-You can list the target pattern of an implicit rule (such as @samp{%.o})
-as a prerequisite of the special target @code{.PRECIOUS} to preserve
-intermediate files made by implicit rules whose target patterns match
-that file's name; see @ref{Interrupts}.@refill
-@cindex preserving with @code{.PRECIOUS}
-@cindex @code{.PRECIOUS} intermediate files
+If you do not want @code{make} to create a file merely because it does
+not already exist, but you also do not want @code{make} to
+automatically delete the file, you can mark it as a @dfn{secondary}
+file.  To do this, list it as a prerequisite of the special target
+@code{.SECONDARY}.  Marking a file as secondary also marks it as
+intermediate.
 
 A chain can involve more than two implicit rules.  For example, it is
 possible to make a file @file{foo} from @file{RCS/foo.y,v} by running RCS,
diff --git a/src/file.c b/src/file.c
index 76503750..80696b8e 100644
--- a/src/file.c
+++ b/src/file.c
@@ -62,6 +62,9 @@ static struct hash_table files;
 /* Whether or not .SECONDARY with no prerequisites was given.  */
 static int all_secondary = 0;
 
+/* Whether or not .NOTINTERMEDIATE with no prerequisites was given.  */
+static int no_intermediates = 0;
+
 /* Access the hash table of all file records.
    lookup_file  given a name, return the struct file * for that name,
                 or nil if there is none.
@@ -327,13 +330,16 @@ rehash_file (struct file *from_file, const char *to_hname)
 
 #define MERGE(field) to_file->field |= from_file->field
   MERGE (precious);
+  MERGE (loaded);
   MERGE (tried_implicit);
   MERGE (updating);
   MERGE (updated);
   MERGE (is_target);
   MERGE (cmd_target);
   MERGE (phony);
-  MERGE (loaded);
+  /* Don't merge intermediate because this file might be pre-existing */
+  MERGE (secondary);
+  MERGE (notintermediate);
   MERGE (ignore_vpath);
 #undef MERGE
 
@@ -386,7 +392,7 @@ remove_intermediates (int sig)
            given on the command line, and it's either a -include makefile or
            it's not precious.  */
         if (f->intermediate && (f->dontcare || !f->precious)
-            && !f->secondary && !f->cmd_target)
+            && !f->secondary && !f->notintermediate && !f->cmd_target)
           {
             int status;
             if (f->update_status == us_none)
@@ -671,10 +677,18 @@ snap_file (const void *item, void *arg)
   if (!second_expansion)
     f->updating = 0;
 
-  /* If .SECONDARY is set with no deps, mark all targets as intermediate.  */
-  if (all_secondary)
+  /* More specific setting has priority.  */
+
+  /* If .SECONDARY is set with no deps, mark all targets as intermediate,
+     unless the target is a prereq of .NOTINTERMEDIATE.  */
+  if (all_secondary && !f->notintermediate)
     f->intermediate = 1;
 
+  /* If .NOTINTERMEDIATE is set with no deps, mark all targets as
+     notintermediate, unless the target is a prereq of .INTERMEDIATE.  */
+  if (no_intermediates && !f->intermediate && !f->secondary)
+      f->notintermediate = 1;
+
   /* If .EXTRA_PREREQS is set, add them as ignored by automatic variables.  */
   if (f->variables)
     prereqs = expand_extra_prereqs (lookup_variable_in_set (STRING_SIZE_TUPLE(".EXTRA_PREREQS"), f->variables->set));
@@ -776,11 +790,32 @@ snap_deps (void)
           f2->mtime_before_update = NONEXISTENT_MTIME;
         }
 
+  for (f = lookup_file (".NOTINTERMEDIATE"); f != 0; f = f->prev)
+    /* Mark .NOTINTERMEDIATE deps as notintermediate files.  */
+    if (f->deps)
+        for (d = f->deps; d != 0; d = d->next)
+          for (f2 = d->file; f2 != 0; f2 = f2->prev)
+            f2->notintermediate = 1;
+    /* .NOTINTERMEDIATE with no deps marks all files as notintermediate.  */
+    else
+      no_intermediates = 1;
+
+  /* The same file connot be both .INTERMEDIATE and .NOTINTERMEDIATE.
+     However, it is possible for a file to be .INTERMEDIATE and also match a
+     .NOTINTERMEDIATE pattern.  In that case, the intermediate file has
+     priority over the notintermediate pattern.  This priority is enforced by
+     pattern_search.  */
+
   for (f = lookup_file (".INTERMEDIATE"); f != 0; f = f->prev)
     /* Mark .INTERMEDIATE deps as intermediate files.  */
     for (d = f->deps; d != 0; d = d->next)
       for (f2 = d->file; f2 != 0; f2 = f2->prev)
-        f2->intermediate = 1;
+        if (f2->notintermediate)
+          OS (fatal, NILF,
+              _("%s cannot be both .NOTINTERMEDIATE and .INTERMEDIATE."),
+              f2->name);
+        else
+          f2->intermediate = 1;
     /* .INTERMEDIATE with no deps does nothing.
        Marking all files as intermediates is useless since the goal targets
        would be deleted after they are built.  */
@@ -790,11 +825,20 @@ snap_deps (void)
     if (f->deps)
       for (d = f->deps; d != 0; d = d->next)
         for (f2 = d->file; f2 != 0; f2 = f2->prev)
+        if (f2->notintermediate)
+          OS (fatal, NILF,
+              _("%s cannot be both .NOTINTERMEDIATE and .SECONDARY."),
+              f2->name);
+        else
           f2->intermediate = f2->secondary = 1;
     /* .SECONDARY with no deps listed marks *all* files that way.  */
     else
       all_secondary = 1;
 
+  if (no_intermediates && all_secondary)
+    O (fatal, NILF,
+       _(".NOTINTERMEDIATE and .SECONDARY are mutually exclusive"));
+
   f = lookup_file (".EXPORT_ALL_VARIABLES");
   if (f != 0 && f->is_target)
     export_all_variables = 1;
@@ -1038,6 +1082,10 @@ print_file (const void *item)
     printf (_("#  Implicit/static pattern stem: '%s'\n"), f->stem);
   if (f->intermediate)
     puts (_("#  File is an intermediate prerequisite."));
+  if (f->notintermediate)
+    puts (_("#  File is a prerequisite of .NOTINTERMEDIATE."));
+  if (f->secondary)
+    puts (_("#  File is secondary (prerequisite of .SECONDARY)."));
   if (f->also_make != 0)
     {
       const struct dep *d;
diff --git a/src/filedef.h b/src/filedef.h
index 972f8533..36701b76 100644
--- a/src/filedef.h
+++ b/src/filedef.h
@@ -98,6 +98,8 @@ struct file
     unsigned int intermediate:1;/* Nonzero if this is an intermediate file.  */
     unsigned int secondary:1;   /* Nonzero means remove_intermediates should
                                    not delete it.  */
+    unsigned int notintermediate:1; /* Nonzero means a file is a prereq to
+                                       .NOTINTERMEDIATE.  */
     unsigned int dontcare:1;    /* Nonzero if no complaint is to be made if
                                    this target cannot be remade.  */
     unsigned int ignore_vpath:1;/* Nonzero if we threw out VPATH name.  */
diff --git a/src/implicit.c b/src/implicit.c
index 5bbd6b79..dec61428 100644
--- a/src/implicit.c
+++ b/src/implicit.c
@@ -909,7 +909,8 @@ pattern_search (struct file *file, int archive,
           f->pat_searched = imf->pat_searched;
           f->also_make = imf->also_make;
           f->is_target = 1;
-          f->intermediate = !pat->is_explicit;
+          f->notintermediate = imf->notintermediate;
+          f->intermediate = !(pat->is_explicit || f->notintermediate);
           f->tried_implicit = 1;
 
           imf = lookup_file (pat->pattern);
@@ -976,11 +977,16 @@ pattern_search (struct file *file, int archive,
   file->cmds = rule->cmds;
   file->is_target = 1;
 
-  /* Set precious flag. */
+  /* Set precious and notintermediate flags. */
   {
     struct file *f = lookup_file (rule->targets[tryrules[foundrule].matches]);
-    if (f && f->precious)
-      file->precious = 1;
+    if (f)
+      {
+        if (f->precious)
+          file->precious = 1;
+        if (f->notintermediate)
+          file->notintermediate = 1;
+      }
   }
 
   /* If this rule builds other targets, too, put the others into FILE's
@@ -1009,8 +1015,13 @@ pattern_search (struct file *file, int archive,
 
           /* Set precious flag. */
           f = lookup_file (rule->targets[ri]);
-          if (f && f->precious)
-            new->file->precious = 1;
+          if (f)
+            {
+              if (f->precious)
+                new->file->precious = 1;
+              if (f->notintermediate)
+                new->file->notintermediate = 1;
+            }
 
           /* Set the is_target flag so that this file is not treated as
              intermediate by the pattern rule search algorithm and
diff --git a/src/main.c b/src/main.c
index 0f8a66dd..54060f2f 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1330,7 +1330,7 @@ main (int argc, char **argv, char **envp)
   {
     const char *features = "target-specific order-only second-expansion"
                            " else-if shortest-stem undefine oneshell nocomment"
-                           " grouped-target extra-prereqs"
+                           " grouped-target extra-prereqs notintermediate"
 #ifndef NO_ARCHIVES
                            " archives"
 #endif
diff --git a/tests/scripts/targets/NOTINTERMEDIATE b/tests/scripts/targets/NOTINTERMEDIATE
new file mode 100644
index 00000000..bf4cb52e
--- /dev/null
+++ b/tests/scripts/targets/NOTINTERMEDIATE
@@ -0,0 +1,119 @@
+#                                                                    -*-perl-*-
+
+$description = "Test the behaviour of the .NOTINTERMEDIATE target.";
+
+$details = "\
+Test the behavior of the .NOTINTERMEDIATE special target.\n";
+
+touch('hello.z');
+unlink('hello.x');
+
+
+# Test 1. A file which matches a .NOTINTERMEDIATE pattern is not intermediate.
+run_make_test(q!
+hello.z:
+%.z: %.x; touch $@
+%.x: ;
+.NOTINTERMEDIATE: %.q %.x
+!, '', "touch hello.z\n");
+
+# Test 2. .NOTINTERMEDIATE: %.q pattern has no effect on hello.x.
+touch('hello.z');
+run_make_test(q!
+hello.z:
+%.z: %.x; touch $@
+%.x: ;
+.NOTINTERMEDIATE: %.q
+!, '', "#MAKE#: 'hello.z' is up to date.\n");
+
+# Test 3. A file which is a prereq of .NOTINTERMEDIATE is not intermediate.
+run_make_test(q!
+hello.z:
+%.z: %.x; touch $@
+%.x: ;
+.NOTINTERMEDIATE: %.q hello.x
+!, '', "touch hello.z\n");
+
+# Test 4. .NOTINTERMEDIATE without prerequisites makes everything
+# notintermediate.
+unlink('hello.z');
+run_make_test(q!
+hello.z:
+%.z: %.x; touch $@
+%.x: ;
+.NOTINTERMEDIATE:
+!, '', "touch hello.z\n");
+
+# Test 5. Same file cannot be intermediate and notintermediate.
+run_make_test(q!
+.INTERMEDIATE: hello.x
+.NOTINTERMEDIATE: hello.x
+!, '', "#MAKE#: *** hello.x cannot be both .NOTINTERMEDIATE and .INTERMEDIATE..  Stop.\n", 512);
+
+# Test 6. Same file cannot be secondary and notintermediate.
+run_make_test(q!
+.SECONDARY: hello.x
+.NOTINTERMEDIATE: hello.x
+!, '', "#MAKE#: *** hello.x cannot be both .NOTINTERMEDIATE and .SECONDARY..  Stop.\n", 512);
+
+# Test 7. All .SECONDARY and all .NOTINTERMEDIATE are mutually exclusive.
+run_make_test(q!
+.SECONDARY:
+.NOTINTERMEDIATE:
+!, '', "#MAKE#: *** .NOTINTERMEDIATE and .SECONDARY are mutually exclusive.  Stop.\n", 512);
+
+# Test 8. .INTERMEDIATE file takes priority over a .NOTINTERMEDIATE pattern.
+unlink('hello.x');
+run_make_test(q!
+hello.z:
+%.z: %.x; touch $@
+%.x: ;
+.INTERMEDIATE: hello.x
+.NOTINTERMEDIATE: %.q %.x
+!, '', "#MAKE#: 'hello.z' is up to date.\n");
+
+# Test 9. Everything is notintermediate, except hello.x.
+unlink('hello.x');
+run_make_test(q!
+hello.z:
+%.z: %.x; touch $@
+%.x: ;
+.INTERMEDIATE: hello.x
+.NOTINTERMEDIATE:
+!, '', "#MAKE#: 'hello.z' is up to date.\n");
+
+# Test 10. Everything is notintermediate, except hello.x.
+unlink('hello.x');
+run_make_test(q!
+hello.z:
+%.z: %.x; touch $@
+%.x: ;
+.SECONDARY: hello.x
+.NOTINTERMEDIATE:
+!, '', "#MAKE#: 'hello.z' is up to date.\n");
+
+# Test 11. Everything is secondary, except %.q, hello.x.
+unlink('hello.x');
+run_make_test(q!
+hello.z:
+%.z: %.x; touch $@
+%.x: ;
+.NOTINTERMEDIATE: %.q hello.x
+.SECONDARY:
+!, '', "touch hello.z\n");
+
+# Test 12. Everything is secondary, except %.q %.x.
+unlink('hello.x');
+run_make_test(q!
+hello.z:
+%.z: %.x; touch $@
+%.x: ;
+.NOTINTERMEDIATE: %.q %.x
+.SECONDARY:
+!, '', "touch hello.z\n");
+
+
+
+unlink('hello.z');
+# This tells the test driver that the perl test script executed properly.
+1;