import os import re from uuid import uuid4 from io import BytesIO from zipfile import ZipFile from urllib.request import urlopen, HTTPError from SCons.Errors import UserError Import("env") def resolve_pandemonium_download_url(major, minor, patch, extra, platform): #version = f"{major}.{minor}.{patch}" if patch != 0 else f"{major}.{minor}" #if extra == "stable": # return f"https://downloads.tuxfamily.org/godotengine/{version}/Pandemonium_v{version}-{extra}_{platform}.zip" #else: # return f"https://downloads.tuxfamily.org/godotengine/{version}/{extra}/Pandemonium_v{version}-{extra}_{platform}.zip" return "" def resolve_pandemonium_binary_name(major, minor, patch, extra, platform): version = f"{major}.{minor}.{patch}" if patch != 0 else f"{major}.{minor}" return f"Pandemonium_v{version}-{extra}_{platform}" SConscript([f"{env['platform']}/SConscript"]) # Platform-dependant variables assert "bits" in env assert "pandemonium_binary_download_platform" in env assert "cpython_build" in env assert "cpython_build_dir" in env assert "DIST_SITE_PACKAGES" in env # Cython modules need to link against libpython.so env.AppendUnique(CYTHON_COMPILE_DEPS=[env["cpython_build"]]) ### Install CPython build into dist ### # Installing cpython build into dist cannot be simply done by a # `env.InstallAs("$DIST_PLATFORM", cypthon_build)` rule given it would # conflict with the rules that install libpythonscript&godot modules. # To solve this we represent the installation of the build by a virtual target. cpython_build_install_marker = env.File("cpython_build_installed_in_dist.marker") env.VirtualTargetCommand( marker=cpython_build_install_marker, condition=lambda env: os.path.exists(env.Dir("$DIST_PLATFORM").abspath), source=env["cpython_build"], # Note we don't use `cpython_build_dir` ! action=[Delete("$DIST_PLATFORM"), Copy("$DIST_PLATFORM", env["cpython_build_dir"])], ) # Replace default Install command to always depend on cpython build install env.VanillaInstall = env.Install env.VanillaInstallAs = env.InstallAs def install(env, target, source): out = env.VanillaInstall(target, source) env.Depends(out, cpython_build_install_marker) return out def install_as(env, target, source): out = env.VanillaInstallAs(target, source) env.Depends(out, cpython_build_install_marker) return out env.AddMethod(install, "Install") env.AddMethod(install_as, "InstallAs") ### Pandemonium binary (to run tests) ### if not env["pandemonium_binary"]: pandemonium_download_url = resolve_pandemonium_download_url( *env["pandemonium_binary_download_version"], env["pandemonium_binary_download_platform"] ) pandemonium_binary_name = resolve_pandemonium_binary_name( *env["pandemonium_binary_download_version"], env["pandemonium_binary_download_platform"] ) env["pandemonium_binary"] = File(pandemonium_binary_name) pandemonium_binary_zip_path = env.get("pandemonium_binary_download_zip_path", pandemonium_binary_name) def download_and_extract(target, source, env): try: with urlopen(pandemonium_download_url) as rep: zipfile = ZipFile(BytesIO(rep.read())) except HTTPError as exc: # It seems SCons swallows HTTPError, so we have to wrap it raise UserError(exc) from exc if pandemonium_binary_zip_path not in zipfile.namelist(): raise UserError(f"Archive doesn't contain {pandemonium_binary_zip_path}") with open(target[0].abspath, "wb") as fd: fd.write(zipfile.open(pandemonium_binary_zip_path).read()) if env["HOST_OS"] != "win32": os.chmod(target[0].abspath, 0o755) env.Command( env["pandemonium_binary"], None, Action(download_and_extract, f"Download&extract {pandemonium_download_url}"), ) env.NoClean(env["pandemonium_binary"])