Skip to content

Commit 6e54e9f

Browse files
committed
linux: support LibreSSL
The impetus for this is that I couldn't get OpenSSL 1.1.1c building against musl libc. But LibreSSL is a compelling replacement for OpenSSL and I think it is a good idea to support it. We'll want this eventually for BSD support anyway. This commit teaches the Linux build system to build LibreSSL and to have Python use it. AFAICT things "just work."
1 parent eddc2d0 commit 6e54e9f

File tree

8 files changed

+237
-10
lines changed

8 files changed

+237
-10
lines changed

LICENSE.libressl.txt

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
2+
LibReSSL files are retained under the copyright of the authors. New
3+
additions are ISC licensed as per OpenBSD's normal licensing policy,
4+
or are placed in the public domain.
5+
6+
The OpenSSL code is distributed under the terms of the original OpenSSL
7+
licenses which follow:
8+
9+
LICENSE ISSUES
10+
==============
11+
12+
The OpenSSL toolkit stays under a dual license, i.e. both the conditions of
13+
the OpenSSL License and the original SSLeay license apply to the toolkit.
14+
See below for the actual license texts. In case of any license issues
15+
related to OpenSSL please contact [email protected].
16+
17+
OpenSSL License
18+
---------------
19+
20+
/* ====================================================================
21+
* Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved.
22+
*
23+
* Redistribution and use in source and binary forms, with or without
24+
* modification, are permitted provided that the following conditions
25+
* are met:
26+
*
27+
* 1. Redistributions of source code must retain the above copyright
28+
* notice, this list of conditions and the following disclaimer.
29+
*
30+
* 2. Redistributions in binary form must reproduce the above copyright
31+
* notice, this list of conditions and the following disclaimer in
32+
* the documentation and/or other materials provided with the
33+
* distribution.
34+
*
35+
* 3. All advertising materials mentioning features or use of this
36+
* software must display the following acknowledgment:
37+
* "This product includes software developed by the OpenSSL Project
38+
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
39+
*
40+
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
41+
* endorse or promote products derived from this software without
42+
* prior written permission. For written permission, please contact
43+
44+
*
45+
* 5. Products derived from this software may not be called "OpenSSL"
46+
* nor may "OpenSSL" appear in their names without prior written
47+
* permission of the OpenSSL Project.
48+
*
49+
* 6. Redistributions of any form whatsoever must retain the following
50+
* acknowledgment:
51+
* "This product includes software developed by the OpenSSL Project
52+
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
53+
*
54+
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
55+
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
56+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
57+
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
58+
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
59+
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
60+
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
61+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
62+
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
63+
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
64+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
65+
* OF THE POSSIBILITY OF SUCH DAMAGE.
66+
* ====================================================================
67+
*
68+
* This product includes cryptographic software written by Eric Young
69+
* ([email protected]). This product includes software written by Tim
70+
* Hudson ([email protected]).
71+
*
72+
*/
73+
74+
Original SSLeay License
75+
-----------------------
76+
77+
/* Copyright (C) 1995-1998 Eric Young ([email protected])
78+
* All rights reserved.
79+
*
80+
* This package is an SSL implementation written
81+
* by Eric Young ([email protected]).
82+
* The implementation was written so as to conform with Netscapes SSL.
83+
*
84+
* This library is free for commercial and non-commercial use as long as
85+
* the following conditions are aheared to. The following conditions
86+
* apply to all code found in this distribution, be it the RC4, RSA,
87+
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
88+
* included with this distribution is covered by the same copyright terms
89+
* except that the holder is Tim Hudson ([email protected]).
90+
*
91+
* Copyright remains Eric Young's, and as such any Copyright notices in
92+
* the code are not to be removed.
93+
* If this package is used in a product, Eric Young should be given attribution
94+
* as the author of the parts of the library used.
95+
* This can be in the form of a textual message at program startup or
96+
* in documentation (online or textual) provided with the package.
97+
*
98+
* Redistribution and use in source and binary forms, with or without
99+
* modification, are permitted provided that the following conditions
100+
* are met:
101+
* 1. Redistributions of source code must retain the copyright
102+
* notice, this list of conditions and the following disclaimer.
103+
* 2. Redistributions in binary form must reproduce the above copyright
104+
* notice, this list of conditions and the following disclaimer in the
105+
* documentation and/or other materials provided with the distribution.
106+
* 3. All advertising materials mentioning features or use of this software
107+
* must display the following acknowledgement:
108+
* "This product includes cryptographic software written by
109+
* Eric Young ([email protected])"
110+
* The word 'cryptographic' can be left out if the rouines from the library
111+
* being used are not cryptographic related :-).
112+
* 4. If you include any Windows specific code (or a derivative thereof) from
113+
* the apps directory (application code) you must include an acknowledgement:
114+
* "This product includes software written by Tim Hudson ([email protected])"
115+
*
116+
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
117+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
118+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
119+
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
120+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
121+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
122+
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
123+
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
124+
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
125+
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
126+
* SUCH DAMAGE.
127+
*
128+
* The licence and distribution terms for any publically available version or
129+
* derivative of this code cannot be changed. i.e. this code cannot simply be
130+
* copied and put under another distribution licence
131+
* [including the GNU Public Licence.]
132+
*/

