Skip to content

pygame_ce wasm32 wheel (cp312) is missing nearly all compiled extension modules #2

Description

@ZhienWang

Claude asked me if I wanted to file this bug. The texts below are purely from Claude.

pygame_ce wasm32 wheel (cp312, likely cp313/cp314 too) is missing nearly all compiled extension modules

Summary

The pygame_ce-2.5.7-cp312-cp312-wasm32_bi_emscripten.whl currently hosted at
https://pygame-web.github.io/cdn/cp312/pygame_ce-2.5.7-cp312-cp312-wasm32_bi_emscripten.whl
(published in commit b38a6a8, "pygame rls / zengl / pyglm / r-p-c") only contains
the pygame.base compiled extension. Every other pygame submodule that normally
ships as a compiled .so is missing, so import pygame succeeds but immediately
fails as soon as anything triggers from pygame.constants import * in
pygame/__init__.py:

ModuleNotFoundError: No module named 'pygame.constants'
  File "pygame/__init__.py", line 140, in <module>
    from pygame.constants import *

This means any pygbag app that calls pygame.display.set_mode(...) (i.e.
virtually all of them) crashes on startup in the browser. The page never shows
an error to the end user — the traceback only appears in the xterm terminal
panel embedded in the generated page, not in the browser devtools console, so
this is easy to miss and looks like the app is just stuck on a blank/gray screen.

Repro

  1. Any minimal pygbag project with:
    import asyncio, pygame
    
    async def main():
        pygame.init()
        screen = pygame.display.set_mode((640, 480))
        while True:
            await asyncio.sleep(0)
    
    asyncio.run(main())
  2. pygbag main.py, serve build/web, open in a browser, click to satisfy the
    media-engagement gate.
  3. Page background stays gray. The traceback above is visible if you read the
    xterm terminal buffer (window.VM.vt.xterm.buffer.active) — it's not
    surfaced anywhere else on the page.

Investigation

Downloaded and inspected the wheel directly:

$ unzip -l pygame_ce-2.5.7-cp312-cp312-wasm32_bi_emscripten.whl
pygame_ce-2.5.7.dist-info/METADATA
pygame_ce-2.5.7.dist-info/WHEEL
pygame_ce-2.5.7.dist-info/entry_points.txt
pygame/base.cpython-312-wasm32-emscripten.so
pygame/__init__.py
pygame/_camera_opencv.py
... (pure-python files only)
pygame/pygame_icon.bmp
pygame_ce-2.5.7.dist-info/RECORD

33 files total, exactly one compiled extension (base). A normal pygame-ce
wheel has ~30 compiled extensions (constants, display, surface, draw,
image, event, mixer, font, key, mouse, rect, color, mask,
time, transform, _freetype, etc.) — all of those are absent here.

This isn't a regression from that specific commit either — I checked the
wheel it replaced (pygame_ce-2.5.7.dev1-cp312-cp312-wasm32_bi_emscripten.whl,
from the prior commit 5f40e453) and it has the identical problem: same 33
files, same single base extension. So the wasm build for pygame-ce appears
to have been producing incomplete wheels for at least the last couple of
releases.

The same commit also published cp313 and cp314 pygame_ce wheels — I
haven't inspected those directly, but given they come from the same build
step it seems likely they have the same issue.

Where in the pipeline this likely breaks

I looked at pmp-p/pygame-ce-wasm's .github/workflows/build-emsdk.yml
("Build WASM (Emscripten)") to see if the build recipe pointed at an obvious
cause:

  • It builds with Ubuntu 22.04, Emscripten SDK 3.1.32.0 (pinned), and a
    custom "Python WASM SDK" pulled from the pygame-web org (not vanilla emsdk).
  • Its actual output is dist/libpygame.a — a single static library archive
    covering all of pygame's C sources — produced via
    ${SDKROOT}/python3-wasm setup.py build -j$(nproc) followed by
    emar rcs dist/libpygame.a $(find build/temp.wasm32-*/ | grep o$).
  • That workflow does not produce a .whl at all, and it has zero
    recorded runs in that repo, so I couldn't find a working reference build
    to diff against.

So the wheel that ends up on the CDN (pygame-web/cdn) must go through a
separate packaging/splitting step somewhere else that turns libpygame.a
(or an equivalent per-module build) into the individual
pygame/<name>.cpython-312-wasm32-emscripten.so files and assembles the
.whl. Given the wheel only ever contains base, my best guess is that
packaging step is either only invoking/collecting the base extension's
build output, or silently failing/skipping for the other ~30 extension
modules without erroring the build. I wasn't able to locate that packaging
script to confirm further — pointing this out in case it narrows down where
to look.

Expected

The wasm32 pygame_ce wheel should contain all of pygame's compiled
extension modules, matching what's shipped in the regular PyPI wheels
(manylinux/win/macos) for the same version.

Environment

  • pygbag 0.9.3 (PyPI, latest)
  • CDN: https://pygame-web.github.io/cdn/0.9.3/
  • Wheel: cp312/pygame_ce-2.5.7-cp312-cp312-wasm32_bi_emscripten.whl
  • Browser: Chrome (headless, --use-gl=swiftshader), also reproduced by an
    end user in a normal (non-headless) browser session

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions