1# SPDX-License-Identifier: Apache-2.0
2
3# This file provides Zephyr Config Package version information.
4#
5# The purpose of the version file is to ensure that CMake find_package can correctly locate a
6# usable Zephyr installation for building of applications.
7
8# Checking for version 0.0.0 is a way to allow other Zephyr installation to determine if there is a better match.
9# A better match would be an installed Zephyr that has a common index with current source dir.
10# Version 0.0.0 indicates that we should just return, in order to obtain our path.
11if(0.0.0 STREQUAL PACKAGE_FIND_VERSION)
12  return()
13endif()
14
15macro(check_zephyr_version)
16  if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION)
17    if(IS_INCLUDED)
18      # We are just a candidate, meaning we have been included from other installed module.
19      message("\n  The following Zephyr repository configuration file were considered but not accepted:")
20      message("\n    ${CMAKE_CURRENT_LIST_FILE}, version: ${PACKAGE_VERSION}\n")
21    endif()
22
23    set(PACKAGE_VERSION_COMPATIBLE FALSE)
24  else()
25    # For now, Zephyr is capable to find the right base on all older versions as long as they define
26    # a Zephyr config package (This code)
27    # In future, this is the place to update in case Zephyr 3.x is not backward compatible with version 2.x
28    set(PACKAGE_VERSION_COMPATIBLE TRUE)
29    if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION)
30      set(PACKAGE_VERSION_EXACT TRUE)
31    endif()
32  endif()
33endmacro()
34
35# First check to see if user has provided a Zephyr base manually and it is first run (cache not set).
36set(ENV_ZEPHYR_BASE $ENV{ZEPHYR_BASE})
37if((NOT DEFINED ZEPHYR_BASE) AND (DEFINED ENV_ZEPHYR_BASE))
38  # Get rid of any double folder string before comparison, as example, user provides
39  # ZEPHYR_BASE=//path/to//zephyr_base/
40  # must also work.
41  get_filename_component(ZEPHYR_BASE $ENV{ZEPHYR_BASE} ABSOLUTE)
42endif()
43
44# If ZEPHYR_CANDIDATE is set, it means this file was include instead of called via find_package directly.
45if(ZEPHYR_CANDIDATE)
46  set(IS_INCLUDED TRUE)
47else()
48  include(${CMAKE_CURRENT_LIST_DIR}/zephyr_package_search.cmake)
49endif()
50
51if((DEFINED ZEPHYR_BASE) OR (DEFINED ENV_ZEPHYR_BASE))
52  # ZEPHYR_BASE was set in cache from earlier run or in environment (first run),
53  # meaning the package version must be ignored and the Zephyr pointed to by
54  # ZEPHYR_BASE is to be used regardless of version.
55  if (${ZEPHYR_BASE}/share/zephyr-package/cmake STREQUAL ${CMAKE_CURRENT_LIST_DIR})
56    # We are the Zephyr to be used
57
58    set(NO_PRINT_VERSION True)
59    include(${ZEPHYR_BASE}/cmake/modules/version.cmake)
60    # Zephyr uses project version, but CMake package uses PACKAGE_VERSION
61    set(PACKAGE_VERSION ${PROJECT_VERSION})
62    check_zephyr_version()
63
64    if(IS_INCLUDED)
65      # We are included, so we need to ensure that the version of the top-level
66      # package file is returned. This Zephyr version has already been printed
67      # as part of `check_zephyr_version()`
68      if(NOT ${PACKAGE_VERSION_COMPATIBLE}
69        OR (Zephyr_FIND_VERSION_EXACT AND NOT PACKAGE_VERSION_EXACT)
70      )
71        # When Zephyr base is set and we are checked as an included file
72        # (IS_INCLUDED=True), then we are unable to retrieve the version of the
73        # parent Zephyr, therefore just mark it as ignored.
74        set(PACKAGE_VERSION "ignored (ZEPHYR_BASE is set)")
75      endif()
76    endif()
77  elseif ((NOT IS_INCLUDED) AND (DEFINED ZEPHYR_BASE))
78    check_zephyr_package(ZEPHYR_BASE ${ZEPHYR_BASE} VERSION_CHECK)
79  else()
80    # User has pointed to a different Zephyr installation, so don't use this version
81    set(PACKAGE_VERSION_COMPATIBLE FALSE)
82  endif()
83  return()
84endif()
85
86# Find out the current Zephyr base.
87get_filename_component(CURRENT_ZEPHYR_DIR ${CMAKE_CURRENT_LIST_DIR}/../../.. ABSOLUTE)
88get_filename_component(CURRENT_WORKSPACE_DIR ${CMAKE_CURRENT_LIST_DIR}/../../../.. ABSOLUTE)
89
90# Temporary set local Zephyr base to allow using version.cmake to find this Zephyr repository current version
91set(ZEPHYR_BASE ${CURRENT_ZEPHYR_DIR})
92
93# Tell version.cmake to not print as printing version for all Zephyr installations being tested
94# will lead to confusion on which is being used.
95set(NO_PRINT_VERSION True)
96include(${ZEPHYR_BASE}/cmake/modules/version.cmake)
97# Zephyr uses project version, but CMake package uses PACKAGE_VERSION
98set(PACKAGE_VERSION ${PROJECT_VERSION})
99set(ZEPHYR_BASE)
100
101# Do we share common index, if so, this is the correct version to check.
102string(FIND "${CMAKE_CURRENT_SOURCE_DIR}" "${CURRENT_ZEPHYR_DIR}/" COMMON_INDEX)
103if (COMMON_INDEX EQUAL 0)
104  # Project is a Zephyr repository app.
105
106  check_zephyr_version()
107  return()
108endif()
109
110if(NOT IS_INCLUDED)
111  # Only do this if we are an installed CMake Config package and checking for workspace candidates.
112
113  string(FIND "${CMAKE_CURRENT_SOURCE_DIR}" "${CURRENT_WORKSPACE_DIR}/" COMMON_INDEX)
114  if (COMMON_INDEX EQUAL 0)
115    # Project is a Zephyr workspace app.
116    # This means this Zephyr is likely the correct one, but there could be an alternative installed along-side
117    # Thus, check if there is an even better candidate.
118    check_zephyr_package(WORKSPACE_DIR ${CURRENT_WORKSPACE_DIR} VERSION_CHECK)
119
120    # We are the best candidate, so let's check our own version.
121    check_zephyr_version()
122    return()
123  endif()
124
125  # Checking for installed candidates which could also be an workspace candidates.
126  # This check works the following way.
127  # CMake finds packages will look all packages registered in the user package registry.
128  # As this code is processed inside registered packages, we simply test if
129  # another package has a common path with the current sample, and if so, we
130  # will return here, and let CMake call into the other registered package for
131  # real version checking.
132  check_zephyr_package(CHECK_ONLY VERSION_CHECK)
133
134  # Check for workspace candidates.
135  check_zephyr_package(SEARCH_PARENTS VERSION_CHECK)
136endif()
137
138# Ending here means there were no candidates in workspace of the app.
139# Thus, the app is built as a Zephyr Freestanding application.
140# Let's do basic CMake version checking.
141check_zephyr_version()
142