DepperDan/build_functions/build_openssl.py

108 lines
4.9 KiB
Python

# (c) 2025 by Stephan Menzel
# Licensed under the Apache License, Version 2.0.
# See attached file LICENSE for full details
import os
import zipfile
from pathlib import Path
import requests
from build_functions.build_utils import run_in_shell, print_banner, file_and_console_log
from common.azure import write_package_version_batch
from common.directory_helpers import pushd, get_local_prefix
from common.git_helpers import clone_git_tag
import common.settings
from package.package_info import get_package_info
def build_openssl(prefix: Path, sbom: dict):
print_banner("Building OpenSSL")
package_info = get_package_info("openssl")
package_info.add_to_sbom(sbom)
zlib_install_path = package_info.dependency_path("zlib")
zlib_include_path = zlib_install_path / "include"
zlib_library_path = zlib_install_path / "lib" / common.settings.zlib_static_lib_name
openssl_dir = clone_git_tag(package_info, recursive=False)
with pushd(openssl_dir):
install_prefix = package_info.install_location()
if not common.settings.rebuild and Path("built_and_installed.txt").exists():
file_and_console_log("already built, exiting")
return install_prefix
# In the azure devops pipeline there's no Perl available, yet we need it to compile OpenSSL
# So I download the portable package and use this
perl_package_filename = "strawberry-perl-5.38.2.2-64bit-portable.zip"
url = f"https://github.com/StrawberryPerl/Perl-Dist-Strawberry/releases/download/SP_53822_64bit/{perl_package_filename}"
r = requests.get(url, allow_redirects=True)
with open(perl_package_filename, "wb") as package_file:
package_file.write(r.content)
with zipfile.ZipFile(perl_package_filename, "r") as zip_ref:
os.mkdir("perl_portable")
zip_ref.extractall("perl_portable")
path_amend = Path("./perl_portable/c/bin").resolve()
os.environ["PATH"] += os.pathsep + str(path_amend)
# This requires not only perl but also assumes we are in a "Developer Shell" on Windows,
# meaning we have nmake in the path
if os.name == "nt":
run_in_shell("perl.exe .\\Configure no-shared no-legacy zlib no-zlib-dynamic "
"threads no-unit-test no-egd "
f"--with-zlib-include={str(zlib_include_path)} "
f"--with-zlib-lib={str(zlib_library_path)} "
f"--prefix={str(install_prefix)} --openssldir={str(install_prefix)} "
"VC-WIN64A")
# OpenSSL always assumes /MT when building statically. Looks like this cannot be overridden
# So we change the makefile by replacing the occurrences
#
# Update: This trick used to work but no longer does with 3.2.1 / recent MSVC
# I have failed to find a solution but found this source: https://github.com/openssl/openssl/discussions/22668
# arguing this is not necessary (anymore?) because of the /Zl switch which defers the selection
# of the runtime to executable link time. I'm not really buying it but there's little
# I can do about that right now and I will try if it really works when we use OpenSSL with static
# runtime selection. We we only relly know once the egm links against this warning free and works.
# If such is not the case and you end up here looking at this, try again to modify the selected
# runtime like I do below.
#
with open('makefile', 'r') as file:
filedata = file.read()
# Replace the MT flags
filedata = filedata.replace("/MT", "/MD")
# Write the file out again
with open('makefile', 'w') as lockfile:
lockfile.write(filedata)
# If you are here debugging why this doesn't work, you are probably not starting
# this in a x64 native tools command prompt shell
run_in_shell("nmake install")
# I know, dirty, but building openssl takes for evah
with open("built_and_installed.txt", "w") as lockfile:
lockfile.write("built")
elif os.name == "posix":
run_in_shell("perl ./Configure no-shared zlib no-zlib-dynamic threads no-unit-test "
f"--with-zlib-include={str(zlib_include_path)} "
f"--with-zlib-lib={str(zlib_library_path)} "
f"--prefix={str(install_prefix)} --openssldir={str(install_prefix)} "
"")
run_in_shell(f"make -j{common.settings.num_cores} install")
with open("built_and_installed.txt", "w") as lockfile:
lockfile.write("built")
write_package_version_batch(package_info.version)
return install_prefix