Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmake: package_helper CMake script #41302

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 47 additions & 20 deletions cmake/modules/zephyr_default.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -32,40 +32,41 @@ find_package(ZephyrBuildConfiguration
)

# Prepare user cache
include(python)
include(user_cache)
list(APPEND zephyr_cmake_modules python)
list(APPEND zephyr_cmake_modules user_cache)

# Load Zephyr extensions
include(extensions)
include(version) # depends on hex.cmake
list(APPEND zephyr_cmake_modules extensions)
list(APPEND zephyr_cmake_modules version)

#
# Find tools
#

include(west)
include(ccache)
list(APPEND zephyr_cmake_modules west)
list(APPEND zephyr_cmake_modules ccache)

# Load default root settings
include(root)
list(APPEND zephyr_cmake_modules root)

#
# Find Zephyr modules.
# Those may contain additional DTS, BOARD, SOC, ARCH ROOTs.
# Also create the Kconfig binary dir for generated Kconf files.
#
include(zephyr_module)
list(APPEND zephyr_cmake_modules zephyr_module)

include(boards)
include(shields)
include(arch)
include(configuration_files)
list(APPEND zephyr_cmake_modules boards)
list(APPEND zephyr_cmake_modules shields)
list(APPEND zephyr_cmake_modules arch)
list(APPEND zephyr_cmake_modules configuration_files)

include(verify-toolchain)
include(host-tools)
list(APPEND zephyr_cmake_modules verify-toolchain)
list(APPEND zephyr_cmake_modules host-tools)

# Include board specific device-tree flags before parsing.
include(${BOARD_DIR}/pre_dt_board.cmake OPTIONAL)
set(pre_dt_board "\${BOARD_DIR}/pre_dt_board.cmake" OPTIONAL)
list(APPEND zephyr_cmake_modules "\${pre_dt_board}")

# DTS should be close to kconfig because CONFIG_ variables from
# kconfig and dts should be available at the same time.
Expand All @@ -80,9 +81,35 @@ include(${BOARD_DIR}/pre_dt_board.cmake OPTIONAL)
# preprocess DT sources, and then, after we have finished processing
# both DT and Kconfig we complete the target-specific configuration,
# and possibly change the toolchain.
include(generic_toolchain)
include(dts)
include(kconfig)
include(soc)
include(target_toolchain)
list(APPEND zephyr_cmake_modules generic_toolchain)
list(APPEND zephyr_cmake_modules dts)
list(APPEND zephyr_cmake_modules kconfig)
list(APPEND zephyr_cmake_modules soc)
list(APPEND zephyr_cmake_modules target_toolchain)

foreach(component ${SUB_COMPONENTS})
if(NOT ${component} IN_LIST zephyr_cmake_modules)
message(FATAL_ERROR
"Subcomponent '${component}' not default module for Zephyr CMake build system.\n"
"Please choose one or more valid components: ${zephyr_cmake_modules}"
)
endif()
endforeach()

foreach(module IN LISTS zephyr_cmake_modules)
# Ensures any module of type `${module}` are properly expanded to list before
# passed on the `include(${module})`.
# This is done twice to support cases where the content of `${module}` itself
# contains a variable, like `${BOARD_DIR}`.
string(CONFIGURE "${module}" module)
string(CONFIGURE "${module}" module)
include(${module})

list(REMOVE_ITEM SUB_COMPONENTS ${module})
if(DEFINED SUB_COMPONENTS AND NOT SUB_COMPONENTS)
# All requested Zephyr CMake modules have been loaded, so let's return.
return()
endif()
endforeach()

include(kernel)
115 changes: 115 additions & 0 deletions cmake/package_helper.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# SPDX-License-Identifier: Apache-2.0
#
# Copyright (c) 2021, Nordic Semiconductor ASA

