Skip to content

Build as a user C module in CircuitPython too - #41

Merged
bdbarnett merged 1 commit into
mainfrom
cp-usermod
Oct 8, 2026
Merged

bdbarnett merged 1 commit into
mainfrom
cp-usermod

Conversation

@bdbarnett

Copy link
Copy Markdown
Contributor

CircuitPython's make-based ports read USER_C_MODULES the way MicroPython 1.29 does, so with these changes micropython.mk builds pygraphics into CircuitPython-compatible firmware without apply_cp_patches.sh. Proven on CircuitPython 11.0.0-alpha.1: the unix coverage build (import, draw, read back, capabilities() says native), and board builds for adafruit_feather_rp2040 and sparkfun_samd51_thing_plus that link with the module in their module table.

What changed:

  • micropython.mk passes -DPYGRAPHICS_USER_C_MODULE=1. CircuitPython's unix port sets CIRCUITPY=1, and without the define the module skipped MP_REGISTER_MODULE and couldn't be imported. The shared-bindings path through apply_cp_patches.sh is unchanged.
  • The -Wno-* flags the drawing code needs are repeated per object. CircuitPython's MCU ports append -Werror=sign-compare and -Werror=float-equal after the user module flags, and a target-specific flag lands last. The object path is the one py/py.mk uses since MicroPython 1.29, $(BUILD)/<module dir name>/src/<file>.o.
  • Polygon coordinates are read with memcpy rather than a pointer cast. A memoryview can start at any byte, and a Cortex-M0+ (RP2040) faults on an unaligned halfword or word load; atmel-samd builds with -Werror=cast-align, which caught it.
  • In a user C module build, the GS8 copy a PNG save makes of a MONO_HLSB framebuffer comes from the GC heap (m_malloc). atmel-samd has no C heap, so malloc() didn't link. CPython and MicroPython's CMake ports keep malloc/free, through the new gfx_png_release().

MicroPython is unaffected: the unix build with this branch passes the same import/draw/read-back check, and the CPython extension builds without warnings and passes its native suite (93 tests, 6 skipped).

CircuitPython's make-based ports read USER_C_MODULES exactly as MicroPython
1.29 does, so micropython.mk now builds pygraphics into CircuitPython-compatible
firmware with no apply script:

- micropython.mk passes -DPYGRAPHICS_USER_C_MODULE=1, so a build with
  CIRCUITPY=1 still registers the module (the shared-bindings path through
  apply_cp_patches.sh is unchanged).
- The warnings the drawing code trips on purpose are repeated per object,
  where they land after the -Werror=sign-compare/float-equal CircuitPython's
  MCU ports append late.
- Polygon coordinates are read with memcpy instead of a cast: a memoryview
  can start at any byte, and a Cortex-M0+ faults on an unaligned load
  (atmel-samd builds with -Werror=cast-align).
- The MONO_HLSB copy a PNG save makes comes from the GC heap in a user C
  module build: atmel-samd has no C heap, so malloc() didn't link.
@bdbarnett
bdbarnett merged commit b98288c into main Oct 8, 2026
2 checks passed
@bdbarnett
bdbarnett deleted the cp-usermod branch October 8, 2026 05:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant