2022-05-18 05:04:18 +00:00
|
|
|
import argparse
|
|
|
|
import shutil
|
|
|
|
import subprocess
|
|
|
|
from pathlib import Path
|
|
|
|
|
2022-09-19 00:36:12 +00:00
|
|
|
from .common import (
|
|
|
|
exit_with_stdio,
|
|
|
|
get_make_flag,
|
|
|
|
get_pyodide_root,
|
|
|
|
get_unisolated_packages,
|
|
|
|
)
|
2022-09-11 07:20:56 +00:00
|
|
|
from .io import MetaConfig
|
2022-05-18 05:04:18 +00:00
|
|
|
|
|
|
|
|
2022-05-21 20:35:02 +00:00
|
|
|
def make_parser(parser: argparse.ArgumentParser) -> argparse.ArgumentParser:
|
2022-05-18 05:04:18 +00:00
|
|
|
parser.description = (
|
|
|
|
"Create xbuild env.\n\n"
|
|
|
|
"Note: this is a private endpoint that should not be used "
|
|
|
|
"outside of the Pyodide Makefile."
|
|
|
|
)
|
|
|
|
return parser
|
|
|
|
|
|
|
|
|
2022-06-30 06:08:46 +00:00
|
|
|
def copy_xbuild_files(xbuildenv_path: Path) -> None:
|
2022-05-18 05:04:18 +00:00
|
|
|
PYODIDE_ROOT = get_pyodide_root()
|
|
|
|
site_packages = Path(get_make_flag("HOSTSITEPACKAGES"))
|
2022-07-01 18:20:45 +00:00
|
|
|
# Store package cross-build-files into site_packages_extras in the same tree
|
|
|
|
# structure as they would appear in the real package.
|
|
|
|
# In install_xbuildenv, we will use:
|
|
|
|
# pip install -t $HOSTSITEPACKAGES -r requirements.txt
|
|
|
|
# cp site-packages-extras $HOSTSITEPACKAGES
|
|
|
|
site_packages_extras = xbuildenv_path / "site-packages-extras"
|
2022-05-18 05:04:18 +00:00
|
|
|
for pkg in (PYODIDE_ROOT / "packages").glob("**/meta.yaml"):
|
2022-09-11 07:20:56 +00:00
|
|
|
config = MetaConfig.from_yaml(pkg)
|
|
|
|
xbuild_files = config.build.cross_build_files
|
2022-05-18 05:04:18 +00:00
|
|
|
for path in xbuild_files:
|
2022-07-01 18:20:45 +00:00
|
|
|
target = site_packages_extras / path
|
2022-05-18 05:04:18 +00:00
|
|
|
target.parent.mkdir(parents=True, exist_ok=True)
|
|
|
|
shutil.copy(site_packages / path, target)
|
|
|
|
|
|
|
|
|
2022-07-01 18:20:45 +00:00
|
|
|
def get_relative_path(pyodide_root: Path, flag: str) -> Path:
|
|
|
|
return Path(get_make_flag(flag)).relative_to(pyodide_root)
|
|
|
|
|
|
|
|
|
|
|
|
def copy_wasm_libs(xbuildenv_path: Path) -> None:
|
|
|
|
pyodide_root = get_pyodide_root()
|
|
|
|
pythoninclude = get_relative_path(pyodide_root, "PYTHONINCLUDE")
|
|
|
|
wasm_lib_dir = get_relative_path(pyodide_root, "WASM_LIBRARY_DIR")
|
|
|
|
sysconfig_dir = get_relative_path(pyodide_root, "SYSCONFIGDATA_DIR")
|
|
|
|
xbuildenv_root = xbuildenv_path / "pyodide-root"
|
2022-07-06 21:37:19 +00:00
|
|
|
xbuildenv_path.mkdir(exist_ok=True)
|
2022-07-01 18:20:45 +00:00
|
|
|
to_copy: list[Path] = [
|
|
|
|
pythoninclude,
|
|
|
|
sysconfig_dir,
|
|
|
|
Path("Makefile.envs"),
|
|
|
|
wasm_lib_dir / "cmake",
|
|
|
|
Path("tools/pyo3_config.ini"),
|
2022-09-14 03:19:01 +00:00
|
|
|
Path("tools/python"),
|
2022-09-22 01:42:26 +00:00
|
|
|
Path("tools/cmake"),
|
2022-09-14 03:19:01 +00:00
|
|
|
Path("dist/repodata.json"),
|
|
|
|
Path("dist/pyodide_py.tar"),
|
2022-07-01 18:20:45 +00:00
|
|
|
]
|
2022-09-14 03:19:01 +00:00
|
|
|
to_copy.extend(
|
|
|
|
x.relative_to(pyodide_root) for x in (pyodide_root / "dist").glob("pyodide.*")
|
|
|
|
)
|
2022-07-01 18:20:45 +00:00
|
|
|
# Some ad-hoc stuff here to moderate size. We'd like to include all of
|
|
|
|
# wasm_lib_dir but there's 180mb of it. Better to leave out all the video
|
|
|
|
# codecs and stuff.
|
2022-11-04 02:04:50 +00:00
|
|
|
for pkg in ["ssl", "libcrypto", "zlib", "xml", "mpfr", "lapack", "blas", "f2c"]:
|
2022-07-01 18:20:45 +00:00
|
|
|
to_copy.extend(
|
|
|
|
x.relative_to(pyodide_root)
|
|
|
|
for x in (pyodide_root / wasm_lib_dir / "include").glob(f"**/*{pkg}*")
|
|
|
|
if "boost" not in str(x)
|
|
|
|
)
|
|
|
|
to_copy.extend(
|
|
|
|
x.relative_to(pyodide_root)
|
|
|
|
for x in (pyodide_root / wasm_lib_dir / "lib").glob(f"**/*{pkg}*")
|
|
|
|
)
|
|
|
|
|
|
|
|
for path in to_copy:
|
|
|
|
if (pyodide_root / path).is_dir():
|
|
|
|
shutil.copytree(
|
|
|
|
pyodide_root / path, xbuildenv_root / path, dirs_exist_ok=True
|
|
|
|
)
|
|
|
|
else:
|
|
|
|
(xbuildenv_root / path).parent.mkdir(exist_ok=True, parents=True)
|
|
|
|
shutil.copy(pyodide_root / path, xbuildenv_root / path)
|
|
|
|
|
|
|
|
|
2022-06-30 06:08:46 +00:00
|
|
|
def main(args: argparse.Namespace) -> None:
|
2022-05-18 05:04:18 +00:00
|
|
|
pyodide_root = get_pyodide_root()
|
|
|
|
xbuildenv_path = pyodide_root / "xbuildenv"
|
2022-09-19 00:36:12 +00:00
|
|
|
xbuildenv_root = xbuildenv_path / "pyodide-root"
|
2022-05-18 05:04:18 +00:00
|
|
|
shutil.rmtree(xbuildenv_path, ignore_errors=True)
|
2022-07-01 18:20:45 +00:00
|
|
|
|
2022-05-18 05:04:18 +00:00
|
|
|
copy_xbuild_files(xbuildenv_path)
|
2022-07-01 18:20:45 +00:00
|
|
|
copy_wasm_libs(xbuildenv_path)
|
2022-09-14 03:19:01 +00:00
|
|
|
|
2022-09-19 00:36:12 +00:00
|
|
|
(xbuildenv_root / "package.json").write_text("{}")
|
2022-05-18 05:04:18 +00:00
|
|
|
res = subprocess.run(
|
2022-09-19 00:36:12 +00:00
|
|
|
["npm", "i", "node-fetch@2"],
|
|
|
|
cwd=xbuildenv_root,
|
|
|
|
capture_output=True,
|
|
|
|
encoding="utf8",
|
2022-05-18 05:04:18 +00:00
|
|
|
)
|
2022-09-19 00:36:12 +00:00
|
|
|
if res.returncode != 0:
|
|
|
|
print("Failed to install node-fetch:")
|
|
|
|
exit_with_stdio(res)
|
|
|
|
|
|
|
|
res = subprocess.run(
|
|
|
|
["pip", "freeze", "--path", get_make_flag("HOSTSITEPACKAGES")],
|
|
|
|
capture_output=True,
|
|
|
|
encoding="utf8",
|
2022-07-06 21:37:19 +00:00
|
|
|
)
|
2022-09-19 00:36:12 +00:00
|
|
|
if res.returncode != 0:
|
|
|
|
print("Failed to run pip freeze:")
|
|
|
|
exit_with_stdio(res)
|
|
|
|
|
|
|
|
(xbuildenv_path / "requirements.txt").write_text(res.stdout)
|
|
|
|
(xbuildenv_root / "unisolated.txt").write_text("\n".join(get_unisolated_packages()))
|