Yingdi Yu | b3015bd | 2015-06-23 23:21:53 -0700 | [diff] [blame] | 1 | #! /usr/bin/env python |
| 2 | # encoding: utf-8 |
Yingdi Yu | b3015bd | 2015-06-23 23:21:53 -0700 | [diff] [blame] | 3 | |
Davide Pesavento | 2b47ac0 | 2021-03-30 22:38:05 -0400 | [diff] [blame] | 4 | """ |
| 5 | When using this tool, the wscript should look like: |
Yingdi Yu | b3015bd | 2015-06-23 23:21:53 -0700 | [diff] [blame] | 6 | |
| 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 Pesavento | 2b47ac0 | 2021-03-30 22:38:05 -0400 | [diff] [blame] | 16 | """ |
Yingdi Yu | b3015bd | 2015-06-23 23:21:53 -0700 | [diff] [blame] | 17 | |
| 18 | import re |
Davide Pesavento | 77f1c76 | 2019-02-19 03:20:49 -0500 | [diff] [blame] | 19 | from waflib import Utils |
Yingdi Yu | b3015bd | 2015-06-23 23:21:53 -0700 | [diff] [blame] | 20 | from waflib.Configure import conf |
| 21 | |
Alexander Afanasyev | 750472b | 2016-08-05 12:07:13 -0700 | [diff] [blame] | 22 | OPENSSL_DIR_OSX = ['/usr/local', '/opt/local', '/usr/local/opt/openssl'] |
Yingdi Yu | b3015bd | 2015-06-23 23:21:53 -0700 | [diff] [blame] | 23 | OPENSSL_DIR = ['/usr', '/usr/local', '/opt/local', '/sw'] |
| 24 | |
| 25 | def options(opt): |
| 26 | opt.add_option('--with-openssl', type='string', default=None, dest='openssl_dir', |
Davide Pesavento | 77f1c76 | 2019-02-19 03:20:49 -0500 | [diff] [blame] | 27 | help='directory where OpenSSL is installed, e.g., /usr/local') |
Yingdi Yu | b3015bd | 2015-06-23 23:21:53 -0700 | [diff] [blame] | 28 | |
| 29 | @conf |
| 30 | def __openssl_get_version_file(self, dir): |
| 31 | try: |
Davide Pesavento | 77f1c76 | 2019-02-19 03:20:49 -0500 | [diff] [blame] | 32 | return self.root.find_dir(dir).find_node('include/openssl/opensslv.h') |
Yingdi Yu | b3015bd | 2015-06-23 23:21:53 -0700 | [diff] [blame] | 33 | except: |
| 34 | return None |
| 35 | |
| 36 | @conf |
Davide Pesavento | 2b47ac0 | 2021-03-30 22:38:05 -0400 | [diff] [blame] | 37 | def __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 Yu | b3015bd | 2015-06-23 23:21:53 -0700 | [diff] [blame] | 42 | return (root, file) |
| 43 | |
Davide Pesavento | 2b47ac0 | 2021-03-30 22:38:05 -0400 | [diff] [blame] | 44 | openssl_dirs = OPENSSL_DIR |
Davide Pesavento | 77f1c76 | 2019-02-19 03:20:49 -0500 | [diff] [blame] | 45 | if Utils.unversioned_sys_platform() == 'darwin': |
Davide Pesavento | 2b47ac0 | 2021-03-30 22:38:05 -0400 | [diff] [blame] | 46 | openssl_dirs = OPENSSL_DIR_OSX |
Yingdi Yu | b3015bd | 2015-06-23 23:21:53 -0700 | [diff] [blame] | 47 | |
Davide Pesavento | 2b47ac0 | 2021-03-30 22:38:05 -0400 | [diff] [blame] | 48 | for dir in openssl_dirs: |
| 49 | file = self.__openssl_get_version_file(dir) |
| 50 | if file: |
| 51 | return (dir, file) |
Yingdi Yu | b3015bd | 2015-06-23 23:21:53 -0700 | [diff] [blame] | 52 | |
Davide Pesavento | 2b47ac0 | 2021-03-30 22:38:05 -0400 | [diff] [blame] | 53 | self.fatal('OpenSSL not found, please provide a --with-openssl=PATH argument (see --help)') |
| 54 | |
| 55 | @conf |
| 56 | def __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 Yu | b3015bd | 2015-06-23 23:21:53 -0700 | [diff] [blame] | 79 | |
| 80 | @conf |
| 81 | def check_openssl(self, *k, **kw): |
Davide Pesavento | 77f1c76 | 2019-02-19 03:20:49 -0500 | [diff] [blame] | 82 | self.start_msg('Checking for OpenSSL version') |
Yingdi Yu | b3015bd | 2015-06-23 23:21:53 -0700 | [diff] [blame] | 83 | |
Davide Pesavento | 2b47ac0 | 2021-03-30 22:38:05 -0400 | [diff] [blame] | 84 | 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 Pesavento | 77f1c76 | 2019-02-19 03:20:49 -0500 | [diff] [blame] | 86 | atleast_version = kw.get('atleast_version', 0) |
Davide Pesavento | 2b47ac0 | 2021-03-30 22:38:05 -0400 | [diff] [blame] | 87 | 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 Yu | b3015bd | 2015-06-23 23:21:53 -0700 | [diff] [blame] | 93 | |
Davide Pesavento | 77f1c76 | 2019-02-19 03:20:49 -0500 | [diff] [blame] | 94 | 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 Pesavento | 2b47ac0 | 2021-03-30 22:38:05 -0400 | [diff] [blame] | 101 | kw['define_name'] = f"HAVE_{kw['uselib_store']}" |
| 102 | kw['includes'] = f'{root}/include' |
| 103 | kw['libpath'] = f'{root}/lib' |
Yingdi Yu | b3015bd | 2015-06-23 23:21:53 -0700 | [diff] [blame] | 104 | |
Davide Pesavento | 77f1c76 | 2019-02-19 03:20:49 -0500 | [diff] [blame] | 105 | self.check_cxx(**kw) |