[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250903190806.2604757-1-SpriteOvO@gmail.com>
Date: Wed, 3 Sep 2025 21:07:56 +0200
From: Asuna Yang <spriteovo@...il.com>
To: Conor Dooley <conor@...nel.org>,
Jason Montleon <jmontleo@...hat.com>,
Han Gao <rabenda.cn@...il.com>,
Miguel Ojeda <ojeda@...nel.org>,
Alex Gaynor <alex.gaynor@...il.com>,
Boqun Feng <boqun.feng@...il.com>,
Gary Guo <gary@...yguo.net>,
Björn Roy Baron <bjorn3_gh@...tonmail.com>,
Benno Lossin <lossin@...nel.org>,
Andreas Hindborg <a.hindborg@...nel.org>,
Alice Ryhl <aliceryhl@...gle.com>,
Trevor Gross <tmgross@...ch.edu>,
Danilo Krummrich <dakr@...nel.org>,
Jonathan Corbet <corbet@....net>,
Paul Walmsley <paul.walmsley@...ive.com>,
Palmer Dabbelt <palmer@...belt.com>,
Albert Ou <aou@...s.berkeley.edu>,
Alexandre Ghiti <alex@...ti.fr>,
Masahiro Yamada <masahiroy@...nel.org>,
Nathan Chancellor <nathan@...nel.org>,
Nick Desaulniers <nick.desaulniers+lkml@...il.com>,
Bill Wendling <morbo@...gle.com>,
Justin Stitt <justinstitt@...gle.com>,
Kees Cook <kees@...nel.org>,
Tejun Heo <tj@...nel.org>,
Peter Zijlstra <peterz@...radead.org>,
Matthew Maurer <mmaurer@...gle.com>,
Jeff Xu <jeffxu@...omium.org>,
Jan Hendrik Farr <kernel@...rr.cc>,
Shakeel Butt <shakeel.butt@...ux.dev>,
Michal Koutný <mkoutny@...e.com>,
Christian Brauner <brauner@...nel.org>,
Brian Gerst <brgerst@...il.com>
Cc: linux-doc@...r.kernel.org,
linux-kernel@...r.kernel.org,
linux-riscv@...ts.infradead.org,
linux-kbuild@...r.kernel.org,
llvm@...ts.linux.dev,
Asuna Yang <SpriteOvO@...il.com>
Subject: [PATCH 1/2] rust: get the version of libclang used by bindgen in a separate script
Decouple the code for getting the version of libclang used by Rust
bindgen from rust_is_available.sh into a separate script so that we can
define a symbol for the version in Kconfig that will be used for
checking in subsequent patches.
Signed-off-by: Asuna Yang <SpriteOvO@...il.com>
---
init/Kconfig | 6 ++
rust/Makefile | 2 +-
scripts/Kconfig.include | 1 +
...lang.h => rust-bindgen-libclang-version.h} | 0
scripts/rust-bindgen-libclang-version.sh | 94 +++++++++++++++++++
scripts/rust_is_available.sh | 58 +++---------
scripts/rust_is_available_test.py | 22 ++---
7 files changed, 125 insertions(+), 58 deletions(-)
rename scripts/{rust_is_available_bindgen_libclang.h => rust-bindgen-libclang-version.h} (100%)
create mode 100755 scripts/rust-bindgen-libclang-version.sh
diff --git a/init/Kconfig b/init/Kconfig
index 666783eb50ab..322af2ba76cd 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -82,6 +82,12 @@ config RUSTC_LLVM_VERSION
int
default $(rustc-llvm-version)
+config RUST_BINDGEN_LIBCLANG_VERSION
+ int
+ default $(rustc-bindgen-libclang-version)
+ help
+ This is the version of `libclang` used by the Rust bindings generator.
+
config CC_CAN_LINK
bool
default $(success,$(srctree)/scripts/cc-can-link.sh $(CC) $(CLANG_FLAGS) $(USERCFLAGS) $(USERLDFLAGS) $(m64-flag)) if 64BIT
diff --git a/rust/Makefile b/rust/Makefile
index 115b63b7d1e3..34d0429d50fd 100644
--- a/rust/Makefile
+++ b/rust/Makefile
@@ -300,7 +300,7 @@ bindgen_extra_c_flags = -w --target=$(BINDGEN_TARGET)
# https://github.com/llvm/llvm-project/issues/44842
# https://github.com/llvm/llvm-project/blob/llvmorg-16.0.0-rc2/clang/docs/ReleaseNotes.rst#deprecated-compiler-flags
ifdef CONFIG_INIT_STACK_ALL_ZERO
-libclang_maj_ver=$(shell $(BINDGEN) $(srctree)/scripts/rust_is_available_bindgen_libclang.h 2>&1 | sed -ne 's/.*clang version \([0-9]*\).*/\1/p')
+libclang_maj_ver=$(shell $(srctree)/scripts/rust-bindgen-libclang-version.sh --with-non-canonical $(BINDGEN) | sed -ne '2s/\([0-9]*\).*/\1/p')
ifeq ($(shell expr $(libclang_maj_ver) \< 16), 1)
bindgen_extra_c_flags += -enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang
endif
diff --git a/scripts/Kconfig.include b/scripts/Kconfig.include
index 33193ca6e803..68df1fed69a1 100644
--- a/scripts/Kconfig.include
+++ b/scripts/Kconfig.include
@@ -67,6 +67,7 @@ m64-flag := $(cc-option-bit,-m64)
rustc-version := $(shell,$(srctree)/scripts/rustc-version.sh $(RUSTC))
rustc-llvm-version := $(shell,$(srctree)/scripts/rustc-llvm-version.sh $(RUSTC))
+rustc-bindgen-libclang-version := $(shell,$(srctree)/scripts/rust-bindgen-libclang-version.sh $(BINDGEN) 2>/dev/null)
# $(rustc-option,<flag>)
# Return y if the Rust compiler supports <flag>, n otherwise
diff --git a/scripts/rust_is_available_bindgen_libclang.h b/scripts/rust-bindgen-libclang-version.h
similarity index 100%
rename from scripts/rust_is_available_bindgen_libclang.h
rename to scripts/rust-bindgen-libclang-version.h
diff --git a/scripts/rust-bindgen-libclang-version.sh b/scripts/rust-bindgen-libclang-version.sh
new file mode 100755
index 000000000000..45485d0f95c8
--- /dev/null
+++ b/scripts/rust-bindgen-libclang-version.sh
@@ -0,0 +1,94 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+#
+# Print the version of `libclang` used by the Rust bindings generator in a 5 or 6-digit form,
+# and a non-canonical form if `--with-non-canonical` option is specified.
+# Also, perform the minimum version check.
+
+set -e
+
+# If the script fails, print 0 to stdout as the version output.
+trap 'if [ $? -ne 0 ]; then echo 0; fi' EXIT
+
+while [ $# -gt 0 ]; do
+ case "$1" in
+ --with-non-canonical)
+ with_non_canonical=1
+ ;;
+ -*)
+ echo >&2 "Unknown option: $1"
+ exit 1
+ ;;
+ *)
+ break
+ ;;
+ esac
+ shift
+done
+
+get_bindgen_libclang_version()
+{
+ # 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.
+ output=$( \
+ LC_ALL=C "$@" $(dirname $0)/rust-bindgen-libclang-version.h 2>&1 >/dev/null
+ ) || code=$?
+ if [ -n "$code" ]; then
+ echo >&2 "***"
+ echo >&2 "*** Running '$@' to check the libclang version (used by the Rust"
+ echo >&2 "*** bindings generator) failed with code $code. This may be caused by"
+ echo >&2 "*** a failure to locate libclang. See output and docs below for details:"
+ echo >&2 "***"
+ echo >&2 "$output"
+ echo >&2 "***"
+ exit 1
+ fi
+
+ # Unlike other version checks, note that this one does not necessarily appear
+ # in the first line of the output, thus no `sed` address is provided.
+ version=$( \
+ echo "$output" \
+ | sed -nE 's:.*clang version ([0-9]+\.[0-9]+\.[0-9]+).*:\1:p'
+ )
+ if [ -z "$version" ]; then
+ echo >&2 "***"
+ echo >&2 "*** Running '$@' to check the libclang version (used by the Rust"
+ echo >&2 "*** bindings generator) did not return an expected output. See output"
+ echo >&2 "*** and docs below for details:"
+ echo >&2 "***"
+ echo >&2 "$output"
+ echo >&2 "***"
+ exit 1
+ fi
+ echo "$version"
+}
+
+# Convert the version string x.y.z to a canonical 5 or 6-digit form.
+get_canonical_version()
+{
+ IFS=.
+ set -- $1
+ echo $((10000 * $1 + 100 * $2 + $3))
+}
+
+min_tool_version=$(dirname $0)/min-tool-version.sh
+
+version=$(get_bindgen_libclang_version "$@")
+min_version=$($min_tool_version llvm)
+cversion=$(get_canonical_version $version)
+min_cversion=$(get_canonical_version $min_version)
+
+if [ "$cversion" -lt "$min_cversion" ]; then
+ echo >&2 "***"
+ echo >&2 "*** libclang (used by the Rust bindings generator '$@') is too old."
+ echo >&2 "*** Your version: $version"
+ echo >&2 "*** Minimum version: $min_version"
+ echo >&2 "***"
+ exit 1
+fi
+
+echo "$cversion"
+if [ -n "$with_non_canonical" ]; then
+ echo "$version"
+fi
diff --git a/scripts/rust_is_available.sh b/scripts/rust_is_available.sh
index d2323de0692c..ccbd5efe9498 100755
--- a/scripts/rust_is_available.sh
+++ b/scripts/rust_is_available.sh
@@ -179,55 +179,21 @@ fi
# Check that the `libclang` used by the Rust bindings generator is suitable.
#
-# 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.
-#
-# Unlike other version checks, note that this one does not necessarily appear
-# in the first line of the output, thus no `sed` address is provided.
-bindgen_libclang_version=$( \
- echo "$bindgen_libclang_output" \
- | sed -nE 's:.*clang version ([0-9]+\.[0-9]+\.[0-9]+).*:\1:p'
-)
-if [ -z "$bindgen_libclang_version" ]; then
- echo >&2 "***"
- echo >&2 "*** Running '$BINDGEN' to check the libclang version (used by the Rust"
- echo >&2 "*** bindings generator) did not return an expected output. See output"
- echo >&2 "*** and docs below for details:"
- echo >&2 "***"
- echo >&2 "$bindgen_libclang_output"
- echo >&2 "***"
- exit 1
-fi
-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
- 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 "***"
+# Get the version, and the minimum version check will be performed internally.
+bindgen_libclang_version_output=$( \
+ $(dirname $0)/rust-bindgen-libclang-version.sh --with-non-canonical $BINDGEN
+) || bindgen_libclang_version_code=$?
+if [ -n "$bindgen_libclang_version_code" ]; then
+ # Detailed error messages have already been output in the script we just called.
exit 1
fi
-if [ "$bindgen_libclang_cversion" -ge 1900100 ] &&
+# Getting the version successfully, thus use the output to check that the
+# version of the `libclang` found by the Rust bindings generator is suitable.
+readarray -t bindgen_libclang_version_array <<<"$bindgen_libclang_version_output"
+bindgen_libclang_version=${bindgen_libclang_version_array[1]}
+bindgen_libclang_cversion=${bindgen_libclang_version_array[0]}
+if [ "$bindgen_libclang_cversion" -ge 190100 ] &&
[ "$rust_bindings_generator_cversion" -lt 6905 ]; then
# Distributions may have patched the issue (e.g. Debian did).
if ! "$BINDGEN" $(dirname $0)/rust_is_available_bindgen_libclang_concat.h | grep -q foofoo; then
diff --git a/scripts/rust_is_available_test.py b/scripts/rust_is_available_test.py
index 4fcc319dea84..b7265e2691cf 100755
--- a/scripts/rust_is_available_test.py
+++ b/scripts/rust_is_available_test.py
@@ -72,7 +72,7 @@ else:
return cls.generate_executable(f"""#!/usr/bin/env python3
import sys
-if "rust_is_available_bindgen_libclang.h" in " ".join(sys.argv):
+if "rust-bindgen-libclang-version.h" in " ".join(sys.argv):
{libclang_case}
elif "rust_is_available_bindgen_0_66.h" in " ".join(sys.argv):
{version_0_66_case}
@@ -113,7 +113,7 @@ else:
cls.bindgen_default_bindgen_version_stdout = f"bindgen {cls.bindgen_default_version}"
cls.bindgen_default_bindgen_libclang_failure_exit_code = 42
- cls.bindgen_default_bindgen_libclang_stderr = f"scripts/rust_is_available_bindgen_libclang.h:2:9: warning: clang version {cls.llvm_default_version} [-W#pragma-messages], err: false"
+ cls.bindgen_default_bindgen_libclang_stderr = f"scripts/rust-bindgen-libclang-version.h:2:9: warning: clang version {cls.llvm_default_version} [-W#pragma-messages], err: false"
cls.default_rustc = cls.generate_rustc(f"rustc {cls.rustc_default_version}")
cls.default_bindgen = cls.generate_bindgen(cls.bindgen_default_bindgen_version_stdout, cls.bindgen_default_bindgen_libclang_stderr)
@@ -265,13 +265,13 @@ else:
self.assertIn(f"bindings generator) failed with code {self.bindgen_default_bindgen_libclang_failure_exit_code}. This may be caused by", result.stderr)
def test_bindgen_libclang_unexpected_version(self):
- bindgen = self.generate_bindgen_libclang("scripts/rust_is_available_bindgen_libclang.h:2:9: warning: clang version unexpected [-W#pragma-messages], err: false")
+ bindgen = self.generate_bindgen_libclang("scripts/rust-bindgen-libclang-version.h:2:9: warning: clang version unexpected [-W#pragma-messages], err: false")
result = self.run_script(self.Expected.FAILURE, { "BINDGEN": bindgen })
self.assertIn(f"Running '{bindgen}' to check the libclang version (used by the Rust", result.stderr)
self.assertIn("bindings generator) did not return an expected output. See output", result.stderr)
def test_bindgen_libclang_old_version(self):
- bindgen = self.generate_bindgen_libclang("scripts/rust_is_available_bindgen_libclang.h:2:9: warning: clang version 10.0.0 [-W#pragma-messages], err: false")
+ bindgen = self.generate_bindgen_libclang("scripts/rust-bindgen-libclang-version.h:2:9: warning: clang version 10.0.0 [-W#pragma-messages], err: false")
result = self.run_script(self.Expected.FAILURE, { "BINDGEN": bindgen })
self.assertIn(f"libclang (used by the Rust bindings generator '{bindgen}') is too old.", result.stderr)
@@ -291,7 +291,7 @@ else:
):
with self.subTest(bindgen_version=bindgen_version, libclang_version=libclang_version):
cc = self.generate_clang(f"clang version {libclang_version}")
- libclang_stderr = f"scripts/rust_is_available_bindgen_libclang.h:2:9: warning: clang version {libclang_version} [-W#pragma-messages], err: false"
+ libclang_stderr = f"scripts/rust-bindgen-libclang-version.h:2:9: warning: clang version {libclang_version} [-W#pragma-messages], err: false"
bindgen = self.generate_bindgen(f"bindgen {bindgen_version}", libclang_stderr)
result = self.run_script(expected_not_patched, { "BINDGEN": bindgen, "CC": cc })
if expected_not_patched == self.Expected.SUCCESS_WITH_WARNINGS:
@@ -301,7 +301,7 @@ else:
result = self.run_script(self.Expected.SUCCESS, { "BINDGEN": bindgen, "CC": cc })
def test_clang_matches_bindgen_libclang_different_bindgen(self):
- bindgen = self.generate_bindgen_libclang("scripts/rust_is_available_bindgen_libclang.h:2:9: warning: clang version 999.0.0 [-W#pragma-messages], err: false")
+ bindgen = self.generate_bindgen_libclang("scripts/rust-bindgen-libclang-version.h:2:9: warning: clang version 999.0.0 [-W#pragma-messages], err: false")
result = self.run_script(self.Expected.SUCCESS_WITH_WARNINGS, { "BINDGEN": bindgen })
self.assertIn("version does not match Clang's. This may be a problem.", result.stderr)
@@ -352,16 +352,16 @@ InstalledDir: /usr/bin
def test_success_bindgen_libclang(self):
for stderr in (
- f"scripts/rust_is_available_bindgen_libclang.h:2:9: warning: clang version {self.llvm_default_version} (https://github.com/llvm/llvm-project.git 4a2c05b05ed07f1f620e94f6524a8b4b2760a0b1) [-W#pragma-messages], err: false",
- f"/home/jd/Documents/dev/kernel-module-flake/linux-6.1/outputs/dev/lib/modules/6.1.0-development/source/scripts/rust_is_available_bindgen_libclang.h:2:9: warning: clang version {self.llvm_default_version} [-W#pragma-messages], err: false",
- f"scripts/rust_is_available_bindgen_libclang.h:2:9: warning: clang version {self.llvm_default_version} (Fedora 13.0.0-3.fc35) [-W#pragma-messages], err: false",
+ f"scripts/rust-bindgen-libclang-version.h:2:9: warning: clang version {self.llvm_default_version} (https://github.com/llvm/llvm-project.git 4a2c05b05ed07f1f620e94f6524a8b4b2760a0b1) [-W#pragma-messages], err: false",
+ f"/home/jd/Documents/dev/kernel-module-flake/linux-6.1/outputs/dev/lib/modules/6.1.0-development/source/scripts/rust-bindgen-libclang-version.h:2:9: warning: clang version {self.llvm_default_version} [-W#pragma-messages], err: false",
+ f"scripts/rust-bindgen-libclang-version.h:2:9: warning: clang version {self.llvm_default_version} (Fedora 13.0.0-3.fc35) [-W#pragma-messages], err: false",
f"""
/nix/store/dsd5gz46hdbdk2rfdimqddhq6m8m8fqs-bash-5.1-p16/bin/bash: warning: setlocale: LC_ALL: cannot change locale (c)
-scripts/rust_is_available_bindgen_libclang.h:2:9: warning: clang version {self.llvm_default_version} [-W#pragma-messages], err: false
+scripts/rust-bindgen-libclang-version.h:2:9: warning: clang version {self.llvm_default_version} [-W#pragma-messages], err: false
""",
f"""
/nix/store/dsd5gz46hdbdk2rfdimqddhq6m8m8fqs-bash-5.1.0-p16/bin/bash: warning: setlocale: LC_ALL: cannot change locale (c)
-/home/jd/Documents/dev/kernel-module-flake/linux-6.1/outputs/dev/lib/modules/6.1.0-development/source/scripts/rust_is_available_bindgen_libclang.h:2:9: warning: clang version {self.llvm_default_version} (Fedora 13.0.0-3.fc35) [-W#pragma-messages], err: false
+/home/jd/Documents/dev/kernel-module-flake/linux-6.1/outputs/dev/lib/modules/6.1.0-development/source/scripts/rust-bindgen-libclang-version.h:2:9: warning: clang version {self.llvm_default_version} (Fedora 13.0.0-3.fc35) [-W#pragma-messages], err: false
"""
):
with self.subTest(stderr=stderr):
--
2.51.0
Powered by blists - more mailing lists