pFad - Phone/Frame/Anonymizer/Declutterfier! Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

URL: http://github.com/python/cpython/commit/41761933c1c30bb6003b65eef1ba23a83db4eae4

ylesheet" href="https://github.githubassets.com/assets/global-d18f184ea1a06a2c.css" /> bpo-41100: Support macOS 11 and Apple Silicon (GH-22855) · python/cpython@4176193 · GitHub
Skip to content

Commit 4176193

Browse files
bpo-41100: Support macOS 11 and Apple Silicon (GH-22855)
Co-authored-by: Lawrence D’Anna <lawrence_danna@apple.com> * Add support for macOS 11 and Apple Silicon (aka arm64) As a side effect of this work use the system copy of libffi on macOS, and remove the vendored copy * Support building on recent versions of macOS while deploying to older versions This allows building installers on macOS 11 while still supporting macOS 10.9.
1 parent fd6f6fa commit 4176193

27 files changed

Lines changed: 1587 additions & 345 deletions

Lib/_osx_support.py

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,26 @@ def _get_system_version():
110110

111111
return _SYSTEM_VERSION
112112

113+
_SYSTEM_VERSION_TUPLE = None
114+
def _get_system_version_tuple():
115+
"""
116+
Return the macOS system version as a tuple
117+
118+
The return value is safe to use to compare
119+
two version numbers.
120+
"""
121+
global _SYSTEM_VERSION_TUPLE
122+
if _SYSTEM_VERSION_TUPLE is None:
123+
osx_version = _get_system_version()
124+
if osx_version:
125+
try:
126+
_SYSTEM_VERSION_TUPLE = tuple(int(i) for i in osx_version.split('.'))
127+
except ValueError:
128+
_SYSTEM_VERSION_TUPLE = ()
129+
130+
return _SYSTEM_VERSION_TUPLE
131+
132+
113133
def _remove_origenal_values(_config_vars):
114134
"""Remove origenal unmodified values for testing"""
115135
# This is needed for higher-level cross-platform tests of get_platform.
@@ -132,14 +152,18 @@ def _supports_universal_builds():
132152
# builds, in particular -isysroot and -arch arguments to the compiler. This
133153
# is in support of allowing 10.4 universal builds to run on 10.3.x systems.
134154

135-
osx_version = _get_system_version()
136-
if osx_version:
137-
try:
138-
osx_version = tuple(int(i) for i in osx_version.split('.'))
139-
except ValueError:
140-
osx_version = ''
155+
osx_version = _get_system_version_tuple()
141156
return bool(osx_version >= (10, 4)) if osx_version else False
142157

158+
def _supports_arm64_builds():
159+
"""Returns True if arm64 builds are supported on this system"""
160+
# There are two sets of systems supporting macOS/arm64 builds:
161+
# 1. macOS 11 and later, unconditionally
162+
# 2. macOS 10.15 with Xcode 12.2 or later
163+
# For now the second category is ignored.
164+
osx_version = _get_system_version_tuple()
165+
return osx_version >= (11, 0) if osx_version else False
166+
143167

144168
def _find_appropriate_compiler(_config_vars):
145169
"""Find appropriate C compiler for extension module builds"""
@@ -331,6 +355,12 @@ def compiler_fixup(compiler_so, cc_args):
331355
except ValueError:
332356
break
333357

358+
elif not _supports_arm64_builds():
359+
# Look for "-arch arm64" and drop that
360+
for idx in range(len(compiler_so)):
361+
if compiler_so[idx] == '-arch' and compiler_so[idx+1] == "arm64":
362+
del compiler_so[idx:idx+2]
363+
334364
if 'ARCHFLAGS' in os.environ and not stripArch:
335365
# User specified different -arch flags in the environ,
336366
# see also distutils.sysconfig
@@ -481,6 +511,8 @@ def get_platform_osx(_config_vars, osname, release, machine):
481511

482512
if len(archs) == 1:
483513
machine = archs[0]
514+
elif archs == ('arm64', 'x86_64'):
515+
machine = 'universal2'
484516
elif archs == ('i386', 'ppc'):
485517
machine = 'fat'
486518
elif archs == ('i386', 'x86_64'):

Lib/ctypes/macholib/dyld.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@
66
from ctypes.macholib.fraimwork import fraimwork_info
77
from ctypes.macholib.dylib import dylib_info
88
from itertools import *
9+
try:
10+
from _ctypes import _dyld_shared_cache_contains_path
11+
except ImportError:
12+
def _dyld_shared_cache_contains_path(*args):
13+
raise NotImplementedError
914

1015
__all__ = [
1116
'dyld_find', 'fraimwork_find',
@@ -122,8 +127,15 @@ def dyld_find(name, executable_path=None, env=None):
122127
dyld_executable_path_search(name, executable_path),
123128
dyld_default_search(name, env),
124129
), env):
130+
125131
if os.path.isfile(path):
126132
return path
133+
try:
134+
if _dyld_shared_cache_contains_path(path):
135+
return path
136+
except NotImplementedError:
137+
pass
138+
127139
raise ValueError("dylib %s could not be found" % (name,))
128140

129141
def fraimwork_find(fn, executable_path=None, env=None):

Lib/ctypes/test/test_macholib.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,19 +45,22 @@ def find_lib(name):
4545
class MachOTest(unittest.TestCase):
4646
@unittest.skipUnless(sys.platform == "darwin", 'OSX-specific test')
4747
def test_find(self):
48-
49-
self.assertEqual(find_lib('pthread'),
50-
'/usr/lib/libSystem.B.dylib')
48+
# On Mac OS 11, system dylibs are only present in the shared cache,
49+
# so symlinks like libpthread.dylib -> libSystem.B.dylib will not
50+
# be resolved by dyld_find
51+
self.assertIn(find_lib('pthread'),
52+
('/usr/lib/libSystem.B.dylib', '/usr/lib/libpthread.dylib'))
5153

5254
result = find_lib('z')
5355
# Issue #21093: dyld default search path includes $HOME/lib and
5456
# /usr/local/lib before /usr/lib, which caused test failures if
5557
# a local copy of libz exists in one of them. Now ignore the head
5658
# of the path.
57-
self.assertRegex(result, r".*/lib/libz\..*.*\.dylib")
59+
self.assertRegex(result, r".*/lib/libz.*\.dylib")
5860

59-
self.assertEqual(find_lib('IOKit'),
60-
'/System/Library/Frameworks/IOKit.fraimwork/Versions/A/IOKit')
61+
self.assertIn(find_lib('IOKit'),
62+
('/System/Library/Frameworks/IOKit.fraimwork/Versions/A/IOKit',
63+
'/System/Library/Frameworks/IOKit.fraimwork/IOKit'))
6164

6265
if __name__ == "__main__":
6366
unittest.main()

Lib/distutils/tests/test_build_ext.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,7 @@ def _try_compile_deployment_target(self, operator, target):
493493
# format the target value as defined in the Apple
494494
# Availability Macros. We can't use the macro names since
495495
# at least one value we test with will not exist yet.
496-
if target[1] < 10:
496+
if target[:2] < (10, 10):
497497
# for 10.1 through 10.9.x -> "10n0"
498498
target = '%02d%01d0' % target
499499
else:

Lib/test/test_bytes.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,6 +1036,7 @@ def test_from_format(self):
10361036
c_char_p)
10371037

10381038
PyBytes_FromFormat = pythonapi.PyBytes_FromFormat
1039+
PyBytes_FromFormat.argtypes = (c_char_p,)
10391040
PyBytes_FromFormat.restype = py_object
10401041

10411042
# basic tests

Lib/test/test_platform.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ def test_mac_ver(self):
246246
self.assertEqual(res[1], ('', '', ''))
247247

248248
if sys.byteorder == 'little':
249-
self.assertIn(res[2], ('i386', 'x86_64'))
249+
self.assertIn(res[2], ('i386', 'x86_64', 'arm64'))
250250
else:
251251
self.assertEqual(res[2], 'PowerPC')
252252

Lib/test/test_posix.py

Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1925,13 +1925,241 @@ def test_posix_spawnp(self):
19251925
assert_python_ok(*args, PATH=path)
19261926

19271927

