Skip to content

py/frozenmod.c: Use ".frozen/" as a virtual search path for frozen modules. #8079

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 8 commits into from
Closed
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
5 changes: 5 additions & 0 deletions docs/library/sys.rst
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,11 @@ Constants

A mutable list of directories to search for imported modules.

.. admonition:: Difference to CPython
:class: attention

On MicroPython, an entry with the value ``".frozen"`` will indicate that it should search :term:`frozen modules <frozen module>`.

.. data:: platform

The platform that MicroPython is running on. For OS/RTOS ports, this is
Expand Down
3 changes: 3 additions & 0 deletions ports/esp32/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,9 @@ void mp_task(void *pvParameter) {
gc_init(mp_task_heap, mp_task_heap + mp_task_heap_size);
mp_init();
mp_obj_list_init(mp_sys_path, 0);
#if MICROPY_MODULE_FROZEN
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__dot_frozen));
#endif
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_));
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_lib));
mp_obj_list_init(mp_sys_argv, 0);
Expand Down
7 changes: 1 addition & 6 deletions ports/esp8266/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ AXTLS_DEFS_EXTRA = -Dabort=abort_ -DRT_MAX_PLAIN_LENGTH=1024 -DRT_EXTRA=4096
BTREE_DEFS_EXTRA = -DDEFPSIZE=1024 -DMINCACHE=3

FROZEN_MANIFEST ?= boards/manifest.py
FROZEN_DIR ?=
FROZEN_MPY_DIR ?=

# include py core make definitions
include $(TOP)/py/py.mk
Expand Down Expand Up @@ -196,12 +194,9 @@ $(BUILD)/uart.o: $(CONFVARS_FILE)

FROZEN_EXTRA_DEPS = $(CONFVARS_FILE)

ifneq ($(FROZEN_MANIFEST)$(FROZEN_MPY_DIR),)
ifneq ($(FROZEN_MANIFEST),)
CFLAGS += -DMICROPY_MODULE_FROZEN_MPY
CFLAGS += -DMICROPY_QSTR_EXTRA_POOL=mp_qstr_frozen_const_pool
endif

ifneq ($(FROZEN_MANIFEST)$(FROZEN_DIR),)
CFLAGS += -DMICROPY_MODULE_FROZEN_STR
endif

Expand Down
3 changes: 3 additions & 0 deletions ports/esp8266/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ STATIC void mp_reset(void) {
gc_init(heap, heap + sizeof(heap));
mp_init();
mp_obj_list_init(mp_sys_path, 0);
#if MICROPY_MODULE_FROZEN
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__dot_frozen));
#endif
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_)); // current dir (or base dir of the script)
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_lib));
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_));
Expand Down
7 changes: 0 additions & 7 deletions ports/javascript/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,6 @@ CFLAGS += -std=c99 -Wall -Werror -Wdouble-promotion -Wfloat-conversion
CFLAGS += -O3 -DNDEBUG
CFLAGS += $(INC)

ifneq ($(FROZEN_MPY_DIR),)
# To use frozen bytecode, put your .py files in a subdirectory (eg frozen/) and
# then invoke make with FROZEN_MPY_DIR=frozen (be sure to build from scratch).
CFLAGS += -DMICROPY_QSTR_EXTRA_POOL=mp_qstr_frozen_const_pool
CFLAGS += -DMICROPY_MODULE_FROZEN_MPY
endif

