162306a36Sopenharmony_ci#!/bin/sh 262306a36Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0 362306a36Sopenharmony_ci# 462306a36Sopenharmony_ci# Tests whether a suitable Rust toolchain is available. 562306a36Sopenharmony_ci 662306a36Sopenharmony_ciset -e 762306a36Sopenharmony_ci 862306a36Sopenharmony_cimin_tool_version=$(dirname $0)/min-tool-version.sh 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci# Convert the version string x.y.z to a canonical up-to-7-digits form. 1162306a36Sopenharmony_ci# 1262306a36Sopenharmony_ci# Note that this function uses one more digit (compared to other 1362306a36Sopenharmony_ci# instances in other version scripts) to give a bit more space to 1462306a36Sopenharmony_ci# `rustc` since it will reach 1.100.0 in late 2026. 1562306a36Sopenharmony_ciget_canonical_version() 1662306a36Sopenharmony_ci{ 1762306a36Sopenharmony_ci IFS=. 1862306a36Sopenharmony_ci set -- $1 1962306a36Sopenharmony_ci echo $((100000 * $1 + 100 * $2 + $3)) 2062306a36Sopenharmony_ci} 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci# Print a reference to the Quick Start guide in the documentation. 2362306a36Sopenharmony_ciprint_docs_reference() 2462306a36Sopenharmony_ci{ 2562306a36Sopenharmony_ci echo >&2 "***" 2662306a36Sopenharmony_ci echo >&2 "*** Please see Documentation/rust/quick-start.rst for details" 2762306a36Sopenharmony_ci echo >&2 "*** on how to set up the Rust support." 2862306a36Sopenharmony_ci echo >&2 "***" 2962306a36Sopenharmony_ci} 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci# Print an explanation about the fact that the script is meant to be called from Kbuild. 3262306a36Sopenharmony_ciprint_kbuild_explanation() 3362306a36Sopenharmony_ci{ 3462306a36Sopenharmony_ci echo >&2 "***" 3562306a36Sopenharmony_ci echo >&2 "*** This script is intended to be called from Kbuild." 3662306a36Sopenharmony_ci echo >&2 "*** Please use the 'rustavailable' target to call it instead." 3762306a36Sopenharmony_ci echo >&2 "*** Otherwise, the results may not be meaningful." 3862306a36Sopenharmony_ci exit 1 3962306a36Sopenharmony_ci} 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci# If the script fails for any reason, or if there was any warning, then 4262306a36Sopenharmony_ci# print a reference to the documentation on exit. 4362306a36Sopenharmony_ciwarning=0 4462306a36Sopenharmony_citrap 'if [ $? -ne 0 ] || [ $warning -ne 0 ]; then print_docs_reference; fi' EXIT 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci# Check that the expected environment variables are set. 4762306a36Sopenharmony_ciif [ -z "${RUSTC+x}" ]; then 4862306a36Sopenharmony_ci echo >&2 "***" 4962306a36Sopenharmony_ci echo >&2 "*** Environment variable 'RUSTC' is not set." 5062306a36Sopenharmony_ci print_kbuild_explanation 5162306a36Sopenharmony_cifi 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ciif [ -z "${BINDGEN+x}" ]; then 5462306a36Sopenharmony_ci echo >&2 "***" 5562306a36Sopenharmony_ci echo >&2 "*** Environment variable 'BINDGEN' is not set." 5662306a36Sopenharmony_ci print_kbuild_explanation 5762306a36Sopenharmony_cifi 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ciif [ -z "${CC+x}" ]; then 6062306a36Sopenharmony_ci echo >&2 "***" 6162306a36Sopenharmony_ci echo >&2 "*** Environment variable 'CC' is not set." 6262306a36Sopenharmony_ci print_kbuild_explanation 6362306a36Sopenharmony_cifi 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci# Check that the Rust compiler exists. 6662306a36Sopenharmony_ciif ! command -v "$RUSTC" >/dev/null; then 6762306a36Sopenharmony_ci echo >&2 "***" 6862306a36Sopenharmony_ci echo >&2 "*** Rust compiler '$RUSTC' could not be found." 6962306a36Sopenharmony_ci echo >&2 "***" 7062306a36Sopenharmony_ci exit 1 7162306a36Sopenharmony_cifi 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci# Check that the Rust bindings generator exists. 7462306a36Sopenharmony_ciif ! command -v "$BINDGEN" >/dev/null; then 7562306a36Sopenharmony_ci echo >&2 "***" 7662306a36Sopenharmony_ci echo >&2 "*** Rust bindings generator '$BINDGEN' could not be found." 7762306a36Sopenharmony_ci echo >&2 "***" 7862306a36Sopenharmony_ci exit 1 7962306a36Sopenharmony_cifi 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci# Check that the Rust compiler version is suitable. 8262306a36Sopenharmony_ci# 8362306a36Sopenharmony_ci# Non-stable and distributions' versions may have a version suffix, e.g. `-dev`. 8462306a36Sopenharmony_cirust_compiler_output=$( \ 8562306a36Sopenharmony_ci LC_ALL=C "$RUSTC" --version 2>/dev/null 8662306a36Sopenharmony_ci) || rust_compiler_code=$? 8762306a36Sopenharmony_ciif [ -n "$rust_compiler_code" ]; then 8862306a36Sopenharmony_ci echo >&2 "***" 8962306a36Sopenharmony_ci echo >&2 "*** Running '$RUSTC' to check the Rust compiler version failed with" 9062306a36Sopenharmony_ci echo >&2 "*** code $rust_compiler_code. See output and docs below for details:" 9162306a36Sopenharmony_ci echo >&2 "***" 9262306a36Sopenharmony_ci echo >&2 "$rust_compiler_output" 9362306a36Sopenharmony_ci echo >&2 "***" 9462306a36Sopenharmony_ci exit 1 9562306a36Sopenharmony_cifi 9662306a36Sopenharmony_cirust_compiler_version=$( \ 9762306a36Sopenharmony_ci echo "$rust_compiler_output" \ 9862306a36Sopenharmony_ci | sed -nE '1s:.*rustc ([0-9]+\.[0-9]+\.[0-9]+).*:\1:p' 9962306a36Sopenharmony_ci) 10062306a36Sopenharmony_ciif [ -z "$rust_compiler_version" ]; then 10162306a36Sopenharmony_ci echo >&2 "***" 10262306a36Sopenharmony_ci echo >&2 "*** Running '$RUSTC' to check the Rust compiler version did not return" 10362306a36Sopenharmony_ci echo >&2 "*** an expected output. See output and docs below for details:" 10462306a36Sopenharmony_ci echo >&2 "***" 10562306a36Sopenharmony_ci echo >&2 "$rust_compiler_output" 10662306a36Sopenharmony_ci echo >&2 "***" 10762306a36Sopenharmony_ci exit 1 10862306a36Sopenharmony_cifi 10962306a36Sopenharmony_cirust_compiler_min_version=$($min_tool_version rustc) 11062306a36Sopenharmony_cirust_compiler_cversion=$(get_canonical_version $rust_compiler_version) 11162306a36Sopenharmony_cirust_compiler_min_cversion=$(get_canonical_version $rust_compiler_min_version) 11262306a36Sopenharmony_ciif [ "$rust_compiler_cversion" -lt "$rust_compiler_min_cversion" ]; then 11362306a36Sopenharmony_ci echo >&2 "***" 11462306a36Sopenharmony_ci echo >&2 "*** Rust compiler '$RUSTC' is too old." 11562306a36Sopenharmony_ci echo >&2 "*** Your version: $rust_compiler_version" 11662306a36Sopenharmony_ci echo >&2 "*** Minimum version: $rust_compiler_min_version" 11762306a36Sopenharmony_ci echo >&2 "***" 11862306a36Sopenharmony_ci exit 1 11962306a36Sopenharmony_cifi 12062306a36Sopenharmony_ciif [ "$rust_compiler_cversion" -gt "$rust_compiler_min_cversion" ]; then 12162306a36Sopenharmony_ci echo >&2 "***" 12262306a36Sopenharmony_ci echo >&2 "*** Rust compiler '$RUSTC' is too new. This may or may not work." 12362306a36Sopenharmony_ci echo >&2 "*** Your version: $rust_compiler_version" 12462306a36Sopenharmony_ci echo >&2 "*** Expected version: $rust_compiler_min_version" 12562306a36Sopenharmony_ci echo >&2 "***" 12662306a36Sopenharmony_ci warning=1 12762306a36Sopenharmony_cifi 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci# Check that the Rust bindings generator is suitable. 13062306a36Sopenharmony_ci# 13162306a36Sopenharmony_ci# Non-stable and distributions' versions may have a version suffix, e.g. `-dev`. 13262306a36Sopenharmony_cirust_bindings_generator_output=$( \ 13362306a36Sopenharmony_ci LC_ALL=C "$BINDGEN" --version 2>/dev/null 13462306a36Sopenharmony_ci) || rust_bindings_generator_code=$? 13562306a36Sopenharmony_ciif [ -n "$rust_bindings_generator_code" ]; then 13662306a36Sopenharmony_ci echo >&2 "***" 13762306a36Sopenharmony_ci echo >&2 "*** Running '$BINDGEN' to check the Rust bindings generator version failed with" 13862306a36Sopenharmony_ci echo >&2 "*** code $rust_bindings_generator_code. See output and docs below for details:" 13962306a36Sopenharmony_ci echo >&2 "***" 14062306a36Sopenharmony_ci echo >&2 "$rust_bindings_generator_output" 14162306a36Sopenharmony_ci echo >&2 "***" 14262306a36Sopenharmony_ci exit 1 14362306a36Sopenharmony_cifi 14462306a36Sopenharmony_cirust_bindings_generator_version=$( \ 14562306a36Sopenharmony_ci echo "$rust_bindings_generator_output" \ 14662306a36Sopenharmony_ci | sed -nE '1s:.*bindgen ([0-9]+\.[0-9]+\.[0-9]+).*:\1:p' 14762306a36Sopenharmony_ci) 14862306a36Sopenharmony_ciif [ -z "$rust_bindings_generator_version" ]; then 14962306a36Sopenharmony_ci echo >&2 "***" 15062306a36Sopenharmony_ci echo >&2 "*** Running '$BINDGEN' to check the bindings generator version did not return" 15162306a36Sopenharmony_ci echo >&2 "*** an expected output. See output and docs below for details:" 15262306a36Sopenharmony_ci echo >&2 "***" 15362306a36Sopenharmony_ci echo >&2 "$rust_bindings_generator_output" 15462306a36Sopenharmony_ci echo >&2 "***" 15562306a36Sopenharmony_ci exit 1 15662306a36Sopenharmony_cifi 15762306a36Sopenharmony_cirust_bindings_generator_min_version=$($min_tool_version bindgen) 15862306a36Sopenharmony_cirust_bindings_generator_cversion=$(get_canonical_version $rust_bindings_generator_version) 15962306a36Sopenharmony_cirust_bindings_generator_min_cversion=$(get_canonical_version $rust_bindings_generator_min_version) 16062306a36Sopenharmony_ciif [ "$rust_bindings_generator_cversion" -lt "$rust_bindings_generator_min_cversion" ]; then 16162306a36Sopenharmony_ci echo >&2 "***" 16262306a36Sopenharmony_ci echo >&2 "*** Rust bindings generator '$BINDGEN' is too old." 16362306a36Sopenharmony_ci echo >&2 "*** Your version: $rust_bindings_generator_version" 16462306a36Sopenharmony_ci echo >&2 "*** Minimum version: $rust_bindings_generator_min_version" 16562306a36Sopenharmony_ci echo >&2 "***" 16662306a36Sopenharmony_ci exit 1 16762306a36Sopenharmony_cifi 16862306a36Sopenharmony_ciif [ "$rust_bindings_generator_cversion" -gt "$rust_bindings_generator_min_cversion" ]; then 16962306a36Sopenharmony_ci echo >&2 "***" 17062306a36Sopenharmony_ci echo >&2 "*** Rust bindings generator '$BINDGEN' is too new. This may or may not work." 17162306a36Sopenharmony_ci echo >&2 "*** Your version: $rust_bindings_generator_version" 17262306a36Sopenharmony_ci echo >&2 "*** Expected version: $rust_bindings_generator_min_version" 17362306a36Sopenharmony_ci echo >&2 "***" 17462306a36Sopenharmony_ci warning=1 17562306a36Sopenharmony_cifi 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci# Check that the `libclang` used by the Rust bindings generator is suitable. 17862306a36Sopenharmony_ci# 17962306a36Sopenharmony_ci# In order to do that, first invoke `bindgen` to get the `libclang` version 18062306a36Sopenharmony_ci# found by `bindgen`. This step may already fail if, for instance, `libclang` 18162306a36Sopenharmony_ci# is not found, thus inform the user in such a case. 18262306a36Sopenharmony_cibindgen_libclang_output=$( \ 18362306a36Sopenharmony_ci LC_ALL=C "$BINDGEN" $(dirname $0)/rust_is_available_bindgen_libclang.h 2>&1 >/dev/null 18462306a36Sopenharmony_ci) || bindgen_libclang_code=$? 18562306a36Sopenharmony_ciif [ -n "$bindgen_libclang_code" ]; then 18662306a36Sopenharmony_ci echo >&2 "***" 18762306a36Sopenharmony_ci echo >&2 "*** Running '$BINDGEN' to check the libclang version (used by the Rust" 18862306a36Sopenharmony_ci echo >&2 "*** bindings generator) failed with code $bindgen_libclang_code. This may be caused by" 18962306a36Sopenharmony_ci echo >&2 "*** a failure to locate libclang. See output and docs below for details:" 19062306a36Sopenharmony_ci echo >&2 "***" 19162306a36Sopenharmony_ci echo >&2 "$bindgen_libclang_output" 19262306a36Sopenharmony_ci echo >&2 "***" 19362306a36Sopenharmony_ci exit 1 19462306a36Sopenharmony_cifi 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci# `bindgen` returned successfully, thus use the output to check that the version 19762306a36Sopenharmony_ci# of the `libclang` found by the Rust bindings generator is suitable. 19862306a36Sopenharmony_ci# 19962306a36Sopenharmony_ci# Unlike other version checks, note that this one does not necessarily appear 20062306a36Sopenharmony_ci# in the first line of the output, thus no `sed` address is provided. 20162306a36Sopenharmony_cibindgen_libclang_version=$( \ 20262306a36Sopenharmony_ci echo "$bindgen_libclang_output" \ 20362306a36Sopenharmony_ci | sed -nE 's:.*clang version ([0-9]+\.[0-9]+\.[0-9]+).*:\1:p' 20462306a36Sopenharmony_ci) 20562306a36Sopenharmony_ciif [ -z "$bindgen_libclang_version" ]; then 20662306a36Sopenharmony_ci echo >&2 "***" 20762306a36Sopenharmony_ci echo >&2 "*** Running '$BINDGEN' to check the libclang version (used by the Rust" 20862306a36Sopenharmony_ci echo >&2 "*** bindings generator) did not return an expected output. See output" 20962306a36Sopenharmony_ci echo >&2 "*** and docs below for details:" 21062306a36Sopenharmony_ci echo >&2 "***" 21162306a36Sopenharmony_ci echo >&2 "$bindgen_libclang_output" 21262306a36Sopenharmony_ci echo >&2 "***" 21362306a36Sopenharmony_ci exit 1 21462306a36Sopenharmony_cifi 21562306a36Sopenharmony_cibindgen_libclang_min_version=$($min_tool_version llvm) 21662306a36Sopenharmony_cibindgen_libclang_cversion=$(get_canonical_version $bindgen_libclang_version) 21762306a36Sopenharmony_cibindgen_libclang_min_cversion=$(get_canonical_version $bindgen_libclang_min_version) 21862306a36Sopenharmony_ciif [ "$bindgen_libclang_cversion" -lt "$bindgen_libclang_min_cversion" ]; then 21962306a36Sopenharmony_ci echo >&2 "***" 22062306a36Sopenharmony_ci echo >&2 "*** libclang (used by the Rust bindings generator '$BINDGEN') is too old." 22162306a36Sopenharmony_ci echo >&2 "*** Your version: $bindgen_libclang_version" 22262306a36Sopenharmony_ci echo >&2 "*** Minimum version: $bindgen_libclang_min_version" 22362306a36Sopenharmony_ci echo >&2 "***" 22462306a36Sopenharmony_ci exit 1 22562306a36Sopenharmony_cifi 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci# If the C compiler is Clang, then we can also check whether its version 22862306a36Sopenharmony_ci# matches the `libclang` version used by the Rust bindings generator. 22962306a36Sopenharmony_ci# 23062306a36Sopenharmony_ci# In the future, we might be able to perform a full version check, see 23162306a36Sopenharmony_ci# https://github.com/rust-lang/rust-bindgen/issues/2138. 23262306a36Sopenharmony_cicc_name=$($(dirname $0)/cc-version.sh $CC | cut -f1 -d' ') 23362306a36Sopenharmony_ciif [ "$cc_name" = Clang ]; then 23462306a36Sopenharmony_ci clang_version=$( \ 23562306a36Sopenharmony_ci LC_ALL=C $CC --version 2>/dev/null \ 23662306a36Sopenharmony_ci | sed -nE '1s:.*version ([0-9]+\.[0-9]+\.[0-9]+).*:\1:p' 23762306a36Sopenharmony_ci ) 23862306a36Sopenharmony_ci if [ "$clang_version" != "$bindgen_libclang_version" ]; then 23962306a36Sopenharmony_ci echo >&2 "***" 24062306a36Sopenharmony_ci echo >&2 "*** libclang (used by the Rust bindings generator '$BINDGEN')" 24162306a36Sopenharmony_ci echo >&2 "*** version does not match Clang's. This may be a problem." 24262306a36Sopenharmony_ci echo >&2 "*** libclang version: $bindgen_libclang_version" 24362306a36Sopenharmony_ci echo >&2 "*** Clang version: $clang_version" 24462306a36Sopenharmony_ci echo >&2 "***" 24562306a36Sopenharmony_ci warning=1 24662306a36Sopenharmony_ci fi 24762306a36Sopenharmony_cifi 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci# Check that the source code for the `core` standard library exists. 25062306a36Sopenharmony_ci# 25162306a36Sopenharmony_ci# `$KRUSTFLAGS` is passed in case the user added `--sysroot`. 25262306a36Sopenharmony_cirustc_sysroot=$("$RUSTC" $KRUSTFLAGS --print sysroot) 25362306a36Sopenharmony_cirustc_src=${RUST_LIB_SRC:-"$rustc_sysroot/lib/rustlib/src/rust/library"} 25462306a36Sopenharmony_cirustc_src_core="$rustc_src/core/src/lib.rs" 25562306a36Sopenharmony_ciif [ ! -e "$rustc_src_core" ]; then 25662306a36Sopenharmony_ci echo >&2 "***" 25762306a36Sopenharmony_ci echo >&2 "*** Source code for the 'core' standard library could not be found" 25862306a36Sopenharmony_ci echo >&2 "*** at '$rustc_src_core'." 25962306a36Sopenharmony_ci echo >&2 "***" 26062306a36Sopenharmony_ci exit 1 26162306a36Sopenharmony_cifi 262