Skip to content

Commit 2a44c97

Browse files
committed
setup.py: fix OpenSSL detection for OpenSSL 3, add build dependencies
- Fix the OpenSSL minimum version check. The regex could not parse OpenSSL 3's opensslv.h, where OPENSSL_VERSION_NUMBER is an expression of OPENSSL_VERSION_MAJOR/MINOR/PATCH, so _hashlib was considered too old. The new _detect_openssl_version() understands both formats (and LibreSSL). The minimum is now 1.0.2, matching Modules/_ssl_compat.h, and it applies to both _ssl and _hashlib (previously _ssl was built with any OpenSSL). - Add _ssl_compat.h and the _ssl_data*.h error tables to the depends lists of _ssl and _hashlib. - pyexpat: fall back to the system libexpat when the bundled Modules/expat directory has been removed from the tree. Patch: python36-OpenSSL-32-setup-py-version-detection.patch
1 parent 6bc7de1 commit 2a44c97

1 file changed

Lines changed: 67 additions & 47 deletions

File tree

‎setup.py‎

Lines changed: 67 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -863,57 +863,38 @@ def detect_modules(self):
863863
'/usr/contrib/ssl/lib/'
864864
] )
865865

866-
if (ssl_incs is not None and
867-
ssl_libs is not None):
868-
exts.append( Extension('_ssl', ['_ssl.c'],
869-
include_dirs = ssl_incs,
870-
library_dirs = ssl_libs,
871-
libraries = ['ssl', 'crypto'],
872-
depends = ['socketmodule.h']), )
873-
else:
874-
missing.append('_ssl')
875-
876866
# find out which version of OpenSSL we have
877-
openssl_ver = 0
878-
openssl_ver_re = re.compile(
879-
r'^\s*#\s*define\s+OPENSSL_VERSION_NUMBER\s+(0x[0-9a-fA-F]+)' )
880-
881-
# look for the openssl version header on the compiler search path.
882-
opensslv_h = find_file('openssl/opensslv.h', [],
883-
inc_dirs + search_for_ssl_incs_in)
884-
if opensslv_h:
885-
name = os.path.join(opensslv_h[0], 'openssl/opensslv.h')
886-
if host_platform == 'darwin' and is_macosx_sdk_path(name):
887-
name = os.path.join(macosx_sdk_root(), name[1:])
888-
try:
889-
with open(name, 'r') as incfile:
890-
for line in incfile:
891-
m = openssl_ver_re.match(line)
892-
if m:
893-
openssl_ver = int(m.group(1), 16)
894-
break
895-
except IOError as msg:
896-
print("IOError while reading opensshv.h:", msg)
897-
898-
#print('openssl_ver = 0x%08x' % openssl_ver)
899-
min_openssl_ver = 0x00907000
867+
openssl_ver = self._detect_openssl_version(inc_dirs +
868+
search_for_ssl_incs_in)
869+
# Keep in sync with the check in Modules/_ssl_compat.h
870+
min_openssl_ver = 0x10002000
900871
have_any_openssl = ssl_incs is not None and ssl_libs is not None
901872
have_usable_openssl = (have_any_openssl and
902873
openssl_ver >= min_openssl_ver)
874+
if have_any_openssl and not have_usable_openssl:
875+
print("warning: openssl 0x%08x is too old for _ssl and _hashlib, "
876+
"at least 0x%08x is required" %
877+
(openssl_ver, min_openssl_ver))
903878

