Configuration: only produce a new configdata.pm if it has changed contents
authorRichard Levitte <levitte@openssl.org>
Mon, 23 Aug 2021 06:48:02 +0000 (08:48 +0200)
committerRichard Levitte <levitte@openssl.org>
Sun, 22 May 2022 15:33:08 +0000 (17:33 +0200)
The goal is to avoid having too much of the OpenSSL source rebuilt
because configdata.pm got a new time stamp.  The conditions for
updating configdata.pm are now:

1.  its time stamp is older than Configure's, or...
2.  its contents has changed.

Fixes #16377

Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Todd Short <todd.short@me.com>
(Merged from https://github.com/openssl/openssl/pull/16378)

Configure
configdata.pm.in

index a8dc0c37f61a6b8e071900a80e3d39eeeb0401ef..648fc0694efd94c994c061804d9a4760457d72eb 100755 (executable)
--- a/Configure
+++ b/Configure
@@ -17,6 +17,7 @@ use lib "$FindBin::Bin/util/perl";
 use File::Basename;
 use File::Spec::Functions qw/:DEFAULT abs2rel rel2abs splitdir/;
 use File::Path qw/mkpath/;
+use File::Compare qw(compare_text);
 use OpenSSL::fallback "$FindBin::Bin/external/perl/MODULES.txt";
 use OpenSSL::Glob;
 use OpenSSL::Template;
@@ -2761,7 +2762,7 @@ EOF
                                   keys %{$unified_info{htmldocs} // {}}),
                                  (map { @{$unified_info{mandocs}->{$_} // []} }
                                   keys %{$unified_info{mandocs} // {}}) ] );
-    foreach my $type (keys %loopinfo) {
+    foreach my $type (sort keys %loopinfo) {
         foreach my $product (@{$loopinfo{$type}}) {
             my %dirs = ();
             my $pd = dirname($product);
@@ -2782,7 +2783,7 @@ EOF
                 push @{$unified_info{dirinfo}->{$d}->{deps}}, $_
                     if $d ne $pd;
             }
-            foreach (keys %dirs) {
+            foreach (sort keys %dirs) {
                 push @{$unified_info{dirinfo}->{$_}->{products}->{$type}},
                     $product;
             }
@@ -2817,7 +2818,6 @@ my %template_vars = (
     user_crossable => \@user_crossable,
 );
 my $configdata_outname = 'configdata.pm';
-print "Creating $configdata_outname\n";
 open CONFIGDATA, ">$configdata_outname.new"
     or die "Trying to create $configdata_outname.new: $!";
 my $configdata_tmplname = cleanfile($srcdir, "configdata.pm.in", $blddir);
@@ -2833,19 +2833,57 @@ $configdata_tmpl->fill_in(
               ] }
 ) or die $Text::Template::ERROR;
 close CONFIGDATA;
-rename "$configdata_outname.new", $configdata_outname;
-if ($builder_platform eq 'unix') {
-    my $mode = (0755 & ~umask);
-    chmod $mode, 'configdata.pm'
-        or warn sprintf("WARNING: Couldn't change mode for 'configdata.pm' to 0%03o: %s\n",$mode,$!);
-}
-
-print "Running $configdata_outname\n";
-my $perlcmd = (quotify("maybeshell", $config{PERL}))[0];
-my $cmd = "$perlcmd $configdata_outname";
-#print STDERR "DEBUG[run_dofile]: \$cmd = $cmd\n";
-system($cmd);
-exit 1 if $? != 0;
+
+# When using stat() on Windows, we can get it to perform better by avoid some
+# data.  This doesn't affect the mtime field, so we're not losing anything...
+${^WIN32_SLOPPY_STAT} = 1;
+
+my $update_configdata = 0;
+my $run_configdata = 0;
+if (-f $configdata_outname) {
+    my $Configure_mtime = (stat($0))[9];
+    my $configdata_mtime = (stat($configdata_outname))[9];
+
+    # If this script was updated after the last configdata.pm, or if
+    # configdata.pm.new differs from configdata.pm, we update configdata.pm
+    if ($configdata_mtime < $Configure_mtime
+        || compare_text("$configdata_outname.new", $configdata_outname) != 0) {
+        $update_configdata = 1;
+    } else {
+        # If nothing has changed, let's just drop the new one and pretend
+        # like nothing happened
+        unlink "$configdata_outname.new";
+
+        # We still run configdata.pm if the build file (Makefile) is missing
+        $run_configdata = !( -f $target{build_file} );
+    }
+} else {
+    $update_configdata = 1;
+}
+
+if ($update_configdata) {
+    # If something did change, or there was no previous configdata.pm, we
+    # rename the new one, set permissions as needed, and run it.
+    rename "$configdata_outname.new", $configdata_outname;
+    if ($builder_platform eq 'unix') {
+        my $mode = (0755 & ~umask);
+        chmod $mode, 'configdata.pm'
+            or warn sprintf("WARNING: Couldn't change mode for 'configdata.pm' to 0%03o: %s\n",$mode,$!);
+    }
+    $run_configdata = 1;
+    print "Created $configdata_outname\n";
+}
+
+if ($run_configdata) {
+    print "Running $configdata_outname\n";
+    my $perlcmd = (quotify("maybeshell", $config{PERL}))[0];
+    my $cmd = "$perlcmd $configdata_outname";
+    #print STDERR "DEBUG[run_dofile]: \$cmd = $cmd\n";
+    system($cmd);
+    exit 1 if $? != 0;
+} else {
+    print "No changes in $configdata_outname, no need to run it\n";
+}
 
 $SIG{__DIE__} = $orig_death_handler;
 
index 2dfb7d8d7014c31624e8609e532abb0ca60cb370..cdaea868c1c299395684143adfd81c8105e1d9fc 100644 (file)
@@ -111,7 +111,6 @@ unless (caller) {
         use lib '{- sourcedir('Configurations') -}';
         use gentemplate;
 
-        print 'Creating ',$buildfile_template,"\n";
         open my $buildfile_template_fh, ">$buildfile_template"
             or die "Trying to create $buildfile_template: $!";
         foreach (@{$config{build_file_templates}}) {
@@ -120,6 +119,7 @@ unless (caller) {
         }
         gentemplate(output => $buildfile_template_fh, %gendata);
         close $buildfile_template_fh;
+        print 'Created ',$buildfile_template,"\n";
 
         use OpenSSL::Template;
 
@@ -131,7 +131,6 @@ use lib '{- $config{builddir} -}';
 use platform;
 _____
 
-        print 'Creating ',$buildfile,"\n";
         open BUILDFILE, ">$buildfile.new"
             or die "Trying to create $buildfile.new: $!";
         my $tmpl = OpenSSL::Template->new(TYPE => 'FILE',
@@ -148,6 +147,7 @@ _____
         close BUILDFILE;
         rename("$buildfile.new", $buildfile)
             or die "Trying to rename $buildfile.new to $buildfile: $!";
+        print 'Created ',$buildfile,"\n";
 
         exit(0);
     }