From f44ae4db5feccb8012c1b2df169bf87576ce760e Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Fri, 15 Jan 2021 11:28:51 -0500 Subject: [PATCH] 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 --- src/template/darwin | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/template/darwin b/src/template/darwin index 32414d21a9..1868c147cb 100644 --- a/src/template/darwin +++ b/src/template/darwin @@ -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"