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
|
||||
|
||||
_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):
|
||||
"""Remove original unmodified values for testing"""
|
||||
# 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
|
||||
# is in support of allowing 10.4 universal builds to run on 10.3.x systems.
|
||||
|
||||
osx_version = _get_system_version()
|
||||
if osx_version:
|
||||
try:
|
||||
osx_version = tuple(int(i) for i in osx_version.split('.'))
|
||||
except ValueError:
|
||||
osx_version = ''
|
||||
osx_version = _get_system_version_tuple()
|
||||
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):
|
||||
"""Find appropriate C compiler for extension module builds"""
|
||||
|
@ -331,6 +355,12 @@ def compiler_fixup(compiler_so, cc_args):
|
|||
except ValueError:
|
||||
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:
|
||||
# User specified different -arch flags in the environ,
|
||||
# see also distutils.sysconfig
|
||||
|
@ -481,6 +511,8 @@ def get_platform_osx(_config_vars, osname, release, machine):
|
|||
|
||||
if len(archs) == 1:
|
||||
machine = archs[0]
|
||||
elif archs == ('arm64', 'x86_64'):
|
||||
machine = 'universal2'
|
||||
elif archs == ('i386', 'ppc'):
|
||||
machine = 'fat'
|
||||
elif archs == ('i386', 'x86_64'):
|
||||
|
|
|
@ -6,6 +6,11 @@ import os
|
|||
from ctypes.macholib.framework import framework_info
|
||||
from ctypes.macholib.dylib import dylib_info
|
||||
from itertools import *
|
||||
try:
|
||||
from _ctypes import _dyld_shared_cache_contains_path
|
||||
except ImportError:
|
||||
def _dyld_shared_cache_contains_path(*args):
|
||||
raise NotImplementedError
|
||||
|
||||
__all__ = [
|
||||
'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_default_search(name, env),
|
||||
), env):
|
||||
|
||||
if os.path.isfile(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,))
|
||||
|
||||
def framework_find(fn, executable_path=None, env=None):
|
||||
|
|
|
@ -45,19 +45,22 @@ def find_lib(name):
|
|||
class MachOTest(unittest.TestCase):
|
||||
@unittest.skipUnless(sys.platform == "darwin", 'OSX-specific test')
|
||||
def test_find(self):
|
||||
|
||||
self.assertEqual(find_lib('pthread'),
|
||||
'/usr/lib/libSystem.B.dylib')
|
||||
# On Mac OS 11, system dylibs are only present in the shared cache,
|
||||
# so symlinks like libpthread.dylib -> libSystem.B.dylib will not
|
||||
# be resolved by dyld_find
|
||||
self.assertIn(find_lib('pthread'),
|
||||
('/usr/lib/libSystem.B.dylib', '/usr/lib/libpthread.dylib'))
|
||||
|
||||
result = find_lib('z')
|
||||
# Issue #21093: dyld default search path includes $HOME/lib and
|
||||
# /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
|
||||
# of the path.
|
||||
self.assertRegex(result, r".*/lib/libz\..*.*\.dylib")
|
||||
self.assertRegex(result, r".*/lib/libz.*\.dylib")
|
||||
|
||||
self.assertEqual(find_lib('IOKit'),
|
||||
'/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit')
|
||||
self.assertIn(find_lib('IOKit'),
|
||||
('/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit',
|
||||
'/System/Library/Frameworks/IOKit.framework/IOKit'))
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
@ -493,7 +493,7 @@ class BuildExtTestCase(TempdirManager,
|
|||
# format the target value as defined in the Apple
|
||||
# Availability Macros. We can't use the macro names since
|
||||
# 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"
|
||||
target = '%02d%01d0' % target
|
||||
else:
|
||||
|
|
|
@ -1036,6 +1036,7 @@ class BytesTest(BaseBytesTest, unittest.TestCase):
|
|||
c_char_p)
|
||||
|
||||
PyBytes_FromFormat = pythonapi.PyBytes_FromFormat
|
||||
PyBytes_FromFormat.argtypes = (c_char_p,)
|
||||
PyBytes_FromFormat.restype = py_object
|
||||
|
||||
# basic tests
|
||||
|
|
|
@ -246,7 +246,7 @@ class PlatformTest(unittest.TestCase):
|
|||
self.assertEqual(res[1], ('', '', ''))
|
||||
|
||||
if sys.byteorder == 'little':
|
||||
self.assertIn(res[2], ('i386', 'x86_64'))
|
||||
self.assertIn(res[2], ('i386', 'x86_64', 'arm64'))
|
||||
else:
|
||||
self.assertEqual(res[2], 'PowerPC')
|
||||
|
||||
|
|
|
@ -1925,6 +1925,233 @@ class TestPosixSpawnP(unittest.TestCase, _PosixSpawnMixin):
|
|||
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():
|
||||
try:
|
||||
support.run_unittest(
|
||||
|
@ -1932,6 +2159,7 @@ def test_main():
|
|||
PosixGroupsTester,
|
||||
TestPosixSpawn,
|
||||
TestPosixSpawnP,
|
||||
TestPosixWeaklinking
|
||||
)
|
||||
finally:
|
||||
support.reap_children()
|
||||
|
|
|
@ -1041,6 +1041,36 @@ class TestOldPyTime(CPyTimeTestCase, unittest.TestCase):
|
|||
with self.assertRaises(ValueError):
|
||||
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__":
|
||||
unittest.main()
|
||||
|
|
|
@ -2516,11 +2516,13 @@ class CAPITest(unittest.TestCase):
|
|||
def test_from_format(self):
|
||||
import_helper.import_module('ctypes')
|
||||
from ctypes import (
|
||||
c_char_p,
|
||||
pythonapi, py_object, sizeof,
|
||||
c_int, c_long, c_longlong, c_ssize_t,
|
||||
c_uint, c_ulong, c_ulonglong, c_size_t, c_void_p)
|
||||
name = "PyUnicode_FromFormat"
|
||||
_PyUnicode_FromFormat = getattr(pythonapi, name)
|
||||
_PyUnicode_FromFormat.argtypes = (c_char_p,)
|
||||
_PyUnicode_FromFormat.restype = py_object
|
||||
|
||||
def PyUnicode_FromFormat(format, *args):
|
||||
|
|
|
@ -116,7 +116,8 @@ WORKDIR = "/tmp/_py"
|
|||
DEPSRC = os.path.join(WORKDIR, 'third-party')
|
||||
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',),
|
||||
'intel': ('i386', 'x86_64'),
|
||||
'intel-32': ('i386',),
|
||||
|
@ -124,6 +125,7 @@ universal_opts_map = { '32-bit': ('i386', 'ppc',),
|
|||
'3-way': ('ppc', 'i386', 'x86_64'),
|
||||
'all': ('i386', 'ppc', 'x86_64', 'ppc64',) }
|
||||
default_target_map = {
|
||||
'universal2': '10.9',
|
||||
'64-bit': '10.5',
|
||||
'3-way': '10.5',
|
||||
'intel': '10.5',
|
||||
|
@ -190,6 +192,27 @@ EXPECTED_SHARED_LIBS = {}
|
|||
def internalTk():
|
||||
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.
|
||||
# The names will be inserted into the rtf version of the License.
|
||||
THIRD_PARTY_LIBS = []
|
||||
|
@ -215,6 +238,9 @@ def library_recipes():
|
|||
buildrecipe=build_universal_openssl,
|
||||
configure=None,
|
||||
install=None,
|
||||
patches=[
|
||||
"openssl-mac-arm64.patch",
|
||||
],
|
||||
),
|
||||
])
|
||||
|
||||
|
@ -231,6 +257,7 @@ def library_recipes():
|
|||
'--libdir=/Library/Frameworks/Python.framework/Versions/%s/lib'%(getVersion(),),
|
||||
],
|
||||
useLDFlags=False,
|
||||
buildrecipe=tweak_tcl_build,
|
||||
install='make TCL_LIBRARY=%(TCL_LIBRARY)s && make install TCL_LIBRARY=%(TCL_LIBRARY)s DESTDIR=%(DESTDIR)s'%{
|
||||
"DESTDIR": shellQuote(os.path.join(WORKDIR, 'libraries')),
|
||||
"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 = {
|
||||
"i386": ["darwin-i386-cc"],
|
||||
"x86_64": ["darwin64-x86_64-cc", "enable-ec_nistp_64_gcc_128"],
|
||||
"arm64": ["darwin64-arm64-cc"],
|
||||
"ppc": ["darwin-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
|
||||
values are available:
|
||||
|
||||
* ``universal2``: ``arm64``, ``x86_64``
|
||||
|
||||
* ``intel``: ``i386``, ``x86_64``
|
||||
|
||||
* ``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
|
||||
|
||||
* 11.0 and later SDKs support ``universal2``
|
||||
|
||||
The makefile for a framework build will also install ``python3.x-32``
|
||||
binaries when the universal architecture includes at least one 32-bit
|
||||
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
|
||||
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
|
||||
=========
|
||||
|
|
|
@ -95,9 +95,6 @@ setup_spawnattr(posix_spawnattr_t* spawnattr)
|
|||
size_t count;
|
||||
cpu_type_t cpu_types[1];
|
||||
short flags = 0;
|
||||
#ifdef __LP64__
|
||||
int ch;
|
||||
#endif
|
||||
|
||||
if ((errno = posix_spawnattr_init(spawnattr)) != 0) {
|
||||
err(2, "posix_spawnattr_int");
|
||||
|
@ -119,10 +116,16 @@ setup_spawnattr(posix_spawnattr_t* spawnattr)
|
|||
|
||||
#elif defined(__ppc__)
|
||||
cpu_types[0] = CPU_TYPE_POWERPC;
|
||||
|
||||
#elif defined(__i386__)
|
||||
cpu_types[0] = CPU_TYPE_X86;
|
||||
|
||||
#elif defined(__arm64__)
|
||||
cpu_types[0] = CPU_TYPE_ARM64;
|
||||
|
||||
#else
|
||||
# error "Unknown CPU"
|
||||
|
||||
#endif
|
||||
|
||||
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
|
||||
* an executable build on 10.5 can work on 10.4.
|
||||
*/
|
||||
if (posix_spawn != NULL) {
|
||||
|
||||
if (&posix_spawn != NULL) {
|
||||
posix_spawnattr_t spawnattr = NULL;
|
||||
|
||||
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 "frameobject.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <ffi.h>
|
||||
#ifdef MS_WIN32
|
||||
#include <windows.h>
|
||||
|
@ -18,7 +20,7 @@ CThunkObject_dealloc(PyObject *myself)
|
|||
Py_XDECREF(self->callable);
|
||||
Py_XDECREF(self->restype);
|
||||
if (self->pcl_write)
|
||||
ffi_closure_free(self->pcl_write);
|
||||
Py_ffi_closure_free(self->pcl_write);
|
||||
PyObject_GC_Del(self);
|
||||
}
|
||||
|
||||
|
@ -362,8 +364,7 @@ CThunkObject *_ctypes_alloc_callback(PyObject *callable,
|
|||
|
||||
assert(CThunk_CheckExact((PyObject *)p));
|
||||
|
||||
p->pcl_write = ffi_closure_alloc(sizeof(ffi_closure),
|
||||
&p->pcl_exec);
|
||||
p->pcl_write = Py_ffi_closure_alloc(sizeof(ffi_closure), &p->pcl_exec);
|
||||
if (p->pcl_write == NULL) {
|
||||
PyErr_NoMemory();
|
||||
goto error;
|
||||
|
@ -409,13 +410,35 @@ CThunkObject *_ctypes_alloc_callback(PyObject *callable,
|
|||
"ffi_prep_cif failed with %d", result);
|
||||
goto error;
|
||||
}
|
||||
#if defined(X86_DARWIN) || defined(POWERPC_DARWIN)
|
||||
result = ffi_prep_closure(p->pcl_write, &p->cif, closure_fcn, p);
|
||||
#else
|
||||
result = ffi_prep_closure_loc(p->pcl_write, &p->cif, closure_fcn,
|
||||
p,
|
||||
p->pcl_exec);
|
||||
#if HAVE_FFI_PREP_CLOSURE_LOC
|
||||
# if USING_APPLE_OS_LIBFFI
|
||||
# define HAVE_FFI_PREP_CLOSURE_LOC_RUNTIME __builtin_available(macos 10.15, ios 13, watchos 6, tvos 13, *)
|
||||
# else
|
||||
# define HAVE_FFI_PREP_CLOSURE_LOC_RUNTIME 1
|
||||
# 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
|
||||
{
|
||||
#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) {
|
||||
PyErr_Format(PyExc_RuntimeError,
|
||||
"ffi_prep_closure failed with %d", result);
|
||||
|
|
|
@ -57,6 +57,8 @@
|
|||
#include "Python.h"
|
||||
#include "structmember.h" // PyMemberDef
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef MS_WIN32
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
|
@ -64,6 +66,10 @@
|
|||
#include "ctypes_dlfcn.h"
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <mach-o/dyld.h>
|
||||
#endif
|
||||
|
||||
#ifdef MS_WIN32
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
@ -812,7 +818,8 @@ static int _call_function_pointer(int flags,
|
|||
ffi_type **atypes,
|
||||
ffi_type *restype,
|
||||
void *resmem,
|
||||
int argcount)
|
||||
int argcount,
|
||||
int argtypecount)
|
||||
{
|
||||
PyThreadState *_save = NULL; /* For Py_BLOCK_THREADS and Py_UNBLOCK_THREADS */
|
||||
PyObject *error_object = NULL;
|
||||
|
@ -835,14 +842,70 @@ static int _call_function_pointer(int flags,
|
|||
if ((flags & FUNCFLAG_CDECL) == 0)
|
||||
cc = FFI_STDCALL;
|
||||
#endif
|
||||
if (FFI_OK != ffi_prep_cif(&cif,
|
||||
cc,
|
||||
argcount,
|
||||
restype,
|
||||
atypes)) {
|
||||
PyErr_SetString(PyExc_RuntimeError,
|
||||
"ffi_prep_cif failed");
|
||||
return -1;
|
||||
|
||||
# if USING_APPLE_OS_LIBFFI
|
||||
# define HAVE_FFI_PREP_CIF_VAR_RUNTIME __builtin_available(macos 10.15, ios 13, watchos 6, tvos 13, *)
|
||||
# elif HAVE_FFI_PREP_CIF_VAR
|
||||
# define HAVE_FFI_PREP_CIF_VAR_RUNTIME true
|
||||
# else
|
||||
# define HAVE_FFI_PREP_CIF_VAR_RUNTIME false
|
||||
# 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)) {
|
||||
|
@ -1212,9 +1275,8 @@ PyObject *_ctypes_callproc(PPROC pProc,
|
|||
|
||||
if (-1 == _call_function_pointer(flags, pProc, avalues, atypes,
|
||||
rtype, resbuf,
|
||||
Py_SAFE_DOWNCAST(argcount,
|
||||
Py_ssize_t,
|
||||
int)))
|
||||
Py_SAFE_DOWNCAST(argcount, Py_ssize_t, int),
|
||||
Py_SAFE_DOWNCAST(argtype_count, Py_ssize_t, int)))
|
||||
goto cleanup;
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
|
@ -1398,6 +1460,42 @@ copy_com_pointer(PyObject *self, PyObject *args)
|
|||
}
|
||||
#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)
|
||||
{
|
||||
PyObject *name, *name2;
|
||||
|
@ -1887,6 +1985,8 @@ buffer_info(PyObject *self, PyObject *arg)
|
|||
return Py_BuildValue("siN", dict->format, dict->ndim, shape);
|
||||
}
|
||||
|
||||
|
||||
|
||||
PyMethodDef _ctypes_module_methods[] = {
|
||||
{"get_errno", get_errno, METH_NOARGS},
|
||||
{"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"},
|
||||
{"dlclose", py_dl_close, METH_VARARGS, "dlclose a 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
|
||||
{"alignment", align_func, METH_O, alignment_doc},
|
||||
{"sizeof", sizeof_func, METH_O, sizeof_doc},
|
||||
|
|
|
@ -366,6 +366,14 @@ PyObject *_ctypes_get_errobj(int **pspace);
|
|||
extern PyObject *ComError;
|
||||
#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:
|
||||
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 */
|
||||
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->next = free_list;
|
||||
free_list = item;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
if (!free_list)
|
||||
more_core();
|
||||
|
|
|
@ -923,11 +923,7 @@ static PyStatus
|
|||
calculate_program_macos(wchar_t **abs_path_p)
|
||||
{
|
||||
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;
|
||||
#else
|
||||
unsigned long nsexeclength = Py_ARRAY_LENGTH(execpath) - 1;
|
||||
#endif
|
||||
|
||||
/* On Mac OS X, if a script uses an interpreter of the form
|
||||
"#!/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
|
||||
#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)
|
||||
|
||||
/* Forward declarations */
|
||||
|
@ -149,6 +158,16 @@ perf_counter(_Py_clock_info_t *info)
|
|||
}
|
||||
|
||||
#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 *
|
||||
time_clock_gettime(PyObject *self, PyObject *args)
|
||||
{
|
||||
|
@ -297,6 +316,11 @@ PyDoc_STRVAR(clock_getres_doc,
|
|||
"clock_getres(clk_id) -> floating point number\n\
|
||||
\n\
|
||||
Return the resolution (precision) of the specified clock clk_id.");
|
||||
|
||||
#ifdef __APPLE__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif /* HAVE_CLOCK_GETRES */
|
||||
|
||||
#ifdef HAVE_PTHREAD_GETCPUCLOCKID
|
||||
|
@ -1162,31 +1186,35 @@ _PyTime_GetProcessTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)
|
|||
#if defined(HAVE_CLOCK_GETTIME) \
|
||||
&& (defined(CLOCK_PROCESS_CPUTIME_ID) || defined(CLOCK_PROF))
|
||||
struct timespec ts;
|
||||
|
||||
if (HAVE_CLOCK_GETTIME_RUNTIME) {
|
||||
|
||||
#ifdef CLOCK_PROF
|
||||
const clockid_t clk_id = CLOCK_PROF;
|
||||
const char *function = "clock_gettime(CLOCK_PROF)";
|
||||
const clockid_t clk_id = CLOCK_PROF;
|
||||
const char *function = "clock_gettime(CLOCK_PROF)";
|
||||
#else
|
||||
const clockid_t clk_id = CLOCK_PROCESS_CPUTIME_ID;
|
||||
const char *function = "clock_gettime(CLOCK_PROCESS_CPUTIME_ID)";
|
||||
const clockid_t clk_id = CLOCK_PROCESS_CPUTIME_ID;
|
||||
const char *function = "clock_gettime(CLOCK_PROCESS_CPUTIME_ID)";
|
||||
#endif
|
||||
|
||||
if (clock_gettime(clk_id, &ts) == 0) {
|
||||
if (info) {
|
||||
struct timespec res;
|
||||
info->implementation = function;
|
||||
info->monotonic = 1;
|
||||
info->adjustable = 0;
|
||||
if (clock_getres(clk_id, &res)) {
|
||||
PyErr_SetFromErrno(PyExc_OSError);
|
||||
if (clock_gettime(clk_id, &ts) == 0) {
|
||||
if (info) {
|
||||
struct timespec res;
|
||||
info->implementation = function;
|
||||
info->monotonic = 1;
|
||||
info->adjustable = 0;
|
||||
if (clock_getres(clk_id, &res)) {
|
||||
PyErr_SetFromErrno(PyExc_OSError);
|
||||
return -1;
|
||||
}
|
||||
info->resolution = res.tv_sec + res.tv_nsec * 1e-9;
|
||||
}
|
||||
|
||||
if (_PyTime_FromTimespec(tp, &ts) < 0) {
|
||||
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
|
||||
|
||||
|
@ -1390,6 +1418,16 @@ _PyTime_GetThreadTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)
|
|||
|
||||
#elif defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_PROCESS_CPUTIME_ID)
|
||||
#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
|
||||
_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
|
||||
|
||||
#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 *
|
||||
time_thread_time(PyObject *self, PyObject *unused)
|
||||
{
|
||||
|
@ -1451,6 +1498,11 @@ PyDoc_STRVAR(thread_time_ns_doc,
|
|||
\n\
|
||||
Thread time for profiling as nanoseconds:\n\
|
||||
sum of the kernel and user-space CPU time.");
|
||||
|
||||
#ifdef __APPLE__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -1500,9 +1552,19 @@ time_get_clock_info(PyObject *self, PyObject *args)
|
|||
}
|
||||
#ifdef HAVE_THREAD_TIME
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
|
@ -1783,68 +1845,116 @@ if it is -1, mktime() should guess based on the date and time.\n");
|
|||
static int
|
||||
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 */
|
||||
if (init_timezone(module) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_CLOCK_SETTIME) || defined(HAVE_CLOCK_GETRES)
|
||||
if (HAVE_CLOCK_GETTIME_RUNTIME) {
|
||||
|
||||
#ifdef CLOCK_REALTIME
|
||||
if (PyModule_AddIntMacro(module, CLOCK_REALTIME) < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (PyModule_AddIntMacro(module, CLOCK_REALTIME) < 0) {
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CLOCK_MONOTONIC
|
||||
if (PyModule_AddIntMacro(module, CLOCK_MONOTONIC) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (PyModule_AddIntMacro(module, CLOCK_MONOTONIC) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
#ifdef CLOCK_MONOTONIC_RAW
|
||||
if (PyModule_AddIntMacro(module, CLOCK_MONOTONIC_RAW) < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (PyModule_AddIntMacro(module, CLOCK_MONOTONIC_RAW) < 0) {
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CLOCK_HIGHRES
|
||||
if (PyModule_AddIntMacro(module, CLOCK_HIGHRES) < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (PyModule_AddIntMacro(module, CLOCK_HIGHRES) < 0) {
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
#ifdef CLOCK_PROCESS_CPUTIME_ID
|
||||
if (PyModule_AddIntMacro(module, CLOCK_PROCESS_CPUTIME_ID) < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (PyModule_AddIntMacro(module, CLOCK_PROCESS_CPUTIME_ID) < 0) {
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CLOCK_THREAD_CPUTIME_ID
|
||||
if (PyModule_AddIntMacro(module, CLOCK_THREAD_CPUTIME_ID) < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (PyModule_AddIntMacro(module, CLOCK_THREAD_CPUTIME_ID) < 0) {
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
#ifdef CLOCK_PROF
|
||||
if (PyModule_AddIntMacro(module, CLOCK_PROF) < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (PyModule_AddIntMacro(module, CLOCK_PROF) < 0) {
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
#ifdef CLOCK_BOOTTIME
|
||||
if (PyModule_AddIntMacro(module, CLOCK_BOOTTIME) < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (PyModule_AddIntMacro(module, CLOCK_BOOTTIME) < 0) {
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
#ifdef CLOCK_TAI
|
||||
if (PyModule_AddIntMacro(module, CLOCK_TAI) < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (PyModule_AddIntMacro(module, CLOCK_TAI) < 0) {
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
#ifdef CLOCK_UPTIME
|
||||
if (PyModule_AddIntMacro(module, CLOCK_UPTIME) < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (PyModule_AddIntMacro(module, CLOCK_UPTIME) < 0) {
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
#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 /* defined(HAVE_CLOCK_GETTIME) || defined(HAVE_CLOCK_SETTIME) || defined(HAVE_CLOCK_GETRES) */
|
||||
|
||||
|
|
|
@ -25,6 +25,16 @@
|
|||
# include <sanitizer/msan_interface.h>
|
||||
#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
|
||||
int _Py_HashSecret_Initialized = 0;
|
||||
#else
|
||||
|
@ -208,6 +218,16 @@ py_getrandom(void *buffer, Py_ssize_t size, int blocking, int raise)
|
|||
error.
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
#if defined(PY_GETRANDOM) || defined(PY_GETENTROPY)
|
||||
if (HAVE_GETENTRYPY_GETRANDOM_RUNTIME) {
|
||||
#ifdef PY_GETRANDOM
|
||||
res = py_getrandom(buffer, size, blocking, raise);
|
||||
res = py_getrandom(buffer, size, blocking, raise);
|
||||
#else
|
||||
res = py_getentropy(buffer, size, raise);
|
||||
res = py_getentropy(buffer, size, raise);
|
||||
#endif
|
||||
if (res < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (res == 1) {
|
||||
return 0;
|
||||
}
|
||||
/* getrandom() or getentropy() function is not available: failed with
|
||||
ENOSYS or EPERM. Fall back on reading from /dev/urandom. */
|
||||
if (res < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (res == 1) {
|
||||
return 0;
|
||||
}
|
||||
/* getrandom() or getentropy() function is not available: failed with
|
||||
ENOSYS or EPERM. Fall back on reading from /dev/urandom. */
|
||||
} /* end of availability block */
|
||||
#endif
|
||||
|
||||
return dev_urandom(buffer, size, raise);
|
||||
|
|
|
@ -5,6 +5,12 @@
|
|||
|
||||
#if defined(__APPLE__)
|
||||
#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
|
||||
|
||||
#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 */
|
||||
int err;
|
||||
#ifdef HAVE_CLOCK_GETTIME
|
||||
#if defined(HAVE_CLOCK_GETTIME)
|
||||
struct timespec ts;
|
||||
#else
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_CLOCK_GETTIME) || defined(__APPLE__)
|
||||
struct timeval tv;
|
||||
#endif
|
||||
|
||||
assert(info == NULL || raise);
|
||||
|
||||
#ifdef HAVE_CLOCK_GETTIME
|
||||
|
||||
#ifdef HAVE_CLOCK_GETTIME_RUNTIME
|
||||
if (HAVE_CLOCK_GETTIME_RUNTIME) {
|
||||
#endif
|
||||
|
||||
err = clock_gettime(CLOCK_REALTIME, &ts);
|
||||
if (err) {
|
||||
if (raise) {
|
||||
|
@ -715,7 +728,14 @@ pygettimeofday(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
|
|||
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() */
|
||||
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->adjustable = 1;
|
||||
}
|
||||
|
||||
#if defined(HAVE_CLOCK_GETTIME_RUNTIME) && defined(HAVE_CLOCK_GETTIME)
|
||||
} /* end of availibity block */
|
||||
#endif
|
||||
|
||||
#endif /* !HAVE_CLOCK_GETTIME */
|
||||
#endif /* !MS_WINDOWS */
|
||||
return 0;
|
||||
|
|
|
@ -1511,8 +1511,8 @@ Optional Packages:
|
|||
specify the kind of universal binary that should be
|
||||
created. this option is only valid when
|
||||
--enable-universalsdk is set; options are:
|
||||
("32-bit", "64-bit", "3-way", "intel", "intel-32",
|
||||
"intel-64", or "all") see Mac/README.rst
|
||||
("universal2", "32-bit", "64-bit", "3-way", "intel",
|
||||
"intel-32", "intel-64", or "all") see Mac/README.rst
|
||||
--with-framework-name=FRAMEWORK
|
||||
specify the name for the python framework on macOS
|
||||
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=
|
||||
|
||||
|
||||
|
@ -7529,6 +7529,11 @@ $as_echo "$CC" >&6; }
|
|||
LIPO_32BIT_FLAGS="-extract ppc7400 -extract i386"
|
||||
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)
|
||||
UNIVERSAL_ARCH_FLAGS="-arch i386 -arch x86_64"
|
||||
LIPO_32BIT_FLAGS="-extract i386"
|
||||
|
@ -7550,7 +7555,7 @@ $as_echo "$CC" >&6; }
|
|||
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
|
||||
|
||||
|
@ -9382,7 +9387,7 @@ fi
|
|||
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
|
||||
else
|
||||
|
@ -9392,9 +9397,12 @@ fi
|
|||
;;
|
||||
ppc)
|
||||
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
|
||||
|
||||
|
@ -12029,6 +12037,31 @@ else
|
|||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$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
|
||||
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],
|
||||
[specify the kind of universal binary that should be created. this option is
|
||||
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]),
|
||||
[
|
||||
UNIVERSAL_ARCHS="$withval"
|
||||
|
@ -1597,7 +1597,7 @@ AC_SUBST(BASECFLAGS)
|
|||
AC_SUBST(CFLAGS_NODIST)
|
||||
AC_SUBST(LDFLAGS_NODIST)
|
||||
|
||||
# The -arch flags for universal builds on OSX
|
||||
# The -arch flags for universal builds on macOS
|
||||
UNIVERSAL_ARCH_FLAGS=
|
||||
AC_SUBST(UNIVERSAL_ARCH_FLAGS)
|
||||
|
||||
|
@ -1898,6 +1898,11 @@ yes)
|
|||
LIPO_32BIT_FLAGS="-extract ppc7400 -extract i386"
|
||||
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)
|
||||
UNIVERSAL_ARCH_FLAGS="-arch i386 -arch x86_64"
|
||||
LIPO_32BIT_FLAGS="-extract i386"
|
||||
|
@ -1919,7 +1924,7 @@ yes)
|
|||
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
|
||||
|
||||
|
@ -2489,7 +2494,7 @@ case $ac_sys_system/$ac_sys_release in
|
|||
MACOSX_DEFAULT_ARCH="ppc"
|
||||
;;
|
||||
*)
|
||||
AC_MSG_ERROR([Unexpected output of 'arch' on OSX])
|
||||
AC_MSG_ERROR([Unexpected output of 'arch' on macOS])
|
||||
;;
|
||||
esac
|
||||
else
|
||||
|
@ -2499,9 +2504,12 @@ case $ac_sys_system/$ac_sys_release in
|
|||
;;
|
||||
ppc)
|
||||
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
|
||||
|
||||
|
@ -3774,6 +3782,12 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
|||
AC_MSG_RESULT(yes)],
|
||||
[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_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||
|
|
|
@ -784,6 +784,9 @@
|
|||
/* Define if you have the 'prlimit' functions. */
|
||||
#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. */
|
||||
#undef HAVE_PROCESS_H
|
||||
|
||||
|
|
92
setup.py
92
setup.py
|
@ -239,6 +239,13 @@ def is_macosx_sdk_path(path):
|
|||
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):
|
||||
"""Searches for the directory where a given file is located,
|
||||
and returns a possibly-empty list of additional directories, or None
|
||||
|
@ -2105,43 +2112,17 @@ class PyBuildExt(build_ext):
|
|||
library_dirs=added_lib_dirs))
|
||||
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):
|
||||
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
|
||||
|
||||
def detect_ctypes(self):
|
||||
# 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 = []
|
||||
extra_compile_args = ['-DPy_BUILD_CORE_MODULE']
|
||||
extra_link_args = []
|
||||
|
@ -2154,11 +2135,9 @@ class PyBuildExt(build_ext):
|
|||
|
||||
if MACOS:
|
||||
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')
|
||||
include_dirs.append('_ctypes/darwin')
|
||||
# XXX Is this still needed?
|
||||
# extra_link_args.extend(['-read_only_relocs', 'warning'])
|
||||
|
||||
elif HOST_PLATFORM == 'sunos5':
|
||||
# XXX This shouldn't be necessary; it appears that some
|
||||
|
@ -2188,31 +2167,48 @@ class PyBuildExt(build_ext):
|
|||
sources=['_ctypes/_ctypes_test.c'],
|
||||
libraries=['m']))
|
||||
|
||||
ffi_inc = sysconfig.get_config_var("LIBFFI_INCLUDEDIR")
|
||||
ffi_lib = None
|
||||
|
||||
ffi_inc_dirs = self.inc_dirs.copy()
|
||||
if MACOS:
|
||||
if '--with-system-ffi' not in sysconfig.get_config_var("CONFIG_ARGS"):
|
||||
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_in_sdk = os.path.join(macosx_sdk_root(), "usr/include/ffi")
|
||||
|
||||
ffi_inc = [sysconfig.get_config_var("LIBFFI_INCLUDEDIR")]
|
||||
if not ffi_inc or ffi_inc[0] == '':
|
||||
ffi_inc = find_file('ffi.h', [], ffi_inc_dirs)
|
||||
if ffi_inc is not None:
|
||||
ffi_h = ffi_inc[0] + '/ffi.h'
|
||||
if not ffi_inc:
|
||||
if os.path.exists(ffi_in_sdk):
|
||||
ext.extra_compile_args.append("-DUSING_APPLE_OS_LIBFFI=1")
|
||||
ffi_inc = ffi_in_sdk
|
||||
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):
|
||||
ffi_inc = None
|
||||
print('Header file {} does not exist'.format(ffi_h))
|
||||
ffi_lib = None
|
||||
if ffi_inc is not None:
|
||||
if ffi_lib is None and ffi_inc:
|
||||
for lib_name in ('ffi', 'ffi_pic'):
|
||||
if (self.compiler.find_library_file(self.lib_dirs, lib_name)):
|
||||
ffi_lib = lib_name
|
||||
break
|
||||
|
||||
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)
|
||||
self.use_system_libffi = True
|
||||
|
||||
|
|
Loading…
Reference in New Issue