nRF Connect SDK v3.0.2: Build system calling my `CMakeLists.txt` twice?

Hi all,

I've got an existing OpenThread project for my workplace's metering product which currently is written for a TI CC2538 and I'm porting it across to run on a nRF52840 which we plan to use in the next generation of the product.  The existing project uses CMake, and the tricky bit is I want to retain the ability to build for both systems, as we'll need to backport fixes and changes to the existing fleet of devices (sadly, I cannot make a CC2538+CC2592 sprout a nRF52840+nRF21540 by over-the-air software update).  I don't use a development environment, my coding uses the command line and gVim.

Our existing project has a root-level CMakeLists.txt, with three sub-directories:

  • hal: Hardware abstraction layer, this houses drivers for all the various hardware bits and pieces.  The top-level directory here contains drivers and code relevant to both hardware platforms, platform-specific HAL code is in sub-directories (let's call it hal/cc2538 and hal/nrf52840).
  • hub: Main application
  • boot: A bootloader

boot will probably remain for the existing fleet, with the new code using mcuboot.  There are some bits of hal that will be relevant to both boards, hub is relevant to both boards.

I found through experiment with ncs-example-application, that I could move some things around to make the example application better fit the structure of the existing project:

  1. scripts got dropped, since those features weren't needed for building the example
  2. the app/, boards/drivers/, dts/, include/ and lib/ directories got moved beneath the zephyr/ directory
  3. the doc/, tests/ and miscellaneous root-level files got deleted

I could then modify zephyr/module.yml to point to the new locations:

ncs-example-application$ git diff main..HEAD -- zephyr/module.yml 
diff --git a/zephyr/module.yml b/zephyr/module.yml
index 7d53dfd..0792892 100644
--- a/zephyr/module.yml
+++ b/zephyr/module.yml
@@ -5,20 +5,16 @@ build:
   # Path to the Kconfig file that will be sourced into Zephyr Kconfig tree under
   # Zephyr > Modules > example-application. Path is relative from root of this
   # repository.
-  kconfig: Kconfig
+  kconfig: zephyr/Kconfig
   # Path to the folder that contains the CMakeLists.txt file to be included by
   # Zephyr build system. The `.` is the root of this repository.
-  cmake: .
+  cmake: zephyr
   settings:
     # Additional roots for boards and DTS files. Zephyr will use the
     # `<board_root>/boards` for additional boards. The `.` is the root of this
     # repository.
-    board_root: .
+    board_root: zephyr
     # Zephyr will use the `<dts_root>/dts` for additional dts files and
     # `<dts_root>/dts/bindings` for additional dts binding files. The `.` is
     # the root of this repository.
-    dts_root: .
-runners:
-  # Additional runners, Zephyr will import these when discovering
-  # subclasses of the `ZephyrBinaryRunner` class.
-  - file: scripts/example_runner.py
+    dts_root: zephyr

That got me a bare-minimum project that built, and would neatly slot into the existing project.  I copied the resulting zephyr/ directory to my firmware project directory.  Then I updated the app/CMakeLists.txt to point it at my firmware project.

firmware$ cat zephyr/app/CMakeLists.txt 
#-------------------------------------------------------------------------------
# Zephyr Example Application
#
# Copyright (c) 2021 Nordic Semiconductor ASA
# SPDX-License-Identifier: Apache-2.0

cmake_minimum_required(VERSION 3.13.1)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})

set(
        THIRD_PARTY_SRC_DIR
        ${CMAKE_CURRENT_LIST_DIR}/../../third_party
        CACHE PATH "Third-party modules"
)

set(
        NRFXLIB_DIR
        ${THIRD_PARTY_SRC_DIR}/nrfxlib
        CACHE PATH "Nordic Semiconductor nrfxlib directory"
)

set(
        OPENTHREAD_SRC_DIR
        ${NRFXLIB_DIR}/openthread
        CACHE PATH "OpenThread source directory"
)

set(
        MBEDTLS_DIR
        ${THIRD_PARTY_SRC_DIR}/mbedtls
        CACHE PATH "mbedTLS source directory"
)
project(app LANGUAGES C)