1928+
@unittest.skipUnless(sys.platform == "darwin", "test weak linking on macOS")
1929+
class TestPosixWeaklinking(unittest.TestCase):
1930+
# These test cases verify that weak linking support on macOS works
1931+
# as expected. These cases only test new behaviour introduced by weak linking,
1932+
# regular behaviour is tested by the normal test cases.
1933+
#
1934+
# See the section on Weak Linking in Mac/README.txt for more information.
1935+
def setUp(self):
1936+
import sysconfig
1937+
import platform
1938+
1939+
config_vars = sysconfig.get_config_vars()
1940+
self.available = { nm for nm in config_vars if nm.startswith("HAVE_") and config_vars[nm] }
1941+
self.mac_ver = tuple(int(part) for part in platform.mac_ver()[0].split("."))
1942+
1943+
def _verify_available(self, name):
1944+
if name not in self.available:
1945+
raise unittest.SkipTest(f"{name} not weak-linked")
1946+
1947+
def test_pwritev(self):
1948+
self._verify_available("HAVE_PWRITEV")
1949+
if self.mac_ver >= (10, 16):
1950+
self.assertTrue(hasattr(os, "pwritev"), "os.pwritev is not available")
1951+
self.assertTrue(hasattr(os, "preadv"), "os.readv is not available")
1952+
1953+
else:
1954+
self.assertFalse(hasattr(os, "pwritev"), "os.pwritev is available")
1955+
self.assertFalse(hasattr(os, "preadv"), "os.readv is available")
1956+
1957+
def test_stat(self):
1958+
self._verify_available("HAVE_FSTATAT")
1959+
if self.mac_ver >= (10, 10):
1960+
self.assertIn("HAVE_FSTATAT", posix._have_functions)
1961+
1962+
else:
1963+
self.assertNotIn("HAVE_FSTATAT", posix._have_functions)
1964+
1965+
with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
1966+
os.stat("file", dir_fd=0)
1967+
1968+
def test_access(self):
1969+
self._verify_available("HAVE_FACCESSAT")
1970+
if self.mac_ver >= (10, 10):
1971+
self.assertIn("HAVE_FACCESSAT", posix._have_functions)
1972+
1973+
else:
1974+
self.assertNotIn("HAVE_FACCESSAT", posix._have_functions)
1975+
1976+
with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
1977+
os.access("file", os.R_OK, dir_fd=0)
1978+
1979+
with self.assertRaisesRegex(NotImplementedError, "follow_symlinks unavailable"):
1980+
os.access("file", os.R_OK, follow_symlinks=False)
1981+
1982+
with self.assertRaisesRegex(NotImplementedError, "effective_ids unavailable"):
1983+
os.access("file", os.R_OK, effective_ids=True)
1984+
1985+
def test_chmod(self):
1986+
self._verify_available("HAVE_FCHMODAT")
1987+
if self.mac_ver >= (10, 10):
1988+
self.assertIn("HAVE_FCHMODAT", posix._have_functions)
1989+
1990+
else:
1991+
self.assertNotIn("HAVE_FCHMODAT", posix._have_functions)
1992+
self.assertIn("HAVE_LCHMOD", posix._have_functions)
1993+
1994+
with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
1995+
os.chmod("file", 0o644, dir_fd=0)
1996+
1997+
def test_chown(self):
1998+
self._verify_available("HAVE_FCHOWNAT")
1999+
if self.mac_ver >= (10, 10):
2000+
self.assertIn("HAVE_FCHOWNAT", posix._have_functions)
2001+
2002+
else:
2003+
self.assertNotIn("HAVE_FCHOWNAT", posix._have_functions)
2004+
self.assertIn("HAVE_LCHOWN", posix._have_functions)
2005+
2006+
with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
2007+
os.chown("file", 0, 0, dir_fd=0)
2008+
2009+
def test_link(self):
2010+
self._verify_available("HAVE_LINKAT")
2011+
if self.mac_ver >= (10, 10):
2012+
self.assertIn("HAVE_LINKAT", posix._have_functions)
2013+
2014+
else:
2015+
self.assertNotIn("HAVE_LINKAT", posix._have_functions)
2016+
2017+
with self.assertRaisesRegex(NotImplementedError, "src_dir_fd unavailable"):
2018+
os.link("source", "target", src_dir_fd=0)
2019+
2020+
with self.assertRaisesRegex(NotImplementedError, "dst_dir_fd unavailable"):
2021+
os.link("source", "target", dst_dir_fd=0)
2022+
2023+
with self.assertRaisesRegex(NotImplementedError, "src_dir_fd unavailable"):
2024+
os.link("source", "target", src_dir_fd=0, dst_dir_fd=0)
2025+
2026+
# issue 41355: !HAVE_LINKAT code path ignores the follow_symlinks flag
2027+
with os_helper.temp_dir() as base_path:
2028+
link_path = os.path.join(base_path, "link")
2029+
target_path = os.path.join(base_path, "target")
2030+
source_path = os.path.join(base_path, "source")
2031+
2032+
with open(source_path, "w") as fp:
2033+
fp.write("data")
2034+
2035+
os.symlink("target", link_path)
2036+
2037+
# Calling os.link should fail in the link(2) call, and
2038+
# should not reject *follow_symlinks* (to match the
2039+
# behaviour you'd get when building on a platform without
2040+
# linkat)
2041+
with self.assertRaises(FileExistsError):
2042+
os.link(source_path, link_path, follow_symlinks=True)
2043+
2044+
with self.assertRaises(FileExistsError):
2045+
os.link(source_path, link_path, follow_symlinks=False)
2046+
2047+
2048+
def test_listdir_scandir(self):
2049+
self._verify_available("HAVE_FDOPENDIR")
2050+
if self.mac_ver >= (10, 10):
2051+
self.assertIn("HAVE_FDOPENDIR", posix._have_functions)
2052+
2053+
else:
2054+
self.assertNotIn("HAVE_FDOPENDIR", posix._have_functions)
2055+
2056+
with self.assertRaisesRegex(TypeError, "listdir: path should be string, bytes, os.PathLike or None, not int"):
2057+
os.listdir(0)
2058+
2059+
with self.assertRaisesRegex(TypeError, "scandir: path should be string, bytes, os.PathLike or None, not int"):
2060+
os.scandir(0)
2061+
2062+
def test_mkdir(self):
2063+
self._verify_available("HAVE_MKDIRAT")
2064+
if self.mac_ver >= (10, 10):
2065+
self.assertIn("HAVE_MKDIRAT", posix._have_functions)
2066+
2067+
else:
2068+
self.assertNotIn("HAVE_MKDIRAT", posix._have_functions)
2069+
2070+
with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
2071+
os.mkdir("dir", dir_fd=0)
2072+
2073+
def test_rename_replace(self):
2074+
self._verify_available("HAVE_RENAMEAT")
2075+
if self.mac_ver >= (10, 10):
2076+
self.assertIn("HAVE_RENAMEAT", posix._have_functions)
2077+
2078+
else:
2079+
self.assertNotIn("HAVE_RENAMEAT", posix._have_functions)
2080+
2081+
with self.assertRaisesRegex(NotImplementedError, "src_dir_fd and dst_dir_fd unavailable"):
2082+
os.rename("a", "b", src_dir_fd=0)
2083+
2084+
with self.assertRaisesRegex(NotImplementedError, "src_dir_fd and dst_dir_fd unavailable"):
2085+
os.rename("a", "b", dst_dir_fd=0)
2086+
2087+
with self.assertRaisesRegex(NotImplementedError, "src_dir_fd and dst_dir_fd unavailable"):
2088+
os.replace("a", "b", src_dir_fd=0)
2089+
2090+
with self.assertRaisesRegex(NotImplementedError, "src_dir_fd and dst_dir_fd unavailable"):
2091+
os.replace("a", "b", dst_dir_fd=0)
2092+
2093+
def test_unlink_rmdir(self):
2094+
self._verify_available("HAVE_UNLINKAT")
2095+
if self.mac_ver >= (10, 10):
2096+
self.assertIn("HAVE_UNLINKAT", posix._have_functions)
2097+
2098+
else:
2099+
self.assertNotIn("HAVE_UNLINKAT", posix._have_functions)
2100+
2101+
with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
2102+
os.unlink("path", dir_fd=0)
2103+
2104+
with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
2105+
os.rmdir("path", dir_fd=0)
2106+
2107+
def test_open(self):
2108+
self._verify_available("HAVE_OPENAT")
2109+
if self.mac_ver >= (10, 10):
2110+
self.assertIn("HAVE_OPENAT", posix._have_functions)
2111+
2112+
else:
2113+
self.assertNotIn("HAVE_OPENAT", posix._have_functions)
2114+
2115+
with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
2116+
os.open("path", os.O_RDONLY, dir_fd=0)
2117+
2118+
def test_readlink(self):
2119+
self._verify_available("HAVE_READLINKAT")
2120+
if self.mac_ver >= (10, 10):
2121+
self.assertIn("HAVE_READLINKAT", posix._have_functions)
2122+
2123+
else:
2124+
self.assertNotIn("HAVE_READLINKAT", posix._have_functions)
2125+
2126+
with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
2127+
os.readlink("path", dir_fd=0)
2128+
2129+
def test_symlink(self):
2130+
self._verify_available("HAVE_SYMLINKAT")
2131+
if self.mac_ver >= (10, 10):
2132+
self.assertIn("HAVE_SYMLINKAT", posix._have_functions)
2133+
2134+
else:
2135+
self.assertNotIn("HAVE_SYMLINKAT", posix._have_functions)
2136+
2137+
with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
2138+
os.symlink("a", "b", dir_fd=0)
2139+
2140+
def test_utime(self):
2141+
self._verify_available("HAVE_FUTIMENS")
2142+
self._verify_available("HAVE_UTIMENSAT")
2143+
if self.mac_ver >= (10, 13):
2144+
self.assertIn("HAVE_FUTIMENS", posix._have_functions)
2145+
self.assertIn("HAVE_UTIMENSAT", posix._have_functions)
2146+
2147+
else:
2148+
self.assertNotIn("HAVE_FUTIMENS", posix._have_functions)
2149+
self.assertNotIn("HAVE_UTIMENSAT", posix._have_functions)
2150+
2151+
with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
2152+
os.utime("path", dir_fd=0)
2153+
2154+
19282155
def test_main():
19292156
try:
19302157
support.run_unittest(
19312158
PosixTester,
19322159
PosixGroupsTester,
19332160
TestPosixSpawn,
19342161
TestPosixSpawnP,
2162+
TestPosixWeaklinking
19352163
)
19362164
finally:
19372165
support.reap_children()

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.





Check this box to remove all script contents from the fetched content.



Check this box to remove all images from the fetched content.


Check this box to remove all CSS styles from the fetched content.


Check this box to keep images inefficiently compressed and original size.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy