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
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 83 additions and 38 deletions

View File

@ -15,8 +15,10 @@
from spack.build_environment import InstallError
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.util.executable import Executable
from spack.version import Version
class AutotoolsPackage(PackageBase):
@ -415,6 +417,13 @@ def configure(self, spec, prefix):
with working_dir(self.build_directory, create=True):
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):
"""Makes the build targets specified by
:py:attr:``~.AutotoolsPackage.build_targets``

View File

@ -4,6 +4,7 @@
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import platform as py_platform
import re
from spack.util.executable import Executable
from spack.version import Version
@ -18,11 +19,49 @@ def macos_version():
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():
"""Return SDK path
"""Return path to the active macOS SDK.
"""
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):

View File

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

View File

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

View File

@ -39,3 +39,25 @@ def __init__(self):
@classmethod
def detect(cls):
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
from contextlib import contextmanager
from llnl.util import tty
from llnl.util.lang import match_predicate
from spack import *
from spack.operating_systems.mac_os import macos_version
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):
spec = self.spec
# This is to avoid failures when using -mmacosx-version-min=11.1
# since not all Apple Clang compilers support that version range
# See https://eclecticlight.co/2020/07/21/big-sur-is-both-10-16-and-11-0-its-official/
# It seems that this is only necessary for older versions of the
# command line tools rather than the xcode/clang version.
if spec.satisfies('os=bigsur'):
pkgutil = Executable('pkgutil')
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)
if (spec.version <= Version('5.34.0')
and spec.platform == 'darwin'
and macos_version() >= Version('10.16')):
# Older perl versions reject MACOSX_DEPLOYMENT_TARGET=11 or higher
# as "unexpected"; override the environment variable set by spack's
# platforms.darwin .
env.set('MACOSX_DEPLOYMENT_TARGET', '10.16')
# This is how we tell perl the locations of bzip and zlib.
env.set('BUILD_BZIP2', 0)

View File

@ -3,9 +3,6 @@
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import platform
class PyScipy(PythonPackage):
"""SciPy (pronounced "Sigh Pie") is a Scientific Library for Python.
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:'):
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):
args = []
if spec.satisfies('%fj'):

View File

@ -6,7 +6,6 @@
import glob
import json
import os
import platform
import re
import sys
@ -416,9 +415,6 @@ def setup_build_environment(self, env):
'errors may occur when installing Python modules w/ '
'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('PYTHONHOME')