Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Build with wasm exception handling #81

Open
wants to merge 23 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
30cbe32
Build with wasm exception handling
hoodmane Jan 13, 2025
a02dda7
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jan 13, 2025
3186d20
Fix
hoodmane Jan 13, 2025
8256e72
Fix again
hoodmane Jan 13, 2025
5e46696
Only download rust toolchain once
hoodmane Jan 13, 2025
adda8a5
Fix
hoodmane Jan 13, 2025
b33d1c9
Always run rustup toolchain link
hoodmane Jan 14, 2025
f2d72e7
Add wasm-sjlj suffix to wasm-eh libs
hoodmane Jan 14, 2025
3c3dc79
Update Emscripten toolchain version
hoodmane Jan 14, 2025
30517bd
Merge branch 'main' into rust-wasm-eh
hoodmane Jan 15, 2025
0c88c0f
Merge branch 'main' into rust-wasm-eh
hoodmane Jan 15, 2025
663e78e
Remove duplication of toolchain name
hoodmane Jan 15, 2025
529a583
Pass recipe ldflags through library rewriting logic as well
hoodmane Jan 15, 2025
a63c7b9
Add ignore for too many branches lint
hoodmane Jan 15, 2025
b50d1c1
Only install Emscripten target from url
hoodmane Jan 15, 2025
3b1734b
Fix syntax error
hoodmane Jan 15, 2025
c93aab1
Move target url to config variable
hoodmane Jan 15, 2025
036626d
Set default rust_toolchain to nightly-2025-01-15
hoodmane Jan 15, 2025
7bbdde2
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jan 15, 2025
114e477
Only change pywasmcross behavior for new abi
hoodmane Jan 15, 2025
330e762
Merge branch 'main' into rust-wasm-eh
hoodmane Jan 27, 2025
6a49a51
Merge branch 'main' into rust-wasm-eh
hoodmane Jan 30, 2025
194c463
Don't append None to new_args
hoodmane Jan 31, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions pyodide_build/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,9 @@ def to_bool(value: str) -> bool:
return value.lower() not in {"", "0", "false", "no", "off"}


def download_and_unpack_archive(url: str, path: Path, descr: str) -> None:
def download_and_unpack_archive(
url: str, path: Path, descr: str, *, exists_ok: bool = False
) -> None:
"""
Download the cross-build environment from the given URL and extract it to the given path.

Expand All @@ -465,7 +467,7 @@ def download_and_unpack_archive(url: str, path: Path, descr: str) -> None:
"""
logger.info("Downloading %s from %s", descr, url)

if path.exists():
if not exists_ok and path.exists():
raise FileExistsError(f"Path {path} already exists")

