diff options
Diffstat (limited to 'lib/spack/spack/operating_systems/mac_os.py')
-rw-r--r-- | lib/spack/spack/operating_systems/mac_os.py | 52 |
1 files changed, 47 insertions, 5 deletions
diff --git a/lib/spack/spack/operating_systems/mac_os.py b/lib/spack/spack/operating_systems/mac_os.py index cb430449f2..a150134618 100644 --- a/lib/spack/spack/operating_systems/mac_os.py +++ b/lib/spack/spack/operating_systems/mac_os.py @@ -3,6 +3,7 @@ # # SPDX-License-Identifier: (Apache-2.0 OR MIT) +import os import platform as py_platform import re @@ -12,10 +13,49 @@ from spack.version import Version from ._operating_system import OperatingSystem -# FIXME: store versions inside OperatingSystem as a Version instead of string def macos_version(): - """temporary workaround to return a macOS version as a Version object + """Get the current macOS version as a version object. + + This has three mechanisms for determining the macOS version, which is used + for spack identification (the ``os`` in the spec's ``arch``) and indirectly + for setting the value of ``MACOSX_DEPLOYMENT_TARGET``, which affects the + ``minos`` value of the ``LC_BUILD_VERSION`` macho header. Mixing ``minos`` + values can lead to lots of linker warnings, and using a consistent version + (pinned to the major OS version) allows distribution across clients that + might be slightly behind. + + The version determination is made with three mechanisms in decreasing + priority: + + 1. The ``MACOSX_DEPLOYMENT_TARGET`` variable overrides the actual operating + system version, just like the value can be used to build for older macOS + targets on newer systems. Spack currently will truncate this value when + building packages, but at least the major version will be the same. + + 2. The system ``sw_vers`` command reports the actual operating system + version. + + 3. The Python ``platform.mac_ver`` function is a fallback if the operating + system identification fails, because some Python versions and/or + installations report the OS + on which Python was *built* rather than the one on which it is running. """ + env_ver = os.environ.get('MACOSX_DEPLOYMENT_TARGET', None) + if env_ver: + return Version(env_ver) + + try: + output = Executable('sw_vers')(output=str, fail_on_error=False) + except Exception: + # FileNotFoundError, or spack.util.executable.ProcessError + pass + else: + match = re.search(r'ProductVersion:\s*([0-9.]+)', output) + if match: + return Version(match.group(1)) + + # Fall back to python-reported version, which can be inaccurate around + # macOS 11 (e.g. showing 10.16 for macOS 12) return Version(py_platform.mac_ver()[0]) @@ -26,7 +66,7 @@ def macos_cltools_version(): SDK path. """ pkgutil = Executable('pkgutil') - output = pkgutil('--pkg-info=com.apple.pkg.CLTools_Executables', + 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: @@ -99,11 +139,13 @@ class MacOs(OperatingSystem): '12': 'monterey', } + version = macos_version() + # Big Sur versions go 11.0, 11.0.1, 11.1 (vs. prior versions that # only used the minor component) - part = 1 if macos_version() >= Version('11') else 2 + part = 1 if version >= Version('11') else 2 - mac_ver = str(macos_version().up_to(part)) + mac_ver = str(version.up_to(part)) name = mac_releases.get(mac_ver, "macos") super(MacOs, self).__init__(name, mac_ver) |