diff --git a/pyodide-build/pyodide_build/pywasmcross.py b/pyodide-build/pyodide_build/pywasmcross.py index 0beae6915..7d9a224e6 100755 --- a/pyodide-build/pyodide_build/pywasmcross.py +++ b/pyodide-build/pyodide_build/pywasmcross.py @@ -12,33 +12,45 @@ import json import os import sys from pathlib import Path, PurePosixPath +from typing import Any -IS_MAIN = __name__ == "__main__" -if IS_MAIN: +from __main__ import __file__ as INVOKED_PATH_STR + +INVOKED_PATH = Path(INVOKED_PATH_STR) + +SYMLINKS = {"cc", "c++", "ld", "ar", "gcc", "gfortran", "cargo"} +IS_COMPILER_INVOCATION = INVOKED_PATH.name in SYMLINKS + +if IS_COMPILER_INVOCATION: # If possible load from environment variable, if necessary load from disk. if "PYWASMCROSS_ARGS" in os.environ: PYWASMCROSS_ARGS = json.loads(os.environ["PYWASMCROSS_ARGS"]) - else: - with open(Path(__file__).parent / "pywasmcross_env.json") as f: + try: + with open(INVOKED_PATH.parent / "pywasmcross_env.json") as f: PYWASMCROSS_ARGS = json.load(f) + except FileNotFoundError: + raise RuntimeError( + "Invalid invocation: can't find PYWASMCROSS_ARGS." + f" Invoked from {INVOKED_PATH}." + ) - # restore __name__ so that relative imports work as we expect - __name__ = PYWASMCROSS_ARGS.pop("orig__name__") sys.path = PYWASMCROSS_ARGS.pop("PYTHONPATH") os.environ["PATH"] = PYWASMCROSS_ARGS.pop("PATH") + # restore __name__ so that relative imports work as we expect + __name__ = PYWASMCROSS_ARGS.pop("orig__name__") + import re +import shutil import subprocess from collections import namedtuple from contextlib import contextmanager from tempfile import TemporaryDirectory -from typing import Any, Iterator, Literal, MutableMapping, NoReturn +from typing import Iterator, Literal, MutableMapping, NoReturn from pyodide_build import common from pyodide_build._f2c_fixes import fix_f2c_input, fix_f2c_output, scipy_fixes -symlinks = {"cc", "c++", "ld", "ar", "gcc", "gfortran", "cargo"} - def symlink_dir() -> Path: return Path(common.get_make_flag("TOOLSDIR")) / "symlinks" @@ -68,13 +80,17 @@ def make_command_wrapper_symlinks( exist. """ exec_path = Path(__file__).resolve() - for symlink in symlinks: + for symlink in SYMLINKS: symlink_path = symlink_dir / symlink if os.path.lexists(symlink_path) and not symlink_path.exists(): # remove broken symlink so it can be re-created symlink_path.unlink() try: - symlink_path.symlink_to(exec_path) + pywasmcross_exe = shutil.which("_pywasmcross") + if pywasmcross_exe: + symlink_path.symlink_to(pywasmcross_exe) + else: + symlink_path.symlink_to(exec_path) except FileExistsError: pass if symlink == "c++": @@ -609,13 +625,13 @@ def environment_substitute_args( return subbed_args -if IS_MAIN: - REPLAY_ARGS = ReplayArgs(**PYWASMCROSS_ARGS) - +def compiler_main(): + replay_args = ReplayArgs(**PYWASMCROSS_ARGS) basename = Path(sys.argv[0]).name args = list(sys.argv) args[0] = basename - if basename in symlinks: - sys.exit(handle_command(args, REPLAY_ARGS)) - else: - raise Exception(f"Unexpected invocation '{basename}'") + sys.exit(handle_command(args, replay_args)) + + +if IS_COMPILER_INVOCATION: + compiler_main() diff --git a/pyodide-build/setup.py b/pyodide-build/setup.py index 25f849ce1..52a7cac56 100644 --- a/pyodide-build/setup.py +++ b/pyodide-build/setup.py @@ -2,4 +2,10 @@ import setuptools if __name__ == "__main__": - setuptools.setup() + setuptools.setup( + entry_points={ + "console_scripts": [ + "_pywasmcross = pyodide_build.pywasmcross:compiler_main", + ] + } + )