try:
Expand Down
5 changes: 4 additions & 1 deletion pyodide_build/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ def _get_make_environment_vars(self) -> Mapping[str, str]:
"cpythoninstall": "CPYTHONINSTALL",
"rustflags": "RUSTFLAGS",
"rust_toolchain": "RUST_TOOLCHAIN",
"rust_emscripten_target_url": "RUST_EMSCRIPTEN_TARGET_URL",
"cflags": "SIDE_MODULE_CFLAGS",
"cxxflags": "SIDE_MODULE_CXXFLAGS",
"ldflags": "SIDE_MODULE_LDFLAGS",
Expand Down Expand Up @@ -210,6 +211,7 @@ def _get_make_environment_vars(self) -> Mapping[str, str]:
"cxxflags",
"ldflags",
"rust_toolchain",
"rust_emscripten_target_url",
"meson_cross_file",
"skip_emscripten_version_check",
"build_dependency_index_url",
Expand All @@ -228,7 +230,8 @@ def _get_make_environment_vars(self) -> Mapping[str, str]:
"rustflags": "-C link-arg=-sSIDE_MODULE=2 -C link-arg=-sWASM_BIGINT -Z link-native-libraries=no",
"cargo_build_target": "wasm32-unknown-emscripten",
"cargo_target_wasm32_unknown_emscripten_linker": "emcc",
"rust_toolchain": "nightly-2024-01-29",
"rust_toolchain": "nightly-2025-01-15",
"rust_emscripten_target_url": "",
# Other configuration
"pyodide_jobs": "1",
"skip_emscripten_version_check": "0",
Expand Down
1 change: 1 addition & 0 deletions pyodide_build/pypabuild.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,7 @@ def get_build_env(
args["orig__name__"] = __name__
args["pythoninclude"] = get_build_flag("PYTHONINCLUDE")
args["PATH"] = env["PATH"]
args["abi"] = get_build_flag("PYODIDE_ABI_VERSION")

pywasmcross_env = json.dumps(args)
# Store into environment variable and to disk. In most cases we will
Expand Down
15 changes: 12 additions & 3 deletions pyodide_build/pywasmcross.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ class CrossCompileArgs(NamedTuple):
target_install_dir: str = "" # The path to the target Python installation
pythoninclude: str = "" # path to the cross-compiled Python include directory
exports: Literal["whole_archive", "requested", "pyinit"] | list[str] = "pyinit"
abi: str = ""


def is_link_cmd(line: list[str]) -> bool:
Expand All @@ -93,7 +94,7 @@ def is_link_cmd(line: list[str]) -> bool:
return False


def replay_genargs_handle_dashl(arg: str, used_libs: set[str]) -> str | None:
def replay_genargs_handle_dashl(arg: str, used_libs: set[str], abi: str) -> str | None:
"""
Figure out how to replace a `-lsomelib` argument.

Expand All @@ -118,6 +119,9 @@ def replay_genargs_handle_dashl(arg: str, used_libs: set[str]) -> str | None:
if arg == "-lgfortran":
return None

if abi > "2025" and arg in ["-lfreetype", "-lpng"]:
arg += "-wasm-sjlj"

# WASM link doesn't like libraries being included twice
# skip second one
if arg in used_libs:
Expand Down Expand Up @@ -555,7 +559,7 @@ def handle_command_generate_args( # noqa: C901
continue

if arg.startswith("-l"):
result = replay_genargs_handle_dashl(arg, used_libs)
result = replay_genargs_handle_dashl(arg, used_libs, build_args.abi)
elif arg.startswith("-I"):
result = replay_genargs_handle_dashI(arg, build_args.target_install_dir)
elif arg.startswith("-Wl"):
Expand All @@ -578,7 +582,11 @@ def handle_command_generate_args( # noqa: C901
# Better to fail at compile or link time.
if is_link_cmd(line):
new_args.append("-Wl,--fatal-warnings")
new_args.extend(build_args.ldflags.split())
for arg in build_args.ldflags.split():
if arg.startswith("-l"):
arg = replay_genargs_handle_dashl(arg, used_libs, build_args.abi)
if arg:
new_args.append(arg)
new_args.extend(get_export_flags(line, build_args.exports))

if "-c" in line:
Expand Down Expand Up @@ -638,6 +646,7 @@ def compiler_main():
target_install_dir=PYWASMCROSS_ARGS["target_install_dir"],
pythoninclude=PYWASMCROSS_ARGS["pythoninclude"],
exports=PYWASMCROSS_ARGS["exports"],
abi=PYWASMCROSS_ARGS["abi"],
)
basename = Path(sys.argv[0]).name
args = list(sys.argv)
Expand Down
45 changes: 35 additions & 10 deletions pyodide_build/recipe/graph_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
from pyodide_build import build_env
from pyodide_build.build_env import BuildArgs
from pyodide_build.common import (
download_and_unpack_archive,
exit_with_stdio,
extract_wheel_metadata_file,
find_matching_wheels,
Expand Down Expand Up @@ -647,26 +648,50 @@ def run(self, n_jobs: int, already_built: set[str]) -> None:
self.build_queue.put((job_priority(dependent), dependent))


def _run(cmd, *args, check=False, **kwargs):
result = subprocess.run(cmd, *args, **kwargs, check=check)
if result.returncode != 0:
logger.error("ERROR: command failed %s", " ".join(cmd))
exit_with_stdio(result)
return result


def _ensure_rust_toolchain():
rust_toolchain = build_env.get_build_flag("RUST_TOOLCHAIN")
result = subprocess.run(
["rustup", "toolchain", "install", rust_toolchain], check=False
)
if result.returncode == 0:
result = subprocess.run(
_run(["rustup", "toolchain", "install", rust_toolchain])
_run(["rustup", "default", rust_toolchain])

url = build_env.get_build_flag("RUST_EMSCRIPTEN_TARGET_URL")
if not url:
# Install target with rustup target add
_run(
[
"rustup",
"target",
"add",
"wasm32-unknown-emscripten",
"--toolchain",
rust_toolchain,
],
check=False,
]
)
if result.returncode != 0:
logger.error("ERROR: rustup toolchain install failed")
exit_with_stdio(result)
return

# Install target from url
result = _run(
["rustup", "which", "--toolchain", rust_toolchain, "rustc"],
capture_output=True,
text=True,
)
toolchain_root = Path(result.stdout).parents[1]
rustlib = toolchain_root / "lib/rustlib"
install_token = rustlib / "wasm32-unknown-emscripten_install-url.txt"
if install_token.exists() and install_token.read_text() == url:
return
shutil.rmtree(rustlib / "wasm32-unknown-emscripten", ignore_errors=True)
download_and_unpack_archive(
url, rustlib, "wasm32-unknown-emscripten target", exists_ok=True
)
install_token.write_text(url)


def build_from_graph(
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ lint.select = [

lint.logger-objects = ["pyodide_build.logger.logger"]

lint.ignore = ["E402", "E501", "E731", "E741", "PERF401", "PLW2901", "UP038"]
lint.ignore = ["E402", "E501", "E731", "E741", "PERF401", "PLW2901", "UP038", "PLR0912"]
# line-length = 219 # E501: Recommended goal is 88 to match black
target-version = "py312"

Expand Down