1.. _modules:
2
3Modules (External projects)
4############################
5
6Zephyr relies on the source code of several externally maintained projects in
7order to avoid reinventing the wheel and to reuse as much well-established,
8mature code as possible when it makes sense. In the context of Zephyr's build
9system those are called *modules*. These modules must be integrated with the
10Zephyr build system, as described in more detail in other sections on
11this page.
12
13To be classified as a candidate for being included in the default list of
14modules, an external project is required to have its own life-cycle outside
15the Zephyr Project, that is, reside in its own repository, and have its own
16contribution and maintenance workflow and release process. Zephyr modules
17should not contain code that is written exclusively for Zephyr. Instead,
18such code should be contributed to the main zephyr tree.
19
20Modules to be included in the default manifest of the Zephyr project need to
21provide functionality or features endorsed and approved by the project Technical
22Steering Committee and should comply with the
23:ref:`module licensing requirements<modules_licensing>` and
24:ref:`contribution guidelines<modules_contributing>`. They should also have a
25Zephyr developer that is committed to maintain the module codebase.
26
27Zephyr depends on several categories of modules, including but not limited to:
28
29- Debugger integration
30- Silicon vendor Hardware Abstraction Layers (HALs)
31- Cryptography libraries
32- File Systems
33- Inter-Process Communication (IPC) libraries
34
35Additionally, in some cases modules (particularly vendor HALs) can contain
36references to optional :ref:`binary blobs <bin-blobs>`.
37
38This page summarizes a list of policies and best practices which aim at
39better organizing the workflow in Zephyr modules.
40
41.. _modules-vs-projects:
42
43Modules vs west projects
44************************
45
46Zephyr modules, described in this page, are not the same as :ref:`west projects
47<west-workspace>`. In fact, modules :ref:`do not require west
48<modules_without_west>` at all. However, when using modules :ref:`with west
49<modules_using_west>`, then the build system uses west in order to find modules.
50
51In summary:
52
53Modules are repositories that contain a :file:`zephyr/module.yml` file, so that
54the Zephyr build system can pull in the source code from the repository.
55:ref:`West projects <west-manifests-projects>` are entries in the ``projects:``
56section in the :file:`west.yml` manifest file.
57West projects are often also modules, but not always. There are west projects
58that are not included in the final firmware image (eg. tools) and thus do not
59need to be modules.
60Modules are found by the Zephyr build system either via :ref:`west itself
61<modules_using_west>`, or via the :ref:`ZEPHYR_MODULES CMake variable
62<modules_without_west>`.
63
64The contents of this page only apply to modules, and not to west projects in
65general (unless they are a module themselves).
66
67Module Repositories
68*******************
69
70* All modules included in the default manifest shall be hosted in repositories
71  under the zephyrproject-rtos GitHub organization.
72
73* The module repository codebase shall include a *module.yml* file in a
74  :file:`zephyr/` folder at the root of the repository.
75
76* Module repository names should follow the convention of using lowercase
77  letters and dashes instead of underscores. This rule will apply to all
78  new module repositories, except for repositories that are directly
79  tracking external projects (hosted in Git repositories); such modules
80  may be named as their external project counterparts.
81
82  .. note::
83
84     Existing module repositories that do not conform to the above convention
85     do not need to be renamed to comply with the above convention.
86
87* Module repositories names should be explicitly set in the :file:`zephyr/module.yml` file.
88
89* Modules should use "zephyr" as the default name for the repository main
90  branch. Branches for specific purposes, for example, a module branch for
91  an LTS Zephyr version, shall have names starting with the 'zephyr\_' prefix.
92
93* If the module has an external (upstream) project repository, the module
94  repository should preserve the upstream repository folder structure.
95
96  .. note::
97
98     It is not required in module repositories to maintain a 'master'
99     branch mirroring the master branch of the external repository. It
100     is not recommended as this may generate confusion around the module's
101     main branch, which should be 'zephyr'.
102
103* Modules should expose all provided header files with an include pathname
104  beginning with the module-name.  (E.g., mcuboot should expose its
105  ``bootutil/bootutil.h`` as "mcuboot/bootutil/bootutil.h".)
106
107.. _modules_synchronization:
108
109Synchronizing with upstream
110===========================
111
112It is preferred to synchronize a module repository with the latest stable
113release of the corresponding external project. It is permitted, however, to
114update a Zephyr module repository with the latest development branch tip,
115if this is required to get important updates in the module codebase. When
116synchronizing a module with upstream it is mandatory to document the
117rationale for performing the particular update.
118
119Requirements for allowed practices
120----------------------------------
121
122Changes to the main branch of a module repository, including synchronization
123with upstream code base, may only be applied via pull requests. These pull
124requests shall be *verifiable* by Zephyr CI and *mergeable* (e.g. with the
125*Rebase and merge*, or *Create a merge commit* option using Github UI). This
126ensures that the incoming changes are always **reviewable**, and the
127*downstream* module repository history is incremental (that is, existing
128commits, tags, etc. are always preserved). This policy also allows to run
129Zephyr CI, git lint, identity, and license checks directly on the set of
130changes that are to be brought into the module repository.
131
132.. note::
133
134     Force-pushing to a module's main branch is not allowed.
135
136Allowed practices
137-----------------
138
139The following practices conform to the above requirements and should be
140followed in all modules repositories. It is up to the module code owner
141to select the preferred synchronization practice, however, it is required
142that the selected practice is consistently followed in the respective
143module repository.
144
145**Updating modules with a diff from upstream:**
146Upstream changes brought as a single *snapshot* commit (manual diff) in a
147pull request against the module's main branch, which may be merged using
148the *Rebase & merge* operation. This approach is simple and
149should be applicable to all modules with the downside of suppressing the
150upstream history in the module repository.
151
152  .. note::
153
154     The above practice is the only allowed practice in modules where
155     the external project is not hosted in an upstream Git repository.
156
157The commit message is expected to identify the upstream project URL, the
158version to which the module is updated (upstream version, tag, commit SHA,
159if applicable, etc.), and the reason for the doing the update.
160
161**Updating modules by merging the upstream branch:**
162Upstream changes brought in by performing a Git merge of the intended upstream
163branch (e.g. main branch, latest release branch, etc.) submitting the result in
164pull request against the module main branch, and merging the pull request using
165the *Create a merge commit* operation.
166This approach is applicable to modules with an upstream project Git repository.
167The main advantages of this approach is that the upstream repository history
168(that is, the original commit SHAs) is preserved in the module repository. The
169downside of this approach is that two additional merge commits are generated in
170the downstream main branch.
171
172
173Contributing to Zephyr modules
174******************************
175
176.. _modules_contributing:
177
178
179Individual Roles & Responsibilities
180===================================
181
182To facilitate management of Zephyr module repositories, the following
183individual roles are defined.
184
185**Administrator:** Each Zephyr module shall have an administrator
186who is responsible for managing access to the module repository,
187for example, for adding individuals as Collaborators in the repository
188at the request of the module owner. Module administrators are
189members of the Administrators team, that is a group of project
190members with admin rights to module GitHub repositories.
191
192**Module owner:** Each module shall have a module code owner. Module
193owners will have the overall responsibility of the contents of a
194Zephyr module repository. In particular, a module owner will:
195
196* coordinate code reviewing in the module repository
197* be the default assignee in pull-requests against the repository's
198  main branch
199* request additional collaborators to be added to the repository, as
200  they see fit
201* regularly synchronize the module repository with its upstream
202  counterpart following the policies described in
203  :ref:`modules_synchronization`
204* be aware of security vulnerability issues in the external project
205  and update the module repository to include security fixes, as
206  soon as the fixes are available in the upstream code base
207* list any known security vulnerability issues, present in the
208  module codebase, in Zephyr release notes.
209
210
211  .. note::
212
213     Module owners are not required to be Zephyr
214     :ref:`Maintainers <project_roles>`.
215
216**Merger:** The Zephyr Release Engineering team has the right and the
217responsibility to merge approved pull requests in the main branch of a
218module repository.
219
220
221Maintaining the module codebase
222===============================
223
224Updates in the zephyr main tree, for example, in public Zephyr APIs,
225may require patching a module's codebase. The responsibility for keeping
226the module codebase up to date is shared between the **contributor** of
227such updates in Zephyr and the module **owner**. In particular:
228
229* the contributor of the original changes in Zephyr is required to submit
230  the corresponding changes that are required in module repositories, to
231  ensure that Zephyr CI on the pull request with the original changes, as
232  well as the module integration testing are successful.
233
234* the module owner has the overall responsibility for synchronizing
235  and testing the module codebase with the zephyr main tree.
236  This includes occasional advanced testing of the module's codebase
237  in addition to the testing performed by Zephyr's CI.
238  The module owner is required to fix issues in the module's codebase that
239  have not been caught by Zephyr pull request CI runs.
240
241
242.. _modules_changes:
243
244Contributing changes to modules
245===============================
246
247Submitting and merging changes directly to a module's codebase, that is,
248before they have been merged in the corresponding external project
249repository, should be limited to:
250
251* changes required due to updates in the zephyr main tree
252* urgent changes that should not wait to be merged in the external project
253  first, such as fixes to security vulnerabilities.
254
255Non-trivial changes to a module's codebase, including changes in the module
256design or functionality should be discouraged, if the module has an upstream
257project repository. In that case, such changes shall be submitted to the
258upstream project, directly.
259
260:ref:`Submitting changes to modules <submitting_new_modules>` describes in
261detail the process of contributing changes to module repositories.
262
263Contribution guidelines
264-----------------------
265
266Contributing to Zephyr modules shall follow the generic project
267:ref:`Contribution guidelines <contribute_guidelines>`.
268
269**Pull Requests:** may be merged with minimum of 2 approvals, including
270an approval by the PR assignee. In addition to this, pull requests in module
271repositories may only be merged if the introduced changes are verified
272with Zephyr CI tools, as described in more detail in other sections on
273this page.
274
275The merging of pull requests in the main branch of a module
276repository must be coupled with the corresponding manifest
277file update in the zephyr main tree.
278
279**Issue Reporting:** `GitHub issues`_ are intentionally disabled in module
280repositories, in
281favor of a centralized policy for issue reporting. Tickets concerning, for
282example, bugs or enhancements in modules shall be opened in the main
283zephyr repository. Issues should be appropriately labeled using GitHub
284labels corresponding to each module, where applicable.
285
286  .. note::
287
288     It is allowed to file bug reports for zephyr modules to track
289     the corresponding upstream project bugs in Zephyr. These bug reports
290     shall not affect the
291     :ref:`Release Quality Criteria<release_quality_criteria>`.
292
293
294.. _modules_licensing:
295
296Licensing requirements and policies
297***********************************
298
299All source files in a module's codebase shall include a license header,
300unless the module repository has **main license file** that covers source
301files that do not include license headers.
302
303Main license files shall be added in the module's codebase by Zephyr
304developers, only if they exist as part of the external project,
305and they contain a permissive OSI-compliant license. Main license files
306should preferably contain the full license text instead of including an
307SPDX license identifier. If multiple main license files are present it
308shall be made clear which license applies to each source file in a module's
309codebase.
310
311Individual license headers in module source files supersede the main license.
312
313Any new content to be added in a module repository will require to have
314license coverage.
315
316  .. note::
317
318     Zephyr recommends conveying module licensing via individual license
319     headers and main license files. This not a hard requirement; should
320     an external project have its own practice of conveying how licensing
321     applies in the module's codebase (for example, by having a single or
322     multiple main license files), this practice may be accepted by and
323     be referred to in the Zephyr module, as long as licensing requirements,
324     for example OSI compliance, are satisfied.
325
326License policies
327================
328
329When creating a module repository a developer shall:
330
331* import the main license files, if they exist in the external project, and
332* document (for example in the module README or .yml file) the default license
333  that covers the module's codebase.
334
335License checks
336--------------
337
338License checks (via CI tools) shall be enabled on every pull request that
339adds new content in module repositories.
340
341
342Documentation requirements
343**************************
344
345All Zephyr module repositories shall include an .rst file documenting:
346
347* the scope and the purpose of the module
348* how the module integrates with Zephyr
349* the owner of the module repository
350* synchronization information with the external project (commit, SHA, version etc.)
351* licensing information as described in :ref:`modules_licensing`.
352
353The file shall be required for the inclusion of the module and the contained
354information should be kept up to date.
355
356
357Testing requirements
358********************
359
360All Zephyr modules should provide some level of **integration** testing,
361ensuring that the integration with Zephyr works correctly.
362Integration tests:
363
364* may be in the form of a minimal set of samples and tests that reside
365  in the zephyr main tree
366* should verify basic usage of the module (configuration,
367  functional APIs, etc.) that is integrated with Zephyr.
368* shall be built and executed (for example in QEMU) as part of
369  twister runs in pull requests that introduce changes in module
370  repositories.
371
372  .. note::
373
374     New modules, that are candidates for being included in the Zephyr
375     default manifest, shall provide some level of integration testing.
376
377  .. note::
378
379     Vendor HALs are implicitly tested via Zephyr tests built or executed
380     on target platforms, so they do not need to provide integration tests.
381
382The purpose of integration testing is not to provide functional verification
383of the module; this should be part of the testing framework of the external
384project.
385
386Certain external projects provide test suites that reside in the upstream
387testing infrastructure but are written explicitly for Zephyr. These tests
388may (but are not required to) be part of the Zephyr test framework.
389
390Deprecating and removing modules
391*********************************
392
393Modules may be deprecated for reasons including, but not limited to:
394
395* Lack of maintainership in the module
396* Licensing changes in the external project
397* Codebase becoming obsolete
398
399The module information shall indicate whether a module is
400deprecated and the build system shall issue a warning
401when trying to build Zephyr using a deprecated module.
402
403Deprecated modules may be removed from the Zephyr default manifest
404after 2 Zephyr releases.
405
406  .. note::
407
408     Repositories of removed modules shall remain accessible via their
409     original URL, as they are required by older Zephyr versions.
410
411
412Integrate modules in Zephyr build system
413****************************************
414
415The build system variable :makevar:`ZEPHYR_MODULES` is a `CMake list`_ of
416absolute paths to the directories containing Zephyr modules. These modules
417contain :file:`CMakeLists.txt` and :file:`Kconfig` files describing how to
418build and configure them, respectively. Module :file:`CMakeLists.txt` files are
419added to the build using CMake's `add_subdirectory()`_ command, and the
420:file:`Kconfig` files are included in the build's Kconfig menu tree.
421
422If you have :ref:`west <west>` installed, you don't need to worry about how
423this variable is defined unless you are adding a new module. The build system
424knows how to use west to set :makevar:`ZEPHYR_MODULES`. You can add additional
425modules to this list by setting the :makevar:`EXTRA_ZEPHYR_MODULES` CMake
426variable or by adding a :makevar:`EXTRA_ZEPHYR_MODULES` line to ``.zephyrrc``
427(See the section on :ref:`env_vars` for more details). This can be useful if you
428want to keep the list of modules found with west and also add your own. If
429:makevar:`EXTRA_ZEPHYR_MODULES` is set in multiple places, for example both as
430an environment variable and as a CMake variable, the final list of additional
431modules will be the merged result of all sources.
432
433.. note::
434   If the module ``FOO`` is provided by :ref:`west <west>` but also given with
435   ``-DEXTRA_ZEPHYR_MODULES=/<path>/foo`` then the module given by the command
436   line variable :makevar:`EXTRA_ZEPHYR_MODULES` will take precedence.
437   This allows you to use a custom version of ``FOO`` when building and still
438   use other Zephyr modules provided by :ref:`west <west>`.
439   This can for example be useful for special test purposes.
440
441If you want to permanently add modules to the zephyr workspace and you are
442using zephyr as your manifest repository, you can also add a west manifest file
443into the :zephyr_file:`submanifests` directory. See
444:zephyr_file:`submanifests/README.txt` for more details.
445
446See :ref:`west-basics` for more on west workspaces.
447
448Finally, you can also specify the list of modules yourself in various ways, or
449not use modules at all if your application doesn't need them.
450
451.. _module-yml:
452
453Module yaml file description
454****************************
455
456A module can be described using a file named :file:`zephyr/module.yml`.
457The format of :file:`zephyr/module.yml` is described in the following:
458
459Module name
460===========
461
462Each Zephyr module is given a name by which it can be referred to in the build
463system.
464
465The name should be specified in the :file:`zephyr/module.yml` file. This will
466ensure the module name is not changeable through user-defined directory names
467or ``west`` manifest files:
468
469.. code-block:: yaml
470
471   name: <name>
472
473In CMake the location of the Zephyr module can then be referred to using the
474CMake variable ``ZEPHYR_<MODULE_NAME>_MODULE_DIR`` and the variable
475``ZEPHYR_<MODULE_NAME>_CMAKE_DIR`` holds the location of the directory
476containing the module's :file:`CMakeLists.txt` file.
477
478.. note::
479   When used for CMake and Kconfig variables, all letters in module names are
480   converted to uppercase and all non-alphanumeric characters are converted
481   to underscores (_).
482   As example, the module ``foo-bar`` must be referred to as
483   ``ZEPHYR_FOO_BAR_MODULE_DIR`` in CMake and Kconfig.
484
485Here is an example for the Zephyr module ``foo``:
486
487.. code-block:: yaml
488
489   name: foo
490
491.. note::
492   If the ``name`` field is not specified then the Zephyr module name will be
493   set to the name of the module folder.
494   As example, the Zephyr module located in :file:`<workspace>/modules/bar` will
495   use ``bar`` as its module name if nothing is specified in
496   :file:`zephyr/module.yml`.
497
498Module integration files (in-module)
499====================================
500
501Inclusion of build files, :file:`CMakeLists.txt` and :file:`Kconfig`, can be
502described as:
503
504.. code-block:: yaml
505
506   build:
507     cmake: <cmake-directory>
508     kconfig: <directory>/Kconfig
509
510The ``cmake: <cmake-directory>`` part specifies that
511:file:`<cmake-directory>` contains the :file:`CMakeLists.txt` to use. The
512``kconfig: <directory>/Kconfig`` part specifies the Kconfig file to use.
513Neither is required: ``cmake`` defaults to ``zephyr``, and ``kconfig``
514defaults to ``zephyr/Kconfig``.
515
516Here is an example :file:`module.yml` file referring to
517:file:`CMakeLists.txt` and :file:`Kconfig` files in the root directory of the
518module:
519
520.. code-block:: yaml
521
522   build:
523     cmake: .
524     kconfig: Kconfig
525
526.. _sysbuild_module_integration:
527
528Sysbuild integration
529====================
530
531:ref:`Sysbuild<sysbuild>` is the Zephyr build system that allows for building
532multiple images as part of a single application, the sysbuild build process
533can be extended externally with modules as needed, for example to add custom
534build steps or add additional targets to a build. Inclusion of
535sysbuild-specific build files, :file:`CMakeLists.txt` and :file:`Kconfig`, can
536be described as:
537
538.. code-block:: yaml
539
540   build:
541     sysbuild-cmake: <cmake-directory>
542     sysbuild-kconfig: <directory>/Kconfig
543
544The ``sysbuild-cmake: <cmake-directory>`` part specifies that
545:file:`<cmake-directory>` contains the :file:`CMakeLists.txt` to use. The
546``sysbuild-kconfig: <directory>/Kconfig`` part specifies the Kconfig file to
547use.
548
549Here is an example :file:`module.yml` file referring to
550:file:`CMakeLists.txt` and :file:`Kconfig` files in the ``sysbuild`` directory of
551the module:
552
553.. code-block:: yaml
554
555   build:
556     sysbuild-cmake: sysbuild
557     sysbuild-kconfig: sysbuild/Kconfig
558
559The module description file :file:`zephyr/module.yml` can also be used to
560specify that the build files, :file:`CMakeLists.txt` and :file:`Kconfig`, are
561located in a :ref:`modules_module_ext_root`.
562
563Build files located in a ``MODULE_EXT_ROOT`` can be described as:
564
565.. code-block:: yaml
566
567   build:
568     sysbuild-cmake-ext: True
569     sysbuild-kconfig-ext: True
570
571This allows control of the build inclusion to be described externally to the
572Zephyr module.
573
574.. _modules-vulnerability-monitoring:
575
576Vulnerability monitoring
577========================
578
579The module description file :file:`zephyr/module.yml` can be used to improve vulnerability monitoring.
580
581If your module needs to track vulnerabilities using an external reference
582(e.g your module is forked from another repository), you can use the ``security`` section.
583It contains the field ``external-references`` that contains a list of references that needs to
584be monitored for your module. The supported formats are:
585
586- CPE (Common Platform Enumeration)
587- PURL (Package URL)
588
589.. code-block:: yaml
590
591   security:
592     external-references:
593       - <module-related-cpe>
594       - <an-other-module-related-cpe>
595       - <module-related-purl>
596
597A real life example for ``mbedTLS`` module could look like this:
598
599.. code-block:: yaml
600
601   security:
602     external-references:
603       - cpe:2.3:a:arm:mbed_tls:3.5.2:*:*:*:*:*:*:*
604       - pkg:github/Mbed-TLS/mbedtls@V3.5.2
605
606.. note::
607   CPE field must follow the CPE 2.3 schema provided by `NVD
608   <https://csrc.nist.gov/projects/security-content-automation-protocol/specifications/cpe>`_.
609   PURL field must follow the PURL specification provided by `Github
610   <https://github.com/package-url/purl-spec/blob/master/PURL-SPECIFICATION.rst>`_.
611
612
613Build system integration
614========================
615
616When a module has a :file:`module.yml` file, it will automatically be included into
617the Zephyr build system. The path to the module is then accessible through Kconfig
618and CMake variables.
619
620Zephyr modules
621--------------
622
623In both Kconfig and CMake, the variable ``ZEPHYR_<MODULE_NAME>_MODULE_DIR``
624contains the absolute path to the module.
625
626Additionally, ``ZEPHYR_<MODULE_NAME>_MODULE`` and ``ZEPHYR_<MODULE_NAME>_MODULE_BLOBS``
627(in case the module declares blobs) symbols are automatically generated for available
628modules. These can be used e.g. to declare dependencies from other Kconfig symbols
629which depend on the module or blobs from the module. To satisfy compliance checking
630when building Zephyr without the module present, it's recommended for the module to
631have default definitions for these symbols in its respective Kconfig file under
632``modules/`` in the Zephyr main tree.
633
634In CMake, ``ZEPHYR_<MODULE_NAME>_CMAKE_DIR`` contains the
635absolute path to the directory containing the :file:`CMakeLists.txt` file that
636is included into CMake build system. This variable's value is empty if the
637module.yml file does not specify a CMakeLists.txt.
638
639To read these variables for a Zephyr module named ``foo``:
640
641- In CMake: use ``${ZEPHYR_FOO_MODULE_DIR}`` for the module's top level directory, and ``${ZEPHYR_FOO_CMAKE_DIR}`` for the directory containing its :file:`CMakeLists.txt`
642- In Kconfig: use ``$(ZEPHYR_FOO_MODULE_DIR)`` for the module's top level directory
643
644Notice how a lowercase module name ``foo`` is capitalized to ``FOO``
645in both CMake and Kconfig.
646
647These variables can also be used to test whether a given module exists.
648For example, to verify that ``foo`` is the name of a Zephyr module:
649
650.. code-block:: cmake
651
652  if(ZEPHYR_FOO_MODULE_DIR)
653    # Do something if FOO exists.
654  endif()
655
656In Kconfig, the variable may be used to find additional files to include.
657For example, to include the file :file:`some/Kconfig` in module ``foo``:
658
659.. code-block:: kconfig
660
661  source "$(ZEPHYR_FOO_MODULE_DIR)/some/Kconfig"
662
663During CMake processing of each Zephyr module, the following variables are
664also available:
665
666- the current module's name: ``${ZEPHYR_CURRENT_MODULE_NAME}``
667- the current module's top level directory: ``${ZEPHYR_CURRENT_MODULE_DIR}``
668- the current module's :file:`CMakeLists.txt` directory: ``${ZEPHYR_CURRENT_CMAKE_DIR}``
669
670This removes the need for a Zephyr module to know its own name during CMake
671processing. The module can source additional CMake files using these ``CURRENT``
672variables. For example:
673
674.. code-block:: cmake
675
676  include(${ZEPHYR_CURRENT_MODULE_DIR}/cmake/code.cmake)
677
678It is possible to append values to a Zephyr `CMake list`_ variable from the module's first
679CMakeLists.txt file.
680To do so, append the value to the list and then set the list in the PARENT_SCOPE
681of the CMakeLists.txt file. For example, to append ``bar`` to the ``FOO_LIST`` variable in the
682Zephyr CMakeLists.txt scope:
683
684.. code-block:: cmake
685
686  list(APPEND FOO_LIST bar)
687  set(FOO_LIST ${FOO_LIST} PARENT_SCOPE)
688
689An example of a Zephyr list where this is useful is when adding additional
690directories to the ``SYSCALL_INCLUDE_DIRS`` list.
691
692Sysbuild modules
693----------------
694
695In both Kconfig and CMake, the variable ``SYSBUILD_CURRENT_MODULE_DIR``
696contains the absolute path to the sysbuild module. In CMake,
697``SYSBUILD_CURRENT_CMAKE_DIR`` contains the absolute path to the directory
698containing the :file:`CMakeLists.txt` file that is included into CMake build
699system. This variable's value is empty if the module.yml file does not specify
700a CMakeLists.txt.
701
702To read these variables for a sysbuild module:
703
704- In CMake: use ``${SYSBUILD_CURRENT_MODULE_DIR}`` for the module's top level
705  directory, and ``${SYSBUILD_CURRENT_CMAKE_DIR}`` for the directory containing
706  its :file:`CMakeLists.txt`
707- In Kconfig: use ``$(SYSBUILD_CURRENT_MODULE_DIR)`` for the module's top level
708  directory
709
710In Kconfig, the variable may be used to find additional files to include.
711For example, to include the file :file:`some/Kconfig`:
712
713.. code-block:: kconfig
714
715  source "$(SYSBUILD_CURRENT_MODULE_DIR)/some/Kconfig"
716
717The module can source additional CMake files using these variables. For
718example:
719
720.. code-block:: cmake
721
722  include(${SYSBUILD_CURRENT_MODULE_DIR}/cmake/code.cmake)
723
724It is possible to append values to a Zephyr `CMake list`_ variable from the
725module's first CMakeLists.txt file.
726To do so, append the value to the list and then set the list in the
727PARENT_SCOPE of the CMakeLists.txt file. For example, to append ``bar`` to the
728``FOO_LIST`` variable in the Zephyr CMakeLists.txt scope:
729
730.. code-block:: cmake
731
732  list(APPEND FOO_LIST bar)
733  set(FOO_LIST ${FOO_LIST} PARENT_SCOPE)
734
735Sysbuild modules hooks
736----------------------
737
738Sysbuild provides an infrastructure which allows a sysbuild module to define
739a function which will be invoked by sysbuild at a pre-defined point in the
740CMake flow.
741
742Functions invoked by sysbuild:
743
744- ``<module-name>_pre_cmake(IMAGES <images>)``: This function is called for each
745  sysbuild module before CMake configure is invoked for all images.
746- ``<module-name>_post_cmake(IMAGES <images>)``: This function is called for each
747  sysbuild module after CMake configure has completed for all images.
748- ``<module-name>_pre_domains(IMAGES <images>)``: This function is called for each
749  sysbuild module before domains yaml is created by sysbuild.
750- ``<module-name>_post_domains(IMAGES <images>)``: This function is called for each
751  sysbuild module after domains yaml has been created by sysbuild.
752
753arguments passed from sysbuild to the function defined by a module:
754
755- ``<images>`` is the list of Zephyr images that will be created by the build system.
756
757If a module ``foo`` want to provide a post CMake configure function, then the
758module's sysbuild :file:`CMakeLists.txt` file must define function ``foo_post_cmake()``.
759
760To facilitate naming of functions, the module name is provided by sysbuild CMake
761through the ``SYSBUILD_CURRENT_MODULE_NAME`` CMake variable when loading the
762module's sysbuild :file:`CMakeLists.txt` file.
763
764Example of how the ``foo`` sysbuild module can define ``foo_post_cmake()``:
765
766.. code-block:: cmake
767
768   function(${SYSBUILD_CURRENT_MODULE_NAME}_post_cmake)
769     cmake_parse_arguments(POST_CMAKE "" "" "IMAGES" ${ARGN})
770
771     message("Invoking ${CMAKE_CURRENT_FUNCTION}. Images: ${POST_CMAKE_IMAGES}")
772   endfunction()
773
774Zephyr module dependencies
775==========================
776
777A Zephyr module may be dependent on other Zephyr modules to be present in order
778to function correctly. Or it might be that a given Zephyr module must be
779processed after another Zephyr module, due to dependencies of certain CMake
780targets.
781
782Such a dependency can be described using the ``depends`` field.
783
784.. code-block:: yaml
785
786   build:
787     depends:
788       - <module>
789
790Here is an example for the Zephyr module ``foo`` that is dependent on the Zephyr
791module ``bar`` to be present in the build system:
792
793.. code-block:: yaml
794
795   name: foo
796   build:
797     depends:
798       - bar
799
800This example will ensure that ``bar`` is present when ``foo`` is included into
801the build system, and it will also ensure that ``bar`` is processed before
802``foo``.
803
804.. _modules_module_ext_root:
805
806Module integration files (external)
807===================================
808
809Module integration files can be located externally to the Zephyr module itself.
810The ``MODULE_EXT_ROOT`` variable holds a list of roots containing integration
811files located externally to Zephyr modules.
812
813Module integration files in Zephyr
814----------------------------------
815
816The Zephyr repository contain :file:`CMakeLists.txt` and :file:`Kconfig` build
817files for certain known Zephyr modules.
818
819Those files are located under
820
821.. code-block:: none
822
823   <ZEPHYR_BASE>
824   └── modules
825       └── <module_name>
826           ├── CMakeLists.txt
827           └── Kconfig
828
829Module integration files in a custom location
830---------------------------------------------
831
832You can create a similar ``MODULE_EXT_ROOT`` for additional modules, and make
833those modules known to Zephyr build system.
834
835Create a ``MODULE_EXT_ROOT`` with the following structure
836
837.. code-block:: none
838
839   <MODULE_EXT_ROOT>
840   └── modules
841       ├── modules.cmake
842       └── <module_name>
843           ├── CMakeLists.txt
844           └── Kconfig
845
846and then build your application by specifying ``-DMODULE_EXT_ROOT`` parameter to
847the CMake build system. The ``MODULE_EXT_ROOT`` accepts a `CMake list`_ of roots as
848argument.
849
850A Zephyr module can automatically be added to the ``MODULE_EXT_ROOT``
851list using the module description file :file:`zephyr/module.yml`, see
852:ref:`modules_build_settings`.
853
854.. note::
855
856   ``ZEPHYR_BASE`` is always added as a ``MODULE_EXT_ROOT`` with the lowest
857   priority.
858   This allows you to overrule any integration files under
859   ``<ZEPHYR_BASE>/modules/<module_name>`` with your own implementation your own
860   ``MODULE_EXT_ROOT``.
861
862The :file:`modules.cmake` file must contain the logic that specifies the
863integration files for Zephyr modules via specifically named CMake variables.
864
865To include a module's CMake file, set the variable ``ZEPHYR_<MODULE_NAME>_CMAKE_DIR``
866to the path containing the CMake file.
867
868To include a module's Kconfig file, set the variable ``ZEPHYR_<MODULE_NAME>_KCONFIG``
869to the path to the Kconfig file.
870
871The following is an example on how to add support the ``FOO`` module.
872
873Create the following structure
874
875.. code-block:: none
876
877   <MODULE_EXT_ROOT>
878   └── modules
879       ├── modules.cmake
880       └── foo
881           ├── CMakeLists.txt
882           └── Kconfig
883
884and inside the :file:`modules.cmake` file, add the following content
885
886.. code-block:: cmake
887
888   set(ZEPHYR_FOO_CMAKE_DIR ${CMAKE_CURRENT_LIST_DIR}/foo)
889   set(ZEPHYR_FOO_KCONFIG   ${CMAKE_CURRENT_LIST_DIR}/foo/Kconfig)
890
891Module integration files (zephyr/module.yml)
892--------------------------------------------
893
894The module description file :file:`zephyr/module.yml` can be used to specify
895that the build files, :file:`CMakeLists.txt` and :file:`Kconfig`, are located
896in a :ref:`modules_module_ext_root`.
897
898Build files located in a ``MODULE_EXT_ROOT`` can be described as:
899
900.. code-block:: yaml
901
902   build:
903     cmake-ext: True
904     kconfig-ext: True
905
906This allows control of the build inclusion to be described externally to the
907Zephyr module.
908
909The Zephyr repository itself is always added as a Zephyr module ext root.
910
911.. _modules_build_settings:
912
913Build settings
914==============
915
916It is possible to specify additional build settings that must be used when
917including the module into the build system.
918
919All ``root`` settings are relative to the root of the module.
920
921Build settings supported in the :file:`module.yml` file are:
922
923- ``board_root``: Contains additional boards that are available to the build
924  system. Additional boards must be located in a :file:`<board_root>/boards`
925  folder.
926- ``dts_root``: Contains additional dts files related to the architecture/soc
927  families. Additional dts files must be located in a :file:`<dts_root>/dts`
928  folder.
929- ``snippet_root``: Contains additional snippets that are available for use.
930  These snippets must be defined in :file:`snippet.yml` files underneath the
931  :file:`<snippet_root>/snippets` folder. For example, if you have
932  ``snippet_root: foo``, then you should place your module's
933  :file:`snippet.yml` files in :file:`<your-module>/foo/snippets` or any
934  nested subdirectory.
935- ``soc_root``: Contains additional SoCs that are available to the build
936  system. Additional SoCs must be located in a :file:`<soc_root>/soc` folder.
937- ``arch_root``: Contains additional architectures that are available to the
938  build system. Additional architectures must be located in a
939  :file:`<arch_root>/arch` folder.
940- ``module_ext_root``: Contains :file:`CMakeLists.txt` and :file:`Kconfig` files
941  for Zephyr modules, see also :ref:`modules_module_ext_root`.
942- ``sca_root``: Contains additional :ref:`SCA <sca>` tool implementations
943  available to the build system. Each tool must be located in
944  :file:`<sca_root>/sca/<tool>` folder. The folder must contain a
945  :file:`sca.cmake`.
946
947Example of a :file:`module.yaml` file containing additional roots, and the
948corresponding file system layout.
949
950.. code-block:: yaml
951
952   build:
953     settings:
954       board_root: .
955       dts_root: .
956       soc_root: .
957       arch_root: .
958       module_ext_root: .
959
960
961requires the following folder structure:
962
963.. code-block:: none
964
965   <zephyr-module-root>
966   ├── arch
967   ├── boards
968   ├── dts
969   ├── modules
970   └── soc
971
972Twister (Test Runner)
973=====================
974
975To execute both tests and samples available in modules, the Zephyr test runner
976(twister) should be pointed to the directories containing those samples and
977tests. This can be done by specifying the path to both samples and tests in the
978:file:`zephyr/module.yml` file.  Additionally, if a module defines out of tree
979boards, the module file can point twister to the path where those files
980are maintained in the module. For example:
981
982
983.. code-block:: yaml
984
985    build:
986      cmake: .
987    samples:
988      - samples
989    tests:
990      - tests
991    boards:
992      - boards
993
994.. _modules-bin-blobs:
995
996Binary Blobs
997============
998
999Zephyr supports fetching and using :ref:`binary blobs <bin-blobs>`, and their
1000metadata is contained entirely in :file:`zephyr/module.yml`. This is because
1001a binary blob must always be associated with a Zephyr module, and thus the
1002blob metadata belongs in the module's description itself.
1003
1004Binary blobs are fetched using :ref:`west blobs <west-blobs>`.  If ``west`` is
1005:ref:`not used <modules_without_west>`, they must be downloaded and
1006verified manually.
1007
1008The ``blobs`` section in :file:`zephyr/module.yml` consists of a sequence of
1009maps, each of which has the following entries:
1010
1011- ``path``: The path to the binary blob, relative to the :file:`zephyr/blobs/`
1012  folder in the module repository
1013- ``sha256``: `SHA-256 <https://en.wikipedia.org/wiki/SHA-2>`_ checksum of the
1014  binary blob file
1015- ``type``: The :ref:`type of binary blob <bin-blobs-types>`. Currently limited
1016  to ``img`` or ``lib``
1017- ``version``: A version string
1018- ``license-path``: Path to the license file for this blob, relative to the root
1019  of the module repository
1020- ``url``: URL that identifies the location the blob will be fetched from, as
1021  well as the fetching scheme to use
1022- ``description``: Human-readable description of the binary blob
1023- ``doc-url``: A URL pointing to the location of the official documentation for
1024  this blob
1025
1026Package manager dependencies
1027============================
1028
1029Zephyr modules can describe dependencies available from package managers,
1030currently only ``pip`` is supported.
1031
1032A west extension command ``west packages <manager>`` is available to list
1033dependencies for Zephyr and present modules that leverage this feature in their
1034``module.yml`` file.
1035Run ``west help packages`` for more details.
1036
1037Python pip
1038----------
1039
1040Calling ``west packages pip`` lists `requirement files`_ for Zephyr and modules.
1041Passing ``--install`` installs these if there's an active virtual environment.
1042
1043The following example demonstrates a ``zephyr/module.yml`` file with some
1044requirement files in the ``scripts`` directory of the module.
1045
1046
1047.. code-block:: yaml
1048
1049    package-managers:
1050      pip:
1051        requirement-files:
1052          - scripts/requirements-build.txt
1053          - scripts/requirements-doc.txt
1054
1055
1056.. _modules-runners:
1057
1058External Runners
1059================
1060
1061If a module has out of tree boards that require custom :ref:`runners <west-runner>`,
1062then it can add a list to its ``zephyr/module.yml`` file, for example:
1063
1064
1065.. code-block:: yaml
1066
1067    runners:
1068      - file: scripts/my-runner.py
1069
1070
1071Each file entry is imported when executing ``west flash`` or ``west debug`` and
1072subclasses of the ``ZephyrBinaryRunner`` are registered for use.
1073
1074Module Inclusion
1075================
1076
1077.. _modules_using_west:
1078
1079Using West
1080----------
1081
1082If west is installed and :makevar:`ZEPHYR_MODULES` is not already set, the
1083build system finds all the modules in your :term:`west installation` and uses
1084those. It does this by running :ref:`west list <west-built-in-misc>` to get
1085the paths of all the projects in the installation, then filters the results to
1086just those projects which have the necessary module metadata files.
1087
1088Each project in the ``west list`` output is tested like this:
1089
1090- If the project contains a file named :file:`zephyr/module.yml`, then the
1091  content of that file will be used to determine which files should be added
1092  to the build, as described in the previous section.
1093
1094- Otherwise (i.e. if the project has no :file:`zephyr/module.yml`), the
1095  build system looks for :file:`zephyr/CMakeLists.txt` and
1096  :file:`zephyr/Kconfig` files in the project. If both are present, the project
1097  is considered a module, and those files will be added to the build.
1098
1099- If neither of those checks succeed, the project is not considered a module,
1100  and is not added to :makevar:`ZEPHYR_MODULES`.
1101
1102.. _modules_without_west:
1103
1104Without West
1105------------
1106
1107If you don't have west installed or don't want the build system to use it to
1108find Zephyr modules, you can set :makevar:`ZEPHYR_MODULES` yourself using one
1109of the following options. Each of the directories in the list must contain
1110either a :file:`zephyr/module.yml` file or the files
1111:file:`zephyr/CMakeLists.txt` and :file:`Kconfig`, as described in the previous
1112section.
1113
1114#. At the CMake command line, like this:
1115
1116   .. code-block:: console
1117
1118      cmake -DZEPHYR_MODULES=<path-to-module1>[;<path-to-module2>[...]] ...
1119
1120#. At the top of your application's top level :file:`CMakeLists.txt`, like this:
1121
1122   .. code-block:: cmake
1123
1124      set(ZEPHYR_MODULES <path-to-module1> <path-to-module2> [...])
1125      find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
1126
1127   If you choose this option, make sure to set the variable **before**  calling
1128   ``find_package(Zephyr ...)``, as shown above.
1129
1130#. In a separate CMake script which is pre-loaded to populate the CMake cache,
1131   like this:
1132
1133   .. code-block:: cmake
1134
1135      # Put this in a file with a name like "zephyr-modules.cmake"
1136      set(ZEPHYR_MODULES <path-to-module1> <path-to-module2>
1137        CACHE STRING "pre-cached modules")
1138
1139   You can tell the build system to use this file by adding ``-C
1140   zephyr-modules.cmake`` to your CMake command line.
1141
1142Not using modules
1143-----------------
1144
1145If you don't have west installed and don't specify :makevar:`ZEPHYR_MODULES`
1146yourself, then no additional modules are added to the build. You will still be
1147able to build any applications that don't require code or Kconfig options
1148defined in an external repository.
1149
1150Submitting changes to modules
1151******************************
1152
1153When submitting new or making changes to existing modules the main repository
1154Zephyr needs a reference to the changes to be able to verify the changes. In the
1155main tree this is done using revisions. For code that is already merged and part
1156of the tree we use the commit hash, a tag, or a branch name. For pull requests
1157however, we require specifying the pull request number in the revision field to
1158allow building the zephyr main tree with the changes submitted to the
1159module.
1160
1161To avoid merging changes to master with pull request information, the pull
1162request should be marked as ``DNM`` (Do Not Merge) or preferably a draft pull
1163request to make sure it is not merged by mistake and to allow for the module to
1164be merged first and be assigned a permanent commit hash. Drafts reduce noise by
1165not automatically notifying anyone until marked as "Ready for review".
1166Once the module is
1167merged, the revision will need to be changed either by the submitter or by the
1168maintainer to the commit hash of the module which reflects the changes.
1169
1170Note that multiple and dependent changes to different modules can be submitted
1171using exactly the same process. In this case you will change multiple entries of
1172all modules that have a pull request against them.
1173
1174.. _submitting_new_modules:
1175
1176Process for submitting a new module
1177===================================
1178
1179Please follow the process in :ref:`external-src-process` and obtain the TSC
1180approval to integrate the external source code as a module
1181
1182If the request is approved, a new repository will
1183created by the project team and initialized with basic information that would
1184allow submitting code to the module project following the project contribution
1185guidelines.
1186
1187If a module is maintained as a fork of another project on Github, the Zephyr
1188module related files and changes in relation to upstream need to be maintained
1189in a special branch named ``zephyr``.
1190
1191Maintainers from the Zephyr project will create the repository and initialize
1192it. You will be added as a collaborator in the new repository.  Submit the
1193module content (code) to the new repository following the guidelines described
1194:ref:`here <modules_using_west>`, and then add a new entry to the
1195:zephyr_file:`west.yml` with the following information:
1196
1197   .. code-block:: console
1198
1199        - name: <name of repository>
1200          path: <path to where the repository should be cloned>
1201          revision: <ref pointer to module pull request>
1202
1203
1204For example, to add *my_module* to the manifest:
1205
1206.. code-block:: console
1207
1208    - name: my_module
1209      path: modules/lib/my_module
1210      revision: pull/23/head
1211
1212
1213Where 23 in the example above indicated the pull request number submitted to the
1214*my_module* repository. Once the module changes are reviewed and merged, the
1215revision needs to be changed to the commit hash from the module repository.
1216
1217.. _changes_to_existing_module:
1218
1219Process for submitting changes to existing modules
1220==================================================
1221
1222#. Submit the changes using a pull request to an existing repository following
1223   the :ref:`contribution guidelines <contribute_guidelines>` and
1224   :ref:`expectations <contributor-expectations>`.
1225#. Submit a pull request changing the entry referencing the module into the
1226   :zephyr_file:`west.yml` of the main Zephyr tree with the following
1227   information:
1228
1229   .. code-block:: console
1230
1231        - name: <name of repository>
1232          path: <path to where the repository should be cloned>
1233          revision: <ref pointer to module pull request>
1234
1235
1236For example, to add *my_module* to the manifest:
1237
1238.. code-block:: console
1239
1240    - name: my_module
1241      path: modules/lib/my_module
1242      revision: pull/23/head
1243
1244Where 23 in the example above indicated the pull request number submitted to the
1245*my_module* repository. Once the module changes are reviewed and merged, the
1246revision needs to be changed to the commit hash from the module repository.
1247
1248
1249
1250.. _CMake list: https://cmake.org/cmake/help/latest/manual/cmake-language.7.html#lists
1251.. _add_subdirectory(): https://cmake.org/cmake/help/latest/command/add_subdirectory.html
1252.. _GitHub issues: https://github.com/zephyrproject-rtos/zephyr/issues
1253.. _requirement files: https://pip.pypa.io/en/stable/reference/requirements-file-format/
1254