diff options
Diffstat (limited to 'comm/third_party/openpgp.configure')
-rw-r--r-- | comm/third_party/openpgp.configure | 374 |
1 files changed, 374 insertions, 0 deletions
diff --git a/comm/third_party/openpgp.configure b/comm/third_party/openpgp.configure new file mode 100644 index 0000000000..03f760ed57 --- /dev/null +++ b/comm/third_party/openpgp.configure @@ -0,0 +1,374 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + +@template +def noset_check_header( + header, language="C++", flags=None, includes=None, when=None, onerror=lambda: None +): + if when is None: + when = always + + if includes: + includes = includes[:] + else: + includes = [] + includes.append(header) + + return try_compile( + includes=includes, + language=language, + flags=flags, + check_msg="for %s" % header, + when=when, + onerror=onerror, + ) + + +@template +def check_symbol_exists( + symbol, + header, + language="C", + flags=None, + includes=None, + when=None, + onerror=lambda: None, +): + if when is None: + when = always + + if includes: + includes = includes[:] + else: + includes = [] + includes.append("stdio.h") + + if isinstance(header, str): + header = [header] + includes.extend(header) + + body = """#ifndef %s +(void) %s; +#endif +""" % ( + symbol, + symbol, + ) + + return try_compile( + includes, + body, + language=language, + flags=flags, + check_msg="for %s" % symbol, + when=when, + onerror=onerror, + ) + + +with only_when("--enable-compile-environment"): + option( + "--with-system-librnp", + help="Use system RNP (librnp) for OpenPGP support.", + ) + + @depends("--with-system-librnp") + def in_tree_librnp(system_librnp): + if system_librnp: + log.info("System librnp will be used at runtime.") + return False + return True + + set_config("MZLA_LIBRNP", depends_if(in_tree_librnp)(lambda _: True)) + set_define("MZLA_LIBRNP", depends_if(in_tree_librnp)(lambda _: True)) + + +with only_when(in_tree_librnp): + # JSON-C --with-system-json + system_lib_option( + "--with-system-jsonc", + help="Use system JSON-C for librnp (located with pkgconfig)", + ) + + jsonc_pkg = pkg_check_modules("MZLA_JSONC", "json-c >= 0.11", when="--with-system-jsonc") + set_config("MZLA_SYSTEM_JSONC", depends_if(jsonc_pkg)(lambda _: True)) + + @depends("--with-system-jsonc") + def in_tree_jsonc(system_jsonc): + if not system_jsonc: + return True + + # Bzip2 --with-system-bz2 + system_lib_option( + "--with-system-bz2", + nargs="?", + help="Use system Bzip2 for librnp (pkgconfig/given prefix)", + ) + set_config("MZLA_SYSTEM_BZIP2", True, when="--with-system-bz2") + + # Bzip2 does not include a pkgconfig file, but some Linux distributions add one + bzip2_pkg = pkg_check_modules( + "MZLA_BZIP2", + "bzip2 >= 1.0.6", + when="--with-system-bz2", + allow_missing=True, + config=False, + ) + + @depends_if("--with-system-bz2", bzip2_pkg) + def bzip2_flags(value, bzip2_pkg): + if len(value): + # A path (eg. /usr/local was given) + return namespace( + cflags=("-I%s/include" % value[0],), + ldflags=("-L%s/lib" % value[0], "-lbz2"), + ) + if bzip2_pkg: + cflags = list(bzip2_pkg.cflags) + libs = bzip2_pkg.libs + return namespace( + cflags=cflags, + ldflags=libs, + ) + # Fallback + return namespace( + ldflags=["-lbz2"], + ) + + with only_when("--with-system-bz2"): + check_symbol( + "BZ2_bzread", + flags=bzip2_flags.ldflags, + onerror=lambda: die("--with-system-bz2 requested but symbol " "BZ2_bzread not found."), + ) + c_compiler.try_compile( + includes=[ + "stdio.h", + "sys/types.h", + "bzlib.h", + ], + body=""" + #ifndef _BZLIB_H + #error _BZLIB_H bzlib.h not found + #endif + """, + flags=bzip2_flags.cflags, + check_msg="for bzlib.h", + onerror=lambda: die("bzlib.h header not found"), + ) + set_config("MZLA_BZIP2_CFLAGS", bzip2_flags.cflags) + set_config("MZLA_BZIP2_LIBS", bzip2_flags.ldflags) + + # librnp crypto backend selection + @depends(target_has_linux_kernel) + def librnp_backend_choices(is_linux): + if is_linux: + return ("botan", "openssl") + else: + return ("botan",) + + option( + "--with-librnp-backend", + help="Build librnp with the selected backend", + choices=librnp_backend_choices, + nargs=1, + default="botan", + ) + + @depends("--with-librnp-backend") + def librnp_backend(backend): + if backend: + return backend[0] + + set_config("MZLA_LIBRNP_BACKEND", librnp_backend) + + @depends(librnp_backend) + def rnp_botan(backend): + return backend == "botan" + + @depends(librnp_backend) + def rnp_openssl(backend): + return backend == "openssl" + + # Botan backend (--with-system-botan) + with only_when(rnp_botan): + system_lib_option( + "--with-system-botan", + help="Use system Botan for librnp (located with pkgconfig)", + ) + + botan_pkg = pkg_check_modules("MZLA_BOTAN", "botan-2 >= 2.8.0", when="--with-system-botan") + set_config("MZLA_SYSTEM_BOTAN", depends_if(botan_pkg)(lambda _: True)) + + # OpenSSL backend + with only_when(rnp_openssl): + option( + "--with-openssl", + nargs=1, + help="OpenSSL library prefix (when not found by pkgconfig)", + ) + openssl_pkg = pkg_check_modules( + "MZLA_LIBRNP_OPENSSL", "openssl >= 1.1.1e", allow_missing=True, config=False + ) + + @depends_if("--with-openssl", openssl_pkg) + @imports(_from="os.path", _import="isdir") + @imports(_from="os.path", _import="join") + def openssl_flags(openssl_prefix, openssl_pkg): + if openssl_prefix: + openssl_prefix = openssl_prefix[0] + include = join(openssl_prefix, "include") + lib = join(openssl_prefix, "lib") + if not isdir(lib): + lib = join(openssl_prefix, "lib64") + if isdir(include) and isdir(lib): + log.info(f"Using OpenSSL at {openssl_prefix}.") + return namespace( + cflags=(f"-I{include}",), + ldflags=(f"-L{lib}", "-lssl", "-lcrypto"), + ) + if openssl_pkg: + return namespace( + cflags=openssl_pkg.cflags, + ldflags=openssl_pkg.libs, + ) + + set_config("MZLA_LIBRNP_OPENSSL_CFLAGS", openssl_flags.cflags) + set_config("MZLA_LIBRNP_OPENSSL_LIBS", openssl_flags.ldflags) + + @depends(configure_cache, c_compiler, openssl_flags) + @imports(_from="textwrap", _import="dedent") + @imports(_from="__builtin__", _import="chr") + def openssl_version(configure_cache, compiler, openssl_flags): + log.info("Checking for OpenSSL >= 1.1.1e") + if openssl_flags is None: + die("OpenSSL not found. Must be locatable with pkg-config or use --with-openssl.") + + def ossl_hexver(hex_str): + # See opensshlv.h for description of OPENSSL_VERSION_NUMBER + MIN_OSSL_VER = 0x1010105F # Version 1.1.1e + ver_as_int = int(hex_str[:-1], 16) + ossl_major = (ver_as_int & 0xF0000000) >> 28 + ossl_minor = (ver_as_int & 0x0FF00000) >> 20 + ossl_fix = (ver_as_int & 0x000FF000) >> 12 + # as a letter a-z + ossl_patch = chr(96 + ((ver_as_int & 0x00000FF0) >> 4)) + ver_as_str = f"{ossl_major}.{ossl_minor}.{ossl_fix}{ossl_patch}" + if ver_as_int < MIN_OSSL_VER: + die(f"OpenSSL version {ver_as_str} is too old.") + return ver_as_str + + check = dedent( + """\ + #include <openssl/opensslv.h> + #ifdef OPENSSL_VERSION_STR + OPENSSL_VERSION_STR + #elif defined(OPENSSL_VERSION_NUMBER) + OPENSSL_VERSION_NUMBER + #else + #error Unable to determine OpenSSL version. + #endif + """ + ) + result = try_preprocess( + configure_cache, + compiler.wrapper + + [compiler.compiler] + + compiler.flags + + list(openssl_flags.cflags), + "C", + check, + ) + if result: + openssl_ver = result.splitlines()[-1] + if openssl_ver.startswith("0x"): + # OpenSSL 1.x.x - like 0x1010107fL + openssl_ver = ossl_hexver(openssl_ver) + else: + # OpenSSL 3.x.x - quoted version like "3.0.7" + openssl_ver = openssl_ver.replace('"', "") + major_version = openssl_ver.split(".")[0] + if major_version != "3": + die( + "Unrecognized OpenSSL version {openssl_version} found. Require >= 1.1.1e or 3.x.x" + ) + + log.info(f"Found OpenSSL {openssl_ver}.") + return openssl_ver + + set_config("MZLA_LIBRNP_OPENSSL_VERSION", openssl_version) + + # Checks for building librnp itself + # ================================= + have_fcntl_h = check_header("fcntl.h") + have_string_h = check_header("string.h") + check_headers( + "limits.h", + "sys/auxv.h", + "sys/cdefs.h", + "sys/resource.h", + "sys/param.h", + "sys/stat.h", + "sys/wait.h", + ) + + set_define("HAVE_MKDTEMP", check_symbol_exists("mkdtemp", ["stdlib.h", "unistd.h"])) + set_define("HAVE_MKSTEMP", check_symbol_exists("mkstemp", ["stdlib.h", "unistd.h"])) + set_define("HAVE_REALPATH", check_symbol_exists("realpath", "stdlib.h")) + set_define("HAVE_O_BINARY", check_symbol_exists("O_BINARY", "fcntl.h")) + set_define("HAVE__O_BINARY", check_symbol_exists("_O_BINARY", "fcntl.h")) + + # Checks when building JSON-C from tree sources + # ============================================= + with only_when(in_tree_jsonc): + have_stdlib_h = check_header("stdlib.h") + have_locale_h = check_header("locale.h") + have_strings_h = check_header("strings.h") + + check_headers("stdarg.h", "dlfcn.h", "endian.h", "memory.h", "xlocale.h") + + set_define("JSON_C_HAVE_INTTYPES_H", noset_check_header("inttypes.h")) + + set_define("HAVE_DECL__ISNAN", check_symbol_exists("_isnan", "float.h")) + + set_define("HAVE_DECL__FINITE", check_symbol_exists("_finite", "float.h")) + set_define("HAVE_DECL_INFINITY", check_symbol_exists("INFINITY", "math.h")) + set_define("HAVE_DECL_ISINF", check_symbol_exists("isinf", "math.h")) + set_define("HAVE_DECL_ISNAN", check_symbol_exists("isnan", "math.h")) + set_define("HAVE_DECL_NAN", check_symbol_exists("nan", "math.h")) + + set_define("HAVE_DOPRNT", check_symbol_exists("_doprnt", "stdio.h")) + set_define("HAVE_SNPRINTF", check_symbol_exists("snprintf", "stdio.h")) + set_define( + "HAVE_VASPRINTF", + check_symbol_exists("vasprintf", "stdio.h", flags=["-D_GNU_SOURCE"]), + ) + set_define("HAVE_VSNPRINTF", check_symbol_exists("vsnprintf", "stdio.h")) + set_define("HAVE_VPRINTF", check_symbol_exists("vprintf", "stdio.h")) + + set_define("HAVE_OPEN", check_symbol_exists("open", "fcntl.h", when=have_fcntl_h)) + set_define( + "HAVE_REALLOC", + check_symbol_exists("realloc", "stdlib.h", when=have_stdlib_h), + ) + set_define( + "HAVE_SETLOCALE", + check_symbol_exists("setlocale", "locale.h", when=have_locale_h), + ) + set_define( + "HAVE_USELOCALE", + check_symbol_exists("uselocale", "locale.h", when=have_locale_h), + ) + set_define( + "HAVE_STRCASECMP", + check_symbol_exists("strcasecmp", "strings.h", when=have_strings_h), + ) + set_define( + "HAVE_STRNCASECMP", + check_symbol_exists("strncasecmp", "strings.h", when=have_strings_h), + ) + set_define("HAVE_STRDUP", check_symbol_exists("strdup", "string.h", when=have_string_h)) |