target_compile_definitions(
        app PRIVATE
        # Alias sniprintf and iprintf
        sniprintf=snprintf
        iprintf=printf
)


add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/../.." "${CMAKE_CURRENT_BINARY_DIR}/app")

This seemed to work, but I note certain conditions trigger the nRF Connect SDK build system to call my CMakeLists.txt in the root twice:

firmware$ nrfutil toolchain-manager launch -- west build -p always -b hub_mk3 zephyr/app
-- west build: making build dir /home/stuartl/vrt/projects/widesky/hub/workspace/firmware/build pristine
-- west build: generating a build system
Loading Zephyr module(s) (Zephyr base): sysbuild_default
-- Found Python3: /opt/nordicsemi/ncs/toolchains/7cbc0036f4/usr/local/bin/python3.12 (found suitable version "3.12.4", minimum required is "3.10") found components: Interpreter 
-- Cache files will be written to: /home/stuartl/.cache/zephyr
-- Found west (found suitable version "1.2.0", minimum required is "0.14.0")
-- Board: hub_mk3, qualifiers: nrf52840
Parsing /home/stuartl/vrt/projects/widesky/hub/firmware/third_party/zephyr/share/sysbuild/Kconfig
Loaded configuration '/home/stuartl/vrt/projects/widesky/hub/firmware/build/_sysbuild/empty.conf'
Merged configuration '/home/stuartl/vrt/projects/widesky/hub/firmware/build/_sysbuild/empty.conf'
Configuration saved to '/home/stuartl/vrt/projects/widesky/hub/firmware/build/zephyr/.config'
Kconfig header saved to '/home/stuartl/vrt/projects/widesky/hub/firmware/build/_sysbuild/autoconf.h'
-- 
   *************************
   * Running CMake for app *
   *************************

