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# Its purpose is to allow the find_package basic signature mode to lookup Zephyr
8# SDK and based on user / environment settings of selected toolchain decide if
9# the Zephyr SDK CMake package should be loaded.
10#
11# It extends the Zephyr-sdk CMake package by providing more flexibility in when
12# the Zephyr SDK is loaded and loads additional host tools from the Zephyr SDK.
13#
14# The module defines the following variables:
15#
16# 'ZEPHYR_SDK_INSTALL_DIR'
17# Install location of the Zephyr SDK
18#
19# 'ZEPHYR_TOOLCHAIN_VARIANT'
20# Zephyr toolchain variant to use if not defined already.
21#
22# 'Zephyr-sdk_FOUND'
23# True if the Zephyr SDK was found.
24
25# Set internal variables if set in environment.
26zephyr_get(ZEPHYR_TOOLCHAIN_VARIANT)
27
28zephyr_get(ZEPHYR_SDK_INSTALL_DIR)
29
30# Load Zephyr SDK Toolchain.
31# There are three scenarios where Zephyr SDK should be looked up:
32# 1) Zephyr specified as toolchain (ZEPHYR_SDK_INSTALL_DIR still used if defined)
33# 2) No toolchain specified == Default to Zephyr toolchain
34# Until we completely deprecate it
35if(("zephyr" STREQUAL ${ZEPHYR_TOOLCHAIN_VARIANT}) OR
36   (NOT DEFINED ZEPHYR_TOOLCHAIN_VARIANT) OR
37   (DEFINED ZEPHYR_SDK_INSTALL_DIR) OR
38   (Zephyr-sdk_FIND_REQUIRED))
39
40  # No toolchain was specified, so inform user that we will be searching.
41  if (NOT DEFINED ZEPHYR_SDK_INSTALL_DIR AND
42      NOT DEFINED ZEPHYR_TOOLCHAIN_VARIANT)
43    message(STATUS "ZEPHYR_TOOLCHAIN_VARIANT not set, trying to locate Zephyr SDK")
44  endif()
45
46  # This ensure packages are sorted in descending order.
47  SET(CMAKE_FIND_PACKAGE_SORT_DIRECTION_CURRENT ${CMAKE_FIND_PACKAGE_SORT_DIRECTION})
48  SET(CMAKE_FIND_PACKAGE_SORT_ORDER_CURRENT ${CMAKE_FIND_PACKAGE_SORT_ORDER})
49  SET(CMAKE_FIND_PACKAGE_SORT_DIRECTION DEC)
50  SET(CMAKE_FIND_PACKAGE_SORT_ORDER NATURAL)
51
52  if(DEFINED ZEPHYR_SDK_INSTALL_DIR)
53    # The Zephyr SDK will automatically set the toolchain variant.
54    # To support Zephyr SDK tools (DTC, and other tools) with 3rd party toolchains
55    # then we keep track of current toolchain variant.
56    set(ZEPHYR_CURRENT_TOOLCHAIN_VARIANT ${ZEPHYR_TOOLCHAIN_VARIANT})
57    find_package(Zephyr-sdk ${Zephyr-sdk_FIND_VERSION}
58                 REQUIRED QUIET CONFIG HINTS ${ZEPHYR_SDK_INSTALL_DIR}
59    )
60    if(DEFINED ZEPHYR_CURRENT_TOOLCHAIN_VARIANT)
61      set(ZEPHYR_TOOLCHAIN_VARIANT ${ZEPHYR_CURRENT_TOOLCHAIN_VARIANT})
62    endif()
63  else()
64    # Paths that are used to find installed Zephyr SDK versions
65    SET(zephyr_sdk_search_paths
66        /usr
67        /usr/local
68        /opt
69        $ENV{HOME}
70        $ENV{HOME}/.local
71        $ENV{HOME}/.local/opt
72        $ENV{HOME}/bin)
73
74    # Search for Zephyr SDK version 0.0.0 which does not exist, this is needed to
75    # return a list of compatible versions and find the best suited version that
76    # is available.
77    find_package(Zephyr-sdk 0.0.0 EXACT QUIET CONFIG PATHS ${zephyr_sdk_search_paths})
78
79    # Remove duplicate entries and sort naturally in descending order.
80    set(zephyr_sdk_found_versions ${Zephyr-sdk_CONSIDERED_VERSIONS})
81    set(zephyr_sdk_found_configs ${Zephyr-sdk_CONSIDERED_CONFIGS})
82
83    list(REMOVE_DUPLICATES Zephyr-sdk_CONSIDERED_VERSIONS)
84    list(SORT Zephyr-sdk_CONSIDERED_VERSIONS COMPARE NATURAL ORDER DESCENDING)
85
86    # Loop over each found Zepher SDK version until one is found that is compatible.
87    foreach(zephyr_sdk_candidate ${Zephyr-sdk_CONSIDERED_VERSIONS})
88      if("${zephyr_sdk_candidate}" VERSION_GREATER_EQUAL "${Zephyr-sdk_FIND_VERSION}")
89        # Find the path for the current version being checked and get the directory
90        # of the Zephyr SDK so it can be checked.
91        list(FIND zephyr_sdk_found_versions ${zephyr_sdk_candidate} zephyr_sdk_current_index)
92        list(GET zephyr_sdk_found_configs ${zephyr_sdk_current_index} zephyr_sdk_current_check_path)
93        get_filename_component(zephyr_sdk_current_check_path ${zephyr_sdk_current_check_path} DIRECTORY)
94
95        # Then see if this version is compatible.
96        find_package(Zephyr-sdk ${Zephyr-sdk_FIND_VERSION} QUIET CONFIG PATHS ${zephyr_sdk_current_check_path} NO_DEFAULT_PATH)
97
98        if (${Zephyr-sdk_FOUND})
99          # A compatible version of the Zephyr SDK has been found which is the highest
100          # supported version, exit.
101          break()
102        endif()
103      endif()
104    endforeach()
105
106    if (NOT ${Zephyr-sdk_FOUND})
107      # This means no compatible Zephyr SDK versions were found, set the version
108      # back to the minimum version so that it is displayed in the error text.
109      find_package(Zephyr-sdk ${Zephyr-sdk_FIND_VERSION} REQUIRED CONFIG PATHS ${zephyr_sdk_search_paths})
110    endif()
111  endif()
112
113  SET(CMAKE_FIND_PACKAGE_SORT_DIRECTION ${CMAKE_FIND_PACKAGE_SORT_DIRECTION_CURRENT})
114  SET(CMAKE_FIND_PACKAGE_SORT_ORDER ${CMAKE_FIND_PACKAGE_SORT_ORDER_CURRENT})
115endif()
116
117# Clean up temp variables
118set(zephyr_sdk_search_paths)
119set(zephyr_sdk_found_versions)
120set(zephyr_sdk_found_configs)
121set(zephyr_sdk_current_index)
122set(zephyr_sdk_current_check_path)
123
124if(DEFINED ZEPHYR_SDK_INSTALL_DIR)
125  # Cache the Zephyr SDK install dir.
126  set(ZEPHYR_SDK_INSTALL_DIR ${ZEPHYR_SDK_INSTALL_DIR} CACHE PATH "Zephyr SDK install directory")
127endif()
128
129if(Zephyr-sdk_FOUND)
130  include(${ZEPHYR_SDK_INSTALL_DIR}/cmake/zephyr/host-tools.cmake)
131
132  message(STATUS "Found host-tools: zephyr ${SDK_VERSION} (${ZEPHYR_SDK_INSTALL_DIR})")
133endif()
134