SRC_SHARED = $(addprefix shared/,\
runtime/interrupt_char.c \
runtime/stdout_helpers.c \
Expand Down
3 changes: 3 additions & 0 deletions ports/mimxrt/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ int main(void) {
mp_init();

mp_obj_list_init(MP_OBJ_TO_PTR(mp_sys_path), 0);
#if MICROPY_MODULE_FROZEN
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__dot_frozen));
#endif
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_));
mp_obj_list_init(MP_OBJ_TO_PTR(mp_sys_argv), 0);
#if MICROPY_PY_NETWORK
Expand Down
16 changes: 2 additions & 14 deletions ports/nrf/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -340,11 +340,6 @@ DRIVERS_SRC_C += $(addprefix modules/,\
SRC_C += \
device/startup_$(MCU_SUB_VARIANT).c \

ifneq ($(FROZEN_MPY_DIR),)
FROZEN_MPY_PY_FILES := $(shell find -L $(FROZEN_MPY_DIR) -type f -name '*.py')
FROZEN_MPY_MPY_FILES := $(addprefix $(BUILD)/,$(FROZEN_MPY_PY_FILES:.py=.mpy))
endif

LIBGCC_FILE_NAME = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
LIBS += -L $(dir $(LIBGCC_FILE_NAME)) -lgcc

Expand Down Expand Up @@ -542,17 +537,10 @@ GEN_PINS_QSTR = $(BUILD)/pins_qstr.h
GEN_PINS_AF_CONST = $(HEADER_BUILD)/pins_af_const.h
GEN_PINS_AF_PY = $(BUILD)/pins_af.py

ifneq ($(FROZEN_MANIFEST)$(FROZEN_DIR),)
# To use frozen source modules, put your .py files in a subdirectory (eg scripts/)
# and then invoke make with FROZEN_DIR=scripts (be sure to build from scratch).
CFLAGS += -DMICROPY_MODULE_FROZEN_STR
endif

ifneq ($(FROZEN_MANIFEST)$(FROZEN_MPY_DIR),)
# To use frozen bytecode, put your .py files in a subdirectory (eg frozen/) and
# then invoke make with FROZEN_MPY_DIR=frozen (be sure to build from scratch).
ifneq ($(FROZEN_MANIFEST),)
CFLAGS += -DMICROPY_QSTR_EXTRA_POOL=mp_qstr_frozen_const_pool
CFLAGS += -DMICROPY_MODULE_FROZEN_MPY
CFLAGS += -DMICROPY_MODULE_FROZEN_STR
endif

$(PY_BUILD)/nlr%.o: CFLAGS += -Os -fno-lto
Expand Down
30 changes: 0 additions & 30 deletions ports/nrf/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,36 +96,6 @@ The **make sd** will trigger a flash of the bluetooth stack before that applicat

Note: further tuning of features to include in bluetooth or even setting up the device to use REPL over Bluetooth can be configured in the `bluetooth_conf.h`.

## Compile with frozen modules

Frozen modules are Python modules compiled to bytecode and added to the firmware
image, as part of MicroPython. They can be imported as usual, using the `import`
statement. The advantage is that frozen modules use a lot less RAM as the
bytecode is stored in flash, not in RAM like when importing from a filesystem.
Also, frozen modules are available even when no filesystem is present to import
from.

To use frozen modules, put them in a directory (e.g. `freeze/`) and supply
`make` with the given directory. For example:

make BOARD=pca10040 FROZEN_MPY_DIR=freeze

## Compile with freeze manifest

Freeze manifests can be used by definining `FROZEN_MANIFEST` pointing to a
`manifest.py`. This can either be done by a `make` invocation or by defining
it in the specific target board's `mpconfigboard.mk`.

For example:

make BOARD=pca10040 FROZEN_MANIFEST=path/to/manifest.py

In case of using the target board's makefile, add a line similar to this:

FROZEN_MANIFEST ?= $(BOARD_DIR)/manifest.py

In these two examples, the manual `make` invocation will have precedence.

## Enable MICROPY_VFS_FAT
As the `oofatfs` module is not having header guards that can exclude the implementation compile time, this port provides a flag to enable it explicitly. The MICROPY_VFS_FAT is by default set to 0 and has to be set to 1 if `oofatfs` files should be compiled. This will be in addition of setting `MICROPY_VFS` in mpconfigport.h.

Expand Down
3 changes: 3 additions & 0 deletions ports/nrf/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,9 @@ int main(int argc, char **argv) {

mp_init();
mp_obj_list_init(mp_sys_path, 0);
#if MICROPY_MODULE_FROZEN
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__dot_frozen));
#endif
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_)); // current dir (or base dir of the script)
mp_obj_list_init(mp_sys_argv, 0);

