| .. _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 (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:: |
| |
| 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 package |
| **************************************** |
| |
| The Zephyr Build Configuration CMake package provides a possibility for a Zephyr based project to |
| control Zephyr build settings in a generic way. |
| |
| It is similar to the per-user ``.zephyrrc`` file that can be used to set :ref:`env_vars`, but it |
| sets CMake variables instead. It also allows you to automatically share the build configuration |
| among all users through the project repository. It also allows more advanced use cases, such as loading |
| of additional CMake boilerplate code. |
| |
| The Zephyr Build Configuration CMake package will be loaded in the Zephyr boilerplate code after |
| initial properties and ``ZEPHYR_BASE`` has been defined, but before CMake code execution. |
| This allows the Zephyr Build Configuration CMake package 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 Zephyr Build Configuration CMake package, create ``ZephyrBuildConfig.cmake`` and place |
| it in a Zephyr workspace top-level folder as: |
| |
| .. code-block:: none |
| |
| <projects>/zephyr-workspace |
| ├── zephyr |
| ├── ... |
| └── zephyr application (can be named anything) |
| └── share/zephyrbuild-package/cmake/ZephyrBuildConfig.cmake |
| |
| The Zephyr Build Configuration CMake package will not search in any CMake default search paths, and |
| thus cannot be installed in the CMake package registry. There will be no version checking on the |
| Zephyr Build Configuration package. |
| |
| .. note:: ``share/zephyrbuild-package/cmake/ZephyrBuildConfig.cmake`` follows the same folder |
| structure as the Zephyr CMake package. |
| |
| It is possible to place ``ZephyrBuildConfig.cmake`` directly in a |
| ``<zephyr application>/cmake`` folder or another folder, as long as that folder is |
| honoring the `CMake package search`_ algorithm. |
| |
| A sample ``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 Build Configuration CMake package (Freestanding application) |
| ******************************************************************* |
| |
| The Zephyr Build Configuration CMake package can be located outside a Zephyr |
| workspace, for example located with a :ref:`zephyr-freestanding-app`. |
| |
| Create the build configuration as described in the previous section, and then |
| refer to the location of your Zephyr Build Configuration CMake package using |
| the CMake variable ``ZephyrBuildConfiguration_ROOT``. |
| |
| #. At the CMake command line, like this: |
| |
| .. code-block:: console |
| |
| cmake -DZephyrBuildConfiguration_ROOT=<path-to-build-config> ... |
| |
| #. At the top of your application's top level :file:`CMakeLists.txt`, like this: |
| |
| .. code-block:: cmake |
| |
| set(ZephyrBuildConfiguration_ROOT <path-to-build-config>) |
| 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-settings.cmake" |
| set(ZephyrBuildConfiguration_ROOT <path-to-build-config> |
| CACHE STRING "pre-cached build config" |
| ) |
| |
| You can tell the build system to use this file by adding ``-C |
| zephyr-settings.cmake`` to your CMake command line. |
| This principle is useful when not using ``west`` as both this setting and |
| Zephyr modules can be specified using the same file. |
| See Zephyr module :ref:`modules_without_west`. |
| |
| Zephyr CMake package source code |
| ******************************** |
| |
| The Zephyr CMake package source code in |
| ``<PATH-TO-ZEPHYR>/share/zephyr-package/cmake`` contains the CMake config package |
| which is used by CMake ``find_package`` function. |
| |
| It also contains code for exporting Zephyr as a CMake config package. |
| |
| The following is an overview of those files |
| |
| :file:`CMakeLists.txt` |
| The CMakeLists.txt file for the CMake build system which is responsible for |
| exporting Zephyr as a package to the CMake user package registry. |
| |
| :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:`pristine.cmake` |
| Pristine file for removing all files created by CMake during configure and generator time when |
| exporting Zephyr CMake package. Running pristine keeps all package related files mentioned above. |
| |
| .. _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: https://cmake.org/cmake/help/latest/command/find_package.html#search-procedure |