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# Find last `-B` and `-S` instances.
48foreach(i RANGE ${CMAKE_ARGC})
49  if(CMAKE_ARGV${i} MATCHES "^-B(.*)")
50    set(argB ${CMAKE_MATCH_1})
51    set(argB_index ${i})
52  elseif()
53  elseif(CMAKE_ARGV${i} MATCHES "^-S(.*)")
54    set(argS_index ${i})
55    set(argS ${CMAKE_MATCH_1})
56  endif()
57endforeach()
58
59if(DEFINED argB_index)
60  if(DEFINED argB)
61    set(CMAKE_BINARY_DIR ${argB})
62  else()
63    # value of -B follows in next index
64    math(EXPR argB_value_index "${argB_index} + 1")
65    set(CMAKE_BINARY_DIR ${CMAKE_ARGV${argB_value_index}})
66  endif()
67endif()
68
69if(DEFINED argS_index)
70  if(DEFINED argS)
71    set(APPLICATION_SOURCE_DIR ${argS})
72  else()
73    # value of -S follows in next index
74    math(EXPR argS_value_index "${argS_index} + 1")
75    set(APPLICATION_SOURCE_DIR ${CMAKE_ARGV${argS_value_index}})
76  endif()
77endif()
78
79if(NOT DEFINED APPLICATION_SOURCE_DIR)
80  message(FATAL_ERROR
81    "Source directory not defined, please use '-S <path-to-source>' to the "
82    "application for which this tool shall run.\n"
83    "For example: -S ${ZEPHYR_BASE}/samples/hello_world"
84  )
85endif()
86if(DEFINED APPLICATION_SOURCE_DIR)
87  cmake_path(ABSOLUTE_PATH APPLICATION_SOURCE_DIR NORMALIZE)
88endif()
89
90cmake_path(ABSOLUTE_PATH CMAKE_BINARY_DIR NORMALIZE)
91set(CMAKE_CURRENT_BINARY_DIR ${CMAKE_BINARY_DIR})
92
93if(NOT DEFINED MODULES)
94  message(FATAL_ERROR
95    "No MODULES defined, please invoke package helper with minimum one module"
96    " to execute in script mode."
97  )
98endif()
99
100string(REPLACE ";" "," MODULES "${MODULES}")
101find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE} COMPONENTS zephyr_default:${MODULES})
102