Skip to content
Merged
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
40 changes: 29 additions & 11 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ jobs:
- name: macos-aarch64
os: macos-15
target_cpu: arm64
- name: linux-aarch64-musl-compat
os: ubuntu-24.04
target_cpu: arm64

steps:
- uses: extractions/setup-just@v3
Expand All @@ -86,6 +89,11 @@ jobs:

- name: Build dll with v8
run: just build-dll "--out-path=_dll" "--target-cpu=${{ matrix.config.target_cpu }}"
if: matrix.config.name != 'linux-aarch64-musl-compat'

- name: Build dll with v8
run: just build-dll "--out-path=_dll" "--target-cpu=${{ matrix.config.target_cpu }}" --aarch64-musl-compat
if: matrix.config.name == 'linux-aarch64-musl-compat'

- uses: actions/upload-artifact@v4
with:
Expand Down Expand Up @@ -134,10 +142,28 @@ jobs:
path: src/py_mini_racer

- run: just build-wheel
if: matrix.config.os != 'windows-11-arm'

# By default, uv still uses the x86_64 python in emulation on Windows.
# https://github.com/astral-sh/uv/issues/12906
# Override this behavior to build an actual aarch64 wheel:
- run: UV_PYTHON=arm64 just build-wheel
if: matrix.config.os == 'windows-11-arm'

- name: Test wheel
if: matrix.config.os != 'windows-11-arm'
run: just test-matrix

# As above; uv on Windows aarch64 likes to do emulation by default
# (and uv has no 3.10 Python build):
- name: Test wheel
if: matrix.config.os == 'windows-11-arm'
run: |
uv run --python cpython-3.11-windows-aarch64-none pytest tests
uv run --python cpython-3.12-windows-aarch64-none pytest tests
uv run --python cpython-3.13-windows-aarch64-none pytest tests
uv run --python cpython-3.14-windows-aarch64-none pytest tests

- uses: actions/upload-artifact@v4
with:
name: wheels-${{ matrix.config.name }}
Expand All @@ -157,7 +183,7 @@ jobs:
dll: linux-x64_64
- name: alpine-aarch64
image: ubuntu-22.04-arm
dll: linux-aarch64
dll: linux-aarch64-musl-compat

container:
image: alpine
Expand All @@ -182,11 +208,7 @@ jobs:
shell: /bin/sh {0}
run: |
apk update
apk add bash curl gcompat libgcc

curl -LsSf https://astral.sh/uv/install.sh | UV_INSTALL_DIR=/usr/local/bin sh

curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash -s -- --to /usr/local/bin
apk add bash curl gcompat libgcc uv just

- uses: actions/checkout@v3
with:
Expand All @@ -213,15 +235,11 @@ jobs:
# confuses uv into thinking we're on a glibc Linux and thus it rejects our
# musl wheel.
uv sync --python 3.10
LD_PRELOAD="/lib/libgcompat.so.0" uv run --frozen --python 3.10 pytest tests
uv sync --python 3.11
LD_PRELOAD="/lib/libgcompat.so.0" uv run --frozen --python 3.11 pytest tests
uv sync --python 3.12
LD_PRELOAD="/lib/libgcompat.so.0" uv run --frozen --python 3.12 pytest tests
uv sync --python 3.13
LD_PRELOAD="/lib/libgcompat.so.0" uv run --frozen --python 3.13 pytest tests
uv sync --python 3.14
LD_PRELOAD="/lib/libgcompat.so.0" uv run --frozen --python 3.14 pytest tests
LD_PRELOAD="/lib/libgcompat.so.0" just test-matrix --frozen

release:
name: Create GitHub release
Expand Down
4 changes: 2 additions & 2 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -261,8 +261,8 @@ Alpine without extensive patching (or just dispensing with the V8 build system
entirely!).

So instead we build a on Ubuntu with glibc and then put that into a wheel on Alpine. To
use the resulting wheel, you must `apk add gcompat` and add the environment variable
`LD_PRELOAD="/lib/libgcompat.so.0"`.
use the resulting wheel, you must `apk add gcompat libgcc` and add the environment
variable `LD_PRELOAD="/lib/libgcompat.so.0"`.

### Build V8 _with_ our frontend (`v8_py_frontend`) as a snuck-in component

Expand Down
12 changes: 6 additions & 6 deletions Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,12 @@ build: build-dll build-wheel
test:
uv run pytest tests

test-matrix:
uv run --python 3.10 pytest tests
uv run --python 3.11 pytest tests
uv run --python 3.12 pytest tests
uv run --python 3.13 pytest tests
uv run --python 3.14 pytest tests
test-matrix *args:
uv run --python 3.10 {{args}} pytest tests
uv run --python 3.11 {{args}} pytest tests
uv run --python 3.12 {{args}} pytest tests
uv run --python 3.13 {{args}} pytest tests
uv run --python 3.14 {{args}} pytest tests

