gdnative_python/platforms/windows-64/SConscript

105 lines
3.2 KiB
Python

import zstandard
import tarfile
import json
import shutil
import subprocess
from pathlib import Path
Import("env")
cpython_build = Dir("cpython_build")
env["bits"] = "64"
env["pandemonium_binary_download_platform"] = "win64.exe"
env["cpython_build"] = cpython_build
env["cpython_build_dir"] = cpython_build
env["DIST_SITE_PACKAGES"] = Dir(f"{env['DIST_PLATFORM']}/Lib/site-packages")
### Build config for pythonscript ###
# Cannot use CPPPATH&LIBPATH here given headers are within `cpython_build` target,
# so Scons consider the headers are a missing target
env.AppendUnique(CFLAGS=[f"-I{cpython_build.abspath}/include"])
env.AppendUnique(LINKFLAGS=[f"/LIBPATH:{cpython_build.abspath}/libs"])
env.AppendUnique(CYTHON_COMPILE_DEPS=[cpython_build])
### Fetch Python prebuild ###
CPYTHON_PREBUILD_URL = "https://github.com/indygreg/python-build-standalone/releases/download/20200830/cpython-3.8.5-x86_64-pc-windows-msvc-shared-pgo-20200830T2254.tar.zst"
cpython_prebuild_archive = env.Download(
target=File(CPYTHON_PREBUILD_URL.rsplit("/", 1)[1]), url=CPYTHON_PREBUILD_URL
)
env.NoClean(cpython_prebuild_archive)
### Extract prebuild ###
def extract_cpython_prebuild(target, source, env):
archive_path = source[0].abspath
target_path = target[0].abspath
with open(archive_path, "rb") as fh:
dctx = zstandard.ZstdDecompressor()
with dctx.stream_reader(fh) as reader:
with tarfile.open(mode="r|", fileobj=reader) as tf:
tf.extractall(target_path)
cpython_prebuild_src = env.Command(
Dir("cpython_prebuild"), cpython_prebuild_archive, extract_cpython_prebuild
)
env.NoClean(cpython_prebuild_src)
### Generate custom build from the prebuild ###
def generate_cpython_build(target, source, env):
build = Path(target[0].abspath)
prebuild = Path(source[0].abspath) / "python"
conf = json.loads((prebuild / "PYTHON.json").read_text())
assert conf["version"] == "5"
assert conf["libpython_link_mode"] == "shared"
assert conf["target_triple"] == "x86_64-pc-windows-msvc"
shutil.copytree(str(prebuild / "install"), str(build), symlinks=True)
shutil.copytree(str(prebuild / "licenses"), str(build / "licenses"), symlinks=True)
stdlib_path = build / "Lib"
# Remove tests lib (pretty big and basically useless)
shutil.rmtree(str(stdlib_path / "test"))
# Remove .pdb debug symbols
for pdbfile in (build / "DLLs").glob("*.pdb"):
pdbfile.unlink()
# Also remove __pycache__ & .pyc stuff
for pycache in stdlib_path.glob("**/__pycache__"):
shutil.rmtree(str(pycache))
# Make sure site-packages is empty to avoid including pip (ensurepip should be used instead)
shutil.rmtree(str(stdlib_path / "site-packages"))
# Zip the stdlib to save plenty of space \o/
if env["compressed_stdlib"]:
shutil.make_archive(base_name=build / "python38", format="zip", root_dir=str(stdlib_path))
shutil.rmtree(str(stdlib_path))
stdlib_path.mkdir()
# Oddly enough, os.py must be present (even if empty !) otherwise
# Python failed to find it home...
(stdlib_path / "os.py").touch()
(stdlib_path / "site-packages").mkdir()
env.Command(cpython_build, cpython_prebuild_src, generate_cpython_build)
env.NoClean(cpython_build)