# The Zephyr package helper script provides a generic script mode interface
# to the Zephyr CMake package and module structure.
#
# The purpose of this script is to provide a single entry for running any Zephyr
# build tool that is executed during CMake configure time without creating a
# complete build system.
#
# It does so by loading the Zephyr CMake modules specified with the 'MODULES'
# argument.
#
# This script executes the given module identical to Zephyr CMake configure time.
# The application source directory must be specified using
# '-S <path-to-sample>'
#
# The build directory will default to current working directory but can be
# controlled with: '-B <path-to-build>'
#
# For example, if you were invoking CMake for 'hello_world' sample as:
# $ cmake -DBOARD=<board> -B build -S samples/hello_world
#
# you can invoke only dts module (and dependencies) as:
# $ cmake -DBOARD=<board> -B build -S samples/hello_world \
# -DMODULES=dts -P <ZEPHYR_BASE>/cmake/package_helper.cmake
#
# It is also possible to pass additional build settings.
# If you invoke CMake for 'hello_world' as:
#
# $ cmake -DBOARD=<board> -B build -S samples/hello_world -DOVERLAY_CONFIG=foo.overlay
#
# you just add the same argument to the helper like:
# $ cmake -DBOARD=<board> -B build -S samples/hello_world -DOVERLAY_CONFIG=foo.overlay \
# -DMODULES=dts -P <ZEPHYR_BASE>/cmake/package_helper.cmake
#
# Note: the samples CMakeLists.txt file is not processed by package helper, so
# any 'set(<var> <value>)' specified before 'find_package(Zephyr)' must be
# manually applied, for example if the CMakeLists.txt contains:
# set(OVERLAY_CONFIG foo.overlay)
# find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
# the 'foo.overlay' must be specified using '-DOVERLAY_CONFIG=foo.overlay'

cmake_minimum_required(VERSION 3.20)

# add_custom_target and set_target_properties are not supported in script mode.
# However, several Zephyr CMake modules create custom target for user convenience
# like menuconfig, boards, shields, etc.
# As we are not generating a build system with this tool, only running part of
# the modules, then we simply override those functions to allow running those
# modules.
function(add_custom_target)
# This silence the error: 'add_custom_target command is not scriptable'
endfunction()

function(set_target_properties)
# This silence the error: 'set_target_properties command is not scriptable'
endfunction()

# Find last `-B` and `-S` instances.
foreach(i RANGE ${CMAKE_ARGC})
if(CMAKE_ARGV${i} MATCHES "^-B(.*)")
set(argB ${CMAKE_MATCH_1})
set(argB_index ${i})
elseif()
elseif(CMAKE_ARGV${i} MATCHES "^-S(.*)")
set(argS_index ${i})
set(argS ${CMAKE_MATCH_1})
endif()
endforeach()

if(DEFINED argB_index)
if(DEFINED argB)
set(CMAKE_BINARY_DIR ${argB})
else()
# value of -B follows in next index
math(EXPR argB_value_index "${argB_index} + 1")
set(CMAKE_BINARY_DIR ${CMAKE_ARGV${argB_value_index}})
endif()
endif()

if(DEFINED argS_index)
if(DEFINED argS)
set(APPLICATION_SOURCE_DIR ${argS})
else()
# value of -S follows in next index
math(EXPR argS_value_index "${argS_index} + 1")
set(APPLICATION_SOURCE_DIR ${CMAKE_ARGV${argS_value_index}})
endif()
endif()

if(NOT DEFINED APPLICATION_SOURCE_DIR)
message(FATAL_ERROR
"Source directory not defined, please use '-S <path-to-source>' to the "
"application for which this tool shall run.\n"
"For example: -S ${ZEPHYR_BASE}/samples/hello_world"
)
endif()
if(DEFINED APPLICATION_SOURCE_DIR)
cmake_path(ABSOLUTE_PATH APPLICATION_SOURCE_DIR NORMALIZE)
endif()

cmake_path(ABSOLUTE_PATH CMAKE_BINARY_DIR NORMALIZE)
set(CMAKE_CURRENT_BINARY_DIR ${CMAKE_BINARY_DIR})

if(NOT DEFINED MODULES)
message(FATAL_ERROR
"No MODULES defined, please invoke package helper with minimum one module"
" to execute in script mode."
)
endif()

string(REPLACE ";" "," MODULES "${MODULES}")
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE} COMPONENTS zephyr_default:${MODULES})
4 changes: 4 additions & 0 deletions share/zephyr-package/cmake/ZephyrConfig.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ macro(include_boilerplate location)
else()
message("Loading Zephyr module(s) (${location}): ${Zephyr_FIND_COMPONENTS}")
foreach(component ${Zephyr_FIND_COMPONENTS})
if(${component} MATCHES "^\([^:]*\):\(.*\)$")
string(REPLACE "," ";" SUB_COMPONENTS ${CMAKE_MATCH_2})
set(component ${CMAKE_MATCH_1})
endif()
include(${component})
endforeach()
endif()
Expand Down