7

While building python from source on a MacOS, I accidntally overwrote the python that came with MacOS, now it doesn't have SSL. I tried to build again by running --with-ssl option

./configure --with-ssl

but when I subsequently ran make, it said this

Python build finished, but the necessary bits to build these modules were not found:
_bsddb             _ssl               dl              
imageop            linuxaudiodev      ossaudiodev     
readline           spwd               sunaudiodev     
To find the necessary bits, look in setup.py in detect_modules() for the module's name.

It's not clear to me from looking at setup.py what I'm supposed to do to find the "necessary bits". What can I do to build python with SSL on MacOS?

1

2 Answers 2

13

First of all, MacOS only includes LibreSSL 2.2.7 libraries and no headers, you really want to install OpenSSL using homebrew:

$ brew install openssl

The openssl formula is a keg-only formula because the LibreSSL library is shadowing OpenSSL and Homebrew will not interfere with this. This means that you can find OpenSSL not in /usr/local but in /usr/local/opt/openssl. But Homebrew includes the necessary command-line tools to figure out what path to use.

You then need to tell configure about these. If you are building Python 3.7 or newer, use the --with-openssl switch:

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

If you are building an older release, set the CPPFLAGS and LDFLAGS environment variables:

CPPFLAGS="-I$(brew --prefix openssl)/include" \
LDFLAGS="-L$(brew --prefix openssl)/lib" \
./configure

and the Python configuration infrastructure takes it from there.

Know that now ancient Python releases (2.6 or older, 3.0-3.4) only work with OpenSSL 1.0.x and before, which no longer is installable from homebrew core.

Sign up to request clarification or add additional context in comments.

1 Comment

2022 update: you have a choice between OpenSSL 1.1.1 and 3.0 (both work on recent CPython versions). In brew commands you might have to specify [email protected] or openssl@3 (e.g. brew install [email protected] and brew --prefix [email protected]). As of Python 3.11.0, OpenSSL 1.1.1 is often the default, so you might prefer that right now. But that might change soon.
7

Just open setup.py and find method detect_modules(). It has some lines like (2.7.11 for me):

    # Detect SSL support for the socket module (via _ssl)
    search_for_ssl_incs_in = [
                          '/usr/local/ssl/include',
                          '/usr/contrib/ssl/include/'
                         ]
    ssl_incs = find_file('openssl/ssl.h', inc_dirs,
                         search_for_ssl_incs_in
                         )
    if ssl_incs is not None:
        krb5_h = find_file('krb5.h', inc_dirs,
                           ['/usr/kerberos/include'])
        if krb5_h:
            ssl_incs += krb5_h
    ssl_libs = find_library_file(self.compiler, 'ssl',lib_dirs,
                                 ['/usr/local/ssl/lib',
                                  '/usr/contrib/ssl/lib/'
                                 ] )

    if (ssl_incs is not None and
        ssl_libs is not None):
        exts.append( Extension('_ssl', ['_ssl.c'],
                               include_dirs = ssl_incs,
                               library_dirs = ssl_libs,
                               libraries = ['ssl', 'crypto'],
                               depends = ['socketmodule.h']), )
    else:
        missing.append('_ssl')

So it seems that you need SSL and Kerberos. Kerberos comes installed with Mac. So You need to install openssl. You can do it with brew:

brew install openssl

openssl headers could be installed in a path different than Python will search. So issue

locate ssl.h

and add the path to search_for_ssl_incs_in. For example for me it is:

/usr/local/Cellar/openssl/1.0.2d_1/include/openssl/ssl.h

So I should add /usr/local/Cellar/openssl/1.0.2d_1/include/ to search_for_ssl_incs_in.

Don't forget that these are for Python 2.7.11. But the process should be same.

Hope that helps.

3 Comments

I changed the paths to /opt/local/... for the MacPorts OpenSSL. The built succeeded, but Python failed to import the _ssl module due to undefined symbols. Installing OpenSSL from source solved the problem, using the default paths in CPython's setup.py.
I had the same problem but was able to get it working with openSSL from Homebrew. Here's how stackoverflow.com/a/46476640/2934226
There is absolutely no need to edit setup.py. Just make sure to set the CPPFLAGS and LDFLAGS variables when running configure: CPPFLAGS="-I$(brew --prefix openssl)/include" LDFLAGS="-L$(brew --prefix openssl)/lib" ./configure

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.