From 4a366874d037d526b3cc02deef45aece338d354c Mon Sep 17 00:00:00 2001 From: Ronald Oussoren Date: Sun, 10 Jan 2021 10:49:22 +0100 Subject: [PATCH 1/3] Teach _osx_support about testing for arm64 compatibility in the compiler --- Lib/_osx_support.py | 50 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/Lib/_osx_support.py b/Lib/_osx_support.py index 37975fe8a3eefa..9993792a04acc3 100644 --- a/Lib/_osx_support.py +++ b/Lib/_osx_support.py @@ -185,14 +185,60 @@ def _supports_universal_builds(): osx_version = _get_system_version_tuple() return bool(osx_version >= (10, 4)) if osx_version else False +_cache_supports_arm64_builds = None def _supports_arm64_builds(): """Returns True if arm64 builds are supported on this system""" # There are two sets of systems supporting macOS/arm64 builds: # 1. macOS 11 and later, unconditionally # 2. macOS 10.15 with Xcode 12.2 or later - # For now the second category is ignored. + global _cache_supports_arm64_builds + if _cache_supports_arm64_builds is not None: + return _cache_supports_arm64_builds + osx_version = _get_system_version_tuple() - return osx_version >= (11, 0) if osx_version else False + if not osx_version: + _cache_supports_arm64_builds = False + return False + + if osx_version >= (11, 0): + # Xcode on macOS 11 supports arm64 + _cache_supports_arm64_builds = True + + elif osx_version < (10, 15): + # Xcode on 10.14 or earlier does not support + # arm64 + _cache_supports_arm64_builds = False + + else: + # We're on macOS 10.15, building for arm64 is possible + # only if Xcode 12 is present. + + # NOTE: Due to bootstrapping issues we cannot use + # subprocess or os.popen here. Tempfile is also not + # present during bootstrap + import contextlib + try: + import tempfile + fp = tempfile.NamedTemporaryFile(suffix=".c") + except ImportError: + fp = open("/tmp/_osx_support_%s.c"%( + os.getpid(),), "w+b") + + with contextlib.closing(fp): + fp.write(b"#include \n") + fp.write(b"int main(void) { exit(42); }\n") + fp.flush() + + status = os.system("cc -arch arm64 -o '%s' '%s'"%(fp.name[:-2], fp.name)) + try: + os.unlink(fp.name[:-2]) + except os.error: + pass + + _cache_supports_arm64_builds = (status == 0) + + assert _cache_supports_arm64_builds is not None + return _cache_supports_arm64_builds def _find_appropriate_compiler(_config_vars): From 7b66cb95e774f5cd6bbc3c7867440c8cbff99902 Mon Sep 17 00:00:00 2001 From: Ronald Oussoren Date: Sun, 10 Jan 2021 11:02:02 +0100 Subject: [PATCH 2/3] Add tests --- Lib/test/test__osx_support.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/Lib/test/test__osx_support.py b/Lib/test/test__osx_support.py index 907ae27d529b50..db700a0af3cdd2 100644 --- a/Lib/test/test__osx_support.py +++ b/Lib/test/test__osx_support.py @@ -7,6 +7,7 @@ import stat import sys import unittest +import unittest.mock from test.support import os_helper @@ -323,5 +324,35 @@ def test_get_platform_osx(self): result = _osx_support.get_platform_osx(config_vars, ' ', ' ', ' ') self.assertEqual(('macosx', '10.6', 'fat'), result) + def test__supports_arm64_builds(self): + _osx_support._cache_supports_arm64_builds = None + with self.subTest("macOS 10.14 or earlier"): + with unittest.mock.patch("_osx_support._get_system_version_tuple", return_value=(10, 14)): + self.assertFalse(_osx_support._supports_arm64_builds()) + + _osx_support._cache_supports_arm64_builds = None + with self.subTest("macOS 11 or later"): + with unittest.mock.patch("_osx_support._get_system_version_tuple", return_value=(11, 0)): + self.assertTrue(_osx_support._supports_arm64_builds()) + + _osx_support._cache_supports_arm64_builds = None + with self.subTest("macOS 10.15, recent SDK"): + with unittest.mock.patch("_osx_support._get_system_version_tuple", return_value=(10, 15)): + with unittest.mock.patch("os.system", return_value=0): + self.assertTrue(_osx_support._supports_arm64_builds()) + + _osx_support._cache_supports_arm64_builds = None + with self.subTest("macOS 10.15, old SDK"): + with unittest.mock.patch("_osx_support._get_system_version_tuple", return_value=(10, 15)): + with unittest.mock.patch("os.system", return_value=240): + self.assertFalse(_osx_support._supports_arm64_builds()) + + if _osx_support._get_system_version_tuple() >= (11, 0): + # Compiler is known to support arm64, mock the system version to ensure that + # the compiler probe is used + _osx_support._cache_supports_arm64_builds = None + with unittest.mock.patch("_osx_support._get_system_version_tuple", return_value=(10, 15)): + self.assertTrue(_osx_support._supports_arm64_builds()) + if __name__ == "__main__": unittest.main() From aee7c99874e5d0960977143c5b8b0ee9462a7ad8 Mon Sep 17 00:00:00 2001 From: Ronald Oussoren Date: Sun, 10 Jan 2021 11:04:37 +0100 Subject: [PATCH 3/3] Add burb --- .../NEWS.d/next/macOS/2021-01-10-11-04-33.bpo-42619._jWi3B.rst | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 Misc/NEWS.d/next/macOS/2021-01-10-11-04-33.bpo-42619._jWi3B.rst diff --git a/Misc/NEWS.d/next/macOS/2021-01-10-11-04-33.bpo-42619._jWi3B.rst b/Misc/NEWS.d/next/macOS/2021-01-10-11-04-33.bpo-42619._jWi3B.rst new file mode 100644 index 00000000000000..6762ad85e60fba --- /dev/null +++ b/Misc/NEWS.d/next/macOS/2021-01-10-11-04-33.bpo-42619._jWi3B.rst @@ -0,0 +1,3 @@ +Detect if the compiler supports building for arm64 when running on macOS +10.15. This enables building "universal2" extensions on macOS 10.15 when +Xcode 12.2 is installed.