spack/var/spack/repos/builtin/packages/openssl/package.py
2025-02-28 23:34:31 +01:00

290 lines
11 KiB
Python

# Copyright Spack Project Developers. See COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import os
import re
from spack.package import *
class Openssl(Package): # Uses Fake Autotools, should subclass Package
"""OpenSSL is an open source project that provides a robust, commercial-grade, and
full-featured toolkit for the Transport Layer Security (TLS) and Secure Sockets Layer (SSL)
protocols. It is also a general-purpose cryptography library."""
homepage = "https://www.openssl.org"
url = "https://www.openssl.org/source/openssl-1.1.1d.tar.gz"
list_url = "https://www.openssl.org/source/old/"
list_depth = 1
maintainers("AlexanderRichert-NOAA")
tags = ["core-packages", "windows"]
executables = ["openssl"]
license("Apache-2.0")
version("3.4.0", sha256="e15dda82fe2fe8139dc2ac21a36d4ca01d5313c75f99f46c4e8a27709b7294bf")
version("3.3.2", sha256="2e8a40b01979afe8be0bbfb3de5dc1c6709fedb46d6c89c10da114ab5fc3d281")
version("3.2.3", sha256="52b5f1c6b8022bc5868c308c54fb77705e702d6c6f4594f99a0df216acf46239")
version("3.1.7", sha256="053a31fa80cf4aebe1068c987d2ef1e44ce418881427c4464751ae800c31d06c")
version("3.0.15", sha256="23c666d0edf20f14249b3d8f0368acaee9ab585b09e1de82107c66e1f3ec9533")
version(
"3.3.1",
sha256="777cd596284c883375a2a7a11bf5d2786fc5413255efab20c50d6ffe6d020b7e",
deprecated=True,
)
version(
"3.3.0",
sha256="53e66b043322a606abf0087e7699a0e033a37fa13feb9742df35c3a33b18fb02",
deprecated=True,
)
version(
"3.2.2",
sha256="197149c18d9e9f292c43f0400acaba12e5f52cacfe050f3d199277ea738ec2e7",
deprecated=True,
)
version(
"3.2.1",
sha256="83c7329fe52c850677d75e5d0b0ca245309b97e8ecbcfdc1dfdc4ab9fac35b39",
deprecated=True,
)
version(
"3.1.6",
sha256="5d2be4036b478ef3cb0a854ca9b353072c3a0e26d8a56f8f0ab9fb6ed32d38d7",
deprecated=True,
)
version(
"3.1.5",
sha256="6ae015467dabf0469b139ada93319327be24b98251ffaeceda0221848dc09262",
deprecated=True,
)
version(
"3.0.14",
sha256="eeca035d4dd4e84fc25846d952da6297484afa0650a6f84c682e39df3a4123ca",
deprecated=True,
)
version(
"3.0.13",
sha256="88525753f79d3bec27d2fa7c66aa0b92b3aa9498dafd93d7cfa4b3780cdae313",
deprecated=True,
)
version(
"1.1.1w",
sha256="cf3098950cb4d853ad95c0841f1f9c6d3dc102dccfcacd521d93925208b76ac8",
deprecated=True,
)
version(
"1.0.2u",
sha256="ecd0c6ffb493dd06707d38b14bb4d8c2288bb7033735606569d8f90f89669d16",
deprecated=True,
)
depends_on("c", type="build") # generated
# On Cray DVS mounts, we can't make symlinks to /etc/ssl/openssl.cnf,
# either due to a bug or because DVS is not intended to be POSIX compliant.
# Therefore, stick to system agnostic certs=mozilla.
variant(
"certs",
default="mozilla",
values=("mozilla", "system", "none"),
multi=False,
description=(
"Use certificates from the ca-certificates-mozilla package, symlink system "
"certificates, or use none, respectively. The default is `mozilla`, since it is "
"system agnostic. Instead of picking certs=system, one can mark openssl as an "
"external package, to avoid compiling openssl entirely."
),
)
variant("docs", default=False, description="Install docs and manpages")
variant("shared", default=True, description="Build shared library version")
with when("platform=windows"):
variant("dynamic", default=False, description="Link with MSVC's dynamic runtime library")
depends_on("zlib-api")
depends_on("perl@5.14.0:", type=("build", "test"))
depends_on("ca-certificates-mozilla", type="build", when="certs=mozilla")
depends_on("nasm", when="platform=windows")
depends_on("gmake", type="build", when="platform=linux")
depends_on("gmake", type="build", when="platform=darwin")
@classmethod
def determine_version(cls, exe):
output = Executable(exe)("version", output=str, error=str)
match = re.search(r"OpenSSL.(\S+)*", output)
return match.group(1) if match else None
@property
def libs(self):
return find_libraries(
["libssl", "libcrypto"],
root=self.prefix,
recursive=True,
shared=self.spec.variants["shared"].value,
runtime=False,
)
def handle_fetch_error(self, error):
tty.warn(
"Fetching OpenSSL failed. This may indicate that OpenSSL has "
"been updated, and the version in your instance of Spack is "
"insecure. Consider updating to the latest OpenSSL version."
)
def install(self, spec, prefix):
# OpenSSL uses these variables in its Makefile or config scripts. If any of them
# happen to be set in the environment, then this will override what is set in
# the script or Makefile, leading to build errors.
for v in ("APPS", "BUILD", "RELEASE", "MACHINE", "SYSTEM"):
env.pop(v, None)
if str(spec.target.family) in ("x86_64", "ppc64"):
# This needs to be done for all 64-bit architectures (except Linux,
# where it happens automatically?)
env["KERNEL_BITS"] = "64"
options = ["zlib"]
if spec.satisfies("@1.0"):
options.append("no-krb5")
# clang does not support the .arch directive in assembly files.
if "clang" in self.spec["c"].package.cc and spec.target.family == "aarch64":
options.append("no-asm")
elif "%nvhpc" in spec:
# Last tested on nvidia@22.3 for x86_64:
# nvhpc segfaults NVC++-F-0000-Internal compiler error.
# gen_llvm_expr(): unknown opcode 0 (crypto/rsa/rsa_oaep.c: 248)
options.append("no-asm")
elif spec.satisfies("@3: %oneapi"):
# Last tested on oneapi@2023.1.0 for x86_64:
# crypto/md5/md5-x86_64.s:684:31: error: expected string
options.append("no-asm")
# The default glibc provided by CentOS 7 does not provide proper
# atomic support when using the NVIDIA compilers
if self.spec.satisfies("%nvhpc os=centos7"):
options.append("-D__STDC_NO_ATOMICS__")
# Make a flag for shared library builds
base_args = [
"--prefix=%s" % prefix,
"--openssldir=%s" % join_path(prefix, "etc", "openssl"),
]
if spec.satisfies("platform=windows"):
if spec.satisfies("@:1"):
base_args.extend([f'CC="{self.compiler.cc}"', f'CXX="{self.compiler.cxx}"'])
else:
base_args.extend([f"CC={self.compiler.cc}", f"CXX={self.compiler.cxx}"])
base_args.append("VC-WIN64A")
else:
base_args.extend(
[
"-I{0}".format(self.spec["zlib-api"].prefix.include),
"-L{0}".format(self.spec["zlib-api"].prefix.lib),
]
)
base_args.extend(options)
if spec.satisfies("~shared"):
base_args.append("no-shared")
else:
base_args.append("shared")
# On Windows, we use perl for configuration and build through MSVC
# nmake.
if spec.satisfies("platform=windows"):
# The configure executable requires that paths with spaces
# on Windows be wrapped in quotes
Executable("perl")("Configure", *base_args, ignore_quotes=True)
else:
Executable("./config")(*base_args)
# Remove non-standard compiler options if present. These options are
# present e.g. on Darwin. They are non-standard, i.e. most compilers
# (e.g. gcc) will not accept them.
filter_file(r"-arch x86_64", "", "Makefile")
if spec.satisfies("platform=windows"):
host_make = nmake
else:
host_make = make
host_make()
if self.run_tests:
host_make("test", parallel=False) # 'VERBOSE=1'
install_tgt = "install" if self.spec.satisfies("+docs") else "install_sw"
# See https://github.com/openssl/openssl/issues/7466#issuecomment-432148137
host_make(install_tgt, parallel=False)
@run_after("install")
def link_system_certs(self):
if self.spec.variants["certs"].value != "system":
return
system_dirs = [
# CentOS, Fedora, RHEL
"/etc/pki/tls",
# Ubuntu
"/usr/lib/ssl",
# OpenSUSE
"/etc/ssl",
]
pkg_dir = join_path(self.prefix, "etc", "openssl")
mkdirp(pkg_dir)
for directory in system_dirs:
# Link configuration file
sys_conf = join_path(directory, "openssl.cnf")
pkg_conf = join_path(pkg_dir, "openssl.cnf")
if os.path.exists(sys_conf) and not os.path.exists(pkg_conf):
os.symlink(sys_conf, pkg_conf)
sys_cert = join_path(directory, "cert.pem")
pkg_cert = join_path(pkg_dir, "cert.pem")
# If a bundle exists, use it. This is the preferred way on Fedora,
# where the certs directory does not work.
if os.path.exists(sys_cert) and not os.path.exists(pkg_cert):
os.symlink(sys_cert, pkg_cert)
sys_certs = join_path(directory, "certs")
pkg_certs = join_path(pkg_dir, "certs")
# If the certs directory exists, symlink it into the package.
# We symlink the whole directory instead of all files because
# the directory contents might change without Spack noticing.
if os.path.isdir(sys_certs) and not os.path.islink(pkg_certs):
if os.path.isdir(pkg_certs):
os.rmdir(pkg_certs)
os.symlink(sys_certs, pkg_certs)
@run_after("install")
def copy_mozilla_certs(self):
if self.spec.variants["certs"].value != "mozilla":
return
pkg_dir = join_path(self.prefix, "etc", "openssl")
mkdirp(pkg_dir)
mozilla_pem = self.spec["ca-certificates-mozilla"].pem_path
pkg_cert = join_path(pkg_dir, "cert.pem")
install(mozilla_pem, pkg_cert)
def patch(self):
if self.spec.satisfies("%nvhpc"):
# Remove incompatible preprocessor flags
filter_file("-MF ", "", "Configurations/unix-Makefile.tmpl", string=True)
filter_file(r"-MT \$\@ ", "", "Configurations/unix-Makefile.tmpl", string=True)
def setup_build_environment(self, env):
env.set("PERL", self.spec["perl"].prefix.bin.perl)