blob: 07c3c6a5e309ce4e3c3ae0a77dcb500dd06b9808 [file] [log] [blame]
Davide Pesavento2b47ac02021-03-30 22:38:05 -04001"""
2When using this tool, the wscript should look like:
Yingdi Yub3015bd2015-06-23 23:21:53 -07003
4 def options(opt):
5 opt.load('openssl')
6
7 def configure(conf):
8 conf.load('compiler_cxx openssl')
9 conf.check_openssl()
10
11 def build(bld):
12 bld(source='main.cpp', target='app', use='OPENSSL')
Davide Pesavento2b47ac02021-03-30 22:38:05 -040013"""
Yingdi Yub3015bd2015-06-23 23:21:53 -070014
15import re
Davide Pesavento77f1c762019-02-19 03:20:49 -050016from waflib import Utils
Yingdi Yub3015bd2015-06-23 23:21:53 -070017from waflib.Configure import conf
18
Yingdi Yub3015bd2015-06-23 23:21:53 -070019OPENSSL_DIR = ['/usr', '/usr/local', '/opt/local', '/sw']
Davide Pesaventof6625002022-07-31 17:15:02 -040020OPENSSL_DIR_MACOS = ['/usr/local',
21 '/opt/homebrew/opt/openssl', # Homebrew on arm64
22 '/usr/local/opt/openssl', # Homebrew on x86_64
23 '/opt/local'] # MacPorts
Yingdi Yub3015bd2015-06-23 23:21:53 -070024
25def options(opt):
26 opt.add_option('--with-openssl', type='string', default=None, dest='openssl_dir',
Davide Pesavento77f1c762019-02-19 03:20:49 -050027 help='directory where OpenSSL is installed, e.g., /usr/local')
Yingdi Yub3015bd2015-06-23 23:21:53 -070028
29@conf
30def __openssl_get_version_file(self, dir):
31 try:
Davide Pesavento77f1c762019-02-19 03:20:49 -050032 return self.root.find_dir(dir).find_node('include/openssl/opensslv.h')
Yingdi Yub3015bd2015-06-23 23:21:53 -070033 except:
34 return None
35
36@conf
Davide Pesavento2b47ac02021-03-30 22:38:05 -040037def __openssl_find_root_and_version_file(self, root):
38 if root:
39 file = self.__openssl_get_version_file(root)
40 if not file:
41 self.fatal(f'OpenSSL not found in {root}')
Yingdi Yub3015bd2015-06-23 23:21:53 -070042 return (root, file)
43
Davide Pesavento2b47ac02021-03-30 22:38:05 -040044 openssl_dirs = OPENSSL_DIR
Davide Pesavento77f1c762019-02-19 03:20:49 -050045 if Utils.unversioned_sys_platform() == 'darwin':
Davide Pesaventof6625002022-07-31 17:15:02 -040046 openssl_dirs = OPENSSL_DIR_MACOS
Yingdi Yub3015bd2015-06-23 23:21:53 -070047
Davide Pesavento2b47ac02021-03-30 22:38:05 -040048 for dir in openssl_dirs:
49 file = self.__openssl_get_version_file(dir)
50 if file:
51 return (dir, file)
Yingdi Yub3015bd2015-06-23 23:21:53 -070052
Davide Pesavento2b47ac02021-03-30 22:38:05 -040053 self.fatal('OpenSSL not found, please provide a --with-openssl=PATH argument (see --help)')
54
55@conf
56def __openssl_check_version(self, version_file, atleast_version):
57 min_version = tuple(int(i) for i in atleast_version.split('.'))
58 txt = version_file.read()
59
60 # OpenSSL 3.0.0 and later
61 ver_tuple = (re.search(r'^#\s*define\s+OPENSSL_VERSION_MAJOR\s+(\d+)', txt, re.MULTILINE),
62 re.search(r'^#\s*define\s+OPENSSL_VERSION_MINOR\s+(\d+)', txt, re.MULTILINE),
63 re.search(r'^#\s*define\s+OPENSSL_VERSION_PATCH\s+(\d+)', txt, re.MULTILINE))
64 ver_string = re.search(r'^#\s*define\s+OPENSSL_FULL_VERSION_STR\s+"(.+)"', txt, re.MULTILINE)
65 if all(ver_tuple):
66 version = tuple(int(i[1]) for i in ver_tuple)
67 ver_string = ver_string[1] if ver_string else '.'.join(version)
68 return (version >= min_version, ver_string)
69
70 # OpenSSL 1.1.1 and earlier
71 ver_number = re.search(r'^#\s*define\s+OPENSSL_VERSION_NUMBER\s+(.+)L', txt, re.MULTILINE)
72 ver_string = re.search(r'^#\s*define\s+OPENSSL_VERSION_TEXT\s+"(.+)"', txt, re.MULTILINE)
73 if ver_number and ver_string:
74 version = int(ver_number[1], 16)
75 min_version = (min_version[0] << 28) | (min_version[1] << 20) | (min_version[2] << 12) | 0xf
76 return (version >= min_version, ver_string[1])
77
78 self.fatal(f'Cannot extract version information from {version_file}')
Yingdi Yub3015bd2015-06-23 23:21:53 -070079
80@conf
81def check_openssl(self, *k, **kw):
Davide Pesavento77f1c762019-02-19 03:20:49 -050082 self.start_msg('Checking for OpenSSL version')
Yingdi Yub3015bd2015-06-23 23:21:53 -070083
Davide Pesavento2b47ac02021-03-30 22:38:05 -040084 path = k and k[0] or kw.get('path', self.options.openssl_dir)
85 root, version_file = self.__openssl_find_root_and_version_file(path)
Davide Pesavento77f1c762019-02-19 03:20:49 -050086 atleast_version = kw.get('atleast_version', 0)
Davide Pesavento2b47ac02021-03-30 22:38:05 -040087 ok, version_str = self.__openssl_check_version(version_file, atleast_version)
88
89 self.end_msg(version_str)
90 if not ok:
91 self.fatal(f'The version of OpenSSL is too old; {atleast_version} or later is required.\n'
92 'Please upgrade your distribution or manually install a newer version of OpenSSL.')
Yingdi Yub3015bd2015-06-23 23:21:53 -070093
Davide Pesavento77f1c762019-02-19 03:20:49 -050094 if 'msg' not in kw:
95 kw['msg'] = 'Checking if OpenSSL library works'
96 if 'lib' not in kw:
97 kw['lib'] = ['ssl', 'crypto']
98 if 'uselib_store' not in kw:
99 kw['uselib_store'] = 'OPENSSL'
100 if 'define_name' not in kw:
Davide Pesavento2b47ac02021-03-30 22:38:05 -0400101 kw['define_name'] = f"HAVE_{kw['uselib_store']}"
102 kw['includes'] = f'{root}/include'
103 kw['libpath'] = f'{root}/lib'
Yingdi Yub3015bd2015-06-23 23:21:53 -0700104
Davide Pesavento77f1c762019-02-19 03:20:49 -0500105 self.check_cxx(**kw)