# SPDX-License-Identifier: Apache-2.0 include_guard(GLOBAL) include(extensions) include(python) # This cmake file provides functionality to import CMakeLists.txt and Kconfig # files for Zephyr modules into Zephyr build system. # # CMakeLists.txt and Kconfig files can reside directly in the Zephyr module or # in a MODULE_EXT_ROOT. # The `/zephyr/module.yml` file specifies whether the build files are # located in the Zephyr module or in a MODULE_EXT_ROOT. # # A list of Zephyr modules can be provided to the build system using: # -DZEPHYR_MODULES=[;] # # It looks for: /zephyr/module.yml or # /zephyr/CMakeLists.txt # to load the Zephyr module into Zephyr build system. # If west is installed, it uses west's APIs to obtain a list of projects to # search for zephyr/module.yml from the current workspace's manifest. # # If the module.yml file specifies that build files are located in a # MODULE_EXT_ROOT then the variables: # - `ZEPHYR__CMAKE_DIR` is used for inclusion of the CMakeLists.txt # - `ZEPHYR__KCONFIG` is used for inclusion of the Kconfig # files into the build system. # Settings used by Zephyr module but where systems may define an alternative value. set_ifndef(KCONFIG_BINARY_DIR ${CMAKE_BINARY_DIR}/Kconfig) zephyr_get(ZEPHYR_MODULES) if(ZEPHYR_MODULES) set(ZEPHYR_MODULES_ARG "--modules" ${ZEPHYR_MODULES}) endif() zephyr_get(EXTRA_ZEPHYR_MODULES VAR EXTRA_ZEPHYR_MODULES ZEPHYR_EXTRA_MODULES) if(EXTRA_ZEPHYR_MODULES) set(EXTRA_ZEPHYR_MODULES_ARG "--extra-modules" ${EXTRA_ZEPHYR_MODULES}) endif() file(MAKE_DIRECTORY ${KCONFIG_BINARY_DIR}) set(kconfig_modules_file ${KCONFIG_BINARY_DIR}/Kconfig.modules) set(kconfig_sysbuild_file ${KCONFIG_BINARY_DIR}/Kconfig.sysbuild.modules) set(cmake_modules_file ${CMAKE_BINARY_DIR}/zephyr_modules.txt) set(cmake_sysbuild_file ${CMAKE_BINARY_DIR}/sysbuild_modules.txt) set(zephyr_settings_file ${CMAKE_BINARY_DIR}/zephyr_settings.txt) if(WEST OR ZEPHYR_MODULES) # Zephyr module uses west, so only call it if west is installed or # ZEPHYR_MODULES was provided as argument to CMake. execute_process( COMMAND ${PYTHON_EXECUTABLE} ${ZEPHYR_BASE}/scripts/zephyr_module.py --zephyr-base=${ZEPHYR_BASE} ${ZEPHYR_MODULES_ARG} ${EXTRA_ZEPHYR_MODULES_ARG} --kconfig-out ${kconfig_modules_file} --cmake-out ${cmake_modules_file} --sysbuild-kconfig-out ${kconfig_sysbuild_file} --sysbuild-cmake-out ${cmake_sysbuild_file} --settings-out ${zephyr_settings_file} WORKING_DIRECTORY ${ZEPHYR_BASE} ERROR_VARIABLE zephyr_module_error_text RESULT_VARIABLE zephyr_module_return ) if(${zephyr_module_return}) message(FATAL_ERROR "${zephyr_module_error_text}") endif() if(EXISTS ${zephyr_settings_file}) file(STRINGS ${zephyr_settings_file} zephyr_settings_txt ENCODING UTF-8 REGEX "^[^#]") foreach(setting ${zephyr_settings_txt}) # Match : for each line of file, each corresponding to # a setting. The use of quotes is required due to CMake not supporting # lazy regexes (it supports greedy only). string(REGEX REPLACE "\"(.*)\":\".*\"" "\\1" key ${setting}) string(REGEX REPLACE "\".*\":\"(.*)\"" "\\1" value ${setting}) list(APPEND ${key} ${value}) endforeach() endif() # Append ZEPHYR_BASE as a default ext root at lowest priority list(APPEND MODULE_EXT_ROOT ${ZEPHYR_BASE}) if(EXISTS ${cmake_modules_file}) file(STRINGS ${cmake_modules_file} zephyr_modules_txt ENCODING UTF-8) endif() set(ZEPHYR_MODULE_NAMES) foreach(module ${zephyr_modules_txt}) # Match "":"" for each line of file, each corresponding to # one module. The use of quotes is required due to CMake not supporting # lazy regexes (it supports greedy only). string(REGEX REPLACE "\"(.*)\":\".*\":\".*\"" "\\1" module_name ${module}) list(APPEND ZEPHYR_MODULE_NAMES ${module_name}) endforeach() if(EXISTS ${cmake_sysbuild_file}) file(STRINGS ${cmake_sysbuild_file} sysbuild_modules_txt ENCODING UTF-8) endif() set(SYSBUILD_MODULE_NAMES) foreach(module ${sysbuild_modules_txt}) # Match "":"" for each line of file, each corresponding to # one module. The use of quotes is required due to CMake not supporting # lazy regexes (it supports greedy only). string(REGEX REPLACE "\"(.*)\":\".*\":\".*\"" "\\1" module_name ${module}) list(APPEND SYSBUILD_MODULE_NAMES ${module_name}) endforeach() # MODULE_EXT_ROOT is process order which means Zephyr module roots processed # later wins. therefore we reverse the list before processing. list(REVERSE MODULE_EXT_ROOT) foreach(root ${MODULE_EXT_ROOT}) set(module_cmake_file_path modules/modules.cmake) if(NOT EXISTS ${root}/${module_cmake_file_path}) message(FATAL_ERROR "No `${module_cmake_file_path}` found in module root `${root}`.") endif() include(${root}/${module_cmake_file_path}) endforeach() foreach(module ${zephyr_modules_txt}) # Match "":"" for each line of file, each corresponding to # one Zephyr module. The use of quotes is required due to CMake not # supporting lazy regexes (it supports greedy only). string(CONFIGURE ${module} module) string(REGEX REPLACE "\"(.*)\":\".*\":\".*\"" "\\1" module_name ${module}) string(REGEX REPLACE "\".*\":\"(.*)\":\".*\"" "\\1" module_path ${module}) string(REGEX REPLACE "\".*\":\".*\":\"(.*)\"" "\\1" cmake_path ${module}) zephyr_string(SANITIZE TOUPPER MODULE_NAME_UPPER ${module_name}) if(NOT ${MODULE_NAME_UPPER} STREQUAL CURRENT) set(ZEPHYR_${MODULE_NAME_UPPER}_MODULE_NAME ${module_name}) set(ZEPHYR_${MODULE_NAME_UPPER}_MODULE_DIR ${module_path}) set(ZEPHYR_${MODULE_NAME_UPPER}_CMAKE_DIR ${cmake_path}) else() message(FATAL_ERROR "Found Zephyr module named: ${module_name}\n\ ${MODULE_NAME_UPPER} is a restricted name for Zephyr modules as it is used for \ \${ZEPHYR_${MODULE_NAME_UPPER}_MODULE_DIR} CMake variable.") endif() endforeach() foreach(module ${sysbuild_modules_txt}) # Match "":"" for each line of file, each corresponding to # one Zephyr module. The use of quotes is required due to CMake not # supporting lazy regexes (it supports greedy only). string(CONFIGURE ${module} module) string(REGEX REPLACE "\"(.*)\":\".*\":\".*\"" "\\1" module_name ${module}) string(REGEX REPLACE "\".*\":\"(.*)\":\".*\"" "\\1" module_path ${module}) string(REGEX REPLACE "\".*\":\".*\":\"(.*)\"" "\\1" cmake_path ${module}) zephyr_string(SANITIZE TOUPPER MODULE_NAME_UPPER ${module_name}) if(NOT ${MODULE_NAME_UPPER} STREQUAL CURRENT) set(SYSBUILD_${MODULE_NAME_UPPER}_MODULE_DIR ${module_path}) set(SYSBUILD_${MODULE_NAME_UPPER}_CMAKE_DIR ${cmake_path}) else() message(FATAL_ERROR "Found Zephyr module named: ${module_name}\n\ ${MODULE_NAME_UPPER} is a restricted name for Zephyr modules as it is used for \ \${SYSBUILD_${MODULE_NAME_UPPER}_MODULE_DIR} CMake variable.") endif() endforeach() else() file(WRITE ${kconfig_modules_file} "# No west and no Zephyr modules\n" ) file(WRITE ${kconfig_sysbuild_file} "# No west and no Zephyr modules\n" ) endif()