diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index e989acb..759e1a6 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-24.04 env: MPY_DIR: ./micropython - MICROPYTHON_BIN: ./micropython/ports/unix/build-standard/micropython + MICROPYTHON_BIN: ./micropython/ports/unix/build-nomodules/micropython steps: - uses: actions/checkout@v4 with: @@ -29,8 +29,12 @@ jobs: run: pip install -r requirements.txt - name: Setup MicroPython X86 working-directory: micropython - run: source tools/ci.sh && ci_unix_32bit_setup && ci_unix_standard_build - - name: Run test and build module x64 + run: | + source tools/ci.sh && ci_unix_32bit_setup && ci_unix_standard_build + mv ./ports/unix/build-standard/ ./ports/unix/build-nomodules/ + - name: Build custom firmware with user modules, and tests. Unix/x64 + run: make check_unix V=1 + - name: Build .mpy modules and run tests Unix/x64 run: make check ARCH=x64 V=1 - name: Setup MicroPython ARM working-directory: micropython diff --git a/Makefile b/Makefile index ec5dcf7..02bf1e8 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,13 @@ VERSION := $(shell git describe --tags --always) MPY_DIR_ABS = $(abspath $(MPY_DIR)) +C_MODULES_SRC_PATH = $(abspath ./src) +MANIFEST_PATH = $(abspath ./src/manifest.py) + +PORT=unix MODULES_PATH = ./dist/$(ARCH)_$(MPY_ABI_VERSION) +PORT_DIR = ./dist/ports/$(PORT) +UNIX_MICROPYTHON = ./dist/ports/unix/micropython $(MODULES_PATH)/emlearn_trees.mpy: make -C src/emlearn_trees/ ARCH=$(ARCH) MPY_DIR=$(MPY_DIR_ABS) V=1 clean dist @@ -61,7 +67,20 @@ emlearn_iir_q15.results: $(MODULES_PATH)/emlearn_iir_q15.mpy emlearn_arrayutils.results: $(MODULES_PATH)/emlearn_arrayutils.mpy MICROPYPATH=$(MODULES_PATH) $(MICROPYTHON_BIN) tests/test_arrayutils.py -.PHONY: clean +$(PORT_DIR): + mkdir -p $@ + +$(UNIX_MICROPYTHON): $(PORT_DIR) + make -C $(MPY_DIR)/ports/unix V=1 USER_C_MODULES=$(C_MODULES_SRC_PATH) FROZEN_MANIFEST=$(MANIFEST_PATH) CFLAGS_EXTRA='-Wno-unused-function -Wno-unused-function' -j4 + cp $(MPY_DIR)/ports/unix/build-standard/micropython $@ + +unix: $(UNIX_MICROPYTHON) + +check_unix: $(UNIX_MICROPYTHON) + $(UNIX_MICROPYTHON) tests/test_trees.py + $(UNIX_MICROPYTHON) tests/test_iir.py + +.PHONY: clean unix clean: make -C src/emlearn_trees/ ARCH=$(ARCH) MPY_DIR=$(MPY_DIR_ABS) V=1 clean diff --git a/requirements.txt b/requirements.txt index 6ee4e56..3a89384 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -emlearn>=0.21.1 +emlearn>=0.21.2 scikit-learn>=1.0.0 ar>=1.0.0 pyelftools>=0.31 diff --git a/src/emlearn_fft/Makefile b/src/emlearn_fft/Makefile index 857868c..a9836ee 100644 --- a/src/emlearn_fft/Makefile +++ b/src/emlearn_fft/Makefile @@ -33,6 +33,6 @@ $(DIST_FILE): $(MOD).mpy $(DIST_DIR) include $(MPY_DIR)/py/dynruntime.mk -CFLAGS += -I$(EMLEARN_DIR) +CFLAGS += -I$(EMLEARN_DIR) -Wno-unused-function dist: $(DIST_FILE) diff --git a/src/emlearn_iir/Makefile b/src/emlearn_iir/Makefile index d884e95..5160c7d 100644 --- a/src/emlearn_iir/Makefile +++ b/src/emlearn_iir/Makefile @@ -32,6 +32,6 @@ $(DIST_FILE): $(MOD).mpy $(DIST_DIR) # Include to get the rules for compiling and linking the module include $(MPY_DIR)/py/dynruntime.mk -CFLAGS += -I$(EMLEARN_DIR) +CFLAGS += -I$(EMLEARN_DIR) -Wno-unused-function dist: $(DIST_FILE) diff --git a/src/emlearn_iir_q15/Makefile b/src/emlearn_iir_q15/Makefile index 7a8005f..e5f0faf 100644 --- a/src/emlearn_iir_q15/Makefile +++ b/src/emlearn_iir_q15/Makefile @@ -41,6 +41,7 @@ LIBGCC_FILENAME = $(shell $(CROSS)gcc $(CFLAGS) -print-libgcc-file-name) $(info $(LIBGCC_FILENAME)) CFLAGS += -I$(CMSIS_DSP_DIR)/Include +CFLAGS += -Wno-unused-function $(CMSIS_DSP_DIR)/iir_q15.patched: cd $(CMSIS_DSP_DIR) && git apply -v ../df1_q15_disable_dsp.patch diff --git a/src/emlearn_neighbors/Makefile b/src/emlearn_neighbors/Makefile index 53ee216..cadd861 100644 --- a/src/emlearn_neighbors/Makefile +++ b/src/emlearn_neighbors/Makefile @@ -33,6 +33,6 @@ $(DIST_DIR): $(DIST_FILE): $(MOD).mpy $(DIST_DIR) cp $< $@ -CFLAGS += -I$(EMLEARN_DIR) +CFLAGS += -I$(EMLEARN_DIR) -Wno-unused-function dist: $(DIST_FILE) diff --git a/src/emlearn_trees/Makefile b/src/emlearn_trees/Makefile index 01220c9..cb30c04 100644 --- a/src/emlearn_trees/Makefile +++ b/src/emlearn_trees/Makefile @@ -19,7 +19,7 @@ DIST_DIR := ../../dist/$(ARCH)_$(MPY_ABI_VERSION) MOD = emlearn_trees # Source files (.c or .py) -SRC = trees.c trees.py +SRC = trees.c emlearn_trees.py # Releases DIST_FILE = $(DIST_DIR)/$(MOD).mpy @@ -32,6 +32,6 @@ $(DIST_FILE): $(MOD).mpy $(DIST_DIR) # Include to get the rules for compiling and linking the module include $(MPY_DIR)/py/dynruntime.mk -CFLAGS += -I$(EMLEARN_DIR) -DDYNAMIC_RUNTIME=1 +CFLAGS += -I$(EMLEARN_DIR) -Wno-unused-function dist: $(DIST_FILE) diff --git a/src/emlearn_trees/trees.py b/src/emlearn_trees/emlearn_trees.py similarity index 76% rename from src/emlearn_trees/trees.py rename to src/emlearn_trees/emlearn_trees.py index a46b2b3..f652ec4 100644 --- a/src/emlearn_trees/trees.py +++ b/src/emlearn_trees/emlearn_trees.py @@ -1,4 +1,11 @@ +# When used as external C module, the .py is the top-level import, +# and we need to merge the native module symbols at import time +# When used as dynamic native modules (.mpy), .py and native code is merged at build time +try: + from emlearn_trees_c import * +except ImportError as e: + pass def load_model(builder, f): diff --git a/src/emlearn_trees/trees.c b/src/emlearn_trees/trees.c index 8cb3f45..bff1866 100644 --- a/src/emlearn_trees/trees.c +++ b/src/emlearn_trees/trees.c @@ -332,7 +332,8 @@ const mp_obj_module_t emlearn_trees_cmodule = { .globals = (mp_obj_dict_t *)&emlearn_trees_globals, }; -MP_REGISTER_MODULE(MP_QSTR_emlearn_trees, emlearn_trees_cmodule); +// External module name is XXX_c to allow .py file to be the entrypoint +MP_REGISTER_MODULE(MP_QSTR_emlearn_trees_c, emlearn_trees_cmodule); #endif diff --git a/src/manifest.py b/src/manifest.py new file mode 100644 index 0000000..c9d207e --- /dev/null +++ b/src/manifest.py @@ -0,0 +1,5 @@ + +# Manifest is used to include .py files for external C module build +# NOTE: this is a different mechanism than +# Ref https://docs.micropython.org/en/latest/reference/manifest.html +module("emlearn_trees.py", base_path='./emlearn_trees')