Loading Zephyr default modules (Zephyr base).
-- Application: /home/stuartl/vrt/projects/widesky/hub/firmware/zephyr/app
-- CMake version: 3.21.0
-- Found Python3: /opt/nordicsemi/ncs/toolchains/7cbc0036f4/usr/local/bin/python (found suitable version "3.12.4", minimum required is "3.10") found components: Interpreter 
-- Cache files will be written to: /home/stuartl/.cache/zephyr
-- Zephyr version: 4.0.99 (/home/stuartl/vrt/projects/widesky/hub/workspace/firmware/third_party/zephyr)
-- Found west (found suitable version "1.2.0", minimum required is "0.14.0")
-- Board: hub_mk3, qualifiers: nrf52840
-- Found host-tools: zephyr 0.17.0 (/opt/nordicsemi/ncs/toolchains/7cbc0036f4/opt/zephyr-sdk)
-- Found toolchain: zephyr 0.17.0 (/opt/nordicsemi/ncs/toolchains/7cbc0036f4/opt/zephyr-sdk)
-- Found Dtc: /opt/nordicsemi/ncs/toolchains/7cbc0036f4/usr/bin/dtc (found suitable version "1.5.0", minimum required is "1.4.6") 
-- Found BOARD.dts: /home/stuartl/vrt/projects/widesky/hub/workspace/firmware/zephyr/boards/widesky/hub_mk3/hub_mk3.dts
-- Generated zephyr.dts: /home/stuartl/vrt/projects/widesky/hub/firmware/build/app/zephyr/zephyr.dts
-- Generated pickled edt: /home/stuartl/vrt/projects/widesky/hub/firmware/build/app/zephyr/edt.pickle
-- Generated zephyr.dts: /home/stuartl/vrt/projects/widesky/hub/firmware/build/app/zephyr/zephyr.dts
-- Generated devicetree_generated.h: /home/stuartl/vrt/projects/widesky/hub/firmware/build/app/zephyr/include/generated/zephyr/devicetree_generated.h
-- Including generated dts.cmake file: /home/stuartl/vrt/projects/widesky/hub/firmware/build/app/zephyr/dts.cmake
Parsing /home/stuartl/vrt/projects/widesky/hub/firmware/zephyr/app/Kconfig
Loaded configuration '/home/stuartl/vrt/projects/widesky/hub/workspace/firmware/zephyr/boards/widesky/hub_mk3/hub_mk3_defconfig'
Merged configuration '/home/stuartl/vrt/projects/widesky/hub/firmware/zephyr/app/prj.conf'
Merged configuration '/home/stuartl/vrt/projects/widesky/hub/firmware/build/app/zephyr/.config.sysbuild'
Configuration saved to '/home/stuartl/vrt/projects/widesky/hub/firmware/build/app/zephyr/.config'
Kconfig header saved to '/home/stuartl/vrt/projects/widesky/hub/firmware/build/app/zephyr/include/generated/zephyr/autoconf.h'
-- Found GnuLd: /opt/nordicsemi/ncs/toolchains/7cbc0036f4/opt/zephyr-sdk/arm-zephyr-eabi/arm-zephyr-eabi/bin/ld.bfd (found version "2.38") 
-- The C compiler identification is GNU 12.2.0
-- The CXX compiler identification is GNU 12.2.0
-- The ASM compiler identification is GNU
-- Found assembler: /opt/nordicsemi/ncs/toolchains/7cbc0036f4/opt/zephyr-sdk/arm-zephyr-eabi/bin/arm-zephyr-eabi-gcc
Loading Zephyr default modules (Zephyr base (cached)).
-- Found Python3: /opt/nordicsemi/ncs/toolchains/7cbc0036f4/usr/local/bin/python (found version "3.12.4") found components: Interpreter 
Source directory: /home/stuartl/vrt/projects/widesky/hub/workspace/firmware
HAL directory: /home/stuartl/vrt/projects/widesky/hub/workspace/firmware/hal
Configuration directory: /home/stuartl/vrt/projects/widesky/hub/workspace/firmware/config
Third-party module directory: /home/stuartl/vrt/projects/widesky/hub/workspace/firmware/zephyr/app/../../third_party
OpenThread Source directory: /home/stuartl/vrt/projects/widesky/hub/workspace/firmware/zephyr/app/../../third_party/nrfxlib/openthread
mbedTLS source directory: /home/stuartl/vrt/projects/widesky/hub/workspace/firmware/zephyr/app/../../third_party/mbedtls
NTP client source directory: /home/stuartl/vrt/projects/widesky/hub/workspace/firmware/zephyr/app/../../third_party/ntp_client
CCAN module source directory: /home/stuartl/vrt/projects/widesky/hub/workspace/firmware/zephyr/app/../../third_party/ccan
SPIFFS source directory: /home/stuartl/vrt/projects/widesky/hub/workspace/firmware/zephyr/app/../../third_party/spiffs/repo
TinyCBOR directory: /home/stuartl/vrt/projects/widesky/hub/workspace/firmware/zephyr/app/../../third_party/tinycbor/repo
Firmware version to build: 1.8.9-alpha.56+250806T0125-0e43bd67
Firmware version for CMake: 1.8.9.56
Building for platform: H30
-- Building as Zephyr application --
-- Skipping stand-alone definitions --
-- Using ccache: /opt/nordicsemi/ncs/toolchains/7cbc0036f4/usr/bin/ccache
Source directory: /home/stuartl/vrt/projects/widesky/hub/workspace/firmware
HAL directory: /home/stuartl/vrt/projects/widesky/hub/workspace/firmware/hal
Configuration directory: /home/stuartl/vrt/projects/widesky/hub/workspace/firmware/config
Third-party module directory: /home/stuartl/vrt/projects/widesky/hub/workspace/firmware/zephyr/app/../../third_party
OpenThread Source directory: /home/stuartl/vrt/projects/widesky/hub/workspace/firmware/zephyr/app/../../third_party/nrfxlib/openthread
mbedTLS source directory: /home/stuartl/vrt/projects/widesky/hub/workspace/firmware/zephyr/app/../../third_party/mbedtls
NTP client source directory: /home/stuartl/vrt/projects/widesky/hub/workspace/firmware/zephyr/app/../../third_party/ntp_client
CCAN module source directory: /home/stuartl/vrt/projects/widesky/hub/workspace/firmware/zephyr/app/../../third_party/ccan
SPIFFS source directory: /home/stuartl/vrt/projects/widesky/hub/workspace/firmware/zephyr/app/../../third_party/spiffs/repo
TinyCBOR directory: /home/stuartl/vrt/projects/widesky/hub/workspace/firmware/zephyr/app/../../third_party/tinycbor/repo
Firmware version to build: 1.8.9-alpha.56+250806T0125-0e43bd67
Firmware version for CMake: 1.8.9.56
Building for platform: H30
-- Building as Zephyr application --
CMake Error at /home/stuartl/vrt/projects/widesky/hub/firmware/third_party/ccan/CMakeLists.txt:4 (add_library):
  add_library cannot create target "ccan" because another target with the
  same name already exists.  The existing target is a static library created
  in source directory
  "/home/stuartl/vrt/projects/widesky/hub/workspace/firmware/third_party/ccan".
  See documentation for policy CMP0002 for more details.


CMake Error at /home/stuartl/vrt/projects/widesky/hub/firmware/third_party/ccan/CMakeLists.txt:33 (file):
  file problem touching file:
  /home/stuartl/vrt/projects/widesky/hub/firmware/build/app/include/ccan/../../../../firmware/third_party/ccan/build_assert/config.h


CMake Error at /home/stuartl/vrt/projects/widesky/hub/firmware/third_party/ccan/CMakeLists.txt:33 (file):
  file problem touching file:
  /home/stuartl/vrt/projects/widesky/hub/firmware/build/app/include/ccan/../../../../firmware/third_party/ccan/check_type/config.h


CMake Error at /home/stuartl/vrt/projects/widesky/hub/firmware/third_party/ccan/CMakeLists.txt:33 (file):
  file problem touching file:
  /home/stuartl/vrt/projects/widesky/hub/firmware/build/app/include/ccan/../../../../firmware/third_party/ccan/container_of/config.h


CMake Error at /home/stuartl/vrt/projects/widesky/hub/firmware/third_party/ccan/CMakeLists.txt:33 (file):
  file problem touching file:
  /home/stuartl/vrt/projects/widesky/hub/firmware/build/app/include/ccan/../../../../firmware/third_party/ccan/stringbuilder/config.h


CMake Error at /home/stuartl/vrt/projects/widesky/hub/firmware/third_party/spiffs/CMakeLists.txt:4 (add_library):
  add_library cannot create target "spiffs" because another target with the
  same name already exists.  The existing target is a static library created
  in source directory
  "/home/stuartl/vrt/projects/widesky/hub/workspace/firmware/third_party/spiffs".
  See documentation for policy CMP0002 for more details.


CMake Error at /home/stuartl/vrt/projects/widesky/hub/firmware/third_party/tinycbor/CMakeLists.txt:4 (add_library):
  add_library cannot create target "tinycbor" because another target with the
  same name already exists.  The existing target is a static library created
  in source directory
  "/home/stuartl/vrt/projects/widesky/hub/workspace/firmware/third_party/tinycbor".
  See documentation for policy CMP0002 for more details.


CMake Error at /home/stuartl/vrt/projects/widesky/hub/firmware/third_party/ntp_client/CMakeLists.txt:4 (add_library):
  add_library cannot create target "ntpclient" because another target with
  the same name already exists.  The existing target is a static library
  created in source directory
  "/home/stuartl/vrt/projects/widesky/hub/workspace/firmware/third_party/ntp_client".
  See documentation for policy CMP0002 for more details.


CMake Error at /home/stuartl/vrt/projects/widesky/hub/firmware/hal/CMakeLists.txt:1 (add_library):
  add_library cannot create target "widesky-boot-hal" because another target
  with the same name already exists.  The existing target is a static library
  created in source directory
  "/home/stuartl/vrt/projects/widesky/hub/workspace/firmware/hal".  See
  documentation for policy CMP0002 for more details.


CMake Error at /home/stuartl/vrt/projects/widesky/hub/firmware/hal/CMakeLists.txt:2 (add_library):
  add_library cannot create target "widesky-hub-hal" because another target
  with the same name already exists.  The existing target is a static library
  created in source directory
  "/home/stuartl/vrt/projects/widesky/hub/workspace/firmware/hal".  See
  documentation for policy CMP0002 for more details.


