Skip to content

py/usermod: Route usermod sources through native port build.#18

Draft
andrewleech wants to merge 1 commit intoreview/usermod-native-source-registrationfrom
usermod-native-source-registration
Draft

py/usermod: Route usermod sources through native port build.#18
andrewleech wants to merge 1 commit intoreview/usermod-native-source-registrationfrom
usermod-native-source-registration

Conversation

@andrewleech
Copy link
Owner

Summary

User C module sources on cmake-based ports are compiled via INTERFACE library linking rather than through the port's native source registration. This means usermod sources miss platform compile flags that are applied at the directory or component level. On ESP32, user C modules are compiled without optimisation flags across all architectures because ESP-IDF applies flags via add_compile_options() during idf_component_register(), which doesn't propagate to INTERFACE library sources. On rp2 it works by accident because CMAKE_BUILD_TYPE=MinSizeRel sets flags via the truly global CMAKE_C_FLAGS.

This adds MICROPY_SOURCE_USERMOD (the flat source list already gathered by usermod_gather_sources()) to each port's native source registration — idf_component_register(SRCS) on esp32 and target_sources() on rp2 — the same way every other source domain (py, extmod, shared, lib, drivers, port, board) already works. INTERFACE_SOURCES are cleared from usermod targets after gathering to prevent double compilation. The existing target_link_libraries(${MICROPY_TARGET} usermod) is kept for propagating non-source INTERFACE properties (compile definitions, compile options, link libraries).

No user-facing API change. Existing micropython.cmake module files work as-is.

This is the root cause of several existing issues:

Testing

Built ESP32_GENERIC (IDF v5.5.1) and RPI_PICO with USER_C_MODULES pointing to examples/usercmodule/micropython.cmake. Verified from build logs:

  • ESP32 usermod sources compile with -O2, matching core sources. Previously they had no optimisation flag.
  • Each usermod source appears exactly once in the build — no double compilation on either port.
  • Build without USER_C_MODULES also succeeds (empty MICROPY_SOURCE_USERMOD is harmless).

Not tested: zephyr port (doesn't currently support user C modules).

Trade-offs and Alternatives

usermod_gather_sources() is now a destructive operation — it clears INTERFACE_SOURCES from each target as a side effect, making it non-idempotent. This is acceptable because it's called exactly once (line 63 of py/usermod.cmake) and the alternative of conditionally skipping the INTERFACE link or adding per-port source deduplication would be more invasive.

An alternative would be to inject platform flags into the usermod INTERFACE library (e.g. idf_build_get_property + target_compile_options(usermod INTERFACE ...)), but that's a workaround rather than fixing the architectural mismatch.

Generative AI

I used generative AI tools when creating this PR, but a human has checked the code and is responsible for the description above.

User C module sources on cmake-based ports were compiled via INTERFACE
library linking rather than through the native port build system.  This
meant usermod sources missed platform compile flags -- on ESP32, user C
modules were compiled without optimisation flags.

Add MICROPY_SOURCE_USERMOD to the native source registration in both
esp32 (idf_component_register SRCS) and rp2 (target_sources).  Clear
INTERFACE_SOURCES from usermod targets after gathering them into the
flat list to prevent double compilation.  The existing
target_link_libraries for the usermod INTERFACE library is kept for
propagating non-source properties (compile definitions, compile options,
link libraries).

Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants