178521f33SMiguel Ojeda#!/bin/sh 278521f33SMiguel Ojeda# SPDX-License-Identifier: GPL-2.0 378521f33SMiguel Ojeda# 478521f33SMiguel Ojeda# Tests whether a suitable Rust toolchain is available. 578521f33SMiguel Ojeda 678521f33SMiguel Ojedaset -e 778521f33SMiguel Ojeda 878521f33SMiguel Ojedamin_tool_version=$(dirname $0)/min-tool-version.sh 978521f33SMiguel Ojeda 1078521f33SMiguel Ojeda# Convert the version string x.y.z to a canonical up-to-7-digits form. 1178521f33SMiguel Ojeda# 1278521f33SMiguel Ojeda# Note that this function uses one more digit (compared to other 1378521f33SMiguel Ojeda# instances in other version scripts) to give a bit more space to 1478521f33SMiguel Ojeda# `rustc` since it will reach 1.100.0 in late 2026. 1578521f33SMiguel Ojedaget_canonical_version() 1678521f33SMiguel Ojeda{ 1778521f33SMiguel Ojeda IFS=. 1878521f33SMiguel Ojeda set -- $1 1978521f33SMiguel Ojeda echo $((100000 * $1 + 100 * $2 + $3)) 2078521f33SMiguel Ojeda} 2178521f33SMiguel Ojeda 22aac284b1SMiguel Ojeda# Print a reference to the Quick Start guide in the documentation. 23aac284b1SMiguel Ojedaprint_docs_reference() 24aac284b1SMiguel Ojeda{ 25aac284b1SMiguel Ojeda echo >&2 "***" 26aac284b1SMiguel Ojeda echo >&2 "*** Please see Documentation/rust/quick-start.rst for details" 27aac284b1SMiguel Ojeda echo >&2 "*** on how to set up the Rust support." 28aac284b1SMiguel Ojeda echo >&2 "***" 29aac284b1SMiguel Ojeda} 30aac284b1SMiguel Ojeda 31e90db552SMiguel Ojeda# Print an explanation about the fact that the script is meant to be called from Kbuild. 32e90db552SMiguel Ojedaprint_kbuild_explanation() 33e90db552SMiguel Ojeda{ 34e90db552SMiguel Ojeda echo >&2 "***" 35e90db552SMiguel Ojeda echo >&2 "*** This script is intended to be called from Kbuild." 36e90db552SMiguel Ojeda echo >&2 "*** Please use the 'rustavailable' target to call it instead." 37e90db552SMiguel Ojeda echo >&2 "*** Otherwise, the results may not be meaningful." 38e90db552SMiguel Ojeda exit 1 39e90db552SMiguel Ojeda} 40e90db552SMiguel Ojeda 41aac284b1SMiguel Ojeda# If the script fails for any reason, or if there was any warning, then 42aac284b1SMiguel Ojeda# print a reference to the documentation on exit. 43aac284b1SMiguel Ojedawarning=0 44aac284b1SMiguel Ojedatrap 'if [ $? -ne 0 ] || [ $warning -ne 0 ]; then print_docs_reference; fi' EXIT 45aac284b1SMiguel Ojeda 46e90db552SMiguel Ojeda# Check that the expected environment variables are set. 47e90db552SMiguel Ojedaif [ -z "${RUSTC+x}" ]; then 48e90db552SMiguel Ojeda echo >&2 "***" 49e90db552SMiguel Ojeda echo >&2 "*** Environment variable 'RUSTC' is not set." 50e90db552SMiguel Ojeda print_kbuild_explanation 51e90db552SMiguel Ojedafi 52e90db552SMiguel Ojeda 53e90db552SMiguel Ojedaif [ -z "${BINDGEN+x}" ]; then 54e90db552SMiguel Ojeda echo >&2 "***" 55e90db552SMiguel Ojeda echo >&2 "*** Environment variable 'BINDGEN' is not set." 56e90db552SMiguel Ojeda print_kbuild_explanation 57e90db552SMiguel Ojedafi 58e90db552SMiguel Ojeda 59e90db552SMiguel Ojedaif [ -z "${CC+x}" ]; then 60e90db552SMiguel Ojeda echo >&2 "***" 61e90db552SMiguel Ojeda echo >&2 "*** Environment variable 'CC' is not set." 62e90db552SMiguel Ojeda print_kbuild_explanation 63e90db552SMiguel Ojedafi 64e90db552SMiguel Ojeda 6578521f33SMiguel Ojeda# Check that the Rust compiler exists. 6678521f33SMiguel Ojedaif ! command -v "$RUSTC" >/dev/null; then 6778521f33SMiguel Ojeda echo >&2 "***" 6878521f33SMiguel Ojeda echo >&2 "*** Rust compiler '$RUSTC' could not be found." 6978521f33SMiguel Ojeda echo >&2 "***" 7078521f33SMiguel Ojeda exit 1 7178521f33SMiguel Ojedafi 7278521f33SMiguel Ojeda 7378521f33SMiguel Ojeda# Check that the Rust bindings generator exists. 7478521f33SMiguel Ojedaif ! command -v "$BINDGEN" >/dev/null; then 7578521f33SMiguel Ojeda echo >&2 "***" 7678521f33SMiguel Ojeda echo >&2 "*** Rust bindings generator '$BINDGEN' could not be found." 7778521f33SMiguel Ojeda echo >&2 "***" 7878521f33SMiguel Ojeda exit 1 7978521f33SMiguel Ojedafi 8078521f33SMiguel Ojeda 8178521f33SMiguel Ojeda# Check that the Rust compiler version is suitable. 8278521f33SMiguel Ojeda# 8378521f33SMiguel Ojeda# Non-stable and distributions' versions may have a version suffix, e.g. `-dev`. 84f2955228SMiguel Ojedarust_compiler_output=$( \ 85f2955228SMiguel Ojeda LC_ALL=C "$RUSTC" --version 2>/dev/null 86f2955228SMiguel Ojeda) || rust_compiler_code=$? 87f2955228SMiguel Ojedaif [ -n "$rust_compiler_code" ]; then 88f2955228SMiguel Ojeda echo >&2 "***" 89f2955228SMiguel Ojeda echo >&2 "*** Running '$RUSTC' to check the Rust compiler version failed with" 90f2955228SMiguel Ojeda echo >&2 "*** code $rust_compiler_code. See output and docs below for details:" 91f2955228SMiguel Ojeda echo >&2 "***" 92f2955228SMiguel Ojeda echo >&2 "$rust_compiler_output" 93f2955228SMiguel Ojeda echo >&2 "***" 94f2955228SMiguel Ojeda exit 1 95f2955228SMiguel Ojedafi 9678521f33SMiguel Ojedarust_compiler_version=$( \ 97f2955228SMiguel Ojeda echo "$rust_compiler_output" \ 987cd6a3e1SMiguel Ojeda | sed -nE '1s:.*rustc ([0-9]+\.[0-9]+\.[0-9]+).*:\1:p' 9978521f33SMiguel Ojeda) 100bc60c930SMiguel Ojedaif [ -z "$rust_compiler_version" ]; then 101bc60c930SMiguel Ojeda echo >&2 "***" 102bc60c930SMiguel Ojeda echo >&2 "*** Running '$RUSTC' to check the Rust compiler version did not return" 103bc60c930SMiguel Ojeda echo >&2 "*** an expected output. See output and docs below for details:" 104bc60c930SMiguel Ojeda echo >&2 "***" 105bc60c930SMiguel Ojeda echo >&2 "$rust_compiler_output" 106bc60c930SMiguel Ojeda echo >&2 "***" 107bc60c930SMiguel Ojeda exit 1 108bc60c930SMiguel Ojedafi 10978521f33SMiguel Ojedarust_compiler_min_version=$($min_tool_version rustc) 11078521f33SMiguel Ojedarust_compiler_cversion=$(get_canonical_version $rust_compiler_version) 11178521f33SMiguel Ojedarust_compiler_min_cversion=$(get_canonical_version $rust_compiler_min_version) 11278521f33SMiguel Ojedaif [ "$rust_compiler_cversion" -lt "$rust_compiler_min_cversion" ]; then 11378521f33SMiguel Ojeda echo >&2 "***" 11478521f33SMiguel Ojeda echo >&2 "*** Rust compiler '$RUSTC' is too old." 11578521f33SMiguel Ojeda echo >&2 "*** Your version: $rust_compiler_version" 11678521f33SMiguel Ojeda echo >&2 "*** Minimum version: $rust_compiler_min_version" 11778521f33SMiguel Ojeda echo >&2 "***" 11878521f33SMiguel Ojeda exit 1 11978521f33SMiguel Ojedafi 12078521f33SMiguel Ojeda 12178521f33SMiguel Ojeda# Check that the Rust bindings generator is suitable. 12278521f33SMiguel Ojeda# 12378521f33SMiguel Ojeda# Non-stable and distributions' versions may have a version suffix, e.g. `-dev`. 1249e98db17SMiguel Ojeda# 1259e98db17SMiguel Ojeda# The dummy parameter `workaround-for-0.69.0` is required to support 0.69.0 126*c23d1f7eSMiguel Ojeda# (https://github.com/rust-lang/rust-bindgen/pull/2678) and 0.71.0 127*c23d1f7eSMiguel Ojeda# (https://github.com/rust-lang/rust-bindgen/pull/3040). It can be removed when 128*c23d1f7eSMiguel Ojeda# the minimum version is upgraded past the latter (0.69.1 and 0.71.1 both fixed 129*c23d1f7eSMiguel Ojeda# the issue). 130f2955228SMiguel Ojedarust_bindings_generator_output=$( \ 1319e98db17SMiguel Ojeda LC_ALL=C "$BINDGEN" --version workaround-for-0.69.0 2>/dev/null 132f2955228SMiguel Ojeda) || rust_bindings_generator_code=$? 133f2955228SMiguel Ojedaif [ -n "$rust_bindings_generator_code" ]; then 134f2955228SMiguel Ojeda echo >&2 "***" 135f2955228SMiguel Ojeda echo >&2 "*** Running '$BINDGEN' to check the Rust bindings generator version failed with" 136f2955228SMiguel Ojeda echo >&2 "*** code $rust_bindings_generator_code. See output and docs below for details:" 137f2955228SMiguel Ojeda echo >&2 "***" 138f2955228SMiguel Ojeda echo >&2 "$rust_bindings_generator_output" 139f2955228SMiguel Ojeda echo >&2 "***" 140f2955228SMiguel Ojeda exit 1 141f2955228SMiguel Ojedafi 14278521f33SMiguel Ojedarust_bindings_generator_version=$( \ 143f2955228SMiguel Ojeda echo "$rust_bindings_generator_output" \ 1447cd6a3e1SMiguel Ojeda | sed -nE '1s:.*bindgen ([0-9]+\.[0-9]+\.[0-9]+).*:\1:p' 14578521f33SMiguel Ojeda) 146bc60c930SMiguel Ojedaif [ -z "$rust_bindings_generator_version" ]; then 147bc60c930SMiguel Ojeda echo >&2 "***" 148bc60c930SMiguel Ojeda echo >&2 "*** Running '$BINDGEN' to check the bindings generator version did not return" 149bc60c930SMiguel Ojeda echo >&2 "*** an expected output. See output and docs below for details:" 150bc60c930SMiguel Ojeda echo >&2 "***" 151bc60c930SMiguel Ojeda echo >&2 "$rust_bindings_generator_output" 152bc60c930SMiguel Ojeda echo >&2 "***" 153bc60c930SMiguel Ojeda exit 1 154bc60c930SMiguel Ojedafi 15578521f33SMiguel Ojedarust_bindings_generator_min_version=$($min_tool_version bindgen) 15678521f33SMiguel Ojedarust_bindings_generator_cversion=$(get_canonical_version $rust_bindings_generator_version) 15778521f33SMiguel Ojedarust_bindings_generator_min_cversion=$(get_canonical_version $rust_bindings_generator_min_version) 15878521f33SMiguel Ojedaif [ "$rust_bindings_generator_cversion" -lt "$rust_bindings_generator_min_cversion" ]; then 15978521f33SMiguel Ojeda echo >&2 "***" 16078521f33SMiguel Ojeda echo >&2 "*** Rust bindings generator '$BINDGEN' is too old." 16178521f33SMiguel Ojeda echo >&2 "*** Your version: $rust_bindings_generator_version" 16278521f33SMiguel Ojeda echo >&2 "*** Minimum version: $rust_bindings_generator_min_version" 16378521f33SMiguel Ojeda echo >&2 "***" 16478521f33SMiguel Ojeda exit 1 16578521f33SMiguel Ojedafi 166981ad93cSMiguel Ojedaif [ "$rust_bindings_generator_cversion" -eq 6600 ] || 167981ad93cSMiguel Ojeda [ "$rust_bindings_generator_cversion" -eq 6601 ]; then 168981ad93cSMiguel Ojeda # Distributions may have patched the issue (e.g. Debian did). 169981ad93cSMiguel Ojeda if ! "$BINDGEN" $(dirname $0)/rust_is_available_bindgen_0_66.h >/dev/null; then 170981ad93cSMiguel Ojeda echo >&2 "***" 171981ad93cSMiguel Ojeda echo >&2 "*** Rust bindings generator '$BINDGEN' versions 0.66.0 and 0.66.1 may not" 172981ad93cSMiguel Ojeda echo >&2 "*** work due to a bug (https://github.com/rust-lang/rust-bindgen/pull/2567)," 173981ad93cSMiguel Ojeda echo >&2 "*** unless patched (like Debian's)." 174981ad93cSMiguel Ojeda echo >&2 "*** Your version: $rust_bindings_generator_version" 175981ad93cSMiguel Ojeda echo >&2 "***" 176981ad93cSMiguel Ojeda warning=1 177981ad93cSMiguel Ojeda fi 178981ad93cSMiguel Ojedafi 17978521f33SMiguel Ojeda 18078521f33SMiguel Ojeda# Check that the `libclang` used by the Rust bindings generator is suitable. 18152cae7f2SMiguel Ojeda# 18252cae7f2SMiguel Ojeda# In order to do that, first invoke `bindgen` to get the `libclang` version 18352cae7f2SMiguel Ojeda# found by `bindgen`. This step may already fail if, for instance, `libclang` 18452cae7f2SMiguel Ojeda# is not found, thus inform the user in such a case. 18552cae7f2SMiguel Ojedabindgen_libclang_output=$( \ 18652cae7f2SMiguel Ojeda LC_ALL=C "$BINDGEN" $(dirname $0)/rust_is_available_bindgen_libclang.h 2>&1 >/dev/null 18752cae7f2SMiguel Ojeda) || bindgen_libclang_code=$? 18852cae7f2SMiguel Ojedaif [ -n "$bindgen_libclang_code" ]; then 18952cae7f2SMiguel Ojeda echo >&2 "***" 19052cae7f2SMiguel Ojeda echo >&2 "*** Running '$BINDGEN' to check the libclang version (used by the Rust" 19152cae7f2SMiguel Ojeda echo >&2 "*** bindings generator) failed with code $bindgen_libclang_code. This may be caused by" 19252cae7f2SMiguel Ojeda echo >&2 "*** a failure to locate libclang. See output and docs below for details:" 19352cae7f2SMiguel Ojeda echo >&2 "***" 19452cae7f2SMiguel Ojeda echo >&2 "$bindgen_libclang_output" 19552cae7f2SMiguel Ojeda echo >&2 "***" 19652cae7f2SMiguel Ojeda exit 1 19752cae7f2SMiguel Ojedafi 19852cae7f2SMiguel Ojeda 19952cae7f2SMiguel Ojeda# `bindgen` returned successfully, thus use the output to check that the version 20052cae7f2SMiguel Ojeda# of the `libclang` found by the Rust bindings generator is suitable. 2017cd6a3e1SMiguel Ojeda# 2027cd6a3e1SMiguel Ojeda# Unlike other version checks, note that this one does not necessarily appear 2037cd6a3e1SMiguel Ojeda# in the first line of the output, thus no `sed` address is provided. 20478521f33SMiguel Ojedabindgen_libclang_version=$( \ 20552cae7f2SMiguel Ojeda echo "$bindgen_libclang_output" \ 2069eb7e20eSMiguel Ojeda | sed -nE 's:.*clang version ([0-9]+\.[0-9]+\.[0-9]+).*:\1:p' 20778521f33SMiguel Ojeda) 208bc60c930SMiguel Ojedaif [ -z "$bindgen_libclang_version" ]; then 209bc60c930SMiguel Ojeda echo >&2 "***" 210bc60c930SMiguel Ojeda echo >&2 "*** Running '$BINDGEN' to check the libclang version (used by the Rust" 211bc60c930SMiguel Ojeda echo >&2 "*** bindings generator) did not return an expected output. See output" 212bc60c930SMiguel Ojeda echo >&2 "*** and docs below for details:" 213bc60c930SMiguel Ojeda echo >&2 "***" 214bc60c930SMiguel Ojeda echo >&2 "$bindgen_libclang_output" 215bc60c930SMiguel Ojeda echo >&2 "***" 216bc60c930SMiguel Ojeda exit 1 217bc60c930SMiguel Ojedafi 21878521f33SMiguel Ojedabindgen_libclang_min_version=$($min_tool_version llvm) 21978521f33SMiguel Ojedabindgen_libclang_cversion=$(get_canonical_version $bindgen_libclang_version) 22078521f33SMiguel Ojedabindgen_libclang_min_cversion=$(get_canonical_version $bindgen_libclang_min_version) 22178521f33SMiguel Ojedaif [ "$bindgen_libclang_cversion" -lt "$bindgen_libclang_min_cversion" ]; then 22278521f33SMiguel Ojeda echo >&2 "***" 22378521f33SMiguel Ojeda echo >&2 "*** libclang (used by the Rust bindings generator '$BINDGEN') is too old." 22478521f33SMiguel Ojeda echo >&2 "*** Your version: $bindgen_libclang_version" 22578521f33SMiguel Ojeda echo >&2 "*** Minimum version: $bindgen_libclang_min_version" 22678521f33SMiguel Ojeda echo >&2 "***" 22778521f33SMiguel Ojeda exit 1 22878521f33SMiguel Ojedafi 22978521f33SMiguel Ojeda 230b2603f8aSMiguel Ojedaif [ "$bindgen_libclang_cversion" -ge 1900100 ] && 231b2603f8aSMiguel Ojeda [ "$rust_bindings_generator_cversion" -lt 6905 ]; then 232b2603f8aSMiguel Ojeda # Distributions may have patched the issue (e.g. Debian did). 233b2603f8aSMiguel Ojeda if ! "$BINDGEN" $(dirname $0)/rust_is_available_bindgen_libclang_concat.h | grep -q foofoo; then 234b2603f8aSMiguel Ojeda echo >&2 "***" 235b2603f8aSMiguel Ojeda echo >&2 "*** Rust bindings generator '$BINDGEN' < 0.69.5 together with libclang >= 19.1" 236b2603f8aSMiguel Ojeda echo >&2 "*** may not work due to a bug (https://github.com/rust-lang/rust-bindgen/pull/2824)," 237b2603f8aSMiguel Ojeda echo >&2 "*** unless patched (like Debian's)." 238b2603f8aSMiguel Ojeda echo >&2 "*** Your bindgen version: $rust_bindings_generator_version" 239b2603f8aSMiguel Ojeda echo >&2 "*** Your libclang version: $bindgen_libclang_version" 240b2603f8aSMiguel Ojeda echo >&2 "***" 241b2603f8aSMiguel Ojeda warning=1 242b2603f8aSMiguel Ojeda fi 243b2603f8aSMiguel Ojedafi 244b2603f8aSMiguel Ojeda 24578521f33SMiguel Ojeda# If the C compiler is Clang, then we can also check whether its version 24678521f33SMiguel Ojeda# matches the `libclang` version used by the Rust bindings generator. 24778521f33SMiguel Ojeda# 24878521f33SMiguel Ojeda# In the future, we might be able to perform a full version check, see 24978521f33SMiguel Ojeda# https://github.com/rust-lang/rust-bindgen/issues/2138. 250dee3a6b8SRussell Curreycc_name=$($(dirname $0)/cc-version.sh $CC | cut -f1 -d' ') 25178521f33SMiguel Ojedaif [ "$cc_name" = Clang ]; then 25278521f33SMiguel Ojeda clang_version=$( \ 253dee3a6b8SRussell Currey LC_ALL=C $CC --version 2>/dev/null \ 25478521f33SMiguel Ojeda | sed -nE '1s:.*version ([0-9]+\.[0-9]+\.[0-9]+).*:\1:p' 25578521f33SMiguel Ojeda ) 25678521f33SMiguel Ojeda if [ "$clang_version" != "$bindgen_libclang_version" ]; then 25778521f33SMiguel Ojeda echo >&2 "***" 25878521f33SMiguel Ojeda echo >&2 "*** libclang (used by the Rust bindings generator '$BINDGEN')" 25978521f33SMiguel Ojeda echo >&2 "*** version does not match Clang's. This may be a problem." 26078521f33SMiguel Ojeda echo >&2 "*** libclang version: $bindgen_libclang_version" 26178521f33SMiguel Ojeda echo >&2 "*** Clang version: $clang_version" 26278521f33SMiguel Ojeda echo >&2 "***" 263aac284b1SMiguel Ojeda warning=1 26478521f33SMiguel Ojeda fi 26578521f33SMiguel Ojedafi 26678521f33SMiguel Ojeda 26778521f33SMiguel Ojeda# Check that the source code for the `core` standard library exists. 26878521f33SMiguel Ojeda# 26978521f33SMiguel Ojeda# `$KRUSTFLAGS` is passed in case the user added `--sysroot`. 27078521f33SMiguel Ojedarustc_sysroot=$("$RUSTC" $KRUSTFLAGS --print sysroot) 27178521f33SMiguel Ojedarustc_src=${RUST_LIB_SRC:-"$rustc_sysroot/lib/rustlib/src/rust/library"} 27278521f33SMiguel Ojedarustc_src_core="$rustc_src/core/src/lib.rs" 27378521f33SMiguel Ojedaif [ ! -e "$rustc_src_core" ]; then 27478521f33SMiguel Ojeda echo >&2 "***" 27578521f33SMiguel Ojeda echo >&2 "*** Source code for the 'core' standard library could not be found" 27678521f33SMiguel Ojeda echo >&2 "*** at '$rustc_src_core'." 27778521f33SMiguel Ojeda echo >&2 "***" 27878521f33SMiguel Ojeda exit 1 27978521f33SMiguel Ojedafi 280