macOS: always set MACOSX_DEPLOYMENT_TARGET (#28797)

* core: Make platform environment an instance not class method

In preparation for accessing data constructed in __init__.

* macos: set consistent macosx deployment target

This should silence numerous warnings from mixed gcc/macos toolchains.

* perl: prevent too-new deployment target version

```
*** Unexpected MACOSX_DEPLOYMENT_TARGET=11
***
*** Please either set it to a valid macOS version number (e.g., 10.15) or to empty.
```

* Stylin'

* Add deployment target overrides to failing autoconf packages

* Move configure workaround to base autoconf package

This reverts commit 3c119eaf8b4fb37c943d503beacf5ad2aa513d4c.

* Stylin'

* macos: add utility functions for SDK

These aren't yet used but should probably be added to spack debug
report.
This commit is contained in:
Seth R. Johnson
2022-02-10 18:22:30 -05:00
committed by GitHub
parent e502a264b5
commit 2fa6cd6d23
8 changed files with 83 additions and 38 deletions

View File

@@ -15,8 +15,10 @@
from spack.build_environment import InstallError from spack.build_environment import InstallError
from spack.directives import depends_on from spack.directives import depends_on
from spack.operating_systems.mac_os import macos_version
from spack.package import PackageBase, run_after, run_before from spack.package import PackageBase, run_after, run_before
from spack.util.executable import Executable from spack.util.executable import Executable
from spack.version import Version
class AutotoolsPackage(PackageBase): class AutotoolsPackage(PackageBase):
@@ -415,6 +417,13 @@ def configure(self, spec, prefix):
with working_dir(self.build_directory, create=True): with working_dir(self.build_directory, create=True):
inspect.getmodule(self).configure(*options) inspect.getmodule(self).configure(*options)
def setup_build_environment(self, env):
if (self.spec.platform == 'darwin'
and macos_version() >= Version('11')):
# Many configure files rely on matching '10.*' for macOS version
# detection and fail to add flags if it shows as version 11.
env.set('MACOSX_DEPLOYMENT_TARGET', '10.16')
def build(self, spec, prefix): def build(self, spec, prefix):
"""Makes the build targets specified by """Makes the build targets specified by
:py:attr:``~.AutotoolsPackage.build_targets`` :py:attr:``~.AutotoolsPackage.build_targets``

View File

@@ -4,6 +4,7 @@
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
import platform as py_platform import platform as py_platform
import re
from spack.util.executable import Executable from spack.util.executable import Executable
from spack.version import Version from spack.version import Version
@@ -18,11 +19,49 @@ def macos_version():
return Version(py_platform.mac_ver()[0]) return Version(py_platform.mac_ver()[0])
def macos_cltools_version():
"""Find the last installed version of the CommandLineTools.
The CLT version might only affect the build if it's selected as the macOS
SDK path.
"""
pkgutil = Executable('pkgutil')
output = pkgutil('--pkg-info=com.apple.pkg.CLTools_Executables',
output=str, fail_on_error=False)
match = re.search(r'version:\s*([0-9.]+)', output)
if match:
return Version(match.group(1))
# No CLTools installed by package manager: try Xcode
output = pkgutil('--pkg-info=com.apple.pkg.Xcode',
output=str, fail_on_error=False)
match = re.search(r'version:\s*([0-9.]+)', output)
if match:
return Version(match.group(1))
return None
def macos_sdk_path(): def macos_sdk_path():
"""Return SDK path """Return path to the active macOS SDK.
""" """
xcrun = Executable('xcrun') xcrun = Executable('xcrun')
return xcrun('--show-sdk-path', output=str, error=str).rstrip() return xcrun('--show-sdk-path', output=str).rstrip()
def macos_sdk_version():
"""Return the version of the active macOS SDK.
The SDK version usually corresponds to the installed Xcode version and can
affect how some packages (especially those that use the GUI) can fail. This
information should somehow be embedded into the future "compilers are
dependencies" feature.
The macOS deployment target cannot be greater than the SDK version, but
usually it can be at least a few versions less.
"""
xcrun = Executable('xcrun')
return Version(xcrun('--show-sdk-version', output=str).rstrip())
class MacOs(OperatingSystem): class MacOs(OperatingSystem):

View File

@@ -104,11 +104,11 @@ def operating_system(self, name):
return self.operating_sys.get(name, None) return self.operating_sys.get(name, None)
@classmethod def setup_platform_environment(self, pkg, env):
def setup_platform_environment(cls, pkg, env):
"""Subclass can override this method if it requires any """Subclass can override this method if it requires any
platform-specific build environment modifications. platform-specific build environment modifications.
""" """
pass
@classmethod @classmethod
def detect(cls): def detect(cls):

View File

@@ -84,8 +84,7 @@ def __init__(self):
if self.front_os != self.back_os: if self.front_os != self.back_os:
self.add_operating_system(self.front_os, front_distro) self.add_operating_system(self.front_os, front_distro)
@classmethod def setup_platform_environment(self, pkg, env):
def setup_platform_environment(cls, pkg, env):
""" Change the linker to default dynamic to be more """ Change the linker to default dynamic to be more
similar to linux/standard linker behavior similar to linux/standard linker behavior
""" """

View File

@@ -39,3 +39,25 @@ def __init__(self):
@classmethod @classmethod
def detect(cls): def detect(cls):
return 'darwin' in platform.system().lower() return 'darwin' in platform.system().lower()
def setup_platform_environment(self, pkg, env):
"""Specify deployment target based on target OS version.
The ``MACOSX_DEPLOYMENT_TARGET`` environment variable provides a
default ``-mmacosx-version-min`` argument for GCC and Clang compilers,
as well as the default value of ``CMAKE_OSX_DEPLOYMENT_TARGET`` for
CMake-based build systems. The default value for the deployment target
is usually the major version (11, 10.16, ...) for CMake and Clang, but
some versions of GCC specify a minor component as well (11.3), leading
to numerous link warnings about inconsistent or incompatible target
versions. Setting the environment variable ensures consistent versions
for an install toolchain target, even when the host macOS version
changes.
TODO: it may be necessary to add SYSTEM_VERSION_COMPAT for older
versions of the macosx developer tools; see
https://github.com/spack/spack/pull/26290 for discussion.
"""
os = self.operating_sys[pkg.spec.os]
env.set('MACOSX_DEPLOYMENT_TARGET', str(os.version))

View File

@@ -15,10 +15,10 @@
import re import re
from contextlib import contextmanager from contextlib import contextmanager
from llnl.util import tty
from llnl.util.lang import match_predicate from llnl.util.lang import match_predicate
from spack import * from spack import *
from spack.operating_systems.mac_os import macos_version
class Perl(Package): # Perl doesn't use Autotools, it should subclass Package class Perl(Package): # Perl doesn't use Autotools, it should subclass Package
@@ -297,24 +297,13 @@ def setup_dependent_package(self, module, dependent_spec):
def setup_build_environment(self, env): def setup_build_environment(self, env):
spec = self.spec spec = self.spec
# This is to avoid failures when using -mmacosx-version-min=11.1 if (spec.version <= Version('5.34.0')
# since not all Apple Clang compilers support that version range and spec.platform == 'darwin'
# See https://eclecticlight.co/2020/07/21/big-sur-is-both-10-16-and-11-0-its-official/ and macos_version() >= Version('10.16')):
# It seems that this is only necessary for older versions of the # Older perl versions reject MACOSX_DEPLOYMENT_TARGET=11 or higher
# command line tools rather than the xcode/clang version. # as "unexpected"; override the environment variable set by spack's
if spec.satisfies('os=bigsur'): # platforms.darwin .
pkgutil = Executable('pkgutil') env.set('MACOSX_DEPLOYMENT_TARGET', '10.16')
output = pkgutil('--pkg-info=com.apple.pkg.CLTools_Executables',
output=str, error=str, fail_on_error=False)
match = re.search(r'version:\s*([0-9.]+)', output)
if not match:
tty.warn('Failed to detect macOS command line tools version: '
+ output)
else:
if Version(match.group(1)) < Version('12'):
tty.warn("Setting SYSTEM_VERSION_COMPAT=1 due to older "
"command line tools version")
env.set('SYSTEM_VERSION_COMPAT', 1)
# This is how we tell perl the locations of bzip and zlib. # This is how we tell perl the locations of bzip and zlib.
env.set('BUILD_BZIP2', 0) env.set('BUILD_BZIP2', 0)

View File

@@ -3,9 +3,6 @@
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
import platform
class PyScipy(PythonPackage): class PyScipy(PythonPackage):
"""SciPy (pronounced "Sigh Pie") is a Scientific Library for Python. """SciPy (pronounced "Sigh Pie") is a Scientific Library for Python.
It provides many user-friendly and efficient numerical routines such It provides many user-friendly and efficient numerical routines such
@@ -104,12 +101,6 @@ def setup_build_environment(self, env):
if self.spec.satisfies('@:1.4 %gcc@10:'): if self.spec.satisfies('@:1.4 %gcc@10:'):
env.set('FFLAGS', '-fallow-argument-mismatch') env.set('FFLAGS', '-fallow-argument-mismatch')
# Kluge to get the gfortran linker to work correctly on Big
# Sur, at least until a gcc release > 10.2 is out with a fix.
# (There is a fix in their development tree.)
if platform.mac_ver()[0][0:2] == '11':
env.set('MACOSX_DEPLOYMENT_TARGET', '10.15')
def install_options(self, spec, prefix): def install_options(self, spec, prefix):
args = [] args = []
if spec.satisfies('%fj'): if spec.satisfies('%fj'):

View File

@@ -6,7 +6,6 @@
import glob import glob
import json import json
import os import os
import platform
import re import re
import sys import sys
@@ -416,9 +415,6 @@ def setup_build_environment(self, env):
'errors may occur when installing Python modules w/ ' 'errors may occur when installing Python modules w/ '
'mixed C/C++ source files.').format(self.version)) 'mixed C/C++ source files.').format(self.version))
# Need this to allow python build to find the Python installation.
env.set('MACOSX_DEPLOYMENT_TARGET', platform.mac_ver()[0])
env.unset('PYTHONPATH') env.unset('PYTHONPATH')
env.unset('PYTHONHOME') env.unset('PYTHONHOME')