From 6c61c2695a6b657573acf189020f2cd435ce3ea4 Mon Sep 17 00:00:00 2001 From: "Seth R. Johnson" Date: Thu, 17 Feb 2022 22:50:41 -0500 Subject: darwin: robust macos version detection (#28991) Prefer `sw_vers` to `platform.mac_ver`. In anaconda3 installation, for example, the latter reports 10.16 on Monterey -- I think this is affected by how and where the python instance was built. Use MACOSX_DEPLOYMENT_TARGET if present to override the operating system choice. --- lib/spack/spack/operating_systems/mac_os.py | 52 ++++++++++++++++++++++++++--- lib/spack/spack/platforms/darwin.py | 4 +-- 2 files changed, 49 insertions(+), 7 deletions(-) (limited to 'lib') 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) diff --git a/lib/spack/spack/platforms/darwin.py b/lib/spack/spack/platforms/darwin.py index 23aa10d81b..c2d6bbb281 100644 --- a/lib/spack/spack/platforms/darwin.py +++ b/lib/spack/spack/platforms/darwin.py @@ -3,7 +3,7 @@ # # SPDX-License-Identifier: (Apache-2.0 OR MIT) -import platform +import platform as py_platform import archspec.cpu @@ -38,7 +38,7 @@ class Darwin(Platform): @classmethod def detect(cls): - return 'darwin' in platform.system().lower() + return 'darwin' in py_platform.system().lower() def setup_platform_environment(self, pkg, env): """Specify deployment target based on target OS version. -- cgit v1.2.3-70-g09d2