D7net
Home
Console
Upload
information
Create File
Create Folder
About
Tools
:
/
proc
/
thread-self
/
root
/
opt
/
saltstack
/
salt
/
lib
/
python3.10
/
site-packages
/
relenv
/
build
/
Filename :
darwin.py
back
Copy
# Copyright 2025-2026 Broadcom. # SPDX-License-Identifier: Apache-2 # mypy: ignore-errors """ The darwin build process. """ from __future__ import annotations import glob import io import os import pathlib import shutil import tarfile import time import urllib.request from typing import IO, TYPE_CHECKING from ..common import DARWIN, MACOS_DEVELOPMENT_TARGET, arches, runcmd from .common import ( Dirs, build_openssl, build_sqlite, builds, finalize, get_dependency_version, update_sbom_checksums, ) if TYPE_CHECKING: from collections.abc import MutableMapping ARCHES = arches[DARWIN] def populate_env(env: MutableMapping[str, str], dirs: Dirs) -> None: """ Make sure we have the correct environment variables set. :param env: The environment dictionary :type env: dict :param dirs: The working directories :type dirs: ``relenv.build.common.Dirs`` """ env["CC"] = "clang" ldflags = [ "-Wl,-rpath,{prefix}/lib", "-L{prefix}/lib", ] env["LDFLAGS"] = " ".join(ldflags).format(prefix=dirs.prefix) env["MACOSX_DEPLOYMENT_TARGET"] = MACOS_DEVELOPMENT_TARGET cflags = [ "-I{prefix}/include", "-I{prefix}/include/readline", ] env["CFLAGS"] = " ".join(cflags).format(prefix=dirs.prefix) def update_expat(dirs: Dirs, env: MutableMapping[str, str]) -> None: """ Update the bundled expat library to the latest version. Python ships with an older bundled expat. This function updates it to the latest version for security and bug fixes. """ # Get version from JSON expat_info = get_dependency_version("expat", "darwin") if not expat_info: # No update needed, use bundled version return version = expat_info["version"] version_tag = version.replace(".", "_") url = f"https://github.com/libexpat/libexpat/releases/download/R_{version_tag}/expat-{version}.tar.xz" expat_dir = pathlib.Path(dirs.source) / "Modules" / "expat" if not expat_dir.exists(): # No expat directory, skip return # Download expat tarball tmpbuild = pathlib.Path(dirs.tmpbuild) tarball_path = tmpbuild / f"expat-{version}.tar.xz" urllib.request.urlretrieve(url, str(tarball_path)) # Extract tarball with tarfile.open(tarball_path) as tar: tar.extractall(path=str(tmpbuild)) # Copy source files to Modules/expat/ expat_source_dir = tmpbuild / f"expat-{version}" / "lib" updated_files = [] for source_file in ["*.h", "*.c"]: for file_path in glob.glob(str(expat_source_dir / source_file)): target_file = expat_dir / pathlib.Path(file_path).name # Remove old file if it exists if target_file.exists(): target_file.unlink() shutil.copy2(file_path, str(expat_dir)) updated_files.append(target_file) # Touch all updated files to ensure make rebuilds them # (The tarball may contain files with newer timestamps) now = time.time() for target_file in updated_files: os.utime(target_file, (now, now)) # For expat >= 2.8.0, new entropy source files are required but not compiled # by Python's build system. Include them directly in xmlparse.c. xmlparse_c = expat_dir / "xmlparse.c" if xmlparse_c.exists(): with open(str(xmlparse_c), "a") as f: f.write("\n/* Relenv: include new entropy sources for expat >= 2.8.0 */\n") f.write('#if defined(_WIN32)\n#include "random_rand_s.c"\n#endif\n') f.write('#if defined(HAVE_GETENTROPY)\n#include "random_getentropy.c"\n#endif\n') f.write("#if defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM)\n") f.write('#include "random_getrandom.c"\n#endif\n') f.write('#if defined(HAVE_ARC4RANDOM_BUF)\n#include "random_arc4random_buf.c"\n#endif\n') f.write('#if defined(HAVE_ARC4RANDOM)\n#include "random_arc4random.c"\n#endif\n') f.write('#if !defined(_WIN32) && defined(XML_DEV_URANDOM)\n#include "random_dev_urandom.c"\n#endif\n') # Update SBOM with correct checksums for updated expat files files_to_update = {} for target_file in updated_files: # SBOM uses relative paths from Python source root relative_path = f"Modules/expat/{target_file.name}" files_to_update[relative_path] = target_file update_sbom_checksums(dirs.source, files_to_update) def build_python(env: MutableMapping[str, str], dirs: Dirs, logfp: IO[str]) -> None: """ Run the commands to build Python. :param env: The environment dictionary :type env: dict :param dirs: The working directories :type dirs: ``relenv.build.common.Dirs`` :param logfp: A handle for the log file :type logfp: file """ # Update bundled expat to latest version update_expat(dirs, env) env["LDFLAGS"] = "-Wl,-rpath,{prefix}/lib {ldflags}".format(prefix=dirs.prefix, ldflags=env["LDFLAGS"]) runcmd( [ "./configure", "-v", f"--prefix={dirs.prefix}", f"--with-openssl={dirs.prefix}", "--enable-optimizations", "--disable-test-modules", ], env=env, stderr=logfp, stdout=logfp, ) with open("Modules/Setup", "a+") as fp: fp.seek(0, io.SEEK_END) fp.write("*disabled*\n_tkinter\nnsl\nncurses\nnis\n") runcmd(["sed", "s/#zlib/zlib/g", "Modules/Setup"], env=env, stderr=logfp, stdout=logfp) runcmd(["make", "-j8"], env=env, stderr=logfp, stdout=logfp) runcmd(["make", "install"], env=env, stderr=logfp, stdout=logfp) build = builds.add("darwin", populate_env=populate_env) # Get dependency versions from JSON (with fallback to hardcoded values) openssl_info = get_dependency_version("openssl", "darwin") if openssl_info: openssl_version = openssl_info["version"] openssl_url = openssl_info["url"] openssl_checksum = openssl_info["sha256"] else: openssl_version = "3.5.4" openssl_url = "https://github.com/openssl/openssl/releases/download/openssl-{version}/openssl-{version}.tar.gz" openssl_checksum = "b75daac8e10f189abe28a076ba5905d363e4801f" build.add( "openssl", build_func=build_openssl, download={ "url": openssl_url, "version": openssl_version, "checksum": openssl_checksum, }, ) # Get XZ version from JSON xz_info = get_dependency_version("xz", "darwin") if xz_info: xz_version = xz_info["version"] xz_url = xz_info["url"] xz_checksum = xz_info["sha256"] else: xz_version = "5.8.1" xz_url = "http://tukaani.org/xz/xz-{version}.tar.gz" xz_checksum = "ed4d5589c4cfe84e1697bd02a9954b76af336931" build.add( "XZ", download={ "url": xz_url, "version": xz_version, "checksum": xz_checksum, }, ) # Get SQLite version from JSON sqlite_info = get_dependency_version("sqlite", "darwin") if sqlite_info: sqlite_url = sqlite_info["url"] sqlite_checksum = sqlite_info["sha256"] sqlite_version_num = sqlite_info.get("sqliteversion", "3500400") else: sqlite_version_num = "3500400" sqlite_url = "https://sqlite.org/2025/sqlite-autoconf-{version}.tar.gz" sqlite_checksum = "145048005c777796dd8494aa1cfed304e8c34283" build.add( name="SQLite", build_func=build_sqlite, download={ "url": sqlite_url, "fallback_url": "https://woz.io/relenv/dependencies/sqlite-autoconf-{version}.tar.gz", "version": sqlite_version_num, "checksum": sqlite_checksum, }, ) build.add( "python", build_func=build_python, wait_on=[ "openssl", "XZ", "SQLite", ], download={ "url": "https://www.python.org/ftp/python/{version}/Python-{version}.tar.xz", "fallback_url": "https://woz.io/relenv/dependencies/Python-{version}.tar.gz", "version": build.version, "checksum": None, }, ) build.add( "relenv-finalize", build_func=finalize, wait_on=[ "python", ], )