From b9e9292d75fdea621e05e39b8629e6935d282d0d Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Tue, 23 Nov 2021 23:58:13 +0200 Subject: [PATCH] bpo-45847: Port _ssl and _hashlib to PY_STDLIB_MOD (GH-29727) --- Modules/Setup.stdlib.in | 5 + configure | 289 ++++++++++++++++++++++++++++++++++------ configure.ac | 138 +++++++++++++------ setup.py | 77 +---------- 4 files changed, 350 insertions(+), 159 deletions(-) diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index 7422ddb59e3..9f66d531fef 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -123,6 +123,11 @@ # @MODULE__SQLITE3_TRUE@_sqlite3 _sqlite/connection.c _sqlite/cursor.c _sqlite/microprotocols.c _sqlite/module.c _sqlite/prepare_protocol.c _sqlite/row.c _sqlite/statement.c _sqlite/util.c +# needs -lssl and -lcrypt +@MODULE__SSL_TRUE@_ssl _ssl.c +# needs -lcrypt +@MODULE__HASHLIB_TRUE@_hashlib _hashopenssl.c + ############################################################################ # macOS specific modules diff --git a/configure b/configure index 01aa80091cd..ac0a1f320b2 100755 --- a/configure +++ b/configure @@ -642,6 +642,10 @@ MODULE__TESTINTERNALCAPI_FALSE MODULE__TESTINTERNALCAPI_TRUE MODULE__TESTCAPI_FALSE MODULE__TESTCAPI_TRUE +MODULE__HASHLIB_FALSE +MODULE__HASHLIB_TRUE +MODULE__SSL_FALSE +MODULE__SSL_TRUE MODULE__LZMA_FALSE MODULE__LZMA_TRUE MODULE__BZ2_FALSE @@ -20297,6 +20301,16 @@ rm -f core conftest.err conftest.$ac_objext \ # rpath to libssl and libcrypto +if test "x$GNULD" = xyes; then : + + rpath_arg="-Wl,--enable-new-dtags,-rpath=" + +else + + rpath_arg="-Wl,-rpath=" + +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-openssl-rpath" >&5 $as_echo_n "checking for --with-openssl-rpath... " >&6; } @@ -20310,12 +20324,26 @@ fi case $with_openssl_rpath in #( auto|yes) : - OPENSSL_RPATH=auto ;; #( + + OPENSSL_RPATH=auto + for arg in "$OPENSSL_LDFLAGS"; do + case $arg in #( + -L*) : + OPENSSL_LDFLAGS_RPATH="$OPENSSL_LDFLAGS_RPATH ${rpath_arg}$(echo $arg | cut -c3-)" + ;; #( + *) : + ;; +esac + done + ;; #( no) : OPENSSL_RPATH= ;; #( *) : if test -d "$with_openssl_rpath"; then : - OPENSSL_RPATH="$with_openssl_rpath" + + OPENSSL_RPATH="$with_openssl_rpath" + OPENSSL_LDFLAGS_RPATH="${rpath_arg}$with_openssl_rpath" + else as_fn_error $? "--with-openssl-rpath \"$with_openssl_rpath\" is not a directory" "$LINENO" 5 fi @@ -20326,71 +20354,163 @@ esac $as_echo "$OPENSSL_RPATH" >&6; } +# This static linking is NOT OFFICIALLY SUPPORTED and not advertised. +# Requires static OpenSSL build with position-independent code. Some features +# like DSO engines or external OSSL providers don't work. Only tested with GCC +# and clang on X86_64. +if test "x$PY_UNSUPPORTED_OPENSSL_BUILD" = xstatic; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for unsupported static openssl build" >&5 +$as_echo_n "checking for unsupported static openssl build... " >&6; } + new_OPENSSL_LIBS= + for arg in $OPENSSL_LIBS; do + case $arg in #( + -l*) : + + libname=$(echo $arg | cut -c3-) + new_OPENSSL_LIBS="$new_OPENSSL_LIBS -l:lib${libname}.a -Wl,--exclude-libs,lib${libname}.a" + ;; #( + *) : + new_OPENSSL_LIBS="$new_OPENSSL_LIBS $arg" + ;; +esac + done + OPENSSL_LIBS="$new_OPENSSL_LIBS $ZLIB_LIBS" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OPENSSL_LIBS" >&5 +$as_echo "$OPENSSL_LIBS" >&6; } + +fi + +LIBCRYPTO_LIBS= +for arg in $OPENSSL_LIBS; do + case $arg in #( + -l*ssl*|-Wl*ssl*) : + ;; #( + *) : + LIBCRYPTO_LIBS="$LIBCRYPTO_LIBS $arg" + ;; +esac +done + # check if OpenSSL libraries work as expected -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL provides required APIs" >&5 -$as_echo_n "checking whether OpenSSL provides required APIs... " >&6; } -if ${ac_cv_working_openssl+:} false; then : +save_CFLAGS=$CFLAGS +save_CPPFLAGS=$CPPFLAGS +save_LDFLAGS=$LDFLAGS +save_LIBS=$LIBS + + + LIBS="$LIBS $OPENSSL_LIBS" + CFLAGS="$CFLAGS $OPENSSL_INCLUDES" + LDFLAGS="$LDFLAGS $OPENSSL_LDFLAGS $OPENSSL_LDFLAGS_RPATH" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL provides required ssl module APIs" >&5 +$as_echo_n "checking whether OpenSSL provides required ssl module APIs... " >&6; } +if ${ac_cv_working_openssl_ssl+:} false; then : $as_echo_n "(cached) " >&6 else -save_LIBS="$LIBS" -save_CFLAGS="$CFLAGS" -save_LDFLAGS="$LDFLAGS" -LIBS="$LIBS $OPENSSL_LIBS" -CFLAGS="$CFLAGS_NODIST $OPENSSL_INCLUDES" -LDFLAGS="$LDFLAGS $OPENSSL_LDFLAGS" - -cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include -#include -#include - -#if OPENSSL_VERSION_NUMBER < 0x10101000L -#error "OpenSSL >= 1.1.1 is required" -#endif - -static void keylog_cb(const SSL *ssl, const char *line) {} + #include + #include + #if OPENSSL_VERSION_NUMBER < 0x10101000L + #error "OpenSSL >= 1.1.1 is required" + #endif + static void keylog_cb(const SSL *ssl, const char *line) {} int main () { -/* SSL APIs */ -SSL_CTX *ctx = SSL_CTX_new(TLS_client_method()); -SSL_CTX_set_keylog_callback(ctx, keylog_cb); -SSL *ssl = SSL_new(ctx); -X509_VERIFY_PARAM *param = SSL_get0_param(ssl); -X509_VERIFY_PARAM_set1_host(param, "python.org", 0); -SSL_free(ssl); -SSL_CTX_free(ctx); - -/* hashlib APIs */ -OBJ_nid2sn(NID_md5); -OBJ_nid2sn(NID_sha1); -OBJ_nid2sn(NID_sha3_512); -OBJ_nid2sn(NID_blake2b512); -EVP_PBE_scrypt(NULL, 0, NULL, 0, 2, 8, 1, 0, NULL, 0); + SSL_CTX *ctx = SSL_CTX_new(TLS_client_method()); + SSL_CTX_set_keylog_callback(ctx, keylog_cb); + SSL *ssl = SSL_new(ctx); + X509_VERIFY_PARAM *param = SSL_get0_param(ssl); + X509_VERIFY_PARAM_set1_host(param, "python.org", 0); + SSL_free(ssl); + SSL_CTX_free(ctx); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : - ac_cv_working_openssl=yes + ac_cv_working_openssl_ssl=yes else - ac_cv_working_openssl=no + ac_cv_working_openssl_ssl=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext -LIBS="$save_LIBS" -CFLAGS="$save_CFLAGS" -LDFLAGS="$save_LDFLAGS" fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_working_openssl" >&5 -$as_echo "$ac_cv_working_openssl" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_working_openssl_ssl" >&5 +$as_echo "$ac_cv_working_openssl_ssl" >&6; } + +CFLAGS=$save_CFLAGS +CPPFLAGS=$save_CPPFLAGS +LDFLAGS=$save_LDFLAGS +LIBS=$save_LIBS + + + +save_CFLAGS=$CFLAGS +save_CPPFLAGS=$CPPFLAGS +save_LDFLAGS=$LDFLAGS +save_LIBS=$LIBS + + + LIBS="$LIBS $LIBCRYPTO_LIBS" + CFLAGS="$CFLAGS $OPENSSL_INCLUDES" + LDFLAGS="$LDFLAGS $OPENSSL_LDFLAGS $OPENSSL_LDFLAGS_RPATH" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL provides required hashlib module APIs" >&5 +$as_echo_n "checking whether OpenSSL provides required hashlib module APIs... " >&6; } +if ${ac_cv_working_openssl_hashlib+:} false; then : + $as_echo_n "(cached) " >&6 +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include + #include + #if OPENSSL_VERSION_NUMBER < 0x10101000L + #error "OpenSSL >= 1.1.1 is required" + #endif + +int +main () +{ + + OBJ_nid2sn(NID_md5); + OBJ_nid2sn(NID_sha1); + OBJ_nid2sn(NID_sha3_512); + OBJ_nid2sn(NID_blake2b512); + EVP_PBE_scrypt(NULL, 0, NULL, 0, 2, 8, 1, 0, NULL, 0); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_working_openssl_hashlib=yes +else + ac_cv_working_openssl_hashlib=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_working_openssl_hashlib" >&5 +$as_echo "$ac_cv_working_openssl_hashlib" >&6; } + +CFLAGS=$save_CFLAGS +CPPFLAGS=$save_CPPFLAGS +LDFLAGS=$save_LDFLAGS +LIBS=$save_LIBS + + # ssl module default cipher suite string @@ -21800,6 +21920,79 @@ $as_echo "$py_cv_module__lzma" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _ssl" >&5 +$as_echo_n "checking for stdlib extension module _ssl... " >&6; } + case $py_stdlib_not_available in #( + *_ssl*) : + py_cv_module__ssl=n/a ;; #( + *) : + if true; then : + if test "$ac_cv_working_openssl_ssl" = yes; then : + py_cv_module__ssl=yes +else + py_cv_module__ssl=missing +fi +else + py_cv_module__ssl=disabled +fi + ;; +esac + as_fn_append MODULE_BLOCK "MODULE__SSL=$py_cv_module__ssl$as_nl" + if test "x$py_cv_module__ssl" = xyes; then : + + as_fn_append MODULE_BLOCK "MODULE__SSL_CFLAGS=$OPENSSL_INCLUDES$as_nl" + as_fn_append MODULE_BLOCK "MODULE__SSL_LDFLAGS=$OPENSSL_LDFLAGS $OPENSSL_LDFLAGS_RPATH $OPENSSL_LIBS$as_nl" + +fi + if test "$py_cv_module__ssl" = yes; then + MODULE__SSL_TRUE= + MODULE__SSL_FALSE='#' +else + MODULE__SSL_TRUE='#' + MODULE__SSL_FALSE= +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__ssl" >&5 +$as_echo "$py_cv_module__ssl" >&6; } + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _hashlib" >&5 +$as_echo_n "checking for stdlib extension module _hashlib... " >&6; } + case $py_stdlib_not_available in #( + *_hashlib*) : + py_cv_module__hashlib=n/a ;; #( + *) : + if true; then : + if test "$ac_cv_working_openssl_hashlib" = yes; then : + py_cv_module__hashlib=yes +else + py_cv_module__hashlib=missing +fi +else + py_cv_module__hashlib=disabled +fi + ;; +esac + as_fn_append MODULE_BLOCK "MODULE__HASHLIB=$py_cv_module__hashlib$as_nl" + if test "x$py_cv_module__hashlib" = xyes; then : + + as_fn_append MODULE_BLOCK "MODULE__HASHLIB_CFLAGS=$OPENSSL_INCLUDES$as_nl" + as_fn_append MODULE_BLOCK "MODULE__HASHLIB_LDFLAGS=$OPENSSL_LDFLAGS $OPENSSL_LDFLAGS_RPATH $LIBCRYPTO_LIBS$as_nl" + +fi + if test "$py_cv_module__hashlib" = yes; then + MODULE__HASHLIB_TRUE= + MODULE__HASHLIB_FALSE='#' +else + MODULE__HASHLIB_TRUE='#' + MODULE__HASHLIB_FALSE= +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__hashlib" >&5 +$as_echo "$py_cv_module__hashlib" >&6; } + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _testcapi" >&5 $as_echo_n "checking for stdlib extension module _testcapi... " >&6; } case $py_stdlib_not_available in #( @@ -22481,6 +22674,14 @@ if test -z "${MODULE__LZMA_TRUE}" && test -z "${MODULE__LZMA_FALSE}"; then as_fn_error $? "conditional \"MODULE__LZMA\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${MODULE__SSL_TRUE}" && test -z "${MODULE__SSL_FALSE}"; then + as_fn_error $? "conditional \"MODULE__SSL\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__HASHLIB_TRUE}" && test -z "${MODULE__HASHLIB_FALSE}"; then + as_fn_error $? "conditional \"MODULE__HASHLIB\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${MODULE__TESTCAPI_TRUE}" && test -z "${MODULE__TESTCAPI_FALSE}"; then as_fn_error $? "conditional \"MODULE__TESTCAPI\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 diff --git a/configure.ac b/configure.ac index 0008e8a746c..92afdf39fef 100644 --- a/configure.ac +++ b/configure.ac @@ -5891,6 +5891,12 @@ ac_includes_default="$save_includes_default" AX_CHECK_OPENSSL([have_openssl=yes],[have_openssl=no]) # rpath to libssl and libcrypto +AS_VAR_IF([GNULD], [yes], [ + rpath_arg="-Wl,--enable-new-dtags,-rpath=" +], [ + rpath_arg="-Wl,-rpath=" +]) + AC_MSG_CHECKING(for --with-openssl-rpath) AC_ARG_WITH(openssl-rpath, AS_HELP_STRING([--with-openssl-rpath=@<:@DIR|auto|no@:>@], @@ -5903,58 +5909,104 @@ AC_ARG_WITH(openssl-rpath, [with_openssl_rpath=no] ) AS_CASE($with_openssl_rpath, - [auto|yes],[OPENSSL_RPATH=auto], - [no],[OPENSSL_RPATH=], + [auto|yes], [ + OPENSSL_RPATH=auto + dnl look for linker directories + for arg in "$OPENSSL_LDFLAGS"; do + AS_CASE([$arg], + [-L*], [OPENSSL_LDFLAGS_RPATH="$OPENSSL_LDFLAGS_RPATH ${rpath_arg}$(echo $arg | cut -c3-)"] + ) + done + ], + [no], [OPENSSL_RPATH=], [AS_IF( [test -d "$with_openssl_rpath"], - [OPENSSL_RPATH="$with_openssl_rpath"], + [ + OPENSSL_RPATH="$with_openssl_rpath" + OPENSSL_LDFLAGS_RPATH="${rpath_arg}$with_openssl_rpath" + ], AC_MSG_ERROR([--with-openssl-rpath "$with_openssl_rpath" is not a directory])) ] ) AC_MSG_RESULT($OPENSSL_RPATH) AC_SUBST([OPENSSL_RPATH]) +# This static linking is NOT OFFICIALLY SUPPORTED and not advertised. +# Requires static OpenSSL build with position-independent code. Some features +# like DSO engines or external OSSL providers don't work. Only tested with GCC +# and clang on X86_64. +AS_VAR_IF([PY_UNSUPPORTED_OPENSSL_BUILD], [static], [ + AC_MSG_CHECKING([for unsupported static openssl build]) + new_OPENSSL_LIBS= + for arg in $OPENSSL_LIBS; do + AS_CASE([$arg], + [-l*], [ + libname=$(echo $arg | cut -c3-) + new_OPENSSL_LIBS="$new_OPENSSL_LIBS -l:lib${libname}.a -Wl,--exclude-libs,lib${libname}.a" + ], + [new_OPENSSL_LIBS="$new_OPENSSL_LIBS $arg"] + ) + done + dnl include libz for OpenSSL build flavors with compression support + OPENSSL_LIBS="$new_OPENSSL_LIBS $ZLIB_LIBS" + AC_MSG_RESULT([$OPENSSL_LIBS]) +]) + +dnl AX_CHECK_OPENSSL does not export libcrypto-only libs +LIBCRYPTO_LIBS= +for arg in $OPENSSL_LIBS; do + AS_CASE([$arg], + [-l*ssl*|-Wl*ssl*], [], + [LIBCRYPTO_LIBS="$LIBCRYPTO_LIBS $arg"] + ) +done + # check if OpenSSL libraries work as expected -AC_CACHE_CHECK([whether OpenSSL provides required APIs], [ac_cv_working_openssl], [ -save_LIBS="$LIBS" -save_CFLAGS="$CFLAGS" -save_LDFLAGS="$LDFLAGS" -LIBS="$LIBS $OPENSSL_LIBS" -CFLAGS="$CFLAGS_NODIST $OPENSSL_INCLUDES" -LDFLAGS="$LDFLAGS $OPENSSL_LDFLAGS" +WITH_SAVE_ENV([ + LIBS="$LIBS $OPENSSL_LIBS" + CFLAGS="$CFLAGS $OPENSSL_INCLUDES" + LDFLAGS="$LDFLAGS $OPENSSL_LDFLAGS $OPENSSL_LDFLAGS_RPATH" -AC_LINK_IFELSE([AC_LANG_PROGRAM([[ -#include -#include -#include + AC_CACHE_CHECK([whether OpenSSL provides required ssl module APIs], [ac_cv_working_openssl_ssl], [ + AC_LINK_IFELSE([AC_LANG_PROGRAM([ + #include + #include + #if OPENSSL_VERSION_NUMBER < 0x10101000L + #error "OpenSSL >= 1.1.1 is required" + #endif + static void keylog_cb(const SSL *ssl, const char *line) {} + ], [ + SSL_CTX *ctx = SSL_CTX_new(TLS_client_method()); + SSL_CTX_set_keylog_callback(ctx, keylog_cb); + SSL *ssl = SSL_new(ctx); + X509_VERIFY_PARAM *param = SSL_get0_param(ssl); + X509_VERIFY_PARAM_set1_host(param, "python.org", 0); + SSL_free(ssl); + SSL_CTX_free(ctx); + ])], [ac_cv_working_openssl_ssl=yes], [ac_cv_working_openssl_ssl=no]) + ]) +]) -#if OPENSSL_VERSION_NUMBER < 0x10101000L -#error "OpenSSL >= 1.1.1 is required" -#endif +WITH_SAVE_ENV([ + LIBS="$LIBS $LIBCRYPTO_LIBS" + CFLAGS="$CFLAGS $OPENSSL_INCLUDES" + LDFLAGS="$LDFLAGS $OPENSSL_LDFLAGS $OPENSSL_LDFLAGS_RPATH" -static void keylog_cb(const SSL *ssl, const char *line) {} -]], [[ -/* SSL APIs */ -SSL_CTX *ctx = SSL_CTX_new(TLS_client_method()); -SSL_CTX_set_keylog_callback(ctx, keylog_cb); -SSL *ssl = SSL_new(ctx); -X509_VERIFY_PARAM *param = SSL_get0_param(ssl); -X509_VERIFY_PARAM_set1_host(param, "python.org", 0); -SSL_free(ssl); -SSL_CTX_free(ctx); - -/* hashlib APIs */ -OBJ_nid2sn(NID_md5); -OBJ_nid2sn(NID_sha1); -OBJ_nid2sn(NID_sha3_512); -OBJ_nid2sn(NID_blake2b512); -EVP_PBE_scrypt(NULL, 0, NULL, 0, 2, 8, 1, 0, NULL, 0); -]])], - [ac_cv_working_openssl=yes], - [ac_cv_working_openssl=no]) -LIBS="$save_LIBS" -CFLAGS="$save_CFLAGS" -LDFLAGS="$save_LDFLAGS" + AC_CACHE_CHECK([whether OpenSSL provides required hashlib module APIs], [ac_cv_working_openssl_hashlib], [ + AC_LINK_IFELSE([AC_LANG_PROGRAM([ + #include + #include + #if OPENSSL_VERSION_NUMBER < 0x10101000L + #error "OpenSSL >= 1.1.1 is required" + #endif + ], [ + OBJ_nid2sn(NID_md5); + OBJ_nid2sn(NID_sha1); + OBJ_nid2sn(NID_sha3_512); + OBJ_nid2sn(NID_blake2b512); + EVP_PBE_scrypt(NULL, 0, NULL, 0, 2, 8, 1, 0, NULL, 0); + ])], [ac_cv_working_openssl_hashlib=yes], [ac_cv_working_openssl_hashlib=no]) + ]) ]) # ssl module default cipher suite string @@ -6245,6 +6297,12 @@ PY_STDLIB_MOD([_bz2], [], [test "$have_bzip2" = yes], PY_STDLIB_MOD([_lzma], [], [test "$have_liblzma" = yes], [$LIBLZMA_CFLAGS], [$LIBLZMA_LIBS]) +dnl OpenSSL bindings +PY_STDLIB_MOD([_ssl], [], [test "$ac_cv_working_openssl_ssl" = yes], + [$OPENSSL_INCLUDES], [$OPENSSL_LDFLAGS $OPENSSL_LDFLAGS_RPATH $OPENSSL_LIBS]) +PY_STDLIB_MOD([_hashlib], [], [test "$ac_cv_working_openssl_hashlib" = yes], + [$OPENSSL_INCLUDES], [$OPENSSL_LDFLAGS $OPENSSL_LDFLAGS_RPATH $LIBCRYPTO_LIBS]) + dnl test modules PY_STDLIB_MOD([_testcapi], [test "$TEST_MODULES" = yes]) PY_STDLIB_MOD([_testinternalcapi], [test "$TEST_MODULES" = yes]) diff --git a/setup.py b/setup.py index 721103e7fce..7972bac46c1 100644 --- a/setup.py +++ b/setup.py @@ -1883,81 +1883,8 @@ def detect_decimal(self): ) def detect_openssl_hashlib(self): - # Detect SSL support for the socket module (via _ssl) - config_vars = sysconfig.get_config_vars() - - def split_var(name, sep): - # poor man's shlex, the re module is not available yet. - value = config_vars.get(name) - if not value: - return () - # This trick works because ax_check_openssl uses --libs-only-L, - # --libs-only-l, and --cflags-only-I. - value = ' ' + value - sep = ' ' + sep - return [v.strip() for v in value.split(sep) if v.strip()] - - openssl_includes = split_var('OPENSSL_INCLUDES', '-I') - openssl_libdirs = split_var('OPENSSL_LDFLAGS', '-L') - openssl_libs = split_var('OPENSSL_LIBS', '-l') - openssl_rpath = config_vars.get('OPENSSL_RPATH') - if not openssl_libs: - # libssl and libcrypto not found - self.missing.extend(['_ssl', '_hashlib']) - return None, None - - # Find OpenSSL includes - ssl_incs = find_file( - 'openssl/ssl.h', self.inc_dirs, openssl_includes - ) - if ssl_incs is None: - self.missing.extend(['_ssl', '_hashlib']) - return None, None - - if openssl_rpath == 'auto': - runtime_library_dirs = openssl_libdirs[:] - elif not openssl_rpath: - runtime_library_dirs = [] - else: - runtime_library_dirs = [openssl_rpath] - - openssl_extension_kwargs = dict( - include_dirs=openssl_includes, - library_dirs=openssl_libdirs, - libraries=openssl_libs, - runtime_library_dirs=runtime_library_dirs, - ) - - # This static linking is NOT OFFICIALLY SUPPORTED. - # Requires static OpenSSL build with position-independent code. Some - # features like DSO engines or external OSSL providers don't work. - # Only tested on GCC and clang on X86_64. - if os.environ.get("PY_UNSUPPORTED_OPENSSL_BUILD") == "static": - extra_linker_args = [] - for lib in openssl_extension_kwargs["libraries"]: - # link statically - extra_linker_args.append(f"-l:lib{lib}.a") - # don't export symbols - extra_linker_args.append(f"-Wl,--exclude-libs,lib{lib}.a") - openssl_extension_kwargs["extra_link_args"] = extra_linker_args - # don't link OpenSSL shared libraries. - # include libz for OpenSSL build flavors with compression support - openssl_extension_kwargs["libraries"] = ["z"] - - self.add( - Extension( - '_ssl', - ['_ssl.c'], - **openssl_extension_kwargs - ) - ) - self.add( - Extension( - '_hashlib', - ['_hashopenssl.c'], - **openssl_extension_kwargs, - ) - ) + self.addext(Extension('_ssl', ['_ssl.c'])) + self.addext(Extension('_hashlib', ['_hashopenssl.c'])) def detect_hash_builtins(self): # By default we always compile these even when OpenSSL is available