Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
9 changes: 9 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,12 @@ jobs:
- name: Build and test
run: python3 Apple ci iOS --fast-ci --simulator 'iPhone SE (3rd generation),OS=17.5'

build-emscripten:
name: 'Emscripten'
needs: build-context
if: needs.build-context.outputs.run-emscripten == 'true'
uses: ./.github/workflows/reusable-emscripten.yml

build-wasi:
name: 'WASI'
needs: build-context
Expand Down Expand Up @@ -650,6 +656,7 @@ jobs:
- build-ubuntu
- build-ubuntu-ssltests
- build-ios
- build-emscripten
- build-wasi
- test-hypothesis
- build-asan
Expand All @@ -664,6 +671,7 @@ jobs:
with:
allowed-failures: >-
build-android,
build-emscripten,
build-windows-msi,
build-ubuntu-ssltests,
test-hypothesis,
Expand Down Expand Up @@ -706,5 +714,6 @@ jobs:
}}
${{ !fromJSON(needs.build-context.outputs.run-android) && 'build-android,' || '' }}
${{ !fromJSON(needs.build-context.outputs.run-ios) && 'build-ios,' || '' }}
${{ !fromJSON(needs.build-context.outputs.run-emscripten) && 'build-emscripten,' || '' }}
${{ !fromJSON(needs.build-context.outputs.run-wasi) && 'build-wasi,' || '' }}
jobs: ${{ toJSON(needs) }}
4 changes: 4 additions & 0 deletions .github/workflows/reusable-context.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ on: # yamllint disable-line rule:truthy
run-ubuntu:
description: Whether to run the Ubuntu tests
value: ${{ jobs.compute-changes.outputs.run-ubuntu }} # bool
run-emscripten:
description: Whether to run the Emscripten tests
value: ${{ jobs.compute-changes.outputs.run-emscripten }} # bool
run-wasi:
description: Whether to run the WASI tests
value: ${{ jobs.compute-changes.outputs.run-wasi }} # bool
Expand All @@ -65,6 +68,7 @@ jobs:
run-macos: ${{ steps.changes.outputs.run-macos }}
run-tests: ${{ steps.changes.outputs.run-tests }}
run-ubuntu: ${{ steps.changes.outputs.run-ubuntu }}
run-emscripten: ${{ steps.changes.outputs.run-emscripten }}
run-wasi: ${{ steps.changes.outputs.run-wasi }}
run-windows-msi: ${{ steps.changes.outputs.run-windows-msi }}
run-windows-tests: ${{ steps.changes.outputs.run-windows-tests }}
Expand Down
72 changes: 72 additions & 0 deletions .github/workflows/reusable-emscripten.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
name: Reusable Emscripten

on:
workflow_call:

env:
FORCE_COLOR: 1

jobs:
build-emscripten-reusable:
name: 'build and test'
runs-on: ubuntu-24.04
timeout-minutes: 60
steps:
- uses: actions/checkout@v6
with:
persist-credentials: false
- name: "Read Emscripten config"
id: emscripten-config
shell: python
run: |
import hashlib
import json
import os
import tomllib
from pathlib import Path

