You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
450 lines
16 KiB
450 lines
16 KiB
.. _cmake_pkg: |
|
|
|
Zephyr CMake Package |
|
#################### |
|
|
|
The Zephyr `CMake package`_ is a convenient way to create a Zephyr-based application. |
|
|
|
.. note:: |
|
The :ref:`zephyr-app-types` section introduces the application types |
|
used in this page. |
|
|
|
The Zephyr CMake package ensures that CMake can automatically select a Zephyr installation to use for building |
|
the application, whether it is a :ref:`Zephyr repository application <zephyr-repo-app>`, |
|
a :ref:`Zephyr workspace application <zephyr-workspace-app>`, or a |
|
:ref:`Zephyr freestanding application <zephyr-freestanding-app>`. |
|
|
|
When developing a Zephyr-based application, then a developer simply needs to write |
|
``find_package(Zephyr)`` in the beginning of the application :file:`CMakeLists.txt` file. |
|
|
|
To use the Zephyr CMake package it must first be exported to the `CMake user package registry`_. |
|
This is means creating a reference to the current Zephyr installation inside the |
|
CMake user package registry. |
|
|
|
|
|
.. tabs:: |
|
|
|
.. group-tab:: Ubuntu |
|
|
|
In Linux, the CMake user package registry is found in: |
|
|
|
``~/.cmake/packages/Zephyr`` |
|
|
|
.. group-tab:: macOS |
|
|
|
In macOS, the CMake user package registry is found in: |
|
|
|
``~/.cmake/packages/Zephyr`` |
|
|
|
.. group-tab:: Windows |
|
|
|
In Windows, the CMake user package registry is found in: |
|
|
|
``HKEY_CURRENT_USER\Software\Kitware\CMake\Packages\Zephyr`` |
|
|
|
|
|
The Zephyr CMake package allows CMake to automatically find a Zephyr base. |
|
One or more Zephyr installations must be exported. |
|
Exporting multiple Zephyr installations may be useful when developing or testing |
|
Zephyr freestanding applications, Zephyr workspace application with vendor forks, etc.. |
|
|
|
|
|
Zephyr CMake package export (west) |
|
********************************** |
|
|
|
When installing Zephyr using :ref:`west <get_the_code>` then it is recommended |
|
to export Zephyr using ``west zephyr-export``. |
|
|
|
.. _zephyr_cmake_package_export: |
|
|
|
Zephyr CMake package export (without west) |
|
****************************************** |
|
|
|
Zephyr CMake package is exported to the CMake user package registry using the following commands: |
|
|
|
.. code-block:: bash |
|
|
|
cmake -P <PATH-TO-ZEPHYR>/share/zephyr-package/cmake/zephyr_export.cmake |
|
|
|
This will export the current Zephyr to the CMake user package registry. |
|
|
|
To also export the Zephyr Unittest CMake package, run the following command in addition: |
|
|
|
.. code-block:: bash |
|
|
|
cmake -P <PATH-TO-ZEPHYR>/share/zephyrunittest-package/cmake/zephyr_export.cmake |
|
|
|
.. _zephyr_cmake_package_zephyr_base: |
|
|
|
Zephyr Base Environment Setting |
|
******************************* |
|
|
|
The Zephyr CMake package search functionality allows for explicitly specifying |
|
a Zephyr base using an environment variable. |
|
|
|
To do this, use the following ``find_package()`` syntax: |
|
|
|
.. code-block:: cmake |
|
|
|
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) |
|
|
|
This syntax instructs CMake to first search for Zephyr using the Zephyr base environment setting |
|
:envvar:`ZEPHYR_BASE` and then use the normal search paths. |
|
|
|
.. _zephyr_cmake_search_order: |
|
|
|
Zephyr CMake Package Search Order |
|
********************************* |
|
|
|
When Zephyr base environment setting is not used for searching, the Zephyr installation matching |
|
the following criteria will be used: |
|
|
|
* A Zephyr repository application will use the Zephyr in which it is located. |
|
For example: |
|
|
|
.. code-block:: none |
|
|
|
<projects>/zephyr-workspace/zephyr |
|
└── samples |
|
└── hello_world |
|
|
|
in this example, ``hello_world`` will use ``<projects>/zephyr-workspace/zephyr``. |
|
|
|
|
|
* Zephyr workspace application will use the Zephyr that share the same workspace. |
|
For example: |
|
|
|
.. code-block:: none |
|
|
|
<projects>/zephyr-workspace |
|
├── zephyr |
|
├── ... |
|
└── my_applications |
|
└── my_first_app |
|
|
|
in this example, ``my_first_app`` will use ``<projects>/zephyr-workspace/zephyr`` as this Zephyr |
|
is located in the same workspace as the Zephyr workspace application. |
|
|
|
.. note:: |
|
The root of a Zephyr workspace is identical to ``west topdir`` if the workspace was |
|
installed using ``west`` |
|
|
|
* Zephyr freestanding application will use the Zephyr registered in the CMake user package registry. |
|
For example: |
|
|
|
.. code-block:: none |
|
|
|
<projects>/zephyr-workspace-1 |
|
└── zephyr (Not exported to CMake) |
|
|
|
<projects>/zephyr-workspace-2 |
|
└── zephyr (Exported to CMake) |
|
|
|
<home>/app |
|
├── CMakeLists.txt |
|
├── prj.conf |
|
└── src |
|
└── main.c |
|
|
|
in this example, only ``<projects>/zephyr-workspace-2/zephyr`` is exported to the CMake package |
|
registry and therefore this Zephyr will be used by the Zephyr freestanding application |
|
``<home>/app``. |
|
|
|
If user wants to test the application with ``<projects>/zephyr-workspace-1/zephyr``, this can be |
|
done by using the Zephyr Base environment setting, meaning set |
|
``ZEPHYR_BASE=<projects>/zephyr-workspace-1/zephyr``, before |
|
running CMake. |
|
|
|
.. note:: |
|
|
|
The Zephyr package selected on the first CMake invocation will be used for all subsequent |
|
builds. To change the Zephyr package, for example to test the application using Zephyr base |
|
environment setting, then it is necessary to do a pristine build first |
|
(See :ref:`application_rebuild`). |
|
|
|
Zephyr CMake Package Version |
|
**************************** |
|
|
|
When writing an application then it is possible to specify a Zephyr version number ``x.y.z`` that |
|
must be used in order to build the application. |
|
|
|
Specifying a version is especially useful for a Zephyr freestanding application as it ensures the |
|
application is built with a minimal Zephyr version. |
|
|
|
It also helps CMake to select the correct Zephyr to use for building, when there are multiple |
|
Zephyr installations in the system. |
|
|
|
For example: |
|
|
|
.. code-block:: cmake |
|
|
|
find_package(Zephyr 2.2.0) |
|
project(app) |
|
|
|
will require ``app`` to be built with Zephyr 2.2.0 as minimum. |
|
CMake will search all exported candidates to find a Zephyr installation which matches this version |
|
criteria. |
|
|
|
Thus it is possible to have multiple Zephyr installations and have CMake automatically select |
|
between them based on the version number provided, see `CMake package version`_ for details. |
|
|
|
For example: |
|
|
|
.. code-block:: none |
|
|
|
<projects>/zephyr-workspace-2.a |
|
└── zephyr (Exported to CMake) |
|
|
|
<projects>/zephyr-workspace-2.b |
|
└── zephyr (Exported to CMake) |
|
|
|
<home>/app |
|
├── CMakeLists.txt |
|
├── prj.conf |
|
└── src |
|
└── main.c |
|
|
|
in this case, there are two released versions of Zephyr installed at their own workspaces. |
|
Workspace 2.a and 2.b, corresponding to the Zephyr version. |
|
|
|
To ensure ``app`` is built with minimum version ``2.a`` the following ``find_package`` |
|
syntax may be used: |
|
|
|
.. code-block:: cmake |
|
|
|
find_package(Zephyr 2.a) |
|
project(app) |
|
|
|
|
|
Note that both ``2.a`` and ``2.b`` fulfill this requirement. |
|
|
|
CMake also supports the keyword ``EXACT``, to ensure an exact version is used, if that is required. |
|
In this case, the application CMakeLists.txt could be written as: |
|
|
|
.. code-block:: cmake |
|
|
|
find_package(Zephyr 2.a EXACT) |
|
project(app) |
|
|
|
In case no Zephyr is found which satisfies the version required, as example, the application specifies |
|
|
|
.. code-block:: cmake |
|
|
|
find_package(Zephyr 2.z) |
|
project(app) |
|
|
|
then an error similar to below will be printed: |
|
|
|
.. code-block:: none |
|
|
|
Could not find a configuration file for package "Zephyr" that is compatible |
|
with requested version "2.z". |
|
|
|
The following configuration files were considered but not accepted: |
|
|
|
<projects>/zephyr-workspace-2.a/zephyr/share/zephyr-package/cmake/ZephyrConfig.cmake, version: 2.a.0 |
|
<projects>/zephyr-workspace-2.b/zephyr/share/zephyr-package/cmake/ZephyrConfig.cmake, version: 2.b.0 |
|
|
|
|
|
.. note:: It can also be beneficial to specify a version number for Zephyr repository applications |
|
and Zephyr workspace applications. Specifying a version in those cases ensures the |
|
application will only build if the Zephyr repository or workspace is matching. |
|
This can be useful to avoid accidental builds when only part of a workspace has been |
|
updated. |
|
|
|
|
|
Multiple Zephyr Installations (Zephyr workspace) |
|
************************************************ |
|
|
|
Testing out a new Zephyr version, while at the same time keeping the existing Zephyr in the |
|
workspace untouched is sometimes beneficial. |
|
|
|
Or having both an upstream Zephyr, Vendor specific, and a custom Zephyr in same workspace. |
|
|
|
For example: |
|
|
|
.. code-block:: none |
|
|
|
<projects>/zephyr-workspace |
|
├── zephyr |
|
├── zephyr-vendor |
|
├── zephyr-custom |
|
├── ... |
|
└── my_applications |
|
└── my_first_app |
|
|
|
|
|
in this setup, ``find_package(Zephyr)`` has the following order of precedence for selecting |
|
which Zephyr to use: |
|
|
|
* Project name: ``zephyr`` |
|
* First project, when Zephyr projects are ordered lexicographical, in this case. |
|
|
|
* ``zephyr-custom`` |
|
* ``zephyr-vendor`` |
|
|
|
This means that ``my_first_app`` will use ``<projects>/zephyr-workspace/zephyr``. |
|
|
|
It is possible to specify a Zephyr preference list in the application. |
|
|
|
A Zephyr preference list can be specified as: |
|
|
|
.. code-block:: cmake |
|
|
|
set(ZEPHYR_PREFER "zephyr-custom" "zephyr-vendor") |
|
find_package(Zephyr) |
|
|
|
project(my_first_app) |
|
|
|
|
|
the ``ZEPHYR_PREFER`` is a list, allowing for multiple Zephyrs. |
|
If a Zephyr is specified in the list, but not found in the system, it is simply ignored and |
|
``find_package(Zephyr)`` will continue to the next candidate. |
|
|
|
|
|
This allows for temporary creation of a new Zephyr release to be tested, without touching current |
|
Zephyr. When testing is done, the ``zephyr-test`` folder can simply be removed. |
|
Such a CMakeLists.txt could look as: |
|
|
|
.. code-block:: cmake |
|
|
|
set(ZEPHYR_PREFER "zephyr-test") |
|
find_package(Zephyr) |
|
|
|
project(my_first_app) |
|
|
|
.. _cmake_build_config_package: |
|
|
|
Zephyr Build Configuration CMake packages |
|
***************************************** |
|
|
|
There are two Zephyr Build configuration packages which provide control over the build |
|
settings in Zephyr in a more generic way. These packages are: |
|
|
|
* **ZephyrBuildConfiguration**: Applies to all Zephyr applications in the workspace |
|
* **ZephyrAppConfiguration**: Applies only to the application you are currently building |
|
|
|
They are similar to the per-user :file:`.zephyrrc` file that can be used to set :ref:`env_vars`, |
|
but they set CMake variables instead. They also allow you to automatically share the build |
|
configuration among all users through the project repository. They also allow more advanced use |
|
cases, such as loading of additional CMake boilerplate code. |
|
|
|
The Zephyr Build Configuration CMake packages will be loaded in the Zephyr boilerplate code after |
|
initial properties and ``ZEPHYR_BASE`` has been defined, but before CMake code execution. The |
|
ZephyrBuildConfiguration is included first and ZephyrAppConfiguration afterwards. That means the |
|
application-specific package could override the workspace settings, if needed. |
|
This allows the Zephyr Build Configuration CMake packages to setup or extend properties such as: |
|
``DTS_ROOT``, ``BOARD_ROOT``, ``TOOLCHAIN_ROOT`` / other toolchain setup, fixed overlays, and any |
|
other property that can be controlled. It also allows inclusion of additional boilerplate code. |
|
|
|
To provide a ZephyrBuildConfiguration or ZephyrAppConfiguration, create |
|
:file:`ZephyrBuildConfig.cmake` and/or :file:`ZephyrAppConfig.cmake` respectively and place them |
|
in the appropriate location. The CMake ``find_package`` mechanism will search for these files with |
|
the steps below. Other default CMake package search paths and hints are disabled and there is no |
|
version checking implemented for these packages. This also means that these packages cannot be |
|
installed in the CMake package registry. The search steps are: |
|
|
|
1. If ``ZephyrBuildConfiguration_ROOT``, or ``ZephyrAppConfiguration_ROOT`` respectively, is set, |
|
search within this prefix path. If a matching file is found, execute this file. If no matching |
|
file is found, go to step 2. |
|
2. Search within ``${ZEPHYR_BASE}/../*``, or ``${APPLICATION_SOURCE_DIR}`` respectively. If a |
|
matching file is found, execute this file. If no matching file is found, abort the search. |
|
|
|
It is recommended to place the files in the default paths from step 2, but with the |
|
``<PackageName>_ROOT`` variables you have the flexibility to place them anywhere. This is |
|
especially necessary for freestanding applications, for which the default path to |
|
ZephyrBuildConfiguration usually does not work. In this case the ``<PackageName>_ROOT`` variables |
|
can be set on the CMake command line, **before** ``find_package(Zephyr ...)``, as environment |
|
variable or from a CMake cache initialization file with the ``-C`` command line option. |
|
|
|
.. note:: The ``<PackageName>_ROOT`` variables, as well as the default paths, are just the prefixes |
|
to the search path. These prefixes get combined with additional path suffixes, which together |
|
form the actual search path. Any combination that honors the |
|
`CMake package search procedure`_ is valid and will work. |
|
|
|
If you want to completely disable the search for these packages, you can use the special CMake |
|
``CMAKE_DISABLE_FIND_PACKAGE_<PackageName>`` variable for that. Just set |
|
``CMAKE_DISABLE_FIND_PACKAGE_ZephyrBuildConfiguration`` or |
|
``CMAKE_DISABLE_FIND_PACKAGE_ZephyrAppConfiguration`` to ``TRUE`` to disable the package. |
|
|
|
An example folder structure could look like this: |
|
|
|
.. code-block:: none |
|
|
|
<projects>/zephyr-workspace |
|
├── zephyr |
|
├── ... |
|
├── manifest repo (can be named anything) |
|
│ └── cmake/ZephyrBuildConfig.cmake |
|
├── ... |
|
└── zephyr application |
|
└── share/zephyrapp-package/cmake/ZephyrAppConfig.cmake |
|
|
|
A sample :file:`ZephyrBuildConfig.cmake` can be seen below. |
|
|
|
.. code-block:: cmake |
|
|
|
# ZephyrBuildConfig.cmake sample code |
|
|
|
# To ensure final path is absolute and does not contain ../.. in variable. |
|
get_filename_component(APPLICATION_PROJECT_DIR |
|
${CMAKE_CURRENT_LIST_DIR}/../../.. |
|
ABSOLUTE |
|
) |
|
|
|
# Add this project to list of board roots |
|
list(APPEND BOARD_ROOT ${APPLICATION_PROJECT_DIR}) |
|
|
|
# Default to GNU Arm Embedded toolchain if no toolchain is set |
|
if(NOT ENV{ZEPHYR_TOOLCHAIN_VARIANT}) |
|
set(ZEPHYR_TOOLCHAIN_VARIANT gnuarmemb) |
|
find_program(GNU_ARM_GCC arm-none-eabi-gcc) |
|
if(NOT ${GNU_ARM_GCC} STREQUAL GNU_ARM_GCC-NOTFOUND) |
|
# The toolchain root is located above the path to the compiler. |
|
get_filename_component(GNUARMEMB_TOOLCHAIN_PATH ${GNU_ARM_GCC}/../.. ABSOLUTE) |
|
endif() |
|
endif() |
|
|
|
Zephyr CMake package source code |
|
******************************** |
|
|
|
The Zephyr CMake package source code in |
|
:zephyr_file:`share/zephyr-package/cmake` and |
|
:zephyr_file:`share/zephyrunittest-package/cmake` contains the CMake config |
|
package which is used by the CMake ``find_package`` function. |
|
|
|
It also contains code for exporting Zephyr as a CMake config package. |
|
|
|
The following is an overview of the files in these directories: |
|
|
|
:file:`ZephyrConfigVersion.cmake` |
|
The Zephyr package version file. This file is called by CMake to determine |
|
if this installation fulfils the requirements specified by user when calling |
|
``find_package(Zephyr ...)``. It is also responsible for detection of Zephyr |
|
repository or workspace only installations. |
|
|
|
:file:`ZephyrUnittestConfigVersion.cmake` |
|
Same responsibility as ``ZephyrConfigVersion.cmake``, but for unit tests. |
|
Includes ``ZephyrConfigVersion.cmake``. |
|
|
|
:file:`ZephyrConfig.cmake` |
|
The Zephyr package file. This file is called by CMake to for the package |
|
meeting which fulfils the requirements specified by user when calling |
|
``find_package(Zephyr ...)``. This file is responsible for sourcing of |
|
boilerplate code. |
|
|
|
:file:`ZephyrUnittestConfig.cmake` |
|
Same responsibility as ``ZephyrConfig.cmake``, but for unit tests. |
|
Includes ``ZephyrConfig.cmake``. |
|
|
|
:file:`zephyr_package_search.cmake` |
|
Common file used for detection of Zephyr repository and workspace candidates. |
|
Used by ``ZephyrConfigVersion.cmake`` and ``ZephyrConfig.cmake`` for common code. |
|
|
|
:file:`zephyr_export.cmake` |
|
See :ref:`zephyr_cmake_package_export`. |
|
|
|
.. _CMake package: https://cmake.org/cmake/help/latest/manual/cmake-packages.7.html |
|
.. _CMake user package registry: https://cmake.org/cmake/help/latest/manual/cmake-packages.7.html#user-package-registry |
|
.. _CMake package version: https://cmake.org/cmake/help/latest/command/find_package.html#version-selection |
|
.. _CMake package search procedure: https://cmake.org/cmake/help/latest/command/find_package.html#search-procedure
|
|
|