From 1f1cd9b5ddc6e7464c1c7416bcce7007fe3bc88c Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Thu, 3 May 2018 18:06:45 -0400
Subject: [PATCH] Avoid overwriting unchanged output files in genbki.pl and
 Gen_fmgrtab.pl.

If a particular output file already exists with the contents it should
have, leave it alone, so that its mod timestamp is not advanced.

In builds using --enable-depend, this can avoid the need to recompile .c
files whose included files didn't actually change.  It's not clear whether
it saves much of anything for users of ccache; but the cost of doing the
file comparisons seems to be negligible, so we might as well do it.

For developers using the MSVC toolchain, this will create a regression:
msvc/Solution.pm will sometimes run genbki.pl or Gen_fmgrtab.pl
unnecessarily.  I'll look into fixing that separately.

Discussion: https://postgr.es/m/16925.1525376229@sss.pgh.pa.us
---
 src/backend/catalog/Catalog.pm | 23 ++++++++++++++++++++---
 1 file changed, 20 insertions(+), 3 deletions(-)

diff --git a/src/backend/catalog/Catalog.pm b/src/backend/catalog/Catalog.pm
index eee7cb3b90..2889cb9fb0 100644
--- a/src/backend/catalog/Catalog.pm
+++ b/src/backend/catalog/Catalog.pm
@@ -16,6 +16,9 @@ package Catalog;
 use strict;
 use warnings;
 
+use File::Compare;
+
+
 # Parses a catalog header file into a data structure describing the schema
 # of the catalog.
 sub ParseHeader
@@ -336,15 +339,29 @@ sub AddDefaultValues
 }
 
 # Rename temporary files to final names.
-# Call this function with the final file name and the .tmp extension
+# Call this function with the final file name and the .tmp extension.
+#
+# If the final file already exists and has identical contents, don't
+# overwrite it; this behavior avoids unnecessary recompiles due to
+# updating the mod date on unchanged header files.
+#
 # Note: recommended extension is ".tmp$$", so that parallel make steps
-# can't use the same temp files
+# can't use the same temp files.
 sub RenameTempFile
 {
 	my $final_name = shift;
 	my $extension  = shift;
 	my $temp_name  = $final_name . $extension;
-	rename($temp_name, $final_name) || die "rename: $temp_name: $!";
+
+	if (-f $final_name
+		&& compare($temp_name, $final_name) == 0)
+	{
+		unlink $temp_name || die "unlink: $temp_name: $!";
+	}
+	else
+	{
+		rename($temp_name, $final_name) || die "rename: $temp_name: $!";
+	}
 }
 
 # Find a symbol defined in a particular header file and extract the value.
-- 
2.40.0