README.rst

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ To build a Python distribution for Linux x64::
5050
# With profile-guided optimizations (generated code should be faster):
5151
$ ./build-linux.py --optimized
5252

53+
To build a Python distribution for Linux x64 using musl libc::
54+
55+
$ ./build-linux.py --musl --libressl
56+
5357
To build a Python distribution for macOS::
5458

5559
$ ./build-macos.py
@@ -224,6 +228,19 @@ system, typically in ``/usr/lib``.
224228
On Linux, we statically link a ``libedit`` we compile ourselves, which
225229
is compiled against a ``libncurses`` we build ourselves.
226230

231+
OpenSSL / LibreSSL
232+
------------------
233+
234+
By default we compile with OpenSSL. We have some support for compiling
235+
against LibreSSL.
236+
237+
LibreSSL is currently required for musl libc builds because
238+
https://github.com/openssl/openssl/commit/38023b87f037f4b832c236dfce2a76272be08763
239+
broke OpenSSL in our build environment. Projects like Alpine Linux appear
240+
to still be able to build OpenSSL 1.1.1c. It requires certain headers
241+
to be in place though. When we tried to work around this, it turned out to
242+
be easier to compile with LibreSSL than with OpenSSL.
243+
227244
Distribution Format
228245
===================
229246

build-linux.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
def bootstrap():
2626
parser = argparse.ArgumentParser()
2727
parser.add_argument('--debug', action='store_true')
28+
parser.add_argument('--libressl', action='store_true')
2829
parser.add_argument('--musl', action='store_true')
2930
parser.add_argument('--optimized', action='store_true')
3031

@@ -44,6 +45,8 @@ def bootstrap():
4445

4546
if args.debug:
4647
os.environ['PYBUILD_DEBUG'] = '1'
48+
if args.libressl:
49+
os.environ['PYBUILD_LIBRESSL'] = '1'
4750
if args.musl:
4851
os.environ['PYBUILD_MUSL'] = '1'
4952
if args.optimized:

cpython-linux/Makefile

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ $(OUTDIR)/openssl-%.tar: $(PYTHON_DEP_DEPENDS) $(HERE)/build-openssl.sh
7979
$(OUTDIR)/libedit-%.tar: $(PYTHON_DEP_DEPENDS) $(OUTDIR)/ncurses-%.tar $(HERE)/build-libedit.sh
8080
$(BUILD) --platform $* libedit
8181

82+
$(OUTDIR)/libressl-%.tar: $(PYTHON_DEP_DEPENDS) $(HERE)/build-libressl.sh
83+
$(BUILD) --platform $* libressl
84+
8285
$(OUTDIR)/readline-%.tar: $(PYTHON_DEP_DEPENDS) $(OUTDIR)/ncurses-$(PLATFORM).tar $(HERE)/build-readline.sh
8386
$(BUILD) --platform $* readline
8487

@@ -104,7 +107,6 @@ PYTHON_DEPENDS := \
104107
$(OUTDIR)/libedit-$(PLATFORM).tar \
105108
$(OUTDIR)/libffi-$(PLATFORM).tar \
106109
$(OUTDIR)/ncurses-$(PLATFORM).tar \
107-
$(OUTDIR)/openssl-$(PLATFORM).tar \
108110
$(OUTDIR)/readline-$(PLATFORM).tar \
109111
$(OUTDIR)/sqlite-$(PLATFORM).tar \
110112
$(OUTDIR)/uuid-$(PLATFORM).tar \
@@ -113,6 +115,12 @@ PYTHON_DEPENDS := \
113115
$(HERE)/static-modules \
114116
$(NULL)
115117

