|
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) |