How can I compile Python 3.6.2 on macOS with openSSL from homebrew?

I had success like this.

  brew update
  brew install openssl

  # these were suggested by brew itself.

  export LDFLAGS="-L/usr/local/opt/openssl/lib"
  export CPPFLAGS="-I/usr/local/opt/openssl/include"
  export PKG_CONFIG_PATH="/usr/local/opt/openssl/lib/pkgconfig"

  # vanilla compilation

  ./configure
  make

None of the previous answers I found earlier worked for me, but I did eventually figure this out with the help of another answer not mentioned earlier. Here was the actual fix: https://stackoverflow.com/a/20740964/2934226

Basically, CPPFLAGS and LDFLAGS can't be set in the environment; you need to set them alongside the configure command, like this:

./configure CPPFLAGS="-I[openSSL install location]/include" LDFLAGS="-L[openSSL install location]/lib" [other flags here]

And then after compiling and installing, it worked!

$ python3 -c "import ssl; print(ssl.OPENSSL_VERSION)"
OpenSSL 1.0.2l  25 May 2017

Here are the things that didn't work, and why:

How do I compile Python 3.4 with custom OpenSSL? doesn't help because you can't set LDFLAGS, CFLAGS, or CPPFLAGS in the environment; setup.py doesn't pass them along to the actual compilation steps. And even if setting LD_LIBRARY_PATH might work, you don't want to do that because it's dangerous (see http://xahlee.info/UnixResource_dir/_/ldpath.html). Finally, --with-ssl isn't a valid configure argument, and the patch listed there to add it doesn't apply cleanly.

Homebrew refusing to link OpenSSL doesn't apply when you're trying to build something from source, rather than trying to get an an already-compiled dylib to find a relocated library. Furthermore, making symlinks in /usr/local is dangerous, and can cause programs to compile against the newer headers but use the older system binaries.

how to include ssl with python build on MacOS doesn't work properly. Editing setup.py to add the lib and include directories for where you've installed my openSSL partially works, and lets you compile in SSL support. Alas, they aren't importable because the old version is still getting used:

Following modules built successfully but were removed because they could not be imported:
_hashlib              _ssl                                    

[...]

building '_ssl' extension
gcc -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -std=c99 -Wextra -Wno-unused-result -Wno-unused-parameter -Wno-missing-field-initializers -I/usr/local/opt/openssl/include/ -I./Include -I/oebuild/python/python-3.6.1/include -I. -I/usr/local/include -I/oebuild/python/src/Python-3.6.1/Include -I/oebuild/python/src/Python-3.6.1 -c /oebuild/python/src/Python-3.6.1/Modules/_ssl.c -o build/temp.macosx-10.11-x86_64-3.6/oebuild/python/src/Python-3.6.1/Modules/_ssl.o
gcc -bundle -undefined dynamic_lookup build/temp.macosx-10.11-x86_64-3.6/oebuild/python/src/Python-3.6.1/Modules/_ssl.o -L/oebuild/python/python-3.6.1/lib -L/usr/local/lib -lssl -lcrypto -o build/lib.macosx-10.11-x86_64-3.6/_ssl.cpython-36m-darwin.so
building '_hashlib' extension
gcc -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -std=c99 -Wextra -Wno-unused-result -Wno-unused-parameter -Wno-missing-field-initializers -I/usr/local/opt/openssl/include/ -I./Include -I/oebuild/python/python-3.6.1/include -I. -I/usr/local/include -I/oebuild/python/src/Python-3.6.1/Include -I/oebuild/python/src/Python-3.6.1 -c /oebuild/python/src/Python-3.6.1/Modules/_hashopenssl.c -o build/temp.macosx-10.11-x86_64-3.6/oebuild/python/src/Python-3.6.1/Modules/_hashopenssl.o
gcc -bundle -undefined dynamic_lookup build/temp.macosx-10.11-x86_64-3.6/oebuild/python/src/Python-3.6.1/Modules/_hashopenssl.o -L/oebuild/python/python-3.6.1/lib -L/usr/local/lib -lssl -lcrypto -o build/lib.macosx-10.11-x86_64-3.6/_hashlib.cpython-36m-darwin.so
*** WARNING: renaming "_ssl" since importing it failed: dlopen(build/lib.macosx-10.11-x86_64-3.6/_ssl.cpython-36m-darwin.so, 2): Symbol not found: _CRYPTO_THREADID_set_callback
  Referenced from: build/lib.macosx-10.11-x86_64-3.6/_ssl.cpython-36m-darwin.so
  Expected in: flat namespace
 in build/lib.macosx-10.11-x86_64-3.6/_ssl.cpython-36m-darwin.so
*** WARNING: renaming "_hashlib" since importing it failed: dlopen(build/lib.macosx-10.11-x86_64-3.6/_hashlib.cpython-36m-darwin.so, 2): Symbol not found: _HMAC_CTX_copy
  Referenced from: build/lib.macosx-10.11-x86_64-3.6/_hashlib.cpython-36m-darwin.so
  Expected in: flat namespace
 in build/lib.macosx-10.11-x86_64-3.6/_hashlib.cpython-36m-darwin.so

otool -L shows the problem:

$ otool -L build/lib.macosx-10.11-x86_64-3.6/_ssl.cpython-36m-darwin_failed.so 
build/lib.macosx-10.11-x86_64-3.6/_ssl.cpython-36m-darwin_failed.so:
    /usr/lib/libssl.0.9.8.dylib (compatibility version 0.9.8, current version 0.9.8)
    /usr/lib/libcrypto.0.9.8.dylib (compatibility version 0.9.8, current version 0.9.8)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1226.10.1)

(CRYPTO_THREADID was introduced in version 1.0.0, according to https://wiki.openssl.org/index.php/Manual:Threads(3)#HISTORY)


No answer above worked for me, for Python 3.8 (currently in beta).

Instead, what worked for me (July 2019, updated January 2022):

brew install openssl
./configure --with-openssl=$(brew --prefix openssl)