pyodide/pyodide-build/pyodide_build/cli/build_recipes.py

136 lines
4.7 KiB
Python

from pathlib import Path
import typer
from .. import build_env, buildall, buildpkg, pywasmcross
from ..build_env import init_environment
from ..common import get_num_cores
from ..logger import logger
def recipe(
packages: list[str] = typer.Argument(
..., help="Packages to build, or ``*`` for all packages in recipe directory"
),
recipe_dir: str = typer.Option(
None,
help="The directory containing the recipe of packages. "
"If not specified, the default is ``./packages``",
),
no_deps: bool = typer.Option(
False, help="If true, do not build dependencies of the specified packages. "
),
install: bool = typer.Option(
False,
help="If true, install the built packages into the install_dir. "
"If false, build packages without installing.",
),
install_dir: str = typer.Option(
None,
help="Path to install built packages and pyodide-lock.json. "
"If not specified, the default is ``./dist``.",
),
metadata_files: bool = typer.Option(
False,
help="If true, extract the METADATA file from the built wheels "
"to a matching ``*.whl.metadata`` file. "
"If false, no ``*.whl.metadata`` file is produced.",
),
cflags: str = typer.Option(
None, help="Extra compiling flags. Default: SIDE_MODULE_CFLAGS"
),
cxxflags: str = typer.Option(
None, help="Extra compiling flags. Default: SIDE_MODULE_CXXFLAGS"
),
ldflags: str = typer.Option(
None, help="Extra linking flags. Default: SIDE_MODULE_LDFLAGS"
),
target_install_dir: str = typer.Option(
None,
help="The path to the target Python installation. Default: TARGETINSTALLDIR",
),
host_install_dir: str = typer.Option(
None,
help="Directory for installing built host packages. Default: HOSTINSTALLDIR",
),
log_dir: str = typer.Option(None, help="Directory to place log files"),
force_rebuild: bool = typer.Option(
False,
help="Force rebuild of all packages regardless of whether they appear to have been updated",
),
continue_: bool = typer.Option(
False,
"--continue",
help="Continue a build from the middle. For debugging. Implies '--force-rebuild'",
),
n_jobs: int = typer.Option(
None,
help="Number of packages to build in parallel (default: # of cores in the system)",
),
compression_level: int = typer.Option(
6,
help="Level of zip compression to apply when installing. 0 means no compression.",
),
) -> None:
"""Build packages using yaml recipes and create pyodide-lock.json"""
init_environment()
if build_env.in_xbuildenv():
build_env.check_emscripten_version()
root = Path.cwd()
recipe_dir_ = root / "packages" if not recipe_dir else Path(recipe_dir).resolve()
install_dir_ = root / "dist" if not install_dir else Path(install_dir).resolve()
log_dir_ = None if not log_dir else Path(log_dir).resolve()
n_jobs = n_jobs or get_num_cores()
if not recipe_dir_.is_dir():
raise FileNotFoundError(f"Recipe directory {recipe_dir_} not found")
build_args = pywasmcross.BuildArgs(
cflags=cflags,
cxxflags=cxxflags,
ldflags=ldflags,
target_install_dir=target_install_dir,
host_install_dir=host_install_dir,
)
build_args = buildall.set_default_build_args(build_args)
if no_deps:
if install or log_dir_ or metadata_files:
logger.warning(
"WARNING: when --no-deps is set, the --install, --log-dir, and --metadata-files parameters are ignored",
)
# TODO: use multiprocessing?
for package in packages:
package_path = recipe_dir_ / package
buildpkg.build_package(package_path, build_args, force_rebuild, continue_)
else:
if len(packages) == 1 and "," in packages[0]:
# Handle packages passed with old comma separated syntax.
# This is to support `PYODIDE_PACKAGES="pkg1,pkg2,..." make` syntax.
targets = packages[0].replace(" ", "")
else:
targets = ",".join(packages)
pkg_map = buildall.build_packages(
recipe_dir_, targets, build_args, n_jobs, force_rebuild
)
if log_dir_:
buildall.copy_logs(pkg_map, log_dir_)
if install:
buildall.install_packages(
pkg_map,
install_dir_,
compression_level=compression_level,
metadata_files=metadata_files,
)
elif metadata_files:
logger.warning(
"WARNING: when --install is not set, the --metadata-files parameter is ignored",
)