Expand Down
3 changes: 3 additions & 0 deletions ports/rp2/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ int main(int argc, char **argv) {
// Initialise MicroPython runtime.
mp_init();
mp_obj_list_init(MP_OBJ_TO_PTR(mp_sys_path), 0);
#if MICROPY_MODULE_FROZEN
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__dot_frozen));
#endif
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_));
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_lib));
mp_obj_list_init(MP_OBJ_TO_PTR(mp_sys_argv), 0);
Expand Down
11 changes: 2 additions & 9 deletions ports/stm32/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -591,17 +591,10 @@ $(TOP)/lib/stm32lib/README.md:
$(ECHO) "stm32lib submodule not found, fetching it now..."
(cd $(TOP) && git submodule update --init lib/stm32lib)

ifneq ($(FROZEN_MANIFEST)$(FROZEN_DIR),)
# To use frozen source modules, put your .py files in a subdirectory (eg scripts/)
# and then invoke make with FROZEN_DIR=scripts (be sure to build from scratch).
CFLAGS += -DMICROPY_MODULE_FROZEN_STR
endif

ifneq ($(FROZEN_MANIFEST)$(FROZEN_MPY_DIR),)
# To use frozen bytecode, put your .py files in a subdirectory (eg frozen/) and
# then invoke make with FROZEN_MPY_DIR=frozen (be sure to build from scratch).
ifneq ($(FROZEN_MANIFEST),)
CFLAGS += -DMICROPY_QSTR_EXTRA_POOL=mp_qstr_frozen_const_pool
CFLAGS += -DMICROPY_MODULE_FROZEN_MPY
CFLAGS += -DMICROPY_MODULE_FROZEN_STR
endif

define RUN_DFU
Expand Down
3 changes: 3 additions & 0 deletions ports/stm32/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,9 @@ void stm32_main(uint32_t reset_mode) {
// MicroPython init
mp_init();
mp_obj_list_init(MP_OBJ_TO_PTR(mp_sys_path), 0);
#if MICROPY_MODULE_FROZEN
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__dot_frozen));
#endif
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_)); // current dir (or base dir of the script)
mp_obj_list_init(MP_OBJ_TO_PTR(mp_sys_argv), 0);

Expand Down
77 changes: 37 additions & 40 deletions ports/teensy/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,42 @@ QSTR_DEFS = qstrdefsport.h $(BUILD)/pins_qstr.h
# MicroPython feature configurations
MICROPY_ROM_TEXT_COMPRESSION ?= 1

USE_FROZEN = 1
USE_MEMZIP = 0

ifeq ($(USE_MEMZIP),1)
SRC_C += \
shared/memzip/import.c \
shared/memzip/lexermemzip.c \
shared/memzip/memzip.c \

OBJ += $(BUILD)/memzip-files.o

MAKE_MEMZIP = $(TOP)/shared/memzip/make-memzip.py
ifeq ($(MEMZIP_DIR),)
MEMZIP_DIR = memzip_files
endif

$(BUILD)/memzip-files.o: $(BUILD)/memzip-files.c
$(call compile_c)

$(BUILD)/memzip-files.c: $(shell find ${MEMZIP_DIR} -type f)
@$(ECHO) "Creating $@"
$(Q)$(PYTHON) $(MAKE_MEMZIP) --zip-file $(BUILD)/memzip-files.zip --c-file $@ $(MEMZIP_DIR)

endif # USE_MEMZIP

ifeq ($(USE_FROZEN),1)

FROZEN_MANIFEST ?= "manifest.py"

CFLAGS += -DMICROPY_MODULE_FROZEN_STR

SRC_C += \
lexerfrozen.c

