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