config = tomllib.loads(Path("Platforms/emscripten/config.toml").read_text())
h = hashlib.sha256()
h.update(json.dumps(config["dependencies"], sort_keys=True).encode())
h.update(Path("Platforms/emscripten/make_libffi.sh").read_bytes())
h.update(b'1') # Update to explicitly bust cache
emsdk_cache = Path(os.environ["RUNNER_TEMP"]) / "emsdk-cache"
with open(os.environ["GITHUB_OUTPUT"], "a") as f:
f.write(f"emscripten-version={config['emscripten-version']}\n")
f.write(f"node-version={config['node-version']}\n")
f.write(f"deps-hash={h.hexdigest()}\n")
with open(os.environ["GITHUB_ENV"], "a") as f:
f.write(f"EMSDK_CACHE={emsdk_cache}\n")
- name: "Install Node.js"
uses: actions/setup-node@v6
with:
node-version: ${{ steps.emscripten-config.outputs.node-version }}
- name: "Cache Emscripten SDK"
id: emsdk-cache
uses: actions/cache@v5
with:
path: ${{ env.EMSDK_CACHE }}
key: emsdk-${{ steps.emscripten-config.outputs.emscripten-version }}-${{ steps.emscripten-config.outputs.deps-hash }}
restore-keys: emsdk-${{ steps.emscripten-config.outputs.emscripten-version }}
- name: "Install Python"
uses: actions/setup-python@v6
with:
python-version: '3.x'
- name: "Runner image version"
run: echo "IMAGE_OS_VERSION=${ImageOS}-${ImageVersion}" >> "$GITHUB_ENV"
- name: "Install Emscripten"
run: python3 Platforms/emscripten install-emscripten
- name: "Configure build Python"
run: python3 Platforms/emscripten configure-build-python -- --config-cache --with-pydebug
- name: "Make build Python"
run: python3 Platforms/emscripten make-build-python
- name: "Make dependencies"
run: >-
python3 Platforms/emscripten make-dependencies
${{ steps.emsdk-cache.outputs.cache-hit == 'true' && '--check-up-to-date' || '' }}
- name: "Configure host Python"
run: python3 Platforms/emscripten configure-host --host-runner node -- --config-cache
- name: "Make host Python"
run: python3 Platforms/emscripten make-host
- name: "Test"
run: python3 Platforms/emscripten run --test
27 changes: 23 additions & 4 deletions Platforms/emscripten/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -350,11 +350,18 @@ def write_library_config(prefix, name, config, quiet):
def make_emscripten_libffi(context, working_dir):
validate_emsdk_version(context.emsdk_cache)
prefix = context.build_paths["prefix_dir"]
libffi_config = load_config_toml()["libffi"]
libffi_config = load_config_toml()["dependencies"]["libffi"]
with open(EMSCRIPTEN_DIR / "make_libffi.sh", "rb") as f:
libffi_config["make_libffi_shasum"] = hashlib.file_digest(f, "sha256").hexdigest()
if not should_build_library(
prefix, "libffi", libffi_config, context.quiet
):
return

if context.check_up_to_date:
print("libffi out of date, expected to be up to date", file=sys.stderr)
sys.exit(1)

url = libffi_config["url"]
version = libffi_config["version"]
shasum = libffi_config["shasum"]
Expand All @@ -378,10 +385,14 @@ def make_emscripten_libffi(context, working_dir):
def make_mpdec(context, working_dir):
validate_emsdk_version(context.emsdk_cache)
prefix = context.build_paths["prefix_dir"]
mpdec_config = load_config_toml()["mpdec"]
mpdec_config = load_config_toml()["dependencies"]["mpdec"]
if not should_build_library(prefix, "mpdec", mpdec_config, context.quiet):
return

if context.check_up_to_date:
print("libmpdec out of date, expected to be up to date", file=sys.stderr)
sys.exit(1)

url = mpdec_config["url"]
version = mpdec_config["version"]
shasum = mpdec_config["shasum"]
Expand Down Expand Up @@ -678,6 +689,14 @@ def main():
help="Build all static library dependencies",
)

for cmd in [make_mpdec_cmd, make_libffi_cmd, make_dependencies_cmd]:
cmd.add_argument(
"--check-up-to-date",
action="store_true",
default=False,
help=("If passed, will fail if dependency is out of date"),
)

make_build = subcommands.add_parser(
"make-build-python", help="Run `make` for the build Python"
)
Expand Down Expand Up @@ -705,15 +724,15 @@ def main():
help=(
"If passed, will add the default test arguments to the beginning of the command. "
"Default arguments loaded from Platforms/emscripten/config.toml"
)
),
)
run.add_argument(
"args",
nargs=argparse.REMAINDER,
help=(
"Arguments to pass to the emscripten Python "
"(use '--' to separate from run options)",
)
),
)
add_cross_build_dir_option(run)

