diff options
Diffstat (limited to 'scripts')
| -rwxr-xr-x | scripts/rust_is_available.sh | 14 | ||||
| -rw-r--r-- | scripts/rust_is_available_bindgen_libclang_22.h | 5 | ||||
| -rwxr-xr-x | scripts/rust_is_available_test.py | 46 | ||||
| -rw-r--r-- | scripts/rustdoc_test_gen.rs | 29 |
4 files changed, 89 insertions, 5 deletions
diff --git a/scripts/rust_is_available.sh b/scripts/rust_is_available.sh index 551f1ebd0dcb..c30983562a2f 100755 --- a/scripts/rust_is_available.sh +++ b/scripts/rust_is_available.sh @@ -208,6 +208,20 @@ if [ "$bindgen_libclang_cversion" -lt "$bindgen_libclang_min_cversion" ]; then exit 1 fi +if [ "$bindgen_libclang_cversion" -ge 2200000 ] && + [ "$rust_bindings_generator_cversion" -lt 7201 ]; then + # Distributions may have patched the issue. + if ! "$BINDGEN" $(dirname $0)/rust_is_available_bindgen_libclang_22.h | grep -q 'pub foo'; then + echo >&2 "***" + echo >&2 "*** Rust bindings generator '$BINDGEN' < 0.72.1 together with libclang >= 22" + echo >&2 "*** may not work due to a bug (https://github.com/rust-lang/rust-bindgen/pull/3278)." + echo >&2 "*** Your bindgen version: $rust_bindings_generator_version" + echo >&2 "*** Your libclang version: $bindgen_libclang_version" + echo >&2 "***" + warning=1 + fi +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. # diff --git a/scripts/rust_is_available_bindgen_libclang_22.h b/scripts/rust_is_available_bindgen_libclang_22.h new file mode 100644 index 000000000000..6b33544c14a8 --- /dev/null +++ b/scripts/rust_is_available_bindgen_libclang_22.h @@ -0,0 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +struct S; +struct S { + int foo; +}; diff --git a/scripts/rust_is_available_test.py b/scripts/rust_is_available_test.py index d6d54b7ea42a..22bdff980c35 100755 --- a/scripts/rust_is_available_test.py +++ b/scripts/rust_is_available_test.py @@ -54,16 +54,23 @@ else: """) @classmethod - def generate_bindgen(cls, version_stdout, libclang_stderr): + def generate_bindgen(cls, version_stdout, libclang_stderr, libclang_22_patched=False): if libclang_stderr is None: libclang_case = f"raise SystemExit({cls.bindgen_default_bindgen_libclang_failure_exit_code})" else: libclang_case = f"print({repr(libclang_stderr)}, file=sys.stderr)" + if libclang_22_patched: + libclang_22_case = "print('pub foo: ::std::os::raw::c_int,')" + else: + libclang_22_case = "pass" + return cls.generate_executable(f"""#!/usr/bin/env python3 import sys if "rust_is_available_bindgen_libclang.h" in " ".join(sys.argv): {libclang_case} +elif "rust_is_available_bindgen_libclang_22.h" in " ".join(sys.argv): + {libclang_22_case} else: print({repr(version_stdout)}) """) @@ -177,7 +184,13 @@ else: def test_rustc_nonexecutable(self): result = self.run_script(self.Expected.FAILURE, { "RUSTC": self.nonexecutable }) - self.assertIn(f"Running '{self.nonexecutable}' to check the Rust compiler version failed with", result.stderr) + self.assertTrue( + # `dash`. + f"Running '{self.nonexecutable}' to check the Rust compiler version failed with" in result.stderr or + # `bash`. + f"Rust compiler '{self.nonexecutable}' could not be found." in result.stderr, + f"Unexpected `stderr`:\n{result.stderr}" + ) def test_rustc_unexpected_binary(self): result = self.run_script(self.Expected.FAILURE, { "RUSTC": self.unexpected_binary }) @@ -205,7 +218,13 @@ else: def test_bindgen_nonexecutable(self): result = self.run_script(self.Expected.FAILURE, { "BINDGEN": self.nonexecutable }) - self.assertIn(f"Running '{self.nonexecutable}' to check the Rust bindings generator version failed with", result.stderr) + self.assertTrue( + # `dash`. + f"Running '{self.nonexecutable}' to check the Rust bindings generator version failed with" in result.stderr or + # `bash`. + f"Rust bindings generator '{self.nonexecutable}' could not be found." in result.stderr, + f"Unexpected `stderr`:\n{result.stderr}" + ) def test_bindgen_unexpected_binary(self): result = self.run_script(self.Expected.FAILURE, { "BINDGEN": self.unexpected_binary }) @@ -248,6 +267,27 @@ else: 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) + def test_bindgen_bad_libclang_22(self): + for (bindgen_version, libclang_version, expected_not_patched) in ( + ("0.71.1", "21.1.0", self.Expected.SUCCESS), + ("0.71.1", "22.0.0", self.Expected.SUCCESS_WITH_WARNINGS), + ("0.71.1", "22.1.0", self.Expected.SUCCESS_WITH_WARNINGS), + + ("0.72.0", "22.0.0", self.Expected.SUCCESS_WITH_WARNINGS), + + ("0.72.1", "22.0.0", self.Expected.SUCCESS), + ): + 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" + 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: + self.assertIn(f"Rust bindings generator '{bindgen}' < 0.72.1 together with libclang >= 22", result.stderr) + + bindgen = self.generate_bindgen(f"bindgen {bindgen_version}", libclang_stderr, libclang_22_patched=True) + 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") result = self.run_script(self.Expected.SUCCESS_WITH_WARNINGS, { "BINDGEN": bindgen }) diff --git a/scripts/rustdoc_test_gen.rs b/scripts/rustdoc_test_gen.rs index d61a77219a8c..d087c0d9fcb3 100644 --- a/scripts/rustdoc_test_gen.rs +++ b/scripts/rustdoc_test_gen.rs @@ -31,8 +31,15 @@ use std::{ fs, fs::File, - io::{BufWriter, Read, Write}, - path::{Path, PathBuf}, + io::{ + BufWriter, + Read, + Write, // + }, + path::{ + Path, + PathBuf, // + }, // }; /// Find the real path to the original file based on the `file` portion of the test name. @@ -232,6 +239,24 @@ pub extern "C" fn {kunit_name}(__kunit_test: *mut ::kernel::bindings::kunit) {{ const __LOG_PREFIX: &[u8] = b"rust_doctests_kernel\0"; +/// Dummy module type for doctest context. +struct LocalModule; + +use kernel::{{ + str::CStr, + ModuleMetadata, + ThisModule, // +}}; +use core::ptr::null_mut; + +impl ModuleMetadata for LocalModule {{ + const NAME: &'static CStr = c"rust_doctests_kernel"; + const THIS_MODULE: ThisModule = {{ + // SAFETY: `try_module_get`/`module_put` handle null module pointers gracefully. + unsafe {{ ThisModule::from_ptr(null_mut()) }} + }}; +}} + {rust_tests} "# ) |