118+
ifdef PYBUILD_LIBRESSL
119+
PYTHON_DEPENDS += $(OUTDIR)/libressl-$(PLATFORM).tar
120+
else
121+
PYTHON_DEPENDS += $(OUTDIR)/openssl-$(PLATFORM).tar
122+
endif
123+
116124
$(OUTDIR)/cpython-$(PLATFORM).tar: $(PYTHON_DEP_DEPENDS) $(HERE)/build-cpython.sh $(PYTHON_DEPENDS)
117125
$(BUILD) --platform $(PLATFORM) cpython
118126

cpython-linux/build-libressl.sh

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#!/usr/bin/env bash
2+
# This Source Code Form is subject to the terms of the Mozilla Public
3+
# License, v. 2.0. If a copy of the MPL was not distributed with this
4+
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
5+
6+
set -ex
7+
8+
cd /build
9+
10+
export PATH=/tools/${TOOLCHAIN}/bin:/tools/host/bin:$PATH
11+
12+
tar -xf libressl-${LIBRESSL_VERSION}.tar.gz
13+
14+
pushd libressl-${LIBRESSL_VERSION}
15+
16+
# Backport of https://github.com/libressl-portable/portable/pull/529 for MUSL support.
17+
patch -p1 << EOF
18+
diff --git a/crypto/compat/getprogname_linux.c b/crypto/compat/getprogname_linux.c
19+
index 2c89743..4e7e31f 100644
20+
--- a/crypto/compat/getprogname_linux.c
21+
+++ b/crypto/compat/getprogname_linux.c
22+
@@ -26,9 +26,7 @@ getprogname(void)
23+
#if defined(__ANDROID_API__) && __ANDROID_API__ < 21
24+
extern const char *__progname;
25+
return __progname;
26+
-#elif defined(__GLIBC__)
27+
- return program_invocation_short_name;
28+
#else
29+
-#error "Cannot emulate getprogname"
30+
+ return program_invocation_short_name;
31+
#endif
32+
}
33+
EOF
34+
35+
CFLAGS="${EXTRA_TARGET_CFLAGS} -fPIC" CPPFLAGS="${EXTRA_TARGET_CFLAGS} -fPIC" ./configure \
36+
--build=x86_x64-unknown-linux-gnu \
37+
--host=${TARGET} \
38+
--prefix=/tools/deps \
39+
--disable-shared
40+
41+
make -j `nproc`
42+
make -j `nproc` install DESTDIR=/build/out

cpython-linux/build.py

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,7 @@ def build_tcltk(client, image, platform, musl=False):
456456
download_tools_archive(container, BUILD / dest_path)
457457

458458

459-
def python_build_info(container, config_c_in, setup_dist, setup_local):
459+
def python_build_info(container, config_c_in, setup_dist, setup_local, libressl=False):
460460
"""Obtain build metadata for the Python distribution."""
461461

462462
bi = {
@@ -559,7 +559,12 @@ def process_setup_line(line, variant=None):
559559
'variant': d['variant'],
560560
}
561561

562-
add_licenses_to_extension_entry(entry)
562+
if libressl:
563+
ignore_keys = {'openssl'}
564+
else:
565+
ignore_keys = {'libressl'}
566+
567+
add_licenses_to_extension_entry(entry, ignore_keys=ignore_keys)
563568

564569
bi['extensions'].setdefault(extension, []).append(entry)
565570

@@ -629,7 +634,8 @@ def process_setup_line(line, variant=None):
629634
return bi
630635

631636

