1.. _sysbuild_images:
2
3Sysbuild images
4###############
5
6Sysbuild can be used to add additional images to builds, these can be added by projects or boards
7though at present must be Zephyr applications.
8
9Methods of adding images
10************************
11
12Images can be added to project or projects in various ways, multiple ways can be used
13simultaneously, they can be added in the following ways:
14
15Applications
16============
17
18Applications can add sysbuild images using the ``sysbuild.cmake`` file in the application
19directory, the inclusion of images can be controlled with a ``Kconfig.sysbuild`` file in the
20application directory.
21
22Boards
23======
24
25Boards can add sysbuild images by using the ``sysbuild.cmake`` file in the board directory, the
26inclusion of images can be controlled with a ``Kconfig.sysbuild`` file in the board directory.
27
28SoCs
29====
30
31SoCs can add sysbuild images by using the ``sysbuild.cmake`` file in the soc directory.
32
33Modules
34=======
35
36:ref:`modules` can add sysbuild images with the ``sysbuild-cmake`` and ``sysbuild-kconfig``
37options in a ``module.yml`` file, see :ref:`sysbuild_module_integration` for details.
38
39Adding images
40*************
41
42Images can be added in one of two ways:
43
44Single unchangeable image
45=========================
46
47With this setup, the image to be added is fixed to a specific application and cannot be changed
48(although it cannot be changed to another image, the version of the image itself can be changed by
49use of a west manifest bringing in a different version of the application repo or from an
50alternate source, assuming that the image is in it's own repository).
51
52.. note::
53
54   This method should only be used if the image is locked to a specific interface and has no
55   extensibility.
56
57An example of how to create such an image, this assumes that a
58:ref:`Zephyr application has been created <application>`:
59
60.. tabs::
61
62   .. group-tab:: ``Kconfig.sysbuild``
63
64      .. code-block:: kconfig
65
66         config MY_IMAGE
67                 bool "Include my amazing image"
68                 help
69                   If enabled, will include my amazing image in the build which does...
70
71      .. note::
72
73         Remember to have ``source "share/sysbuild/Kconfig"`` in the file if this
74         is being applied in an application ``Kconfig.sysbuild`` file.
75
76
77   .. group-tab:: ``sysbuild.cmake``
78
79      .. code-block:: cmake
80
81         if(SB_CONFIG_MY_IMAGE)
82           ExternalZephyrProject_Add(
83             APPLICATION my_image
84             SOURCE_DIR ${ZEPHYR_MY_IMAGE_MODULE_DIR}/path/to/my_image
85           )
86         endif()
87
88Additional dependency ordering can be set here if needed, see
89:ref:`sysbuild_zephyr_application_dependencies` for details, image configuration can also be set
90here, see :ref:`sysbuild_images_config` for details.
91
92This image can be enabled when building with west like so:
93
94.. zephyr-app-commands::
95   :tool: west
96   :zephyr-app: <app>
97   :board: nrf52840dk/nrf52840
98   :goals: build
99   :west-args: --sysbuild
100   :gen-args: -DSB_CONFIG_MY_IMAGE=y
101   :compact:
102
103Extensible changeable image
104===========================
105
106With this setup, the image to be added can be one of any number of possible applications which the
107user has selection over, this list of selections can also be extended downstream to add additional
108options for out-of-tree specific applications that are not available in upstream Zephyr. This is
109more complex to create but is the preferred method for adding images to upstream Zephyr.
110
111.. tabs::
112
113   .. group-tab:: ``Kconfig.sysbuild``
114
115      .. code-block:: kconfig
116
117         config SUPPORT_OTHER_APP
118                 bool
119                 # Conditions can be placed here if this application type is only usable on certain platforms
120                 default y
121
122         config SUPPORT_OTHER_APP_MY_IMAGE
123                 bool
124                 # Conditions can be placed here if this image is only usable on certain platforms
125                 default y
126
127         choice OTHER_APP
128                 prompt "Other app image"
129                 # Defaults can be specified here if a default image should be loaded if e.g. it is supported
130                 default OTHER_APP_NONE
131                 depends on SUPPORT_OTHER_APP
132
133         config OTHER_APP_IMAGE_NONE
134                 bool "None"
135                 help
136                   Do not Include an other app image in the build.
137
138         config OTHER_APP_IMAGE_MY_IMAGE
139                 bool "my_image"
140                 depends on SUPPORT_OTHER_APP_MY_IMAGE
141                 help
142                   Include my amazing image as the other app image to use, which does...
143
144         endchoice
145
146         config OTHER_APP_IMAGE_NAME
147                 string
148                 default "my_image" if OTHER_APP_IMAGE_MY_IMAGE
149                 help
150                   Name of other app image.
151
152         config OTHER_APP_IMAGE_PATH
153                 string
154                 default "$(ZEPHYR_MY_IMAGE_MODULE_DIR)/path/to/my_image" if OTHER_APP_IMAGE_MY_IMAGE
155                 help
156                   Source directory of other app image.
157
158      .. note::
159
160         Remember to have ``source "$(ZEPHYR_BASE)/share/sysbuild/Kconfig"`` in the file if this
161         is being applied in an application ``Kconfig.sysbuild`` file.
162
163   .. group-tab:: ``sysbuild.cmake``
164
165      .. code-block:: cmake
166
167         if(SB_CONFIG_OTHER_APP_IMAGE_PATH)
168           ExternalZephyrProject_Add(
169             APPLICATION ${SB_CONFIG_OTHER_APP_IMAGE_NAME}
170             SOURCE_DIR ${SB_CONFIG_OTHER_APP_IMAGE_PATH}
171           )
172         endif()
173
174Additional dependency ordering can be set here if needed, see
175:ref:`sysbuild_zephyr_application_dependencies` for details, image configuration can also be set
176here, see :ref:`sysbuild_images_config` for details.
177
178This secondary image can be enabled when building with west like so:
179
180.. zephyr-app-commands::
181   :tool: west
182   :zephyr-app: <app>
183   :board: nrf52840dk/nrf52840
184   :goals: build
185   :west-args: --sysbuild
186   :gen-args: -DSB_CONFIG_MY_IMAGE=y
187   :compact:
188
189This can then be extended by :ref:`modules` like so:
190
191.. tabs::
192
193   .. group-tab:: ``Kconfig.sysbuild``
194
195      .. code-block:: kconfig
196
197         config SUPPORT_OTHER_APP_MY_SECOND_IMAGE
198                 bool
199                 default y
200
201         choice OTHER_APP
202
203         config OTHER_APP_IMAGE_MY_SECOND_IMAGE
204                 bool "my_second_image"
205                 depends on SUPPORT_OTHER_APP_MY_SECOND_IMAGE
206                 help
207                   Include my other amazing image as the other app image to use, which does...
208
209         endchoice
210
211         config OTHER_APP_IMAGE_NAME
212                 default "my_second_image" if OTHER_APP_IMAGE_MY_SECOND_IMAGE
213
214         config OTHER_APP_IMAGE_PATH
215                 default "$(ZEPHYR_MY_SECOND_IMAGE_MODULE_DIR)/path/to/my_second_image" if OTHER_APP_IMAGE_MY_SECOND_IMAGE
216
217As can be seen, no additional CMake changes are needed to add an alternative image as the base
218CMake code will add the replacement image instead of the original image, if selected.
219
220This alternative secondary image can be enabled when building with west like so:
221
222.. zephyr-app-commands::
223   :tool: west
224   :zephyr-app: <app>
225   :board: nrf52840dk/nrf52840
226   :goals: build
227   :west-args: --sysbuild
228   :gen-args: -DSB_CONFIG_MY_SECOND_IMAGE=y
229   :compact:
230
231.. _sysbuild_images_config:
232
233Image configuration
234*******************
235
236Sysbuild supports being able to set image configuration (Kconfig options) and also supports
237reading the output of image configuration (Kconfig) which can be used to allow an
238option to be added to sysbuild itself and then to configure it globally or selectively.
239
240Setting image configuration
241===========================
242
243Kconfig
244-------
245
246Sysbuild can be used to set image configuration **before the CMake configuration of images takes
247place**. An important note about setting Kconfig options in images is that these are persistent
248and cannot be changed by the images. The following functions can be used to set configuration on
249an image:
250
251.. code-block:: cmake
252
253   set_config_bool(<image> CONFIG_<setting> <value>)
254   set_config_string(<image> CONFIG_<setting> <value>)
255   set_config_int(<image> CONFIG_<setting> <value>)
256
257For example, to change the default image to output a hex file:
258
259.. code-block:: cmake
260
261   set_config_bool(${DEFAULT_IMAGE} CONFIG_BUILD_OUTPUT_HEX y)
262
263These can safely be used in an application, board or SoC ``sysbuild.cmake`` file, as that file is
264included before the image CMake processes are invoked. When extending
265:ref:`sysbuild using modules <sysbuild_module_integration>` the pre-CMake hook should be used
266instead, for example:
267
268.. code-block:: cmake
269
270   function(${SYSBUILD_CURRENT_MODULE_NAME}_pre_cmake)
271     cmake_parse_arguments(PRE_CMAKE "" "" "IMAGES" ${ARGN})
272
273     foreach(image ${PRE_CMAKE_IMAGES})
274       set_config_bool(${image} CONFIG_BUILD_OUTPUT_HEX y)
275     endforeach()
276   endfunction()
277
278Image configuration script
279==========================
280
281An image configuration script is a CMake file that can be used to configure an image with common
282configuration values, multiple can be used per image, the configuration should be transferrable to
283different images to correctly configure them based upon options set in sysbuild. MCUboot
284configuration options are configured in both the application the MCUboot image using this method
285which allows sysbuild to be the central location for things like the signing key which are then
286kept in-sync in the main application bootloader images.
287
288Inside image configuration scripts, the ``ZCMAKE_APPLICATION`` variable is set to the name of the
289application being configured, the ``set_config_*`` sysbuild CMake functions can be used to set
290configuration and the sysbuild Kconfig can be read, for example:
291
292.. code-block:: cmake
293
294   if(SB_CONFIG_BOOTLOADER_MCUBOOT AND "${SB_CONFIG_SIGNATURE_TYPE}" STREQUAL "NONE")
295     set_config_bool(${ZCMAKE_APPLICATION} CONFIG_MCUBOOT_GENERATE_UNSIGNED_IMAGE y)
296   endif()
297
298Image configuration script (module/application)
299-----------------------------------------------
300
301Module/application image configuration scripts can be set from module or application code, this
302must be done in a ``sysbuild.cmake`` file for an application. This can be used to add an image
303configuration script as follows:
304
305.. tabs::
306
307   .. group-tab:: ``sysbuild.cmake``
308
309      .. code-block:: cmake
310
311         # This applies the image configuration script to the default image only
312         get_property(tmp_conf_scripts TARGET ${DEFAULT_IMAGE} PROPERTY IMAGE_CONF_SCRIPT)
313         list(APPEND tmp_conf_scripts "${CMAKE_SOURCE_DIR}/image_configurations/MY_CUSTOM_TYPE_image_default.cmake")
314         set_target_properties(${DEFAULT_IMAGE} PROPERTIES IMAGE_CONF_SCRIPT "${tmp_conf_scripts}")
315
316
317   .. group-tab:: Module CMake
318
319      .. code-block:: cmake
320
321         function(${SYSBUILD_CURRENT_MODULE_NAME}_pre_cmake)
322           cmake_parse_arguments(PRE_CMAKE "" "" "IMAGES" ${ARGN})
323
324           # This applies the image configuration script to all images
325           foreach(image ${PRE_CMAKE_IMAGES})
326             get_property(tmp_conf_scripts TARGET ${image} PROPERTY IMAGE_CONF_SCRIPT)
327             list(APPEND tmp_conf_scripts "${CMAKE_SOURCE_DIR}/image_configurations/MY_CUSTOM_TYPE_image_default.cmake")
328             set_target_properties(${image} PROPERTIES IMAGE_CONF_SCRIPT "${tmp_conf_scripts}")
329           endforeach()
330         endfunction(${SYSBUILD_CURRENT_MODULE_NAME}_pre_cmake)
331
332Image configuration script (Zephyr-wide)
333----------------------------------------
334
335Global Zephyr provided image configuration scripts, which allow specifying the type when using
336``ExternalZephyrProject_Add()`` require changes to sysbuild code in Zephyr. This should only be
337added to when adding a new type that any project should be able to select, generally this should
338only be needed for upstream Zephyr though forked versions of Zephyr might use this to add
339additional types without restriction.
340
341Image configuration has an allow-list of names which must be set in the Zephyr file
342:zephyr_file:`share/sysbuild/cmake/modules/sysbuild_extensions.cmake` in the
343``ExternalZephyrProject_Add`` function. After adding a new type, it can be used when adding a
344sysbuild image, for example:
345
346.. tabs::
347
348   .. group-tab:: ``sysbuild_extensions.cmake``
349
350      Full file path: ``share/sysbuild/cmake/modules/sysbuild_extensions.cmake``
351
352      .. code-block:: cmake
353
354         # ...
355         # Usage:
356         #   ExternalZephyrProject_Add(APPLICATION <name>
357         #                             SOURCE_DIR <dir>
358         #                             [BOARD <board> [BOARD_REVISION <revision>]]
359         #                             [APP_TYPE <MAIN|BOOTLOADER|MY_CUSTOM_TYPE>]
360         #   )
361         # ...
362         # APP_TYPE <MAIN|BOOTLOADER|MY_CUSTOM_TYPE>: Application type.
363         #                                            MAIN indicates this application is the main application
364         #                                            and where user defined settings should be passed on as-is
365         #                                            except for multi image build flags.
366         #                                            For example, -DCONF_FILES=<files> will be passed on to the
367         #                                            MAIN_APP unmodified.
368         #                                            BOOTLOADER indicates this app is a bootloader
369         #                                            MY_CUSTOM_TYPE indicates this app is...
370         # ...
371         function(ExternalZephyrProject_Add)
372           set(app_types MAIN BOOTLOADER MY_CUSTOM_TYPE)
373         # ...
374
375   .. group-tab:: ``sysbuild.cmake``
376
377      .. code-block:: cmake
378
379         if(SB_CONFIG_OTHER_APP_IMAGE_PATH)
380           ExternalZephyrProject_Add(
381             APPLICATION ${SB_CONFIG_OTHER_APP_IMAGE_NAME}
382             SOURCE_DIR ${SB_CONFIG_OTHER_APP_IMAGE_PATH}
383             APP_TYPE MY_CUSTOM_TYPE
384           )
385         endif()
386
387
388   .. group-tab:: ``MY_CUSTOM_TYPE_image_default.cmake``
389
390      Full file path: ``share/sysbuild/image_configurations/MY_CUSTOM_TYPE_image_default.cmake``
391
392      .. code-block:: cmake
393
394         # Here, the ZCMAKE_APPLICATION variable will be replaced with the image being configured
395         set_config_bool(${ZCMAKE_APPLICATION} CONFIG_BUILD_OUTPUT_HEX y)
396
397Reading image configuration
398===========================
399
400Kconfig
401-------
402
403Kconfig values from images can be read by sysbuild **after the CMake configuration of images has
404taken place**. This can be used to check configuration or to adjust additional sysbuild tasks
405depending upon configuration. The following function can be used for this purpose:
406
407.. code-block:: cmake
408
409   sysbuild_get(<variable> IMAGE <image> [VAR <image-variable>] KCONFIG)
410
411This function can only be used when
412:ref:`sysbuild is extended by a module <sysbuild_module_integration>` or inside of a ``sysbuild/CMakeLists.txt`` file after ``find_package(Sysbuild)`` has been used. An example of outputting
413values from all images is shown:
414
415.. tabs::
416
417   .. group-tab:: Module CMake
418
419      .. code-block:: cmake
420
421         function(${SYSBUILD_CURRENT_MODULE_NAME}_post_cmake)
422           cmake_parse_arguments(POST_CMAKE "" "" "IMAGES" ${ARGN})
423
424           foreach(image ${POST_CMAKE_IMAGES})
425             # Note that the variable to read in to must not be set before using the sysbuild_get() function
426             set(tmp_val)
427             sysbuild_get(tmp_val IMAGE ${image} VAR CONFIG_BUILD_OUTPUT_HEX KCONFIG)
428             message(STATUS "Image ${image} build hex: ${tmp_val}")
429           endforeach()
430         endfunction()
431
432   .. group-tab:: ``sysbuild/CMakeLists.txt``
433
434      .. code-block:: cmake
435
436         find_package(Sysbuild REQUIRED HINTS $ENV{ZEPHYR_BASE})
437
438         project(sysbuild LANGUAGES)
439
440         sysbuild_get(tmp_val IMAGE ${DEFAULT_IMAGE} VAR CONFIG_BUILD_OUTPUT_HEX KCONFIG)
441         message(STATUS "Image ${DEFAULT_IMAGE} build hex: ${tmp_val}")
442