1# SPDX-License-Identifier: Apache-2.0 2# 3# Copyright (c) 2022-2023, Nordic Semiconductor ASA 4 5# FindZephyr-sdk module for supporting module search mode of Zephyr SDK. 6# 7# It is possible to control the behavior of the Zephyr-SDK package using 8# COMPONENTS. 9# The Zephyr-SDK package supports the components: 10# - LOAD: Load a Zephyr-SDK. This is the default behavior if no COMPONENTS is specified. 11# Its purpose is to allow the find_package basic signature mode to lookup Zephyr 12# SDK and based on user / environment settings of selected toolchain decide if 13# the Zephyr SDK CMake package should be loaded. 14# 15# It extends the Zephyr-sdk CMake package by providing more flexibility in when 16# the Zephyr SDK is loaded and loads additional host tools from the Zephyr SDK. 17# 18# The module defines the following variables when used in normal search and load mode: 19# 'ZEPHYR_SDK_INSTALL_DIR' 20# Install location of the Zephyr SDK 21# 22# 'ZEPHYR_TOOLCHAIN_VARIANT' 23# Zephyr toolchain variant to use if not defined already. 24# 25# 'Zephyr-sdk_FOUND' 26# True if the Zephyr SDK was found. 27 28# - LIST: Will list all available Zephyr SDKs found in the system but not load 29# any Sdk. This can be used to fetch available Zephyr-SDKs before doing 30# an actual load. 31# LIST component will define the following lists: 32# - Zephyr-sdk : Version of a Zephyr-SDK 33# - Zephyr-sdk_DIRS : Install dir of the Zephyr-SDK 34# Each entry in Zephyr-SDK has a corresponding entry in Zephyr-SDK_DIRS. 35# For example: 36# index: Zephyr-sdk: Zephyr-sdk_DIRS: 37# 0 0.15.0 /opt/zephyr-sdk-0.15.0 38# 1 0.16.0 /home/<user>/zephyr-sdk-0.16.0 39# 40 41include(extensions) 42 43# Set internal variables if set in environment. 44zephyr_get(ZEPHYR_TOOLCHAIN_VARIANT) 45 46zephyr_get(ZEPHYR_SDK_INSTALL_DIR) 47 48if("${Zephyr-sdk_FIND_COMPONENTS}" STREQUAL "") 49 set(Zephyr-sdk_FIND_COMPONENTS LOAD) 50endif() 51 52# Load Zephyr SDK Toolchain. 53# There are three scenarios where Zephyr SDK should be looked up: 54# 1) Zephyr specified as toolchain (ZEPHYR_SDK_INSTALL_DIR still used if defined) 55# 2) No toolchain specified == Default to Zephyr toolchain 56# Until we completely deprecate it 57if(("zephyr" STREQUAL ${ZEPHYR_TOOLCHAIN_VARIANT}) OR 58 (NOT DEFINED ZEPHYR_TOOLCHAIN_VARIANT) OR 59 (DEFINED ZEPHYR_SDK_INSTALL_DIR) OR 60 (Zephyr-sdk_FIND_REQUIRED)) 61 62 # No toolchain was specified, so inform user that we will be searching. 63 if (NOT Zephyr-sdk_FIND_QUIETLY AND 64 NOT DEFINED ZEPHYR_SDK_INSTALL_DIR AND 65 NOT DEFINED ZEPHYR_TOOLCHAIN_VARIANT) 66 message(STATUS "ZEPHYR_TOOLCHAIN_VARIANT not set, trying to locate Zephyr SDK") 67 endif() 68 69 # This ensure packages are sorted in descending order. 70 SET(CMAKE_FIND_PACKAGE_SORT_DIRECTION_CURRENT ${CMAKE_FIND_PACKAGE_SORT_DIRECTION}) 71 SET(CMAKE_FIND_PACKAGE_SORT_ORDER_CURRENT ${CMAKE_FIND_PACKAGE_SORT_ORDER}) 72 SET(CMAKE_FIND_PACKAGE_SORT_DIRECTION DEC) 73 SET(CMAKE_FIND_PACKAGE_SORT_ORDER NATURAL) 74 75 if(DEFINED ZEPHYR_SDK_INSTALL_DIR AND LOAD IN_LIST Zephyr-sdk_FIND_COMPONENTS) 76 # The Zephyr SDK will automatically set the toolchain variant. 77 # To support Zephyr SDK tools (DTC, and other tools) with 3rd party toolchains 78 # then we keep track of current toolchain variant. 79 set(ZEPHYR_CURRENT_TOOLCHAIN_VARIANT ${ZEPHYR_TOOLCHAIN_VARIANT}) 80 find_package(Zephyr-sdk ${Zephyr-sdk_FIND_VERSION_COMPLETE} 81 REQUIRED QUIET CONFIG HINTS ${ZEPHYR_SDK_INSTALL_DIR} 82 ) 83 if(DEFINED ZEPHYR_CURRENT_TOOLCHAIN_VARIANT) 84 set(ZEPHYR_TOOLCHAIN_VARIANT ${ZEPHYR_CURRENT_TOOLCHAIN_VARIANT}) 85 endif() 86 else() 87 # Paths that are used to find installed Zephyr SDK versions 88 SET(zephyr_sdk_search_paths 89 /usr 90 /usr/local 91 /opt 92 $ENV{HOME} 93 $ENV{HOME}/.local 94 $ENV{HOME}/.local/opt 95 $ENV{HOME}/bin) 96 97 # Search for Zephyr SDK version 0.0.0 which does not exist, this is needed to 98 # return a list of compatible versions and find the best suited version that 99 # is available. 100 find_package(Zephyr-sdk 0.0.0 EXACT QUIET CONFIG PATHS ${zephyr_sdk_search_paths}) 101 102 # Remove duplicate entries and sort naturally in descending order. 103 foreach(version config IN ZIP_LISTS Zephyr-sdk_CONSIDERED_VERSIONS Zephyr-sdk_CONSIDERED_CONFIGS) 104 if(NOT DEFINED Zephyr-sdk-${version}_DIR) 105 set(Zephyr-sdk-${version}_DIR ${config}) 106 endif() 107 endforeach() 108 109 list(REMOVE_DUPLICATES Zephyr-sdk_CONSIDERED_VERSIONS) 110 list(SORT Zephyr-sdk_CONSIDERED_VERSIONS COMPARE NATURAL ORDER DESCENDING) 111 112 if(LIST IN_LIST Zephyr-sdk_FIND_COMPONENTS) 113 set(Zephyr-sdk) 114 set(Zephyr-sdk_DIRS) 115 # Only list the Zephyr SDKs installed in the system. 116 foreach(version ${Zephyr-sdk_CONSIDERED_VERSIONS}) 117 cmake_path(GET Zephyr-sdk-${version}_DIR PARENT_PATH dir) 118 cmake_path(GET dir PARENT_PATH dir) 119 list(APPEND Zephyr-sdk ${version}) 120 list(APPEND Zephyr-sdk_DIRS ${dir}) 121 if (NOT Zephyr-sdk_FIND_QUIETLY) 122 message(STATUS "Zephyr-sdk, version=${version}, dir=${dir}") 123 endif() 124 endforeach() 125 else() 126 if("${Zephyr-sdk_FIND_VERSION_RANGE_MAX}" STREQUAL "INCLUDE") 127 set(upper_bound _EQUAL) 128 endif() 129 130 if(NOT DEFINED Zephyr-sdk_FIND_VERSION_RANGE) 131 # Range not given, max out to ensure max version is not in effect. 132 set(Zephyr-sdk_FIND_VERSION_MAX 99999999) 133 endif() 134 135 # Loop over each found Zepher SDK version until one is found that is compatible. 136 foreach(zephyr_sdk_candidate ${Zephyr-sdk_CONSIDERED_VERSIONS}) 137 if("${zephyr_sdk_candidate}" VERSION_GREATER_EQUAL "${Zephyr-sdk_FIND_VERSION}" 138 AND "${zephyr_sdk_candidate}" VERSION_LESS${upper_bound} "${Zephyr-sdk_FIND_VERSION_MAX}" 139 ) 140 # Find the path for the current version being checked and get the directory 141 # of the Zephyr SDK so it can be checked. 142 cmake_path(GET Zephyr-sdk-${zephyr_sdk_candidate}_DIR PARENT_PATH zephyr_sdk_current_check_path) 143 cmake_path(GET zephyr_sdk_current_check_path PARENT_PATH zephyr_sdk_current_check_path) 144 145 # Then see if this version is compatible. 146 find_package(Zephyr-sdk ${Zephyr-sdk_FIND_VERSION_COMPLETE} QUIET CONFIG PATHS ${zephyr_sdk_current_check_path} NO_DEFAULT_PATH) 147 148 if (${Zephyr-sdk_FOUND}) 149 # A compatible version of the Zephyr SDK has been found which is the highest 150 # supported version, exit. 151 break() 152 endif() 153 endif() 154 endforeach() 155 156 if (NOT ${Zephyr-sdk_FOUND}) 157 # This means no compatible Zephyr SDK versions were found, set the version 158 # back to the minimum version so that it is displayed in the error text. 159 find_package(Zephyr-sdk ${Zephyr-sdk_FIND_VERSION_COMPLETE} REQUIRED CONFIG PATHS ${zephyr_sdk_search_paths}) 160 endif() 161 endif() 162 endif() 163 164 SET(CMAKE_FIND_PACKAGE_SORT_DIRECTION ${CMAKE_FIND_PACKAGE_SORT_DIRECTION_CURRENT}) 165 SET(CMAKE_FIND_PACKAGE_SORT_ORDER ${CMAKE_FIND_PACKAGE_SORT_ORDER_CURRENT}) 166endif() 167 168# Clean up temp variables 169set(zephyr_sdk_search_paths) 170set(zephyr_sdk_found_versions) 171set(zephyr_sdk_found_configs) 172set(zephyr_sdk_current_index) 173set(zephyr_sdk_current_check_path) 174 175if(LOAD IN_LIST Zephyr-sdk_FIND_COMPONENTS) 176 if(DEFINED ZEPHYR_SDK_INSTALL_DIR) 177 # Cache the Zephyr SDK install dir. 178 set(ZEPHYR_SDK_INSTALL_DIR ${ZEPHYR_SDK_INSTALL_DIR} CACHE PATH "Zephyr SDK install directory") 179 endif() 180 181 if(Zephyr-sdk_FOUND) 182 include(${ZEPHYR_SDK_INSTALL_DIR}/cmake/zephyr/host-tools.cmake) 183 184 if (NOT Zephyr-sdk_FIND_QUIETLY) 185 message(STATUS "Found host-tools: zephyr ${SDK_VERSION} (${ZEPHYR_SDK_INSTALL_DIR})") 186 endif() 187 endif() 188endif() 189set(ZEPHYR_TOOLCHAIN_PATH ${ZEPHYR_SDK_INSTALL_DIR}) 190