tools/corrosion/cmake/FindRust.cmake
branchtransitional_engine
changeset 16021 6a3dc15b78b9
equal deleted inserted replaced
16009:7544a7d7c819 16021:6a3dc15b78b9
       
     1 #[=======================================================================[.rst:
       
     2 FindRust
       
     3 --------
       
     4 
       
     5 Find Rust
       
     6 
       
     7 This module finds an installed rustc compiler and the cargo build tool. If Rust
       
     8 is managed by rustup it determines the available toolchains and returns a
       
     9 concrete Rust version, not a rustup proxy.
       
    10 
       
    11 #]=======================================================================]
       
    12 
       
    13 cmake_minimum_required(VERSION 3.12)
       
    14 
       
    15 # search for Cargo here and set up a bunch of cool flags and stuff
       
    16 include(FindPackageHandleStandardArgs)
       
    17 
       
    18 list(APPEND CMAKE_MESSAGE_CONTEXT "FindRust")
       
    19 
       
    20 # Print error message and return.
       
    21 macro(_findrust_failed)
       
    22     if("${Rust_FIND_REQUIRED}")
       
    23         message(FATAL_ERROR ${ARGN})
       
    24     elseif(NOT "${Rust_FIND_QUIETLY}")
       
    25         message(WARNING ${ARGN})
       
    26     endif()
       
    27     # Note: PARENT_SCOPE is the scope of the caller of the caller of this macro.
       
    28     set(Rust_FOUND "" PARENT_SCOPE)
       
    29     return()
       
    30 endmacro()
       
    31 
       
    32 # Checks if the actual version of a Rust toolchain matches the VERSION requirements specified in find_package.
       
    33 function(_findrust_version_ok ACTUAL_VERSION OUT_IS_OK)
       
    34     if(DEFINED Rust_FIND_VERSION_RANGE)
       
    35         if(Rust_FIND_VERSION_RANGE_MAX STREQUAL "INCLUDE")
       
    36             set(COMPARSION_OPERATOR "VERSION_LESS_EQUAL")
       
    37         elseif(Rust_FIND_VERSION_RANGE_MAX STREQUAL "EXCLUDE")
       
    38             set(COMPARSION_OPERATOR "VERSION_LESS")
       
    39         else()
       
    40             message(FATAL_ERROR "Unexpected value in `<PackageName>_FIND_VERSION_RANGE_MAX`: "
       
    41                     "`${Rust_FIND_VERSION_RANGE_MAX}`.")
       
    42         endif()
       
    43         if(("${ACTUAL_VERSION}" VERSION_GREATER_EQUAL "${Rust_FIND_VERSION_RANGE_MIN}")
       
    44                 AND
       
    45             ( "${ACTUAL_VERSION}" ${COMPARSION_OPERATOR} "${Rust_FIND_VERSION_RANGE_MAX}" )
       
    46         )
       
    47             set("${OUT_IS_OK}" TRUE PARENT_SCOPE)
       
    48         else()
       
    49             set("${OUT_IS_OK}" FALSE PARENT_SCOPE)
       
    50         endif()
       
    51     elseif(DEFINED Rust_FIND_VERSION)
       
    52         if(Rust_VERSION_EXACT)
       
    53             set(COMPARISON_OPERATOR VERSION_EQUAL)
       
    54         else()
       
    55             set(COMPARISON_OPERATOR VERSION_GREATER_EQUAL)
       
    56         endif()
       
    57         if(_TOOLCHAIN_${_TOOLCHAIN_SELECTED}_VERSION "${COMPARISON_OPERATOR}" Rust_FIND_VERSION)
       
    58             set("${OUT_IS_OK}" TRUE PARENT_SCOPE)
       
    59         else()
       
    60             set("${OUT_IS_OK}" FALSE PARENT_SCOPE)
       
    61         endif()
       
    62     else()
       
    63         # if no VERSION requirement was specified, the version is always okay.
       
    64         set("${OUT_IS_OK}" TRUE PARENT_SCOPE)
       
    65     endif()
       
    66 endfunction()
       
    67 
       
    68 function(_corrosion_strip_target_triple input_triple_or_path output_triple)
       
    69     # If the target_triple is a path to a custom target specification file, then strip everything
       
    70     # except the filename from `target_triple`.
       
    71     get_filename_component(target_triple_ext "${input_triple_or_path}" EXT)
       
    72     set(target_triple "${input_triple_or_path}")
       
    73     if(target_triple_ext)
       
    74         if(target_triple_ext STREQUAL ".json")
       
    75             get_filename_component(target_triple "${input_triple_or_path}"  NAME_WE)
       
    76         endif()
       
    77     endif()
       
    78     set(${output_triple} "${target_triple}" PARENT_SCOPE)
       
    79 endfunction()
       
    80 
       
    81 function(_corrosion_parse_target_triple target_triple out_arch out_vendor out_os out_env)
       
    82     _corrosion_strip_target_triple(${target_triple} target_triple)
       
    83 
       
    84     # The vendor part may be left out from the target triple, and since `env` is also optional,
       
    85     # we determine if vendor is present by matching against a list of known vendors.
       
    86     set(known_vendors
       
    87         "apple"
       
    88         "esp[a-z0-9]*" # espressif, e.g. riscv32imc-esp-espidf or xtensa-esp32s3-none-elf
       
    89         "fortanix"
       
    90         "kmc"
       
    91         "pc"
       
    92         "nintendo"
       
    93         "nvidia"
       
    94         "openwrt"
       
    95         "alpine"
       
    96         "chimera"
       
    97         "unikraft"
       
    98         "unknown"
       
    99         "uwp" # aarch64-uwp-windows-msvc
       
   100         "wrs" # e.g. aarch64-wrs-vxworks
       
   101         "sony"
       
   102         "sun"
       
   103         )
       
   104     # todo: allow users to add additional vendors to the list via a cmake variable.
       
   105     list(JOIN known_vendors "|" known_vendors_joined)
       
   106     # vendor is optional - We detect if vendor is present by matching against a known list of
       
   107     # vendors. The next field is the OS, which we assume to always be present, while the last field
       
   108     # is again optional and contains the environment.
       
   109     string(REGEX MATCH
       
   110         "^([a-z0-9_\.]+)-((${known_vendors_joined})-)?([a-z0-9_]+)(-([a-z0-9_]+))?$"
       
   111         whole_match
       
   112         "${target_triple}"
       
   113         )
       
   114     if((NOT whole_match) AND (NOT CORROSION_NO_WARN_PARSE_TARGET_TRIPLE_FAILED))
       
   115         message(WARNING "Failed to parse target-triple `${target_triple}`."
       
   116             "Corrosion determines some information about the output artifacts based on OS "
       
   117             "specified in the Rust target-triple.\n"
       
   118             "Currently this is relevant for windows and darwin (mac) targets, since file "
       
   119             "extensions differ.\n"
       
   120             "Note: If you are targeting a different OS you can suppress this warning by"
       
   121             " setting the CMake cache variable "
       
   122             "`CORROSION_NO_WARN_PARSE_TARGET_TRIPLE_FAILED`."
       
   123             "Please consider opening an issue on github if you you need to add a new vendor to the list."
       
   124             )
       
   125     endif()
       
   126 
       
   127     message(DEBUG "Parsed Target triple: arch: ${CMAKE_MATCH_1}, vendor: ${CMAKE_MATCH_3}, "
       
   128         "OS: ${CMAKE_MATCH_4}, env: ${CMAKE_MATCH_6}")
       
   129 
       
   130     set("${out_arch}" "${CMAKE_MATCH_1}" PARENT_SCOPE)
       
   131     set("${out_vendor}" "${CMAKE_MATCH_3}" PARENT_SCOPE)
       
   132     set("${out_os}" "${CMAKE_MATCH_4}" PARENT_SCOPE)
       
   133     set("${out_env}" "${CMAKE_MATCH_6}" PARENT_SCOPE)
       
   134 endfunction()
       
   135 
       
   136 function(_corrosion_determine_libs_new target_triple out_libs out_flags)
       
   137     set(package_dir "${CMAKE_BINARY_DIR}/corrosion/required_libs")
       
   138     # Cleanup on reconfigure to get a cleans state (in case we change something in the future)
       
   139     file(REMOVE_RECURSE "${package_dir}")
       
   140     file(MAKE_DIRECTORY "${package_dir}")
       
   141     set(manifest "[package]\nname = \"required_libs\"\nedition = \"2018\"\nversion = \"0.1.0\"\n")
       
   142     string(APPEND manifest "\n[lib]\ncrate-type=[\"staticlib\"]\npath = \"lib.rs\"\n")
       
   143     string(APPEND manifest "\n[workspace]\n")
       
   144     file(WRITE "${package_dir}/Cargo.toml" "${manifest}")
       
   145     file(WRITE "${package_dir}/lib.rs" "pub fn add(left: usize, right: usize) -> usize {left + right}\n")
       
   146 
       
   147     execute_process(
       
   148         COMMAND ${CMAKE_COMMAND} -E env
       
   149             "CARGO_BUILD_RUSTC=${Rust_COMPILER_CACHED}"
       
   150         ${Rust_CARGO_CACHED} rustc --verbose --color never --target=${target_triple} -- --print=native-static-libs
       
   151         WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/corrosion/required_libs"
       
   152         RESULT_VARIABLE cargo_build_result
       
   153         ERROR_VARIABLE cargo_build_error_message
       
   154     )
       
   155     if(cargo_build_result)
       
   156         message(DEBUG "Determining required native libraries - failed: ${cargo_build_result}.")
       
   157         message(TRACE "The cargo build error was: ${cargo_build_error_message}")
       
   158         message(DEBUG "Note: This is expected for Rust targets without std support")
       
   159         return()
       
   160     else()
       
   161         # The pattern starts with `native-static-libs:` and goes to the end of the line.
       
   162         if(cargo_build_error_message MATCHES "native-static-libs: ([^\r\n]+)\r?\n")
       
   163             string(REPLACE " " ";" "libs_list" "${CMAKE_MATCH_1}")
       
   164             set(stripped_lib_list "")
       
   165             set(flag_list "")
       
   166 
       
   167             set(was_last_framework OFF)
       
   168             foreach(lib ${libs_list})
       
   169                 # merge -framework;lib -> "-framework lib" as CMake does de-duplication of link libraries, and -framework prefix is required
       
   170                 if (lib STREQUAL "-framework")
       
   171                     set(was_last_framework ON)
       
   172                     continue()
       
   173                 endif()
       
   174                 if (was_last_framework)
       
   175                     list(APPEND stripped_lib_list "-framework ${lib}")
       
   176                     set(was_last_framework OFF)
       
   177                     continue()
       
   178                 endif()
       
   179                 
       
   180                 # Flags start with / for MSVC
       
   181                 if (lib MATCHES "^/" AND ${target_triple} MATCHES "msvc$")
       
   182                     list(APPEND flag_list "${lib}")
       
   183                 else()
       
   184                     # Strip leading `-l` (unix) and potential .lib suffix (windows)
       
   185                     string(REGEX REPLACE "^-l" "" "stripped_lib" "${lib}")
       
   186                     string(REGEX REPLACE "\.lib$" "" "stripped_lib" "${stripped_lib}")
       
   187                     list(APPEND stripped_lib_list "${stripped_lib}")
       
   188                 endif()
       
   189             endforeach()
       
   190             set(libs_list "${stripped_lib_list}")
       
   191             # Special case `msvcrt` to link with the debug version in Debug mode.
       
   192             list(TRANSFORM libs_list REPLACE "^msvcrt$" "\$<\$<CONFIG:Debug>:msvcrtd>")
       
   193         else()
       
   194             message(DEBUG "Determining required native libraries - failed: Regex match failure.")
       
   195             message(DEBUG "`native-static-libs` not found in: `${cargo_build_error_message}`")
       
   196             return()
       
   197         endif()
       
   198     endif()
       
   199     set("${out_libs}" "${libs_list}" PARENT_SCOPE)
       
   200     set("${out_flags}" "${flag_list}" PARENT_SCOPE)
       
   201 endfunction()
       
   202 
       
   203 if (NOT "${Rust_TOOLCHAIN}" STREQUAL "$CACHE{Rust_TOOLCHAIN}")
       
   204     # Promote Rust_TOOLCHAIN to a cache variable if it is not already a cache variable
       
   205     set(Rust_TOOLCHAIN ${Rust_TOOLCHAIN} CACHE STRING "Requested rustup toolchain" FORCE)
       
   206 endif()
       
   207 
       
   208 set(_RESOLVE_RUSTUP_TOOLCHAINS_DESC "Indicates whether to descend into the toolchain pointed to by rustup")
       
   209 set(Rust_RESOLVE_RUSTUP_TOOLCHAINS ON CACHE BOOL ${_RESOLVE_RUSTUP_TOOLCHAINS_DESC})
       
   210 
       
   211 # This block checks to see if we're prioritizing a rustup-managed toolchain.
       
   212 if (DEFINED Rust_TOOLCHAIN)
       
   213     # If the user specifies `Rust_TOOLCHAIN`, then look for `rustup` first, rather than `rustc`.
       
   214     find_program(Rust_RUSTUP rustup PATHS "$ENV{HOME}/.cargo/bin")
       
   215     if(NOT Rust_RUSTUP)
       
   216         if(NOT "${Rust_FIND_QUIETLY}")
       
   217             message(
       
   218                 WARNING "CMake variable `Rust_TOOLCHAIN` specified, but `rustup` was not found. "
       
   219                 "Ignoring toolchain and looking for a Rust toolchain not managed by rustup.")
       
   220         endif()
       
   221     endif()
       
   222 else()
       
   223     # If we aren't definitely using a rustup toolchain, look for rustc first - the user may have
       
   224     # a toolchain installed via a method other than rustup higher in the PATH, which should be
       
   225     # preferred. However, if the first-found rustc is a rustup proxy, then we'll revert to
       
   226     # finding the preferred toolchain via rustup.
       
   227 
       
   228     # Uses `Rust_COMPILER` to let user-specified `rustc` win. But we will still "override" the
       
   229     # user's setting if it is pointing to `rustup`. Default rustup install path is provided as a
       
   230     # backup if a toolchain cannot be found in the user's PATH.
       
   231 
       
   232     if (DEFINED Rust_COMPILER)
       
   233         set(_Rust_COMPILER_TEST "${Rust_COMPILER}")
       
   234         set(_USER_SPECIFIED_RUSTC ON)
       
   235         if(NOT (EXISTS "${_Rust_COMPILER_TEST}" AND NOT IS_DIRECTORY "${_Rust_COMPILER_TEST}"))
       
   236             set(_ERROR_MESSAGE "Rust_COMPILER was set to `${Rust_COMPILER}`, but this file does "
       
   237                 "not exist."
       
   238             )
       
   239             _findrust_failed(${_ERROR_MESSAGE})
       
   240             return()
       
   241         endif()
       
   242     else()
       
   243         find_program(_Rust_COMPILER_TEST rustc PATHS "$ENV{HOME}/.cargo/bin")
       
   244         if(NOT EXISTS "${_Rust_COMPILER_TEST}")
       
   245             set(_ERROR_MESSAGE "`rustc` not found in PATH or `$ENV{HOME}/.cargo/bin`.\n"
       
   246                     "Hint: Check if `rustc` is in PATH or manually specify the location "
       
   247                     "by setting `Rust_COMPILER` to the path to `rustc`.")
       
   248             _findrust_failed(${_ERROR_MESSAGE})
       
   249         endif()
       
   250     endif()
       
   251 
       
   252     # Check if the discovered rustc is actually a "rustup" proxy.
       
   253     execute_process(
       
   254         COMMAND
       
   255             ${CMAKE_COMMAND} -E env
       
   256                 RUSTUP_FORCE_ARG0=rustup
       
   257             "${_Rust_COMPILER_TEST}" --version
       
   258         OUTPUT_VARIABLE _RUSTC_VERSION_RAW
       
   259         ERROR_VARIABLE _RUSTC_VERSION_STDERR
       
   260         RESULT_VARIABLE _RUSTC_VERSION_RESULT
       
   261     )
       
   262 
       
   263     if(NOT (_RUSTC_VERSION_RESULT EQUAL "0"))
       
   264         _findrust_failed("`${_Rust_COMPILER_TEST} --version` failed with ${_RUSTC_VERSION_RESULT}\n"
       
   265             "rustc stderr:\n${_RUSTC_VERSION_STDERR}"
       
   266             )
       
   267     endif()
       
   268 
       
   269     if (_RUSTC_VERSION_RAW MATCHES "rustup [0-9\\.]+")
       
   270         if (_USER_SPECIFIED_RUSTC)
       
   271             message(
       
   272                 WARNING "User-specified Rust_COMPILER pointed to rustup's rustc proxy. Corrosion's "
       
   273                 "FindRust will always try to evaluate to an actual Rust toolchain, and so the "
       
   274                 "user-specified Rust_COMPILER will be discarded in favor of the default "
       
   275                 "rustup-managed toolchain."
       
   276             )
       
   277 
       
   278             unset(Rust_COMPILER)
       
   279             unset(Rust_COMPILER CACHE)
       
   280         endif()
       
   281 
       
   282         # Get `rustup` next to the `rustc` proxy
       
   283         get_filename_component(_RUST_PROXIES_PATH "${_Rust_COMPILER_TEST}" DIRECTORY)
       
   284         find_program(Rust_RUSTUP rustup HINTS "${_RUST_PROXIES_PATH}" NO_DEFAULT_PATH)
       
   285     endif()
       
   286 
       
   287     unset(_Rust_COMPILER_TEST CACHE)
       
   288 endif()
       
   289 
       
   290 # At this point, the only thing we should have evaluated is a path to `rustup` _if that's what the
       
   291 # best source for a Rust toolchain was determined to be_.
       
   292 if (NOT Rust_RUSTUP)
       
   293     set(Rust_RESOLVE_RUSTUP_TOOLCHAINS OFF CACHE BOOL ${_RESOLVE_RUSTUP_TOOLCHAINS_DESC} FORCE)
       
   294 endif()
       
   295 
       
   296 # List of user variables that will override any toolchain-provided setting
       
   297 set(_Rust_USER_VARS Rust_COMPILER Rust_CARGO Rust_CARGO_TARGET Rust_CARGO_HOST_TARGET)
       
   298 foreach(_VAR ${_Rust_USER_VARS})
       
   299     if (DEFINED "${_VAR}")
       
   300         set(${_VAR}_CACHED "${${_VAR}}" CACHE INTERNAL "Internal cache of ${_VAR}")
       
   301     else()
       
   302         unset(${_VAR}_CACHED CACHE)
       
   303     endif()
       
   304 endforeach()
       
   305 
       
   306 # Discover what toolchains are installed by rustup, if the discovered `rustc` is a proxy from
       
   307 # `rustup` and the user hasn't explicitly requested to override this behavior, then select either
       
   308 # the default toolchain, or the requested toolchain Rust_TOOLCHAIN
       
   309 if (Rust_RESOLVE_RUSTUP_TOOLCHAINS)
       
   310     execute_process(
       
   311         COMMAND
       
   312             "${Rust_RUSTUP}" toolchain list --verbose
       
   313         OUTPUT_VARIABLE _TOOLCHAINS_RAW
       
   314     )
       
   315 
       
   316     string(REPLACE "\n" ";" _TOOLCHAINS_RAW "${_TOOLCHAINS_RAW}")
       
   317     set(_DISCOVERED_TOOLCHAINS "")
       
   318     set(_DISCOVERED_TOOLCHAINS_RUSTC_PATH "")
       
   319     set(_DISCOVERED_TOOLCHAINS_CARGO_PATH "")
       
   320     set(_DISCOVERED_TOOLCHAINS_VERSION "")
       
   321 
       
   322     foreach(_TOOLCHAIN_RAW ${_TOOLCHAINS_RAW})
       
   323         if (_TOOLCHAIN_RAW MATCHES "([a-zA-Z0-9\\._\\-]+)[ \t\r\n]?(\\(default\\) \\(override\\)|\\(default\\)|\\(override\\))?[ \t\r\n]+(.+)")
       
   324             set(_TOOLCHAIN "${CMAKE_MATCH_1}")
       
   325             set(_TOOLCHAIN_TYPE "${CMAKE_MATCH_2}")
       
   326 
       
   327             set(_TOOLCHAIN_PATH "${CMAKE_MATCH_3}")
       
   328             set(_TOOLCHAIN_${_TOOLCHAIN}_PATH "${CMAKE_MATCH_3}")
       
   329 
       
   330             if (_TOOLCHAIN_TYPE MATCHES ".*\\(default\\).*")
       
   331                 set(_TOOLCHAIN_DEFAULT "${_TOOLCHAIN}")
       
   332             endif()
       
   333 
       
   334             if (_TOOLCHAIN_TYPE MATCHES ".*\\(override\\).*")
       
   335                 set(_TOOLCHAIN_OVERRIDE "${_TOOLCHAIN}")
       
   336             endif()
       
   337 
       
   338             execute_process(
       
   339                     COMMAND
       
   340                     "${_TOOLCHAIN_PATH}/bin/rustc" --version
       
   341                     OUTPUT_VARIABLE _TOOLCHAIN_RAW_VERSION
       
   342             )
       
   343             if (_TOOLCHAIN_RAW_VERSION MATCHES "rustc ([0-9]+)\\.([0-9]+)\\.([0-9]+)(-nightly)?")
       
   344                 list(APPEND _DISCOVERED_TOOLCHAINS "${_TOOLCHAIN}")
       
   345                 list(APPEND _DISCOVERED_TOOLCHAINS_RUSTC_PATH "${_TOOLCHAIN_PATH}/bin/rustc")
       
   346                 list(APPEND _DISCOVERED_TOOLCHAINS_VERSION "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}")
       
   347 
       
   348                 # We need this variable to determine the default toolchain, since `foreach(... IN ZIP_LISTS ...)`
       
   349                 # requires CMake 3.17. As a workaround we define this variable to lookup the version when iterating
       
   350                 # through the `_DISCOVERED_TOOLCHAINS` lists.
       
   351                 set(_TOOLCHAIN_${_TOOLCHAIN}_VERSION "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}")
       
   352                 if(CMAKE_MATCH_4)
       
   353                     set(_TOOLCHAIN_${_TOOLCHAIN}_IS_NIGHTLY "TRUE")
       
   354                 else()
       
   355                     set(_TOOLCHAIN_${_TOOLCHAIN}_IS_NIGHTLY "FALSE")
       
   356                 endif()
       
   357                 if(EXISTS "${_TOOLCHAIN_PATH}/bin/cargo")
       
   358                     list(APPEND _DISCOVERED_TOOLCHAINS_CARGO_PATH "${_TOOLCHAIN_PATH}/bin/cargo")
       
   359                 else()
       
   360                     list(APPEND _DISCOVERED_TOOLCHAINS_CARGO_PATH "NOTFOUND")
       
   361                 endif()
       
   362             else()
       
   363                 message(AUTHOR_WARNING "Unexpected output from `rustc --version` for Toolchain `${_TOOLCHAIN}`: "
       
   364                         "`${_TOOLCHAIN_RAW_VERSION}`.\n"
       
   365                         "Ignoring this toolchain."
       
   366                 )
       
   367             endif()
       
   368         else()
       
   369             message(AUTHOR_WARNING "Didn't recognize toolchain: ${_TOOLCHAIN_RAW}. Ignoring this toolchain.\n"
       
   370                 "Rustup toolchain list output( `${Rust_RUSTUP} toolchain list --verbose`):\n"
       
   371                 "${_TOOLCHAINS_RAW}"
       
   372             )
       
   373         endif()
       
   374     endforeach()
       
   375 
       
   376     # Expose a list of available rustup toolchains.
       
   377     list(LENGTH _DISCOVERED_TOOLCHAINS _toolchain_len)
       
   378     list(LENGTH _DISCOVERED_TOOLCHAINS_RUSTC_PATH _toolchain_rustc_len)
       
   379     list(LENGTH _DISCOVERED_TOOLCHAINS_CARGO_PATH _toolchain_cargo_len)
       
   380     list(LENGTH _DISCOVERED_TOOLCHAINS_VERSION _toolchain_version_len)
       
   381     if(NOT
       
   382         (_toolchain_len EQUAL _toolchain_rustc_len
       
   383             AND _toolchain_cargo_len EQUAL _toolchain_version_len
       
   384             AND _toolchain_len EQUAL _toolchain_cargo_len)
       
   385         )
       
   386         message(FATAL_ERROR "Internal error - list length mismatch."
       
   387             "List lengths: ${_toolchain_len} toolchains, ${_toolchain_rustc_len} rustc, ${_toolchain_cargo_len} cargo,"
       
   388             " ${_toolchain_version_len} version. The lengths should be the same."
       
   389         )
       
   390     endif()
       
   391 
       
   392     set(Rust_RUSTUP_TOOLCHAINS CACHE INTERNAL "List of available Rustup toolchains" "${_DISCOVERED_TOOLCHAINS}")
       
   393     set(Rust_RUSTUP_TOOLCHAINS_RUSTC_PATH
       
   394         CACHE INTERNAL
       
   395         "List of the rustc paths corresponding to the toolchain at the same index in `Rust_RUSTUP_TOOLCHAINS`."
       
   396         "${_DISCOVERED_TOOLCHAINS_RUSTC_PATH}"
       
   397     )
       
   398     set(Rust_RUSTUP_TOOLCHAINS_CARGO_PATH
       
   399         CACHE INTERNAL
       
   400         "List of the cargo paths corresponding to the toolchain at the same index in `Rust_RUSTUP_TOOLCHAINS`. \
       
   401         May also be `NOTFOUND` if the toolchain does not have a cargo executable."
       
   402         "${_DISCOVERED_TOOLCHAINS_CARGO_PATH}"
       
   403     )
       
   404     set(Rust_RUSTUP_TOOLCHAINS_VERSION
       
   405         CACHE INTERNAL
       
   406         "List of the rust toolchain version corresponding to the toolchain at the same index in \
       
   407         `Rust_RUSTUP_TOOLCHAINS`."
       
   408         "${_DISCOVERED_TOOLCHAINS_VERSION}"
       
   409     )
       
   410 
       
   411     # Rust_TOOLCHAIN is preferred over a requested version if it is set.
       
   412     if (NOT DEFINED Rust_TOOLCHAIN)
       
   413         if (NOT DEFINED _TOOLCHAIN_OVERRIDE)
       
   414             set(_TOOLCHAIN_SELECTED "${_TOOLCHAIN_DEFAULT}")
       
   415         else()
       
   416             set(_TOOLCHAIN_SELECTED "${_TOOLCHAIN_OVERRIDE}")
       
   417         endif()
       
   418         # Check default toolchain first.
       
   419         _findrust_version_ok("_TOOLCHAIN_${_TOOLCHAIN_SELECTED}_VERSION" _VERSION_OK)
       
   420         if(NOT "${_VERSION_OK}")
       
   421             foreach(_TOOLCHAIN "${_DISCOVERED_TOOLCHAINS}")
       
   422                 _findrust_version_ok("_TOOLCHAIN_${_TOOLCHAIN}_VERSION" _VERSION_OK)
       
   423                 if("${_VERSION_OK}")
       
   424                     set(_TOOLCHAIN_SELECTED "${_TOOLCHAIN}")
       
   425                     break()
       
   426                 endif()
       
   427             endforeach()
       
   428             # Check if we found a suitable version in the for loop.
       
   429             if(NOT "${_VERSION_OK}")
       
   430                 string(REPLACE ";" "\n" _DISCOVERED_TOOLCHAINS "${_DISCOVERED_TOOLCHAINS}")
       
   431                 _findrust_failed("Failed to find a Rust toolchain matching the version requirements of "
       
   432                         "${Rust_FIND_VERSION}. Available toolchains: ${_DISCOVERED_TOOLCHAINS}")
       
   433             endif()
       
   434         endif()
       
   435     endif()
       
   436 
       
   437     set(Rust_TOOLCHAIN "${_TOOLCHAIN_SELECTED}" CACHE STRING "The rustup toolchain to use")
       
   438     set_property(CACHE Rust_TOOLCHAIN PROPERTY STRINGS "${_DISCOVERED_TOOLCHAINS}")
       
   439 
       
   440     if(NOT Rust_FIND_QUIETLY)
       
   441         message(STATUS "Rust Toolchain: ${Rust_TOOLCHAIN}")
       
   442     endif()
       
   443 
       
   444     if (NOT Rust_TOOLCHAIN IN_LIST _DISCOVERED_TOOLCHAINS)
       
   445         # If the precise toolchain wasn't found, try appending the default host
       
   446         execute_process(
       
   447             COMMAND
       
   448                 "${Rust_RUSTUP}" show
       
   449             RESULT_VARIABLE _SHOW_RESULT
       
   450             OUTPUT_VARIABLE _SHOW_RAW
       
   451         )
       
   452         if(NOT "${_SHOW_RESULT}" EQUAL "0")
       
   453             _findrust_failed("Command `${Rust_RUSTUP} show` failed")
       
   454         endif()
       
   455 
       
   456         if (_SHOW_RAW MATCHES "Default host: ([a-zA-Z0-9_\\-]*)\n")
       
   457             set(_DEFAULT_HOST "${CMAKE_MATCH_1}")
       
   458         else()
       
   459             _findrust_failed("Failed to parse \"Default host\" from `${Rust_RUSTUP} show`. Got: ${_SHOW_RAW}")
       
   460         endif()
       
   461 
       
   462         if (NOT "${Rust_TOOLCHAIN}-${_DEFAULT_HOST}" IN_LIST _DISCOVERED_TOOLCHAINS)
       
   463             set(_NOT_FOUND_MESSAGE "Could not find toolchain '${Rust_TOOLCHAIN}'\n"
       
   464                 "Available toolchains:\n"
       
   465             )
       
   466             foreach(_TOOLCHAIN ${_DISCOVERED_TOOLCHAINS})
       
   467                 list(APPEND _NOT_FOUND_MESSAGE "  `${_TOOLCHAIN}`\n")
       
   468             endforeach()
       
   469             _findrust_failed(${_NOT_FOUND_MESSAGE})
       
   470         endif()
       
   471 
       
   472         set(_RUSTUP_TOOLCHAIN_FULL "${Rust_TOOLCHAIN}-${_DEFAULT_HOST}")
       
   473     else()
       
   474         set(_RUSTUP_TOOLCHAIN_FULL "${Rust_TOOLCHAIN}")
       
   475     endif()
       
   476 
       
   477     set(_RUST_TOOLCHAIN_PATH "${_TOOLCHAIN_${_RUSTUP_TOOLCHAIN_FULL}_PATH}")
       
   478     if(NOT "${Rust_FIND_QUIETLY}")
       
   479         message(VERBOSE "Rust toolchain ${_RUSTUP_TOOLCHAIN_FULL}")
       
   480         message(VERBOSE "Rust toolchain path ${_RUST_TOOLCHAIN_PATH}")
       
   481     endif()
       
   482 
       
   483     # Is overridden if the user specifies `Rust_COMPILER` explicitly.
       
   484     find_program(
       
   485         Rust_COMPILER_CACHED
       
   486         rustc
       
   487             HINTS "${_RUST_TOOLCHAIN_PATH}/bin"
       
   488             NO_DEFAULT_PATH)
       
   489 elseif (Rust_RUSTUP)
       
   490     get_filename_component(_RUST_TOOLCHAIN_PATH "${Rust_RUSTUP}" DIRECTORY)
       
   491     get_filename_component(_RUST_TOOLCHAIN_PATH "${_RUST_TOOLCHAIN_PATH}" DIRECTORY)
       
   492     find_program(
       
   493         Rust_COMPILER_CACHED
       
   494         rustc
       
   495             HINTS "${_RUST_TOOLCHAIN_PATH}/bin"
       
   496             NO_DEFAULT_PATH)
       
   497 else()
       
   498     find_program(Rust_COMPILER_CACHED rustc)
       
   499     if (EXISTS "${Rust_COMPILER_CACHED}")
       
   500         # rustc is expected to be at `<toolchain_path>/bin/rustc`.
       
   501         get_filename_component(_RUST_TOOLCHAIN_PATH "${Rust_COMPILER_CACHED}" DIRECTORY)
       
   502         get_filename_component(_RUST_TOOLCHAIN_PATH "${_RUST_TOOLCHAIN_PATH}" DIRECTORY)
       
   503     endif()
       
   504 endif()
       
   505 
       
   506 if (NOT EXISTS "${Rust_COMPILER_CACHED}")
       
   507     set(_NOT_FOUND_MESSAGE "The rustc executable was not found. "
       
   508         "Rust not installed or ~/.cargo/bin not added to path?\n"
       
   509         "Hint: Consider setting `Rust_COMPILER` to the absolute path of `rustc`."
       
   510     )
       
   511     _findrust_failed(${_NOT_FOUND_MESSAGE})
       
   512 endif()
       
   513 
       
   514 if (Rust_RESOLVE_RUSTUP_TOOLCHAINS)
       
   515     set(_NOT_FOUND_MESSAGE "Rust was detected to be managed by rustup, but failed to find `cargo` "
       
   516         "next to `rustc` in `${_RUST_TOOLCHAIN_PATH}/bin`. This can happen for custom toolchains, "
       
   517         "if cargo was not built. "
       
   518         "Please manually specify the path to a compatible `cargo` by setting `Rust_CARGO`."
       
   519     )
       
   520     find_program(
       
   521         Rust_CARGO_CACHED
       
   522         cargo
       
   523             HINTS "${_RUST_TOOLCHAIN_PATH}/bin"
       
   524             NO_DEFAULT_PATH
       
   525     )
       
   526     # note: maybe can use find_package_handle_standard_args here, if we remove the _CACHED postfix.
       
   527     # not sure why that is here...
       
   528     if(NOT EXISTS "${Rust_CARGO_CACHED}")
       
   529         _findrust_failed(${_NOT_FOUND_MESSAGE})
       
   530     endif()
       
   531     set(Rust_TOOLCHAIN_IS_RUSTUP_MANAGED TRUE CACHE INTERNAL "" FORCE)
       
   532 else()
       
   533     set(_NOT_FOUND_MESSAGE "Failed to find `cargo` in PATH and `${_RUST_TOOLCHAIN_PATH}/bin`.\n"
       
   534         "Please ensure cargo is in PATH or manually specify the path to a compatible `cargo` by "
       
   535         "setting `Rust_CARGO`."
       
   536     )
       
   537     # On some systems (e.g. NixOS) cargo is not managed by rustup and also not next to rustc.
       
   538     find_program(
       
   539             Rust_CARGO_CACHED
       
   540             cargo
       
   541                 HINTS "${_RUST_TOOLCHAIN_PATH}/bin"
       
   542     )
       
   543     # note: maybe can use find_package_handle_standard_args here, if we remove the _CACHED postfix.
       
   544     # not sure why that is here...
       
   545     if(NOT EXISTS "${Rust_CARGO_CACHED}")
       
   546         _findrust_failed(${_NOT_FOUND_MESSAGE})
       
   547     endif()
       
   548 endif()
       
   549 
       
   550 execute_process(
       
   551     COMMAND "${Rust_CARGO_CACHED}" --version --verbose
       
   552     OUTPUT_VARIABLE _CARGO_VERSION_RAW
       
   553     RESULT_VARIABLE _CARGO_VERSION_RESULT
       
   554 )
       
   555 # todo: check if cargo is a required component!
       
   556 if(NOT ( "${_CARGO_VERSION_RESULT}" EQUAL "0" ))
       
   557     _findrust_failed("Failed to get cargo version.\n"
       
   558         "`${Rust_CARGO_CACHED} --version` failed with error: `${_CARGO_VERSION_RESULT}"
       
   559 )
       
   560 endif()
       
   561 
       
   562 # todo: don't set cache variables here, but let find_package_handle_standard_args do the promotion
       
   563 # later.
       
   564 if (_CARGO_VERSION_RAW MATCHES "cargo ([0-9]+)\\.([0-9]+)\\.([0-9]+)")
       
   565     set(Rust_CARGO_VERSION_MAJOR "${CMAKE_MATCH_1}" CACHE INTERNAL "" FORCE)
       
   566     set(Rust_CARGO_VERSION_MINOR "${CMAKE_MATCH_2}" CACHE INTERNAL "" FORCE)
       
   567     set(Rust_CARGO_VERSION_PATCH "${CMAKE_MATCH_3}" CACHE INTERNAL "" FORCE)
       
   568     set(Rust_CARGO_VERSION "${Rust_CARGO_VERSION_MAJOR}.${Rust_CARGO_VERSION_MINOR}.${Rust_CARGO_VERSION_PATCH}" CACHE INTERNAL "" FORCE)
       
   569 # Workaround for the version strings where the `cargo ` prefix is missing.
       
   570 elseif(_CARGO_VERSION_RAW MATCHES "([0-9]+)\\.([0-9]+)\\.([0-9]+)")
       
   571     set(Rust_CARGO_VERSION_MAJOR "${CMAKE_MATCH_1}" CACHE INTERNAL "" FORCE)
       
   572     set(Rust_CARGO_VERSION_MINOR "${CMAKE_MATCH_2}" CACHE INTERNAL "" FORCE)
       
   573     set(Rust_CARGO_VERSION_PATCH "${CMAKE_MATCH_3}" CACHE INTERNAL "" FORCE)
       
   574     set(Rust_CARGO_VERSION "${Rust_CARGO_VERSION_MAJOR}.${Rust_CARGO_VERSION_MINOR}.${Rust_CARGO_VERSION_PATCH}" CACHE INTERNAL "" FORCE)
       
   575 else()
       
   576     _findrust_failed(
       
   577         "Failed to parse cargo version. `cargo --version` evaluated to (${_CARGO_VERSION_RAW}). "
       
   578         "Expected a <Major>.<Minor>.<Patch> version triple."
       
   579     )
       
   580 endif()
       
   581 
       
   582 execute_process(
       
   583     COMMAND "${Rust_COMPILER_CACHED}" --version --verbose
       
   584     OUTPUT_VARIABLE _RUSTC_VERSION_RAW
       
   585     RESULT_VARIABLE _RUSTC_VERSION_RESULT
       
   586 )
       
   587 
       
   588 if(NOT ( "${_RUSTC_VERSION_RESULT}" EQUAL "0" ))
       
   589     _findrust_failed("Failed to get rustc version.\n"
       
   590         "${Rust_COMPILER_CACHED} --version failed with error: `${_RUSTC_VERSION_RESULT}`")
       
   591 endif()
       
   592 
       
   593 if (_RUSTC_VERSION_RAW MATCHES "rustc ([0-9]+)\\.([0-9]+)\\.([0-9]+)(-nightly)?")
       
   594     set(Rust_VERSION_MAJOR "${CMAKE_MATCH_1}" CACHE INTERNAL "" FORCE)
       
   595     set(Rust_VERSION_MINOR "${CMAKE_MATCH_2}" CACHE INTERNAL "" FORCE)
       
   596     set(Rust_VERSION_PATCH "${CMAKE_MATCH_3}" CACHE INTERNAL "" FORCE)
       
   597     set(Rust_VERSION "${Rust_VERSION_MAJOR}.${Rust_VERSION_MINOR}.${Rust_VERSION_PATCH}" CACHE INTERNAL "" FORCE)
       
   598     if(CMAKE_MATCH_4)
       
   599         set(Rust_IS_NIGHTLY 1 CACHE INTERNAL "" FORCE)
       
   600     else()
       
   601         set(Rust_IS_NIGHTLY 0 CACHE INTERNAL "" FORCE)
       
   602     endif()
       
   603 else()
       
   604     _findrust_failed("Failed to parse rustc version. `${Rust_COMPILER_CACHED} --version --verbose` "
       
   605         "evaluated to:\n`${_RUSTC_VERSION_RAW}`"
       
   606     )
       
   607 endif()
       
   608 
       
   609 if (_RUSTC_VERSION_RAW MATCHES "host: ([a-zA-Z0-9_\\-]*)\n")
       
   610     set(Rust_DEFAULT_HOST_TARGET "${CMAKE_MATCH_1}")
       
   611     set(Rust_CARGO_HOST_TARGET_CACHED "${Rust_DEFAULT_HOST_TARGET}" CACHE STRING "Host triple")
       
   612 else()
       
   613     _findrust_failed(
       
   614         "Failed to parse rustc host target. `rustc --version --verbose` evaluated to:\n${_RUSTC_VERSION_RAW}"
       
   615     )
       
   616 endif()
       
   617 
       
   618 if (_RUSTC_VERSION_RAW MATCHES "LLVM version: ([0-9]+)\\.([0-9]+)(\\.([0-9]+))?")
       
   619     set(Rust_LLVM_VERSION_MAJOR "${CMAKE_MATCH_1}" CACHE INTERNAL "" FORCE)
       
   620     set(Rust_LLVM_VERSION_MINOR "${CMAKE_MATCH_2}" CACHE INTERNAL "" FORCE)
       
   621     # With the Rust toolchain 1.44.1 the reported LLVM version is 9.0, i.e. without a patch version.
       
   622     # Since cmake regex does not support non-capturing groups, just ignore Match 3.
       
   623     set(Rust_LLVM_VERSION_PATCH "${CMAKE_MATCH_4}" CACHE INTERNAL "" FORCE)
       
   624     set(Rust_LLVM_VERSION "${Rust_LLVM_VERSION_MAJOR}.${Rust_LLVM_VERSION_MINOR}.${Rust_LLVM_VERSION_PATCH}" CACHE INTERNAL "" FORCE)
       
   625 elseif(NOT Rust_FIND_QUIETLY)
       
   626     message(
       
   627             WARNING
       
   628             "Failed to parse rustc LLVM version. `rustc --version --verbose` evaluated to:\n${_RUSTC_VERSION_RAW}"
       
   629     )
       
   630 endif()
       
   631 
       
   632 if (NOT Rust_CARGO_TARGET_CACHED)
       
   633     unset(_CARGO_ARCH)
       
   634     unset(_CARGO_ABI)
       
   635     if (WIN32)
       
   636         if (CMAKE_VS_PLATFORM_NAME)
       
   637             string(TOLOWER "${CMAKE_VS_PLATFORM_NAME}" LOWER_VS_PLATFORM_NAME)
       
   638             if ("${LOWER_VS_PLATFORM_NAME}" STREQUAL "win32")
       
   639                 set(_CARGO_ARCH i686)
       
   640             elseif("${LOWER_VS_PLATFORM_NAME}" STREQUAL "x64")
       
   641                 set(_CARGO_ARCH x86_64)
       
   642             elseif("${LOWER_VS_PLATFORM_NAME}" STREQUAL "arm64")
       
   643                 set(_CARGO_ARCH aarch64)
       
   644             else()
       
   645                 message(WARNING "VS Platform '${CMAKE_VS_PLATFORM_NAME}' not recognized")
       
   646             endif()
       
   647         endif()
       
   648         # Fallback path
       
   649         if(NOT DEFINED _CARGO_ARCH)
       
   650             # Possible values for windows when not cross-compiling taken from here:
       
   651             # https://learn.microsoft.com/en-us/windows/win32/winprog64/wow64-implementation-details
       
   652             # When cross-compiling the user is expected to supply the value, so we match more variants.
       
   653             if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(AMD64|amd64|x86_64)$")
       
   654                 set(_CARGO_ARCH x86_64)
       
   655             elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(ARM64|arm64|aarch64)$")
       
   656                 set(_CARGO_ARCH aarch64)
       
   657             elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(X86|x86|i686)$")
       
   658                 set(_CARGO_ARCH i686)
       
   659             elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "i586")
       
   660                 set(_CARGO_ARCH i586)
       
   661             elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "IA64")
       
   662                 message(FATAL_ERROR "No rust target for Intel Itanium.")
       
   663             elseif(NOT "${CMAKE_SYSTEM_PROCESSOR}")
       
   664                 message(WARNING "Failed to detect target architecture. Please set `CMAKE_SYSTEM_PROCESSOR`"
       
   665                     " to your target architecture or set `Rust_CARGO_TARGET` to your cargo target triple."
       
   666                 )
       
   667             else()
       
   668                 message(WARNING "Failed to detect target architecture. Please set "
       
   669                     "`Rust_CARGO_TARGET` to your cargo target triple."
       
   670                 )
       
   671             endif()
       
   672         endif()
       
   673 
       
   674         set(_CARGO_VENDOR "pc-windows")
       
   675 
       
   676         # The MSVC Generators will always target the msvc ABI.
       
   677         # For other generators we check the compiler ID and compiler target (if present)
       
   678         # If no compiler is set and we are not cross-compiling then we just choose the
       
   679         # default rust host target.
       
   680         if(DEFINED MSVC
       
   681             OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC"
       
   682             OR "${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC"
       
   683             OR "${CMAKE_CXX_COMPILER_TARGET}" MATCHES "-msvc$"
       
   684             OR "${CMAKE_C_COMPILER_TARGET}" MATCHES "-msvc$"
       
   685         )
       
   686             set(_CARGO_ABI msvc)
       
   687         elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU"
       
   688             OR "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU"
       
   689             OR "${CMAKE_CXX_COMPILER_TARGET}" MATCHES "-gnu$"
       
   690             OR "${CMAKE_C_COMPILER_TARGET}" MATCHES "-gnu$"
       
   691             OR (NOT CMAKE_CROSSCOMPILING AND "${Rust_DEFAULT_HOST_TARGET}" MATCHES "-gnu$")
       
   692             )
       
   693             set(_CARGO_ABI gnu)
       
   694         elseif(NOT "${CMAKE_CROSSCOMPILING}" AND "${Rust_DEFAULT_HOST_TARGET}" MATCHES "-msvc$")
       
   695             # We first check if the gnu branch matches to ensure this fallback is only used
       
   696             # if no compiler is enabled.
       
   697             set(_CARGO_ABI msvc)
       
   698         else()
       
   699             message(WARNING "Could not determine the target ABI. Please specify `Rust_CARGO_TARGET` manually.")
       
   700         endif()
       
   701 
       
   702         if(DEFINED _CARGO_ARCH AND DEFINED _CARGO_VENDOR AND DEFINED _CARGO_ABI)
       
   703             set(Rust_CARGO_TARGET_CACHED "${_CARGO_ARCH}-${_CARGO_VENDOR}-${_CARGO_ABI}"
       
   704                 CACHE STRING "Target triple")
       
   705         endif()
       
   706     elseif (ANDROID)
       
   707         if (CMAKE_ANDROID_ARCH_ABI STREQUAL armeabi-v7a)
       
   708             if (CMAKE_ANDROID_ARM_MODE)
       
   709                 set(_Rust_ANDROID_TARGET armv7-linux-androideabi)
       
   710             else ()
       
   711                 set(_Rust_ANDROID_TARGET thumbv7neon-linux-androideabi)
       
   712             endif()
       
   713         elseif (CMAKE_ANDROID_ARCH_ABI STREQUAL arm64-v8a)
       
   714             set(_Rust_ANDROID_TARGET aarch64-linux-android)
       
   715         elseif (CMAKE_ANDROID_ARCH_ABI STREQUAL x86)
       
   716             set(_Rust_ANDROID_TARGET i686-linux-android)
       
   717         elseif (CMAKE_ANDROID_ARCH_ABI STREQUAL x86_64)
       
   718             set(_Rust_ANDROID_TARGET x86_64-linux-android)
       
   719         endif()
       
   720 
       
   721         if (_Rust_ANDROID_TARGET)
       
   722             set(Rust_CARGO_TARGET_CACHED "${_Rust_ANDROID_TARGET}" CACHE STRING "Target triple")
       
   723         endif()
       
   724     elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "OHOS")
       
   725         if(CMAKE_OHOS_ARCH_ABI STREQUAL arm64-v8a)
       
   726             set(_RUST_OHOS_TARGET aarch64-unknown-linux-ohos)
       
   727         elseif(CMAKE_OHOS_ARCH_ABI STREQUAL armeabi-v7a)
       
   728             set(_RUST_OHOS_TARGET armv7-unknown-linux-ohos)
       
   729         elseif(CMAKE_OHOS_ARCH_ABI STREQUAL x86_64)
       
   730             set(_RUST_OHOS_TARGET x86_64-unknown-linux-ohos)
       
   731         else()
       
   732             message(WARNING "unrecognized OHOS architecture: ${OHOS_ARCH}")
       
   733         endif()
       
   734         if(_RUST_OHOS_TARGET)
       
   735             set(Rust_CARGO_TARGET_CACHED "${_RUST_OHOS_TARGET}" CACHE STRING "Target triple")
       
   736         endif()
       
   737     endif()
       
   738     # Fallback to the default host target
       
   739     if(NOT Rust_CARGO_TARGET_CACHED)
       
   740         if(CMAKE_CROSSCOMPILING)
       
   741             message(WARNING "CMake is in cross-compiling mode, but the cargo target-triple could not be inferred."
       
   742                 "Falling back to the default host target. Please consider manually setting `Rust_CARGO_TARGET`."
       
   743             )
       
   744         endif()
       
   745         set(Rust_CARGO_TARGET_CACHED "${Rust_DEFAULT_HOST_TARGET}" CACHE STRING "Target triple")
       
   746     endif()
       
   747 
       
   748     message(STATUS "Rust Target: ${Rust_CARGO_TARGET_CACHED}")
       
   749 endif()
       
   750 
       
   751 if(Rust_CARGO_TARGET_CACHED STREQUAL Rust_DEFAULT_HOST_TARGET)
       
   752     set(Rust_CROSSCOMPILING FALSE CACHE INTERNAL "Rust is configured for cross-compiling")
       
   753 else()
       
   754     set(Rust_CROSSCOMPILING TRUE  CACHE INTERNAL "Rust is configured for cross-compiling")
       
   755 endif()
       
   756 
       
   757 _corrosion_parse_target_triple("${Rust_CARGO_TARGET_CACHED}" rust_arch rust_vendor rust_os rust_env)
       
   758 _corrosion_parse_target_triple("${Rust_CARGO_HOST_TARGET_CACHED}" rust_host_arch rust_host_vendor rust_host_os rust_host_env)
       
   759 
       
   760 set(Rust_CARGO_TARGET_ARCH "${rust_arch}" CACHE INTERNAL "Target architecture")
       
   761 set(Rust_CARGO_TARGET_VENDOR "${rust_vendor}" CACHE INTERNAL "Target vendor")
       
   762 set(Rust_CARGO_TARGET_OS "${rust_os}" CACHE INTERNAL "Target Operating System")
       
   763 set(Rust_CARGO_TARGET_ENV "${rust_env}" CACHE INTERNAL "Target environment")
       
   764 
       
   765 set(Rust_CARGO_HOST_ARCH "${rust_host_arch}" CACHE INTERNAL "Host architecture")
       
   766 set(Rust_CARGO_HOST_VENDOR "${rust_host_vendor}" CACHE INTERNAL "Host vendor")
       
   767 set(Rust_CARGO_HOST_OS "${rust_host_os}" CACHE INTERNAL "Host Operating System")
       
   768 set(Rust_CARGO_HOST_ENV "${rust_host_env}" CACHE INTERNAL "Host environment")
       
   769 
       
   770 if(NOT DEFINED CACHE{Rust_CARGO_TARGET_LINK_NATIVE_LIBS})
       
   771     message(STATUS "Determining required link libraries for target ${Rust_CARGO_TARGET_CACHED}")
       
   772     unset(required_native_libs)
       
   773     _corrosion_determine_libs_new("${Rust_CARGO_TARGET_CACHED}" required_native_libs required_link_flags)
       
   774     if(DEFINED required_native_libs)
       
   775         message(STATUS "Required static libs for target ${Rust_CARGO_TARGET_CACHED}: ${required_native_libs}" )
       
   776     endif()
       
   777     if(DEFINED required_link_flags)
       
   778         message(STATUS "Required link flags for target ${Rust_CARGO_TARGET_CACHED}: ${required_link_flags}" )
       
   779     endif()
       
   780     # In very recent corrosion versions it is possible to override the rust compiler version
       
   781     # per target, so to be totally correct we would need to determine the libraries for
       
   782     # every installed Rust version, that the user could choose from.
       
   783     # In practice there aren't likely going to be any major differences, so we just do it once
       
   784     # for the target and once for the host target (if cross-compiling).
       
   785     set(Rust_CARGO_TARGET_LINK_NATIVE_LIBS "${required_native_libs}" CACHE INTERNAL
       
   786             "Required native libraries when linking Rust static libraries")
       
   787     set(Rust_CARGO_TARGET_LINK_OPTIONS "${required_link_flags}" CACHE INTERNAL
       
   788             "Required link flags when linking Rust static libraries")
       
   789 endif()
       
   790 
       
   791 if(Rust_CROSSCOMPILING AND NOT DEFINED CACHE{Rust_CARGO_HOST_TARGET_LINK_NATIVE_LIBS})
       
   792     message(STATUS "Determining required link libraries for target ${Rust_CARGO_HOST_TARGET_CACHED}")
       
   793     unset(host_libs)
       
   794     _corrosion_determine_libs_new("${Rust_CARGO_HOST_TARGET_CACHED}" host_libs host_flags)
       
   795     if(DEFINED host_libs)
       
   796         message(STATUS "Required static libs for host target ${Rust_CARGO_HOST_TARGET_CACHED}: ${host_libs}" )
       
   797     endif()
       
   798     set(Rust_CARGO_HOST_TARGET_LINK_NATIVE_LIBS "${host_libs}" CACHE INTERNAL
       
   799         "Required native libraries when linking Rust static libraries for the host target")
       
   800     set(Rust_CARGO_HOST_TARGET_LINK_OPTIONS "${host_flags}" CACHE INTERNAL
       
   801         "Required linker flags when linking Rust static libraries for the host target")
       
   802 endif()
       
   803 
       
   804 # Set the input variables as non-cache variables so that the variables are available after
       
   805 # `find_package`, even if the values were evaluated to defaults.
       
   806 foreach(_VAR ${_Rust_USER_VARS})
       
   807     set(${_VAR} "${${_VAR}_CACHED}")
       
   808     # Ensure cached variables have type INTERNAL
       
   809     set(${_VAR}_CACHED "${${_VAR}_CACHED}" CACHE INTERNAL "Internal cache of ${_VAR}")
       
   810 endforeach()
       
   811 
       
   812 find_package_handle_standard_args(
       
   813     Rust
       
   814     REQUIRED_VARS Rust_COMPILER Rust_VERSION Rust_CARGO Rust_CARGO_VERSION Rust_CARGO_TARGET Rust_CARGO_HOST_TARGET
       
   815     VERSION_VAR Rust_VERSION
       
   816 )
       
   817 
       
   818 
       
   819 if(NOT TARGET Rust::Rustc)
       
   820     add_executable(Rust::Rustc IMPORTED GLOBAL)
       
   821     set_property(
       
   822         TARGET Rust::Rustc
       
   823         PROPERTY IMPORTED_LOCATION "${Rust_COMPILER_CACHED}"
       
   824     )
       
   825 
       
   826     add_executable(Rust::Cargo IMPORTED GLOBAL)
       
   827     set_property(
       
   828         TARGET Rust::Cargo
       
   829         PROPERTY IMPORTED_LOCATION "${Rust_CARGO_CACHED}"
       
   830     )
       
   831     set(Rust_FOUND true)
       
   832 endif()
       
   833 
       
   834 list(POP_BACK CMAKE_MESSAGE_CONTEXT)