mirror of https://github.com/python/cpython
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.
This commit is contained in:
parent
fd6f6fa403
commit
41761933c1
|
@ -110,6 +110,26 @@ def _get_system_version():
|
||||||
|
|
||||||
return _SYSTEM_VERSION
|
return _SYSTEM_VERSION
|
||||||
|
|
||||||
|
_SYSTEM_VERSION_TUPLE = None
|
||||||
|
def _get_system_version_tuple():
|
||||||
|
"""
|
||||||
|
Return the macOS system version as a tuple
|
||||||
|
|
||||||
|
The return value is safe to use to compare
|
||||||
|
two version numbers.
|
||||||
|
"""
|
||||||
|
global _SYSTEM_VERSION_TUPLE
|
||||||
|
if _SYSTEM_VERSION_TUPLE is None:
|
||||||
|
osx_version = _get_system_version()
|
||||||
|
if osx_version:
|
||||||
|
try:
|
||||||
|
_SYSTEM_VERSION_TUPLE = tuple(int(i) for i in osx_version.split('.'))
|
||||||
|
except ValueError:
|
||||||
|
_SYSTEM_VERSION_TUPLE = ()
|
||||||
|
|
||||||
|
return _SYSTEM_VERSION_TUPLE
|
||||||
|
|
||||||
|
|
||||||
def _remove_original_values(_config_vars):
|
def _remove_original_values(_config_vars):
|
||||||
"""Remove original unmodified values for testing"""
|
"""Remove original unmodified values for testing"""
|
||||||
# This is needed for higher-level cross-platform tests of get_platform.
|
# This is needed for higher-level cross-platform tests of get_platform.
|
||||||
|
@ -132,14 +152,18 @@ def _supports_universal_builds():
|
||||||
# builds, in particular -isysroot and -arch arguments to the compiler. This
|
# builds, in particular -isysroot and -arch arguments to the compiler. This
|
||||||
# is in support of allowing 10.4 universal builds to run on 10.3.x systems.
|
# is in support of allowing 10.4 universal builds to run on 10.3.x systems.
|
||||||
|
|
||||||
osx_version = _get_system_version()
|
osx_version = _get_system_version_tuple()
|
||||||
if osx_version:
|
|
||||||
try:
|
|
||||||
osx_version = tuple(int(i) for i in osx_version.split('.'))
|
|
||||||
except ValueError:
|
|
||||||
osx_version = ''
|
|
||||||
return bool(osx_version >= (10, 4)) if osx_version else False
|
return bool(osx_version >= (10, 4)) if osx_version else False
|
||||||
|
|
||||||
|
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.
|
||||||
|
osx_version = _get_system_version_tuple()
|
||||||
|
return osx_version >= (11, 0) if osx_version else False
|
||||||
|
|
||||||
|
|
||||||
def _find_appropriate_compiler(_config_vars):
|
def _find_appropriate_compiler(_config_vars):
|
||||||
"""Find appropriate C compiler for extension module builds"""
|
"""Find appropriate C compiler for extension module builds"""
|
||||||
|
@ -331,6 +355,12 @@ def compiler_fixup(compiler_so, cc_args):
|
||||||
except ValueError:
|
except ValueError:
|
||||||
break
|
break
|
||||||
|
|
||||||
|
elif not _supports_arm64_builds():
|
||||||
|
# Look for "-arch arm64" and drop that
|
||||||
|
for idx in range(len(compiler_so)):
|
||||||
|
if compiler_so[idx] == '-arch' and compiler_so[idx+1] == "arm64":
|
||||||
|
del compiler_so[idx:idx+2]
|
||||||
|
|
||||||
if 'ARCHFLAGS' in os.environ and not stripArch:
|
if 'ARCHFLAGS' in os.environ and not stripArch:
|
||||||
# User specified different -arch flags in the environ,
|
# User specified different -arch flags in the environ,
|
||||||
# see also distutils.sysconfig
|
# see also distutils.sysconfig
|
||||||
|
@ -481,6 +511,8 @@ def get_platform_osx(_config_vars, osname, release, machine):
|
||||||
|
|
||||||
if len(archs) == 1:
|
if len(archs) == 1:
|
||||||
machine = archs[0]
|
machine = archs[0]
|
||||||
|
elif archs == ('arm64', 'x86_64'):
|
||||||
|
machine = 'universal2'
|
||||||
elif archs == ('i386', 'ppc'):
|
elif archs == ('i386', 'ppc'):
|
||||||
machine = 'fat'
|
machine = 'fat'
|
||||||
elif archs == ('i386', 'x86_64'):
|
elif archs == ('i386', 'x86_64'):
|
||||||
|
|
|
@ -6,6 +6,11 @@ import os
|
||||||
from ctypes.macholib.framework import framework_info
|
from ctypes.macholib.framework import framework_info
|
||||||
from ctypes.macholib.dylib import dylib_info
|
from ctypes.macholib.dylib import dylib_info
|
||||||
from itertools import *
|
from itertools import *
|
||||||
|
try:
|
||||||
|
from _ctypes import _dyld_shared_cache_contains_path
|
||||||
|
except ImportError:
|
||||||
|
def _dyld_shared_cache_contains_path(*args):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'dyld_find', 'framework_find',
|
'dyld_find', 'framework_find',
|
||||||
|
@ -122,8 +127,15 @@ def dyld_find(name, executable_path=None, env=None):
|
||||||
dyld_executable_path_search(name, executable_path),
|
dyld_executable_path_search(name, executable_path),
|
||||||
dyld_default_search(name, env),
|
dyld_default_search(name, env),
|
||||||
), env):
|
), env):
|
||||||
|
|
||||||
if os.path.isfile(path):
|
if os.path.isfile(path):
|
||||||
return path
|
return path
|
||||||
|
try:
|
||||||
|
if _dyld_shared_cache_contains_path(path):
|
||||||
|
return path
|
||||||
|
except NotImplementedError:
|
||||||
|
pass
|
||||||
|
|
||||||
raise ValueError("dylib %s could not be found" % (name,))
|
raise ValueError("dylib %s could not be found" % (name,))
|
||||||
|
|
||||||
def framework_find(fn, executable_path=None, env=None):
|
def framework_find(fn, executable_path=None, env=None):
|
||||||
|
|
|
@ -45,19 +45,22 @@ def find_lib(name):
|
||||||
class MachOTest(unittest.TestCase):
|
class MachOTest(unittest.TestCase):
|
||||||
@unittest.skipUnless(sys.platform == "darwin", 'OSX-specific test')
|
@unittest.skipUnless(sys.platform == "darwin", 'OSX-specific test')
|
||||||
def test_find(self):
|
def test_find(self):
|
||||||
|
# On Mac OS 11, system dylibs are only present in the shared cache,
|
||||||
self.assertEqual(find_lib('pthread'),
|
# so symlinks like libpthread.dylib -> libSystem.B.dylib will not
|
||||||
'/usr/lib/libSystem.B.dylib')
|
# be resolved by dyld_find
|
||||||
|
self.assertIn(find_lib('pthread'),
|
||||||
|
('/usr/lib/libSystem.B.dylib', '/usr/lib/libpthread.dylib'))
|
||||||
|
|
||||||
result = find_lib('z')
|
result = find_lib('z')
|
||||||
# Issue #21093: dyld default search path includes $HOME/lib and
|
# Issue #21093: dyld default search path includes $HOME/lib and
|
||||||
# /usr/local/lib before /usr/lib, which caused test failures if
|
# /usr/local/lib before /usr/lib, which caused test failures if
|
||||||
# a local copy of libz exists in one of them. Now ignore the head
|
# a local copy of libz exists in one of them. Now ignore the head
|
||||||
# of the path.
|
# of the path.
|
||||||
self.assertRegex(result, r".*/lib/libz\..*.*\.dylib")
|
self.assertRegex(result, r".*/lib/libz.*\.dylib")
|
||||||
|
|
||||||
self.assertEqual(find_lib('IOKit'),
|
self.assertIn(find_lib('IOKit'),
|
||||||
'/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit')
|
('/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit',
|
||||||
|
'/System/Library/Frameworks/IOKit.framework/IOKit'))
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -493,7 +493,7 @@ class BuildExtTestCase(TempdirManager,
|
||||||
# format the target value as defined in the Apple
|
# format the target value as defined in the Apple
|
||||||
# Availability Macros. We can't use the macro names since
|
# Availability Macros. We can't use the macro names since
|
||||||
# at least one value we test with will not exist yet.
|
# at least one value we test with will not exist yet.
|
||||||
if target[1] < 10:
|
if target[:2] < (10, 10):
|
||||||
# for 10.1 through 10.9.x -> "10n0"
|
# for 10.1 through 10.9.x -> "10n0"
|
||||||
target = '%02d%01d0' % target
|
target = '%02d%01d0' % target
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -1036,6 +1036,7 @@ class BytesTest(BaseBytesTest, unittest.TestCase):
|
||||||
c_char_p)
|
c_char_p)
|
||||||
|
|
||||||
PyBytes_FromFormat = pythonapi.PyBytes_FromFormat
|
PyBytes_FromFormat = pythonapi.PyBytes_FromFormat
|
||||||
|
PyBytes_FromFormat.argtypes = (c_char_p,)
|
||||||
PyBytes_FromFormat.restype = py_object
|
PyBytes_FromFormat.restype = py_object
|
||||||
|
|
||||||
# basic tests
|
# basic tests
|
||||||
|
|
|
@ -246,7 +246,7 @@ class PlatformTest(unittest.TestCase):
|
||||||
self.assertEqual(res[1], ('', '', ''))
|
self.assertEqual(res[1], ('', '', ''))
|
||||||
|
|
||||||
if sys.byteorder == 'little':
|
if sys.byteorder == 'little':
|
||||||
self.assertIn(res[2], ('i386', 'x86_64'))
|
self.assertIn(res[2], ('i386', 'x86_64', 'arm64'))
|
||||||
else:
|
else:
|
||||||
self.assertEqual(res[2], 'PowerPC')
|
self.assertEqual(res[2], 'PowerPC')
|
||||||
|
|
||||||
|
|
|
@ -1925,6 +1925,233 @@ class TestPosixSpawnP(unittest.TestCase, _PosixSpawnMixin):
|
||||||
assert_python_ok(*args, PATH=path)
|
assert_python_ok(*args, PATH=path)
|
||||||
|
|
||||||
|
|
||||||
|
@unittest.skipUnless(sys.platform == "darwin", "test weak linking on macOS")
|
||||||
|
class TestPosixWeaklinking(unittest.TestCase):
|
||||||
|
# These test cases verify that weak linking support on macOS works
|
||||||
|
# as expected. These cases only test new behaviour introduced by weak linking,
|
||||||
|
# regular behaviour is tested by the normal test cases.
|
||||||
|
#
|
||||||
|
# See the section on Weak Linking in Mac/README.txt for more information.
|
||||||
|
def setUp(self):
|
||||||
|
import sysconfig
|
||||||
|
import platform
|
||||||
|
|
||||||
|
config_vars = sysconfig.get_config_vars()
|
||||||
|
self.available = { nm for nm in config_vars if nm.startswith("HAVE_") and config_vars[nm] }
|
||||||
|
self.mac_ver = tuple(int(part) for part in platform.mac_ver()[0].split("."))
|
||||||
|
|
||||||
|
def _verify_available(self, name):
|
||||||
|
if name not in self.available:
|
||||||
|
raise unittest.SkipTest(f"{name} not weak-linked")
|
||||||
|
|
||||||
|
def test_pwritev(self):
|
||||||
|
self._verify_available("HAVE_PWRITEV")
|
||||||
|
if self.mac_ver >= (10, 16):
|
||||||
|
self.assertTrue(hasattr(os, "pwritev"), "os.pwritev is not available")
|
||||||
|
self.assertTrue(hasattr(os, "preadv"), "os.readv is not available")
|
||||||
|
|
||||||
|
else:
|
||||||
|
self.assertFalse(hasattr(os, "pwritev"), "os.pwritev is available")
|
||||||
|
self.assertFalse(hasattr(os, "preadv"), "os.readv is available")
|
||||||
|
|
||||||
|
def test_stat(self):
|
||||||
|
self._verify_available("HAVE_FSTATAT")
|
||||||
|
if self.mac_ver >= (10, 10):
|
||||||
|
self.assertIn("HAVE_FSTATAT", posix._have_functions)
|
||||||
|
|
||||||
|
else:
|
||||||
|
self.assertNotIn("HAVE_FSTATAT", posix._have_functions)
|
||||||
|
|
||||||
|
with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
|
||||||
|
os.stat("file", dir_fd=0)
|
||||||
|
|
||||||
|
def test_access(self):
|
||||||
|
self._verify_available("HAVE_FACCESSAT")
|
||||||
|
if self.mac_ver >= (10, 10):
|
||||||
|
self.assertIn("HAVE_FACCESSAT", posix._have_functions)
|
||||||
|
|
||||||
|
else:
|
||||||
|
self.assertNotIn("HAVE_FACCESSAT", posix._have_functions)
|
||||||
|
|
||||||
|
with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
|
||||||
|
os.access("file", os.R_OK, dir_fd=0)
|
||||||
|
|
||||||
|
with self.assertRaisesRegex(NotImplementedError, "follow_symlinks unavailable"):
|
||||||
|
os.access("file", os.R_OK, follow_symlinks=False)
|
||||||
|
|
||||||
|
with self.assertRaisesRegex(NotImplementedError, "effective_ids unavailable"):
|
||||||
|
os.access("file", os.R_OK, effective_ids=True)
|
||||||
|
|
||||||
|
def test_chmod(self):
|
||||||
|
self._verify_available("HAVE_FCHMODAT")
|
||||||
|
if self.mac_ver >= (10, 10):
|
||||||
|
self.assertIn("HAVE_FCHMODAT", posix._have_functions)
|
||||||
|
|
||||||
|
else:
|
||||||
|
self.assertNotIn("HAVE_FCHMODAT", posix._have_functions)
|
||||||
|
self.assertIn("HAVE_LCHMOD", posix._have_functions)
|
||||||
|
|
||||||
|
with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
|
||||||
|
os.chmod("file", 0o644, dir_fd=0)
|
||||||
|
|
||||||
|
def test_chown(self):
|
||||||
|
self._verify_available("HAVE_FCHOWNAT")
|
||||||
|
if self.mac_ver >= (10, 10):
|
||||||
|
self.assertIn("HAVE_FCHOWNAT", posix._have_functions)
|
||||||
|
|
||||||
|
else:
|
||||||
|
self.assertNotIn("HAVE_FCHOWNAT", posix._have_functions)
|
||||||
|
self.assertIn("HAVE_LCHOWN", posix._have_functions)
|
||||||
|
|
||||||
|
with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
|
||||||
|
os.chown("file", 0, 0, dir_fd=0)
|
||||||
|
|
||||||
|
def test_link(self):
|
||||||
|
self._verify_available("HAVE_LINKAT")
|
||||||
|
if self.mac_ver >= (10, 10):
|
||||||
|
self.assertIn("HAVE_LINKAT", posix._have_functions)
|
||||||
|
|
||||||
|
else:
|
||||||
|
self.assertNotIn("HAVE_LINKAT", posix._have_functions)
|
||||||
|
|
||||||
|
with self.assertRaisesRegex(NotImplementedError, "src_dir_fd unavailable"):
|
||||||
|
os.link("source", "target", src_dir_fd=0)
|
||||||
|
|
||||||
|
with self.assertRaisesRegex(NotImplementedError, "dst_dir_fd unavailable"):
|
||||||
|
os.link("source", "target", dst_dir_fd=0)
|
||||||
|
|
||||||
|
with self.assertRaisesRegex(NotImplementedError, "src_dir_fd unavailable"):
|
||||||
|
os.link("source", "target", src_dir_fd=0, dst_dir_fd=0)
|
||||||
|
|
||||||
|
# issue 41355: !HAVE_LINKAT code path ignores the follow_symlinks flag
|
||||||
|
with os_helper.temp_dir() as base_path:
|
||||||
|
link_path = os.path.join(base_path, "link")
|
||||||
|
target_path = os.path.join(base_path, "target")
|
||||||
|
source_path = os.path.join(base_path, "source")
|
||||||
|
|
||||||
|
with open(source_path, "w") as fp:
|
||||||
|
fp.write("data")
|
||||||
|
|
||||||
|
os.symlink("target", link_path)
|
||||||
|
|
||||||
|
# Calling os.link should fail in the link(2) call, and
|
||||||
|
# should not reject *follow_symlinks* (to match the
|
||||||
|
# behaviour you'd get when building on a platform without
|
||||||
|
# linkat)
|
||||||
|
with self.assertRaises(FileExistsError):
|
||||||
|
os.link(source_path, link_path, follow_symlinks=True)
|
||||||
|
|
||||||
|
with self.assertRaises(FileExistsError):
|
||||||
|
os.link(source_path, link_path, follow_symlinks=False)
|
||||||
|
|
||||||
|
|
||||||
|
def test_listdir_scandir(self):
|
||||||
|
self._verify_available("HAVE_FDOPENDIR")
|
||||||
|
if self.mac_ver >= (10, 10):
|
||||||
|
self.assertIn("HAVE_FDOPENDIR", posix._have_functions)
|
||||||
|
|
||||||
|
else:
|
||||||
|
self.assertNotIn("HAVE_FDOPENDIR", posix._have_functions)
|
||||||
|
|
||||||
|
with self.assertRaisesRegex(TypeError, "listdir: path should be string, bytes, os.PathLike or None, not int"):
|
||||||
|
os.listdir(0)
|
||||||
|
|
||||||
|
with self.assertRaisesRegex(TypeError, "scandir: path should be string, bytes, os.PathLike or None, not int"):
|
||||||
|
os.scandir(0)
|
||||||
|
|
||||||
|
def test_mkdir(self):
|
||||||
|
self._verify_available("HAVE_MKDIRAT")
|
||||||
|
if self.mac_ver >= (10, 10):
|
||||||
|
self.assertIn("HAVE_MKDIRAT", posix._have_functions)
|
||||||
|
|
||||||
|
else:
|
||||||
|
self.assertNotIn("HAVE_MKDIRAT", posix._have_functions)
|
||||||
|
|
||||||
|
with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
|
||||||
|
os.mkdir("dir", dir_fd=0)
|
||||||
|
|
||||||
|
def test_rename_replace(self):
|
||||||
|
self._verify_available("HAVE_RENAMEAT")
|
||||||
|
if self.mac_ver >= (10, 10):
|
||||||
|
self.assertIn("HAVE_RENAMEAT", posix._have_functions)
|
||||||
|
|
||||||
|
else:
|
||||||
|
self.assertNotIn("HAVE_RENAMEAT", posix._have_functions)
|
||||||
|
|
||||||
|
with self.assertRaisesRegex(NotImplementedError, "src_dir_fd and dst_dir_fd unavailable"):
|
||||||
|
os.rename("a", "b", src_dir_fd=0)
|
||||||
|
|
||||||
|
with self.assertRaisesRegex(NotImplementedError, "src_dir_fd and dst_dir_fd unavailable"):
|
||||||
|
os.rename("a", "b", dst_dir_fd=0)
|
||||||
|
|
||||||
|
with self.assertRaisesRegex(NotImplementedError, "src_dir_fd and dst_dir_fd unavailable"):
|
||||||
|
os.replace("a", "b", src_dir_fd=0)
|
||||||
|
|
||||||
|
with self.assertRaisesRegex(NotImplementedError, "src_dir_fd and dst_dir_fd unavailable"):
|
||||||
|
os.replace("a", "b", dst_dir_fd=0)
|
||||||
|
|
||||||
|
def test_unlink_rmdir(self):
|
||||||
|
self._verify_available("HAVE_UNLINKAT")
|
||||||
|
if self.mac_ver >= (10, 10):
|
||||||
|
self.assertIn("HAVE_UNLINKAT", posix._have_functions)
|
||||||
|
|
||||||
|
else:
|
||||||
|
self.assertNotIn("HAVE_UNLINKAT", posix._have_functions)
|
||||||
|
|
||||||
|
with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
|
||||||
|
os.unlink("path", dir_fd=0)
|
||||||
|
|
||||||
|
with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
|
||||||
|
os.rmdir("path", dir_fd=0)
|
||||||
|
|
||||||
|
def test_open(self):
|
||||||
|
self._verify_available("HAVE_OPENAT")
|
||||||
|
if self.mac_ver >= (10, 10):
|
||||||
|
self.assertIn("HAVE_OPENAT", posix._have_functions)
|
||||||
|
|
||||||
|
else:
|
||||||
|
self.assertNotIn("HAVE_OPENAT", posix._have_functions)
|
||||||
|
|
||||||
|
with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
|
||||||
|
os.open("path", os.O_RDONLY, dir_fd=0)
|
||||||
|
|
||||||
|
def test_readlink(self):
|
||||||
|
self._verify_available("HAVE_READLINKAT")
|
||||||
|
if self.mac_ver >= (10, 10):
|
||||||
|
self.assertIn("HAVE_READLINKAT", posix._have_functions)
|
||||||
|
|
||||||
|
else:
|
||||||
|
self.assertNotIn("HAVE_READLINKAT", posix._have_functions)
|
||||||
|
|
||||||
|
with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
|
||||||
|
os.readlink("path", dir_fd=0)
|
||||||
|
|
||||||
|
def test_symlink(self):
|
||||||
|
self._verify_available("HAVE_SYMLINKAT")
|
||||||
|
if self.mac_ver >= (10, 10):
|
||||||
|
self.assertIn("HAVE_SYMLINKAT", posix._have_functions)
|
||||||
|
|
||||||
|
else:
|
||||||
|
self.assertNotIn("HAVE_SYMLINKAT", posix._have_functions)
|
||||||
|
|
||||||
|
with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
|
||||||
|
os.symlink("a", "b", dir_fd=0)
|
||||||
|
|
||||||
|
def test_utime(self):
|
||||||
|
self._verify_available("HAVE_FUTIMENS")
|
||||||
|
self._verify_available("HAVE_UTIMENSAT")
|
||||||
|
if self.mac_ver >= (10, 13):
|
||||||
|
self.assertIn("HAVE_FUTIMENS", posix._have_functions)
|
||||||
|
self.assertIn("HAVE_UTIMENSAT", posix._have_functions)
|
||||||
|
|
||||||
|
else:
|
||||||
|
self.assertNotIn("HAVE_FUTIMENS", posix._have_functions)
|
||||||
|
self.assertNotIn("HAVE_UTIMENSAT", posix._have_functions)
|
||||||
|
|
||||||
|
with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
|
||||||
|
os.utime("path", dir_fd=0)
|
||||||
|
|
||||||
|
|
||||||
def test_main():
|
def test_main():
|
||||||
try:
|
try:
|
||||||
support.run_unittest(
|
support.run_unittest(
|
||||||
|
@ -1932,6 +2159,7 @@ def test_main():
|
||||||
PosixGroupsTester,
|
PosixGroupsTester,
|
||||||
TestPosixSpawn,
|
TestPosixSpawn,
|
||||||
TestPosixSpawnP,
|
TestPosixSpawnP,
|
||||||
|
TestPosixWeaklinking
|
||||||
)
|
)
|
||||||
finally:
|
finally:
|
||||||
support.reap_children()
|
support.reap_children()
|
||||||
|
|
|
@ -1041,6 +1041,36 @@ class TestOldPyTime(CPyTimeTestCase, unittest.TestCase):
|
||||||
with self.assertRaises(ValueError):
|
with self.assertRaises(ValueError):
|
||||||
pytime_object_to_timespec(float('nan'), time_rnd)
|
pytime_object_to_timespec(float('nan'), time_rnd)
|
||||||
|
|
||||||
|
@unittest.skipUnless(sys.platform == "darwin", "test weak linking on macOS")
|
||||||
|
class TestTimeWeaklinking(unittest.TestCase):
|
||||||
|
# These test cases verify that weak linking support on macOS works
|
||||||
|
# as expected. These cases only test new behaviour introduced by weak linking,
|
||||||
|
# regular behaviour is tested by the normal test cases.
|
||||||
|
#
|
||||||
|
# See the section on Weak Linking in Mac/README.txt for more information.
|
||||||
|
def test_clock_functions(self):
|
||||||
|
import sysconfig
|
||||||
|
import platform
|
||||||
|
|
||||||
|
config_vars = sysconfig.get_config_vars()
|
||||||
|
var_name = "HAVE_CLOCK_GETTIME"
|
||||||
|
if var_name not in config_vars or not config_vars[var_name]:
|
||||||
|
raise unittest.SkipTest(f"{var_name} is not available")
|
||||||
|
|
||||||
|
mac_ver = tuple(int(x) for x in platform.mac_ver()[0].split("."))
|
||||||
|
|
||||||
|
clock_names = [
|
||||||
|
"CLOCK_MONOTONIC", "clock_gettime", "clock_gettime_ns", "clock_settime",
|
||||||
|
"clock_settime_ns", "clock_getres"]
|
||||||
|
|
||||||
|
if mac_ver >= (10, 12):
|
||||||
|
for name in clock_names:
|
||||||
|
self.assertTrue(hasattr(time, name), f"time.{name} is not available")
|
||||||
|
|
||||||
|
else:
|
||||||
|
for name in clock_names:
|
||||||
|
self.assertFalse(hasattr(time, name), f"time.{name} is available")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -2516,11 +2516,13 @@ class CAPITest(unittest.TestCase):
|
||||||
def test_from_format(self):
|
def test_from_format(self):
|
||||||
import_helper.import_module('ctypes')
|
import_helper.import_module('ctypes')
|
||||||
from ctypes import (
|
from ctypes import (
|
||||||
|
c_char_p,
|
||||||
pythonapi, py_object, sizeof,
|
pythonapi, py_object, sizeof,
|
||||||
c_int, c_long, c_longlong, c_ssize_t,
|
c_int, c_long, c_longlong, c_ssize_t,
|
||||||
c_uint, c_ulong, c_ulonglong, c_size_t, c_void_p)
|
c_uint, c_ulong, c_ulonglong, c_size_t, c_void_p)
|
||||||
name = "PyUnicode_FromFormat"
|
name = "PyUnicode_FromFormat"
|
||||||
_PyUnicode_FromFormat = getattr(pythonapi, name)
|
_PyUnicode_FromFormat = getattr(pythonapi, name)
|
||||||
|
_PyUnicode_FromFormat.argtypes = (c_char_p,)
|
||||||
_PyUnicode_FromFormat.restype = py_object
|
_PyUnicode_FromFormat.restype = py_object
|
||||||
|
|
||||||
def PyUnicode_FromFormat(format, *args):
|
def PyUnicode_FromFormat(format, *args):
|
||||||
|
|
|
@ -116,7 +116,8 @@ WORKDIR = "/tmp/_py"
|
||||||
DEPSRC = os.path.join(WORKDIR, 'third-party')
|
DEPSRC = os.path.join(WORKDIR, 'third-party')
|
||||||
DEPSRC = os.path.expanduser('~/Universal/other-sources')
|
DEPSRC = os.path.expanduser('~/Universal/other-sources')
|
||||||
|
|
||||||
universal_opts_map = { '32-bit': ('i386', 'ppc',),
|
universal_opts_map = { 'universal2': ('arm64', 'x86_64'),
|
||||||
|
'32-bit': ('i386', 'ppc',),
|
||||||
'64-bit': ('x86_64', 'ppc64',),
|
'64-bit': ('x86_64', 'ppc64',),
|
||||||
'intel': ('i386', 'x86_64'),
|
'intel': ('i386', 'x86_64'),
|
||||||
'intel-32': ('i386',),
|
'intel-32': ('i386',),
|
||||||
|
@ -124,6 +125,7 @@ universal_opts_map = { '32-bit': ('i386', 'ppc',),
|
||||||
'3-way': ('ppc', 'i386', 'x86_64'),
|
'3-way': ('ppc', 'i386', 'x86_64'),
|
||||||
'all': ('i386', 'ppc', 'x86_64', 'ppc64',) }
|
'all': ('i386', 'ppc', 'x86_64', 'ppc64',) }
|
||||||
default_target_map = {
|
default_target_map = {
|
||||||
|
'universal2': '10.9',
|
||||||
'64-bit': '10.5',
|
'64-bit': '10.5',
|
||||||
'3-way': '10.5',
|
'3-way': '10.5',
|
||||||
'intel': '10.5',
|
'intel': '10.5',
|
||||||
|
@ -190,6 +192,27 @@ EXPECTED_SHARED_LIBS = {}
|
||||||
def internalTk():
|
def internalTk():
|
||||||
return getDeptargetTuple() >= (10, 6)
|
return getDeptargetTuple() >= (10, 6)
|
||||||
|
|
||||||
|
|
||||||
|
def tweak_tcl_build(basedir, archList):
|
||||||
|
with open("Makefile", "r") as fp:
|
||||||
|
contents = fp.readlines()
|
||||||
|
|
||||||
|
# For reasons I don't understand the tcl configure script
|
||||||
|
# decides that some stdlib symbols aren't present, before
|
||||||
|
# deciding that strtod is broken.
|
||||||
|
new_contents = []
|
||||||
|
for line in contents:
|
||||||
|
if line.startswith("COMPAT_OBJS"):
|
||||||
|
# note: the space before strtod.o is intentional,
|
||||||
|
# the detection of a broken strtod results in
|
||||||
|
# "fixstrod.o" on this line.
|
||||||
|
for nm in ("strstr.o", "strtoul.o", " strtod.o"):
|
||||||
|
line = line.replace(nm, "")
|
||||||
|
new_contents.append(line)
|
||||||
|
|
||||||
|
with open("Makefile", "w") as fp:
|
||||||
|
fp.writelines(new_contents)
|
||||||
|
|
||||||
# List of names of third party software built with this installer.
|
# List of names of third party software built with this installer.
|
||||||
# The names will be inserted into the rtf version of the License.
|
# The names will be inserted into the rtf version of the License.
|
||||||
THIRD_PARTY_LIBS = []
|
THIRD_PARTY_LIBS = []
|
||||||
|
@ -215,6 +238,9 @@ def library_recipes():
|
||||||
buildrecipe=build_universal_openssl,
|
buildrecipe=build_universal_openssl,
|
||||||
configure=None,
|
configure=None,
|
||||||
install=None,
|
install=None,
|
||||||
|
patches=[
|
||||||
|
"openssl-mac-arm64.patch",
|
||||||
|
],
|
||||||
),
|
),
|
||||||
])
|
])
|
||||||
|
|
||||||
|
@ -231,6 +257,7 @@ def library_recipes():
|
||||||
'--libdir=/Library/Frameworks/Python.framework/Versions/%s/lib'%(getVersion(),),
|
'--libdir=/Library/Frameworks/Python.framework/Versions/%s/lib'%(getVersion(),),
|
||||||
],
|
],
|
||||||
useLDFlags=False,
|
useLDFlags=False,
|
||||||
|
buildrecipe=tweak_tcl_build,
|
||||||
install='make TCL_LIBRARY=%(TCL_LIBRARY)s && make install TCL_LIBRARY=%(TCL_LIBRARY)s DESTDIR=%(DESTDIR)s'%{
|
install='make TCL_LIBRARY=%(TCL_LIBRARY)s && make install TCL_LIBRARY=%(TCL_LIBRARY)s DESTDIR=%(DESTDIR)s'%{
|
||||||
"DESTDIR": shellQuote(os.path.join(WORKDIR, 'libraries')),
|
"DESTDIR": shellQuote(os.path.join(WORKDIR, 'libraries')),
|
||||||
"TCL_LIBRARY": shellQuote('/Library/Frameworks/Python.framework/Versions/%s/lib/tcl8.6'%(getVersion())),
|
"TCL_LIBRARY": shellQuote('/Library/Frameworks/Python.framework/Versions/%s/lib/tcl8.6'%(getVersion())),
|
||||||
|
@ -801,6 +828,7 @@ def build_universal_openssl(basedir, archList):
|
||||||
arch_opts = {
|
arch_opts = {
|
||||||
"i386": ["darwin-i386-cc"],
|
"i386": ["darwin-i386-cc"],
|
||||||
"x86_64": ["darwin64-x86_64-cc", "enable-ec_nistp_64_gcc_128"],
|
"x86_64": ["darwin64-x86_64-cc", "enable-ec_nistp_64_gcc_128"],
|
||||||
|
"arm64": ["darwin64-arm64-cc"],
|
||||||
"ppc": ["darwin-ppc-cc"],
|
"ppc": ["darwin-ppc-cc"],
|
||||||
"ppc64": ["darwin64-ppc-cc"],
|
"ppc64": ["darwin64-ppc-cc"],
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
diff -ur openssl-1.1.1g-orig/Configurations/10-main.conf openssl-1.1.1g/Configurations/10-main.conf
|
||||||
|
--- openssl-1.1.1g-orig/Configurations/10-main.conf 2020-04-21 14:22:39.000000000 +0200
|
||||||
|
+++ openssl-1.1.1g/Configurations/10-main.conf 2020-07-26 12:21:32.000000000 +0200
|
||||||
|
@@ -1557,6 +1557,14 @@
|
||||||
|
bn_ops => "SIXTY_FOUR_BIT_LONG",
|
||||||
|
perlasm_scheme => "macosx",
|
||||||
|
},
|
||||||
|
+ "darwin64-arm64-cc" => {
|
||||||
|
+ inherit_from => [ "darwin-common", asm("aarch64_asm") ],
|
||||||
|
+ CFLAGS => add("-Wall"),
|
||||||
|
+ cflags => add("-arch arm64"),
|
||||||
|
+ lib_cppflags => add("-DL_ENDIAN"),
|
||||||
|
+ bn_ops => "SIXTY_FOUR_BIT_LONG",
|
||||||
|
+ perlasm_scheme => "ios64",
|
||||||
|
+ },
|
||||||
|
|
||||||
|
##### GNU Hurd
|
||||||
|
"hurd-x86" => {
|
||||||
|
diff -ur openssl-1.1.1g-orig/config openssl-1.1.1g/config
|
||||||
|
--- openssl-1.1.1g-orig/config 2020-04-21 14:22:39.000000000 +0200
|
||||||
|
+++ openssl-1.1.1g/config 2020-07-26 12:21:59.000000000 +0200
|
||||||
|
@@ -255,6 +255,9 @@
|
||||||
|
;;
|
||||||
|
x86_64)
|
||||||
|
echo "x86_64-apple-darwin${VERSION}"
|
||||||
|
+ ;;
|
||||||
|
+ arm64)
|
||||||
|
+ echo "arm64-apple-darwin${VERSION}"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "i686-apple-darwin${VERSION}"
|
||||||
|
@@ -497,6 +500,9 @@
|
||||||
|
else
|
||||||
|
OUT="darwin64-x86_64-cc"
|
||||||
|
fi ;;
|
||||||
|
+ x86_64-apple-darwin*)
|
||||||
|
+ OUT="darwin64-arm64-cc"
|
||||||
|
+ ;;
|
||||||
|
armv6+7-*-iphoneos)
|
||||||
|
__CNF_CFLAGS="$__CNF_CFLAGS -arch armv6 -arch armv7"
|
||||||
|
__CNF_CXXFLAGS="$__CNF_CXXFLAGS -arch armv6 -arch armv7"
|
|
@ -120,6 +120,8 @@ support ppc (Xcode 4 on 10.6 and later systems). The flavor can be specified
|
||||||
using the configure option ``--with-universal-archs=VALUE``. The following
|
using the configure option ``--with-universal-archs=VALUE``. The following
|
||||||
values are available:
|
values are available:
|
||||||
|
|
||||||
|
* ``universal2``: ``arm64``, ``x86_64``
|
||||||
|
|
||||||
* ``intel``: ``i386``, ``x86_64``
|
* ``intel``: ``i386``, ``x86_64``
|
||||||
|
|
||||||
* ``intel-32``: ``i386``
|
* ``intel-32``: ``i386``
|
||||||
|
@ -155,6 +157,8 @@ following combinations of SDKs and universal-archs flavors are available:
|
||||||
|
|
||||||
* 10.15 and later SDKs support ``intel-64`` only
|
* 10.15 and later SDKs support ``intel-64`` only
|
||||||
|
|
||||||
|
* 11.0 and later SDKs support ``universal2``
|
||||||
|
|
||||||
The makefile for a framework build will also install ``python3.x-32``
|
The makefile for a framework build will also install ``python3.x-32``
|
||||||
binaries when the universal architecture includes at least one 32-bit
|
binaries when the universal architecture includes at least one 32-bit
|
||||||
architecture (that is, for all flavors but ``64-bit`` and ``intel-64``).
|
architecture (that is, for all flavors but ``64-bit`` and ``intel-64``).
|
||||||
|
@ -352,6 +356,39 @@ A framework install also installs some applications in ``/Applications/Python X.
|
||||||
And lastly a framework installation installs files in ``/usr/local/bin``, all of
|
And lastly a framework installation installs files in ``/usr/local/bin``, all of
|
||||||
them symbolic links to files in ``/Library/Frameworks/Python.framework/Versions/X.Y/bin``.
|
them symbolic links to files in ``/Library/Frameworks/Python.framework/Versions/X.Y/bin``.
|
||||||
|
|
||||||
|
Weak linking support
|
||||||
|
====================
|
||||||
|
|
||||||
|
The CPython sources support building with the latest SDK while targetting deployment
|
||||||
|
to macOS 10.9. This is done through weak linking of symbols introduced in macOS
|
||||||
|
10.10 or later and checking for their availability at runtime.
|
||||||
|
|
||||||
|
This requires the use of Apple's compiler toolchain on macOS 10.13 or later.
|
||||||
|
|
||||||
|
The basic implementation pattern is:
|
||||||
|
|
||||||
|
* ``HAVE_<FUNCTION>`` is a macro defined (or not) by the configure script
|
||||||
|
|
||||||
|
* ``HAVE_<FUNCTION>_RUNTIME`` is a macro defined in the relevant source
|
||||||
|
files. This expands to a call to ``__builtin_available`` when using
|
||||||
|
a new enough Apple compiler, and to a true value otherwise.
|
||||||
|
|
||||||
|
* Use ``HAVE_<FUNCTION>_RUNTIME`` before calling ``<function>``. This macro
|
||||||
|
*must* be used a the sole expression in an if statement::
|
||||||
|
|
||||||
|
if (HAVE_<FUNCTION>_RUNTIME) {
|
||||||
|
/* <function> is available */
|
||||||
|
}
|
||||||
|
|
||||||
|
Or:
|
||||||
|
|
||||||
|
if (HAVE_<FUNCTION>_RUNTIME) {} else {
|
||||||
|
/* <function> is not available */
|
||||||
|
}
|
||||||
|
|
||||||
|
Using other patterns (such as ``!HAVE_<FUNCTION>_RUNTIME``) is not supported
|
||||||
|
by Apple's compilers.
|
||||||
|
|
||||||
|
|
||||||
Resources
|
Resources
|
||||||
=========
|
=========
|
||||||
|
|
|
@ -95,9 +95,6 @@ setup_spawnattr(posix_spawnattr_t* spawnattr)
|
||||||
size_t count;
|
size_t count;
|
||||||
cpu_type_t cpu_types[1];
|
cpu_type_t cpu_types[1];
|
||||||
short flags = 0;
|
short flags = 0;
|
||||||
#ifdef __LP64__
|
|
||||||
int ch;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if ((errno = posix_spawnattr_init(spawnattr)) != 0) {
|
if ((errno = posix_spawnattr_init(spawnattr)) != 0) {
|
||||||
err(2, "posix_spawnattr_int");
|
err(2, "posix_spawnattr_int");
|
||||||
|
@ -119,10 +116,16 @@ setup_spawnattr(posix_spawnattr_t* spawnattr)
|
||||||
|
|
||||||
#elif defined(__ppc__)
|
#elif defined(__ppc__)
|
||||||
cpu_types[0] = CPU_TYPE_POWERPC;
|
cpu_types[0] = CPU_TYPE_POWERPC;
|
||||||
|
|
||||||
#elif defined(__i386__)
|
#elif defined(__i386__)
|
||||||
cpu_types[0] = CPU_TYPE_X86;
|
cpu_types[0] = CPU_TYPE_X86;
|
||||||
|
|
||||||
|
#elif defined(__arm64__)
|
||||||
|
cpu_types[0] = CPU_TYPE_ARM64;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
# error "Unknown CPU"
|
# error "Unknown CPU"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (posix_spawnattr_setbinpref_np(spawnattr, count,
|
if (posix_spawnattr_setbinpref_np(spawnattr, count,
|
||||||
|
@ -220,7 +223,8 @@ main(int argc, char **argv) {
|
||||||
/* We're weak-linking to posix-spawnv to ensure that
|
/* We're weak-linking to posix-spawnv to ensure that
|
||||||
* an executable build on 10.5 can work on 10.4.
|
* an executable build on 10.5 can work on 10.4.
|
||||||
*/
|
*/
|
||||||
if (posix_spawn != NULL) {
|
|
||||||
|
if (&posix_spawn != NULL) {
|
||||||
posix_spawnattr_t spawnattr = NULL;
|
posix_spawnattr_t spawnattr = NULL;
|
||||||
|
|
||||||
setup_spawnattr(&spawnattr);
|
setup_spawnattr(&spawnattr);
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
Add support for macOS 11 and Apple Silicon systems.
|
||||||
|
|
||||||
|
It is now possible to build "Universal 2" binaries using
|
||||||
|
"--enable-universalsdk --with-universal-archs=universal2".
|
||||||
|
|
||||||
|
Binaries build on later macOS versions can be deployed back to older
|
||||||
|
versions (tested up to macOS 10.9), when using the correct deployment
|
||||||
|
target. This is tested using Xcode 11 and later.
|
|
@ -1,6 +1,8 @@
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
#include "frameobject.h"
|
#include "frameobject.h"
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#include <ffi.h>
|
#include <ffi.h>
|
||||||
#ifdef MS_WIN32
|
#ifdef MS_WIN32
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
@ -18,7 +20,7 @@ CThunkObject_dealloc(PyObject *myself)
|
||||||
Py_XDECREF(self->callable);
|
Py_XDECREF(self->callable);
|
||||||
Py_XDECREF(self->restype);
|
Py_XDECREF(self->restype);
|
||||||
if (self->pcl_write)
|
if (self->pcl_write)
|
||||||
ffi_closure_free(self->pcl_write);
|
Py_ffi_closure_free(self->pcl_write);
|
||||||
PyObject_GC_Del(self);
|
PyObject_GC_Del(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -362,8 +364,7 @@ CThunkObject *_ctypes_alloc_callback(PyObject *callable,
|
||||||
|
|
||||||
assert(CThunk_CheckExact((PyObject *)p));
|
assert(CThunk_CheckExact((PyObject *)p));
|
||||||
|
|
||||||
p->pcl_write = ffi_closure_alloc(sizeof(ffi_closure),
|
p->pcl_write = Py_ffi_closure_alloc(sizeof(ffi_closure), &p->pcl_exec);
|
||||||
&p->pcl_exec);
|
|
||||||
if (p->pcl_write == NULL) {
|
if (p->pcl_write == NULL) {
|
||||||
PyErr_NoMemory();
|
PyErr_NoMemory();
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -409,13 +410,35 @@ CThunkObject *_ctypes_alloc_callback(PyObject *callable,
|
||||||
"ffi_prep_cif failed with %d", result);
|
"ffi_prep_cif failed with %d", result);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
#if defined(X86_DARWIN) || defined(POWERPC_DARWIN)
|
#if HAVE_FFI_PREP_CLOSURE_LOC
|
||||||
result = ffi_prep_closure(p->pcl_write, &p->cif, closure_fcn, p);
|
# if USING_APPLE_OS_LIBFFI
|
||||||
#else
|
# define HAVE_FFI_PREP_CLOSURE_LOC_RUNTIME __builtin_available(macos 10.15, ios 13, watchos 6, tvos 13, *)
|
||||||
result = ffi_prep_closure_loc(p->pcl_write, &p->cif, closure_fcn,
|
# else
|
||||||
p,
|
# define HAVE_FFI_PREP_CLOSURE_LOC_RUNTIME 1
|
||||||
p->pcl_exec);
|
# endif
|
||||||
|
if (HAVE_FFI_PREP_CLOSURE_LOC_RUNTIME) {
|
||||||
|
result = ffi_prep_closure_loc(p->pcl_write, &p->cif, closure_fcn,
|
||||||
|
p,
|
||||||
|
p->pcl_exec);
|
||||||
|
} else
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
|
#if USING_APPLE_OS_LIBFFI && defined(__arm64__)
|
||||||
|
PyErr_Format(PyExc_NotImplementedError, "ffi_prep_closure_loc() is missing");
|
||||||
|
goto error;
|
||||||
|
#else
|
||||||
|
#ifdef MACOSX
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||||
|
#endif
|
||||||
|
result = ffi_prep_closure(p->pcl_write, &p->cif, closure_fcn, p);
|
||||||
|
|
||||||
|
#ifdef MACOSX
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
if (result != FFI_OK) {
|
if (result != FFI_OK) {
|
||||||
PyErr_Format(PyExc_RuntimeError,
|
PyErr_Format(PyExc_RuntimeError,
|
||||||
"ffi_prep_closure failed with %d", result);
|
"ffi_prep_closure failed with %d", result);
|
||||||
|
|
|
@ -57,6 +57,8 @@
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
#include "structmember.h" // PyMemberDef
|
#include "structmember.h" // PyMemberDef
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#ifdef MS_WIN32
|
#ifdef MS_WIN32
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <tchar.h>
|
#include <tchar.h>
|
||||||
|
@ -64,6 +66,10 @@
|
||||||
#include "ctypes_dlfcn.h"
|
#include "ctypes_dlfcn.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#include <mach-o/dyld.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef MS_WIN32
|
#ifdef MS_WIN32
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -812,7 +818,8 @@ static int _call_function_pointer(int flags,
|
||||||
ffi_type **atypes,
|
ffi_type **atypes,
|
||||||
ffi_type *restype,
|
ffi_type *restype,
|
||||||
void *resmem,
|
void *resmem,
|
||||||
int argcount)
|
int argcount,
|
||||||
|
int argtypecount)
|
||||||
{
|
{
|
||||||
PyThreadState *_save = NULL; /* For Py_BLOCK_THREADS and Py_UNBLOCK_THREADS */
|
PyThreadState *_save = NULL; /* For Py_BLOCK_THREADS and Py_UNBLOCK_THREADS */
|
||||||
PyObject *error_object = NULL;
|
PyObject *error_object = NULL;
|
||||||
|
@ -835,14 +842,70 @@ static int _call_function_pointer(int flags,
|
||||||
if ((flags & FUNCFLAG_CDECL) == 0)
|
if ((flags & FUNCFLAG_CDECL) == 0)
|
||||||
cc = FFI_STDCALL;
|
cc = FFI_STDCALL;
|
||||||
#endif
|
#endif
|
||||||
if (FFI_OK != ffi_prep_cif(&cif,
|
|
||||||
cc,
|
# if USING_APPLE_OS_LIBFFI
|
||||||
argcount,
|
# define HAVE_FFI_PREP_CIF_VAR_RUNTIME __builtin_available(macos 10.15, ios 13, watchos 6, tvos 13, *)
|
||||||
restype,
|
# elif HAVE_FFI_PREP_CIF_VAR
|
||||||
atypes)) {
|
# define HAVE_FFI_PREP_CIF_VAR_RUNTIME true
|
||||||
PyErr_SetString(PyExc_RuntimeError,
|
# else
|
||||||
"ffi_prep_cif failed");
|
# define HAVE_FFI_PREP_CIF_VAR_RUNTIME false
|
||||||
return -1;
|
# endif
|
||||||
|
|
||||||
|
/* Even on Apple-arm64 the calling convention for variadic functions conincides
|
||||||
|
* with the standard calling convention in the case that the function called
|
||||||
|
* only with its fixed arguments. Thus, we do not need a special flag to be
|
||||||
|
* set on variadic functions. We treat a function as variadic if it is called
|
||||||
|
* with a nonzero number of variadic arguments */
|
||||||
|
bool is_variadic = (argtypecount != 0 && argcount > argtypecount);
|
||||||
|
(void) is_variadic;
|
||||||
|
|
||||||
|
#if defined(__APPLE__) && defined(__arm64__)
|
||||||
|
if (is_variadic) {
|
||||||
|
if (HAVE_FFI_PREP_CIF_VAR_RUNTIME) {
|
||||||
|
} else {
|
||||||
|
PyErr_SetString(PyExc_NotImplementedError, "ffi_prep_cif_var() is missing");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if HAVE_FFI_PREP_CIF_VAR
|
||||||
|
if (is_variadic) {
|
||||||
|
if (HAVE_FFI_PREP_CIF_VAR_RUNTIME) {
|
||||||
|
if (FFI_OK != ffi_prep_cif_var(&cif,
|
||||||
|
cc,
|
||||||
|
argtypecount,
|
||||||
|
argcount,
|
||||||
|
restype,
|
||||||
|
atypes)) {
|
||||||
|
PyErr_SetString(PyExc_RuntimeError,
|
||||||
|
"ffi_prep_cif_var failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (FFI_OK != ffi_prep_cif(&cif,
|
||||||
|
cc,
|
||||||
|
argcount,
|
||||||
|
restype,
|
||||||
|
atypes)) {
|
||||||
|
PyErr_SetString(PyExc_RuntimeError,
|
||||||
|
"ffi_prep_cif failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
|
||||||
|
{
|
||||||
|
if (FFI_OK != ffi_prep_cif(&cif,
|
||||||
|
cc,
|
||||||
|
argcount,
|
||||||
|
restype,
|
||||||
|
atypes)) {
|
||||||
|
PyErr_SetString(PyExc_RuntimeError,
|
||||||
|
"ffi_prep_cif failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & (FUNCFLAG_USE_ERRNO | FUNCFLAG_USE_LASTERROR)) {
|
if (flags & (FUNCFLAG_USE_ERRNO | FUNCFLAG_USE_LASTERROR)) {
|
||||||
|
@ -1212,9 +1275,8 @@ PyObject *_ctypes_callproc(PPROC pProc,
|
||||||
|
|
||||||
if (-1 == _call_function_pointer(flags, pProc, avalues, atypes,
|
if (-1 == _call_function_pointer(flags, pProc, avalues, atypes,
|
||||||
rtype, resbuf,
|
rtype, resbuf,
|
||||||
Py_SAFE_DOWNCAST(argcount,
|
Py_SAFE_DOWNCAST(argcount, Py_ssize_t, int),
|
||||||
Py_ssize_t,
|
Py_SAFE_DOWNCAST(argtype_count, Py_ssize_t, int)))
|
||||||
int)))
|
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
#ifdef WORDS_BIGENDIAN
|
#ifdef WORDS_BIGENDIAN
|
||||||
|
@ -1398,6 +1460,42 @@ copy_com_pointer(PyObject *self, PyObject *args)
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
#ifdef HAVE_DYLD_SHARED_CACHE_CONTAINS_PATH
|
||||||
|
static PyObject *py_dyld_shared_cache_contains_path(PyObject *self, PyObject *args)
|
||||||
|
{
|
||||||
|
PyObject *name, *name2;
|
||||||
|
char *name_str;
|
||||||
|
|
||||||
|
if (__builtin_available(macOS 11.0, iOS 14.0, tvOS 14.0, watchOS 7.0, *)) {
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (!PyArg_ParseTuple(args, "O", &name))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (name == Py_None)
|
||||||
|
Py_RETURN_FALSE;
|
||||||
|
|
||||||
|
if (PyUnicode_FSConverter(name, &name2) == 0)
|
||||||
|
return NULL;
|
||||||
|
name_str = PyBytes_AS_STRING(name2);
|
||||||
|
|
||||||
|
r = _dyld_shared_cache_contains_path(name_str);
|
||||||
|
Py_DECREF(name2);
|
||||||
|
|
||||||
|
if (r) {
|
||||||
|
Py_RETURN_TRUE;
|
||||||
|
} else {
|
||||||
|
Py_RETURN_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
PyErr_SetString(PyExc_NotImplementedError, "_dyld_shared_cache_contains_path symbol is missing");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static PyObject *py_dl_open(PyObject *self, PyObject *args)
|
static PyObject *py_dl_open(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
PyObject *name, *name2;
|
PyObject *name, *name2;
|
||||||
|
@ -1887,6 +1985,8 @@ buffer_info(PyObject *self, PyObject *arg)
|
||||||
return Py_BuildValue("siN", dict->format, dict->ndim, shape);
|
return Py_BuildValue("siN", dict->format, dict->ndim, shape);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
PyMethodDef _ctypes_module_methods[] = {
|
PyMethodDef _ctypes_module_methods[] = {
|
||||||
{"get_errno", get_errno, METH_NOARGS},
|
{"get_errno", get_errno, METH_NOARGS},
|
||||||
{"set_errno", set_errno, METH_VARARGS},
|
{"set_errno", set_errno, METH_VARARGS},
|
||||||
|
@ -1908,6 +2008,9 @@ PyMethodDef _ctypes_module_methods[] = {
|
||||||
"dlopen(name, flag={RTLD_GLOBAL|RTLD_LOCAL}) open a shared library"},
|
"dlopen(name, flag={RTLD_GLOBAL|RTLD_LOCAL}) open a shared library"},
|
||||||
{"dlclose", py_dl_close, METH_VARARGS, "dlclose a library"},
|
{"dlclose", py_dl_close, METH_VARARGS, "dlclose a library"},
|
||||||
{"dlsym", py_dl_sym, METH_VARARGS, "find symbol in shared library"},
|
{"dlsym", py_dl_sym, METH_VARARGS, "find symbol in shared library"},
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_DYLD_SHARED_CACHE_CONTAINS_PATH
|
||||||
|
{"_dyld_shared_cache_contains_path", py_dyld_shared_cache_contains_path, METH_VARARGS, "check if path is in the shared cache"},
|
||||||
#endif
|
#endif
|
||||||
{"alignment", align_func, METH_O, alignment_doc},
|
{"alignment", align_func, METH_O, alignment_doc},
|
||||||
{"sizeof", sizeof_func, METH_O, sizeof_doc},
|
{"sizeof", sizeof_func, METH_O, sizeof_doc},
|
||||||
|
|
|
@ -366,6 +366,14 @@ PyObject *_ctypes_get_errobj(int **pspace);
|
||||||
extern PyObject *ComError;
|
extern PyObject *ComError;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if USING_MALLOC_CLOSURE_DOT_C
|
||||||
|
void Py_ffi_closure_free(void *p);
|
||||||
|
void *Py_ffi_closure_alloc(size_t size, void** codeloc);
|
||||||
|
#else
|
||||||
|
#define Py_ffi_closure_free ffi_closure_free
|
||||||
|
#define Py_ffi_closure_alloc ffi_closure_alloc
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Local Variables:
|
Local Variables:
|
||||||
compile-command: "python setup.py -q build install --home ~"
|
compile-command: "python setup.py -q build install --home ~"
|
||||||
|
|
|
@ -89,16 +89,27 @@ static void more_core(void)
|
||||||
/******************************************************************/
|
/******************************************************************/
|
||||||
|
|
||||||
/* put the item back into the free list */
|
/* put the item back into the free list */
|
||||||
void ffi_closure_free(void *p)
|
void Py_ffi_closure_free(void *p)
|
||||||
{
|
{
|
||||||
|
#if USING_APPLE_OS_LIBFFI && HAVE_FFI_CLOSURE_ALLOC
|
||||||
|
if (__builtin_available(macos 10.15, ios 13, watchos 6, tvos 13, *)) {
|
||||||
|
ffi_closure_free(p);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
ITEM *item = (ITEM *)p;
|
ITEM *item = (ITEM *)p;
|
||||||
item->next = free_list;
|
item->next = free_list;
|
||||||
free_list = item;
|
free_list = item;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return one item from the free list, allocating more if needed */
|
/* return one item from the free list, allocating more if needed */
|
||||||
void *ffi_closure_alloc(size_t ignored, void** codeloc)
|
void *Py_ffi_closure_alloc(size_t size, void** codeloc)
|
||||||
{
|
{
|
||||||
|
#if USING_APPLE_OS_LIBFFI && HAVE_FFI_CLOSURE_ALLOC
|
||||||
|
if (__builtin_available(macos 10.15, ios 13, watchos 6, tvos 13, *)) {
|
||||||
|
return ffi_closure_alloc(size, codeloc);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
ITEM *item;
|
ITEM *item;
|
||||||
if (!free_list)
|
if (!free_list)
|
||||||
more_core();
|
more_core();
|
||||||
|
|
|
@ -923,11 +923,7 @@ static PyStatus
|
||||||
calculate_program_macos(wchar_t **abs_path_p)
|
calculate_program_macos(wchar_t **abs_path_p)
|
||||||
{
|
{
|
||||||
char execpath[MAXPATHLEN + 1];
|
char execpath[MAXPATHLEN + 1];
|
||||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
|
|
||||||
uint32_t nsexeclength = Py_ARRAY_LENGTH(execpath) - 1;
|
uint32_t nsexeclength = Py_ARRAY_LENGTH(execpath) - 1;
|
||||||
#else
|
|
||||||
unsigned long nsexeclength = Py_ARRAY_LENGTH(execpath) - 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* On Mac OS X, if a script uses an interpreter of the form
|
/* On Mac OS X, if a script uses an interpreter of the form
|
||||||
"#!/opt/python2.3/bin/python", the kernel only passes "python"
|
"#!/opt/python2.3/bin/python", the kernel only passes "python"
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -51,6 +51,15 @@
|
||||||
#define _Py_tzname tzname
|
#define _Py_tzname tzname
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(__APPLE__ ) && defined(__has_builtin)
|
||||||
|
# if __has_builtin(__builtin_available)
|
||||||
|
# define HAVE_CLOCK_GETTIME_RUNTIME __builtin_available(macOS 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *)
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
#ifndef HAVE_CLOCK_GETTIME_RUNTIME
|
||||||
|
# define HAVE_CLOCK_GETTIME_RUNTIME 1
|
||||||
|
#endif
|
||||||
|
|
||||||
#define SEC_TO_NS (1000 * 1000 * 1000)
|
#define SEC_TO_NS (1000 * 1000 * 1000)
|
||||||
|
|
||||||
/* Forward declarations */
|
/* Forward declarations */
|
||||||
|
@ -149,6 +158,16 @@ perf_counter(_Py_clock_info_t *info)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_CLOCK_GETTIME
|
#ifdef HAVE_CLOCK_GETTIME
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
/*
|
||||||
|
* The clock_* functions will be removed from the module
|
||||||
|
* dict entirely when the C API is not available.
|
||||||
|
*/
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wunguarded-availability"
|
||||||
|
#endif
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
time_clock_gettime(PyObject *self, PyObject *args)
|
time_clock_gettime(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
|
@ -297,6 +316,11 @@ PyDoc_STRVAR(clock_getres_doc,
|
||||||
"clock_getres(clk_id) -> floating point number\n\
|
"clock_getres(clk_id) -> floating point number\n\
|
||||||
\n\
|
\n\
|
||||||
Return the resolution (precision) of the specified clock clk_id.");
|
Return the resolution (precision) of the specified clock clk_id.");
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* HAVE_CLOCK_GETRES */
|
#endif /* HAVE_CLOCK_GETRES */
|
||||||
|
|
||||||
#ifdef HAVE_PTHREAD_GETCPUCLOCKID
|
#ifdef HAVE_PTHREAD_GETCPUCLOCKID
|
||||||
|
@ -1162,31 +1186,35 @@ _PyTime_GetProcessTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)
|
||||||
#if defined(HAVE_CLOCK_GETTIME) \
|
#if defined(HAVE_CLOCK_GETTIME) \
|
||||||
&& (defined(CLOCK_PROCESS_CPUTIME_ID) || defined(CLOCK_PROF))
|
&& (defined(CLOCK_PROCESS_CPUTIME_ID) || defined(CLOCK_PROF))
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
|
|
||||||
|
if (HAVE_CLOCK_GETTIME_RUNTIME) {
|
||||||
|
|
||||||
#ifdef CLOCK_PROF
|
#ifdef CLOCK_PROF
|
||||||
const clockid_t clk_id = CLOCK_PROF;
|
const clockid_t clk_id = CLOCK_PROF;
|
||||||
const char *function = "clock_gettime(CLOCK_PROF)";
|
const char *function = "clock_gettime(CLOCK_PROF)";
|
||||||
#else
|
#else
|
||||||
const clockid_t clk_id = CLOCK_PROCESS_CPUTIME_ID;
|
const clockid_t clk_id = CLOCK_PROCESS_CPUTIME_ID;
|
||||||
const char *function = "clock_gettime(CLOCK_PROCESS_CPUTIME_ID)";
|
const char *function = "clock_gettime(CLOCK_PROCESS_CPUTIME_ID)";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (clock_gettime(clk_id, &ts) == 0) {
|
if (clock_gettime(clk_id, &ts) == 0) {
|
||||||
if (info) {
|
if (info) {
|
||||||
struct timespec res;
|
struct timespec res;
|
||||||
info->implementation = function;
|
info->implementation = function;
|
||||||
info->monotonic = 1;
|
info->monotonic = 1;
|
||||||
info->adjustable = 0;
|
info->adjustable = 0;
|
||||||
if (clock_getres(clk_id, &res)) {
|
if (clock_getres(clk_id, &res)) {
|
||||||
PyErr_SetFromErrno(PyExc_OSError);
|
PyErr_SetFromErrno(PyExc_OSError);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
info->resolution = res.tv_sec + res.tv_nsec * 1e-9;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_PyTime_FromTimespec(tp, &ts) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
info->resolution = res.tv_sec + res.tv_nsec * 1e-9;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_PyTime_FromTimespec(tp, &ts) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1390,6 +1418,16 @@ _PyTime_GetThreadTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)
|
||||||
|
|
||||||
#elif defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_PROCESS_CPUTIME_ID)
|
#elif defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_PROCESS_CPUTIME_ID)
|
||||||
#define HAVE_THREAD_TIME
|
#define HAVE_THREAD_TIME
|
||||||
|
|
||||||
|
#if defined(__APPLE__) && defined(__has_attribute) && __has_attribute(availability)
|
||||||
|
static int
|
||||||
|
_PyTime_GetThreadTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)
|
||||||
|
__attribute__((availability(macos, introduced=10.12)))
|
||||||
|
__attribute__((availability(ios, introduced=10.0)))
|
||||||
|
__attribute__((availability(tvos, introduced=10.0)))
|
||||||
|
__attribute__((availability(watchos, introduced=3.0)));
|
||||||
|
#endif
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_PyTime_GetThreadTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)
|
_PyTime_GetThreadTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)
|
||||||
{
|
{
|
||||||
|
@ -1421,6 +1459,15 @@ _PyTime_GetThreadTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_THREAD_TIME
|
#ifdef HAVE_THREAD_TIME
|
||||||
|
#ifdef __APPLE__
|
||||||
|
/*
|
||||||
|
* The clock_* functions will be removed from the module
|
||||||
|
* dict entirely when the C API is not available.
|
||||||
|
*/
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wunguarded-availability"
|
||||||
|
#endif
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
time_thread_time(PyObject *self, PyObject *unused)
|
time_thread_time(PyObject *self, PyObject *unused)
|
||||||
{
|
{
|
||||||
|
@ -1451,6 +1498,11 @@ PyDoc_STRVAR(thread_time_ns_doc,
|
||||||
\n\
|
\n\
|
||||||
Thread time for profiling as nanoseconds:\n\
|
Thread time for profiling as nanoseconds:\n\
|
||||||
sum of the kernel and user-space CPU time.");
|
sum of the kernel and user-space CPU time.");
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -1500,9 +1552,19 @@ time_get_clock_info(PyObject *self, PyObject *args)
|
||||||
}
|
}
|
||||||
#ifdef HAVE_THREAD_TIME
|
#ifdef HAVE_THREAD_TIME
|
||||||
else if (strcmp(name, "thread_time") == 0) {
|
else if (strcmp(name, "thread_time") == 0) {
|
||||||
if (_PyTime_GetThreadTimeWithInfo(&t, &info) < 0) {
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
if (HAVE_CLOCK_GETTIME_RUNTIME) {
|
||||||
|
#endif
|
||||||
|
if (_PyTime_GetThreadTimeWithInfo(&t, &info) < 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#ifdef __APPLE__
|
||||||
|
} else {
|
||||||
|
PyErr_SetString(PyExc_ValueError, "unknown clock");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
else {
|
else {
|
||||||
|
@ -1783,68 +1845,116 @@ if it is -1, mktime() should guess based on the date and time.\n");
|
||||||
static int
|
static int
|
||||||
time_exec(PyObject *module)
|
time_exec(PyObject *module)
|
||||||
{
|
{
|
||||||
|
#if defined(__APPLE__) && defined(HAVE_CLOCK_GETTIME)
|
||||||
|
if (HAVE_CLOCK_GETTIME_RUNTIME) {
|
||||||
|
/* pass: ^^^ cannot use '!' here */
|
||||||
|
} else {
|
||||||
|
PyObject* dct = PyModule_GetDict(module);
|
||||||
|
if (dct == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PyDict_DelItemString(dct, "clock_gettime") == -1) {
|
||||||
|
PyErr_Clear();
|
||||||
|
}
|
||||||
|
if (PyDict_DelItemString(dct, "clock_gettime_ns") == -1) {
|
||||||
|
PyErr_Clear();
|
||||||
|
}
|
||||||
|
if (PyDict_DelItemString(dct, "clock_settime") == -1) {
|
||||||
|
PyErr_Clear();
|
||||||
|
}
|
||||||
|
if (PyDict_DelItemString(dct, "clock_settime_ns") == -1) {
|
||||||
|
PyErr_Clear();
|
||||||
|
}
|
||||||
|
if (PyDict_DelItemString(dct, "clock_getres") == -1) {
|
||||||
|
PyErr_Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if defined(__APPLE__) && defined(HAVE_THREAD_TIME)
|
||||||
|
if (HAVE_CLOCK_GETTIME_RUNTIME) {
|
||||||
|
/* pass: ^^^ cannot use '!' here */
|
||||||
|
} else {
|
||||||
|
PyObject* dct = PyModule_GetDict(module);
|
||||||
|
|
||||||
|
if (PyDict_DelItemString(dct, "thread_time") == -1) {
|
||||||
|
PyErr_Clear();
|
||||||
|
}
|
||||||
|
if (PyDict_DelItemString(dct, "thread_time_ns") == -1) {
|
||||||
|
PyErr_Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
/* Set, or reset, module variables like time.timezone */
|
/* Set, or reset, module variables like time.timezone */
|
||||||
if (init_timezone(module) < 0) {
|
if (init_timezone(module) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_CLOCK_SETTIME) || defined(HAVE_CLOCK_GETRES)
|
#if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_CLOCK_SETTIME) || defined(HAVE_CLOCK_GETRES)
|
||||||
|
if (HAVE_CLOCK_GETTIME_RUNTIME) {
|
||||||
|
|
||||||
#ifdef CLOCK_REALTIME
|
#ifdef CLOCK_REALTIME
|
||||||
if (PyModule_AddIntMacro(module, CLOCK_REALTIME) < 0) {
|
if (PyModule_AddIntMacro(module, CLOCK_REALTIME) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CLOCK_MONOTONIC
|
#ifdef CLOCK_MONOTONIC
|
||||||
if (PyModule_AddIntMacro(module, CLOCK_MONOTONIC) < 0) {
|
|
||||||
return -1;
|
if (PyModule_AddIntMacro(module, CLOCK_MONOTONIC) < 0) {
|
||||||
}
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef CLOCK_MONOTONIC_RAW
|
#ifdef CLOCK_MONOTONIC_RAW
|
||||||
if (PyModule_AddIntMacro(module, CLOCK_MONOTONIC_RAW) < 0) {
|
if (PyModule_AddIntMacro(module, CLOCK_MONOTONIC_RAW) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CLOCK_HIGHRES
|
#ifdef CLOCK_HIGHRES
|
||||||
if (PyModule_AddIntMacro(module, CLOCK_HIGHRES) < 0) {
|
if (PyModule_AddIntMacro(module, CLOCK_HIGHRES) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef CLOCK_PROCESS_CPUTIME_ID
|
#ifdef CLOCK_PROCESS_CPUTIME_ID
|
||||||
if (PyModule_AddIntMacro(module, CLOCK_PROCESS_CPUTIME_ID) < 0) {
|
if (PyModule_AddIntMacro(module, CLOCK_PROCESS_CPUTIME_ID) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CLOCK_THREAD_CPUTIME_ID
|
#ifdef CLOCK_THREAD_CPUTIME_ID
|
||||||
if (PyModule_AddIntMacro(module, CLOCK_THREAD_CPUTIME_ID) < 0) {
|
if (PyModule_AddIntMacro(module, CLOCK_THREAD_CPUTIME_ID) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef CLOCK_PROF
|
#ifdef CLOCK_PROF
|
||||||
if (PyModule_AddIntMacro(module, CLOCK_PROF) < 0) {
|
if (PyModule_AddIntMacro(module, CLOCK_PROF) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef CLOCK_BOOTTIME
|
#ifdef CLOCK_BOOTTIME
|
||||||
if (PyModule_AddIntMacro(module, CLOCK_BOOTTIME) < 0) {
|
if (PyModule_AddIntMacro(module, CLOCK_BOOTTIME) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef CLOCK_TAI
|
#ifdef CLOCK_TAI
|
||||||
if (PyModule_AddIntMacro(module, CLOCK_TAI) < 0) {
|
if (PyModule_AddIntMacro(module, CLOCK_TAI) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef CLOCK_UPTIME
|
#ifdef CLOCK_UPTIME
|
||||||
if (PyModule_AddIntMacro(module, CLOCK_UPTIME) < 0) {
|
if (PyModule_AddIntMacro(module, CLOCK_UPTIME) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef CLOCK_UPTIME_RAW
|
#ifdef CLOCK_UPTIME_RAW
|
||||||
if (PyModule_AddIntMacro(module, CLOCK_UPTIME_RAW) < 0) {
|
|
||||||
return -1;
|
if (PyModule_AddIntMacro(module, CLOCK_UPTIME_RAW) < 0) {
|
||||||
}
|
return -1;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* defined(HAVE_CLOCK_GETTIME) || defined(HAVE_CLOCK_SETTIME) || defined(HAVE_CLOCK_GETRES) */
|
#endif /* defined(HAVE_CLOCK_GETTIME) || defined(HAVE_CLOCK_SETTIME) || defined(HAVE_CLOCK_GETRES) */
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,16 @@
|
||||||
# include <sanitizer/msan_interface.h>
|
# include <sanitizer/msan_interface.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(__APPLE__) && defined(__has_builtin)
|
||||||
|
# if __has_builtin(__builtin_available)
|
||||||
|
# define HAVE_GETENTRYPY_GETRANDOM_RUNTIME __builtin_available(macOS 10.12, iOS 10.10, tvOS 10.0, watchOS 3.0, *)
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
#ifndef HAVE_GETENTRYPY_GETRANDOM_RUNTIME
|
||||||
|
# define HAVE_GETENTRYPY_GETRANDOM_RUNTIME 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef Py_DEBUG
|
#ifdef Py_DEBUG
|
||||||
int _Py_HashSecret_Initialized = 0;
|
int _Py_HashSecret_Initialized = 0;
|
||||||
#else
|
#else
|
||||||
|
@ -208,6 +218,16 @@ py_getrandom(void *buffer, Py_ssize_t size, int blocking, int raise)
|
||||||
error.
|
error.
|
||||||
|
|
||||||
getentropy() is retried if it failed with EINTR: interrupted by a signal. */
|
getentropy() is retried if it failed with EINTR: interrupted by a signal. */
|
||||||
|
|
||||||
|
#if defined(__APPLE__) && defined(__has_attribute) && __has_attribute(availability)
|
||||||
|
static int
|
||||||
|
py_getentropy(char *buffer, Py_ssize_t size, int raise)
|
||||||
|
__attribute__((availability(macos,introduced=10.12)))
|
||||||
|
__attribute__((availability(ios,introduced=10.0)))
|
||||||
|
__attribute__((availability(tvos,introduced=10.0)))
|
||||||
|
__attribute__((availability(watchos,introduced=3.0)));
|
||||||
|
#endif
|
||||||
|
|
||||||
static int
|
static int
|
||||||
py_getentropy(char *buffer, Py_ssize_t size, int raise)
|
py_getentropy(char *buffer, Py_ssize_t size, int raise)
|
||||||
{
|
{
|
||||||
|
@ -498,19 +518,21 @@ pyurandom(void *buffer, Py_ssize_t size, int blocking, int raise)
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#if defined(PY_GETRANDOM) || defined(PY_GETENTROPY)
|
#if defined(PY_GETRANDOM) || defined(PY_GETENTROPY)
|
||||||
|
if (HAVE_GETENTRYPY_GETRANDOM_RUNTIME) {
|
||||||
#ifdef PY_GETRANDOM
|
#ifdef PY_GETRANDOM
|
||||||
res = py_getrandom(buffer, size, blocking, raise);
|
res = py_getrandom(buffer, size, blocking, raise);
|
||||||
#else
|
#else
|
||||||
res = py_getentropy(buffer, size, raise);
|
res = py_getentropy(buffer, size, raise);
|
||||||
#endif
|
#endif
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (res == 1) {
|
if (res == 1) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* getrandom() or getentropy() function is not available: failed with
|
/* getrandom() or getentropy() function is not available: failed with
|
||||||
ENOSYS or EPERM. Fall back on reading from /dev/urandom. */
|
ENOSYS or EPERM. Fall back on reading from /dev/urandom. */
|
||||||
|
} /* end of availability block */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return dev_urandom(buffer, size, raise);
|
return dev_urandom(buffer, size, raise);
|
||||||
|
|
|
@ -5,6 +5,12 @@
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
#include <mach/mach_time.h> /* mach_absolute_time(), mach_timebase_info() */
|
#include <mach/mach_time.h> /* mach_absolute_time(), mach_timebase_info() */
|
||||||
|
|
||||||
|
#if defined(__APPLE__) && defined(__has_builtin)
|
||||||
|
# if __has_builtin(__builtin_available)
|
||||||
|
# define HAVE_CLOCK_GETTIME_RUNTIME __builtin_available(macOS 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *)
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define _PyTime_check_mul_overflow(a, b) \
|
#define _PyTime_check_mul_overflow(a, b) \
|
||||||
|
@ -683,15 +689,22 @@ pygettimeofday(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
|
||||||
|
|
||||||
#else /* MS_WINDOWS */
|
#else /* MS_WINDOWS */
|
||||||
int err;
|
int err;
|
||||||
#ifdef HAVE_CLOCK_GETTIME
|
#if defined(HAVE_CLOCK_GETTIME)
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
#else
|
#endif
|
||||||
|
|
||||||
|
#if !defined(HAVE_CLOCK_GETTIME) || defined(__APPLE__)
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
assert(info == NULL || raise);
|
assert(info == NULL || raise);
|
||||||
|
|
||||||
#ifdef HAVE_CLOCK_GETTIME
|
#ifdef HAVE_CLOCK_GETTIME
|
||||||
|
|
||||||
|
#ifdef HAVE_CLOCK_GETTIME_RUNTIME
|
||||||
|
if (HAVE_CLOCK_GETTIME_RUNTIME) {
|
||||||
|
#endif
|
||||||
|
|
||||||
err = clock_gettime(CLOCK_REALTIME, &ts);
|
err = clock_gettime(CLOCK_REALTIME, &ts);
|
||||||
if (err) {
|
if (err) {
|
||||||
if (raise) {
|
if (raise) {
|
||||||
|
@ -715,7 +728,14 @@ pygettimeofday(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
|
||||||
info->resolution = 1e-9;
|
info->resolution = 1e-9;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else /* HAVE_CLOCK_GETTIME */
|
|
||||||
|
#ifdef HAVE_CLOCK_GETTIME_RUNTIME
|
||||||
|
} else {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(HAVE_CLOCK_GETTIME) || defined(HAVE_CLOCK_GETTIME_RUNTIME)
|
||||||
|
|
||||||
/* test gettimeofday() */
|
/* test gettimeofday() */
|
||||||
err = gettimeofday(&tv, (struct timezone *)NULL);
|
err = gettimeofday(&tv, (struct timezone *)NULL);
|
||||||
|
@ -735,6 +755,11 @@ pygettimeofday(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
|
||||||
info->monotonic = 0;
|
info->monotonic = 0;
|
||||||
info->adjustable = 1;
|
info->adjustable = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(HAVE_CLOCK_GETTIME_RUNTIME) && defined(HAVE_CLOCK_GETTIME)
|
||||||
|
} /* end of availibity block */
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* !HAVE_CLOCK_GETTIME */
|
#endif /* !HAVE_CLOCK_GETTIME */
|
||||||
#endif /* !MS_WINDOWS */
|
#endif /* !MS_WINDOWS */
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -1511,8 +1511,8 @@ Optional Packages:
|
||||||
specify the kind of universal binary that should be
|
specify the kind of universal binary that should be
|
||||||
created. this option is only valid when
|
created. this option is only valid when
|
||||||
--enable-universalsdk is set; options are:
|
--enable-universalsdk is set; options are:
|
||||||
("32-bit", "64-bit", "3-way", "intel", "intel-32",
|
("universal2", "32-bit", "64-bit", "3-way", "intel",
|
||||||
"intel-64", or "all") see Mac/README.rst
|
"intel-32", "intel-64", or "all") see Mac/README.rst
|
||||||
--with-framework-name=FRAMEWORK
|
--with-framework-name=FRAMEWORK
|
||||||
specify the name for the python framework on macOS
|
specify the name for the python framework on macOS
|
||||||
only valid when --enable-framework is set. see
|
only valid when --enable-framework is set. see
|
||||||
|
@ -7002,7 +7002,7 @@ fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# The -arch flags for universal builds on OSX
|
# The -arch flags for universal builds on macOS
|
||||||
UNIVERSAL_ARCH_FLAGS=
|
UNIVERSAL_ARCH_FLAGS=
|
||||||
|
|
||||||
|
|
||||||
|
@ -7529,6 +7529,11 @@ $as_echo "$CC" >&6; }
|
||||||
LIPO_32BIT_FLAGS="-extract ppc7400 -extract i386"
|
LIPO_32BIT_FLAGS="-extract ppc7400 -extract i386"
|
||||||
ARCH_RUN_32BIT="/usr/bin/arch -i386 -ppc"
|
ARCH_RUN_32BIT="/usr/bin/arch -i386 -ppc"
|
||||||
;;
|
;;
|
||||||
|
universal2)
|
||||||
|
UNIVERSAL_ARCH_FLAGS="-arch arm64 -arch x86_64"
|
||||||
|
LIPO_32BIT_FLAGS=""
|
||||||
|
ARCH_RUN_32BIT="true"
|
||||||
|
;;
|
||||||
intel)
|
intel)
|
||||||
UNIVERSAL_ARCH_FLAGS="-arch i386 -arch x86_64"
|
UNIVERSAL_ARCH_FLAGS="-arch i386 -arch x86_64"
|
||||||
LIPO_32BIT_FLAGS="-extract i386"
|
LIPO_32BIT_FLAGS="-extract i386"
|
||||||
|
@ -7550,7 +7555,7 @@ $as_echo "$CC" >&6; }
|
||||||
ARCH_RUN_32BIT="/usr/bin/arch -i386 -ppc"
|
ARCH_RUN_32BIT="/usr/bin/arch -i386 -ppc"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
as_fn_error $? "proper usage is --with-universal-arch=32-bit|64-bit|all|intel|3-way" "$LINENO" 5
|
as_fn_error $? "proper usage is --with-universal-arch=universal2|32-bit|64-bit|all|intel|3-way" "$LINENO" 5
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
@ -9382,7 +9387,7 @@ fi
|
||||||
MACOSX_DEFAULT_ARCH="ppc"
|
MACOSX_DEFAULT_ARCH="ppc"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
as_fn_error $? "Unexpected output of 'arch' on OSX" "$LINENO" 5
|
as_fn_error $? "Unexpected output of 'arch' on macOS" "$LINENO" 5
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
else
|
else
|
||||||
|
@ -9392,9 +9397,12 @@ fi
|
||||||
;;
|
;;
|
||||||
ppc)
|
ppc)
|
||||||
MACOSX_DEFAULT_ARCH="ppc64"
|
MACOSX_DEFAULT_ARCH="ppc64"
|
||||||
|
;;
|
||||||
|
arm64)
|
||||||
|
MACOSX_DEFAULT_ARCH="arm64"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
as_fn_error $? "Unexpected output of 'arch' on OSX" "$LINENO" 5
|
as_fn_error $? "Unexpected output of 'arch' on macOS" "$LINENO" 5
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
@ -12029,6 +12037,31 @@ else
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||||
$as_echo "no" >&6; }
|
$as_echo "no" >&6; }
|
||||||
|
|
||||||
|
fi
|
||||||
|
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for _dyld_shared_cache_contains_path" >&5
|
||||||
|
$as_echo_n "checking for _dyld_shared_cache_contains_path... " >&6; }
|
||||||
|
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||||
|
/* end confdefs.h. */
|
||||||
|
#include <mach-o/dyld.h>
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
void *x=_dyld_shared_cache_contains_path
|
||||||
|
;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
_ACEOF
|
||||||
|
if ac_fn_c_try_compile "$LINENO"; then :
|
||||||
|
|
||||||
|
$as_echo "#define HAVE_DYLD_SHARED_CACHE_CONTAINS_PATH 1" >>confdefs.h
|
||||||
|
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||||
|
$as_echo "yes" >&6; }
|
||||||
|
else
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||||
|
$as_echo "no" >&6; }
|
||||||
|
|
||||||
fi
|
fi
|
||||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||||
|
|
||||||
|
|
24
configure.ac
24
configure.ac
|
@ -218,7 +218,7 @@ AC_ARG_WITH(universal-archs,
|
||||||
AS_HELP_STRING([--with-universal-archs=ARCH],
|
AS_HELP_STRING([--with-universal-archs=ARCH],
|
||||||
[specify the kind of universal binary that should be created. this option is
|
[specify the kind of universal binary that should be created. this option is
|
||||||
only valid when --enable-universalsdk is set; options are:
|
only valid when --enable-universalsdk is set; options are:
|
||||||
("32-bit", "64-bit", "3-way", "intel", "intel-32", "intel-64", or "all")
|
("universal2", "32-bit", "64-bit", "3-way", "intel", "intel-32", "intel-64", or "all")
|
||||||
see Mac/README.rst]),
|
see Mac/README.rst]),
|
||||||
[
|
[
|
||||||
UNIVERSAL_ARCHS="$withval"
|
UNIVERSAL_ARCHS="$withval"
|
||||||
|
@ -1597,7 +1597,7 @@ AC_SUBST(BASECFLAGS)
|
||||||
AC_SUBST(CFLAGS_NODIST)
|
AC_SUBST(CFLAGS_NODIST)
|
||||||
AC_SUBST(LDFLAGS_NODIST)
|
AC_SUBST(LDFLAGS_NODIST)
|
||||||
|
|
||||||
# The -arch flags for universal builds on OSX
|
# The -arch flags for universal builds on macOS
|
||||||
UNIVERSAL_ARCH_FLAGS=
|
UNIVERSAL_ARCH_FLAGS=
|
||||||
AC_SUBST(UNIVERSAL_ARCH_FLAGS)
|
AC_SUBST(UNIVERSAL_ARCH_FLAGS)
|
||||||
|
|
||||||
|
@ -1898,6 +1898,11 @@ yes)
|
||||||
LIPO_32BIT_FLAGS="-extract ppc7400 -extract i386"
|
LIPO_32BIT_FLAGS="-extract ppc7400 -extract i386"
|
||||||
ARCH_RUN_32BIT="/usr/bin/arch -i386 -ppc"
|
ARCH_RUN_32BIT="/usr/bin/arch -i386 -ppc"
|
||||||
;;
|
;;
|
||||||
|
universal2)
|
||||||
|
UNIVERSAL_ARCH_FLAGS="-arch arm64 -arch x86_64"
|
||||||
|
LIPO_32BIT_FLAGS=""
|
||||||
|
ARCH_RUN_32BIT="true"
|
||||||
|
;;
|
||||||
intel)
|
intel)
|
||||||
UNIVERSAL_ARCH_FLAGS="-arch i386 -arch x86_64"
|
UNIVERSAL_ARCH_FLAGS="-arch i386 -arch x86_64"
|
||||||
LIPO_32BIT_FLAGS="-extract i386"
|
LIPO_32BIT_FLAGS="-extract i386"
|
||||||
|
@ -1919,7 +1924,7 @@ yes)
|
||||||
ARCH_RUN_32BIT="/usr/bin/arch -i386 -ppc"
|
ARCH_RUN_32BIT="/usr/bin/arch -i386 -ppc"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
AC_MSG_ERROR([proper usage is --with-universal-arch=32-bit|64-bit|all|intel|3-way])
|
AC_MSG_ERROR([proper usage is --with-universal-arch=universal2|32-bit|64-bit|all|intel|3-way])
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
@ -2489,7 +2494,7 @@ case $ac_sys_system/$ac_sys_release in
|
||||||
MACOSX_DEFAULT_ARCH="ppc"
|
MACOSX_DEFAULT_ARCH="ppc"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
AC_MSG_ERROR([Unexpected output of 'arch' on OSX])
|
AC_MSG_ERROR([Unexpected output of 'arch' on macOS])
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
else
|
else
|
||||||
|
@ -2499,9 +2504,12 @@ case $ac_sys_system/$ac_sys_release in
|
||||||
;;
|
;;
|
||||||
ppc)
|
ppc)
|
||||||
MACOSX_DEFAULT_ARCH="ppc64"
|
MACOSX_DEFAULT_ARCH="ppc64"
|
||||||
|
;;
|
||||||
|
arm64)
|
||||||
|
MACOSX_DEFAULT_ARCH="arm64"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
AC_MSG_ERROR([Unexpected output of 'arch' on OSX])
|
AC_MSG_ERROR([Unexpected output of 'arch' on macOS])
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
@ -3774,6 +3782,12 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||||
AC_MSG_RESULT(yes)],
|
AC_MSG_RESULT(yes)],
|
||||||
[AC_MSG_RESULT(no)
|
[AC_MSG_RESULT(no)
|
||||||
])
|
])
|
||||||
|
AC_MSG_CHECKING(for _dyld_shared_cache_contains_path)
|
||||||
|
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <mach-o/dyld.h>]], [[void *x=_dyld_shared_cache_contains_path]])],
|
||||||
|
[AC_DEFINE(HAVE_DYLD_SHARED_CACHE_CONTAINS_PATH, 1, Define if you have the '_dyld_shared_cache_contains_path' function.)
|
||||||
|
AC_MSG_RESULT(yes)],
|
||||||
|
[AC_MSG_RESULT(no)
|
||||||
|
])
|
||||||
|
|
||||||
AC_MSG_CHECKING(for memfd_create)
|
AC_MSG_CHECKING(for memfd_create)
|
||||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||||
|
|
|
@ -784,6 +784,9 @@
|
||||||
/* Define if you have the 'prlimit' functions. */
|
/* Define if you have the 'prlimit' functions. */
|
||||||
#undef HAVE_PRLIMIT
|
#undef HAVE_PRLIMIT
|
||||||
|
|
||||||
|
/* Define if you have the '_dyld_shared_cache_contains_path' function. */
|
||||||
|
#undef HAVE_DYLD_SHARED_CACHE_CONTAINS_PATH
|
||||||
|
|
||||||
/* Define to 1 if you have the <process.h> header file. */
|
/* Define to 1 if you have the <process.h> header file. */
|
||||||
#undef HAVE_PROCESS_H
|
#undef HAVE_PROCESS_H
|
||||||
|
|
||||||
|
|
92
setup.py
92
setup.py
|
@ -239,6 +239,13 @@ def is_macosx_sdk_path(path):
|
||||||
or path.startswith('/Library/') )
|
or path.startswith('/Library/') )
|
||||||
|
|
||||||
|
|
||||||
|
def grep_headers_for(function, headers):
|
||||||
|
for header in headers:
|
||||||
|
with open(header, 'r') as f:
|
||||||
|
if function in f.read():
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
def find_file(filename, std_dirs, paths):
|
def find_file(filename, std_dirs, paths):
|
||||||
"""Searches for the directory where a given file is located,
|
"""Searches for the directory where a given file is located,
|
||||||
and returns a possibly-empty list of additional directories, or None
|
and returns a possibly-empty list of additional directories, or None
|
||||||
|
@ -2105,43 +2112,17 @@ class PyBuildExt(build_ext):
|
||||||
library_dirs=added_lib_dirs))
|
library_dirs=added_lib_dirs))
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def configure_ctypes_darwin(self, ext):
|
|
||||||
# Darwin (OS X) uses preconfigured files, in
|
|
||||||
# the Modules/_ctypes/libffi_osx directory.
|
|
||||||
ffi_srcdir = os.path.abspath(os.path.join(self.srcdir, 'Modules',
|
|
||||||
'_ctypes', 'libffi_osx'))
|
|
||||||
sources = [os.path.join(ffi_srcdir, p)
|
|
||||||
for p in ['ffi.c',
|
|
||||||
'x86/darwin64.S',
|
|
||||||
'x86/x86-darwin.S',
|
|
||||||
'x86/x86-ffi_darwin.c',
|
|
||||||
'x86/x86-ffi64.c',
|
|
||||||
'powerpc/ppc-darwin.S',
|
|
||||||
'powerpc/ppc-darwin_closure.S',
|
|
||||||
'powerpc/ppc-ffi_darwin.c',
|
|
||||||
'powerpc/ppc64-darwin_closure.S',
|
|
||||||
]]
|
|
||||||
|
|
||||||
# Add .S (preprocessed assembly) to C compiler source extensions.
|
|
||||||
self.compiler.src_extensions.append('.S')
|
|
||||||
|
|
||||||
include_dirs = [os.path.join(ffi_srcdir, 'include'),
|
|
||||||
os.path.join(ffi_srcdir, 'powerpc')]
|
|
||||||
ext.include_dirs.extend(include_dirs)
|
|
||||||
ext.sources.extend(sources)
|
|
||||||
return True
|
|
||||||
|
|
||||||
def configure_ctypes(self, ext):
|
def configure_ctypes(self, ext):
|
||||||
if not self.use_system_libffi:
|
|
||||||
if MACOS:
|
|
||||||
return self.configure_ctypes_darwin(ext)
|
|
||||||
print('INFO: Could not locate ffi libs and/or headers')
|
|
||||||
return False
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def detect_ctypes(self):
|
def detect_ctypes(self):
|
||||||
# Thomas Heller's _ctypes module
|
# Thomas Heller's _ctypes module
|
||||||
self.use_system_libffi = False
|
|
||||||
|
if (not sysconfig.get_config_var("LIBFFI_INCLUDEDIR") and MACOS):
|
||||||
|
self.use_system_libffi = True
|
||||||
|
else:
|
||||||
|
self.use_system_libffi = '--with-system-ffi' in sysconfig.get_config_var("CONFIG_ARGS")
|
||||||
|
|
||||||
include_dirs = []
|
include_dirs = []
|
||||||
extra_compile_args = ['-DPy_BUILD_CORE_MODULE']
|
extra_compile_args = ['-DPy_BUILD_CORE_MODULE']
|
||||||
extra_link_args = []
|
extra_link_args = []
|
||||||
|
@ -2154,11 +2135,9 @@ class PyBuildExt(build_ext):
|
||||||
|
|
||||||
if MACOS:
|
if MACOS:
|
||||||
sources.append('_ctypes/malloc_closure.c')
|
sources.append('_ctypes/malloc_closure.c')
|
||||||
sources.append('_ctypes/darwin/dlfcn_simple.c')
|
extra_compile_args.append('-DUSING_MALLOC_CLOSURE_DOT_C=1')
|
||||||
extra_compile_args.append('-DMACOSX')
|
extra_compile_args.append('-DMACOSX')
|
||||||
include_dirs.append('_ctypes/darwin')
|
include_dirs.append('_ctypes/darwin')
|
||||||
# XXX Is this still needed?
|
|
||||||
# extra_link_args.extend(['-read_only_relocs', 'warning'])
|
|
||||||
|
|
||||||
elif HOST_PLATFORM == 'sunos5':
|
elif HOST_PLATFORM == 'sunos5':
|
||||||
# XXX This shouldn't be necessary; it appears that some
|
# XXX This shouldn't be necessary; it appears that some
|
||||||
|
@ -2188,31 +2167,48 @@ class PyBuildExt(build_ext):
|
||||||
sources=['_ctypes/_ctypes_test.c'],
|
sources=['_ctypes/_ctypes_test.c'],
|
||||||
libraries=['m']))
|
libraries=['m']))
|
||||||
|
|
||||||
|
ffi_inc = sysconfig.get_config_var("LIBFFI_INCLUDEDIR")
|
||||||
|
ffi_lib = None
|
||||||
|
|
||||||
ffi_inc_dirs = self.inc_dirs.copy()
|
ffi_inc_dirs = self.inc_dirs.copy()
|
||||||
if MACOS:
|
if MACOS:
|
||||||
if '--with-system-ffi' not in sysconfig.get_config_var("CONFIG_ARGS"):
|
ffi_in_sdk = os.path.join(macosx_sdk_root(), "usr/include/ffi")
|
||||||
return
|
|
||||||
# OS X 10.5 comes with libffi.dylib; the include files are
|
|
||||||
# in /usr/include/ffi
|
|
||||||
ffi_inc_dirs.append('/usr/include/ffi')
|
|
||||||
|
|
||||||
ffi_inc = [sysconfig.get_config_var("LIBFFI_INCLUDEDIR")]
|
if not ffi_inc:
|
||||||
if not ffi_inc or ffi_inc[0] == '':
|
if os.path.exists(ffi_in_sdk):
|
||||||
ffi_inc = find_file('ffi.h', [], ffi_inc_dirs)
|
ext.extra_compile_args.append("-DUSING_APPLE_OS_LIBFFI=1")
|
||||||
if ffi_inc is not None:
|
ffi_inc = ffi_in_sdk
|
||||||
ffi_h = ffi_inc[0] + '/ffi.h'
|
ffi_lib = 'ffi'
|
||||||
|
else:
|
||||||
|
# OS X 10.5 comes with libffi.dylib; the include files are
|
||||||
|
# in /usr/include/ffi
|
||||||
|
ffi_inc_dirs.append('/usr/include/ffi')
|
||||||
|
|
||||||
|
if not ffi_inc:
|
||||||
|
found = find_file('ffi.h', [], ffi_inc_dirs)
|
||||||
|
if found:
|
||||||
|
ffi_inc = found[0]
|
||||||
|
if ffi_inc:
|
||||||
|
ffi_h = ffi_inc + '/ffi.h'
|
||||||
if not os.path.exists(ffi_h):
|
if not os.path.exists(ffi_h):
|
||||||
ffi_inc = None
|
ffi_inc = None
|
||||||
print('Header file {} does not exist'.format(ffi_h))
|
print('Header file {} does not exist'.format(ffi_h))
|
||||||
ffi_lib = None
|
if ffi_lib is None and ffi_inc:
|
||||||
if ffi_inc is not None:
|
|
||||||
for lib_name in ('ffi', 'ffi_pic'):
|
for lib_name in ('ffi', 'ffi_pic'):
|
||||||
if (self.compiler.find_library_file(self.lib_dirs, lib_name)):
|
if (self.compiler.find_library_file(self.lib_dirs, lib_name)):
|
||||||
ffi_lib = lib_name
|
ffi_lib = lib_name
|
||||||
break
|
break
|
||||||
|
|
||||||
if ffi_inc and ffi_lib:
|
if ffi_inc and ffi_lib:
|
||||||
ext.include_dirs.extend(ffi_inc)
|
ffi_headers = glob(os.path.join(ffi_inc, '*.h'))
|
||||||
|
if grep_headers_for('ffi_prep_cif_var', ffi_headers):
|
||||||
|
ext.extra_compile_args.append("-DHAVE_FFI_PREP_CIF_VAR=1")
|
||||||
|
if grep_headers_for('ffi_prep_closure_loc', ffi_headers):
|
||||||
|
ext.extra_compile_args.append("-DHAVE_FFI_PREP_CLOSURE_LOC=1")
|
||||||
|
if grep_headers_for('ffi_closure_alloc', ffi_headers):
|
||||||
|
ext.extra_compile_args.append("-DHAVE_FFI_CLOSURE_ALLOC=1")
|
||||||
|
|
||||||
|
ext.include_dirs.append(ffi_inc)
|
||||||
ext.libraries.append(ffi_lib)
|
ext.libraries.append(ffi_lib)
|
||||||
self.use_system_libffi = True
|
self.use_system_libffi = True
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue