Improve our heuristic for selecting PG_SYSROOT on macOS.

In cases where Xcode is newer than the underlying macOS version,
asking xcodebuild for the SDK path will produce a pointer to the
SDK shipped with Xcode, which may end up building code that does
not work on the underlying macOS version.  It appears that in
such cases, xcodebuild's answer also fails to match the default
behavior of Apple's compiler: assuming one has installed Xcode's
"command line tools", there will be an SDK for the OS's own version
in /Library/Developer/CommandLineTools, and the compiler will
default to using that.  This is all pretty poorly documented,
but experimentation suggests that "xcrun --show-sdk-path" gives
the sysroot path that the compiler is actually using, at least
in some cases.  Hence, try that first, but revert to xcodebuild
if xcrun fails (in very old Xcode, it is missing or lacks the
--show-sdk-path switch).

Also, "xcrun --show-sdk-path" may give a path that is valid but lacks
any OS version identifier.  We don't really want that, since most
of the motivation for wiring -isysroot into the build flags at all
is to ensure that all parts of a PG installation are built against
the same SDK, even when considering extensions built later and/or on
a different machine.  Insist on finding "N.N" in the directory name
before accepting the result.  (Adding "--sdk macosx" to the xcrun
call seems to produce the same answer as xcodebuild, but usually
more quickly because it's cached, so we also try that as a fallback.)

The core reason why we don't want to use Xcode's default SDK in cases
like this is that Apple's technology for introducing new syscalls
does not play nice with Autoconf: for example, configure will think
that preadv/pwritev exist when using a Big Sur SDK, even when building
on an older macOS version where they don't exist.  It'd be nice to
have a better solution to that problem, but this patch doesn't attempt
to fix that.

Per report from Sergey Shinderuk.  Back-patch to all supported versions.

Discussion: https://postgr.es/m/ed3b8e5d-0da8-6ebd-fd1c-e0ac80a4b204@postgrespro.ru
This commit is contained in:
Tom Lane 2021-01-15 11:28:51 -05:00
parent f9900df5f9
commit 4823621db3
1 changed files with 19 additions and 3 deletions

View File

@ -3,11 +3,27 @@
# Note: Darwin is the original code name for macOS, also known as OS X.
# We still use "darwin" as the port name, partly because config.guess does.
# Select where system include files should be sought.
# Select where system include files should be sought, if user didn't say.
if test x"$PG_SYSROOT" = x"" ; then
PG_SYSROOT=`xcodebuild -version -sdk macosx Path 2>/dev/null`
# This is far more complicated than it ought to be. We first ask
# "xcrun --show-sdk-path", which seems to match the default -isysroot
# setting of Apple's compilers. However, that may produce no result or
# a result that is not version-specific (i.e., just ".../SDKs/MacOSX.sdk").
# Using a version-specific sysroot seems desirable, so if there are not
# digits in the directory name, try "xcrun --sdk macosx --show-sdk-path";
# and if that still doesn't work, fall back to asking xcodebuild,
# which is often a good deal slower.
PG_SYSROOT=`xcrun --show-sdk-path 2>/dev/null`
if expr x"$PG_SYSROOT" : '.*[0-9]\.[0-9][^/]*$' >/dev/null ; then : okay
else
PG_SYSROOT=`xcrun --sdk macosx --show-sdk-path 2>/dev/null`
if expr x"$PG_SYSROOT" : '.*[0-9]\.[0-9][^/]*$' >/dev/null ; then : okay
else
PG_SYSROOT=`xcodebuild -version -sdk macosx Path 2>/dev/null`
fi
fi
fi
# Old xcodebuild versions may produce garbage, so validate the result.
# Validate the result: if it doesn't point at a directory, ignore it.
if test x"$PG_SYSROOT" != x"" ; then
if test -d "$PG_SYSROOT" ; then
CPPFLAGS="-isysroot $PG_SYSROOT $CPPFLAGS"