From 522eb86907b41ad460d1fb437c851a4b0007d82b Mon Sep 17 00:00:00 2001 From: Torsten Rasmussen Date: Fri, 26 Sep 2025 12:55:07 +0200 Subject: [PATCH] sysbuild: support application CMakePresets.json files with sysbuild This commit provides a CMakePresets.json which includes the sample's CMakePresets.json file. `west build` is extended to set `APP_DIR` in environment when sysbuild is used. This allows sysbuild's CMakePresets.json to include the sample's presets file. Signed-off-by: Torsten Rasmussen --- doc/build/sysbuild/index.rst | 58 ++++++++++++++++++++++++++++++-- scripts/west_commands/build.py | 9 +++-- share/sysbuild/CMakeLists.txt | 5 +++ share/sysbuild/CMakePresets.json | 11 ++++++ 4 files changed, 78 insertions(+), 5 deletions(-) create mode 100644 share/sysbuild/CMakePresets.json diff --git a/doc/build/sysbuild/index.rst b/doc/build/sysbuild/index.rst index 51675569e0853..42d100c554ea1 100644 --- a/doc/build/sysbuild/index.rst +++ b/doc/build/sysbuild/index.rst @@ -140,8 +140,8 @@ As mentioned above, you can run sysbuild via ``west build`` or ``cmake``. To use sysbuild directly with CMake, you must specify the sysbuild project as the source folder, and give ``-DAPP_DIR=`` as - an extra CMake argument. ``APP_DIR`` is the path to the main Zephyr - application managed by sysbuild. + an extra CMake argument or set APP_DIR as environment variable. + ``APP_DIR`` is the path to the main Zephyr application managed by sysbuild. .. tip:: @@ -880,3 +880,57 @@ can be added. :maxdepth: 1 images.rst + +Sysbuild and CMake presets +************************** + +`CMake presets `_ can be used with +Sysbuild but not all preset macros will work as expected. + +.. note:: + + Using CMake presets with sysbuild requires CMake version 3.27 or higher. + +As described in :ref:`sysbuild` then sysbuild is a higher-level build system which means that when +CMake presets are used together with sysbuild, then the preset is consumed and processed by sysbuild +itself and result is passed to the application. + +Running sysbuild with preset. + +.. tabs:: + + .. group-tab:: ``west build`` + + Here is an example where preset ``release`` should be used. + For details, see :ref:`west-multi-domain-builds` in the ``west build documentation``. + + .. zephyr-app-commands:: + :tool: west + :zephyr-app: samples/hello_world + :board: reel_board + :goals: build + :west-args: --sysbuild -- --preset=release + :compact: + + .. group-tab:: ``cmake`` + + Here is an example using CMake and Ninja. + + .. code-block:: shell + + APP_DIR=samples/hello_world cmake -Bbuild -GNinja -DBOARD=reel_board share/sysbuild + ninja -Cbuild + + When using CMake presets with sysbuild then ``APP_DIR`` must be set in environment in order + for Sysbuild CMake to be able to include the ``CMakePresets.json`` from the main Zephyr + application's source directory. + +.. note:: + + As sysbuild changes the top-level cmake project to its own directory, the cmake presets are + parsed from there, the application's presets are included from this file verbatim. + Therefore relative paths, and macros resolving relative to the source directory will not work as + expected, but as relative to share/sysbuild, for example ``${sourceDir}``. + + The ``${fileDir}`` macro can be used to create portable paths relative to the application's + directory. diff --git a/scripts/west_commands/build.py b/scripts/west_commands/build.py index 8a8b3a23ebeef..0b2b1965cf394 100644 --- a/scripts/west_commands/build.py +++ b/scripts/west_commands/build.py @@ -618,6 +618,8 @@ def _run_cmake(self, board, origin, cmake_opts): if not self.run_cmake: return + cmake_env = None + self._banner('generating a build system') if board is not None and origin != 'CMakeCache.txt': @@ -644,8 +646,9 @@ def _run_cmake(self, board, origin, cmake_opts): config_sysbuild = config_getboolean('sysbuild', False) if self.args.sysbuild or (config_sysbuild and not self.args.no_sysbuild): - cmake_opts.extend([f'-S{SYSBUILD_PROJ_DIR}', - f'-DAPP_DIR:PATH={self.source_dir}']) + cmake_opts.extend([f'-S{SYSBUILD_PROJ_DIR}']) + cmake_env = os.environ.copy() + cmake_env["APP_DIR"] = str(self.source_dir) else: # self.args.no_sysbuild == True or config sysbuild False cmake_opts.extend([f'-S{self.source_dir}']) @@ -661,7 +664,7 @@ def _run_cmake(self, board, origin, cmake_opts): f'-G{config_get("generator", DEFAULT_CMAKE_GENERATOR)}'] if cmake_opts: final_cmake_args.extend(cmake_opts) - run_cmake(final_cmake_args, dry_run=self.args.dry_run) + run_cmake(final_cmake_args, dry_run=self.args.dry_run, env=cmake_env) def _run_pristine(self): self._banner(f'making build dir {self.build_dir} pristine') diff --git a/share/sysbuild/CMakeLists.txt b/share/sysbuild/CMakeLists.txt index f2fbb4b271841..d0180757488a0 100644 --- a/share/sysbuild/CMakeLists.txt +++ b/share/sysbuild/CMakeLists.txt @@ -4,6 +4,11 @@ cmake_minimum_required(VERSION 3.20) + +if(NOT DEFINED APP_DIR AND DEFINED ENV{APP_DIR}) + set(APP_DIR $ENV{APP_DIR}) +endif() + if(NOT DEFINED APP_DIR) message(FATAL_ERROR "No main application specified") endif() diff --git a/share/sysbuild/CMakePresets.json b/share/sysbuild/CMakePresets.json new file mode 100644 index 0000000000000..437f3b68a9447 --- /dev/null +++ b/share/sysbuild/CMakePresets.json @@ -0,0 +1,11 @@ +{ + "version": 7, + "cmakeMinimumRequired": { + "major": 3, + "minor": 27, + "patch": 0 + }, + "include": [ + "$penv{APP_DIR}/CMakePresets.json" + ] +}