Part 1
요약·해설
Application directory와 세 type, CMake·Kconfig·overlay, west/ninja build, clean/pristine, board revision, flash·QEMU, out-of-tree BOARD_ROOT·SOC_ROOT·DTS_ROOT를 설명합니다.
Workspace · Files · CMake
Kconfig · Ninja · West
Board · SoC · DTS
Part 2
접을 수 있는 영어 원문 전체
영어 원문 전체 펼치기
11F161DBA66D7EB07F8561A359545E102773129120F9BA6CDB9141FDDCA8BE36
.. _application:
Application Development
#######################
.. note::
In this document, we'll assume:
- your **application directory**, :file:`<app>`, is something like :file:`<home>/zephyrproject/app`
- its **build directory** is :file:`<app>/build`
These terms are defined below. On Linux/macOS, <home> is equivalent to
``~``. On Windows, it's ``%userprofile%``.
Keeping your application inside the workspace (:file:`<home>/zephyrproject`)
makes it easier to use ``west build`` and other commands with it. (You can
put your application anywhere as long as :ref:`ZEPHYR_BASE
<important-build-vars>` is set appropriately, though.)
Overview
********
Zephyr's build system is based on `CMake`_.
The build system is application-centric, and requires Zephyr-based applications
to initiate building the Zephyr source code. The application build controls
the configuration and build process of both the application and Zephyr itself,
compiling them into a single binary.
The main zephyr repository contains Zephyr's source code, configuration files,
and build system. You also likely have installed various :ref:`modules`
alongside the zephyr repository, which provide third party source code
integration.
The files in the **application directory** link Zephyr and any modules with the
application. This directory contains all application-specific files, such as
application-specific configuration files and source code.
Here are the files in a simple Zephyr application:
.. code-block:: none
<app>
├── CMakeLists.txt
├── app.overlay
├── prj.conf
├── VERSION
└── src
└── main.c
These contents are:
* **CMakeLists.txt**: This file tells the build system where to find the other
application files, and links the application directory with Zephyr's CMake
build system. This link provides features supported by Zephyr's build system,
such as board-specific configuration files, the ability to run and
debug compiled binaries on real or emulated hardware, and more.
* **app.overlay**: This is a devicetree overlay file that specifies
application-specific changes which should be applied to the base devicetree
for any board you build for. The purpose of devicetree overlays is
usually to configure something about the hardware used by the application.
The build system looks for :file:`app.overlay` by default, but you can add
more devicetree overlays, and other default files are also searched for.
See :ref:`devicetree` for more information about devicetree.
* **prj.conf**: This is a Kconfig fragment that specifies application-specific
values for one or more Kconfig options. These application settings are merged
with other settings to produce the final configuration. The purpose of
Kconfig fragments is usually to configure the software features used by
the application.
The build system looks for :file:`prj.conf` by default, but you can add more
Kconfig fragments, and other default files are also searched for.
See :ref:`application-kconfig` below for more information.
* **VERSION**: A text file that contains several version information fields.
These fields let you manage the lifecycle of the application and automate
providing the application version when signing application images.
See :ref:`app-version-details` for more information about this file and how to use it.
* **main.c**: A source code file. Applications typically contain source files
written in C, C++, or assembly language. The Zephyr convention is to place
them in a subdirectory of :file:`<app>` named :file:`src`.
Once an application has been defined, you will use CMake to generate a **build
directory**, which contains the files you need to build the application and
Zephyr, then link them together into a final binary you can run on your board.
The easiest way to do this is with :ref:`west build <west-building>`, but you
can use CMake directly also. Application build artifacts are always generated
in a separate build directory: Zephyr does not support "in-tree" builds.
The following sections describe how to create, build, and run Zephyr
applications, followed by more detailed reference material.
.. _zephyr-app-types:
Application types
*****************
We distinguish three basic types of Zephyr application based on where
:file:`<app>` is located:
.. table::
+------------------------------+--------------------------------+
| Application type | :file:`<app>` location |
+------------------------------+--------------------------------+
| :ref:`repository | zephyr repository |
| <zephyr-repo-app>` | |
+------------------------------+--------------------------------+
| :ref:`workspace | west workspace where Zephyr is |
| <zephyr-workspace-app>` | installed |
+------------------------------+--------------------------------+
| :ref:`freestanding | other locations |
| <zephyr-freestanding-app>` | |
+------------------------------+--------------------------------+
We'll discuss these more below. To learn how the build system supports each
type, see :ref:`cmake_pkg`.
.. _zephyr-repo-app:
Zephyr repository application
=============================
An application located within the ``zephyr`` source code repository in a Zephyr
:ref:`west workspace <west-workspaces>` is referred to as a Zephyr repository
application. In the following example, the :ref:`hello_world sample
<hello_world>` is a Zephyr repository application:
.. code-block:: none
zephyrproject/
├─── .west/
│ └─── config
└─── zephyr/
├── arch/
├── boards/
├── cmake/
├── samples/
│ ├── hello_world/
│ └── ...
├── tests/
└── ...
.. _zephyr-workspace-app:
Zephyr workspace application
============================
An application located within a :ref:`workspace <west-workspaces>`, but outside
the zephyr repository itself, is referred to as a Zephyr workspace application.
In the following example, ``app`` is a Zephyr workspace application:
.. code-block:: none
zephyrproject/
├─── .west/
│ └─── config
├─── zephyr/
├─── bootloader/
├─── modules/
├─── tools/
├─── <vendor/private-repositories>/
└─── applications/
└── app/
.. _zephyr-freestanding-app:
Zephyr freestanding application
===============================
A Zephyr application located outside of a Zephyr :ref:`workspace
<west-workspaces>` is referred to as a Zephyr freestanding application. In the
following example, ``app`` is a Zephyr freestanding application:
.. code-block:: none
<home>/
├─── zephyrproject/
│ ├─── .west/
│ │ └─── config
│ ├── zephyr/
│ ├── bootloader/
│ ├── modules/
│ └── ...
│
└─── app/
├── CMakeLists.txt
├── prj.conf
└── src/
└── main.c
.. _zephyr-creating-app:
Creating an Application
***********************
In Zephyr, you can either use a reference workspace application or create your application by hand.
.. _zephyr-creating-app-from-example:
Using a Reference Workspace Application
=======================================
The `example-application`_ Git repository contains a reference :ref:`workspace
application <zephyr-workspace-app>`. It is recommended to use it as a reference
when creating your own application as described in the following sections.
The example-application repository demonstrates how to use several
commonly-used features, such as:
- Custom :ref:`board ports <board_porting_guide>`
- Custom :ref:`devicetree bindings <dt-bindings>`
- Custom :ref:`device drivers <device_model_api>`
- Continuous Integration (CI) setup, including using :ref:`twister <twister_script>`
- A custom west :ref:`extension command <west-extensions>`
Basic example-application Usage
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The easiest way to get started with the example-application repository within
an existing Zephyr workspace is to follow these steps:
.. code-block:: console
cd <home>/zephyrproject
git clone https://github.com/zephyrproject-rtos/example-application my-app
The directory name :file:`my-app` above is arbitrary: change it as needed. You
can now go into this directory and adapt its contents to suit your needs. Since
you are using an existing Zephyr workspace, you can use ``west build`` or any
other west commands to build, flash, and debug.
Advanced example-application Usage
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You can also use the example-application repository as a starting point for
building your own customized Zephyr-based software distribution. This lets you
do things like:
- remove Zephyr modules you don't need
- add additional custom repositories of your own
- override repositories provided by Zephyr with your own versions
- share the results with others and collaborate further
The example-application repository contains a :file:`west.yml` file and is
therefore also a west :ref:`manifest repository <west-workspace>`. Use this to
create a new, customized workspace by following these steps:
.. code-block:: console
cd <home>
mkdir my-workspace
cd my-workspace
git clone https://github.com/zephyrproject-rtos/example-application my-manifest-repo
west init -l my-manifest-repo
This will create a new workspace with the :ref:`T2 topology <west-t2>`, with
:file:`my-manifest-repo` as the manifest repository. The :file:`my-workspace`
and :file:`my-manifest-repo` names are arbitrary: change them as needed.
Next, customize the manifest repository. The initial contents of this
repository will match the example-application's contents when you clone it. You
can then edit :file:`my-manifest-repo/west.yml` to your liking, changing the
set of repositories in it as you wish. See :ref:`west-manifest-import` for many
examples of how to add or remove different repositories from your workspace as
needed. Make any other changes you need to other files.
When you are satisfied, you can run:
.. code-block::
west update
and your workspace will be ready for use.
If you push the resulting :file:`my-manifest-repo` repository somewhere else,
you can share your work with others. For example, let's say you push the
repository to ``https://git.example.com/my-manifest-repo``. Other people can
then set up a matching workspace by running:
.. code-block::
west init -m https://git.example.com/my-manifest-repo my-workspace
cd my-workspace
west update
From now on, you can collaborate on the shared software by pushing changes to
the repositories you are using and updating :file:`my-manifest-repo/west.yml`
as needed to add and remove repositories, or change their contents.
.. _zephyr-creating-app-by-hand:
Creating an Application by Hand
===============================
You can follow these steps to create a basic application directory from
scratch. However, using the `example-application`_ repository or one of
Zephyr's :ref:`samples-and-demos` as a starting point is likely to be easier.
#. Create an application directory.
For example, in a Unix shell or Windows ``cmd.exe`` prompt:
.. code-block:: console
mkdir app
.. warning::
Building Zephyr or creating an application in a directory with spaces
anywhere on the path is not supported. So the Windows path
:file:`C:\\Users\\YourName\\app` will work, but
:file:`C:\\Users\\Your Name\\app` will not.
#. Create your source code files.
It's recommended to place all application source code in a subdirectory
named :file:`src`. This makes it easier to distinguish between project
files and sources.
Continuing the previous example, enter:
.. code-block:: console
cd app
mkdir src
#. Place your application source code in the :file:`src` sub-directory. For
this example, we'll assume you created a file named :file:`src/main.c`.
#. Create a file named :file:`CMakeLists.txt` in the ``app`` directory with the
following contents:
.. code-block:: cmake
cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr)
project(my_zephyr_app)
target_sources(app PRIVATE src/main.c)
Notes:
- The ``cmake_minimum_required()`` call is required by CMake. It is also
invoked by the Zephyr package on the next line. CMake will error out if
its version is older than either the version in your
:file:`CMakeLists.txt` or the version number in the Zephyr package.
- ``find_package(Zephyr)`` pulls in the Zephyr build system, which creates a
CMake target named ``app`` (see :ref:`cmake_pkg`). Adding sources to this
target is how you include them in the build. The Zephyr package will
define ``Zephyr-Kernel`` as a CMake project and enable support for the
``C``, ``CXX``, ``ASM`` languages.
- ``project(my_zephyr_app)`` defines your application's CMake
project. This must be called after ``find_package(Zephyr)`` to avoid
interference with Zephyr's ``project(Zephyr-Kernel)``.
- ``target_sources(app PRIVATE src/main.c)`` is to add your source file to
the ``app`` target. This must come after ``find_package(Zephyr)`` which
defines the target. You can add as many files as you want with
``target_sources()``.
#. Create at least one Kconfig fragment for your application (usually named
:file:`prj.conf`) and set Kconfig option values needed by your application
there. See :ref:`application-kconfig`. If no Kconfig options need to be set,
create an empty file.
#. Configure any devicetree overlays needed by your application, usually in a
file named :file:`app.overlay`. See :ref:`set-devicetree-overlays`.
#. Set up any other files you may need, such as :ref:`twister <twister_script>`
configuration files, continuous integration files, documentation, etc.
.. _important-build-vars:
Important Build System Variables
********************************
You can control the Zephyr build system using many variables. This
section describes the most important ones that every Zephyr developer
should know about.
.. note::
The variables :makevar:`BOARD`, :makevar:`CONF_FILE`, and
:makevar:`DTC_OVERLAY_FILE` can be supplied to the build system in
3 ways (in order of precedence):
* As a parameter to the ``west build`` or ``cmake`` invocation via the
``-D`` command-line switch. If you have multiple overlay files, you should
use quotations, ``"file1.overlay;file2.overlay"``
* As :ref:`env_vars`.
* As a ``set(<VARIABLE> <VALUE>)`` statement in your :file:`CMakeLists.txt`
* :makevar:`ZEPHYR_BASE`: Zephyr base variable used by the build system.
``find_package(Zephyr)`` will automatically set this as a cached CMake
variable. But ``ZEPHYR_BASE`` can also be set as an environment variable in
order to force CMake to use a specific Zephyr installation.
* :makevar:`BOARD`: Selects the board that the application's build
will use for the default configuration. See :ref:`boards` for
built-in boards, and :ref:`board_porting_guide` for information on
adding board support.
* :makevar:`CONF_FILE`: Indicates the name of one or more Kconfig configuration
fragment files. Multiple filenames can be separated with either spaces or
semicolons. Each file includes Kconfig configuration values that override
the default configuration values.
See :ref:`initial-conf` for more information.
* :makevar:`EXTRA_CONF_FILE`: Additional Kconfig configuration fragment files.
Multiple filenames can be separated with either spaces or semicolons. This
can be useful in order to leave :makevar:`CONF_FILE` at its default value,
but "mix in" some additional configuration options.
* :makevar:`DTC_OVERLAY_FILE`: One or more devicetree overlay files to use.
Multiple files can be separated with semicolons.
See :ref:`set-devicetree-overlays` for examples and :ref:`devicetree-intro`
for information about devicetree and Zephyr.
* :makevar:`EXTRA_DTC_OVERLAY_FILE`: Additional devicetree overlay files to use.
Multiple files can be separated with semicolons. This can be useful to leave
:makevar:`DTC_OVERLAY_FILE` at its default value, but "mix in" some additional
overlay files.
* :makevar:`SHIELD`: see :ref:`shields`
* :makevar:`ZEPHYR_MODULES`: A `CMake list`_ containing absolute paths of
additional directories with source code, Kconfig, etc. that should be used in
the application build. See :ref:`modules` for details. If you set this
variable, it must be a complete list of all modules to use, as the build
system will not automatically pick up any modules from west.
* :makevar:`EXTRA_ZEPHYR_MODULES`: Like :makevar:`ZEPHYR_MODULES`, except these
will be added to the list of modules found via west, instead of replacing it.
* :makevar:`FILE_SUFFIX`: Optional suffix for filenames that will be added to Kconfig
fragments and devicetree overlays (if these files exists, otherwise will fallback to
the name without the prefix). See :ref:`application-file-suffixes` for details.
.. note::
You can use a :ref:`cmake_build_config_package` to share common settings for
these variables.
.. _zephyr-app-cmakelists:
Application CMakeLists.txt
**************************
Every application must have a :file:`CMakeLists.txt` file. This file is the
entry point, or top level, of the build system. The final :file:`zephyr.elf`
image contains both the application and the kernel libraries.
This section describes some of what you can do in your :file:`CMakeLists.txt`.
Make sure to follow these steps in order.
#. If you only want to build for one board, add the name of the board
configuration for your application on a new line. For example:
.. code-block:: cmake
set(BOARD qemu_x86)
Refer to :ref:`boards` for more information on available boards.
The Zephyr build system determines a value for :makevar:`BOARD` by checking
the following, in order (when a BOARD value is found, CMake stops looking
further down the list):
- Any previously used value as determined by the CMake cache takes highest
precedence. This ensures you don't try to run a build with a different
:makevar:`BOARD` value than you set during the build configuration step.
- Any value given on the CMake command line (directly or indirectly via
``west build``) using ``-DBOARD=YOUR_BOARD`` will be checked for and
used next.
- If an :ref:`environment variable <env_vars>` ``BOARD`` is set, its value
will then be used.
- Finally, if you set ``BOARD`` in your application :file:`CMakeLists.txt`
as described in this step, this value will be used.
#. If your application uses a configuration file or files other than
the usual :file:`prj.conf`, add lines setting the :makevar:`CONF_FILE`
variable to these files appropriately. If multiple filenames are given,
separate them by a single space or semicolon. CMake lists can be used to
build up configuration fragment files in a modular way when you want to
avoid setting :makevar:`CONF_FILE` in a single place. For example:
.. code-block:: cmake
set(CONF_FILE "fragment_file1.conf")
list(APPEND CONF_FILE "fragment_file2.conf")
See :ref:`initial-conf` for more information.
#. If your application uses devicetree overlays, you may need to set
:ref:`DTC_OVERLAY_FILE <important-build-vars>`.
See :ref:`set-devicetree-overlays`.
#. If your application has its own kernel configuration options,
create a :file:`Kconfig` file in the same directory as your
application's :file:`CMakeLists.txt`.
See :ref:`the Kconfig section of the manual <kconfig>` for detailed
Kconfig documentation.
An (unlikely) advanced use case would be if your application has its own
unique configuration **options** that are set differently depending on the
build configuration.
If you just want to set application specific **values** for existing Zephyr
configuration options, refer to the :makevar:`CONF_FILE` description above.
Structure your :file:`Kconfig` file like this:
.. literalinclude:: ../../../../develop/application/application-kconfig.include
:language: kconfig
.. note::
Environment variables in ``source`` statements are expanded directly, so
you do not need to define an ``option env="ZEPHYR_BASE"`` Kconfig
"bounce" symbol. If you use such a symbol, it must have the same name as
the environment variable.
See :ref:`kconfig_extensions` for more information.
The :file:`Kconfig` file is automatically detected when placed in
the application directory, but it is also possible for it to be
found elsewhere if the CMake variable :makevar:`KCONFIG_ROOT` is
set with an absolute path.
#. Specify that the application requires Zephyr on a new line, **after any
lines added from the steps above**:
.. code-block:: cmake
find_package(Zephyr)
project(my_zephyr_app)
.. note:: ``find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})`` can be used if
enforcing a specific Zephyr installation by explicitly
setting the ``ZEPHYR_BASE`` environment variable should be
supported. All samples in Zephyr supports the ``ZEPHYR_BASE``
environment variable.
#. Now add any application source files to the 'app' target
library, each on their own line, like so:
.. code-block:: cmake
target_sources(app PRIVATE src/main.c)
Below is a simple example :file:`CMakeList.txt`:
.. code-block:: cmake
set(BOARD qemu_x86)
find_package(Zephyr)
project(my_zephyr_app)
target_sources(app PRIVATE src/main.c)
The Cmake property ``HEX_FILES_TO_MERGE``
leverages the application configuration provided by
Kconfig and CMake to let you merge externally built hex files
with the hex file generated when building the Zephyr application.
For example:
.. code-block:: cmake
set_property(GLOBAL APPEND PROPERTY HEX_FILES_TO_MERGE
${app_bootloader_hex}
${PROJECT_BINARY_DIR}/${KERNEL_HEX_NAME}
${app_provision_hex})
.. _zephyr-app-cmakecache:
CMakeCache.txt
**************
CMake uses a CMakeCache.txt file as persistent key/value string
storage used to cache values between runs, including compile and build
options and paths to library dependencies. This cache file is created
when CMake is run in an empty build folder.
For more details about the CMakeCache.txt file see the official CMake
documentation `runningcmake`_ .
.. _runningcmake: http://cmake.org/runningcmake/
Application Configuration
*************************
.. _application-configuration-directory:
Application Configuration Directory
===================================
Zephyr will use configuration files from the application's configuration
directory except for files with an absolute path provided by the arguments
described earlier, for example ``CONF_FILE``, ``EXTRA_CONF_FILE``,
``DTC_OVERLAY_FILE``, and ``EXTRA_DTC_OVERLAY_FILE``.
The application configuration directory is defined by the
``APPLICATION_CONFIG_DIR`` variable.
``APPLICATION_CONFIG_DIR`` will be set by one of the sources below with the
highest priority listed first.
1. If ``APPLICATION_CONFIG_DIR`` is specified by the user with
``-DAPPLICATION_CONFIG_DIR=<path>`` or in a CMake file before
``find_package(Zephyr)`` then this folder is used a the application's
configuration directory.
2. The application's source directory.
.. _application-kconfig:
Kconfig Configuration
=====================
Application configuration options are usually set in :file:`prj.conf` in the
application directory. For example, C++ support could be enabled with this
assignment:
.. code-block:: cfg
CONFIG_CPP=y
Looking at :ref:`existing samples <samples-and-demos>` is a good way to get
started.
See :ref:`setting_configuration_values` for detailed documentation on setting
Kconfig configuration values. The :ref:`initial-conf` section on the same page
explains how the initial configuration is derived. See :ref:`kconfig-search`
for a complete list of configuration options.
See :ref:`hardening` for security information related with Kconfig options.
The other pages in the :ref:`Kconfig section of the manual <kconfig>` are also
worth going through, especially if you planning to add new configuration
options.
Experimental features
~~~~~~~~~~~~~~~~~~~~~
Zephyr is a project under constant development and thus there are features that
are still in early stages of their development cycle. Such features will be
marked ``[EXPERIMENTAL]`` in their Kconfig title.
The :kconfig:option:`CONFIG_WARN_EXPERIMENTAL` setting can be used to enable warnings
at CMake configure time if any experimental feature is enabled.
.. code-block:: cfg
CONFIG_WARN_EXPERIMENTAL=y
For example, if option ``CONFIG_FOO`` is experimental, then enabling it and
:kconfig:option:`CONFIG_WARN_EXPERIMENTAL` will print the following warning at
CMake configure time when you build an application:
.. code-block:: none
warning: Experimental symbol FOO is enabled.
Devicetree Overlays
===================
See :ref:`set-devicetree-overlays`.
.. _application-file-suffixes:
File Suffixes
=============
Zephyr applications might want to have a single code base with multiple configurations for
different build/product variants which would necessitate different Kconfig options and devicetree
configuration. In order to better configure this, Zephyr provides a :makevar:`FILE_SUFFIX` option
when configuring applications that can be automatically appended to filenames. This is applied to
Kconfig fragments and board overlays but with a fallback so that if such files do not exist, the
files without these suffixes will be used instead.
Given the following example project layout:
.. code-block:: none
<app>
├── CMakeLists.txt
├── prj.conf
├── prj_mouse.conf
├── boards
│ ├── native_sim.overlay
│ └── qemu_cortex_m3_mouse.overlay
└── src
└── main.c
* If this is built normally without ``FILE_SUFFIX`` being defined for ``native_sim`` then
``prj.conf`` and ``boards/native_sim.overlay`` will be used.
* If this is build normally without ``FILE_SUFFIX`` being defined for ``qemu_cortex_m3`` then
``prj.conf`` will be used, no application devicetree overlay will be used.
* If this is built with ``FILE_SUFFIX`` set to ``mouse`` for ``native_sim`` then
``prj_mouse.conf`` and ``boards/native_sim.overlay`` will be used (there is no
``native_sim_mouse.overlay`` file so it falls back to ``native_sim.overlay``).
* If this is build with ``FILE_SUFFIX`` set to ``mouse`` for ``qemu_cortex_m3`` then
``prj_mouse.conf`` will be used and ``boards/qemu_cortex_m3_mouse.overlay`` will be used.
.. note::
When ``CONF_FILE`` is set in the form of ``prj_X.conf`` then the ``X`` will be used as the
build type. If this is combined with ``FILE_SUFFIX`` then the file suffix option will take
priority over the build type.
Application-Specific Code
*************************
Application-specific source code files are normally added to the
application's :file:`src` directory. If the application adds a large
number of files the developer can group them into sub-directories
under :file:`src`, to whatever depth is needed.
Application-specific source code should not use symbol name prefixes that have
been reserved by the kernel for its own use. For more information, see `Naming
Conventions
<https://github.com/zephyrproject-rtos/zephyr/wiki/Naming-Conventions>`_.
Third-party Library Code
========================
It is possible to build library code outside the application's :file:`src`
directory but it is important that both application and library code targets
the same Application Binary Interface (ABI). On most architectures there are
compiler flags that control the ABI targeted, making it important that both
libraries and applications have certain compiler flags in common. It may also
be useful for glue code to have access to Zephyr kernel header files.
To make it easier to integrate third-party components, the Zephyr
build system has defined CMake functions that give application build
scripts access to the zephyr compiler options. The functions are
documented and defined in :zephyr_file:`cmake/modules/extensions.cmake`
and follow the naming convention ``zephyr_get_<type>_<format>``.
The following variables will often need to be exported to the
third-party build system.
* ``CMAKE_C_COMPILER``, ``CMAKE_AR``.
* ``ARCH`` and ``BOARD``, together with several variables that identify the
Zephyr kernel version.
:zephyr_file:`samples/application_development/external_lib` is a sample
project that demonstrates some of these features.
.. _build_an_application:
Building an Application
***********************
The Zephyr build system compiles and links all components of an application
into a single application image that can be run on simulated hardware or real
hardware.
Like any other CMake-based system, the build process takes place :ref:`in
two stages <cmake-details>`. First, build files (also known as a buildsystem)
are generated using the ``cmake`` command-line tool while specifying a
generator. This generator determines the native build tool the buildsystem
will use in the second stage.
The second stage runs the native build tool to actually build the
source files and generate an image. To learn more about these concepts refer to
the `CMake introduction`_ in the official CMake documentation.
Although the default build tool in Zephyr is :std:ref:`west <west>`, Zephyr's
meta-tool, which invokes ``cmake`` and the underlying build tool (``ninja`` or
``make``) behind the scenes, you can also choose to invoke ``cmake`` directly if
you prefer. On Linux and macOS you can choose between the ``make`` and
``ninja``
generators (i.e. build tools), whereas on Windows you need to use ``ninja``,
since ``make`` is not supported on this platform.
For simplicity we will use ``ninja`` throughout this guide, and if you
choose to use ``west build`` to build your application know that it will
default to ``ninja`` under the hood.
As an example, let's build the Hello World sample for the ``reel_board``:
.. zephyr-app-commands::
:tool: all
:app: samples/hello_world
:board: reel_board
:goals: build
On Linux and macOS, you can also build with ``make`` instead of ``ninja``:
Using west:
- to use ``make`` just once, add ``-- -G"Unix Makefiles"`` to the west build
command line; see the :ref:`west build <west-building-generator>`
documentation for an example.
- to use ``make`` by default from now on, run ``west config build.generator
"Unix Makefiles"``.
Using CMake directly:
.. zephyr-app-commands::
:tool: cmake
:app: samples/hello_world
:generator: make
:host-os: unix
:board: reel_board
:goals: build
Basics
======
#. Navigate to the application directory :file:`<app>`.
#. Enter the following commands to build the application's :file:`zephyr.elf`
image for the board specified in the command-line parameters:
.. zephyr-app-commands::
:tool: all
:cd-into:
:board: <board>
:goals: build
If desired, you can build the application using the configuration settings
specified in an alternate :file:`.conf` file using the :code:`CONF_FILE`
parameter. These settings will override the settings in the application's
:file:`.config` file or its default :file:`.conf` file. For example:
.. zephyr-app-commands::
:tool: all
:cd-into:
:board: <board>
:gen-args: -DCONF_FILE=prj.alternate.conf
:goals: build
:compact:
As described in the previous section, you can instead choose to permanently
set the board and configuration settings by either exporting :makevar:`BOARD`
and :makevar:`CONF_FILE` environment variables or by setting their values
in your :file:`CMakeLists.txt` using ``set()`` statements.
Additionally, ``west`` allows you to :ref:`set a default board
<west-building-config>`.
.. _build-directory-contents:
Build Directory Contents
========================
When using the Ninja generator a build directory looks like this:
.. code-block:: none
<app>/build
├── build.ninja
├── CMakeCache.txt
├── CMakeFiles
├── cmake_install.cmake
├── rules.ninja
└── zephyr
The most notable files in the build directory are:
* :file:`build.ninja`, which can be invoked to build the application.
* A :file:`zephyr` directory, which is the working directory of the
generated build system, and where most generated files are created and
stored.
After running ``ninja``, the following build output files will be written to
the :file:`zephyr` sub-directory of the build directory. (This is **not the
Zephyr base directory**, which contains the Zephyr source code etc. and is
described above.)
* :file:`.config`, which contains the configuration settings
used to build the application.
.. note::
The previous version of :file:`.config` is saved to :file:`.config.old`
whenever the configuration is updated. This is for convenience, as
comparing the old and new versions can be handy.
* Various object files (:file:`.o` files and :file:`.a` files) containing
compiled kernel and application code.
* :file:`zephyr.elf`, which contains the final combined application and
kernel binary. Other binary output formats, such as :file:`.hex` and
:file:`.bin`, are also supported.
.. _application_rebuild:
Rebuilding an Application
=========================
Application development is usually fastest when changes are continually tested.
Frequently rebuilding your application makes debugging less painful
as the application becomes more complex. It's usually a good idea to
rebuild and test after any major changes to the application's source files,
CMakeLists.txt files, or configuration settings.
.. important::
The Zephyr build system rebuilds only the parts of the application image
potentially affected by the changes. Consequently, rebuilding an application
is often significantly faster than building it the first time.
Sometimes the build system doesn't rebuild the application correctly
because it fails to recompile one or more necessary files. You can force
the build system to rebuild the entire application from scratch with the
following procedure:
#. Open a terminal console on your host computer, and navigate to the
build directory :file:`<app>/build`.
#. Enter one of the following commands, depending on whether you want to use
``west`` or ``cmake`` directly to delete the application's generated
files, except for the :file:`.config` file that contains the
application's current configuration information.
.. code-block:: console
west build -t clean
or
.. code-block:: console
ninja clean
Alternatively, enter one of the following commands to delete *all*
generated files, including the :file:`.config` files that contain
the application's current configuration information for those board
types.
.. code-block:: console
west build -t pristine
or
.. code-block:: console
ninja pristine
If you use west, you can take advantage of its capability to automatically
:ref:`make the build folder pristine <west-building-config>` whenever it is
required.
#. Rebuild the application normally following the steps specified
in :ref:`build_an_application` above.
.. _application_board_version:
Building for a board revision
=============================
The Zephyr build system has support for specifying multiple hardware revisions
of a single board with small variations. Using revisions allows the board
support files to make minor adjustments to a board configuration without
duplicating all the files described in :ref:`create-your-board-directory` for
each revision.
To build for a particular revision, use ``<board>@<revision>`` instead of plain
``<board>``. For example:
.. zephyr-app-commands::
:tool: all
:cd-into:
:board: <board>@<revision>
:goals: build
:compact:
Check your board's documentation for details on whether it has multiple
revisions, and what revisions are supported.
When targeting a board revision, the active revision will be printed at CMake
configure time, like this:
.. code-block:: console
-- Board: plank, Revision: 1.5.0
.. _application_run:
Run an Application
******************
An application image can be run on a real board or emulated hardware.
.. _application_run_board:
Running on a Board
==================
Most boards supported by Zephyr let you flash a compiled binary using
the ``flash`` target to copy the binary to the board and run it.
Follow these instructions to flash and run an application on real
hardware:
#. Build your application, as described in :ref:`build_an_application`.
#. Make sure your board is attached to your host computer. Usually, you'll do
this via USB.
#. Run one of these console commands from the build directory,
:file:`<app>/build`, to flash the compiled Zephyr image and run it on
your board:
.. code-block:: console
west flash
or
.. code-block:: console
ninja flash
The Zephyr build system integrates with the board support files to
use hardware-specific tools to flash the Zephyr binary to your
hardware, then run it.
Each time you run the flash command, your application is rebuilt and flashed
again.
In cases where board support is incomplete, flashing via the Zephyr build
system may not be supported. If you receive an error message about flash
support being unavailable, consult :ref:`your board's documentation <boards>`
for additional information on how to flash your board.
.. note:: When developing on Linux, it's common to need to install
board-specific udev rules to enable USB device access to
your board as a non-root user. If flashing fails,
consult your board's documentation to see if this is
necessary.
.. _application_run_qemu:
Running in an Emulator
======================
Zephyr has built-in emulator support for QEMU.
It allows you to run and test an application virtually, before
(or in lieu of) loading and running it on actual target hardware.
Check out :ref:`beyond-GSG` for additional steps needed on Windows.
Follow these instructions to run an application via QEMU:
#. Build your application for one of the QEMU boards, as described in
:ref:`build_an_application`.
For example, you could set ``BOARD`` to:
- ``qemu_x86`` to emulate running on an x86-based board
- ``qemu_cortex_m3`` to emulate running on an ARM Cortex M3-based board
#. Run one of these console commands from the build directory,
:file:`<app>/build`, to run the Zephyr binary in QEMU:
.. code-block:: console
west build -t run
or
.. code-block:: console
ninja run
#. Press :kbd:`Ctrl A, X` to stop the application from running
in QEMU.
The application stops running and the terminal console prompt
redisplays.
Each time you execute the run command, your application is rebuilt and run
again.
.. note::
If the (Linux only) :ref:`Zephyr SDK <toolchain_zephyr_sdk>` is installed, the ``run``
target will use the SDK's QEMU binary by default. To use another version of
QEMU, :ref:`set the environment variable <env_vars>` ``QEMU_BIN_PATH``
to the path of the QEMU binary you want to use instead.
.. note::
You can choose a specific emulator by appending ``_<emulator>`` to your
target name, for example ``west build -t run_qemu`` or ``ninja run_qemu``
for QEMU.
.. _custom_board_definition:
Custom Board, Devicetree and SOC Definitions
********************************************
In cases where the board or platform you are developing for is not yet
supported by Zephyr, you can add board, Devicetree and SOC definitions
to your application without having to add them to the Zephyr tree.
The structure needed to support out-of-tree board and SOC development
is similar to how boards and SOCs are maintained in the Zephyr tree. By using
this structure, it will be much easier to upstream your platform related work into
the Zephyr tree after your initial development is done.
Add the custom board to your application or a dedicated repository using the
following structure:
.. code-block:: console
boards/
soc/
CMakeLists.txt
prj.conf
README.rst
src/
where the ``boards`` directory hosts the board you are building for:
.. code-block:: console
.
├── boards
│ └── vendor
│ └── my_custom_board
│ ├── doc
│ │ └── img
│ └── support
└── src
and the ``soc`` directory hosts any SOC code. You can also have boards that are
supported by a SOC that is available in the Zephyr tree.
Boards
======
Use the vendor name as the folder name (which must match the vendor prefix in
:zephyr_file:`dts/bindings/vendor-prefixes.txt` if submitting upstream to Zephyr, or be
``others`` if it is not a vendor board) under ``boards`` for ``my_custom_board``.
Documentation (under ``doc/``) and support files (under ``support/``) are optional, but
will be needed when submitting to Zephyr.
The contents of ``my_custom_board`` should follow the same guidelines for any
Zephyr board, and provide the following files::
my_custom_board_defconfig
my_custom_board.dts
my_custom_board.yaml
board.cmake
board.h
CMakeLists.txt
doc/
Kconfig.my_custom_board
Kconfig.defconfig
support/
Once the board structure is in place, you can build your application
targeting this board by specifying the location of your custom board
information with the ``-DBOARD_ROOT`` parameter to the CMake
build system:
.. zephyr-app-commands::
:tool: all
:board: <board name>
:gen-args: -DBOARD_ROOT=<path to boards>
:goals: build
:compact:
This will use your custom board configuration and will generate the
Zephyr binary into your application directory.
You can also define the ``BOARD_ROOT`` variable in the application
:file:`CMakeLists.txt` file. Make sure to do so **before** pulling in the Zephyr
boilerplate with ``find_package(Zephyr ...)``.
.. note::
When specifying ``BOARD_ROOT`` in a CMakeLists.txt, then an absolute path must
be provided, for example ``list(APPEND BOARD_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/<extra-board-root>)``.
When using ``-DBOARD_ROOT=<board-root>`` both absolute and relative paths can
be used. Relative paths are treated relatively to the application directory.
SOC Definitions
===============
Similar to board support, the structure is similar to how SOCs are maintained in
the Zephyr tree, for example:
.. code-block:: none
soc
└── st
└── stm32
├── common
└── stm32l0x
The file :zephyr_file:`soc/Kconfig` will create the top-level
``SoC/CPU/Configuration Selection`` menu in Kconfig.
Out of tree SoC definitions can be added to this menu using the ``SOC_ROOT``
CMake variable. This variable contains a semicolon-separated list of directories
which contain SoC support files.
Following the structure above, the following files can be added to load
more SoCs into the menu.
.. code-block:: none
soc
└── st
└── stm32
└── stm32l0x
├── Kconfig
├── Kconfig.soc
└── Kconfig.defconfig
The Kconfig files above may describe the SoC or load additional SoC Kconfig files.
An example of loading ``stm31l0`` specific Kconfig files in this structure:
.. code-block:: none
soc
└── st
└── stm32
├── Kconfig.soc
└── stm32l0x
└── Kconfig.soc
can be done with the following content in ``st/stm32/Kconfig.soc``:
.. code-block:: kconfig
rsource "*/Kconfig.soc"
Once the SOC structure is in place, you can build your application
targeting this platform by specifying the location of your custom platform
information with the ``-DSOC_ROOT`` parameter to the CMake
build system:
.. zephyr-app-commands::
:tool: all
:board: <board name>
:gen-args: -DSOC_ROOT=<path to soc> -DBOARD_ROOT=<path to boards>
:goals: build
:compact:
This will use your custom platform configurations and will generate the
Zephyr binary into your application directory.
See :ref:`modules_build_settings` for information on setting SOC_ROOT in a module's
:file:`zephyr/module.yml` file.
Or you can define the ``SOC_ROOT`` variable in the application
:file:`CMakeLists.txt` file. Make sure to do so **before** pulling in the
Zephyr boilerplate with ``find_package(Zephyr ...)``.
.. note::
When specifying ``SOC_ROOT`` in a CMakeLists.txt, then an absolute path must
be provided, for example ``list(APPEND SOC_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/<extra-soc-root>``.
When using ``-DSOC_ROOT=<soc-root>`` both absolute and relative paths can be
used. Relative paths are treated relatively to the application directory.
.. _dts_root:
Devicetree Definitions
======================
Devicetree directory trees are found in ``APPLICATION_SOURCE_DIR``,
``BOARD_DIR``, and ``ZEPHYR_BASE``, but additional trees, or DTS_ROOTs,
can be added by creating this directory tree::
include/
dts/common/
dts/arm/
dts/
dts/bindings/
Where 'arm' is changed to the appropriate architecture. Each directory
is optional. The binding directory contains bindings and the other
directories contain files that can be included from DT sources.
Once the directory structure is in place, you can use it by specifying
its location through the ``DTS_ROOT`` CMake Cache variable:
.. zephyr-app-commands::
:tool: all
:board: <board name>
:gen-args: -DDTS_ROOT=<path to dts root>
:goals: build
:compact:
You can also define the variable in the application :file:`CMakeLists.txt`
file. Make sure to do so **before** pulling in the Zephyr boilerplate with
``find_package(Zephyr ...)``.
.. note::
When specifying ``DTS_ROOT`` in a CMakeLists.txt, then an absolute path must
be provided, for example ``list(APPEND DTS_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/<extra-dts-root>``.
When using ``-DDTS_ROOT=<dts-root>`` both absolute and relative paths can be
used. Relative paths are treated relatively to the application directory.
Devicetree source are passed through the C preprocessor, so you can
include files that can be located in a ``DTS_ROOT`` directory. By
convention devicetree include files have a ``.dtsi`` extension.
You can also use the preprocessor to control the content of a devicetree
file, by specifying directives through the ``DTS_EXTRA_CPPFLAGS`` CMake
Cache variable:
.. zephyr-app-commands::
:tool: all
:board: <board name>
:gen-args: -DDTS_EXTRA_CPPFLAGS=-DTEST_ENABLE_FEATURE
:goals: build
:compact:
.. _CMake: https://www.cmake.org
.. _CMake introduction: https://cmake.org/cmake/help/latest/manual/cmake.1.html#description
.. _CMake list: https://cmake.org/cmake/help/latest/manual/cmake-language.7.html#lists
.. _example-application: https://github.com/zephyrproject-rtos/example-application
Part 3
한국어 전문 번역
Application 개발
개요
Zephyr build system은 CMake를 기반으로 합니다.
Build system은 application 중심입니다. Zephyr 기반 application이 Zephyr source code build를 시작해야 합니다. Application build가 application과 Zephyr 자체의 configuration·build process를 모두 제어하고 둘을 하나의 binary로 compile합니다.
Main zephyr repository에는 Zephyr source code, configuration file, build system이 있습니다. Repository 옆에는 third-party source code integration을 제공하는 여러 module도 설치했을 가능성이 큽니다.
Application directory의 file이 Zephyr·module과 application을 연결합니다. 이 directory에는 application별 configuration file과 source code 같은 모든 application 전용 file이 있습니다.
간단한 Zephyr application의 file 구조:
<app>
├── CMakeLists.txt
├── app.overlay
├── prj.conf
├── VERSION
└── src
└── main.c각 file의 역할:
- CMakeLists.txt: Build system에 다른 application file 위치를 알려 주고 application directory를 Zephyr CMake build system에 연결합니다. Board별 configuration, real·emulated hardware에서 compile binary 실행·debug 등의 기능을 사용할 수 있게 합니다.
- app.overlay: Build 대상 board의 base devicetree에 적용할 application별 변경을 지정하는 devicetree overlay입니다. 보통 application이 사용하는 hardware를 설정합니다. Build system은 기본적으로
app.overlay를 찾으며 overlay를 더 추가할 수 있고 다른 default file도 검색합니다. - prj.conf: 하나 이상의 Kconfig option에 application별 value를 지정하는 Kconfig fragment입니다. 다른 setting과 merge되어 final configuration을 만들며 보통 application의 software feature를 설정합니다. Build system은 기본적으로
prj.conf를 찾고 fragment를 더 추가할 수 있습니다. - VERSION: 여러 version information field가 있는 text file입니다. Application lifecycle을 관리하고 application image signing 시 version 제공을 자동화할 수 있습니다.
- main.c: Source code file입니다. Application은 보통 C, C++, assembly source를 포함하며 Zephyr convention은
<app>/src에 두는 것입니다.
Application을 정의한 뒤 CMake로 build directory를 생성합니다. 이곳의 file로 application과 Zephyr를 build하고 link해 board에서 실행할 final binary를 만듭니다. 가장 쉬운 방법은 west build이지만 CMake를 직접 사용할 수도 있습니다. Build artifact는 항상 별도 build directory에 생성되며 Zephyr는 in-tree build를 지원하지 않습니다.
다음 절은 Zephyr application 생성·build·실행 방법과 자세한 reference material을 설명합니다.
Application type
<app> 위치에 따라 Zephyr application을 세 가지 기본 type으로 구분합니다.
| Application type | <app> 위치 |
|---|---|
| Zephyr repository application | Zephyr repository |
| Zephyr workspace application | Zephyr가 설치된 west workspace |
| Zephyr freestanding application | 그 밖의 위치 |
각 type은 아래에서 설명합니다. Build system이 type별로 어떻게 지원하는지는 Zephyr CMake package를 참고하십시오.
Zephyr repository application
Zephyr west workspace 안의 zephyr source repository에 위치한 application입니다. 다음 예에서 hello_world sample이 repository application입니다.
zephyrproject/
├─── .west/
│ └─── config
└─── zephyr/
├── arch/
├── boards/
├── cmake/
├── samples/
│ ├── hello_world/
│ └── ...
├── tests/
└── ...Zephyr workspace application
West workspace 안이지만 zephyr repository 밖에 위치한 application입니다. 다음 예에서 app이 workspace application입니다.
zephyrproject/
├─── .west/
│ └─── config
├─── zephyr/
├─── bootloader/
├─── modules/
├─── tools/
├─── <vendor/private-repositories>/
└─── applications/
└── app/Zephyr freestanding application
Zephyr west workspace 밖에 있는 application입니다. 다음 예에서 app이 freestanding application입니다.
<home>/
├─── zephyrproject/
│ ├─── .west/
│ │ └─── config
│ ├── zephyr/
│ ├── bootloader/
│ ├── modules/
│ └── ...
│
└─── app/
├── CMakeLists.txt
├── prj.conf
└── src/
└── main.cApplication 만들기
Reference workspace application을 사용하거나 application을 직접 만들 수 있습니다.
Reference workspace application 사용
example-application Git repository에는 reference workspace application이 있습니다. 자체 application을 만들 때 이를 reference로 사용하는 것이 좋습니다.
Example application repository가 보여 주는 일반 feature:
- Custom board port
- Custom devicetree binding
- Custom device driver
- Twister를 포함한 Continuous Integration(CI) 설정
- Custom west extension command
기본 example-application 사용법
기존 Zephyr workspace 안에서 시작하는 가장 쉬운 절차:
cd <home>/zephyrproject
git clone https://github.com/zephyrproject-rtos/example-application my-appmy-app directory 이름은 임의로 바꿀 수 있습니다. 이 directory로 이동해 필요에 맞게 내용을 수정하십시오. 기존 Zephyr workspace를 사용하므로 west build와 다른 west command로 build·flash·debug할 수 있습니다.
고급 example-application 사용법
Example application repository를 자체 Zephyr 기반 software distribution의 출발점으로 사용할 수도 있습니다. 다음 작업이 가능합니다.
- 필요 없는 Zephyr module 제거
- 자체 custom repository 추가
- Zephyr가 제공한 repository를 자체 version으로 override
- 결과를 다른 사람과 공유하고 협업
west.yml이 있으므로 example-application은 west manifest repository이기도 합니다. 새 custom workspace 생성 절차:
cd <home>
mkdir my-workspace
cd my-workspace
git clone https://github.com/zephyrproject-rtos/example-application my-manifest-repo
west init -l my-manifest-repo이 명령은 my-manifest-repo를 manifest repository로 하는 T2 topology workspace를 만듭니다. my-workspace와 my-manifest-repo 이름은 필요에 맞게 바꿀 수 있습니다.
Clone 직후 content를 출발점으로 my-manifest-repo/west.yml의 repository 집합을 원하는 대로 수정하고 다른 file도 변경합니다. 준비되면 다음을 실행합니다.
west updateWorkspace를 사용할 수 있게 됩니다. my-manifest-repo를 다른 곳에 push하면 작업을 공유할 수 있습니다. 예를 들어 https://git.example.com/my-manifest-repo에 push했다면 다른 사람은 다음으로 같은 workspace를 구성합니다.
west init -m https://git.example.com/my-manifest-repo my-workspace
cd my-workspace
west updatemy-manifest-repo/west.yml에서 repository를 추가·제거하거나 content revision을 바꾸고 사용 repository에 변경을 push하며 공유 software를 협업할 수 있습니다.
Application을 직접 만들기
다음 절차로 기본 application directory를 처음부터 만들 수 있습니다. 하지만 example-application이나 Zephyr sample·demo를 출발점으로 쓰는 편이 더 쉽습니다.
- Application directory를 만듭니다. Unix shell 또는 Windows
cmd.exe예:mkdir app - Source code file을 만듭니다. Project file과 source를 쉽게 구분하도록 모든 application source를
srcsubdirectory에 두는 것이 좋습니다.cd app mkdir src src아래에 source code를 둡니다. 여기서는src/main.c를 만들었다고 가정합니다.appdirectory에 다음CMakeLists.txt를 만듭니다.cmake_minimum_required(VERSION 3.20.0) find_package(Zephyr) project(my_zephyr_app) target_sources(app PRIVATE src/main.c)cmake_minimum_required()는 CMake에 필요합니다. 다음 줄의 Zephyr package도 이를 호출하며 CMake version이 application 또는 Zephyr package 요구 version보다 오래되면 error가 납니다.find_package(Zephyr)는 Zephyr build system을 가져오고appCMake target을 만듭니다. Source를 이 target에 추가해 build에 포함합니다. Zephyr package는Zephyr-KernelCMake project를 정의하고 C·CXX·ASM language 지원을 enable합니다.project(my_zephyr_app)는 application CMake project를 정의합니다. Zephyr의project(Zephyr-Kernel)과 간섭하지 않도록find_package(Zephyr)뒤에 호출해야 합니다.target_sources(app PRIVATE src/main.c)는 source file을 app target에 추가합니다. Target을 정의하는 find_package 뒤에 와야 하며 원하는 만큼 file을 추가할 수 있습니다.
- Application용 Kconfig fragment를 최소 하나, 보통
prj.conf이름으로 만들고 필요한 Kconfig option value를 설정합니다. 설정할 option이 없으면 빈 file을 만듭니다. - 보통
app.overlay에 필요한 devicetree overlay를 구성합니다. - Twister configuration, CI file, documentation 등 필요한 다른 file을 설정합니다.
중요한 build system variable
많은 variable로 Zephyr build system을 제어할 수 있습니다. 모든 Zephyr developer가 알아야 할 주요 variable을 설명합니다.
ZEPHYR_BASE: Build system이 사용하는 Zephyr base입니다.find_package(Zephyr)가 cached CMake variable로 자동 설정합니다. Environment variable로 지정해 특정 Zephyr installation을 강제할 수도 있습니다.BOARD: Application build가 default configuration에 사용할 board를 선택합니다.CONF_FILE: 하나 이상의 Kconfig configuration fragment 이름입니다. 여러 filename은 space 또는 semicolon으로 구분하며 default configuration value를 override합니다.EXTRA_CONF_FILE: 추가 Kconfig fragment입니다. CONF_FILE default는 유지하면서 option을 더 섞을 때 유용합니다.DTC_OVERLAY_FILE: 사용할 devicetree overlay file 하나 이상이며 semicolon으로 구분합니다.EXTRA_DTC_OVERLAY_FILE: DTC_OVERLAY_FILE default를 유지하면서 추가 overlay를 섞습니다.SHIELD: Build에 사용할 shield를 선택합니다.ZEPHYR_MODULES: Application build에 사용할 source, Kconfig 등을 담은 추가 directory의 absolute path CMake list입니다. 설정하면 west가 찾은 module을 자동 포함하지 않으므로 사용할 module 전체 목록이어야 합니다.EXTRA_ZEPHYR_MODULES: ZEPHYR_MODULES와 비슷하지만 west가 찾은 module을 대체하지 않고 목록에 추가합니다.FILE_SUFFIX: Kconfig fragment와 devicetree overlay filename에 덧붙일 optional suffix입니다. Suffix file이 없으면 suffix 없는 이름으로 fallback합니다.
Application CMakeLists.txt
CMakeLists.txt는 모든 application에 필요하며 build system의 entry point입니다. Final zephyr.elf image는 application과 kernel library를 모두 포함합니다. 다음 단계를 순서대로 따르십시오.
- Board 하나만 target으로 build하려면 board configuration 이름을 설정합니다.
BOARD 결정 우선순위:set(BOARD qemu_x86)- CMake cache에서 확인한 이전 사용 value가 가장 높습니다. Configuration 단계와 다른 BOARD로 build하지 않게 합니다.
west build를 통한 간접 전달을 포함해 CMake command line의-DBOARD=YOUR_BOARDvalueBOARDenvironment variable- Application
CMakeLists.txt의 BOARD value
- 일반
prj.conf이외 configuration file을 사용하면CONF_FILE을 설정합니다. 여러 filename은 space나 semicolon으로 구분하며 CMake list로 modular하게 구성할 수 있습니다.set(CONF_FILE "fragment_file1.conf") list(APPEND CONF_FILE "fragment_file2.conf") - Devicetree overlay를 사용한다면
DTC_OVERLAY_FILE설정이 필요할 수 있습니다. - Application 자체 kernel configuration option이 있으면
CMakeLists.txt와 같은 directory에Kconfig를 만듭니다. Existing option의 application value만 설정하려면 CONF_FILE을 사용합니다. Kconfig file 구조:# SPDX-License-Identifier: Apache-2.0 mainmenu "Your Application Name" # Your application configuration options go here # Sources Kconfig.zephyr in the Zephyr root directory. # # Note: All 'source' statements work relative to the Zephyr root directory (due # to the $srctree environment variable being set to $ZEPHYR_BASE). If you want # to 'source' relative to the current Kconfig file instead, use 'rsource' (or a # path relative to the Zephyr root). source "Kconfig.zephyr" - 앞 단계의 모든 line 뒤에 Zephyr dependency를 선언합니다.
find_package(Zephyr) project(my_zephyr_app) - Application source file을 각각 app target library에 추가합니다.
target_sources(app PRIVATE src/main.c)
간단한 CMakeLists.txt 전체 예:
set(BOARD qemu_x86)
find_package(Zephyr)
project(my_zephyr_app)
target_sources(app PRIVATE src/main.c)HEX_FILES_TO_MERGE CMake property는 Kconfig와 CMake application configuration을 활용해 외부에서 build한 hex file을 Zephyr application build의 hex file과 merge합니다.
set_property(GLOBAL APPEND PROPERTY HEX_FILES_TO_MERGE
${app_bootloader_hex}
${PROJECT_BINARY_DIR}/${KERNEL_HEX_NAME}
${app_provision_hex})CMakeCache.txt
CMakeCache.txt는 compile·build option과 library dependency path를 포함해 CMake 실행 사이에 value를 cache하는 persistent key/value string storage입니다. 빈 build folder에서 CMake를 실행할 때 생성됩니다.
자세한 내용은 공식 CMake runningcmake 문서를 참고하십시오.
Application configuration
Application configuration directory
CONF_FILE, EXTRA_CONF_FILE, DTC_OVERLAY_FILE, EXTRA_DTC_OVERLAY_FILE argument로 absolute path를 준 file을 제외하면 Zephyr는 application configuration directory의 configuration file을 사용합니다.
APPLICATION_CONFIG_DIR variable이 이 directory를 정의하며 우선순위는 다음과 같습니다.
-DAPPLICATION_CONFIG_DIR=<path>또는find_package(Zephyr)전 CMake file에서 사용자가 지정한 folder- Application source directory
Kconfig configuration
Application configuration option은 보통 application directory의 prj.conf에 설정합니다. C++ support enable 예:
CONFIG_CPP=yExisting sample을 참고하면 시작하기 좋습니다. Kconfig value 설정·initial configuration derivation·전체 option search와 security hardening 문서를 함께 참고하십시오. 새 option을 추가하려면 Kconfig manual도 읽는 것이 좋습니다.
Experimental feature
Zephyr는 계속 개발되므로 개발 주기 초기에 있는 feature가 있습니다. 이런 feature는 Kconfig title에 [EXPERIMENTAL]로 표시합니다.
CONFIG_WARN_EXPERIMENTAL을 설정하면 experimental feature가 enable될 때 CMake configure 단계에 warning을 표시합니다.
CONFIG_WARN_EXPERIMENTAL=y예를 들어 CONFIG_FOO가 experimental이면 CONFIG_FOO와 CONFIG_WARN_EXPERIMENTAL을 enable한 application build의 CMake configure 단계에 다음 warning이 출력됩니다.
warning: Experimental symbol FOO is enabled.Devicetree overlay
설정 방법은 Devicetree overlay를 참고하십시오.
File suffix
하나의 codebase로 여러 build·product variant를 만들면 서로 다른 Kconfig option과 devicetree configuration이 필요할 수 있습니다. Zephyr는 filename에 자동으로 붙는 FILE_SUFFIX를 제공합니다. Kconfig fragment와 board overlay에 적용하며 해당 file이 없으면 suffix 없는 file로 fallback합니다.
예제 project layout:
<app>
├── CMakeLists.txt
├── prj.conf
├── prj_mouse.conf
├── boards
│ ├── native_sim.overlay
│ └── qemu_cortex_m3_mouse.overlay
└── src
└── main.cnative_sim을 FILE_SUFFIX 없이 build하면prj.conf와boards/native_sim.overlay를 사용합니다.qemu_cortex_m3를 FILE_SUFFIX 없이 build하면prj.conf를 사용하고 application devicetree overlay는 사용하지 않습니다.native_sim에서 FILE_SUFFIX를mouse로 하면prj_mouse.conf와boards/native_sim.overlay를 사용합니다.native_sim_mouse.overlay가 없어 fallback합니다.qemu_cortex_m3에서 FILE_SUFFIX를mouse로 하면prj_mouse.conf와boards/qemu_cortex_m3_mouse.overlay를 사용합니다.
Application별 code
src에 application source를 두는 것이 일반적입니다. File이 많으면 필요한 깊이만큼 subdirectory로 묶을 수 있습니다.
Application source는 kernel이 예약한 symbol name prefix를 사용하면 안 됩니다. Naming Conventions를 참고하십시오.
Third-party library code
src 밖의 library code를 build할 수 있지만 application과 library가 같은 ABI(Application Binary Interface)를 target해야 합니다. 대부분 architecture는 compiler flag로 ABI를 제어하므로 일부 flag를 공유해야 하며 glue code에 Zephyr kernel header가 필요할 수도 있습니다.
Third-party component integration을 쉽게 하려고 Zephyr build system은 application build script가 Zephyr compiler option에 접근하는 CMake function을 제공합니다. cmake/modules/extensions.cmake에 정의·문서화되어 있고 zephyr_get_<type>_<format> naming convention을 따릅니다.
Third-party build system으로 export할 때 자주 필요한 variable:
CMAKE_C_COMPILER,CMAKE_ARARCH,BOARD, Zephyr kernel version 식별 variable
samples/application_development/external_lib가 이 feature를 보여 주는 sample project입니다.
Application build
Zephyr build system은 application의 모든 component를 compile·link해 simulated 또는 real hardware에서 실행할 하나의 application image를 만듭니다.
다른 CMake system처럼 build는 두 단계입니다. 첫 단계는 generator를 지정해 cmake로 buildsystem을 생성합니다. Generator가 두 번째 단계의 native build tool을 결정합니다. 두 번째 단계는 native tool로 source를 build해 image를 만듭니다. CMake introduction을 참고하십시오.
Zephyr default meta-tool은 west이며 내부에서 CMake와 ninja 또는 make를 호출합니다. CMake를 직접 실행할 수도 있습니다. Linux·macOS는 make와 ninja를 선택할 수 있지만 Windows는 make를 지원하지 않아 ninja를 사용해야 합니다. 이 guide는 ninja를 사용하며 west build도 기본적으로 ninja를 사용합니다.
reel_board용 Hello World sample build 예:
west build -b reel_board samples/hello_world# Use cmake to configure a Ninja-based buildsystem:
cmake -Bbuild -GNinja -DBOARD=reel_board samples/hello_world
# Now run the build tool on the generated build system:
ninja -Cbuild# Use cmake to configure a Make-based buildsystem:
cmake -Bbuild -DBOARD=reel_board samples/hello_world
# Now run the build tool on the generated build system:
make -CbuildLinux와 macOS에서 ninja 대신 make를 사용할 수 있습니다.
west build -- -G"Unix Makefiles"로 한 번만 make를 사용합니다.west config build.generator "Unix Makefiles"로 앞으로 default를 make로 설정합니다.
기본 절차
- Application directory
<app>로 이동합니다. - Command-line의 board용
zephyr.elf를 build합니다.west build -b <board>
Alternativemkdir build && cd build # Use cmake to configure a Ninja-based buildsystem: cmake -GNinja -DBOARD=<board> .. # Now run the build tool on the generated build system: ninja.conf를 쓰려면CONF_FILEparameter로 application.config또는 default conf setting을 override합니다.west build -b <board> -- -DCONF_FILE=prj.alternate.conf
BOARD와 CONF_FILE environment variable 또는 CMakeLists.txt set statement로 영구 설정할 수도 있고 west default board도 설정할 수 있습니다.mkdir build && cd build cmake -GNinja -DBOARD=<board> -DCONF_FILE=prj.alternate.conf .. ninja
Build directory 내용
Ninja generator를 사용한 build directory:
<app>/build
├── build.ninja
├── CMakeCache.txt
├── CMakeFiles
├── cmake_install.cmake
├── rules.ninja
└── zephyr주요 항목:
build.ninja: Application build에 호출할 수 있습니다.zephyrdirectory: 생성 build system의 working directory이며 대부분의 generated file이 만들어지고 저장됩니다.
ninja 실행 뒤 build directory의 zephyr subdirectory에 다음 output이 생깁니다. 이는 Zephyr source를 담은 Zephyr base directory가 아닙니다.
.config: Build에 사용한 configuration setting입니다. Configuration을 갱신할 때 이전 version은 비교 편의를 위해.config.old에 저장됩니다..o,.a등 compile된 kernel·application code object filezephyr.elf: Final combined application·kernel binary입니다..hex,.bin도 지원합니다.
Application rebuild
변경을 계속 test할 때 application 개발이 가장 빠릅니다. Source, CMakeLists.txt, configuration을 크게 바꿀 때마다 rebuild·test하면 복잡해져도 debug 부담이 줄어듭니다.
필요 file을 다시 compile하지 못해 잘못 rebuild할 때는 다음 절차로 처음부터 강제 rebuild합니다.
- Host terminal을 열고 build directory
<app>/build로 이동합니다. - 현재 configuration
.config를 제외한 generated file을 지우려면 다음 중 하나를 실행합니다.west build -t cleanninja clean.config까지 모두 지우려면 pristine target을 사용합니다.west build -t pristine
West는 필요할 때 build folder를 자동 pristine으로 만들 수도 있습니다.ninja pristine - 앞의 Application build 절차로 정상 rebuild합니다.
Board revision용 build
Zephyr는 작은 차이가 있는 한 board의 여러 hardware revision을 지정할 수 있습니다. 각 revision마다 board support file 전체를 복제하지 않고 사소한 configuration을 조정합니다.
<board> 대신 <board>@<revision>을 사용합니다.
west build -b <board>@<revision>mkdir build && cd build
cmake -GNinja -DBOARD=<board>@<revision> ..
ninja지원 revision은 board documentation을 확인하십시오. Target revision은 CMake configure 때 다음처럼 출력됩니다.
-- Board: plank, Revision: 1.5.0Application 실행
Application image는 real board 또는 emulated hardware에서 실행할 수 있습니다.
Board에서 실행
flash target으로 compile binary를 board에 copy하고 실행할 수 있는 board가 대부분입니다.
- 앞 절처럼 application을 build합니다.
- 보통 USB로 board를 host computer에 연결합니다.
- Build directory
<app>/build에서 다음 중 하나로 Zephyr image를 flash하고 실행합니다.west flashninja flash
Build system은 board support file과 통합해 hardware별 tool로 Zephyr binary를 flash하고 실행합니다. Flash command를 실행할 때마다 application을 rebuild하고 다시 flash합니다.
Board support가 불완전하면 build system flashing을 지원하지 않을 수 있습니다. Flash support unavailable error가 나면 board documentation의 방법을 따르십시오.
Emulator에서 실행
Zephyr는 QEMU emulator를 built-in 지원해 실제 target hardware에 load하기 전 또는 그 대신 application을 virtual로 실행·test할 수 있습니다.
Windows에서는 Getting Started 이후 추가 설정을 확인하십시오.
- QEMU board용 application을 build합니다. 예를 들어
qemu_x86은 x86 board,qemu_cortex_m3는 ARM Cortex-M3 board를 emulate합니다. - Build directory에서 다음 중 하나로 QEMU에서 실행합니다.
west build -t runninja run Ctrl A, X를 눌러 QEMU application을 중지하면 terminal prompt가 다시 나타납니다.
Run command를 실행할 때마다 application을 rebuild하고 다시 실행합니다.
Custom board·Devicetree·SoC 정의
개발 board나 platform을 Zephyr가 아직 지원하지 않으면 Zephyr tree에 추가하지 않고 application에 board, Devicetree, SoC definition을 넣을 수 있습니다.
Out-of-tree board·SoC 구조는 Zephyr tree의 구조와 비슷하므로 초기 개발 뒤 upstream하기 쉽습니다.
Application 또는 전용 repository 구조:
boards/
soc/
CMakeLists.txt
prj.conf
README.rst
src/boards directory의 custom board 예:
.
├── boards
│ └── vendor
│ └── my_custom_board
│ ├── doc
│ │ └── img
│ └── support
└── srcsoc에는 SoC code를 둡니다. Zephyr tree의 SoC가 지원하는 custom board도 가능합니다.
Board
boards 아래 vendor folder 이름은 upstream할 때 dts/bindings/vendor-prefixes.txt의 prefix와 일치해야 하며 vendor board가 아니면 others를 사용합니다.
doc/ documentation과 support/ file은 선택 사항이지만 Zephyr 제출에는 필요합니다.
Custom board가 제공할 file:
my_custom_board_defconfig
my_custom_board.dts
my_custom_board.yaml
board.cmake
board.h
CMakeLists.txt
doc/
Kconfig.my_custom_board
Kconfig.defconfig
support/-DBOARD_ROOT로 custom board 정보 위치를 지정해 build합니다.
west build -b <board name> -- -DBOARD_ROOT=<path to boards>cmake -Bbuild -GNinja -DBOARD=<board name> -DBOARD_ROOT=<path to boards> .
ninja -CbuildCustom board configuration을 사용해 application directory에 Zephyr binary를 생성합니다. CMakeLists.txt에서 BOARD_ROOT를 정의할 수도 있지만 find_package로 Zephyr를 가져오기 전에 해야 합니다.
SoC definition
Board support처럼 Zephyr tree의 SoC 유지보수 구조를 따릅니다.
soc
└── st
└── stm32
├── common
└── stm32l0xsoc/Kconfig가 Kconfig의 SoC/CPU/Configuration Selection 최상위 menu를 만듭니다. Semicolon-separated directory list인 SOC_ROOT CMake variable로 out-of-tree SoC definition을 추가합니다.
추가 SoC를 load할 file 구조:
soc
└── st
└── stm32
└── stm32l0x
├── Kconfig
├── Kconfig.soc
└── Kconfig.defconfig각 Kconfig file은 SoC를 설명하거나 추가 SoC Kconfig를 load할 수 있습니다. STM32L0 전용 Kconfig load 구조:
soc
└── st
└── stm32
├── Kconfig.soc
└── stm32l0x
└── Kconfig.socst/stm32/Kconfig.soc 내용:
rsource "*/Kconfig.soc"-DSOC_ROOT와 custom board 위치로 build합니다.
west build -b <board name> -- -DSOC_ROOT=<path to soc> -DBOARD_ROOT=<path to boards>cmake -Bbuild -GNinja -DBOARD=<board name> -DSOC_ROOT=<path to soc> -DBOARD_ROOT=<path to boards> .
ninja -CbuildCustom platform configuration으로 application directory에 Zephyr binary를 생성합니다. Module의 zephyr/module.yml에서도 SOC_ROOT를 설정할 수 있습니다. CMakeLists.txt에서 정의한다면 find_package 전에 해야 합니다.
Devicetree definition
APPLICATION_SOURCE_DIR, BOARD_DIR, ZEPHYR_BASE에서 devicetree tree를 찾습니다. 추가 DTS_ROOT는 다음 구조로 만들 수 있습니다.
include/
dts/common/
dts/arm/
dts/
dts/bindings/arm은 해당 architecture로 바꿉니다. 각 directory는 optional입니다. Binding directory에는 binding을, 나머지에는 DT source가 include할 수 있는 file을 둡니다.
DTS_ROOT CMake cache variable로 위치를 지정합니다.
west build -b <board name> -- -DDTS_ROOT=<path to dts root>cmake -Bbuild -GNinja -DBOARD=<board name> -DDTS_ROOT=<path to dts root> .
ninja -CbuildCMakeLists.txt에서도 find_package 전에 정의할 수 있습니다.
Devicetree source는 C preprocessor를 통과하므로 DTS_ROOT에서 찾을 수 있는 file을 include할 수 있습니다. Convention상 devicetree include file은 .dtsi extension을 사용합니다.
DTS_EXTRA_CPPFLAGS CMake cache variable로 directive를 지정해 preprocessor가 devicetree content를 제어하게 할 수도 있습니다.
west build -b <board name> -- -DDTS_EXTRA_CPPFLAGS=-DTEST_ENABLE_FEATUREcmake -Bbuild -GNinja -DBOARD=<board name> -DDTS_EXTRA_CPPFLAGS=-DTEST_ENABLE_FEATURE .
ninja -Cbuild
Source
출처
영어 원문에는 문단, 문서 지시문, 표, 코드, 코드 심벌, 경로를 그대로 보존했습니다.