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
428useful if you want to keep the list of modules found with west and also add
429your own.
430
431.. note::
432   If the module ``FOO`` is provided by :ref:`west <west>` but also given with
433   ``-DEXTRA_ZEPHYR_MODULES=/<path>/foo`` then the module given by the command
434   line variable :makevar:`EXTRA_ZEPHYR_MODULES` will take precedence.
435   This allows you to use a custom version of ``FOO`` when building and still
436   use other Zephyr modules provided by :ref:`west <west>`.
437   This can for example be useful for special test purposes.
438
439If you want to permanently add modules to the zephyr workspace and you are
440using zephyr as your manifest repository, you can also add a west manifest file
441into the :zephyr_file:`submanifests` directory. See
442:zephyr_file:`submanifests/README.txt` for more details.
443
444See :ref:`west-basics` for more on west workspaces.
445
446Finally, you can also specify the list of modules yourself in various ways, or
447not use modules at all if your application doesn't need them.
448
449.. _module-yml:
450
451Module yaml file description
452****************************
453
454A module can be described using a file named :file:`zephyr/module.yml`.
455The format of :file:`zephyr/module.yml` is described in the following:
456
457Module name
458===========
459
460Each Zephyr module is given a name by which it can be referred to in the build
461system.
462
463The name should be specified in the :file:`zephyr/module.yml` file. This will
464ensure the module name is not changeable through user-defined directory names
465or ``west`` manifest files:
466
467.. code-block:: yaml
468
469   name: <name>
470
471In CMake the location of the Zephyr module can then be referred to using the
472CMake variable ``ZEPHYR_<MODULE_NAME>_MODULE_DIR`` and the variable
473``ZEPHYR_<MODULE_NAME>_CMAKE_DIR`` holds the location of the directory
474containing the module's :file:`CMakeLists.txt` file.
475
476.. note::
477   When used for CMake and Kconfig variables, all letters in module names are
478   converted to uppercase and all non-alphanumeric characters are converted
479   to underscores (_).
480   As example, the module ``foo-bar`` must be referred to as
481   ``ZEPHYR_FOO_BAR_MODULE_DIR`` in CMake and Kconfig.
482
483Here is an example for the Zephyr module ``foo``:
484
485.. code-block:: yaml
486
487   name: foo
488
489.. note::
490   If the ``name`` field is not specified then the Zephyr module name will be
491   set to the name of the module folder.
492   As example, the Zephyr module located in :file:`<workspace>/modules/bar` will
493   use ``bar`` as its module name if nothing is specified in
494   :file:`zephyr/module.yml`.
495
496Module integration files (in-module)
497====================================
498
499Inclusion of build files, :file:`CMakeLists.txt` and :file:`Kconfig`, can be
500described as:
501
502.. code-block:: yaml
503
504   build:
505     cmake: <cmake-directory>
506     kconfig: <directory>/Kconfig
507
508The ``cmake: <cmake-directory>`` part specifies that
509:file:`<cmake-directory>` contains the :file:`CMakeLists.txt` to use. The
510``kconfig: <directory>/Kconfig`` part specifies the Kconfig file to use.
511Neither is required: ``cmake`` defaults to ``zephyr``, and ``kconfig``
512defaults to ``zephyr/Kconfig``.
513
514Here is an example :file:`module.yml` file referring to
515:file:`CMakeLists.txt` and :file:`Kconfig` files in the root directory of the
516module:
517
518.. code-block:: yaml
519
520   build:
521     cmake: .
522     kconfig: Kconfig
523
524.. _sysbuild_module_integration:
525
526Sysbuild integration
527====================
528
529:ref:`Sysbuild<sysbuild>` is the Zephyr build system that allows for building
530multiple images as part of a single application, the sysbuild build process
531can be extended externally with modules as needed, for example to add custom
532build steps or add additional targets to a build. Inclusion of
533sysbuild-specific build files, :file:`CMakeLists.txt` and :file:`Kconfig`, can
534be described as:
535
536.. code-block:: yaml
537
538   build:
539     sysbuild-cmake: <cmake-directory>
540     sysbuild-kconfig: <directory>/Kconfig
541
542The ``sysbuild-cmake: <cmake-directory>`` part specifies that
543:file:`<cmake-directory>` contains the :file:`CMakeLists.txt` to use. The
544``sysbuild-kconfig: <directory>/Kconfig`` part specifies the Kconfig file to
545use.
546
547Here is an example :file:`module.yml` file referring to
548:file:`CMakeLists.txt` and :file:`Kconfig` files in the ``sysbuild`` directory of
549the module:
550
551.. code-block:: yaml
552
553   build:
554     sysbuild-cmake: sysbuild
555     sysbuild-kconfig: sysbuild/Kconfig
556
557The module description file :file:`zephyr/module.yml` can also be used to
558specify that the build files, :file:`CMakeLists.txt` and :file:`Kconfig`, are
559located in a :ref:`modules_module_ext_root`.
560
561Build files located in a ``MODULE_EXT_ROOT`` can be described as:
562
563.. code-block:: yaml
564
565   build:
566     sysbuild-cmake-ext: True
567     sysbuild-kconfig-ext: True
568
569This allows control of the build inclusion to be described externally to the
570Zephyr module.
571
572.. _modules-vulnerability-monitoring:
573
574Vulnerability monitoring
575========================
576
577The module description file :file:`zephyr/module.yml` can be used to improve vulnerability monitoring.
578
579If your module needs to track vulnerabilities using an external reference
580(e.g your module is forked from another repository), you can use the ``security`` section.
581It contains the field ``external-references`` that contains a list of references that needs to
582be monitored for your module. The supported formats are:
583
584- CPE (Common Platform Enumeration)
585- PURL (Package URL)
586
587.. code-block:: yaml
588
589   security:
590     external-references:
591       - <module-related-cpe>
592       - <an-other-module-related-cpe>
593       - <module-related-purl>
594
595A real life example for ``mbedTLS`` module could look like this:
596
597.. code-block:: yaml
598
599   security:
600     external-references:
601       - cpe:2.3:a:arm:mbed_tls:3.5.2:*:*:*:*:*:*:*
602       - pkg:github/Mbed-TLS/mbedtls@V3.5.2
603
604.. note::
605   CPE field must follow the CPE 2.3 schema provided by `NVD
606   <https://csrc.nist.gov/projects/security-content-automation-protocol/specifications/cpe>`_.
607   PURL field must follow the PURL specification provided by `Github
608   <https://github.com/package-url/purl-spec/blob/master/PURL-SPECIFICATION.rst>`_.
609
610
611Build system integration
612========================
613
614When a module has a :file:`module.yml` file, it will automatically be included into
615the Zephyr build system. The path to the module is then accessible through Kconfig
616and CMake variables.
617
618Zephyr modules
619--------------
620
621In both Kconfig and CMake, the variable ``ZEPHYR_<MODULE_NAME>_MODULE_DIR``
622contains the absolute path to the module.
623
624Additionally, ``ZEPHYR_<MODULE_NAME>_MODULE`` and ``ZEPHYR_<MODULE_NAME>_MODULE_BLOBS``
625(in case the module declares blobs) symbols are automatically generated for available
626modules. These can be used e.g. to declare dependencies from other Kconfig symbols
627which depend on the module or blobs from the module. To satisfy compliance checking
628when building Zephyr without the module present, it's recommended for the module to
629have default definitions for these symbols in its respective Kconfig file under
630``modules/`` in the Zephyr main tree.
631
632In CMake, ``ZEPHYR_<MODULE_NAME>_CMAKE_DIR`` contains the
633absolute path to the directory containing the :file:`CMakeLists.txt` file that
634is included into CMake build system. This variable's value is empty if the
635module.yml file does not specify a CMakeLists.txt.
636
637To read these variables for a Zephyr module named ``foo``:
638
639- 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`
640- In Kconfig: use ``$(ZEPHYR_FOO_MODULE_DIR)`` for the module's top level directory
641
642Notice how a lowercase module name ``foo`` is capitalized to ``FOO``
643in both CMake and Kconfig.
644
645These variables can also be used to test whether a given module exists.
646For example, to verify that ``foo`` is the name of a Zephyr module:
647
648.. code-block:: cmake
649
650  if(ZEPHYR_FOO_MODULE_DIR)
651    # Do something if FOO exists.
652  endif()
653
654In Kconfig, the variable may be used to find additional files to include.
655For example, to include the file :file:`some/Kconfig` in module ``foo``:
656
657.. code-block:: kconfig
658
659  source "$(ZEPHYR_FOO_MODULE_DIR)/some/Kconfig"
660
661During CMake processing of each Zephyr module, the following variables are
662also available:
663
664- the current module's name: ``${ZEPHYR_CURRENT_MODULE_NAME}``
665- the current module's top level directory: ``${ZEPHYR_CURRENT_MODULE_DIR}``
666- the current module's :file:`CMakeLists.txt` directory: ``${ZEPHYR_CURRENT_CMAKE_DIR}``
667
668This removes the need for a Zephyr module to know its own name during CMake
669processing. The module can source additional CMake files using these ``CURRENT``
670variables. For example:
671
672.. code-block:: cmake
673
674  include(${ZEPHYR_CURRENT_MODULE_DIR}/cmake/code.cmake)
675
676It is possible to append values to a Zephyr `CMake list`_ variable from the module's first
677CMakeLists.txt file.
678To do so, append the value to the list and then set the list in the PARENT_SCOPE
679of the CMakeLists.txt file. For example, to append ``bar`` to the ``FOO_LIST`` variable in the
680Zephyr CMakeLists.txt scope:
681
682.. code-block:: cmake
683
684  list(APPEND FOO_LIST bar)
685  set(FOO_LIST ${FOO_LIST} PARENT_SCOPE)
686
687An example of a Zephyr list where this is useful is when adding additional
688directories to the ``SYSCALL_INCLUDE_DIRS`` list.
689
690Sysbuild modules
691----------------
692
693In both Kconfig and CMake, the variable ``SYSBUILD_CURRENT_MODULE_DIR``
694contains the absolute path to the sysbuild module. In CMake,
695``SYSBUILD_CURRENT_CMAKE_DIR`` contains the absolute path to the directory
696containing the :file:`CMakeLists.txt` file that is included into CMake build
697system. This variable's value is empty if the module.yml file does not specify
698a CMakeLists.txt.
699
700To read these variables for a sysbuild module:
701
702- In CMake: use ``${SYSBUILD_CURRENT_MODULE_DIR}`` for the module's top level
703  directory, and ``${SYSBUILD_CURRENT_CMAKE_DIR}`` for the directory containing
704  its :file:`CMakeLists.txt`
705- In Kconfig: use ``$(SYSBUILD_CURRENT_MODULE_DIR)`` for the module's top level
706  directory
707
708In Kconfig, the variable may be used to find additional files to include.
709For example, to include the file :file:`some/Kconfig`:
710
711.. code-block:: kconfig
712
713  source "$(SYSBUILD_CURRENT_MODULE_DIR)/some/Kconfig"
714
715The module can source additional CMake files using these variables. For
716example:
717
718.. code-block:: cmake
719
720  include(${SYSBUILD_CURRENT_MODULE_DIR}/cmake/code.cmake)
721
722It is possible to append values to a Zephyr `CMake list`_ variable from the
723module's first CMakeLists.txt file.
724To do so, append the value to the list and then set the list in the
725PARENT_SCOPE of the CMakeLists.txt file. For example, to append ``bar`` to the
726``FOO_LIST`` variable in the Zephyr CMakeLists.txt scope:
727
728.. code-block:: cmake
729
730  list(APPEND FOO_LIST bar)
731  set(FOO_LIST ${FOO_LIST} PARENT_SCOPE)
732
733Sysbuild modules hooks
734----------------------
735
736Sysbuild provides an infrastructure which allows a sysbuild module to define
737a function which will be invoked by sysbuild at a pre-defined point in the
738CMake flow.
739
740Functions invoked by sysbuild:
741
742- ``<module-name>_pre_cmake(IMAGES <images>)``: This function is called for each
743  sysbuild module before CMake configure is invoked for all images.
744- ``<module-name>_post_cmake(IMAGES <images>)``: This function is called for each
745  sysbuild module after CMake configure has completed for all images.
746- ``<module-name>_pre_domains(IMAGES <images>)``: This function is called for each
747  sysbuild module before domains yaml is created by sysbuild.
748- ``<module-name>_post_domains(IMAGES <images>)``: This function is called for each
749  sysbuild module after domains yaml has been created by sysbuild.
750
751arguments passed from sysbuild to the function defined by a module:
752
753- ``<images>`` is the list of Zephyr images that will be created by the build system.
754
755If a module ``foo`` want to provide a post CMake configure function, then the
756module's sysbuild :file:`CMakeLists.txt` file must define function ``foo_post_cmake()``.
757
758To facilitate naming of functions, the module name is provided by sysbuild CMake
759through the ``SYSBUILD_CURRENT_MODULE_NAME`` CMake variable when loading the
760module's sysbuild :file:`CMakeLists.txt` file.
761
762Example of how the ``foo`` sysbuild module can define ``foo_post_cmake()``:
763
764.. code-block:: cmake
765
766   function(${SYSBUILD_CURRENT_MODULE_NAME}_post_cmake)
767     cmake_parse_arguments(POST_CMAKE "" "" "IMAGES" ${ARGN})
768
769     message("Invoking ${CMAKE_CURRENT_FUNCTION}. Images: ${POST_CMAKE_IMAGES}")
770   endfunction()
771
772Zephyr module dependencies
773==========================
774
775A Zephyr module may be dependent on other Zephyr modules to be present in order
776to function correctly. Or it might be that a given Zephyr module must be
777processed after another Zephyr module, due to dependencies of certain CMake
778targets.
779
780Such a dependency can be described using the ``depends`` field.
781
782.. code-block:: yaml
783
784   build:
785     depends:
786       - <module>
787
788Here is an example for the Zephyr module ``foo`` that is dependent on the Zephyr
789module ``bar`` to be present in the build system:
790
791.. code-block:: yaml
792
793   name: foo
794   build:
795     depends:
796       - bar
797
798This example will ensure that ``bar`` is present when ``foo`` is included into
799the build system, and it will also ensure that ``bar`` is processed before
800``foo``.
801
802.. _modules_module_ext_root:
803
804Module integration files (external)
805===================================
806
807Module integration files can be located externally to the Zephyr module itself.
808The ``MODULE_EXT_ROOT`` variable holds a list of roots containing integration
809files located externally to Zephyr modules.
810
811Module integration files in Zephyr
812----------------------------------
813
814The Zephyr repository contain :file:`CMakeLists.txt` and :file:`Kconfig` build
815files for certain known Zephyr modules.
816
817Those files are located under
818
819.. code-block:: none
820
821   <ZEPHYR_BASE>
822   └── modules
823       └── <module_name>
824           ├── CMakeLists.txt
825           └── Kconfig
826
827Module integration files in a custom location
828---------------------------------------------
829
830You can create a similar ``MODULE_EXT_ROOT`` for additional modules, and make
831those modules known to Zephyr build system.
832
833Create a ``MODULE_EXT_ROOT`` with the following structure
834
835.. code-block:: none
836
837   <MODULE_EXT_ROOT>
838   └── modules
839       ├── modules.cmake
840       └── <module_name>
841           ├── CMakeLists.txt
842           └── Kconfig
843
844and then build your application by specifying ``-DMODULE_EXT_ROOT`` parameter to
845the CMake build system. The ``MODULE_EXT_ROOT`` accepts a `CMake list`_ of roots as
846argument.
847
848A Zephyr module can automatically be added to the ``MODULE_EXT_ROOT``
849list using the module description file :file:`zephyr/module.yml`, see
850:ref:`modules_build_settings`.
851
852.. note::
853
854   ``ZEPHYR_BASE`` is always added as a ``MODULE_EXT_ROOT`` with the lowest
855   priority.
856   This allows you to overrule any integration files under
857   ``<ZEPHYR_BASE>/modules/<module_name>`` with your own implementation your own
858   ``MODULE_EXT_ROOT``.
859
860The :file:`modules.cmake` file must contain the logic that specifies the
861integration files for Zephyr modules via specifically named CMake variables.
862
863To include a module's CMake file, set the variable ``ZEPHYR_<MODULE_NAME>_CMAKE_DIR``
864to the path containing the CMake file.
865
866To include a module's Kconfig file, set the variable ``ZEPHYR_<MODULE_NAME>_KCONFIG``
867to the path to the Kconfig file.
868
869The following is an example on how to add support the ``FOO`` module.
870
871Create the following structure
872
873.. code-block:: none
874
875   <MODULE_EXT_ROOT>
876   └── modules
877       ├── modules.cmake
878       └── foo
879           ├── CMakeLists.txt
880           └── Kconfig
881
882and inside the :file:`modules.cmake` file, add the following content
883
884.. code-block:: cmake
885
886   set(ZEPHYR_FOO_CMAKE_DIR ${CMAKE_CURRENT_LIST_DIR}/foo)
887   set(ZEPHYR_FOO_KCONFIG   ${CMAKE_CURRENT_LIST_DIR}/foo/Kconfig)
888
889Module integration files (zephyr/module.yml)
890--------------------------------------------
891
892The module description file :file:`zephyr/module.yml` can be used to specify
893that the build files, :file:`CMakeLists.txt` and :file:`Kconfig`, are located
894in a :ref:`modules_module_ext_root`.
895
896Build files located in a ``MODULE_EXT_ROOT`` can be described as:
897
898.. code-block:: yaml
899
900   build:
901     cmake-ext: True
902     kconfig-ext: True
903
904This allows control of the build inclusion to be described externally to the
905Zephyr module.
906
907The Zephyr repository itself is always added as a Zephyr module ext root.
908
909.. _modules_build_settings:
910
911Build settings
912==============
913
914It is possible to specify additional build settings that must be used when
915including the module into the build system.
916
917All ``root`` settings are relative to the root of the module.
918
919Build settings supported in the :file:`module.yml` file are:
920
921- ``board_root``: Contains additional boards that are available to the build
922  system. Additional boards must be located in a :file:`<board_root>/boards`
923  folder.
924- ``dts_root``: Contains additional dts files related to the architecture/soc
925  families. Additional dts files must be located in a :file:`<dts_root>/dts`
926  folder.
927- ``snippet_root``: Contains additional snippets that are available for use.
928  These snippets must be defined in :file:`snippet.yml` files underneath the
929  :file:`<snippet_root>/snippets` folder. For example, if you have
930  ``snippet_root: foo``, then you should place your module's
931  :file:`snippet.yml` files in :file:`<your-module>/foo/snippets` or any
932  nested subdirectory.
933- ``soc_root``: Contains additional SoCs that are available to the build
934  system. Additional SoCs must be located in a :file:`<soc_root>/soc` folder.
935- ``arch_root``: Contains additional architectures that are available to the
936  build system. Additional architectures must be located in a
937  :file:`<arch_root>/arch` folder.
938- ``module_ext_root``: Contains :file:`CMakeLists.txt` and :file:`Kconfig` files
939  for Zephyr modules, see also :ref:`modules_module_ext_root`.
940- ``sca_root``: Contains additional :ref:`SCA <sca>` tool implementations
941  available to the build system. Each tool must be located in
942  :file:`<sca_root>/sca/<tool>` folder. The folder must contain a
943  :file:`sca.cmake`.
944
945Example of a :file:`module.yaml` file containing additional roots, and the
946corresponding file system layout.
947
948.. code-block:: yaml
949
950   build:
951     settings:
952       board_root: .
953       dts_root: .
954       soc_root: .
955       arch_root: .
956       module_ext_root: .
957
958
959requires the following folder structure:
960
961.. code-block:: none
962
963   <zephyr-module-root>
964   ├── arch
965   ├── boards
966   ├── dts
967   ├── modules
968   └── soc
969
970Twister (Test Runner)
971=====================
972
973To execute both tests and samples available in modules, the Zephyr test runner
974(twister) should be pointed to the directories containing those samples and
975tests. This can be done by specifying the path to both samples and tests in the
976:file:`zephyr/module.yml` file.  Additionally, if a module defines out of tree
977boards, the module file can point twister to the path where those files
978are maintained in the module. For example:
979
980
981.. code-block:: yaml
982
983    build:
984      cmake: .
985    samples:
986      - samples
987    tests:
988      - tests
989    boards:
990      - boards
991
992.. _modules-bin-blobs:
993
994Binary Blobs
995============
996
997Zephyr supports fetching and using :ref:`binary blobs <bin-blobs>`, and their
998metadata is contained entirely in :file:`zephyr/module.yml`. This is because
999a binary blob must always be associated with a Zephyr module, and thus the
1000blob metadata belongs in the module's description itself.
1001
1002Binary blobs are fetched using :ref:`west blobs <west-blobs>`.  If ``west`` is
1003:ref:`not used <modules_without_west>`, they must be downloaded and
1004verified manually.
1005
1006The ``blobs`` section in :file:`zephyr/module.yml` consists of a sequence of
1007maps, each of which has the following entries:
1008
1009- ``path``: The path to the binary blob, relative to the :file:`zephyr/blobs/`
1010  folder in the module repository
1011- ``sha256``: `SHA-256 <https://en.wikipedia.org/wiki/SHA-2>`_ checksum of the
1012  binary blob file
1013- ``type``: The :ref:`type of binary blob <bin-blobs-types>`. Currently limited
1014  to ``img`` or ``lib``
1015- ``version``: A version string
1016- ``license-path``: Path to the license file for this blob, relative to the root
1017  of the module repository
1018- ``url``: URL that identifies the location the blob will be fetched from, as
1019  well as the fetching scheme to use
1020- ``description``: Human-readable description of the binary blob
1021- ``doc-url``: A URL pointing to the location of the official documentation for
1022  this blob
1023
1024Package manager dependencies
1025============================
1026
1027Zephyr modules can describe dependencies available from package managers,
1028currently only ``pip`` is supported.
1029
1030A west extension command ``west packages <manager>`` is available to list
1031dependencies for Zephyr and present modules that leverage this feature in their
1032``module.yml`` file.
1033Run ``west help packages`` for more details.
1034
1035Python pip
1036----------
1037
1038Calling ``west packages pip`` lists `requirement files`_ for Zephyr and modules.
1039Passing ``--install`` installs these if there's an active virtual environment.
1040
1041The following example demonstrates a ``zephyr/module.yml`` file with some
1042requirement files in the ``scripts`` directory of the module.
1043
1044
1045.. code-block:: yaml
1046
1047    package-managers:
1048      pip:
1049        requirement-files:
1050          - scripts/requirements-build.txt
1051          - scripts/requirements-doc.txt
1052
1053Module Inclusion
1054================
1055
1056.. _modules_using_west:
1057
1058Using West
1059----------
1060
1061If west is installed and :makevar:`ZEPHYR_MODULES` is not already set, the
1062build system finds all the modules in your :term:`west installation` and uses
1063those. It does this by running :ref:`west list <west-built-in-misc>` to get
1064the paths of all the projects in the installation, then filters the results to
1065just those projects which have the necessary module metadata files.
1066
1067Each project in the ``west list`` output is tested like this:
1068
1069- If the project contains a file named :file:`zephyr/module.yml`, then the
1070  content of that file will be used to determine which files should be added
1071  to the build, as described in the previous section.
1072
1073- Otherwise (i.e. if the project has no :file:`zephyr/module.yml`), the
1074  build system looks for :file:`zephyr/CMakeLists.txt` and
1075  :file:`zephyr/Kconfig` files in the project. If both are present, the project
1076  is considered a module, and those files will be added to the build.
1077
1078- If neither of those checks succeed, the project is not considered a module,
1079  and is not added to :makevar:`ZEPHYR_MODULES`.
1080
1081.. _modules_without_west:
1082
1083Without West
1084------------
1085
1086If you don't have west installed or don't want the build system to use it to
1087find Zephyr modules, you can set :makevar:`ZEPHYR_MODULES` yourself using one
1088of the following options. Each of the directories in the list must contain
1089either a :file:`zephyr/module.yml` file or the files
1090:file:`zephyr/CMakeLists.txt` and :file:`Kconfig`, as described in the previous
1091section.
1092
1093#. At the CMake command line, like this:
1094
1095   .. code-block:: console
1096
1097      cmake -DZEPHYR_MODULES=<path-to-module1>[;<path-to-module2>[...]] ...
1098
1099#. At the top of your application's top level :file:`CMakeLists.txt`, like this:
1100
1101   .. code-block:: cmake
1102
1103      set(ZEPHYR_MODULES <path-to-module1> <path-to-module2> [...])
1104      find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
1105
1106   If you choose this option, make sure to set the variable **before**  calling
1107   ``find_package(Zephyr ...)``, as shown above.
1108
1109#. In a separate CMake script which is pre-loaded to populate the CMake cache,
1110   like this:
1111
1112   .. code-block:: cmake
1113
1114      # Put this in a file with a name like "zephyr-modules.cmake"
1115      set(ZEPHYR_MODULES <path-to-module1> <path-to-module2>
1116        CACHE STRING "pre-cached modules")
1117
1118   You can tell the build system to use this file by adding ``-C
1119   zephyr-modules.cmake`` to your CMake command line.
1120
1121Not using modules
1122-----------------
1123
1124If you don't have west installed and don't specify :makevar:`ZEPHYR_MODULES`
1125yourself, then no additional modules are added to the build. You will still be
1126able to build any applications that don't require code or Kconfig options
1127defined in an external repository.
1128
1129Submitting changes to modules
1130******************************
1131
1132When submitting new or making changes to existing modules the main repository
1133Zephyr needs a reference to the changes to be able to verify the changes. In the
1134main tree this is done using revisions. For code that is already merged and part
1135of the tree we use the commit hash, a tag, or a branch name. For pull requests
1136however, we require specifying the pull request number in the revision field to
1137allow building the zephyr main tree with the changes submitted to the
1138module.
1139
1140To avoid merging changes to master with pull request information, the pull
1141request should be marked as ``DNM`` (Do Not Merge) or preferably a draft pull
1142request to make sure it is not merged by mistake and to allow for the module to
1143be merged first and be assigned a permanent commit hash. Drafts reduce noise by
1144not automatically notifying anyone until marked as "Ready for review".
1145Once the module is
1146merged, the revision will need to be changed either by the submitter or by the
1147maintainer to the commit hash of the module which reflects the changes.
1148
1149Note that multiple and dependent changes to different modules can be submitted
1150using exactly the same process. In this case you will change multiple entries of
1151all modules that have a pull request against them.
1152
1153.. _submitting_new_modules:
1154
1155Process for submitting a new module
1156===================================
1157
1158Please follow the process in :ref:`external-src-process` and obtain the TSC
1159approval to integrate the external source code as a module
1160
1161If the request is approved, a new repository will
1162created by the project team and initialized with basic information that would
1163allow submitting code to the module project following the project contribution
1164guidelines.
1165
1166If a module is maintained as a fork of another project on Github, the Zephyr
1167module related files and changes in relation to upstream need to be maintained
1168in a special branch named ``zephyr``.
1169
1170Maintainers from the Zephyr project will create the repository and initialize
1171it. You will be added as a collaborator in the new repository.  Submit the
1172module content (code) to the new repository following the guidelines described
1173:ref:`here <modules_using_west>`, and then add a new entry to the
1174:zephyr_file:`west.yml` with the following information:
1175
1176   .. code-block:: console
1177
1178        - name: <name of repository>
1179          path: <path to where the repository should be cloned>
1180          revision: <ref pointer to module pull request>
1181
1182
1183For example, to add *my_module* to the manifest:
1184
1185.. code-block:: console
1186
1187    - name: my_module
1188      path: modules/lib/my_module
1189      revision: pull/23/head
1190
1191
1192Where 23 in the example above indicated the pull request number submitted to the
1193*my_module* repository. Once the module changes are reviewed and merged, the
1194revision needs to be changed to the commit hash from the module repository.
1195
1196.. _changes_to_existing_module:
1197
1198Process for submitting changes to existing modules
1199==================================================
1200
1201#. Submit the changes using a pull request to an existing repository following
1202   the :ref:`contribution guidelines <contribute_guidelines>` and
1203   :ref:`expectations <contributor-expectations>`.
1204#. Submit a pull request changing the entry referencing the module into the
1205   :zephyr_file:`west.yml` of the main Zephyr tree with the following
1206   information:
1207
1208   .. code-block:: console
1209
1210        - name: <name of repository>
1211          path: <path to where the repository should be cloned>
1212          revision: <ref pointer to module pull request>
1213
1214
1215For example, to add *my_module* to the manifest:
1216
1217.. code-block:: console
1218
1219    - name: my_module
1220      path: modules/lib/my_module
1221      revision: pull/23/head
1222
1223Where 23 in the example above indicated the pull request number submitted to the
1224*my_module* repository. Once the module changes are reviewed and merged, the
1225revision needs to be changed to the commit hash from the module repository.
1226
1227
1228
1229.. _CMake list: https://cmake.org/cmake/help/latest/manual/cmake-language.7.html#lists
1230.. _add_subdirectory(): https://cmake.org/cmake/help/latest/command/add_subdirectory.html
1231.. _GitHub issues: https://github.com/zephyrproject-rtos/zephyr/issues
1232.. _requirement files: https://pip.pypa.io/en/stable/reference/requirements-file-format/
1233