2022-08-04 13:25:53 +03:00
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
#
# Tests whether a suitable Rust toolchain is available.
set -e
min_tool_version = $( dirname $0 ) /min-tool-version.sh
# Convert the version string x.y.z to a canonical up-to-7-digits form.
#
# Note that this function uses one more digit (compared to other
# instances in other version scripts) to give a bit more space to
# `rustc` since it will reach 1.100.0 in late 2026.
get_canonical_version( )
{
IFS = .
set -- $1
echo $(( 100000 * $1 + 100 * $2 + $3 ))
}
2023-06-16 03:16:24 +03:00
# Print a reference to the Quick Start guide in the documentation.
print_docs_reference( )
{
echo >& 2 "***"
echo >& 2 "*** Please see Documentation/rust/quick-start.rst for details"
echo >& 2 "*** on how to set up the Rust support."
echo >& 2 "***"
}
# If the script fails for any reason, or if there was any warning, then
# print a reference to the documentation on exit.
warning = 0
trap 'if [ $? -ne 0 ] || [ $warning -ne 0 ]; then print_docs_reference; fi' EXIT
2022-08-04 13:25:53 +03:00
# Check that the Rust compiler exists.
if ! command -v " $RUSTC " >/dev/null; then
2023-06-16 03:16:21 +03:00
echo >& 2 "***"
echo >& 2 " *** Rust compiler ' $RUSTC ' could not be found. "
echo >& 2 "***"
2022-08-04 13:25:53 +03:00
exit 1
fi
# Check that the Rust bindings generator exists.
if ! command -v " $BINDGEN " >/dev/null; then
2023-06-16 03:16:21 +03:00
echo >& 2 "***"
echo >& 2 " *** Rust bindings generator ' $BINDGEN ' could not be found. "
echo >& 2 "***"
2022-08-04 13:25:53 +03:00
exit 1
fi
# Check that the Rust compiler version is suitable.
#
# Non-stable and distributions' versions may have a version suffix, e.g. `-dev`.
rust_compiler_version = $( \
LC_ALL = C " $RUSTC " --version 2>/dev/null \
| head -n 1 \
| grep -oE '[0-9]+\.[0-9]+\.[0-9]+' \
)
rust_compiler_min_version = $( $min_tool_version rustc)
rust_compiler_cversion = $( get_canonical_version $rust_compiler_version )
rust_compiler_min_cversion = $( get_canonical_version $rust_compiler_min_version )
if [ " $rust_compiler_cversion " -lt " $rust_compiler_min_cversion " ] ; then
2023-06-16 03:16:21 +03:00
echo >& 2 "***"
echo >& 2 " *** Rust compiler ' $RUSTC ' is too old. "
echo >& 2 " *** Your version: $rust_compiler_version "
echo >& 2 " *** Minimum version: $rust_compiler_min_version "
echo >& 2 "***"
2022-08-04 13:25:53 +03:00
exit 1
fi
2023-06-16 03:16:21 +03:00
if [ " $rust_compiler_cversion " -gt " $rust_compiler_min_cversion " ] ; then
2022-08-04 13:25:53 +03:00
echo >& 2 "***"
echo >& 2 " *** Rust compiler ' $RUSTC ' is too new. This may or may not work. "
echo >& 2 " *** Your version: $rust_compiler_version "
echo >& 2 " *** Expected version: $rust_compiler_min_version "
echo >& 2 "***"
2023-06-16 03:16:24 +03:00
warning = 1
2022-08-04 13:25:53 +03:00
fi
# Check that the Rust bindings generator is suitable.
#
# Non-stable and distributions' versions may have a version suffix, e.g. `-dev`.
rust_bindings_generator_version = $( \
LC_ALL = C " $BINDGEN " --version 2>/dev/null \
| head -n 1 \
| grep -oE '[0-9]+\.[0-9]+\.[0-9]+' \
)
rust_bindings_generator_min_version = $( $min_tool_version bindgen)
rust_bindings_generator_cversion = $( get_canonical_version $rust_bindings_generator_version )
rust_bindings_generator_min_cversion = $( get_canonical_version $rust_bindings_generator_min_version )
if [ " $rust_bindings_generator_cversion " -lt " $rust_bindings_generator_min_cversion " ] ; then
2023-06-16 03:16:21 +03:00
echo >& 2 "***"
echo >& 2 " *** Rust bindings generator ' $BINDGEN ' is too old. "
echo >& 2 " *** Your version: $rust_bindings_generator_version "
echo >& 2 " *** Minimum version: $rust_bindings_generator_min_version "
echo >& 2 "***"
2022-08-04 13:25:53 +03:00
exit 1
fi
2023-06-16 03:16:21 +03:00
if [ " $rust_bindings_generator_cversion " -gt " $rust_bindings_generator_min_cversion " ] ; then
2022-08-04 13:25:53 +03:00
echo >& 2 "***"
echo >& 2 " *** Rust bindings generator ' $BINDGEN ' is too new. This may or may not work. "
echo >& 2 " *** Your version: $rust_bindings_generator_version "
echo >& 2 " *** Expected version: $rust_bindings_generator_min_version "
echo >& 2 "***"
2023-06-16 03:16:24 +03:00
warning = 1
2022-08-04 13:25:53 +03:00
fi
# Check that the `libclang` used by the Rust bindings generator is suitable.
kbuild: rust_is_available: add check for `bindgen` invocation
`scripts/rust_is_available.sh` calls `bindgen` with a special
header in order to check whether the `libclang` version in use
is suitable.
However, the invocation itself may fail if, for instance, `bindgen`
cannot locate `libclang`. This is fine for Kconfig (since the
script will still fail and therefore disable Rust as it should),
but it is pretty confusing for users of the `rustavailable` target
given the error will be unrelated:
./scripts/rust_is_available.sh: 21: arithmetic expression: expecting primary: "100000 * + 100 * + "
make: *** [Makefile:1816: rustavailable] Error 2
Instead, run the `bindgen` invocation independently in a previous
step, saving its output and return code. If it fails, then show
the user a proper error message. Otherwise, continue as usual
with the saved output.
Since the previous patch we show a reference to the docs, and
the docs now explain how `bindgen` looks for `libclang`,
thus the error message can leverage the documentation, avoiding
duplication here (and making users aware of the setup guide in
the documentation).
Reported-by: Nick Desaulniers <ndesaulniers@google.com>
Link: https://lore.kernel.org/rust-for-linux/CAKwvOdm5JT4wbdQQYuW+RT07rCi6whGBM2iUAyg8A1CmLXG6Nw@mail.gmail.com/
Reported-by: François Valenduc <francoisvalenduc@gmail.com>
Closes: https://github.com/Rust-for-Linux/linux/issues/934
Reported-by: Alexandru Radovici <msg4alex@gmail.com>
Closes: https://github.com/Rust-for-Linux/linux/pull/921
Reported-by: Matthew Leach <dev@mattleach.net>
Closes: https://lore.kernel.org/rust-for-linux/20230507084116.1099067-1-dev@mattleach.net/
Fixes: 78521f3399ab ("scripts: add `rust_is_available.sh`")
Reviewed-by: Martin Rodriguez Reboredo <yakoyoku@gmail.com>
Reviewed-by: Masahiro Yamada <masahiroy@kernel.org>
Reviewed-by: Nathan Chancellor <nathan@kernel.org>
Link: https://lore.kernel.org/r/20230616001631.463536-6-ojeda@kernel.org
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
2023-06-16 03:16:25 +03:00
#
# In order to do that, first invoke `bindgen` to get the `libclang` version
# found by `bindgen`. This step may already fail if, for instance, `libclang`
# is not found, thus inform the user in such a case.
bindgen_libclang_output = $( \
LC_ALL = C " $BINDGEN " $( dirname $0 ) /rust_is_available_bindgen_libclang.h 2>& 1 >/dev/null
) || bindgen_libclang_code = $?
if [ -n " $bindgen_libclang_code " ] ; then
echo >& 2 "***"
echo >& 2 " *** Running ' $BINDGEN ' to check the libclang version (used by the Rust "
echo >& 2 " *** bindings generator) failed with code $bindgen_libclang_code . This may be caused by "
echo >& 2 "*** a failure to locate libclang. See output and docs below for details:"
echo >& 2 "***"
echo >& 2 " $bindgen_libclang_output "
echo >& 2 "***"
exit 1
fi
# `bindgen` returned successfully, thus use the output to check that the version
# of the `libclang` found by the Rust bindings generator is suitable.
2022-08-04 13:25:53 +03:00
bindgen_libclang_version = $( \
kbuild: rust_is_available: add check for `bindgen` invocation
`scripts/rust_is_available.sh` calls `bindgen` with a special
header in order to check whether the `libclang` version in use
is suitable.
However, the invocation itself may fail if, for instance, `bindgen`
cannot locate `libclang`. This is fine for Kconfig (since the
script will still fail and therefore disable Rust as it should),
but it is pretty confusing for users of the `rustavailable` target
given the error will be unrelated:
./scripts/rust_is_available.sh: 21: arithmetic expression: expecting primary: "100000 * + 100 * + "
make: *** [Makefile:1816: rustavailable] Error 2
Instead, run the `bindgen` invocation independently in a previous
step, saving its output and return code. If it fails, then show
the user a proper error message. Otherwise, continue as usual
with the saved output.
Since the previous patch we show a reference to the docs, and
the docs now explain how `bindgen` looks for `libclang`,
thus the error message can leverage the documentation, avoiding
duplication here (and making users aware of the setup guide in
the documentation).
Reported-by: Nick Desaulniers <ndesaulniers@google.com>
Link: https://lore.kernel.org/rust-for-linux/CAKwvOdm5JT4wbdQQYuW+RT07rCi6whGBM2iUAyg8A1CmLXG6Nw@mail.gmail.com/
Reported-by: François Valenduc <francoisvalenduc@gmail.com>
Closes: https://github.com/Rust-for-Linux/linux/issues/934
Reported-by: Alexandru Radovici <msg4alex@gmail.com>
Closes: https://github.com/Rust-for-Linux/linux/pull/921
Reported-by: Matthew Leach <dev@mattleach.net>
Closes: https://lore.kernel.org/rust-for-linux/20230507084116.1099067-1-dev@mattleach.net/
Fixes: 78521f3399ab ("scripts: add `rust_is_available.sh`")
Reviewed-by: Martin Rodriguez Reboredo <yakoyoku@gmail.com>
Reviewed-by: Masahiro Yamada <masahiroy@kernel.org>
Reviewed-by: Nathan Chancellor <nathan@kernel.org>
Link: https://lore.kernel.org/r/20230616001631.463536-6-ojeda@kernel.org
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
2023-06-16 03:16:25 +03:00
echo " $bindgen_libclang_output " \
2022-08-04 13:25:53 +03:00
| grep -F 'clang version ' \
| grep -oE '[0-9]+\.[0-9]+\.[0-9]+' \
| head -n 1 \
)
bindgen_libclang_min_version = $( $min_tool_version llvm)
bindgen_libclang_cversion = $( get_canonical_version $bindgen_libclang_version )
bindgen_libclang_min_cversion = $( get_canonical_version $bindgen_libclang_min_version )
if [ " $bindgen_libclang_cversion " -lt " $bindgen_libclang_min_cversion " ] ; then
2023-06-16 03:16:21 +03:00
echo >& 2 "***"
echo >& 2 " *** libclang (used by the Rust bindings generator ' $BINDGEN ') is too old. "
echo >& 2 " *** Your version: $bindgen_libclang_version "
echo >& 2 " *** Minimum version: $bindgen_libclang_min_version "
echo >& 2 "***"
2022-08-04 13:25:53 +03:00
exit 1
fi
# If the C compiler is Clang, then we can also check whether its version
# matches the `libclang` version used by the Rust bindings generator.
#
# In the future, we might be able to perform a full version check, see
# https://github.com/rust-lang/rust-bindgen/issues/2138.
2023-06-16 03:16:22 +03:00
cc_name = $( $( dirname $0 ) /cc-version.sh $CC | cut -f1 -d' ' )
2023-06-16 03:16:21 +03:00
if [ " $cc_name " = Clang ] ; then
clang_version = $( \
2023-06-16 03:16:22 +03:00
LC_ALL = C $CC --version 2>/dev/null \
2023-06-16 03:16:21 +03:00
| sed -nE '1s:.*version ([0-9]+\.[0-9]+\.[0-9]+).*:\1:p'
)
if [ " $clang_version " != " $bindgen_libclang_version " ] ; then
echo >& 2 "***"
echo >& 2 " *** libclang (used by the Rust bindings generator ' $BINDGEN ') "
echo >& 2 "*** version does not match Clang's. This may be a problem."
echo >& 2 " *** libclang version: $bindgen_libclang_version "
echo >& 2 " *** Clang version: $clang_version "
echo >& 2 "***"
2023-06-16 03:16:24 +03:00
warning = 1
2022-08-04 13:25:53 +03:00
fi
fi
# Check that the source code for the `core` standard library exists.
#
# `$KRUSTFLAGS` is passed in case the user added `--sysroot`.
rustc_sysroot = $( " $RUSTC " $KRUSTFLAGS --print sysroot)
rustc_src = ${ RUST_LIB_SRC :- " $rustc_sysroot /lib/rustlib/src/rust/library " }
rustc_src_core = " $rustc_src /core/src/lib.rs "
if [ ! -e " $rustc_src_core " ] ; then
2023-06-16 03:16:21 +03:00
echo >& 2 "***"
echo >& 2 "*** Source code for the 'core' standard library could not be found"
echo >& 2 " *** at ' $rustc_src_core '. "
echo >& 2 "***"
2022-08-04 13:25:53 +03:00
exit 1
fi