git-config-global:
git config --global core.symlinks true
Expand Down
37 changes: 20 additions & 17 deletions builder/v8_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,16 +108,14 @@ def run(*args: str, cwd: Path) -> None:
env = environ.copy()

env["PATH"] = pathsep.join([str(get_depot_tools_path()), environ["PATH"]])

# The v8 build tries to download its own toolchain for Windows... just use the local
# one:
env["DEPOT_TOOLS_WIN_TOOLCHAIN"] = "0"

# vpython is V8's Python environment manager; it downloads Python binaries
# dynamically. This doesn't work on Alpine (because it downloads a glibc binary,
# but needs a musl binary), so let's just disable it on all environments:
# dynamically. Let's just use uv's:
env["VPYTHON_BYPASS"] = "manually managed python not supported by chrome operations"
# Goma is a remote build system which we aren't using. depot_tools/autoninja.py
# tries to run the goma client, which is checked into depot_tools as a glibc binary.
# This fails on musl (on Alpine), so let's just disable the thing:
env["GOMA_DISABLED"] = "1"

check_call(args, env=env, cwd=cwd)

Expand All @@ -137,7 +135,7 @@ def ensure_depot_tools() -> None:
)

# depot_tools will auto-update when we run various commands. This creates extra
# dependencies, e.g., on goma (which has trouble running on Alpine due to musl).
# dependencies.
# We just created a fresh single-use depot_tools checkout. There is no reason to
# update it, so let's just disable that functionality:
(get_depot_tools_path() / ".disable_auto_update").write_text("")
Expand Down Expand Up @@ -244,6 +242,13 @@ def run_build(build_dir: Path, args: Args) -> None:
"v8_custom_deps": '"//custom_deps/mini_racer"',
}

if args.aarch64_musl_compat:
# Avoid "Error relocating /PyMiniRacer/src/py_mini_racer/libmini_racer.so:
# unsupported relocation type 1032"
# when running ubuntu-built aarch64 shared objects on Alpine:
# https://gitlab.alpinelinux.org/alpine/aports/-/issues/16210
opts["v8_enable_partition_alloc"] = "false"

if is_linux() and target_cpu != get_local_v8_target_cpu():
run(
executable,
Expand All @@ -252,16 +257,7 @@ def run_build(build_dir: Path, args: Args) -> None:
cwd=get_v8_path(),
)

args_text = "\n".join(f"{n}={v}" for n, v in opts.items())
args_gn = f"""\
# This file is auto-generated by v8_build.py
{args_text}
"""

LOGGER.info(f"Writing args.gn:\n{args_gn}") # noqa: G004

build_dir.mkdir(parents=True, exist_ok=True)
Path(build_dir / "args.gn").write_text(args_gn, encoding="utf-8")
args_text = " ".join(f"{n}={v}" for n, v in opts.items())

# Now generate Ninja build files:
run(
Expand All @@ -270,6 +266,7 @@ def run_build(build_dir: Path, args: Args) -> None:
"gen",
str(build_dir),
"--check",
f"--args={args_text}",
cwd=get_v8_path(),
)

Expand All @@ -292,6 +289,7 @@ class Args:
v8_revision: str
fetch_only: bool
skip_fetch: bool
aarch64_musl_compat: bool


def build_v8(args: Args) -> None:
Expand Down Expand Up @@ -342,5 +340,10 @@ def clean_v8(out_path: Path) -> None:
parser.add_argument("--v8-revision", default=V8_VERSION)
parser.add_argument("--fetch-only", action="store_true", help="Only fetch V8")
parser.add_argument("--skip-fetch", action="store_true", help="Do not fetch V8")
parser.add_argument(
"--aarch64-musl-compat",
action="store_true",
help="Make a compat build for aarch64 musl",
)
args = parser.parse_args()
build_v8(Args(**vars(args)))
2 changes: 1 addition & 1 deletion src/py_mini_racer/__about__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

__author__ = "bpcreech"
__email__ = "mini-racer@bpcreech.com"
__version__ = "0.12.4"
__version__ = "0.13.0"
7 changes: 4 additions & 3 deletions src/py_mini_racer/_dll.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,10 +228,11 @@ def _open_dll(flags: Iterable[str]) -> Iterator[ctypes.CDLL]:
# Find the dll and its external dependency files:
meipass = getattr(sys, "_MEIPASS", None)
if meipass is not None:
# We are running under PyInstaller
# We are running under PyInstaller.
# See https://github.com/bpcreech/PyMiniRacer/issues/78
meipass_path = Path(meipass)
dll_path = meipass_path / dll_filename
icu_data_path = meipass_path / _ICU_DATA_FILENAME
dll_path = meipass_path / "py_mini_racer" / dll_filename
icu_data_path = meipass_path / "py_mini_racer" / _ICU_DATA_FILENAME
else:
dll_path = _open_resource_file(dll_filename, exit_stack)
icu_data_path = _open_resource_file(_ICU_DATA_FILENAME, exit_stack)
Expand Down
Loading