109 lines
3.9 KiB
Python
109 lines
3.9 KiB
Python
#! /usr/bin/env python
|
|
# encoding: utf-8
|
|
|
|
"""
|
|
When using this tool, the wscript should look like:
|
|
|
|
def options(opt):
|
|
opt.load('openssl')
|
|
|
|
def configure(conf):
|
|
conf.load('compiler_cxx openssl')
|
|
conf.check_openssl()
|
|
|
|
def build(bld):
|
|
bld(source='main.cpp', target='app', use='OPENSSL')
|
|
"""
|
|
|
|
import re
|
|
from waflib import Utils
|
|
from waflib.Configure import conf
|
|
|
|
OPENSSL_DIR = ['/usr', '/usr/local', '/opt/local', '/sw']
|
|
OPENSSL_DIR_MACOS = ['/usr/local',
|
|
'/opt/homebrew/opt/openssl', # Homebrew on arm64
|
|
'/usr/local/opt/openssl', # Homebrew on x86_64
|
|
'/opt/local'] # MacPorts
|
|
|
|
def options(opt):
|
|
opt.add_option('--with-openssl', type='string', default=None, dest='openssl_dir',
|
|
help='directory where OpenSSL is installed, e.g., /usr/local')
|
|
|
|
@conf
|
|
def __openssl_get_version_file(self, dir):
|
|
try:
|
|
return self.root.find_dir(dir).find_node('include/openssl/opensslv.h')
|
|
except:
|
|
return None
|
|
|
|
@conf
|
|
def __openssl_find_root_and_version_file(self, root):
|
|
if root:
|
|
file = self.__openssl_get_version_file(root)
|
|
if not file:
|
|
self.fatal(f'OpenSSL not found in {root}')
|
|
return (root, file)
|
|
|
|
openssl_dirs = OPENSSL_DIR
|
|
if Utils.unversioned_sys_platform() == 'darwin':
|
|
openssl_dirs = OPENSSL_DIR_MACOS
|
|
|
|
for dir in openssl_dirs:
|
|
file = self.__openssl_get_version_file(dir)
|
|
if file:
|
|
return (dir, file)
|
|
|
|
self.fatal('OpenSSL not found, please provide a --with-openssl=PATH argument (see --help)')
|
|
|
|
@conf
|
|
def __openssl_check_version(self, version_file, atleast_version):
|
|
min_version = tuple(int(i) for i in atleast_version.split('.'))
|
|
txt = version_file.read()
|
|
|
|
# OpenSSL 3.0.0 and later
|
|
ver_tuple = (re.search(r'^#\s*define\s+OPENSSL_VERSION_MAJOR\s+(\d+)', txt, re.MULTILINE),
|
|
re.search(r'^#\s*define\s+OPENSSL_VERSION_MINOR\s+(\d+)', txt, re.MULTILINE),
|
|
re.search(r'^#\s*define\s+OPENSSL_VERSION_PATCH\s+(\d+)', txt, re.MULTILINE))
|
|
ver_string = re.search(r'^#\s*define\s+OPENSSL_FULL_VERSION_STR\s+"(.+)"', txt, re.MULTILINE)
|
|
if all(ver_tuple):
|
|
version = tuple(int(i[1]) for i in ver_tuple)
|
|
ver_string = ver_string[1] if ver_string else '.'.join(version)
|
|
return (version >= min_version, ver_string)
|
|
|
|
# OpenSSL 1.1.1 and earlier
|
|
ver_number = re.search(r'^#\s*define\s+OPENSSL_VERSION_NUMBER\s+(.+)L', txt, re.MULTILINE)
|
|
ver_string = re.search(r'^#\s*define\s+OPENSSL_VERSION_TEXT\s+"(.+)"', txt, re.MULTILINE)
|
|
if ver_number and ver_string:
|
|
version = int(ver_number[1], 16)
|
|
min_version = (min_version[0] << 28) | (min_version[1] << 20) | (min_version[2] << 12) | 0xf
|
|
return (version >= min_version, ver_string[1])
|
|
|
|
self.fatal(f'Cannot extract version information from {version_file}')
|
|
|
|
@conf
|
|
def check_openssl(self, *k, **kw):
|
|
self.start_msg('Checking for OpenSSL version')
|
|
|
|
path = k and k[0] or kw.get('path', self.options.openssl_dir)
|
|
root, version_file = self.__openssl_find_root_and_version_file(path)
|
|
atleast_version = kw.get('atleast_version', 0)
|
|
ok, version_str = self.__openssl_check_version(version_file, atleast_version)
|
|
|
|
self.end_msg(version_str)
|
|
if not ok:
|
|
self.fatal(f'The version of OpenSSL is too old; {atleast_version} or later is required.\n'
|
|
'Please upgrade your distribution or manually install a newer version of OpenSSL.')
|
|
|
|
if 'msg' not in kw:
|
|
kw['msg'] = 'Checking if OpenSSL library works'
|
|
if 'lib' not in kw:
|
|
kw['lib'] = ['ssl', 'crypto']
|
|
if 'uselib_store' not in kw:
|
|
kw['uselib_store'] = 'OPENSSL'
|
|
if 'define_name' not in kw:
|
|
kw['define_name'] = f"HAVE_{kw['uselib_store']}"
|
|
kw['includes'] = f'{root}/include'
|
|
kw['libpath'] = f'{root}/lib'
|
|
|
|
self.check_cxx(**kw)
|