CMake Error at /home/stuartl/vrt/projects/widesky/hub/firmware/hal/mk3/CMakeLists.txt:1 (add_library):
  add_library cannot create target "widesky-boot-hal-mk3" because another
  target with the same name already exists.  The existing target is a static
  library created in source directory
  "/home/stuartl/vrt/projects/widesky/hub/workspace/firmware/hal/mk3".  See
  documentation for policy CMP0002 for more details.


CMake Error at /home/stuartl/vrt/projects/widesky/hub/firmware/hal/mk3/CMakeLists.txt:2 (add_library):
  add_library cannot create target "widesky-hub-hal-mk3" because another
  target with the same name already exists.  The existing target is a static
  library created in source directory
  "/home/stuartl/vrt/projects/widesky/hub/workspace/firmware/hal/mk3".  See
  documentation for policy CMP0002 for more details.


CMake Error at /home/stuartl/vrt/projects/widesky/hub/firmware/hal/CMakeLists.txt:21 (add_custom_target):
  add_custom_target cannot create target "widesky-hub-hal-txptable" because
  another target with the same name already exists.  The existing target is a
  custom target created in source directory
  "/home/stuartl/vrt/projects/widesky/hub/workspace/firmware/hal".  See
  documentation for policy CMP0002 for more details.


CMake Error at /home/stuartl/vrt/projects/widesky/hub/firmware/hub/CMakeLists.txt:3 (add_custom_target):
  add_custom_target cannot create target "widesky-hub-application-wshversion"
  because another target with the same name already exists.  The existing
  target is a custom target created in source directory
  "/home/stuartl/vrt/projects/widesky/hub/workspace/firmware/hub".  See
  documentation for policy CMP0002 for more details.


-- Skipping stand-alone definitions --
-- Configuring incomplete, errors occurred!
See also "/home/stuartl/vrt/projects/widesky/hub/firmware/build/app/CMakeFiles/CMakeOutput.log".
See also "/home/stuartl/vrt/projects/widesky/hub/firmware/build/app/CMakeFiles/CMakeError.log".
CMake Error at cmake/modules/sysbuild_extensions.cmake:514 (message):
  CMake configure failed for Zephyr project: app

  Location: /home/stuartl/vrt/projects/widesky/hub/firmware/zephyr/app
Call Stack (most recent call first):
  cmake/modules/sysbuild_images.cmake:43 (ExternalZephyrProject_Cmake)
  cmake/modules/sysbuild_default.cmake:21 (include)
  /home/stuartl/vrt/projects/widesky/hub/firmware/third_party/zephyr/share/zephyr-package/cmake/ZephyrConfig.cmake:75 (include)
  /home/stuartl/vrt/projects/widesky/hub/firmware/third_party/zephyr/share/zephyr-package/cmake/ZephyrConfig.cmake:92 (include_boilerplate)
  /home/stuartl/vrt/projects/widesky/hub/firmware/third_party/zephyr/share/sysbuild-package/cmake/SysbuildConfig.cmake:8 (include)
  template/CMakeLists.txt:10 (find_package)


-- Configuring incomplete, errors occurred!
See also "/home/stuartl/vrt/projects/widesky/hub/firmware/build/CMakeFiles/CMakeOutput.log".
FATAL ERROR: command exited with status 1: /opt/nordicsemi/ncs/toolchains/7cbc0036f4/usr/local/bin/cmake -DWEST_PYTHON=/opt/nordicsemi/ncs/toolchains/7cbc0036f4/usr/local/bin/python3.12 -B/home/stuartl/vrt/projects/widesky/hub/workspace/firmware/build -GNinja -DBOARD=hub_mk3 -S/home/stuartl/vrt/projects/widesky/hub/workspace/firmware/third_party/zephyr/share/sysbuild -DAPP_DIR:PATH=/home/stuartl/vrt/projects/widesky/hub/workspace/firmware/zephyr/app
Error: Launched process exited with non-zero status: 1

Is there a reason why the build system feels it necessary to double-include the project top-level CMakeFile.txt?

Related