632-
def build_cpython(client, image, platform, debug=False, optimized=False, musl=False):
637+
def build_cpython(client, image, platform, debug=False, optimized=False, musl=False,
638+
libressl=False):
633639
"""Build CPython in a Docker image'"""
634640
python_archive = download_entry('cpython-3.7', BUILD)
635641
setuptools_archive = download_entry('setuptools', BUILD)
@@ -659,7 +665,12 @@ def build_cpython(client, image, platform, debug=False, optimized=False, musl=Fa
659665
install_tools_archive(container, BUILD / ('libedit-%s.tar' % dep_platform))
660666
install_tools_archive(container, BUILD / ('libffi-%s.tar' % dep_platform))
661667
install_tools_archive(container, BUILD / ('ncurses-%s.tar' % dep_platform))
662-
install_tools_archive(container, BUILD / ('openssl-%s.tar' % dep_platform))
668+
669+
if libressl:
670+
install_tools_archive(container, BUILD / ('libressl-%s.tar' % dep_platform))
671+
else:
672+
install_tools_archive(container, BUILD / ('openssl-%s.tar' % dep_platform))
673+
663674
install_tools_archive(container, BUILD / ('readline-%s.tar' % dep_platform))
664675
install_tools_archive(container, BUILD / ('sqlite-%s.tar' % dep_platform))
665676
# tk requires a bunch of X11 stuff.
@@ -729,7 +740,8 @@ def build_cpython(client, image, platform, debug=False, optimized=False, musl=Fa
729740
'python_include': 'install/include/%s' % fully_qualified_name,
730741
'python_stdlib': 'install/lib/python3.7',
731742
'build_info': python_build_info(container, config_c_in,
732-
setup_dist_content, setup_local_content),
743+
setup_dist_content, setup_local_content,
744+
libressl=libressl),
733745
'licenses': DOWNLOADS['cpython-3.7']['licenses'],
734746
'license_path': 'licenses/LICENSE.cpython.txt',
735747
}
@@ -824,7 +836,7 @@ def main():
824836
build_readline(client, get_image(client, 'build'), platform=platform,
825837
musl=musl)
826838

827-
elif action in ('bdb', 'bzip2', 'gdbm', 'libffi', 'ncurses', 'openssl', 'sqlite', 'uuid', 'xz', 'zlib'):
839+
elif action in ('bdb', 'bzip2', 'gdbm', 'libffi', 'libressl', 'ncurses', 'openssl', 'sqlite', 'uuid', 'xz', 'zlib'):
828840
simple_build(client, get_image(client, 'build'), action, platform=platform,
829841
musl=musl)
830842

@@ -834,7 +846,8 @@ def main():
834846

835847
elif action == 'cpython':
836848
build_cpython(client, get_image(client, 'build'), platform=platform,
837-
musl=musl, debug=args.debug, optimized=args.optimized)
849+
musl=musl, debug=args.debug, optimized=args.optimized,
850+
libressl='PYBUILD_LIBRESSL' in os.environ)
838851

839852
else:
840853
print('unknown build action: %s' % action)

pythonbuild/downloads.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,15 @@
141141
'licenses': ['MIT'],
142142
'license_file': 'LICENSE.libffi.txt',
143143
},
144+
'libressl': {
145+
'url': 'https://ftp.openbsd.org/pub/OpenBSD/LibreSSL/libressl-2.9.2.tar.gz',
146+
'size': 3607549,
147+
'sha256': 'c4c78167fae325b47aebd8beb54b6041d6f6a56b3743f4bd5d79b15642f9d5d4',
148+
'version': '2.9.2',
149+
'library_names': ['crypto', 'ssl'],
150+
'licenses': ['OpenSSL'],
151+
'license_file': 'LICENSE.libressl.txt',
152+
},
144153
'libx11': {
145154
'url': 'https://www.x.org/releases/X11R7.7/src/lib/libX11-1.5.0.tar.gz',
146155
'size': 3073820,

pythonbuild/utils.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ def compress_python_archive(source_path: pathlib.Path,
159159
return dest_path
160160

161161

162-
def add_licenses_to_extension_entry(entry):
162+
def add_licenses_to_extension_entry(entry, ignore_keys=None):
163163
"""Add licenses keys to a ``extensions`` entry for JSON distribution info."""
164164

165165
have_licenses = False
@@ -170,7 +170,10 @@ def add_licenses_to_extension_entry(entry):
170170
for link in entry['links']:
171171
name = link['name']
172172

173-
for value in DOWNLOADS.values():
173+
for key, value in DOWNLOADS.items():
174+
if ignore_keys and key in ignore_keys:
175+
continue
176+
174177
if name not in value.get('library_names', []):
175178
continue
176179

0 commit comments

Comments
 (0)