autoconf: Log more stuff in log_environment

https://github.com/libsdl-org/autoconf/commit/d2b2a03a240be1d798612dec06e4889d98af8713

From d2b2a03a240be1d798612dec06e4889d98af8713 Mon Sep 17 00:00:00 2001
From: Zack Weinberg <[EMAIL REDACTED]>
Date: Sat, 18 Sep 2021 11:28:35 -0400
Subject: [PATCH] Log more stuff in log_environment

- Number of available CPUs
- On Linux, attempt to identify the build C library
  (currently only knows about glibc and musl)
---
 BuildCommon.pm  | 48 +++++++++++++++++++++++++++++
 log_environment | 80 +++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 126 insertions(+), 2 deletions(-)

diff --git a/BuildCommon.pm b/BuildCommon.pm
index 2f598c42..321442ce 100644
--- a/BuildCommon.pm
+++ b/BuildCommon.pm
@@ -33,6 +33,7 @@ BEGIN {
     @EXPORT_OK = qw(
         ensure_C_locale
         error
+        get_status_and_output
         popen
         run
         sh_split
@@ -181,6 +182,53 @@ sub popen {
     return $fh;
 }
 
+# Run, and log execution of, a subprocess.  Capture all of its output,
+# including both stdout and stderr.
+# @_ should be an argument vector.
+# If the subprocess exits normally (successful or unsuccessful),
+# returns a list whose first element is the exit status, followed by
+# all the lines of output from the subprocess (stdout and stderr are
+# intermingled).
+# If the subprocess could not be started because there is no such command,
+# returns (-1,).
+# Otherwise invocation_error/subprocess_error are called as appropriate.
+sub get_status_and_output {
+    die 'get_status_and_output: no command to execute'
+        if scalar(@_) == 0;
+    log_execution(@_);
+
+    my $pid = open(my $fh, '-|')
+        // invocation_error($_[0]);
+
+    if ($pid == 0) {
+        # child
+        open(STDERR, ">&STDOUT") or do {
+            print {*STDERR} "Can't dup STDOUT: $!\n";
+            exit(127);
+        };
+        { exec {$_[0]} @_; };
+        exit(126) if $!{ENOENT};
+        print {*STDERR} "exec $_[0] failed: $!\n";
+        exit(127);
+    }
+
+    # parent
+    my @lines = <$fh>;
+    close $fh or do {
+        if ($! != 0 || ($? & 0x7F) != 0) {
+            subprocess_error(@_);
+        }
+    };
+    my $status = $? >> 8;
+    if ($status == 127) {
+        subprocess_error(@_);
+    }
+    if ($status == 126) {
+        $status = -1;
+    }
+    return ($status, @lines);
+}
+
 # Force use of the C locale for this process and all subprocesses.
 # This is necessary because subprocesses' output may be locale-
 # dependent.  If the C.UTF-8 locale is available, it is used,
diff --git a/log_environment b/log_environment
index aa33591d..5aa13db1 100755
--- a/log_environment
+++ b/log_environment
@@ -24,7 +24,7 @@ use warnings FATAL => 'all';
 use utf8;
 use open qw(:utf8);
 
-use Cwd qw(cwd);
+use Cwd qw(getcwd);
 use FindBin ();
 use POSIX ();
 
@@ -32,11 +32,69 @@ use lib $FindBin::Bin;
 use BuildCommon qw(
     ensure_C_locale
     error
+    get_status_and_output
     run
     sh_quote
     which
 );
 
+# C library detection for Linux.  Algorithm from NPM package 'detect-libc',
+# <https://github.com/lovell/detect-libc>; currently only supports GNU and
+# musl libc.  If cross-compiling, the result is for the build environment,
+# not the host or target.  Does not use a C compiler.
+sub report_linux_libc {
+    # Try getconf.
+    my ($gcstat, @gcout) = get_status_and_output('getconf', 'GNU_LIBC_VERSION');
+    if ($gcstat == 0) {
+       my $gcver = $gcout[0];
+       chomp $gcver;
+       print "C library: $gcver\n\n";
+       return;
+    } elsif ($gcstat == -1) {
+       print "getconf: command not found\n";
+    }
+
+    # Try ldd --version.
+    my ($ldstat, @ldout) = get_status_and_output('ldd', '--version');
+    if ($ldstat == 0 || $ldstat == 1) {
+        my $ld1 = $ldout[0];
+        my $ld2 = $ldout[1];
+        if ($ld1 =~ /\bmusl\b/ia) {
+            $ld2 =~ s/^version\s+(\S+).*$/$1/i;
+            print "C library: musl $ld2\n\n";
+            return;
+        }
+        if ($ld2 =~ /^copyright.*free software foundation/i) {
+            $ld1 =~ s/^\S+\s+\([^\)]+\)\s+//;
+            $ld1 =~ s/\s+\z//;
+            print "C library: glibc $ld1\n\n";
+            return;
+        }
+
+        print "WARNING: ldd --version output not recognized:\n";
+        for my $line (@ldout) {
+            print '> ', $line;
+        }
+        print "\n";
+
+    } elsif ($ldstat == -1) {
+        print "ldd: command not found\n";
+    } else {
+        print "WARNING: ldd --version exit $ldstat\n";
+        for my $line (@ldout) {
+            print '> ', $line;
+        }
+        print "\n";
+    }
+
+    # detect-libc goes on to poke around in /lib, which I don't think is
+    # solid enough to base an actual detection on, but we may as well list
+    # contents that may be relevant.
+    print "C library: unknown\n\n";
+    run("ls", "-l", glob('/lib*/{libc[.-],ld[-.]*.so}*'));
+    print "\n";
+}
+
 sub report_machine {
     print "## Machine information:\n\n";
 
@@ -47,7 +105,25 @@ sub report_machine {
     print '$(uname -v) = ', sh_quote($version || 'unknown'), "\n";
     print "\n";
 
-    my $cwd = cwd();
+    if ($sysname eq 'Linux') {
+        report_linux_libc();
+    }
+
+    my ($npstat, @npout) = get_status_and_output('nproc');
+    if ($npstat == 0) {
+        chomp @npout;
+        print '$(nproc) = ', $npout[0], "\n";
+    } elsif ($npstat == -1) {
+        print "nproc: command not found\n";
+    } else {
+        print "nproc: exit $npstat\n";
+        for my $line (@npout) {
+            print '> ', $line;
+        }
+    }
+
+    print "\n";
+    my $cwd = getcwd();
     my $qcwd = sh_quote($cwd);
     print '$(pwd) = ', $qcwd, "\n";
     print "WARNING: working directory requires quotation\n"