22#
33# build_ffi.py
44#
5- # Copyright (C) 2006-2020 wolfSSL Inc.
5+ # Copyright (C) 2006-2022 wolfSSL Inc.
66#
77# This file is part of wolfSSL. (formerly known as CyaSSL)
88#
2222
2323# pylint: disable=missing-docstring, invalid-name
2424
25+ import argparse
26+ from contextlib import contextmanager
2527from distutils .util import get_platform
2628from cffi import FFI
27- from wolfssl ._build_wolfssl import wolfssl_inc_path , wolfssl_lib_path , ensure_wolfssl_src , make , make_flags , local_path
28- from wolfssl .__about__ import __wolfssl_version__ as version
29+ from wolfssl ._version import __wolfssl_version__ as version
2930import wolfssl ._openssl as openssl
3031import subprocess
3132import shlex
3536
3637libwolfssl_path = ""
3738
39+
40+ def local_path (path ):
41+ """ Return path relative to the root of this project
42+ """
43+ current = os .path .abspath (os .getcwd ())
44+ return os .path .abspath (os .path .join (current , path ))
45+
46+
47+ WOLFSSL_SRC_PATH = local_path ("lib/wolfssl" )
48+
49+
50+ def wolfssl_inc_path ():
51+ wolfssl_path = os .environ .get ("USE_LOCAL_WOLFSSL" )
52+ if wolfssl_path is None :
53+ return local_path ("lib/wolfssl" )
54+ else :
55+ if os .path .isdir (wolfssl_path ) and os .path .exists (wolfssl_path ):
56+ return wolfssl_path + "/include"
57+ else :
58+ return "/usr/local/include"
59+
60+
61+ def wolfssl_lib_path ():
62+ wolfssl_path = os .environ .get ("USE_LOCAL_WOLFSSL" )
63+ if wolfssl_path is None :
64+ return local_path ("lib/wolfssl/{}/{}/lib" .format (
65+ get_platform (), version ))
66+ else :
67+ if os .path .isdir (wolfssl_path ) and os .path .exists (wolfssl_path ):
68+ return wolfssl_path + "/lib"
69+ else :
70+ return "/usr/local/lib"
71+
72+
73+ def call (cmd ):
74+ print ("Calling: '{}' from working directory {}" .format (cmd , os .getcwd ()))
75+
76+ old_env = os .environ ["PATH" ]
77+ os .environ ["PATH" ] = "{}:{}" .format (WOLFSSL_SRC_PATH , old_env )
78+ subprocess .check_call (cmd , shell = True , env = os .environ )
79+ os .environ ["PATH" ] = old_env
80+
81+
82+ @contextmanager
83+ def chdir (new_path , mkdir = False ):
84+ old_path = os .getcwd ()
85+
86+ if mkdir :
87+ try :
88+ os .mkdir (new_path )
89+ except OSError :
90+ pass
91+
92+ try :
93+ yield os .chdir (new_path )
94+ finally :
95+ os .chdir (old_path )
96+
97+
98+ def checkout_ref (ref ):
99+ """ Ensure that we have the right version
100+ """
101+ with chdir (WOLFSSL_SRC_PATH ):
102+ current = ""
103+ try :
104+ current = subprocess .check_output (
105+ ["git" , "describe" , "--all" , "--exact-match" ]
106+ ).strip ().decode ().split ('/' )[- 1 ]
107+ except :
108+ pass
109+
110+ if current != ref :
111+ tags = subprocess .check_output (
112+ ["git" , "tag" ]
113+ ).strip ().decode ().split ("\n " )
114+
115+ if ref != "master" and ref not in tags :
116+ call ("git fetch --depth=1 origin tag {}" .format (ref ))
117+
118+ call ("git checkout --force {}" .format (ref ))
119+
120+ return True # rebuild needed
121+
122+ return False
123+
124+
125+ def ensure_wolfssl_src (ref ):
126+ """ Ensure that wolfssl sources are presents and up-to-date
127+ """
128+ if not os .path .isdir ("lib" ):
129+ os .mkdir ("lib" )
130+ with chdir ("lib" ):
131+ subprocess .run (["git" , "clone" , "--depth=1" , "https://github.com/wolfssl/wolfssl" ])
132+
133+ if not os .path .isdir (os .path .join (WOLFSSL_SRC_PATH , "wolfssl" )):
134+ subprocess .run (["git" , "submodule" , "update" , "--init" , "--depth=1" ])
135+
136+ return checkout_ref (ref )
137+
138+
139+ def make_flags (prefix , debug ):
140+ """ Returns compilation flags
141+ """
142+ flags = []
143+ cflags = []
144+
145+ if get_platform () in ["linux-x86_64" , "linux-i686" ]:
146+ cflags .append ("-fpic" )
147+
148+ # install location
149+ flags .append ("--prefix={}" .format (prefix ))
150+
151+ # lib only
152+ flags .append ("--disable-shared" )
153+ flags .append ("--disable-examples" )
154+
155+ # tls 1.3
156+ flags .append ("--enable-tls13" )
157+ flags .append ("--enable-sslv3" )
158+
159+ # for urllib3 - requires SNI (tlsx), options (openssl compat), peer cert
160+ flags .append ("--enable-tlsx" )
161+ flags .append ("--enable-opensslextra" )
162+ cflags .append ("-DKEEP_PEER_CERT" )
163+
164+ # for pyOpenSSL
165+ flags .append ("--enable-secure-renegotiation" )
166+ flags .append ("--enable-opensslall" )
167+ cflags .append ("-DFP_MAX_BITS=8192" )
168+ cflags .append ("-DHAVE_EX_DATA" )
169+ cflags .append ("-DOPENSSL_COMPATIBLE_DEFAULTS" )
170+
171+ if debug :
172+ flags .append ("--enable-debug" )
173+
174+ # Note: websocket-client test server (echo.websocket.org) only supports
175+ # TLS 1.2 with TLS_RSA_WITH_AES_128_CBC_SHA
176+ # If compiling for use with websocket-client, must enable static RSA suites.
177+ # cflags.append("-DWOLFSSL_STATIC_RSA")
178+
179+ joined_flags = " " .join (flags )
180+ joined_cflags = " " .join (cflags )
181+
182+ return joined_flags + " CFLAGS=\" " + joined_cflags + "\" "
183+
184+
185+ def make (configure_flags ):
186+ """ Create a release of wolfSSL C library
187+ """
188+ with chdir (WOLFSSL_SRC_PATH ):
189+ call ("git clean -fdX" )
190+
191+ try :
192+ call ("./autogen.sh" )
193+ except subprocess .CalledProcessError :
194+ call ("libtoolize" )
195+ call ("./autogen.sh" )
196+
197+ call ("./configure {}" .format (configure_flags ))
198+ call ("make" )
199+ call ("make install" )
200+
201+
202+ def build_wolfssl (ref , debug = False ):
203+ prefix = local_path ("lib/wolfssl/{}/{}" .format (
204+ get_platform (), ref ))
205+ libfile = os .path .join (prefix , 'lib/libwolfssl.la' )
206+
207+ rebuild = ensure_wolfssl_src (ref )
208+
209+ if rebuild or not os .path .isfile (libfile ):
210+ make (make_flags (prefix , debug ))
211+
212+
38213def make_optional_func_list (libwolfssl_path , funcs ):
39214 if libwolfssl_path .endswith (".so" ):
40215 libwolfssl = cdll .LoadLibrary (libwolfssl_path )
@@ -55,6 +230,7 @@ def make_optional_func_list(libwolfssl_path, funcs):
55230
56231 return defined
57232
233+
58234def get_libwolfssl ():
59235 libwolfssl_path = os .path .join (wolfssl_lib_path (), "libwolfssl.a" )
60236 if not os .path .exists (libwolfssl_path ):
@@ -66,13 +242,16 @@ def get_libwolfssl():
66242 else :
67243 return 1
68244
245+
69246def generate_libwolfssl ():
70247 ensure_wolfssl_src (version )
71248 prefix = local_path ("lib/wolfssl/{}/{}" .format (
72249 get_platform (), version ))
73250 make (make_flags (prefix , False ))
74251
75- if get_libwolfssl () == 0 :
252+
253+ local_wolfssl = os .environ .get ("USE_LOCAL_WOLFSSL" )
254+ if local_wolfssl and get_libwolfssl () == 0 :
76255 generate_libwolfssl ()
77256 get_libwolfssl ()
78257
@@ -294,4 +473,5 @@ def generate_libwolfssl():
294473ffi_cdef = cdef + openssl .construct_cdef (optional_funcs )
295474ffi .cdef (ffi_cdef )
296475
297- ffi .compile (verbose = True )
476+ if __name__ == "__main__" :
477+ ffi .compile (verbose = True )
0 commit comments