|
| 1 | +MicroPython manifest files |
| 2 | +========================== |
| 3 | + |
| 4 | +When building firmware for a device the following components are included in |
| 5 | +the compilation process: |
| 6 | + |
| 7 | +- the core MicroPython virtual machine and runtime |
| 8 | +- port-specific system code and drivers to interface with the |
| 9 | + microcontroller/device that the firmware is targeting |
| 10 | +- standard built-in modules, like ``sys`` |
| 11 | +- extended built-in modules, like ``json`` and ``machine`` |
| 12 | +- extra modules written in C/C++ |
| 13 | +- extra modules written in Python |
| 14 | + |
| 15 | +All the modules included in the firmware are available via ``import`` from |
| 16 | +Python code. The extra modules written in Python that are included in a build |
| 17 | +(the last point above) are called *frozen modules*, and are specified by a |
| 18 | +``manifest.py`` file. Changing this manifest requires rebuilding the firmware. |
| 19 | + |
| 20 | +It's also possible to add additional modules to the filesystem of the device |
| 21 | +once it is up and running. Adding and removing modules to/from the filesystem |
| 22 | +does not require rebuilding the firmware so is a simpler process than rebuilding |
| 23 | +firmware. The benefit of using a manifest is that frozen modules are more |
| 24 | +efficient: they are faster to import and take up less RAM once imported. |
| 25 | + |
| 26 | +MicroPython manifest files are Python files and can contain arbitrary Python |
| 27 | +code. There are also a set of commands (predefined functions) which are used |
| 28 | +to specify the Python source files to include. These commands are described |
| 29 | +below. |
| 30 | + |
| 31 | +Freezing source code |
| 32 | +-------------------- |
| 33 | + |
| 34 | +.. function:: freeze(path, script=None, opt=0) |
| 35 | + |
| 36 | + Freeze the input specified by *path*, automatically determining its type. A |
| 37 | + ``.py`` script will be compiled to a ``.mpy`` first then frozen, and a |
| 38 | + ``.mpy`` file will be frozen directly. |
| 39 | + |
| 40 | + *path* must be a directory, which is the base directory to begin searching |
| 41 | + for files. When importing the resulting frozen modules, the name of the |
| 42 | + module will start after *path*, i.e. *path* is excluded from the module |
| 43 | + name. |
| 44 | + |
| 45 | + If *path* is relative, it is resolved to the current ``manifest.py``. Use |
| 46 | + ``$(MPY_DIR)``, ``$(MPY_LIB_DIR)``, ``$(PORT_DIR)``, ``$(BOARD_DIR)`` if you |
| 47 | + need to access specific paths. |
| 48 | + |
| 49 | + If *script* is None, all files in *path* will be frozen. |
| 50 | + |
| 51 | + If *script* is an iterable then ``freeze()`` is called on all items of the |
| 52 | + iterable (with the same *path* and *opt* passed through). |
| 53 | + |
| 54 | + If *script* is a string then it specifies the file or directory to freeze, |
| 55 | + and can include extra directories before the file or last directory. The |
| 56 | + file or directory will be searched for in *path*. If *script* is a |
| 57 | + directory then all files in that directory will be frozen. |
| 58 | + |
| 59 | + *opt* is the optimisation level to pass to mpy-cross when compiling ``.py`` |
| 60 | + to ``.mpy``. |
| 61 | + |
| 62 | +.. function:: freeze_as_str(path) |
| 63 | + |
| 64 | + Freeze the given *path* and all ``.py`` scripts within it as a string, which |
| 65 | + will be compiled upon import. |
| 66 | + |
| 67 | +.. function:: freeze_as_mpy(path, script=None, opt=0) |
| 68 | + |
| 69 | + Freeze the input by first compiling the ``.py`` scripts to ``.mpy`` files, |
| 70 | + then freezing the resulting ``.mpy`` files. See ``freeze()`` for further |
| 71 | + details on the arguments. |
| 72 | + |
| 73 | +.. function:: freeze_mpy(path, script=None, opt=0) |
| 74 | + |
| 75 | + Freeze the input, which must be ``.mpy`` files that are frozen directly. |
| 76 | + See ``freeze()`` for further details on the arguments. |
| 77 | + |
| 78 | + |
| 79 | +Including other manifest files |
| 80 | +------------------------------ |
| 81 | + |
| 82 | +.. function:: include(manifest, **kwargs) |
| 83 | + |
| 84 | + Include another manifest. |
| 85 | + |
| 86 | + The *manifest* argument can be a string (filename) or an iterable of |
| 87 | + strings. |
| 88 | + |
| 89 | + Relative paths are resolved with respect to the current manifest file. |
| 90 | + |
| 91 | + Optional *kwargs* can be provided which will be available to the included |
| 92 | + script via the *options* variable. |
| 93 | + |
| 94 | + For example: |
| 95 | + |
| 96 | + .. code-block:: python3 |
| 97 | +
|
| 98 | + include("path.py", extra_features=True) |
| 99 | +
|
| 100 | + then in path.py: |
| 101 | + |
| 102 | + .. code-block:: python3 |
| 103 | +
|
| 104 | + options.defaults(standard_features=True) |
| 105 | + # freeze minimal modules. |
| 106 | + if options.standard_features: |
| 107 | + # freeze standard modules. |
| 108 | + if options.extra_features: |
| 109 | + # freeze extra modules. |
| 110 | +
|
| 111 | +
|
| 112 | +Examples |
| 113 | +-------- |
| 114 | + |
| 115 | +To freeze a single file which is available as ``import mydriver``, use: |
| 116 | + |
| 117 | +.. code-block:: python3 |
| 118 | +
|
| 119 | + freeze(".", "mydriver.py") |
| 120 | +
|
| 121 | +To freeze a set of files which are available as ``import test1`` and |
| 122 | +``import test2``, and which are compiled with optimisation level 3, use: |
| 123 | + |
| 124 | +.. code-block:: python3 |
| 125 | +
|
| 126 | + freeze("/path/to/tests", ("test1.py", "test2.py"), opt=3) |
| 127 | +
|
| 128 | +To freeze a module which can be imported as ``import mymodule``, use: |
| 129 | + |
| 130 | +.. code-block:: python3 |
| 131 | +
|
| 132 | + freeze( |
| 133 | + "../relative/path", |
| 134 | + ( |
| 135 | + "mymodule/__init__.py", |
| 136 | + "mymodule/core.py", |
| 137 | + "mymodule/extra.py", |
| 138 | + ), |
| 139 | + ) |
| 140 | +
|
| 141 | +To include a manifest from the MicroPython repository, use: |
| 142 | + |
| 143 | +.. code-block:: python3 |
| 144 | +
|
| 145 | + include("$(MPY_DIR)/extmod/uasyncio/manifest.py") |
0 commit comments