tools/corrosion/cmake/FindRust.cmake
branchtransitional_engine
changeset 16038 d903f8d2395a
parent 16021 6a3dc15b78b9
equal deleted inserted replaced
16036:7b8d96fc8799 16038:d903f8d2395a
    10 
    10 
    11 #]=======================================================================]
    11 #]=======================================================================]
    12 
    12 
    13 cmake_minimum_required(VERSION 3.12)
    13 cmake_minimum_required(VERSION 3.12)
    14 
    14 
       
    15 option(
       
    16         Rust_RUSTUP_INSTALL_MISSING_TARGET
       
    17         "Use Rustup to automatically install missing targets instead of giving up"
       
    18         OFF
       
    19 )
       
    20 
    15 # search for Cargo here and set up a bunch of cool flags and stuff
    21 # search for Cargo here and set up a bunch of cool flags and stuff
    16 include(FindPackageHandleStandardArgs)
    22 include(FindPackageHandleStandardArgs)
    17 
    23 
    18 list(APPEND CMAKE_MESSAGE_CONTEXT "FindRust")
    24 list(APPEND CMAKE_MESSAGE_CONTEXT "FindRust")
    19 
    25 
    20 # Print error message and return.
    26 # Print error message and return. Should not be used from inside functions
    21 macro(_findrust_failed)
    27 macro(_findrust_failed)
    22     if("${Rust_FIND_REQUIRED}")
    28     if("${Rust_FIND_REQUIRED}")
    23         message(FATAL_ERROR ${ARGN})
    29         message(FATAL_ERROR ${ARGN})
    24     elseif(NOT "${Rust_FIND_QUIETLY}")
    30     elseif(NOT "${Rust_FIND_QUIETLY}")
    25         message(WARNING ${ARGN})
    31         message(WARNING ${ARGN})
    26     endif()
    32     endif()
    27     # Note: PARENT_SCOPE is the scope of the caller of the caller of this macro.
    33     set(Rust_FOUND "")
    28     set(Rust_FOUND "" PARENT_SCOPE)
       
    29     return()
    34     return()
    30 endmacro()
    35 endmacro()
    31 
    36 
    32 # Checks if the actual version of a Rust toolchain matches the VERSION requirements specified in find_package.
    37 # 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)
    38 function(_findrust_version_ok ACTUAL_VERSION OUT_IS_OK)
   177                     continue()
   182                     continue()
   178                 endif()
   183                 endif()
   179                 
   184                 
   180                 # Flags start with / for MSVC
   185                 # Flags start with / for MSVC
   181                 if (lib MATCHES "^/" AND ${target_triple} MATCHES "msvc$")
   186                 if (lib MATCHES "^/" AND ${target_triple} MATCHES "msvc$")
   182                     list(APPEND flag_list "${lib}")
   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()
   183                 else()
   194                 else()
   184                     # Strip leading `-l` (unix) and potential .lib suffix (windows)
   195                     # Strip leading `-l` (unix) and potential .lib suffix (windows)
   185                     string(REGEX REPLACE "^-l" "" "stripped_lib" "${lib}")
   196                     string(REGEX REPLACE "^-l" "" "stripped_lib" "${lib}")
   186                     string(REGEX REPLACE "\.lib$" "" "stripped_lib" "${stripped_lib}")
   197                     string(REGEX REPLACE "\.lib$" "" "stripped_lib" "${stripped_lib}")
   187                     list(APPEND stripped_lib_list "${stripped_lib}")
   198                     list(APPEND stripped_lib_list "${stripped_lib}")
   188                 endif()
   199                 endif()
   189             endforeach()
   200             endforeach()
   190             set(libs_list "${stripped_lib_list}")
   201             set(libs_list "${stripped_lib_list}")
   191             # Special case `msvcrt` to link with the debug version in Debug mode.
   202             # We leave it up to the C/C++ executable that links in the Rust static-library
   192             list(TRANSFORM libs_list REPLACE "^msvcrt$" "\$<\$<CONFIG:Debug>:msvcrtd>")
   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?")
   193         else()
   206         else()
   194             message(DEBUG "Determining required native libraries - failed: Regex match failure.")
   207             message(DEBUG "Determining required native libraries - failed: Regex match failure.")
   195             message(DEBUG "`native-static-libs` not found in: `${cargo_build_error_message}`")
   208             message(DEBUG "`native-static-libs` not found in: `${cargo_build_error_message}`")
   196             return()
   209             return()
   197         endif()
   210         endif()
   240             return()
   253             return()
   241         endif()
   254         endif()
   242     else()
   255     else()
   243         find_program(_Rust_COMPILER_TEST rustc PATHS "$ENV{HOME}/.cargo/bin")
   256         find_program(_Rust_COMPILER_TEST rustc PATHS "$ENV{HOME}/.cargo/bin")
   244         if(NOT EXISTS "${_Rust_COMPILER_TEST}")
   257         if(NOT EXISTS "${_Rust_COMPILER_TEST}")
   245             set(_ERROR_MESSAGE "`rustc` not found in PATH or `$ENV{HOME}/.cargo/bin`.\n"
   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"
   246                     "Hint: Check if `rustc` is in PATH or manually specify the location "
   260                     "Hint: Check if `rustc` is in PATH or manually specify the location "
   247                     "by setting `Rust_COMPILER` to the path to `rustc`.")
   261                     "by setting `Rust_COMPILER` to the path to `rustc`.")
   248             _findrust_failed(${_ERROR_MESSAGE})
   262             _findrust_failed(${_ERROR_MESSAGE})
   249         endif()
   263         endif()
   250     endif()
   264     endif()
   387             "List lengths: ${_toolchain_len} toolchains, ${_toolchain_rustc_len} rustc, ${_toolchain_cargo_len} cargo,"
   401             "List lengths: ${_toolchain_len} toolchains, ${_toolchain_rustc_len} rustc, ${_toolchain_cargo_len} cargo,"
   388             " ${_toolchain_version_len} version. The lengths should be the same."
   402             " ${_toolchain_version_len} version. The lengths should be the same."
   389         )
   403         )
   390     endif()
   404     endif()
   391 
   405 
   392     set(Rust_RUSTUP_TOOLCHAINS CACHE INTERNAL "List of available Rustup toolchains" "${_DISCOVERED_TOOLCHAINS}")
   406     set(Rust_RUSTUP_TOOLCHAINS "${_DISCOVERED_TOOLCHAINS}" CACHE INTERNAL "List of available Rustup toolchains")
   393     set(Rust_RUSTUP_TOOLCHAINS_RUSTC_PATH
   407     set(Rust_RUSTUP_TOOLCHAINS_RUSTC_PATH "${_DISCOVERED_TOOLCHAINS_RUSTC_PATH}"
   394         CACHE INTERNAL
   408         CACHE INTERNAL
   395         "List of the rustc paths corresponding to the toolchain at the same index in `Rust_RUSTUP_TOOLCHAINS`."
   409         "List of the rustc paths corresponding to the toolchain at the same index in `Rust_RUSTUP_TOOLCHAINS`."
   396         "${_DISCOVERED_TOOLCHAINS_RUSTC_PATH}"
   410     )
   397     )
   411     set(Rust_RUSTUP_TOOLCHAINS_CARGO_PATH "${_DISCOVERED_TOOLCHAINS_CARGO_PATH}"
   398     set(Rust_RUSTUP_TOOLCHAINS_CARGO_PATH
       
   399         CACHE INTERNAL
   412         CACHE INTERNAL
   400         "List of the cargo paths corresponding to the toolchain at the same index in `Rust_RUSTUP_TOOLCHAINS`. \
   413         "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."
   414         May also be `NOTFOUND` if the toolchain does not have a cargo executable."
   402         "${_DISCOVERED_TOOLCHAINS_CARGO_PATH}"
   415     )
   403     )
   416     set(Rust_RUSTUP_TOOLCHAINS_VERSION "${_DISCOVERED_TOOLCHAINS_VERSION}"
   404     set(Rust_RUSTUP_TOOLCHAINS_VERSION
       
   405         CACHE INTERNAL
   417         CACHE INTERNAL
   406         "List of the rust toolchain version corresponding to the toolchain at the same index in \
   418         "List of the rust toolchain version corresponding to the toolchain at the same index in \
   407         `Rust_RUSTUP_TOOLCHAINS`."
   419         `Rust_RUSTUP_TOOLCHAINS`."
   408         "${_DISCOVERED_TOOLCHAINS_VERSION}"
       
   409     )
   420     )
   410 
   421 
   411     # Rust_TOOLCHAIN is preferred over a requested version if it is set.
   422     # Rust_TOOLCHAIN is preferred over a requested version if it is set.
   412     if (NOT DEFINED Rust_TOOLCHAIN)
   423     if (NOT DEFINED Rust_TOOLCHAIN)
   413         if (NOT DEFINED _TOOLCHAIN_OVERRIDE)
   424         if (NOT DEFINED _TOOLCHAIN_OVERRIDE)
   484     find_program(
   495     find_program(
   485         Rust_COMPILER_CACHED
   496         Rust_COMPILER_CACHED
   486         rustc
   497         rustc
   487             HINTS "${_RUST_TOOLCHAIN_PATH}/bin"
   498             HINTS "${_RUST_TOOLCHAIN_PATH}/bin"
   488             NO_DEFAULT_PATH)
   499             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()
   500 else()
   498     find_program(Rust_COMPILER_CACHED rustc)
   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}")
   499     if (EXISTS "${Rust_COMPILER_CACHED}")
   509     if (EXISTS "${Rust_COMPILER_CACHED}")
   500         # rustc is expected to be at `<toolchain_path>/bin/rustc`.
   510         # rustc is expected to be at `<toolchain_path>/bin/rustc`.
   501         get_filename_component(_RUST_TOOLCHAIN_PATH "${Rust_COMPILER_CACHED}" DIRECTORY)
   511         get_filename_component(_RUST_TOOLCHAIN_PATH "${Rust_COMPILER_CACHED}" DIRECTORY)
   502         get_filename_component(_RUST_TOOLCHAIN_PATH "${_RUST_TOOLCHAIN_PATH}" DIRECTORY)
   512         get_filename_component(_RUST_TOOLCHAIN_PATH "${_RUST_TOOLCHAIN_PATH}" DIRECTORY)
   503     endif()
   513     endif()
   684             OR "${CMAKE_C_COMPILER_TARGET}" MATCHES "-msvc$"
   694             OR "${CMAKE_C_COMPILER_TARGET}" MATCHES "-msvc$"
   685         )
   695         )
   686             set(_CARGO_ABI msvc)
   696             set(_CARGO_ABI msvc)
   687         elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU"
   697         elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU"
   688             OR "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU"
   698             OR "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU"
   689             OR "${CMAKE_CXX_COMPILER_TARGET}" MATCHES "-gnu$"
   699             OR (NOT CMAKE_CROSSCOMPILING
   690             OR "${CMAKE_C_COMPILER_TARGET}" MATCHES "-gnu$"
   700                AND NOT DEFINED CMAKE_CXX_COMPILER_ID
   691             OR (NOT CMAKE_CROSSCOMPILING AND "${Rust_DEFAULT_HOST_TARGET}" MATCHES "-gnu$")
   701                AND NOT DEFINED CMAKE_C_COMPILER_ID
       
   702                AND "${Rust_DEFAULT_HOST_TARGET}" MATCHES "-gnu$"
   692             )
   703             )
       
   704         )
   693             set(_CARGO_ABI gnu)
   705             set(_CARGO_ABI gnu)
       
   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()
   694         elseif(NOT "${CMAKE_CROSSCOMPILING}" AND "${Rust_DEFAULT_HOST_TARGET}" MATCHES "-msvc$")
   720         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
   721             # We first check if the gnu branches match to ensure this fallback is only used
   696             # if no compiler is enabled.
   722             # if no compiler is enabled.
   697             set(_CARGO_ABI msvc)
   723             set(_CARGO_ABI msvc)
   698         else()
   724         else()
   699             message(WARNING "Could not determine the target ABI. Please specify `Rust_CARGO_TARGET` manually.")
   725             message(WARNING "Could not determine the target ABI. Please specify `Rust_CARGO_TARGET` manually.")
   700         endif()
   726         endif()
   746     endif()
   772     endif()
   747 
   773 
   748     message(STATUS "Rust Target: ${Rust_CARGO_TARGET_CACHED}")
   774     message(STATUS "Rust Target: ${Rust_CARGO_TARGET_CACHED}")
   749 endif()
   775 endif()
   750 
   776 
       
   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 
   751 if(Rust_CARGO_TARGET_CACHED STREQUAL Rust_DEFAULT_HOST_TARGET)
   817 if(Rust_CARGO_TARGET_CACHED STREQUAL Rust_DEFAULT_HOST_TARGET)
   752     set(Rust_CROSSCOMPILING FALSE CACHE INTERNAL "Rust is configured for cross-compiling")
   818     set(Rust_CROSSCOMPILING FALSE CACHE INTERNAL "Rust is configured for cross-compiling")
   753 else()
   819 else()
   754     set(Rust_CROSSCOMPILING TRUE  CACHE INTERNAL "Rust is configured for cross-compiling")
   820     set(Rust_CROSSCOMPILING TRUE  CACHE INTERNAL "Rust is configured for cross-compiling")
   755 endif()
   821 endif()