pyodide/pyodide-build/pyodide_build/install_xbuildenv.py

88 lines
3.2 KiB
Python

import argparse
import json
import shutil
import subprocess
from pathlib import Path
from urllib.request import urlopen, urlretrieve
from .common import exit_with_stdio, get_make_flag, get_pyodide_root
from .create_pypa_index import create_pypa_index
def make_parser(parser: argparse.ArgumentParser) -> argparse.ArgumentParser:
parser.description = (
"Install xbuild env.\n\n"
"The installed environment is the same as the one that would result from\n"
"`PYODIDE_PACKAGES='scipy' make` except that it is much faster.\n"
"The goal is to enable out-of-tree builds for binary packages that depend\n"
"on numpy or scipy.\n"
"Note: this is a private endpoint that should not be used outside of the Pyodide Makefile."
)
parser.add_argument("--download", action="store_true", help="Download xbuild env")
parser.add_argument("xbuildenv", type=str, nargs=1)
return parser
def download_xbuildenv(version: str, xbuildenv_path: Path) -> None:
from shutil import rmtree, unpack_archive
from tempfile import NamedTemporaryFile
print("Downloading xbuild environment")
rmtree(xbuildenv_path, ignore_errors=True)
with NamedTemporaryFile(suffix=".tar") as f:
urlretrieve(
f"https://github.com/pyodide/pyodide/releases/download/{version}/xbuildenv-{version}.tar.bz2",
f.name,
)
unpack_archive(f.name, xbuildenv_path)
def install_xbuildenv(version: str, xbuildenv_path: Path) -> None:
print("Installing xbuild environment")
xbuildenv_path = xbuildenv_path / "xbuildenv"
pyodide_root = get_pyodide_root()
xbuildenv_root = xbuildenv_path / "pyodide-root"
host_site_packages = xbuildenv_root / Path(
get_make_flag("HOSTSITEPACKAGES")
).relative_to(pyodide_root)
host_site_packages.mkdir(exist_ok=True, parents=True)
result = subprocess.run(
[
"pip",
"install",
"-t",
host_site_packages,
"-r",
xbuildenv_path / "requirements.txt",
],
capture_output=True,
encoding="utf8",
)
if result.returncode != 0:
exit_with_stdio(result)
# Copy the site-packages-extras (coming from the cross-build-files meta.yaml
# key) over the site-packages directory with the newly installed packages.
shutil.copytree(
xbuildenv_path / "site-packages-extras", host_site_packages, dirs_exist_ok=True
)
cdn_base = f"https://cdn.jsdelivr.net/pyodide/v{version}/full/"
if (xbuildenv_root / "repodata.json").exists():
repodata_bytes = (xbuildenv_root / "repodata.json").read_bytes()
else:
repodata_url = cdn_base + "repodata.json"
with urlopen(repodata_url) as response:
repodata_bytes = response.read()
repodata = json.loads(repodata_bytes)
version = repodata["info"]["version"]
create_pypa_index(repodata["packages"], xbuildenv_root, cdn_base)
def main(args: argparse.Namespace) -> None:
from . import __version__
xbuildenv_path = Path(args.xbuildenv[0])
version = __version__
if args.download:
download_xbuildenv(version, xbuildenv_path)
install_xbuildenv(version, xbuildenv_path)