1156 lines
43 KiB
ReStructuredText
1156 lines
43 KiB
ReStructuredText
.. _modules:
|
|
|
|
Modules (External projects)
|
|
############################
|
|
|
|
Zephyr relies on the source code of several externally maintained projects in
|
|
order to avoid reinventing the wheel and to reuse as much well-established,
|
|
mature code as possible when it makes sense. In the context of Zephyr's build
|
|
system those are called *modules*. These modules must be integrated with the
|
|
Zephyr build system, as described in more detail in other sections on
|
|
this page.
|
|
|
|
To be classified as a candidate for being included in the default list of
|
|
modules, an external project is required to have its own life-cycle outside
|
|
the Zephyr Project, that is, reside in its own repository, and have its own
|
|
contribution and maintenance workflow and release process. Zephyr modules
|
|
should not contain code that is written exclusively for Zephyr. Instead,
|
|
such code should be contributed to the main zephyr tree.
|
|
|
|
Modules to be included in the default manifest of the Zephyr project need to
|
|
provide functionality or features endorsed and approved by the project Technical
|
|
Steering Committee and should comply with the
|
|
:ref:`module licensing requirements<modules_licensing>` and
|
|
:ref:`contribution guidelines<modules_contributing>`. They should also have a
|
|
Zephyr developer that is committed to maintain the module codebase.
|
|
|
|
Zephyr depends on several categories of modules, including but not limited to:
|
|
|
|
- Debugger integration
|
|
- Silicon vendor Hardware Abstraction Layers (HALs)
|
|
- Cryptography libraries
|
|
- File Systems
|
|
- Inter-Process Communication (IPC) libraries
|
|
|
|
Additionally, in some cases modules (particularly vendor HALs) can contain
|
|
references to optional :ref:`binary blobs <bin-blobs>`.
|
|
|
|
This page summarizes a list of policies and best practices which aim at
|
|
better organizing the workflow in Zephyr modules.
|
|
|
|
.. _modules-vs-projects:
|
|
|
|
Modules vs west projects
|
|
************************
|
|
|
|
Zephyr modules, described in this page, are not the same as :ref:`west projects
|
|
<west-workspace>`. In fact, modules :ref:`do not require west
|
|
<modules_without_west>` at all. However, when using modules :ref:`with west
|
|
<modules_using_west>`, then the build system uses west in order to find modules.
|
|
|
|
In summary:
|
|
|
|
Modules are repositories that contain a :file:`zephyr/module.yml` file, so that
|
|
the Zephyr build system can pull in the source code from the repository.
|
|
:ref:`West projects <west-manifests-projects>` are entries in the `projects:`
|
|
section in the :file:`west.yml` manifest file.
|
|
West projects are often also modules, but not always. There are west projects
|
|
that are not included in the final firmware image (eg. tools) and thus do not
|
|
need to be modules.
|
|
Modules are found by the Zephyr build system either via :ref:`west itself
|
|
<modules_using_west>`, or via the :ref:`ZEPHYR_MODULES CMake variable
|
|
<modules_without_west>`.
|
|
|
|
The contents of this page only apply to modules, and not to west projects in
|
|
general (unless they are a module themselves).
|
|
|
|
Module Repositories
|
|
*******************
|
|
|
|
* All modules included in the default manifest shall be hosted in repositories
|
|
under the zephyrproject-rtos GitHub organization.
|
|
|
|
* The module repository codebase shall include a *module.yml* file in a
|
|
:file:`zephyr/` folder at the root of the repository.
|
|
|
|
* Module repository names should follow the convention of using lowercase
|
|
letters and dashes instead of underscores. This rule will apply to all
|
|
new module repositories, except for repositories that are directly
|
|
tracking external projects (hosted in Git repositories); such modules
|
|
may be named as their external project counterparts.
|
|
|
|
.. note::
|
|
|
|
Existing module repositories that do not conform to the above convention
|
|
do not need to be renamed to comply with the above convention.
|
|
|
|
* Module repositories names should be explicitly set in the :file:`zephyr/module.yml` file.
|
|
|
|
* Modules should use "zephyr" as the default name for the repository main
|
|
branch. Branches for specific purposes, for example, a module branch for
|
|
an LTS Zephyr version, shall have names starting with the 'zephyr\_' prefix.
|
|
|
|
* If the module has an external (upstream) project repository, the module
|
|
repository should preserve the upstream repository folder structure.
|
|
|
|
.. note::
|
|
|
|
It is not required in module repositories to maintain a 'master'
|
|
branch mirroring the master branch of the external repository. It
|
|
is not recommended as this may generate confusion around the module's
|
|
main branch, which should be 'zephyr'.
|
|
|
|
* Modules should expose all provided header files with an include pathname
|
|
beginning with the module-name. (E.g., mcuboot should expose its
|
|
``bootutil/bootutil.h`` as "mcuboot/bootutil/bootutil.h".)
|
|
|
|
.. _modules_synchronization:
|
|
|
|
Synchronizing with upstream
|
|
===========================
|
|
|
|
It is preferred to synchronize a module repository with the latest stable
|
|
release of the corresponding external project. It is permitted, however, to
|
|
update a Zephyr module repository with the latest development branch tip,
|
|
if this is required to get important updates in the module codebase. When
|
|
synchronizing a module with upstream it is mandatory to document the
|
|
rationale for performing the particular update.
|
|
|
|
Requirements for allowed practices
|
|
----------------------------------
|
|
|
|
Changes to the main branch of a module repository, including synchronization
|
|
with upstream code base, may only be applied via pull requests. These pull
|
|
requests shall be *verifiable* by Zephyr CI and *mergeable* (e.g. with the
|
|
*Rebase and merge*, or *Create a merge commit* option using Github UI). This
|
|
ensures that the incoming changes are always **reviewable**, and the
|
|
*downstream* module repository history is incremental (that is, existing
|
|
commits, tags, etc. are always preserved). This policy also allows to run
|
|
Zephyr CI, git lint, identity, and license checks directly on the set of
|
|
changes that are to be brought into the module repository.
|
|
|
|
.. note::
|
|
|
|
Force-pushing to a module's main branch is not allowed.
|
|
|
|
Allowed practices
|
|
-----------------
|
|
|
|
The following practices conform to the above requirements and should be
|
|
followed in all modules repositories. It is up to the module code owner
|
|
to select the preferred synchronization practice, however, it is required
|
|
that the selected practice is consistently followed in the respective
|
|
module repository.
|
|
|
|
**Updating modules with a diff from upstream:**
|
|
Upstream changes brought as a single *snapshot* commit (manual diff) in a
|
|
pull request against the module's main branch, which may be merged using
|
|
the *Rebase & merge* operation. This approach is simple and
|
|
should be applicable to all modules with the downside of suppressing the
|
|
upstream history in the module repository.
|
|
|
|
.. note::
|
|
|
|
The above practice is the only allowed practice in modules where
|
|
the external project is not hosted in an upstream Git repository.
|
|
|
|
The commit message is expected to identify the upstream project URL, the
|
|
version to which the module is updated (upstream version, tag, commit SHA,
|
|
if applicable, etc.), and the reason for the doing the update.
|
|
|
|
**Updating modules by merging the upstream branch:**
|
|
Upstream changes brought in by performing a Git merge of the intended upstream
|
|
branch (e.g. main branch, latest release branch, etc.) submitting the result in
|
|
pull request against the module main branch, and merging the pull request using
|
|
the *Create a merge commit* operation.
|
|
This approach is applicable to modules with an upstream project Git repository.
|
|
The main advantages of this approach is that the upstream repository history
|
|
(that is, the original commit SHAs) is preserved in the module repository. The
|
|
downside of this approach is that two additional merge commits are generated in
|
|
the downstream main branch.
|
|
|
|
|
|
Contributing to Zephyr modules
|
|
******************************
|
|
|
|
.. _modules_contributing:
|
|
|
|
|
|
Individual Roles & Responsibilities
|
|
===================================
|
|
|
|
To facilitate management of Zephyr module repositories, the following
|
|
individual roles are defined.
|
|
|
|
**Administrator:** Each Zephyr module shall have an administrator
|
|
who is responsible for managing access to the module repository,
|
|
for example, for adding individuals as Collaborators in the repository
|
|
at the request of the module owner. Module administrators are
|
|
members of the Administrators team, that is a group of project
|
|
members with admin rights to module GitHub repositories.
|
|
|
|
**Module owner:** Each module shall have a module code owner. Module
|
|
owners will have the overall responsibility of the contents of a
|
|
Zephyr module repository. In particular, a module owner will:
|
|
|
|
* coordinate code reviewing in the module repository
|
|
* be the default assignee in pull-requests against the repository's
|
|
main branch
|
|
* request additional collaborators to be added to the repository, as
|
|
they see fit
|
|
* regularly synchronize the module repository with its upstream
|
|
counterpart following the policies described in
|
|
:ref:`modules_synchronization`
|
|
* be aware of security vulnerability issues in the external project
|
|
and update the module repository to include security fixes, as
|
|
soon as the fixes are available in the upstream code base
|
|
* list any known security vulnerability issues, present in the
|
|
module codebase, in Zephyr release notes.
|
|
|
|
|
|
.. note::
|
|
|
|
Module owners are not required to be Zephyr
|
|
:ref:`Maintainers <project_roles>`.
|
|
|
|
**Merger:** The Zephyr Release Engineering team has the right and the
|
|
responsibility to merge approved pull requests in the main branch of a
|
|
module repository.
|
|
|
|
|
|
Maintaining the module codebase
|
|
===============================
|
|
|
|
Updates in the zephyr main tree, for example, in public Zephyr APIs,
|
|
may require patching a module's codebase. The responsibility for keeping
|
|
the module codebase up to date is shared between the **contributor** of
|
|
such updates in Zephyr and the module **owner**. In particular:
|
|
|
|
* the contributor of the original changes in Zephyr is required to submit
|
|
the corresponding changes that are required in module repositories, to
|
|
ensure that Zephyr CI on the pull request with the original changes, as
|
|
well as the module integration testing are successful.
|
|
|
|
* the module owner has the overall responsibility for synchronizing
|
|
and testing the module codebase with the zephyr main tree.
|
|
This includes occasional advanced testing of the module's codebase
|
|
in addition to the testing performed by Zephyr's CI.
|
|
The module owner is required to fix issues in the module's codebase that
|
|
have not been caught by Zephyr pull request CI runs.
|
|
|
|
|
|
.. _modules_changes:
|
|
|
|
Contributing changes to modules
|
|
===============================
|
|
|
|
Submitting and merging changes directly to a module's codebase, that is,
|
|
before they have been merged in the corresponding external project
|
|
repository, should be limited to:
|
|
|
|
* changes required due to updates in the zephyr main tree
|
|
* urgent changes that should not wait to be merged in the external project
|
|
first, such as fixes to security vulnerabilities.
|
|
|
|
Non-trivial changes to a module's codebase, including changes in the module
|
|
design or functionality should be discouraged, if the module has an upstream
|
|
project repository. In that case, such changes shall be submitted to the
|
|
upstream project, directly.
|
|
|
|
:ref:`Submitting changes to modules <submitting_new_modules>` describes in
|
|
detail the process of contributing changes to module repositories.
|
|
|
|
Contribution guidelines
|
|
-----------------------
|
|
|
|
Contributing to Zephyr modules shall follow the generic project
|
|
:ref:`Contribution guidelines <contribute_guidelines>`.
|
|
|
|
**Pull Requests:** may be merged with minimum of 2 approvals, including
|
|
an approval by the PR assignee. In addition to this, pull requests in module
|
|
repositories may only be merged if the introduced changes are verified
|
|
with Zephyr CI tools, as described in more detail in other sections on
|
|
this page.
|
|
|
|
The merging of pull requests in the main branch of a module
|
|
repository must be coupled with the corresponding manifest
|
|
file update in the zephyr main tree.
|
|
|
|
**Issue Reporting:** `GitHub issues`_ are intentionally disabled in module
|
|
repositories, in
|
|
favor of a centralized policy for issue reporting. Tickets concerning, for
|
|
example, bugs or enhancements in modules shall be opened in the main
|
|
zephyr repository. Issues should be appropriately labeled using GitHub
|
|
labels corresponding to each module, where applicable.
|
|
|
|
.. note::
|
|
|
|
It is allowed to file bug reports for zephyr modules to track
|
|
the corresponding upstream project bugs in Zephyr. These bug reports
|
|
shall not affect the
|
|
:ref:`Release Quality Criteria<release_quality_criteria>`.
|
|
|
|
|
|
.. _modules_licensing:
|
|
|
|
Licensing requirements and policies
|
|
***********************************
|
|
|
|
All source files in a module's codebase shall include a license header,
|
|
unless the module repository has **main license file** that covers source
|
|
files that do not include license headers.
|
|
|
|
Main license files shall be added in the module's codebase by Zephyr
|
|
developers, only if they exist as part of the external project,
|
|
and they contain a permissive OSI-compliant license. Main license files
|
|
should preferably contain the full license text instead of including an
|
|
SPDX license identifier. If multiple main license files are present it
|
|
shall be made clear which license applies to each source file in a module's
|
|
codebase.
|
|
|
|
Individual license headers in module source files supersede the main license.
|
|
|
|
Any new content to be added in a module repository will require to have
|
|
license coverage.
|
|
|
|
.. note::
|
|
|
|
Zephyr recommends conveying module licensing via individual license
|
|
headers and main license files. This not a hard requirement; should
|
|
an external project have its own practice of conveying how licensing
|
|
applies in the module's codebase (for example, by having a single or
|
|
multiple main license files), this practice may be accepted by and
|
|
be referred to in the Zephyr module, as long as licensing requirements,
|
|
for example OSI compliance, are satisfied.
|
|
|
|
License policies
|
|
================
|
|
|
|
When creating a module repository a developer shall:
|
|
|
|
* import the main license files, if they exist in the external project, and
|
|
* document (for example in the module README or .yml file) the default license
|
|
that covers the module's codebase.
|
|
|
|
License checks
|
|
--------------
|
|
|
|
License checks (via CI tools) shall be enabled on every pull request that
|
|
adds new content in module repositories.
|
|
|
|
|
|
Documentation requirements
|
|
**************************
|
|
|
|
All Zephyr module repositories shall include an .rst file documenting:
|
|
|
|
* the scope and the purpose of the module
|
|
* how the module integrates with Zephyr
|
|
* the owner of the module repository
|
|
* synchronization information with the external project (commit, SHA, version etc.)
|
|
* licensing information as described in :ref:`modules_licensing`.
|
|
|
|
The file shall be required for the inclusion of the module and the contained
|
|
information should be kept up to date.
|
|
|
|
|
|
Testing requirements
|
|
********************
|
|
|
|
All Zephyr modules should provide some level of **integration** testing,
|
|
ensuring that the integration with Zephyr works correctly.
|
|
Integration tests:
|
|
|
|
* may be in the form of a minimal set of samples and tests that reside
|
|
in the zephyr main tree
|
|
* should verify basic usage of the module (configuration,
|
|
functional APIs, etc.) that is integrated with Zephyr.
|
|
* shall be built and executed (for example in QEMU) as part of
|
|
twister runs in pull requests that introduce changes in module
|
|
repositories.
|
|
|
|
.. note::
|
|
|
|
New modules, that are candidates for being included in the Zephyr
|
|
default manifest, shall provide some level of integration testing.
|
|
|
|
.. note::
|
|
|
|
Vendor HALs are implicitly tested via Zephyr tests built or executed
|
|
on target platforms, so they do not need to provide integration tests.
|
|
|
|
The purpose of integration testing is not to provide functional verification
|
|
of the module; this should be part of the testing framework of the external
|
|
project.
|
|
|
|
Certain external projects provide test suites that reside in the upstream
|
|
testing infrastructure but are written explicitly for Zephyr. These tests
|
|
may (but are not required to) be part of the Zephyr test framework.
|
|
|
|
Deprecating and removing modules
|
|
*********************************
|
|
|
|
Modules may be deprecated for reasons including, but not limited to:
|
|
|
|
* Lack of maintainership in the module
|
|
* Licensing changes in the external project
|
|
* Codebase becoming obsolete
|
|
|
|
The module information shall indicate whether a module is
|
|
deprecated and the build system shall issue a warning
|
|
when trying to build Zephyr using a deprecated module.
|
|
|
|
Deprecated modules may be removed from the Zephyr default manifest
|
|
after 2 Zephyr releases.
|
|
|
|
.. note::
|
|
|
|
Repositories of removed modules shall remain accessible via their
|
|
original URL, as they are required by older Zephyr versions.
|
|
|
|
|
|
Integrate modules in Zephyr build system
|
|
****************************************
|
|
|
|
The build system variable :makevar:`ZEPHYR_MODULES` is a `CMake list`_ of
|
|
absolute paths to the directories containing Zephyr modules. These modules
|
|
contain :file:`CMakeLists.txt` and :file:`Kconfig` files describing how to
|
|
build and configure them, respectively. Module :file:`CMakeLists.txt` files are
|
|
added to the build using CMake's `add_subdirectory()`_ command, and the
|
|
:file:`Kconfig` files are included in the build's Kconfig menu tree.
|
|
|
|
If you have :ref:`west <west>` installed, you don't need to worry about how
|
|
this variable is defined unless you are adding a new module. The build system
|
|
knows how to use west to set :makevar:`ZEPHYR_MODULES`. You can add additional
|
|
modules to this list by setting the :makevar:`EXTRA_ZEPHYR_MODULES` CMake
|
|
variable or by adding a :makevar:`EXTRA_ZEPHYR_MODULES` line to ``.zephyrrc``
|
|
(See the section on :ref:`env_vars` for more details). This can be
|
|
useful if you want to keep the list of modules found with west and also add
|
|
your own.
|
|
|
|
.. note::
|
|
If the module ``FOO`` is provided by :ref:`west <west>` but also given with
|
|
``-DEXTRA_ZEPHYR_MODULES=/<path>/foo`` then the module given by the command
|
|
line variable :makevar:`EXTRA_ZEPHYR_MODULES` will take precedence.
|
|
This allows you to use a custom version of ``FOO`` when building and still
|
|
use other Zephyr modules provided by :ref:`west <west>`.
|
|
This can for example be useful for special test purposes.
|
|
|
|
If you want to permanently add modules to the zephyr workspace and you are
|
|
using zephyr as your manifest repository, you can also add a west manifest file
|
|
into the :zephyr_file:`submanifests` directory. See
|
|
:zephyr_file:`submanifests/README.txt` for more details.
|
|
|
|
See :ref:`west-basics` for more on west workspaces.
|
|
|
|
Finally, you can also specify the list of modules yourself in various ways, or
|
|
not use modules at all if your application doesn't need them.
|
|
|
|
.. _module-yml:
|
|
|
|
Module yaml file description
|
|
****************************
|
|
|
|
A module can be described using a file named :file:`zephyr/module.yml`.
|
|
The format of :file:`zephyr/module.yml` is described in the following:
|
|
|
|
Module name
|
|
===========
|
|
|
|
Each Zephyr module is given a name by which it can be referred to in the build
|
|
system.
|
|
|
|
The name should be specified in the :file:`zephyr/module.yml` file. This will
|
|
ensure the module name is not changeable through user-defined directory names
|
|
or ``west`` manifest files:
|
|
|
|
.. code-block:: yaml
|
|
|
|
name: <name>
|
|
|
|
In CMake the location of the Zephyr module can then be referred to using the
|
|
CMake variable ``ZEPHYR_<MODULE_NAME>_MODULE_DIR`` and the variable
|
|
``ZEPHYR_<MODULE_NAME>_CMAKE_DIR`` holds the location of the directory
|
|
containing the module's :file:`CMakeLists.txt` file.
|
|
|
|
.. note::
|
|
When used for CMake and Kconfig variables, all letters in module names are
|
|
converted to uppercase and all non-alphanumeric characters are converted
|
|
to underscores (_).
|
|
As example, the module ``foo-bar`` must be referred to as
|
|
``ZEPHYR_FOO_BAR_MODULE_DIR`` in CMake and Kconfig.
|
|
|
|
Here is an example for the Zephyr module ``foo``:
|
|
|
|
.. code-block:: yaml
|
|
|
|
name: foo
|
|
|
|
.. note::
|
|
If the ``name`` field is not specified then the Zephyr module name will be
|
|
set to the name of the module folder.
|
|
As example, the Zephyr module located in :file:`<workspace>/modules/bar` will
|
|
use ``bar`` as its module name if nothing is specified in
|
|
:file:`zephyr/module.yml`.
|
|
|
|
Module integration files (in-module)
|
|
====================================
|
|
|
|
Inclusion of build files, :file:`CMakeLists.txt` and :file:`Kconfig`, can be
|
|
described as:
|
|
|
|
.. code-block:: yaml
|
|
|
|
build:
|
|
cmake: <cmake-directory>
|
|
kconfig: <directory>/Kconfig
|
|
|
|
The ``cmake: <cmake-directory>`` part specifies that
|
|
:file:`<cmake-directory>` contains the :file:`CMakeLists.txt` to use. The
|
|
``kconfig: <directory>/Kconfig`` part specifies the Kconfig file to use.
|
|
Neither is required: ``cmake`` defaults to ``zephyr``, and ``kconfig``
|
|
defaults to ``zephyr/Kconfig``.
|
|
|
|
Here is an example :file:`module.yml` file referring to
|
|
:file:`CMakeLists.txt` and :file:`Kconfig` files in the root directory of the
|
|
module:
|
|
|
|
.. code-block:: yaml
|
|
|
|
build:
|
|
cmake: .
|
|
kconfig: Kconfig
|
|
|
|
.. _sysbuild_module_integration:
|
|
|
|
Sysbuild integration
|
|
====================
|
|
|
|
:ref:`Sysbuild<sysbuild>` is the Zephyr build system that allows for building
|
|
multiple images as part of a single application, the sysbuild build process
|
|
can be extended externally with modules as needed, for example to add custom
|
|
build steps or add additional targets to a build. Inclusion of
|
|
sysbuild-specific build files, :file:`CMakeLists.txt` and :file:`Kconfig`, can
|
|
be described as:
|
|
|
|
.. code-block:: yaml
|
|
|
|
build:
|
|
sysbuild-cmake: <cmake-directory>
|
|
sysbuild-kconfig: <directory>/Kconfig
|
|
|
|
The ``sysbuild-cmake: <cmake-directory>`` part specifies that
|
|
:file:`<cmake-directory>` contains the :file:`CMakeLists.txt` to use. The
|
|
``sysbuild-kconfig: <directory>/Kconfig`` part specifies the Kconfig file to
|
|
use.
|
|
|
|
Here is an example :file:`module.yml` file referring to
|
|
:file:`CMakeLists.txt` and :file:`Kconfig` files in the `sysbuild` directory of
|
|
the module:
|
|
|
|
.. code-block:: yaml
|
|
|
|
build:
|
|
sysbuild-cmake: sysbuild
|
|
sysbuild-kconfig: sysbuild/Kconfig
|
|
|
|
The module description file :file:`zephyr/module.yml` can also be used to
|
|
specify that the build files, :file:`CMakeLists.txt` and :file:`Kconfig`, are
|
|
located in a :ref:`modules_module_ext_root`.
|
|
|
|
Build files located in a ``MODULE_EXT_ROOT`` can be described as:
|
|
|
|
.. code-block:: yaml
|
|
|
|
build:
|
|
sysbuild-cmake-ext: True
|
|
sysbuild-kconfig-ext: True
|
|
|
|
This allows control of the build inclusion to be described externally to the
|
|
Zephyr module.
|
|
|
|
Build system integration
|
|
========================
|
|
|
|
When a module has a :file:`module.yml` file, it will automatically be included into
|
|
the Zephyr build system. The path to the module is then accessible through Kconfig
|
|
and CMake variables.
|
|
|
|
Zephyr modules
|
|
--------------
|
|
|
|
In both Kconfig and CMake, the variable ``ZEPHYR_<MODULE_NAME>_MODULE_DIR``
|
|
contains the absolute path to the module.
|
|
|
|
In CMake, ``ZEPHYR_<MODULE_NAME>_CMAKE_DIR`` contains the
|
|
absolute path to the directory containing the :file:`CMakeLists.txt` file that
|
|
is included into CMake build system. This variable's value is empty if the
|
|
module.yml file does not specify a CMakeLists.txt.
|
|
|
|
To read these variables for a Zephyr module named ``foo``:
|
|
|
|
- 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`
|
|
- In Kconfig: use ``$(ZEPHYR_FOO_MODULE_DIR)`` for the module's top level directory
|
|
|
|
Notice how a lowercase module name ``foo`` is capitalized to ``FOO``
|
|
in both CMake and Kconfig.
|
|
|
|
These variables can also be used to test whether a given module exists.
|
|
For example, to verify that ``foo`` is the name of a Zephyr module:
|
|
|
|
.. code-block:: cmake
|
|
|
|
if(ZEPHYR_FOO_MODULE_DIR)
|
|
# Do something if FOO exists.
|
|
endif()
|
|
|
|
In Kconfig, the variable may be used to find additional files to include.
|
|
For example, to include the file :file:`some/Kconfig` in module ``foo``:
|
|
|
|
.. code-block:: kconfig
|
|
|
|
source "$(ZEPHYR_FOO_MODULE_DIR)/some/Kconfig"
|
|
|
|
During CMake processing of each Zephyr module, the following variables are
|
|
also available:
|
|
|
|
- the current module's name: ``${ZEPHYR_CURRENT_MODULE_NAME}``
|
|
- the current module's top level directory: ``${ZEPHYR_CURRENT_MODULE_DIR}``
|
|
- the current module's :file:`CMakeLists.txt` directory: ``${ZEPHYR_CURRENT_CMAKE_DIR}``
|
|
|
|
This removes the need for a Zephyr module to know its own name during CMake
|
|
processing. The module can source additional CMake files using these ``CURRENT``
|
|
variables. For example:
|
|
|
|
.. code-block:: cmake
|
|
|
|
include(${ZEPHYR_CURRENT_MODULE_DIR}/cmake/code.cmake)
|
|
|
|
It is possible to append values to a Zephyr `CMake list`_ variable from the module's first
|
|
CMakeLists.txt file.
|
|
To do so, append the value to the list and then set the list in the PARENT_SCOPE
|
|
of the CMakeLists.txt file. For example, to append ``bar`` to the ``FOO_LIST`` variable in the
|
|
Zephyr CMakeLists.txt scope:
|
|
|
|
.. code-block:: cmake
|
|
|
|
list(APPEND FOO_LIST bar)
|
|
set(FOO_LIST ${FOO_LIST} PARENT_SCOPE)
|
|
|
|
An example of a Zephyr list where this is useful is when adding additional
|
|
directories to the ``SYSCALL_INCLUDE_DIRS`` list.
|
|
|
|
Sysbuild modules
|
|
----------------
|
|
|
|
In both Kconfig and CMake, the variable ``SYSBUILD_CURRENT_MODULE_DIR``
|
|
contains the absolute path to the sysbuild module. In CMake,
|
|
``SYSBUILD_CURRENT_CMAKE_DIR`` contains the absolute path to the directory
|
|
containing the :file:`CMakeLists.txt` file that is included into CMake build
|
|
system. This variable's value is empty if the module.yml file does not specify
|
|
a CMakeLists.txt.
|
|
|
|
To read these variables for a sysbuild module:
|
|
|
|
- In CMake: use ``${SYSBUILD_CURRENT_MODULE_DIR}`` for the module's top level
|
|
directory, and ``${SYSBUILD_CURRENT_CMAKE_DIR}`` for the directory containing
|
|
its :file:`CMakeLists.txt`
|
|
- In Kconfig: use ``$(SYSBUILD_CURRENT_MODULE_DIR)`` for the module's top level
|
|
directory
|
|
|
|
In Kconfig, the variable may be used to find additional files to include.
|
|
For example, to include the file :file:`some/Kconfig`:
|
|
|
|
.. code-block:: kconfig
|
|
|
|
source "$(SYSBUILD_CURRENT_MODULE_DIR)/some/Kconfig"
|
|
|
|
The module can source additional CMake files using these variables. For
|
|
example:
|
|
|
|
.. code-block:: cmake
|
|
|
|
include(${SYSBUILD_CURRENT_MODULE_DIR}/cmake/code.cmake)
|
|
|
|
It is possible to append values to a Zephyr `CMake list`_ variable from the
|
|
module's first CMakeLists.txt file.
|
|
To do so, append the value to the list and then set the list in the
|
|
PARENT_SCOPE of the CMakeLists.txt file. For example, to append ``bar`` to the
|
|
``FOO_LIST`` variable in the Zephyr CMakeLists.txt scope:
|
|
|
|
.. code-block:: cmake
|
|
|
|
list(APPEND FOO_LIST bar)
|
|
set(FOO_LIST ${FOO_LIST} PARENT_SCOPE)
|
|
|
|
Sysbuild modules hooks
|
|
----------------------
|
|
|
|
Sysbuild provides an infrastructure which allows a sysbuild module to define
|
|
a function which will be invoked by sysbuild at a pre-defined point in the
|
|
CMake flow.
|
|
|
|
Functions invoked by sysbuild:
|
|
|
|
- ``<module-name>_pre_cmake(IMAGES <images>)``: This function is called for each
|
|
sysbuild module before CMake configure is invoked for all images.
|
|
- ``<module-name>_post_cmake(IMAGES <images>)``: This function is called for each
|
|
sysbuild module after CMake configure has completed for all images.
|
|
- ``<module-name>_pre_domains(IMAGES <images>)``: This function is called for each
|
|
sysbuild module before domains yaml is created by sysbuild.
|
|
- ``<module-name>_post_domains(IMAGES <images>)``: This function is called for each
|
|
sysbuild module after domains yaml has been created by sysbuild.
|
|
|
|
arguments passed from sysbuild to the function defined by a module:
|
|
|
|
- ``<images>`` is the list of Zephyr images that will be created by the build system.
|
|
|
|
If a module ``foo`` want to provide a post CMake configure function, then the
|
|
module's sysbuild :file:`CMakeLists.txt` file must define function ``foo_post_cmake()``.
|
|
|
|
To facilitate naming of functions, the module name is provided by sysbuild CMake
|
|
through the ``SYSBUILD_CURRENT_MODULE_NAME`` CMake variable when loading the
|
|
module's sysbuild :file:`CMakeLists.txt` file.
|
|
|
|
Example of how the ``foo`` sysbuild module can define ``foo_post_cmake()``:
|
|
|
|
.. code-block:: cmake
|
|
|
|
function(${SYSBUILD_CURRENT_MODULE_NAME}_post_cmake)
|
|
cmake_parse_arguments(POST_CMAKE "" "" "IMAGES" ${ARGN})
|
|
|
|
message("Invoking ${CMAKE_CURRENT_FUNCTION}. Images: ${POST_CMAKE_IMAGES}")
|
|
endfunction()
|
|
|
|
Zephyr module dependencies
|
|
==========================
|
|
|
|
A Zephyr module may be dependent on other Zephyr modules to be present in order
|
|
to function correctly. Or it might be that a given Zephyr module must be
|
|
processed after another Zephyr module, due to dependencies of certain CMake
|
|
targets.
|
|
|
|
Such a dependency can be described using the ``depends`` field.
|
|
|
|
.. code-block:: yaml
|
|
|
|
build:
|
|
depends:
|
|
- <module>
|
|
|
|
Here is an example for the Zephyr module ``foo`` that is dependent on the Zephyr
|
|
module ``bar`` to be present in the build system:
|
|
|
|
.. code-block:: yaml
|
|
|
|
name: foo
|
|
build:
|
|
depends:
|
|
- bar
|
|
|
|
This example will ensure that ``bar`` is present when ``foo`` is included into
|
|
the build system, and it will also ensure that ``bar`` is processed before
|
|
``foo``.
|
|
|
|
.. _modules_module_ext_root:
|
|
|
|
Module integration files (external)
|
|
===================================
|
|
|
|
Module integration files can be located externally to the Zephyr module itself.
|
|
The ``MODULE_EXT_ROOT`` variable holds a list of roots containing integration
|
|
files located externally to Zephyr modules.
|
|
|
|
Module integration files in Zephyr
|
|
----------------------------------
|
|
|
|
The Zephyr repository contain :file:`CMakeLists.txt` and :file:`Kconfig` build
|
|
files for certain known Zephyr modules.
|
|
|
|
Those files are located under
|
|
|
|
.. code-block:: none
|
|
|
|
<ZEPHYR_BASE>
|
|
└── modules
|
|
└── <module_name>
|
|
├── CMakeLists.txt
|
|
└── Kconfig
|
|
|
|
Module integration files in a custom location
|
|
---------------------------------------------
|
|
|
|
You can create a similar ``MODULE_EXT_ROOT`` for additional modules, and make
|
|
those modules known to Zephyr build system.
|
|
|
|
Create a ``MODULE_EXT_ROOT`` with the following structure
|
|
|
|
.. code-block:: none
|
|
|
|
<MODULE_EXT_ROOT>
|
|
└── modules
|
|
├── modules.cmake
|
|
└── <module_name>
|
|
├── CMakeLists.txt
|
|
└── Kconfig
|
|
|
|
and then build your application by specifying ``-DMODULE_EXT_ROOT`` parameter to
|
|
the CMake build system. The ``MODULE_EXT_ROOT`` accepts a `CMake list`_ of roots as
|
|
argument.
|
|
|
|
A Zephyr module can automatically be added to the ``MODULE_EXT_ROOT``
|
|
list using the module description file :file:`zephyr/module.yml`, see
|
|
:ref:`modules_build_settings`.
|
|
|
|
.. note::
|
|
|
|
``ZEPHYR_BASE`` is always added as a ``MODULE_EXT_ROOT`` with the lowest
|
|
priority.
|
|
This allows you to overrule any integration files under
|
|
``<ZEPHYR_BASE>/modules/<module_name>`` with your own implementation your own
|
|
``MODULE_EXT_ROOT``.
|
|
|
|
The :file:`modules.cmake` file must contain the logic that specifies the
|
|
integration files for Zephyr modules via specifically named CMake variables.
|
|
|
|
To include a module's CMake file, set the variable ``ZEPHYR_<MODULE_NAME>_CMAKE_DIR``
|
|
to the path containing the CMake file.
|
|
|
|
To include a module's Kconfig file, set the variable ``ZEPHYR_<MODULE_NAME>_KCONFIG``
|
|
to the path to the Kconfig file.
|
|
|
|
The following is an example on how to add support the ``FOO`` module.
|
|
|
|
Create the following structure
|
|
|
|
.. code-block:: none
|
|
|
|
<MODULE_EXT_ROOT>
|
|
└── modules
|
|
├── modules.cmake
|
|
└── foo
|
|
├── CMakeLists.txt
|
|
└── Kconfig
|
|
|
|
and inside the :file:`modules.cmake` file, add the following content
|
|
|
|
.. code-block:: cmake
|
|
|
|
set(ZEPHYR_FOO_CMAKE_DIR ${CMAKE_CURRENT_LIST_DIR}/foo)
|
|
set(ZEPHYR_FOO_KCONFIG ${CMAKE_CURRENT_LIST_DIR}/foo/Kconfig)
|
|
|
|
Module integration files (zephyr/module.yml)
|
|
--------------------------------------------
|
|
|
|
The module description file :file:`zephyr/module.yml` can be used to specify
|
|
that the build files, :file:`CMakeLists.txt` and :file:`Kconfig`, are located
|
|
in a :ref:`modules_module_ext_root`.
|
|
|
|
Build files located in a ``MODULE_EXT_ROOT`` can be described as:
|
|
|
|
.. code-block:: yaml
|
|
|
|
build:
|
|
cmake-ext: True
|
|
kconfig-ext: True
|
|
|
|
This allows control of the build inclusion to be described externally to the
|
|
Zephyr module.
|
|
|
|
The Zephyr repository itself is always added as a Zephyr module ext root.
|
|
|
|
.. _modules_build_settings:
|
|
|
|
Build settings
|
|
==============
|
|
|
|
It is possible to specify additional build settings that must be used when
|
|
including the module into the build system.
|
|
|
|
All ``root`` settings are relative to the root of the module.
|
|
|
|
Build settings supported in the :file:`module.yml` file are:
|
|
|
|
- ``board_root``: Contains additional boards that are available to the build
|
|
system. Additional boards must be located in a :file:`<board_root>/boards`
|
|
folder.
|
|
- ``dts_root``: Contains additional dts files related to the architecture/soc
|
|
families. Additional dts files must be located in a :file:`<dts_root>/dts`
|
|
folder.
|
|
- ``snippet_root``: Contains additional snippets that are available for use.
|
|
These snippets must be defined in :file:`snippet.yml` files underneath the
|
|
:file:`<snippet_root>/snippets` folder. For example, if you have
|
|
``snippet_root: foo``, then you should place your module's
|
|
:file:`snippet.yml` files in :file:`<your-module>/foo/snippets` or any
|
|
nested subdirectory.
|
|
- ``soc_root``: Contains additional SoCs that are available to the build
|
|
system. Additional SoCs must be located in a :file:`<soc_root>/soc` folder.
|
|
- ``arch_root``: Contains additional architectures that are available to the
|
|
build system. Additional architectures must be located in a
|
|
:file:`<arch_root>/arch` folder.
|
|
- ``module_ext_root``: Contains :file:`CMakeLists.txt` and :file:`Kconfig` files
|
|
for Zephyr modules, see also :ref:`modules_module_ext_root`.
|
|
- ``sca_root``: Contains additional :ref:`SCA <sca>` tool implementations
|
|
available to the build system. Each tool must be located in
|
|
:file:`<sca_root>/sca/<tool>` folder. The folder must contain a
|
|
:file:`sca.cmake`.
|
|
|
|
Example of a :file:`module.yaml` file containing additional roots, and the
|
|
corresponding file system layout.
|
|
|
|
.. code-block:: yaml
|
|
|
|
build:
|
|
settings:
|
|
board_root: .
|
|
dts_root: .
|
|
soc_root: .
|
|
arch_root: .
|
|
module_ext_root: .
|
|
|
|
|
|
requires the following folder structure:
|
|
|
|
.. code-block:: none
|
|
|
|
<zephyr-module-root>
|
|
├── arch
|
|
├── boards
|
|
├── dts
|
|
├── modules
|
|
└── soc
|
|
|
|
Twister (Test Runner)
|
|
=====================
|
|
|
|
To execute both tests and samples available in modules, the Zephyr test runner
|
|
(twister) should be pointed to the directories containing those samples and
|
|
tests. This can be done by specifying the path to both samples and tests in the
|
|
:file:`zephyr/module.yml` file. Additionally, if a module defines out of tree
|
|
boards, the module file can point twister to the path where those files
|
|
are maintained in the module. For example:
|
|
|
|
|
|
.. code-block:: yaml
|
|
|
|
build:
|
|
cmake: .
|
|
samples:
|
|
- samples
|
|
tests:
|
|
- tests
|
|
boards:
|
|
- boards
|
|
|
|
.. _modules-bin-blobs:
|
|
|
|
Binary Blobs
|
|
============
|
|
|
|
Zephyr supports fetching and using :ref:`binary blobs <bin-blobs>`, and their
|
|
metadata is contained entirely in :file:`zephyr/module.yml`. This is because
|
|
a binary blob must always be associated with a Zephyr module, and thus the
|
|
blob metadata belongs in the module's description itself.
|
|
|
|
Binary blobs are fetched using :ref:`west blobs <west-blobs>`. If ``west`` is
|
|
:ref:`not used <modules_without_west>`, they must be downloaded and
|
|
verified manually.
|
|
|
|
The ``blobs`` section in :file:`zephyr/module.yml` consists of a sequence of
|
|
maps, each of which has the following entries:
|
|
|
|
- ``path``: The path to the binary blob, relative to the :file:`zephyr/blobs/`
|
|
folder in the module repository
|
|
- ``sha256``: `SHA-256 <https://en.wikipedia.org/wiki/SHA-2>`_ checksum of the
|
|
binary blob file
|
|
- ``type``: The :ref:`type of binary blob <bin-blobs-types>`. Currently limited
|
|
to ``img`` or ``lib``
|
|
- ``version``: A version string
|
|
- ``license-path``: Path to the license file for this blob, relative to the root
|
|
of the module repository
|
|
- ``url``: URL that identifies the location the blob will be fetched from, as
|
|
well as the fetching scheme to use
|
|
- ``description``: Human-readable description of the binary blob
|
|
- ``doc-url``: A URL pointing to the location of the official documentation for
|
|
this blob
|
|
|
|
Module Inclusion
|
|
================
|
|
|
|
.. _modules_using_west:
|
|
|
|
Using West
|
|
----------
|
|
|
|
If west is installed and :makevar:`ZEPHYR_MODULES` is not already set, the
|
|
build system finds all the modules in your :term:`west installation` and uses
|
|
those. It does this by running :ref:`west list <west-built-in-misc>` to get
|
|
the paths of all the projects in the installation, then filters the results to
|
|
just those projects which have the necessary module metadata files.
|
|
|
|
Each project in the ``west list`` output is tested like this:
|
|
|
|
- If the project contains a file named :file:`zephyr/module.yml`, then the
|
|
content of that file will be used to determine which files should be added
|
|
to the build, as described in the previous section.
|
|
|
|
- Otherwise (i.e. if the project has no :file:`zephyr/module.yml`), the
|
|
build system looks for :file:`zephyr/CMakeLists.txt` and
|
|
:file:`zephyr/Kconfig` files in the project. If both are present, the project
|
|
is considered a module, and those files will be added to the build.
|
|
|
|
- If neither of those checks succeed, the project is not considered a module,
|
|
and is not added to :makevar:`ZEPHYR_MODULES`.
|
|
|
|
.. _modules_without_west:
|
|
|
|
Without West
|
|
------------
|
|
|
|
If you don't have west installed or don't want the build system to use it to
|
|
find Zephyr modules, you can set :makevar:`ZEPHYR_MODULES` yourself using one
|
|
of the following options. Each of the directories in the list must contain
|
|
either a :file:`zephyr/module.yml` file or the files
|
|
:file:`zephyr/CMakeLists.txt` and :file:`Kconfig`, as described in the previous
|
|
section.
|
|
|
|
#. At the CMake command line, like this:
|
|
|
|
.. code-block:: console
|
|
|
|
cmake -DZEPHYR_MODULES=<path-to-module1>[;<path-to-module2>[...]] ...
|
|
|
|
#. At the top of your application's top level :file:`CMakeLists.txt`, like this:
|
|
|
|
.. code-block:: cmake
|
|
|
|
set(ZEPHYR_MODULES <path-to-module1> <path-to-module2> [...])
|
|
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
|
|
|
If you choose this option, make sure to set the variable **before** calling
|
|
``find_package(Zephyr ...)``, as shown above.
|
|
|
|
#. In a separate CMake script which is pre-loaded to populate the CMake cache,
|
|
like this:
|
|
|
|
.. code-block:: cmake
|
|
|
|
# Put this in a file with a name like "zephyr-modules.cmake"
|
|
set(ZEPHYR_MODULES <path-to-module1> <path-to-module2>
|
|
CACHE STRING "pre-cached modules")
|
|
|
|
You can tell the build system to use this file by adding ``-C
|
|
zephyr-modules.cmake`` to your CMake command line.
|
|
|
|
Not using modules
|
|
-----------------
|
|
|
|
If you don't have west installed and don't specify :makevar:`ZEPHYR_MODULES`
|
|
yourself, then no additional modules are added to the build. You will still be
|
|
able to build any applications that don't require code or Kconfig options
|
|
defined in an external repository.
|
|
|
|
Submitting changes to modules
|
|
******************************
|
|
|
|
When submitting new or making changes to existing modules the main repository
|
|
Zephyr needs a reference to the changes to be able to verify the changes. In the
|
|
main tree this is done using revisions. For code that is already merged and part
|
|
of the tree we use the commit hash, a tag, or a branch name. For pull requests
|
|
however, we require specifying the pull request number in the revision field to
|
|
allow building the zephyr main tree with the changes submitted to the
|
|
module.
|
|
|
|
To avoid merging changes to master with pull request information, the pull
|
|
request should be marked as ``DNM`` (Do Not Merge) or preferably a draft pull
|
|
request to make sure it is not merged by mistake and to allow for the module to
|
|
be merged first and be assigned a permanent commit hash. Drafts reduce noise by
|
|
not automatically notifying anyone until marked as "Ready for review".
|
|
Once the module is
|
|
merged, the revision will need to be changed either by the submitter or by the
|
|
maintainer to the commit hash of the module which reflects the changes.
|
|
|
|
Note that multiple and dependent changes to different modules can be submitted
|
|
using exactly the same process. In this case you will change multiple entries of
|
|
all modules that have a pull request against them.
|
|
|
|
.. _submitting_new_modules:
|
|
|
|
Process for submitting a new module
|
|
===================================
|
|
|
|
Please follow the process in :ref:`external-src-process` and obtain the TSC
|
|
approval to integrate the external source code as a module
|
|
|
|
If the request is approved, a new repository will
|
|
created by the project team and initialized with basic information that would
|
|
allow submitting code to the module project following the project contribution
|
|
guidelines.
|
|
|
|
If a module is maintained as a fork of another project on Github, the Zephyr
|
|
module related files and changes in relation to upstream need to be maintained
|
|
in a special branch named ``zephyr``.
|
|
|
|
Maintainers from the Zephyr project will create the repository and initialize
|
|
it. You will be added as a collaborator in the new repository. Submit the
|
|
module content (code) to the new repository following the guidelines described
|
|
:ref:`here <modules_using_west>`, and then add a new entry to the
|
|
:zephyr_file:`west.yml` with the following information:
|
|
|
|
.. code-block:: console
|
|
|
|
- name: <name of repository>
|
|
path: <path to where the repository should be cloned>
|
|
revision: <ref pointer to module pull request>
|
|
|
|
|
|
For example, to add *my_module* to the manifest:
|
|
|
|
.. code-block:: console
|
|
|
|
- name: my_module
|
|
path: modules/lib/my_module
|
|
revision: pull/23/head
|
|
|
|
|
|
Where 23 in the example above indicated the pull request number submitted to the
|
|
*my_module* repository. Once the module changes are reviewed and merged, the
|
|
revision needs to be changed to the commit hash from the module repository.
|
|
|
|
.. _changes_to_existing_module:
|
|
|
|
Process for submitting changes to existing modules
|
|
==================================================
|
|
|
|
#. Submit the changes using a pull request to an existing repository following
|
|
the :ref:`contribution guidelines <contribute_guidelines>` and
|
|
:ref:`expectations <contributor-expectations>`.
|
|
#. Submit a pull request changing the entry referencing the module into the
|
|
:zephyr_file:`west.yml` of the main Zephyr tree with the following
|
|
information:
|
|
|
|
.. code-block:: console
|
|
|
|
- name: <name of repository>
|
|
path: <path to where the repository should be cloned>
|
|
revision: <ref pointer to module pull request>
|
|
|
|
|
|
For example, to add *my_module* to the manifest:
|
|
|
|
.. code-block:: console
|
|
|
|
- name: my_module
|
|
path: modules/lib/my_module
|
|
revision: pull/23/head
|
|
|
|
Where 23 in the example above indicated the pull request number submitted to the
|
|
*my_module* repository. Once the module changes are reviewed and merged, the
|
|
revision needs to be changed to the commit hash from the module repository.
|
|
|
|
|
|
|
|
.. _CMake list: https://cmake.org/cmake/help/latest/manual/cmake-language.7.html#lists
|
|
.. _add_subdirectory(): https://cmake.org/cmake/help/latest/command/add_subdirectory.html
|
|
.. _GitHub issues: https://github.com/zephyrproject-rtos/zephyr/issues
|