|
| 1 | +.. _mpy_files: |
| 2 | + |
| 3 | +MicroPython .mpy files |
| 4 | +====================== |
| 5 | + |
| 6 | +MicroPython defines the concept of an .mpy file which is a binary container |
| 7 | +file format that holds precompiled code, and which can be imported like a |
| 8 | +normal .py module. The file ``foo.mpy`` can be imported via ``import foo``, |
| 9 | +as long as ``foo.mpy`` can be found in the usual way by the import machinery. |
| 10 | +Usually, each directory listed in ``sys.path`` is searched in order. When |
| 11 | +searching a particular directory ``foo.py`` is looked for first and if that |
| 12 | +is not found then ``foo.mpy`` is looked for, then the search continues in the |
| 13 | +next directory if neither is found. As such, ``foo.py`` will take precedence |
| 14 | +over ``foo.mpy``. |
| 15 | + |
| 16 | +These .mpy files can contain bytecode which is usually generated from Python |
| 17 | +source files (.py files) via the ``mpy-cross`` program. For some architectures |
| 18 | +an .mpy file can also contain native machine code, which can be generated in |
| 19 | +a variety of ways, most notably from C source code. |
| 20 | + |
| 21 | +Versioning and compatibility of .mpy files |
| 22 | +------------------------------------------ |
| 23 | + |
| 24 | +A given .mpy file may or may not be compatible with a given MicroPython system. |
| 25 | +Compatibility is based on the following: |
| 26 | + |
| 27 | +* Version of the .mpy file: the version of the file must match the version |
| 28 | + supported by the system loading it. |
| 29 | + |
| 30 | +* Bytecode features used in the .mpy file: there are two bytecode features |
| 31 | + which must match between the file and the system: unicode support and |
| 32 | + inline caching of map lookups in the bytecode. |
| 33 | + |
| 34 | +* Small integer bits: the .mpy file will require a minimum number of bits in |
| 35 | + a small integer and the system loading it must support at least this many |
| 36 | + bits. |
| 37 | + |
| 38 | +* Qstr compression window size: the .mpy file will require a minimum window |
| 39 | + size for qstr decompression and the system loading it must have a window |
| 40 | + greater or equal to this size. |
| 41 | + |
| 42 | +* Native architecture: if the .mpy file contains native machine code then |
| 43 | + it will specify the architecture of that machine code and the system |
| 44 | + loading it must support execution of that architecture's code. |
| 45 | + |
| 46 | +If a MicroPython system supports importing .mpy files then the |
| 47 | +``sys.implementation.mpy`` field will exist and return an integer which |
| 48 | +encodes the version (lower 8 bits), features and native architecture. |
| 49 | + |
| 50 | +Trying to import an .mpy file that fails one of the first four tests will |
| 51 | +raise ``ValueError('incompatible .mpy file')``. Trying to import an .mpy |
| 52 | +file that fails the native architecture test (if it contains native machine |
| 53 | +code) will raise ``ValueError('incompatible .mpy arch')``. |
| 54 | + |
| 55 | +If importing an .mpy file fails then try the following: |
| 56 | + |
| 57 | +* Determine the .mpy version and flags supported by your MicroPython system |
| 58 | + by executing:: |
| 59 | + |
| 60 | + import sys |
| 61 | + sys_mpy = sys.implementation.mpy |
| 62 | + arch = [None, 'x86', 'x64', |
| 63 | + 'armv6', 'armv6m', 'armv7m', 'armv7em', 'armv7emsp', 'armv7emdp', |
| 64 | + 'xtensa', 'xtensawin'][sys_mpy >> 10] |
| 65 | + print('mpy version:', sys_mpy & 0xff) |
| 66 | + print('mpy flags:', end='') |
| 67 | + if arch: |
| 68 | + print(' -march=' + arch, end='') |
| 69 | + if sys_mpy & 0x100: |
| 70 | + print(' -mcache-lookup-bc', end='') |
| 71 | + if not sys_mpy & 0x200: |
| 72 | + print(' -mno-unicode', end='') |
| 73 | + print() |
| 74 | + |
| 75 | +* Check the validity of the .mpy file by inspecting the first two bytes of |
| 76 | + the file. The first byte should be an uppercase 'M' and the second byte |
| 77 | + will be the version number, which should match the system version from above. |
| 78 | + If it doesn't match then rebuild the .mpy file. |
| 79 | + |
| 80 | +* Check if the system .mpy version matches the version emitted by ``mpy-cross`` |
| 81 | + that was used to build the .mpy file, found by ``mpy-cross --version``. |
| 82 | + If it doesn't match then recompile ``mpy-cross`` from the Git repository |
| 83 | + checked out at the tag (or hash) reported by ``mpy-cross --version``. |
| 84 | + |
| 85 | +* Make sure you are using the correct ``mpy-cross`` flags, found by the code |
| 86 | + above, or by inspecting the ``MPY_CROSS_FLAGS`` Makefile variable for the |
| 87 | + port that you are using. |
| 88 | + |
| 89 | +The following table shows the correspondence between MicroPython release |
| 90 | +and .mpy version. |
| 91 | + |
| 92 | +=================== ============ |
| 93 | +MicroPython release .mpy version |
| 94 | +=================== ============ |
| 95 | +v1.12 and up 5 |
| 96 | +v1.11 4 |
| 97 | +v1.9.3 - v1.10 3 |
| 98 | +v1.9 - v1.9.2 2 |
| 99 | +v1.5.1 - v1.8.7 0 |
| 100 | +=================== ============ |
| 101 | + |
| 102 | +For completeness, the next table shows the Git commit of the main |
| 103 | +MicroPython repository at which the .mpy version was changed. |
| 104 | + |
| 105 | +=================== ======================================== |
| 106 | +.mpy version change Git commit |
| 107 | +=================== ======================================== |
| 108 | +4 to 5 5716c5cf65e9b2cb46c2906f40302401bdd27517 |
| 109 | +3 to 4 9a5f92ea72754c01cc03e5efcdfe94021120531e |
| 110 | +2 to 3 ff93fd4f50321c6190e1659b19e64fef3045a484 |
| 111 | +1 to 2 dd11af209d226b7d18d5148b239662e30ed60bad |
| 112 | +0 to 1 6a11048af1d01c78bdacddadd1b72dc7ba7c6478 |
| 113 | +initial version 0 d8c834c95d506db979ec871417de90b7951edc30 |
| 114 | +=================== ======================================== |
| 115 | + |
| 116 | +Binary encoding of .mpy files |
| 117 | +----------------------------- |
| 118 | + |
| 119 | +MicroPython .mpy files are a binary container format with code objects |
| 120 | +stored internally in a nested hierarchy. To keep files small while still |
| 121 | +providing a large range of possible values it uses the concept of a |
| 122 | +variably-encoded-unsigned-integer (vuint) in many places. Similar to utf-8 |
| 123 | +encoding, this encoding stores 7 bits per byte with the 8th bit (MSB) set |
| 124 | +if one or more bytes follow. The bits of the unsigned integer are stored |
| 125 | +in the vuint in LSB form. |
| 126 | + |
| 127 | +The top-level of an .mpy file consists of two parts: |
| 128 | + |
| 129 | +* The header. |
| 130 | + |
| 131 | +* The raw-code for the outer scope of the module. |
| 132 | + This outer scope is executed when the .mpy file is imported. |
| 133 | + |
| 134 | +The header |
| 135 | +~~~~~~~~~~ |
| 136 | + |
| 137 | +The .mpy header is: |
| 138 | + |
| 139 | +====== ================================ |
| 140 | +size field |
| 141 | +====== ================================ |
| 142 | +byte value 0x4d (ASCII 'M') |
| 143 | +byte .mpy version number |
| 144 | +byte feature flags |
| 145 | +byte number of bits in a small int |
| 146 | +vuint size of qstr window |
| 147 | +====== ================================ |
| 148 | + |
| 149 | +Raw code elements |
| 150 | +~~~~~~~~~~~~~~~~~ |
| 151 | + |
| 152 | +A raw-code element contains code, either bytecode or native machine code. Its |
| 153 | +contents are: |
| 154 | + |
| 155 | +====== ================================ |
| 156 | +size field |
| 157 | +====== ================================ |
| 158 | +vuint type and size |
| 159 | +... code (bytecode or machine code) |
| 160 | +vuint number of constant objects |
| 161 | +vuint number of sub-raw-code elements |
| 162 | +... constant objects |
| 163 | +... sub-raw-code elements |
| 164 | +====== ================================ |
| 165 | + |
| 166 | +The first vuint in a raw-code element encodes the type of code stored in this |
| 167 | +element (the two least-significant bits), and the decompressed length of the code |
| 168 | +(the amount of RAM to allocate for it). |
| 169 | + |
| 170 | +Following the vuint comes the code itself. In the case of bytecode it also contains |
| 171 | +compressed qstr values. |
| 172 | + |
| 173 | +Following the code comes a vuint counting the number of constant objects, and |
| 174 | +another vuint counting the number of sub-raw-code elements. |
| 175 | + |
| 176 | +The constant objects are then stored next. |
| 177 | + |
| 178 | +Finally any sub-raw-code elements are stored, recursively. |
0 commit comments