diff options
author | Damien George <damien@micropython.org> | 2021-04-02 17:07:20 +1100 |
---|---|---|
committer | Damien George <damien@micropython.org> | 2021-04-02 17:07:20 +1100 |
commit | f541b3673d272fbe9081a96776072a83ac5add9d (patch) | |
tree | 41757ec72688961a7e10c0d3732ab21a55060e48 | |
parent | d87f42b0e53829052f17955ba1e17f938ae486fb (diff) | |
download | micropython-f541b3673d272fbe9081a96776072a83ac5add9d.tar.gz micropython-f541b3673d272fbe9081a96776072a83ac5add9d.zip |
docs/develop: Improve user C modules to properly describe how to build.
Make and CMake builds are slightly different and these changes help make it
clear what to do in each case.
Signed-off-by: Damien George <damien@micropython.org>
-rw-r--r-- | docs/develop/cmodules.rst | 176 |
1 files changed, 102 insertions, 74 deletions
diff --git a/docs/develop/cmodules.rst b/docs/develop/cmodules.rst index be49485f2c..346b3e0314 100644 --- a/docs/develop/cmodules.rst +++ b/docs/develop/cmodules.rst @@ -18,7 +18,11 @@ If however you're targeting obscure or proprietary systems it may make more sense to keep this external to the main MicroPython repository. This chapter describes how to compile such external modules into the -MicroPython executable or firmware image. +MicroPython executable or firmware image. Both Make and CMake build +tools are supported, and when writing an external module it's a good idea to +add the build files for both of these tools so the module can be used on all +ports. But when compiling a particular port you will only need to use one +method of building, either Make or CMake. An alternative approach is to use :ref:`natmod` which allows writing custom C code that is placed in a .mpy file, which can be imported dynamically in to @@ -111,116 +115,140 @@ To build such a module, compile MicroPython (see `getting started <https://github.com/micropython/micropython/wiki/Getting-Started>`_), applying 2 modifications: -- an extra ``make`` flag named ``USER_C_MODULES`` set to the directory - containing all modules you want included (not to the module itself). - For building the example modules which come with MicroPython, - set ``USER_C_MODULES`` to the ``examples/usercmodule`` directory. - For your own projects it's more convenient to keep custom code out of - the main source tree so a typical project directory structure will look - like this:: +1. Set the build-time flag ``USER_C_MODULES`` to point to the modules + you want to include. For ports that use Make this variable should be a + directory which is searched automatically for modules. For ports that + use CMake this variable should be a file which includes the modules to + build. See below for details. - my_project/ - ├── modules/ - │ └──example1/ - │ ├──example1.c - │ ├──micropython.mk - │ └──micropython.cmake - │ └──example2/ - │ ├──example2.c - │ ├──micropython.mk - │ └──micropython.cmake - │ └──micropython.cmake - └── micropython/ - ├──ports/ - ... ├──stm32/ - ... +2. Enable the modules by setting the corresponding C preprocessor macro to + 1. This is only needed if the modules you are building are not + automatically enabled. +For building the example modules which come with MicroPython, +set ``USER_C_MODULES`` to the ``examples/usercmodule`` directory for Make, +or to ``examples/usercmodule/micropython.cmake`` for CMake. - with ``USER_C_MODULES`` set to the ``my_project/modules`` directory. +For example, here's how the to build the unix port with the example modules: - A top level ``micropython.cmake`` - found directly in the ``my_project/modules`` - directory - should ``include`` all of your modules. +.. code-block:: bash - .. code-block:: cmake + cd micropython/ports/unix + make USER_C_MODULES=../../examples/usercmodule - include(${CMAKE_CURRENT_LIST_DIR}/example1/micropython.cmake) - include(${CMAKE_CURRENT_LIST_DIR}/example2/micropython.cmake) +You may need to run ``make clean`` once at the start when including new +user modules in the build. The build output will show the modules found:: + ... + Including User C Module from ../../examples/usercmodule/cexample + Including User C Module from ../../examples/usercmodule/cppexample + ... -- all modules found in this directory (or added via ``include`` in the top-level - ``micropython.cmake`` when using CMake) will be compiled, but only those which are - enabled will be available for importing. If a module is to always be enabled, - which is usually the case for custom modules and custom builds, then it is - enough to supply "1" as the third parameter to the registration macro, like: +For a CMake-based port such as rp2, this will look a little different (note +that CMake is actually invoked by ``make``): - .. code-block:: c +.. code-block:: bash - MP_REGISTER_MODULE(MP_QSTR_cexample, example_user_cmodule, 1); + cd micropython/ports/rp2 + make USER_C_MODULES=../../examples/usercmodule/micropython.cmake - Alternatively, to make the module disabled by default but selectable through - a preprocessor configuration option, use: +Again, you may need to run ``make clean`` first for CMake to pick up the +user modules. The CMake build output lists the modules by name:: - .. code-block:: c + ... + Including User C Module(s) from ../../examples/usercmodule/micropython.cmake + Found User C Module(s): usermod_cexample, usermod_cppexample + ... - MP_REGISTER_MODULE(MP_QSTR_cexample, example_user_cmodule, MODULE_CEXAMPLE_ENABLED); +The contents of the top-level ``micropython.cmake`` can be used to control which +modules are enabled. +For your own projects it's more convenient to keep custom code out of the main +MicroPython source tree, so a typical project directory structure will look +like this:: - Then ``MODULE_CEXAMPLE_ENABLED`` has to be set to 1 to make the module available. - This can be done by adding ``CFLAGS_EXTRA=-DMODULE_CEXAMPLE_ENABLED=1`` to - the ``make`` command, or editing ``mpconfigport.h`` or ``mpconfigboard.h`` - to add + my_project/ + ├── modules/ + │ ├── example1/ + │ │ ├── example1.c + │ │ ├── micropython.mk + │ │ └── micropython.cmake + │ ├── example2/ + │ │ ├── example2.c + │ │ ├── micropython.mk + │ │ └── micropython.cmake + │ └── micropython.cmake + └── micropython/ + ├──ports/ + ... ├──stm32/ + ... - .. code-block:: c +When building with Make set ``USER_C_MODULES`` to the ``my_project/modules`` +directory. For example, building the stm32 port: - #define MODULE_CEXAMPLE_ENABLED (1) +.. code-block:: bash + cd my_project/micropython/ports/stm32 + make USER_C_MODULES=../../../modules - Note that the exact method depends on the port as they have different - structures. If not done correctly it will compile but importing will - fail to find the module. +When building with CMake the top level ``micropython.cmake`` -- found directly +in the ``my_project/modules`` directory -- should ``include`` all of the modules +you want to have available: -To sum up, here's how the ``cexample`` module from the ``examples/usercmodule`` -directory can be built for the unix port: + .. code-block:: cmake -.. code-block:: bash + include(${CMAKE_CURRENT_LIST_DIR}/example1/micropython.cmake) + include(${CMAKE_CURRENT_LIST_DIR}/example2/micropython.cmake) - cd micropython/ports/unix - make USER_C_MODULES=../../examples/usercmodule all +Then build with: -The build output will show the modules found:: +.. code-block:: bash - ... - Including User C Module from ../../examples/usercmodule/cexample - Including User C Module from ../../examples/usercmodule/cppexample - ... + cd my_project/micropython/ports/esp32 + make USER_C_MODULES=../../../../modules/micropython.cmake +Note that the esp32 port needs the extra ``..`` for relative paths due to the +location of its main ``CMakeLists.txt`` file. You can also specify absolute +paths to ``USER_C_MODULES``. -For a CMake-based port such as rp2, this will look a little different: +All modules specified by the ``USER_C_MODULES`` variable (either found in this +directory when using Make, or added via ``include`` when using CMake) will be +compiled, but only those which are enabled will be available for importing. +User modules are usually enabled by default (this is decided by the developer +of the module), in which case there is nothing more to do than set ``USER_C_MODULES`` +as described above. -.. code-block:: bash +If a module is not enabled by default then the corresponding C preprocessor macro +must be enabled. This macro name can be found by searching for the ``MP_REGISTER_MODULE`` +line in the module's source code (it usually appears at the end of the main source file). +The third argument to ``MP_REGISTER_MODULE`` is the macro name, and this must be set +to 1 using ``CFLAGS_EXTRA`` to make the module available. If the third argument is just +the number 1 then the module is enabled by default. - cd micropython/ports/rp2 - make USER_C_MODULES=../../examples/usercmodule all +For example, the ``examples/usercmodule/cexample`` module is enabled by default so +has the following line in its source code: + .. code-block:: c -The CMake build output lists the modules by name:: + MP_REGISTER_MODULE(MP_QSTR_cexample, example_user_cmodule, 1); - ... - Including User C Module(s) from ../../examples/usercmodule/micropython.cmake - Found User C Module(s): usermod_cexample, usermod_cppexample - ... +Alternatively, to make this module disabled by default but selectable through +a preprocessor configuration option, it would be: + .. code-block:: c -The top-level ``micropython.cmake`` can be used to control which modules are enabled. + MP_REGISTER_MODULE(MP_QSTR_cexample, example_user_cmodule, MODULE_CEXAMPLE_ENABLED); +In this case the module is enabled by adding ``CFLAGS_EXTRA=-DMODULE_CEXAMPLE_ENABLED=1`` +to the ``make`` command, or editing ``mpconfigport.h`` or ``mpconfigboard.h`` to add -Or for your own project with a directory structure as shown above, -including both modules and building the stm32 port for example: + .. code-block:: c -.. code-block:: bash + #define MODULE_CEXAMPLE_ENABLED (1) - cd my_project/micropython/ports/stm32 - make USER_C_MODULES=../../../modules all +Note that the exact method depends on the port as they have different +structures. If not done correctly it will compile but importing will +fail to find the module. Module usage in MicroPython |