Expand Down
4 changes: 2 additions & 2 deletions Platforms/emscripten/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ test-args = [
"-W",
]

[libffi]
[dependencies.libffi]
url = "https://github.com/libffi/libffi/releases/download/v{version}/libffi-{version}.tar.gz"
version = "3.4.6"
shasum = "b0dea9df23c863a7a50e825440f3ebffabd65df1497108e5d437747843895a4e"

[mpdec]
[dependencies.mpdec]
url = "https://www.bytereef.org/software/mpdecimal/releases/mpdecimal-{version}.tar.gz"
version = "4.0.1"
shasum = "96d33abb4bb0070c7be0fed4246cd38416188325f820468214471938545b1ac8"
13 changes: 13 additions & 0 deletions Tools/build/compute-changes.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
SUFFIXES_DOCUMENTATION = frozenset({".rst", ".md"})

ANDROID_DIRS = frozenset({"Android"})
EMSCRIPTEN_DIRS = frozenset({Path("Platforms", "emscripten")})
IOS_DIRS = frozenset({"Apple", "iOS"})
MACOS_DIRS = frozenset({"Mac"})
WASI_DIRS = frozenset({Path("Platforms", "WASI")})
Expand Down Expand Up @@ -107,6 +108,7 @@ class Outputs:
run_ci_fuzz: bool = False
run_ci_fuzz_stdlib: bool = False
run_docs: bool = False
run_emscripten: bool = False
run_ios: bool = False
run_macos: bool = False
run_tests: bool = False
Expand All @@ -126,6 +128,7 @@ def compute_changes() -> None:
# Otherwise, just run the tests
outputs = Outputs(
run_android=True,
run_emscripten=True,
run_ios=True,
run_macos=True,
run_tests=True,
Expand Down Expand Up @@ -196,6 +199,8 @@ def get_file_platform(file: Path) -> str | None:
return "ios"
if first_part in ANDROID_DIRS:
return "android"
if len(file.parts) >= 2 and Path(*file.parts[:2]) in EMSCRIPTEN_DIRS:
return "emscripten"
if len(file.parts) >= 2 and Path(*file.parts[:2]) in WASI_DIRS:
return "wasi"
return None
Expand Down Expand Up @@ -244,6 +249,10 @@ def process_changed_files(changed_files: Set[Path]) -> Outputs:
run_tests = True
platforms_changed.add("macos")
continue
if file.name == "reusable-emscripten.yml":
run_tests = True
platforms_changed.add("emscripten")
continue
if file.name == "reusable-wasi.yml":
run_tests = True
platforms_changed.add("wasi")
Expand Down Expand Up @@ -284,18 +293,21 @@ def process_changed_files(changed_files: Set[Path]) -> Outputs:
if run_tests:
if not has_platform_specific_change or not platforms_changed:
run_android = True
run_emscripten = True
run_ios = True
run_macos = True
run_ubuntu = True
run_wasi = True
else:
run_android = "android" in platforms_changed
run_emscripten = "emscripten" in platforms_changed
run_ios = "ios" in platforms_changed
run_macos = "macos" in platforms_changed
run_ubuntu = False
run_wasi = "wasi" in platforms_changed
else:
run_android = False
run_emscripten = False
run_ios = False
run_macos = False
run_ubuntu = False
Expand All @@ -306,6 +318,7 @@ def process_changed_files(changed_files: Set[Path]) -> Outputs:
run_ci_fuzz=run_ci_fuzz,
run_ci_fuzz_stdlib=run_ci_fuzz_stdlib,
run_docs=run_docs,
run_emscripten=run_emscripten,
run_ios=run_ios,
run_macos=run_macos,
run_tests=run_tests,
Expand Down
Loading