endif # USE_FROZEN

# include py core make definitions
include $(TOP)/py/py.mk

Expand Down Expand Up @@ -76,10 +112,7 @@ endif
CFLAGS += -fdata-sections -ffunction-sections
LDFLAGS += -Wl,--gc-sections

USE_FROZEN = 1
USE_MEMZIP = 0

SRC_C = \
SRC_C += \
hal_ftm.c \
hal_gpio.c \
help.c \
Expand Down Expand Up @@ -127,42 +160,6 @@ OBJ += $(BUILD)/pins_gen.o
all: hex
hex: $(BUILD)/micropython.hex

ifeq ($(USE_MEMZIP),1)
SRC_C += \
shared/memzip/import.c \
shared/memzip/lexermemzip.c \
shared/memzip/memzip.c \

OBJ += $(BUILD)/memzip-files.o

MAKE_MEMZIP = $(TOP)/shared/memzip/make-memzip.py
ifeq ($(MEMZIP_DIR),)
MEMZIP_DIR = memzip_files
endif

$(BUILD)/memzip-files.o: $(BUILD)/memzip-files.c
$(call compile_c)

$(BUILD)/memzip-files.c: $(shell find ${MEMZIP_DIR} -type f)
@$(ECHO) "Creating $@"
$(Q)$(PYTHON) $(MAKE_MEMZIP) --zip-file $(BUILD)/memzip-files.zip --c-file $@ $(MEMZIP_DIR)

endif # USE_MEMZIP

ifeq ($(USE_FROZEN),1)

ifeq ($(FROZEN_DIR),)
FROZEN_DIR = memzip_files
endif

CFLAGS += -DMICROPY_MODULE_FROZEN_STR

SRC_C += \
lexerfrozen.c \
$(BUILD)/frozen.c

endif # USE_FROZEN

ifeq ($(ARDUINO),)
post_compile: $(BUILD)/micropython.hex
$(ECHO) "Please define ARDUINO (where TeensyDuino is installed)"
Expand Down
1 change: 1 addition & 0 deletions ports/teensy/manifest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
freeze_as_str("$(PORT_DIR)/memzip_files")
9 changes: 2 additions & 7 deletions ports/unix/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,8 @@ include ../../py/mkenv.mk
-include mpconfigport.mk
include $(VARIANT_DIR)/mpconfigvariant.mk

# use FROZEN_MANIFEST for new projects, others are legacy
# Use the default frozen manifest, variants may override this.
FROZEN_MANIFEST ?= variants/manifest.py
FROZEN_DIR =
FROZEN_MPY_DIR =

# This should be configured by the mpconfigvariant.mk
PROG ?= micropython
Expand Down Expand Up @@ -263,15 +261,12 @@ SRC_QSTR += $(SRC_C) $(SRC_CXX) $(SHARED_SRC_C) $(EXTMOD_SRC_C)
# SRC_QSTR
SRC_QSTR_AUTO_DEPS +=

ifneq ($(FROZEN_MANIFEST)$(FROZEN_MPY_DIR),)
ifneq ($(FROZEN_MANIFEST),)
# To use frozen code create a manifest.py file with a description of files to
# freeze, then invoke make with FROZEN_MANIFEST=manifest.py (be sure to build from scratch).
CFLAGS += -DMICROPY_QSTR_EXTRA_POOL=mp_qstr_frozen_const_pool
CFLAGS += -DMICROPY_MODULE_FROZEN_MPY
CFLAGS += -DMPZ_DIG_SIZE=16 # force 16 bits to work on both 32 and 64 bit archs
endif

ifneq ($(FROZEN_MANIFEST)$(FROZEN_DIR),)
CFLAGS += -DMICROPY_MODULE_FROZEN_STR
endif

