blob: 51521c45758d5fbcc34a0a5bd6e5ffa49fdfef8b [file] [log] [blame]
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -07001#! /usr/bin/env python
2# encoding: utf-8
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -07003
Davide Pesavento5672d292021-11-19 18:19:25 -05004"""
5When using this tool, the wscript should look like:
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -07006
7 def options(opt):
8 opt.load('openssl')
9
10 def configure(conf):
11 conf.load('compiler_cxx openssl')
12 conf.check_openssl()
13
14 def build(bld):
15 bld(source='main.cpp', target='app', use='OPENSSL')
Davide Pesavento5672d292021-11-19 18:19:25 -050016"""
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070017
18import re
Davide Pesavento55d98602019-10-15 22:40:05 -040019from waflib import Utils
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070020from waflib.Configure import conf
21
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070022OPENSSL_DIR = ['/usr', '/usr/local', '/opt/local', '/sw']
Davide Pesavento6d1b6722022-08-20 17:54:05 -040023OPENSSL_DIR_MACOS = ['/usr/local',
24 '/opt/homebrew/opt/openssl', # Homebrew on arm64
25 '/usr/local/opt/openssl', # Homebrew on x86_64
26 '/opt/local'] # MacPorts
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070027
28def options(opt):
29 opt.add_option('--with-openssl', type='string', default=None, dest='openssl_dir',
Davide Pesavento55d98602019-10-15 22:40:05 -040030 help='directory where OpenSSL is installed, e.g., /usr/local')
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070031
32@conf
33def __openssl_get_version_file(self, dir):
34 try:
Davide Pesavento55d98602019-10-15 22:40:05 -040035 return self.root.find_dir(dir).find_node('include/openssl/opensslv.h')
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070036 except:
37 return None
38
39@conf
Davide Pesavento5672d292021-11-19 18:19:25 -050040def __openssl_find_root_and_version_file(self, root):
41 if root:
42 file = self.__openssl_get_version_file(root)
43 if not file:
44 self.fatal(f'OpenSSL not found in {root}')
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070045 return (root, file)
46
Davide Pesavento5672d292021-11-19 18:19:25 -050047 openssl_dirs = OPENSSL_DIR
Davide Pesavento55d98602019-10-15 22:40:05 -040048 if Utils.unversioned_sys_platform() == 'darwin':
Davide Pesavento6d1b6722022-08-20 17:54:05 -040049 openssl_dirs = OPENSSL_DIR_MACOS
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070050
Davide Pesavento5672d292021-11-19 18:19:25 -050051 for dir in openssl_dirs:
52 file = self.__openssl_get_version_file(dir)
53 if file:
54 return (dir, file)
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070055
Davide Pesavento5672d292021-11-19 18:19:25 -050056 self.fatal('OpenSSL not found, please provide a --with-openssl=PATH argument (see --help)')
57
58@conf
59def __openssl_check_version(self, version_file, atleast_version):
60 min_version = tuple(int(i) for i in atleast_version.split('.'))
61 txt = version_file.read()
62
63 # OpenSSL 3.0.0 and later
64 ver_tuple = (re.search(r'^#\s*define\s+OPENSSL_VERSION_MAJOR\s+(\d+)', txt, re.MULTILINE),
65 re.search(r'^#\s*define\s+OPENSSL_VERSION_MINOR\s+(\d+)', txt, re.MULTILINE),
66 re.search(r'^#\s*define\s+OPENSSL_VERSION_PATCH\s+(\d+)', txt, re.MULTILINE))
67 ver_string = re.search(r'^#\s*define\s+OPENSSL_FULL_VERSION_STR\s+"(.+)"', txt, re.MULTILINE)
68 if all(ver_tuple):
69 version = tuple(int(i[1]) for i in ver_tuple)
70 ver_string = ver_string[1] if ver_string else '.'.join(version)
71 return (version >= min_version, ver_string)
72
73 # OpenSSL 1.1.1 and earlier
74 ver_number = re.search(r'^#\s*define\s+OPENSSL_VERSION_NUMBER\s+(.+)L', txt, re.MULTILINE)
75 ver_string = re.search(r'^#\s*define\s+OPENSSL_VERSION_TEXT\s+"(.+)"', txt, re.MULTILINE)
76 if ver_number and ver_string:
77 version = int(ver_number[1], 16)
78 min_version = (min_version[0] << 28) | (min_version[1] << 20) | (min_version[2] << 12) | 0xf
79 return (version >= min_version, ver_string[1])
80
81 self.fatal(f'Cannot extract version information from {version_file}')
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070082
83@conf
84def check_openssl(self, *k, **kw):
Davide Pesavento55d98602019-10-15 22:40:05 -040085 self.start_msg('Checking for OpenSSL version')
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070086
Davide Pesavento5672d292021-11-19 18:19:25 -050087 path = k and k[0] or kw.get('path', self.options.openssl_dir)
88 root, version_file = self.__openssl_find_root_and_version_file(path)
Davide Pesavento55d98602019-10-15 22:40:05 -040089 atleast_version = kw.get('atleast_version', 0)
Davide Pesavento5672d292021-11-19 18:19:25 -050090 ok, version_str = self.__openssl_check_version(version_file, atleast_version)
91
92 self.end_msg(version_str)
93 if not ok:
94 self.fatal(f'The version of OpenSSL is too old; {atleast_version} or later is required.\n'
95 'Please upgrade your distribution or manually install a newer version of OpenSSL.')
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -070096
Davide Pesavento55d98602019-10-15 22:40:05 -040097 if 'msg' not in kw:
98 kw['msg'] = 'Checking if OpenSSL library works'
99 if 'lib' not in kw:
100 kw['lib'] = ['ssl', 'crypto']
101 if 'uselib_store' not in kw:
102 kw['uselib_store'] = 'OPENSSL'
103 if 'define_name' not in kw:
Davide Pesavento5672d292021-11-19 18:19:25 -0500104 kw['define_name'] = f"HAVE_{kw['uselib_store']}"
105 kw['includes'] = f'{root}/include'
106 kw['libpath'] = f'{root}/lib'
Zhiyi Zhangaf7c2902019-03-14 22:13:21 -0700107
Davide Pesavento55d98602019-10-15 22:40:05 -0400108 self.check_cxx(**kw)