1# SPDX-License-Identifier: Apache-2.0 2# 3# Copyright (c) 2021, Nordic Semiconductor ASA 4 5# The Zephyr package helper script provides a generic script mode interface 6# to the Zephyr CMake package and module structure. 7# 8# The purpose of this script is to provide a single entry for running any Zephyr 9# build tool that is executed during CMake configure time without creating a 10# complete build system. 11# 12# It does so by loading the Zephyr CMake modules specified with the 'MODULES' 13# argument. 14# 15# This script executes the given module identical to Zephyr CMake configure time. 16# The application source directory must be specified using 17# '-S <path-to-sample>' 18# 19# The build directory will default to current working directory but can be 20# controlled with: '-B <path-to-build>' 21# 22# For example, if you were invoking CMake for 'hello_world' sample as: 23# $ cmake -DBOARD=<board> -B build -S samples/hello_world 24# 25# you can invoke only dts module (and dependencies) as: 26# $ cmake -DBOARD=<board> -B build -S samples/hello_world \ 27# -DMODULES=dts -P <ZEPHYR_BASE>/cmake/package_helper.cmake 28# 29# It is also possible to pass additional build settings. 30# If you invoke CMake for 'hello_world' as: 31# 32# $ cmake -DBOARD=<board> -B build -S samples/hello_world -DEXTRA_CONF_FILE=foo.conf 33# 34# you just add the same argument to the helper like: 35# $ cmake -DBOARD=<board> -B build -S samples/hello_world -DEXTRA_CONF_FILE=foo.conf \ 36# -DMODULES=dts -P <ZEPHYR_BASE>/cmake/package_helper.cmake 37# 38# Note: the samples CMakeLists.txt file is not processed by package helper, so 39# any 'set(<var> <value>)' specified before 'find_package(Zephyr)' must be 40# manually applied, for example if the CMakeLists.txt contains: 41# set(EXTRA_CONF_FILE foo.conf) 42# find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) 43# the 'foo.conf' must be specified using '-DEXTRA_CONF_FILE=foo.conf' 44 45cmake_minimum_required(VERSION 3.20.5) 46 47# add_custom_target and set_target_properties are not supported in script mode. 48# However, several Zephyr CMake modules create custom target for user convenience 49# like menuconfig, boards, shields, etc. 50# As we are not generating a build system with this tool, only running part of 51# the modules, then we simply override those functions to allow running those 52# modules. 53function(add_custom_target) 54 # This silence the error: 'add_custom_target command is not scriptable' 55endfunction() 56 57function(set_target_properties) 58 # This silence the error: 'set_target_properties command is not scriptable' 59endfunction() 60 61# Find last `-B` and `-S` instances. 62foreach(i RANGE ${CMAKE_ARGC}) 63 if(CMAKE_ARGV${i} MATCHES "^-B(.*)") 64 set(argB ${CMAKE_MATCH_1}) 65 set(argB_index ${i}) 66 elseif() 67 elseif(CMAKE_ARGV${i} MATCHES "^-S(.*)") 68 set(argS_index ${i}) 69 set(argS ${CMAKE_MATCH_1}) 70 endif() 71endforeach() 72 73if(DEFINED argB_index) 74 if(DEFINED argB) 75 set(CMAKE_BINARY_DIR ${argB}) 76 else() 77 # value of -B follows in next index 78 math(EXPR argB_value_index "${argB_index} + 1") 79 set(CMAKE_BINARY_DIR ${CMAKE_ARGV${argB_value_index}}) 80 endif() 81endif() 82 83if(DEFINED argS_index) 84 if(DEFINED argS) 85 set(APPLICATION_SOURCE_DIR ${argS}) 86 else() 87 # value of -S follows in next index 88 math(EXPR argS_value_index "${argS_index} + 1") 89 set(APPLICATION_SOURCE_DIR ${CMAKE_ARGV${argS_value_index}}) 90 endif() 91endif() 92 93if(NOT DEFINED APPLICATION_SOURCE_DIR) 94 message(FATAL_ERROR 95 "Source directory not defined, please use '-S <path-to-source>' to the " 96 "application for which this tool shall run.\n" 97 "For example: -S ${ZEPHYR_BASE}/samples/hello_world" 98 ) 99endif() 100if(DEFINED APPLICATION_SOURCE_DIR) 101 cmake_path(ABSOLUTE_PATH APPLICATION_SOURCE_DIR NORMALIZE) 102endif() 103 104cmake_path(ABSOLUTE_PATH CMAKE_BINARY_DIR NORMALIZE) 105set(CMAKE_CURRENT_BINARY_DIR ${CMAKE_BINARY_DIR}) 106 107if(NOT DEFINED MODULES) 108 message(FATAL_ERROR 109 "No MODULES defined, please invoke package helper with minimum one module" 110 " to execute in script mode." 111 ) 112endif() 113 114# Loading Zephyr CMake extension commands, which allows us to overload Zephyr 115# scoping rules. 116find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE} COMPONENTS extensions) 117 118# Zephyr scoping creates custom targets for handling of properties. 119# However, custom targets cannot be used in CMake script mode. 120# Therefore disable zephyr_set(... SCOPE ...) in package helper as it is not needed. 121function(zephyr_set variable) 122 # This silence the error: zephyr_set(... SCOPE <scope>) doesn't exists. 123endfunction() 124 125string(REPLACE ";" "," MODULES "${MODULES}") 126find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE} COMPONENTS zephyr_default:${MODULES}) 127