904-
if have_any_openssl:
905-
if have_usable_openssl:
906-
# The _hashlib module wraps optimized implementations
907-
# of hash functions from the OpenSSL library.
908-
exts.append( Extension('_hashlib', ['_hashopenssl.c'],
909-
depends = ['hashlib.h'],
910-
include_dirs = ssl_incs,
911-
library_dirs = ssl_libs,
912-
libraries = ['ssl', 'crypto']) )
913-
else:
914-
print("warning: openssl 0x%08x is too old for _hashlib" %
915-
openssl_ver)
916-
missing.append('_hashlib')
879+
if have_usable_openssl:
880+
exts.append( Extension('_ssl', ['_ssl.c'],
881+
include_dirs = ssl_incs,
882+
library_dirs = ssl_libs,
883+
libraries = ['ssl', 'crypto'],
884+
depends = ['socketmodule.h',
885+
'_ssl_compat.h',
886+
'_ssl_data.h',
887+
'_ssl_data_111.h',
888+
'_ssl_data_300.h']), )
889+
# The _hashlib module wraps optimized implementations
890+
# of hash functions from the OpenSSL library.
891+
exts.append( Extension('_hashlib', ['_hashopenssl.c'],
892+
depends = ['hashlib.h', '_ssl_compat.h'],
893+
include_dirs = ssl_incs,
894+
library_dirs = ssl_libs,
895+
libraries = ['ssl', 'crypto']) )
896+
else:
897+
missing.extend(['_ssl', '_hashlib'])
917898

918899
# We always compile these even when OpenSSL is available (issue #14693).
919900
# It's harmless and the object code is tiny (40-50 KB per module,
@@ -1522,7 +1503,11 @@ class db_found(Exception): pass
15221503
#
15231504
# More information on Expat can be found at www.libexpat.org.
15241505
#
1525-
if '--with-system-expat' in sysconfig.get_config_var("CONFIG_ARGS"):
1506+
# Use the system libexpat if requested, or if the bundled copy has
1507+
# been removed from the source tree (as distributions often do).
1508+
expat_cfgargs = sysconfig.get_config_var("CONFIG_ARGS") or ''
1509+
if ('--with-system-expat' in expat_cfgargs or
1510+
not os.path.exists(os.path.join(srcdir, 'Modules', 'expat'))):
15261511
expat_inc = []
15271512
define_macros = []
15281513
extra_compile_args = []
@@ -2098,6 +2083,41 @@ def detect_ctypes(self, inc_dirs, lib_dirs):
20982083
# for dlopen, see bpo-32647
20992084
ext.libraries.append('dl')
21002085

2086+
def _detect_openssl_version(self, search_dirs):
2087+
"""Return OPENSSL_VERSION_NUMBER from openssl/opensslv.h, or 0.
2088+
2089+
OpenSSL < 3.0 and LibreSSL define OPENSSL_VERSION_NUMBER as a hex
2090+
literal; OpenSSL 3.0+ defines it as an expression of
2091+
OPENSSL_VERSION_MAJOR/MINOR/PATCH.
2092+
"""
2093+
opensslv_h = find_file('openssl/opensslv.h', [], search_dirs)
2094+
if not opensslv_h:
2095+
return 0
2096+
name = os.path.join(opensslv_h[0], 'openssl/opensslv.h')
2097+
if host_platform == 'darwin' and is_macosx_sdk_path(name):
2098+
name = os.path.join(macosx_sdk_root(), name[1:])
2099+
number_re = re.compile(
2100+
r'^\s*#\s*define\s+OPENSSL_VERSION_NUMBER\s+(0x[0-9a-fA-F]+)')
2101+
part_re = re.compile(
2102+
r'^\s*#\s*define\s+OPENSSL_VERSION_(MAJOR|MINOR|PATCH)\s+(\d+)')
2103+
parts = {}
2104+
try:
2105+
with open(name, 'r') as incfile:
2106+
for line in incfile:
2107+
m = number_re.match(line)
2108+
if m:
2109+
return int(m.group(1), 16)
2110+
m = part_re.match(line)
2111+
if m:
2112+
parts[m.group(1)] = int(m.group(2))
2113+
except IOError as msg:
2114+
print("IOError while reading opensslv.h:", msg)
2115+
return 0
2116+
if 'MAJOR' in parts and 'MINOR' in parts:
2117+
return ((parts['MAJOR'] << 28) | (parts['MINOR'] << 20) |
2118+
(parts.get('PATCH', 0) << 4) | 0xf)
2119+
return 0
2120+
21012121
def _decimal_ext(self):
21022122
extra_compile_args = []
21032123
undef_macros = []

0 commit comments

Comments
 (0)