Expand Down
13 changes: 5 additions & 8 deletions ports/unix/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -495,13 +495,9 @@ MP_NOINLINE int main_(int argc, char **argv) {
char *home = getenv("HOME");
char *path = getenv("MICROPYPATH");
if (path == NULL) {
#ifdef MICROPY_PY_SYS_PATH_DEFAULT
path = MICROPY_PY_SYS_PATH_DEFAULT;
#else
path = "~/.micropython/lib:/usr/lib/micropython";
#endif
}
size_t path_num = 1; // [0] is for current dir (or base dir of the script)
size_t path_num = 2; // [0] is frozen, [1] is for current dir (or base dir of the script)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This ordering of putting the script path second should also fix the upip issue, looks good to me.
It will mean however if you run upip from source rather than frozen in, any libs will be installed next to upip.py script by default

if (*path == PATHLIST_SEP_CHAR) {
path_num++;
}
Expand All @@ -514,10 +510,11 @@ MP_NOINLINE int main_(int argc, char **argv) {
mp_obj_list_init(MP_OBJ_TO_PTR(mp_sys_path), path_num);
mp_obj_t *path_items;
mp_obj_list_get(mp_sys_path, &path_num, &path_items);
path_items[0] = MP_OBJ_NEW_QSTR(MP_QSTR_);
path_items[0] = MP_OBJ_NEW_QSTR(MP_QSTR__dot_frozen);
path_items[1] = MP_OBJ_NEW_QSTR(MP_QSTR_);
{
char *p = path;
for (mp_uint_t i = 1; i < path_num; i++) {
for (mp_uint_t i = 2; i < path_num; i++) {
char *p1 = strchr(p, PATHLIST_SEP_CHAR);
if (p1 == NULL) {
p1 = p + strlen(p);
Expand Down Expand Up @@ -660,7 +657,7 @@ MP_NOINLINE int main_(int argc, char **argv) {

// Set base dir of the script as first entry in sys.path
char *p = strrchr(basedir, '/');
path_items[0] = mp_obj_new_str_via_qstr(basedir, p - basedir);
path_items[1] = mp_obj_new_str_via_qstr(basedir, p - basedir);
free(pathbuf);

set_sys_argv(argv, argc, a);
Expand Down
3 changes: 3 additions & 0 deletions ports/unix/mpconfigport.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,9 @@
#define MICROPY_PY_SYS_PLATFORM "linux"
#endif
#endif
#ifndef MICROPY_PY_SYS_PATH_DEFAULT
#define MICROPY_PY_SYS_PATH_DEFAULT "~/.micropython/lib:/usr/lib/micropython"
#endif
#define MICROPY_PY_SYS_MAXSIZE (1)
#define MICROPY_PY_SYS_STDFILES (1)
#define MICROPY_PY_SYS_EXC_INFO (1)
Expand Down
1 change: 0 additions & 1 deletion ports/unix/variants/coverage/mpconfigvariant.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@
#define MICROPY_PY_MATH_FACTORIAL (1)
#define MICROPY_PY_URANDOM_EXTRA_FUNCS (1)
#define MICROPY_PY_IO_BUFFEREDWRITER (1)
#define MICROPY_PY_IO_RESOURCE_STREAM (1)
#define MICROPY_PY_UASYNCIO (1)
#define MICROPY_PY_URE_DEBUG (1)
#define MICROPY_PY_URE_MATCH_GROUPS (1)
Expand Down
3 changes: 3 additions & 0 deletions ports/unix/variants/minimal/mpconfigvariant.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@
#define MICROPY_PY_SYS (1)
#define MICROPY_PY_SYS_EXIT (0)
#define MICROPY_PY_SYS_PLATFORM "linux"
#ifndef MICROPY_PY_SYS_PATH_DEFAULT
#define MICROPY_PY_SYS_PATH_DEFAULT "~/.micropython/lib:/usr/lib/micropython"
#endif
#define MICROPY_PY_SYS_MAXSIZE (0)
#define MICROPY_PY_SYS_STDFILES (0)
#define MICROPY_PY_CMATH (0)
Expand Down
Loading