History

Merge tag 'rust-7.1' of git://git.kernel.org/pub/scm/linux/kernel/git/ojeda/linux

Pull Rust updates from Miguel Ojeda: "Toolchain and infrastructure: - Bump the minimum Rust version to 1.85.0 (and 'bindgen' to 0.71.1). As proposed in LPC 2025 and the Maintainers Summit [1], we are going to follow Debian Stable's Rust versions as our minimum versions. Debian Trixie was released on 2025-08-09 with a Rust 1.85.0 and 'bindgen' 0.71.1 toolchain, which is a fair amount of time for e.g. kernel developers to upgrade. Other major distributions support a Rust version that is high enough as well, including: + Arch Linux. + Fedora Linux. + Gentoo Linux. + Nix. + openSUSE Slowroll and openSUSE Tumbleweed. + Ubuntu 25.10 and 26.04 LTS. In addition, 24.04 LTS using their versioned packages. The merged patch series comes with the associated cleanups and simplifications treewide that can be performed thanks to both bumps, as well as documentation updates. In addition, start using 'bindgen''s '--with-attribute-custom-enum' feature to set the 'cfi_encoding' attribute for the 'lru_status' enum used in Binder. Link: https://lwn.net/Articles/1050174/ [1] - Add experimental Kconfig option ('CONFIG_RUST_INLINE_HELPERS') that inlines C helpers into Rust. Essentially, it performs a step similar to LTO, but just for the helpers, i.e. very local and fast. It relies on 'llvm-link' and its '--internalize' flag, and requires a compatible LLVM between Clang and 'rustc' (i.e. same major version, 'CONFIG_RUSTC_CLANG_LLVM_COMPATIBLE'). It is only enabled for two architectures for now. The result is a measurable speedup in different workloads that different users have tested. For instance, for the null block driver, it amounts to a 2%. - Support global per-version flags. While we already have per-version flags in many places, we didn't have a place to set global ones that depend on the compiler version, i.e. in 'rust_common_flags', which sometimes is needed to e.g. tweak the lints set per version. Use that to allow the 'clippy::precedence' lint for Rust < 1.86.0, since it had a change in behavior. - Support overriding the crate name and apply it to Rust Binder, which wanted the module to be called 'rust_binder'. - Add the remaining '__rust_helper' annotations (started in the previous cycle). 'kernel' crate: - Introduce the 'const_assert!' macro: a more powerful version of 'static_assert!' that can refer to generics inside functions or implementation bodies, e.g.: fn f<const N: usize>() { const_assert!(N > 1); } fn g<T>() { const_assert!(size_of::<T>() > 0, "T cannot be ZST"); } In addition, reorganize our set of build-time assertion macros ('{build,const,static_assert}!') to live in the 'build_assert' module. Finally, improve the docs as well to clarify how these are different from one another and how to pick the right one to use, and their equivalence (if any) to the existing C ones for extra clarity. - 'sizes' module: add 'SizeConstants' trait. This gives us typed 'SZ_*' constants (avoiding casts) for use in device address spaces where the address width depends on the hardware (e.g. 32-bit MMIO windows, 64-bit GPU framebuffers, etc.), e.g.: let gpu_heap = 14 * u64::SZ_1M; let mmio_window = u32::SZ_16M; - 'clk' module: implement 'Send' and 'Sync' for 'Clk' and thus simplify the users in Tyr and PWM. - 'ptr' module: add 'const_align_up'. - 'str' module: improve the documentation of the 'c_str!' macro to explain that one should only use it for non-literal cases (for the other case we instead use C string literals, e.g. 'c"abc"'). - Disallow the use of 'CStr::{as_ptr,from_ptr}' and clean one such use in the 'task' module. - 'sync' module: finish the move of 'ARef' and 'AlwaysRefCounted' outside of the 'types' module, i.e. update the last remaining instances and finally remove the re-exports. - 'error' module: clarify that 'from_err_ptr' can return 'Ok(NULL)', including runtime-tested examples. The intention is to hopefully prevent UB that assumes the result of the function is not 'NULL' if successful. This originated from a case of UB I noticed in 'regulator' that created a 'NonNull' on it. Timekeeping: - Expand the example section in the 'HrTimer' documentation. - Mark the 'ClockSource' trait as unsafe to ensure valid values for 'ktime_get()'. - Add 'Delta::from_nanos()'. 'pin-init' crate: - Replace the 'Zeroable' impls for 'Option<NonZero*>' with impls of 'ZeroableOption' for 'NonZero*'. - Improve feature gate handling for unstable features. - Declutter the documentation of implementations of 'Zeroable' for tuples. - Replace uses of 'addr_of[_mut]!' with '&raw [mut]'. rust-analyzer: - Add type annotations to 'generate_rust_analyzer.py'. - Add support for scripts written in Rust ('generate_rust_target.rs', 'rustdoc_test_builder.rs', 'rustdoc_test_gen.rs'). - Refactor 'generate_rust_analyzer.py' to explicitly identify host and target crates, improve readability, and reduce duplication. And some other fixes, cleanups and improvements" * tag 'rust-7.1' of git://git.kernel.org/pub/scm/linux/kernel/git/ojeda/linux: (79 commits) rust: sizes: add SizeConstants trait for device address space constants rust: kernel: update `file_with_nul` comment rust: kbuild: allow `clippy::precedence` for Rust < 1.86.0 rust: kbuild: support global per-version flags rust: declare cfi_encoding for lru_status docs: rust: general-information: use real example docs: rust: general-information: simplify Kconfig example docs: rust: quick-start: remove GDB/Binutils mention docs: rust: quick-start: remove Nix "unstable channel" note docs: rust: quick-start: remove Gentoo "testing" note docs: rust: quick-start: add Ubuntu 26.04 LTS and remove subsection title docs: rust: quick-start: update minimum Ubuntu version docs: rust: quick-start: update Ubuntu versioned packages docs: rust: quick-start: openSUSE provides `rust-src` package nowadays rust: kbuild: remove "dummy parameter" workaround for `bindgen` < 0.71.1 rust: kbuild: update `bindgen --rust-target` version and replace comment rust: rust_is_available: remove warning for `bindgen` < 0.69.5 && libclang >= 19.1 rust: rust_is_available: remove warning for `bindgen` 0.66.[01] rust: bump `bindgen` minimum supported version to 0.71.1 (Debian Trixie) rust: block: update `const_refs_to_static` MSRV TODO comment ...

Linus Torvalds committed 7 months ago

Commit 26ff9692 parents 2848320 8a2305178 files · +1391 −821Browse files

Showing the changes to scripts (7 of 78 files). Show all

Unified · Split

7 files
  1. scripts/Makefile.build +7 −8
  2. scripts/generate_rust_analyzer.py +216 −82
  3. scripts/min-tool-version.sh +2 −2
  4. scripts/rust_is_available.sh +1 −35
  5. scripts/rust_is_available_bindgen_0_66.h +0 −2
  6. scripts/rust_is_available_bindgen_libclang_concat.h +0 −3
  7. scripts/rust_is_available_test.py +3 −55
scripts/Makefile.build+7−8
@@ -310,18 +310,13 @@ $(obj)/%.lst: $(obj)/%.c FORCE · 309 unmodified lines
310 310
311# The features in this list are the ones allowed for non-`rust/` code.311# The features in this list are the ones allowed for non-`rust/` code.
312#312#
313# - Stable since Rust 1.79.0: `feature(slice_ptr_len)`.
314# - Stable since Rust 1.81.0: `feature(lint_reasons)`.
315# - Stable since Rust 1.82.0: `feature(asm_const)`,
316# `feature(offset_of_nested)`, `feature(raw_ref_op)`.
317# - Stable since Rust 1.84.0: `feature(strict_provenance)`.
318# - Stable since Rust 1.87.0: `feature(asm_goto)`.313# - Stable since Rust 1.87.0: `feature(asm_goto)`.
319# - Expected to become stable: `feature(arbitrary_self_types)`.314# - Expected to become stable: `feature(arbitrary_self_types)`.
320# - To be determined: `feature(used_with_arg)`.315# - To be determined: `feature(used_with_arg)`.
321#316#
322# Please see https://github.com/Rust-for-Linux/linux/issues/2 for details on317# Please see https://github.com/Rust-for-Linux/linux/issues/2 for details on
323# the unstable features in use.318# the unstable features in use.
324rust_allowed_features := asm_const,asm_goto,arbitrary_self_types,lint_reasons,offset_of_nested,raw_ref_op,slice_ptr_len,strict_provenance,used_with_arg319rust_allowed_features := arbitrary_self_types,asm_goto,used_with_arg
325 320
326# `--out-dir` is required to avoid temporaries being created by `rustc` in the321# `--out-dir` is required to avoid temporaries being created by `rustc` in the
327# current working directory, which may be not accessible in the out-of-tree322# current working directory, which may be not accessible in the out-of-tree
@@ -334,7 +329,6 @@ rust_common_cmd = \ · 6 unmodified lines
334 -Zcrate-attr='feature($(rust_allowed_features))' \329 -Zcrate-attr='feature($(rust_allowed_features))' \
335 -Zunstable-options --extern pin_init --extern kernel \330 -Zunstable-options --extern pin_init --extern kernel \
336 --crate-type rlib -L $(objtree)/rust/ \331 --crate-type rlib -L $(objtree)/rust/ \
337 --crate-name $(basename $(notdir $@)) \
338 --sysroot=/dev/null \332 --sysroot=/dev/null \
339 --out-dir $(dir $@) --emit=dep-info=$(depfile)333 --out-dir $(dir $@) --emit=dep-info=$(depfile)
340 334
@@ -347,7 +341,12 @@ rust_common_cmd = \ · 6 unmodified lines
347# would not match each other.341# would not match each other.
348 342
349quiet_cmd_rustc_o_rs = $(RUSTC_OR_CLIPPY_QUIET) $(quiet_modtag) $@343quiet_cmd_rustc_o_rs = $(RUSTC_OR_CLIPPY_QUIET) $(quiet_modtag) $@
350 cmd_rustc_o_rs = $(rust_common_cmd) --emit=obj=$@ $< $(cmd_objtool)344 cmd_rustc_o_rs = $(rust_common_cmd) --emit=$(if $(CONFIG_RUST_INLINE_HELPERS),llvm-bc=$(patsubst %.o,%.bc,$@),obj=$@) $< \
345 $(if $(CONFIG_RUST_INLINE_HELPERS),;$(LLVM_LINK) --internalize --suppress-warnings $(patsubst %.o,%.bc,$@) \
346 $(objtree)/rust/helpers/helpers$(if $(part-of-module),_module).bc -o $(patsubst %.o,%.m.bc,$@); \
347 $(CC) $(CLANG_FLAGS) $(KBUILD_CFLAGS) -Wno-override-module -c $(patsubst %.o,%.m.bc,$@) -o $@ \
348 $(cmd_ld_single)) \
349 $(cmd_objtool)
351 350
352define rule_rustc_o_rs351define rule_rustc_o_rs
353 $(call cmd_and_fixdep,rustc_o_rs)352 $(call cmd_and_fixdep,rustc_o_rs)
scripts/generate_rust_analyzer.py+216−82
@@ -10,8 +10,15 @@ import os · 9 unmodified lines
10import pathlib10import pathlib
11import subprocess11import subprocess
12import sys12import sys
13from typing import Dict, Iterable, List, Literal, Optional, TypedDict
13 14
14def args_crates_cfgs(cfgs):15def invoke_rustc(args: List[str]) -> str:
16 return subprocess.check_output(
17 [os.environ["RUSTC"]] + args,
18 stdin=subprocess.DEVNULL,
19 ).decode('utf-8').strip()
20
21def args_crates_cfgs(cfgs: List[str]) -> Dict[str, List[str]]:
15 crates_cfgs = {}22 crates_cfgs = {}
16 for cfg in cfgs:23 for cfg in cfgs:
17 crate, vals = cfg.split("=", 1)24 crate, vals = cfg.split("=", 1)
@@ -19,54 +26,153 @@ def args_crates_cfgs(cfgs): · 1 unmodified line
19 26
20 return crates_cfgs27 return crates_cfgs
21 28
22def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs, core_edition):29class Dependency(TypedDict):
30 crate: int
31 name: str
32
33
34class Source(TypedDict):
35 include_dirs: List[str]
36 exclude_dirs: List[str]
37
38
39class Crate(TypedDict):
40 display_name: str
41 root_module: str
42 is_workspace_member: bool
43 deps: List[Dependency]
44 cfg: List[str]
45 edition: str
46 env: Dict[str, str]
47
48
49class ProcMacroCrate(Crate):
50 is_proc_macro: Literal[True]
51 proc_macro_dylib_path: str # `pathlib.Path` is not JSON serializable.
52
53
54class CrateWithGenerated(Crate):
55 source: Source
56
57
58def generate_crates(
59 srctree: pathlib.Path,
60 objtree: pathlib.Path,
61 sysroot_src: pathlib.Path,
62 external_src: Optional[pathlib.Path],
63 cfgs: List[str],
64 core_edition: str,
65) -> List[Crate]:
23 # Generate the configuration list.66 # Generate the configuration list.
24 cfg = []67 generated_cfg = []
25 with open(objtree / "include" / "generated" / "rustc_cfg") as fd:68 with open(objtree / "include" / "generated" / "rustc_cfg") as fd:
26 for line in fd:69 for line in fd:
27 line = line.replace("--cfg=", "")70 line = line.replace("--cfg=", "")
28 line = line.replace("\n", "")71 line = line.replace("\n", "")
29 cfg.append(line)72 generated_cfg.append(line)
30 73
31 # Now fill the crates list -- dependencies need to come first.74 # Now fill the crates list.
32 #75 crates: List[Crate] = []
33 # Avoid O(n^2) iterations by keeping a map of indexes.
34 crates = []
35 crates_indexes = {}
36 crates_cfgs = args_crates_cfgs(cfgs)76 crates_cfgs = args_crates_cfgs(cfgs)
37 77
38 def append_crate(display_name, root_module, deps, cfg=[], is_workspace_member=True, is_proc_macro=False, edition="2021"):78 def get_crate_name(path: pathlib.Path) -> str:
39 crate = {79 return invoke_rustc(["--print", "crate-name", str(path)])
80
81 def build_crate(
82 display_name: str,
83 root_module: pathlib.Path,
84 deps: List[Dependency],
85 *,
86 cfg: Optional[List[str]],
87 is_workspace_member: Optional[bool],
88 edition: Optional[str],
89 ) -> Crate:
90 cfg = cfg if cfg is not None else crates_cfgs.get(display_name, [])
91 is_workspace_member = (
92 is_workspace_member if is_workspace_member is not None else True
93 )
94 edition = edition if edition is not None else "2021"
95 return {
40 "display_name": display_name,96 "display_name": display_name,
41 "root_module": str(root_module),97 "root_module": str(root_module),
42 "is_workspace_member": is_workspace_member,98 "is_workspace_member": is_workspace_member,
43 "is_proc_macro": is_proc_macro,99 "deps": deps,
44 "deps": [{"crate": crates_indexes[dep], "name": dep} for dep in deps],
45 "cfg": cfg,100 "cfg": cfg,
46 "edition": edition,101 "edition": edition,
47 "env": {102 "env": {
48 "RUST_MODFILE": "This is only for rust-analyzer"103 "RUST_MODFILE": "This is only for rust-analyzer"
49 }104 }
50 }105 }
51 if is_proc_macro:106
52 proc_macro_dylib_name = subprocess.check_output(107 def append_proc_macro_crate(
53 [os.environ["RUSTC"], "--print", "file-names", "--crate-name", display_name, "--crate-type", "proc-macro", "-"],108 display_name: str,
54 stdin=subprocess.DEVNULL,109 root_module: pathlib.Path,
55 ).decode('utf-8').strip()110 deps: List[Dependency],
56 crate["proc_macro_dylib_path"] = f"{objtree}/rust/{proc_macro_dylib_name}"111 *,
57 crates_indexes[display_name] = len(crates)112 cfg: Optional[List[str]] = None,
113 is_workspace_member: Optional[bool] = None,
114 edition: Optional[str] = None,
115 ) -> Dependency:
116 crate = build_crate(
117 display_name,
118 root_module,
119 deps,
120 cfg=cfg,
121 is_workspace_member=is_workspace_member,
122 edition=edition,
123 )
124 proc_macro_dylib_name = invoke_rustc([
125 "--print",
126 "file-names",
127 "--crate-name",
128 display_name,
129 "--crate-type",
130 "proc-macro",
131 "-",
132 ])
133 proc_macro_crate: ProcMacroCrate = {
134 **crate,
135 "is_proc_macro": True,
136 "proc_macro_dylib_path": str(objtree / "rust" / proc_macro_dylib_name),
137 }
138 return register_crate(proc_macro_crate)
139
140 def register_crate(crate: Crate) -> Dependency:
141 index = len(crates)
58 crates.append(crate)142 crates.append(crate)
143 return {"crate": index, "name": crate["display_name"]}
144
145 def append_crate(
146 display_name: str,
147 root_module: pathlib.Path,
148 deps: List[Dependency],
149 *,
150 cfg: Optional[List[str]] = None,
151 is_workspace_member: Optional[bool] = None,
152 edition: Optional[str] = None,
153 ) -> Dependency:
154 return register_crate(
155 build_crate(
156 display_name,
157 root_module,
158 deps,
159 cfg=cfg,
160 is_workspace_member=is_workspace_member,
161 edition=edition,
162 )
163 )
59 164
60 def append_sysroot_crate(165 def append_sysroot_crate(
61 display_name,166 display_name: str,
62 deps,167 deps: List[Dependency],
63 cfg=[],168 *,
64 ):169 cfg: Optional[List[str]] = None,
65 append_crate(170 ) -> Dependency:
171 return append_crate(
66 display_name,172 display_name,
67 sysroot_src / display_name / "src" / "lib.rs",173 sysroot_src / display_name / "src" / "lib.rs",
68 deps,174 deps,
69 cfg,175 cfg=cfg,
70 is_workspace_member=False,176 is_workspace_member=False,
71 # Miguel Ojeda writes:177 # Miguel Ojeda writes:
72 #178 #
@@ -98,129 +204,146 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs, core_edit · 25 unmodified lines
98 # NB: sysroot crates reexport items from one another so setting up our transitive dependencies204 # NB: sysroot crates reexport items from one another so setting up our transitive dependencies
99 # here is important for ensuring that rust-analyzer can resolve symbols. The sources of truth205 # here is important for ensuring that rust-analyzer can resolve symbols. The sources of truth
100 # for this dependency graph are `(sysroot_src / crate / "Cargo.toml" for crate in crates)`.206 # for this dependency graph are `(sysroot_src / crate / "Cargo.toml" for crate in crates)`.
101 append_sysroot_crate("core", [], cfg=crates_cfgs.get("core", []))207 core = append_sysroot_crate("core", [])
102 append_sysroot_crate("alloc", ["core"])208 alloc = append_sysroot_crate("alloc", [core])
103 append_sysroot_crate("std", ["alloc", "core"])209 std = append_sysroot_crate("std", [alloc, core])
104 append_sysroot_crate("proc_macro", ["core", "std"])210 proc_macro = append_sysroot_crate("proc_macro", [core, std])
105 211
106 append_crate(212 compiler_builtins = append_crate(
107 "compiler_builtins",213 "compiler_builtins",
108 srctree / "rust" / "compiler_builtins.rs",214 srctree / "rust" / "compiler_builtins.rs",
109 ["core"],215 [core],
110 )216 )
111 217
112 append_crate(218 proc_macro2 = append_crate(
113 "proc_macro2",219 "proc_macro2",
114 srctree / "rust" / "proc-macro2" / "lib.rs",220 srctree / "rust" / "proc-macro2" / "lib.rs",
115 ["core", "alloc", "std", "proc_macro"],221 [core, alloc, std, proc_macro],
116 cfg=crates_cfgs["proc_macro2"],
117 )222 )
118 223
119 append_crate(224 quote = append_crate(
120 "quote",225 "quote",
121 srctree / "rust" / "quote" / "lib.rs",226 srctree / "rust" / "quote" / "lib.rs",
122 ["core", "alloc", "std", "proc_macro", "proc_macro2"],227 [core, alloc, std, proc_macro, proc_macro2],
123 cfg=crates_cfgs["quote"],
124 edition="2018",228 edition="2018",
125 )229 )
126 230
127 append_crate(231 syn = append_crate(
128 "syn",232 "syn",
129 srctree / "rust" / "syn" / "lib.rs",233 srctree / "rust" / "syn" / "lib.rs",
130 ["std", "proc_macro", "proc_macro2", "quote"],234 [std, proc_macro, proc_macro2, quote],
131 cfg=crates_cfgs["syn"],
132 )235 )
133 236
134 append_crate(237 macros = append_proc_macro_crate(
135 "macros",238 "macros",
136 srctree / "rust" / "macros" / "lib.rs",239 srctree / "rust" / "macros" / "lib.rs",
137 ["std", "proc_macro", "proc_macro2", "quote", "syn"],240 [std, proc_macro, proc_macro2, quote, syn],
138 is_proc_macro=True,
139 )241 )
140 242
141 append_crate(243 build_error = append_crate(
142 "build_error",244 "build_error",
143 srctree / "rust" / "build_error.rs",245 srctree / "rust" / "build_error.rs",
144 ["core", "compiler_builtins"],246 [core, compiler_builtins],
145 )247 )
146 248
147 append_crate(249 pin_init_internal = append_proc_macro_crate(
148 "pin_init_internal",250 "pin_init_internal",
149 srctree / "rust" / "pin-init" / "internal" / "src" / "lib.rs",251 srctree / "rust" / "pin-init" / "internal" / "src" / "lib.rs",
150 ["std", "proc_macro", "proc_macro2", "quote", "syn"],252 [std, proc_macro, proc_macro2, quote, syn],
151 cfg=["kernel"],
152 is_proc_macro=True,
153 )253 )
154 254
155 append_crate(255 pin_init = append_crate(
156 "pin_init",256 "pin_init",
157 srctree / "rust" / "pin-init" / "src" / "lib.rs",257 srctree / "rust" / "pin-init" / "src" / "lib.rs",
158 ["core", "compiler_builtins", "pin_init_internal", "macros"],258 [core, compiler_builtins, pin_init_internal, macros],
159 cfg=["kernel"],
160 )259 )
161 260
162 append_crate(261 ffi = append_crate(
163 "ffi",262 "ffi",
164 srctree / "rust" / "ffi.rs",263 srctree / "rust" / "ffi.rs",
165 ["core", "compiler_builtins"],264 [core, compiler_builtins],
166 )265 )
167 266
168 def append_crate_with_generated(267 def append_crate_with_generated(
169 display_name,268 display_name: str,
170 deps,269 deps: List[Dependency],
171 ):270 ) -> Dependency:
172 append_crate(271 crate = build_crate(
173 display_name,272 display_name,
174 srctree / "rust"/ display_name / "lib.rs",273 srctree / "rust"/ display_name / "lib.rs",
175 deps,274 deps,
176 cfg=cfg,275 cfg=generated_cfg,
276 is_workspace_member=True,
277 edition=None,
177 )278 )
178 crates[-1]["env"]["OBJTREE"] = str(objtree.resolve(True))279 crate["env"]["OBJTREE"] = str(objtree.resolve(True))
179 crates[-1]["source"] = {280 crate_with_generated: CrateWithGenerated = {
180 "include_dirs": [281 **crate,
181 str(srctree / "rust" / display_name),282 "source": {
182 str(objtree / "rust")283 "include_dirs": [
183 ],284 str(srctree / "rust" / display_name),
184 "exclude_dirs": [],285 str(objtree / "rust"),
286 ],
287 "exclude_dirs": [],
288 },
185 }289 }
290 return register_crate(crate_with_generated)
291
292 bindings = append_crate_with_generated("bindings", [core, ffi, pin_init])
293 uapi = append_crate_with_generated("uapi", [core, ffi, pin_init])
294 kernel = append_crate_with_generated(
295 "kernel", [core, macros, build_error, pin_init, ffi, bindings, uapi]
296 )
186 297
187 append_crate_with_generated("bindings", ["core", "ffi", "pin_init"])298 scripts = srctree / "scripts"
188 append_crate_with_generated("uapi", ["core", "ffi", "pin_init"])299 makefile = (scripts / "Makefile").read_text()
189 append_crate_with_generated("kernel", ["core", "macros", "build_error", "pin_init", "ffi", "bindings", "uapi"])300 for path in scripts.glob("*.rs"):
301 name = path.stem
302 if f"{name}-rust" not in makefile:
303 continue
304 append_crate(
305 name,
306 path,
307 [std],
308 )
190 309
191 def is_root_crate(build_file, target):310 def is_root_crate(build_file: pathlib.Path, target: str) -> bool:
192 try:311 try:
193 return f"{target}.o" in open(build_file).read()312 contents = build_file.read_text()
194 except FileNotFoundError:313 except FileNotFoundError:
195 return False314 return False
315 return f"{target}.o" in contents
196 316
197 # Then, the rest outside of `rust/`.317 # Then, the rest outside of `rust/`.
198 #318 #
199 # We explicitly mention the top-level folders we want to cover.319 # We explicitly mention the top-level folders we want to cover.
200 extra_dirs = map(lambda dir: srctree / dir, ("samples", "drivers"))320 extra_dirs: Iterable[pathlib.Path] = (
321 srctree / dir for dir in ("samples", "drivers")
322 )
201 if external_src is not None:323 if external_src is not None:
202 extra_dirs = [external_src]324 extra_dirs = [external_src]
203 for folder in extra_dirs:325 for folder in extra_dirs:
204 for path in folder.rglob("*.rs"):326 for path in folder.rglob("*.rs"):
205 logging.info("Checking %s", path)327 logging.info("Checking %s", path)
206 name = path.name.replace(".rs", "")328 file_name = path.stem
207 329
208 # Skip those that are not crate roots.330 # Skip those that are not crate roots.
209 if not is_root_crate(path.parent / "Makefile", name) and \331 if not is_root_crate(path.parent / "Makefile", file_name) and \
210 not is_root_crate(path.parent / "Kbuild", name):332 not is_root_crate(path.parent / "Kbuild", file_name):
211 continue333 continue
212 334
213 logging.info("Adding %s", name)335 crate_name = get_crate_name(path)
336 logging.info("Adding %s", crate_name)
214 append_crate(337 append_crate(
215 name,338 crate_name,
216 path,339 path,
217 ["core", "kernel", "pin_init"],340 [core, kernel, pin_init],
218 cfg=cfg,341 cfg=generated_cfg,
219 )342 )
220 343
221 return crates344 return crates
222 345
223def main():346def main() -> None:
224 parser = argparse.ArgumentParser()347 parser = argparse.ArgumentParser()
225 parser.add_argument('--verbose', '-v', action='store_true')348 parser.add_argument('--verbose', '-v', action='store_true')
226 parser.add_argument('--cfgs', action='append', default=[])349 parser.add_argument('--cfgs', action='append', default=[])
@@ -230,7 +353,18 @@ def main(): · 3 unmodified lines
230 parser.add_argument("sysroot", type=pathlib.Path)353 parser.add_argument("sysroot", type=pathlib.Path)
231 parser.add_argument("sysroot_src", type=pathlib.Path)354 parser.add_argument("sysroot_src", type=pathlib.Path)
232 parser.add_argument("exttree", type=pathlib.Path, nargs="?")355 parser.add_argument("exttree", type=pathlib.Path, nargs="?")
233 args = parser.parse_args()356
357 class Args(argparse.Namespace):
358 verbose: bool
359 cfgs: List[str]
360 srctree: pathlib.Path
361 objtree: pathlib.Path
362 sysroot: pathlib.Path
363 sysroot_src: pathlib.Path
364 exttree: Optional[pathlib.Path]
365 core_edition: str
366
367 args = parser.parse_args(namespace=Args())
234 368
235 logging.basicConfig(369 logging.basicConfig(
236 format="[%(asctime)s] [%(levelname)s] %(message)s",370 format="[%(asctime)s] [%(levelname)s] %(message)s",
scripts/min-tool-version.sh+2−2
@@ -31,10 +31,10 @@ llvm) · 30 unmodified lines
31 fi31 fi
32 ;;32 ;;
33rustc)33rustc)
34 echo 1.78.034 echo 1.85.0
35 ;;35 ;;
36bindgen)36bindgen)
37 echo 0.65.137 echo 0.71.1
38 ;;38 ;;
39*)39*)
40 echo "$1: unknown tool" >&240 echo "$1: unknown tool" >&2
scripts/rust_is_available.sh+1−35
@@ -121,14 +121,8 @@ fi · 120 unmodified lines
121# Check that the Rust bindings generator is suitable.121# Check that the Rust bindings generator is suitable.
122#122#
123# Non-stable and distributions' versions may have a version suffix, e.g. `-dev`.123# Non-stable and distributions' versions may have a version suffix, e.g. `-dev`.
124#
125# The dummy parameter `workaround-for-0.69.0` is required to support 0.69.0
126# (https://github.com/rust-lang/rust-bindgen/pull/2678) and 0.71.0
127# (https://github.com/rust-lang/rust-bindgen/pull/3040). It can be removed when
128# the minimum version is upgraded past the latter (0.69.1 and 0.71.1 both fixed
129# the issue).
130rust_bindings_generator_output=$( \124rust_bindings_generator_output=$( \
131 LC_ALL=C "$BINDGEN" --version workaround-for-0.69.0 2>/dev/null125 LC_ALL=C "$BINDGEN" --version 2>/dev/null
132) || rust_bindings_generator_code=$?126) || rust_bindings_generator_code=$?
133if [ -n "$rust_bindings_generator_code" ]; then127if [ -n "$rust_bindings_generator_code" ]; then
134 echo >&2 "***"128 echo >&2 "***"
@@ -163,19 +157,6 @@ if [ "$rust_bindings_generator_cversion" -lt "$rust_bindings_generator_min_cvers · 28 unmodified lines
163 echo >&2 "***"157 echo >&2 "***"
164 exit 1158 exit 1
165fi159fi
166if [ "$rust_bindings_generator_cversion" -eq 6600 ] ||
167 [ "$rust_bindings_generator_cversion" -eq 6601 ]; then
168 # Distributions may have patched the issue (e.g. Debian did).
169 if ! "$BINDGEN" $(dirname $0)/rust_is_available_bindgen_0_66.h >/dev/null; then
170 echo >&2 "***"
171 echo >&2 "*** Rust bindings generator '$BINDGEN' versions 0.66.0 and 0.66.1 may not"
172 echo >&2 "*** work due to a bug (https://github.com/rust-lang/rust-bindgen/pull/2567),"
173 echo >&2 "*** unless patched (like Debian's)."
174 echo >&2 "*** Your version: $rust_bindings_generator_version"
175 echo >&2 "***"
176 warning=1
177 fi
178fi
179 160
180# Check that the `libclang` used by the Rust bindings generator is suitable.161# Check that the `libclang` used by the Rust bindings generator is suitable.
181#162#
@@ -227,21 +208,6 @@ if [ "$bindgen_libclang_cversion" -lt "$bindgen_libclang_min_cversion" ]; then · 45 unmodified lines
227 exit 1208 exit 1
228fi209fi
229 210
230if [ "$bindgen_libclang_cversion" -ge 1900100 ] &&
231 [ "$rust_bindings_generator_cversion" -lt 6905 ]; then
232 # Distributions may have patched the issue (e.g. Debian did).
233 if ! "$BINDGEN" $(dirname $0)/rust_is_available_bindgen_libclang_concat.h | grep -q foofoo; then
234 echo >&2 "***"
235 echo >&2 "*** Rust bindings generator '$BINDGEN' < 0.69.5 together with libclang >= 19.1"
236 echo >&2 "*** may not work due to a bug (https://github.com/rust-lang/rust-bindgen/pull/2824),"
237 echo >&2 "*** unless patched (like Debian's)."
238 echo >&2 "*** Your bindgen version: $rust_bindings_generator_version"
239 echo >&2 "*** Your libclang version: $bindgen_libclang_version"
240 echo >&2 "***"
241 warning=1
242 fi
243fi
244
245# If the C compiler is Clang, then we can also check whether its version211# If the C compiler is Clang, then we can also check whether its version
246# matches the `libclang` version used by the Rust bindings generator.212# matches the `libclang` version used by the Rust bindings generator.
247#213#
scripts/rust_is_available_bindgen_0_66.h+0−2
@@ -1,2 +0,0 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2#define A "\0"
scripts/rust_is_available_bindgen_libclang_concat.h+0−3
@@ -1,3 +0,0 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2#define F(x) int x##x
3F(foo);
scripts/rust_is_available_test.py+3−55
@@ -54,37 +54,23 @@ else: · 53 unmodified lines
54""")54""")
55 55
56 @classmethod56 @classmethod
57 def generate_bindgen(cls, version_stdout, libclang_stderr, version_0_66_patched=False, libclang_concat_patched=False):57 def generate_bindgen(cls, version_stdout, libclang_stderr):
58 if libclang_stderr is None:58 if libclang_stderr is None:
59 libclang_case = f"raise SystemExit({cls.bindgen_default_bindgen_libclang_failure_exit_code})"59 libclang_case = f"raise SystemExit({cls.bindgen_default_bindgen_libclang_failure_exit_code})"
60 else:60 else:
61 libclang_case = f"print({repr(libclang_stderr)}, file=sys.stderr)"61 libclang_case = f"print({repr(libclang_stderr)}, file=sys.stderr)"
62 62
63 if version_0_66_patched:
64 version_0_66_case = "pass"
65 else:
66 version_0_66_case = "raise SystemExit(1)"
67
68 if libclang_concat_patched:
69 libclang_concat_case = "print('pub static mut foofoo: ::std::os::raw::c_int;')"
70 else:
71 libclang_concat_case = "pass"
72
73 return cls.generate_executable(f"""#!/usr/bin/env python363 return cls.generate_executable(f"""#!/usr/bin/env python3
74import sys64import sys
75if "rust_is_available_bindgen_libclang.h" in " ".join(sys.argv):65if "rust_is_available_bindgen_libclang.h" in " ".join(sys.argv):
76 {libclang_case}66 {libclang_case}
77elif "rust_is_available_bindgen_0_66.h" in " ".join(sys.argv):
78 {version_0_66_case}
79elif "rust_is_available_bindgen_libclang_concat.h" in " ".join(sys.argv):
80 {libclang_concat_case}
81else:67else:
82 print({repr(version_stdout)})68 print({repr(version_stdout)})
83""")69""")
84 70
85 @classmethod71 @classmethod
86 def generate_bindgen_version(cls, stdout, version_0_66_patched=False):72 def generate_bindgen_version(cls, stdout):
87 return cls.generate_bindgen(stdout, cls.bindgen_default_bindgen_libclang_stderr, version_0_66_patched)73 return cls.generate_bindgen(stdout, cls.bindgen_default_bindgen_libclang_stderr)
88 74
89 @classmethod75 @classmethod
90 def generate_bindgen_libclang_failure(cls):76 def generate_bindgen_libclang_failure(cls):
@@ -245,19 +231,6 @@ else: · 154 unmodified lines
245 result = self.run_script(self.Expected.FAILURE, { "BINDGEN": bindgen })231 result = self.run_script(self.Expected.FAILURE, { "BINDGEN": bindgen })
246 self.assertIn(f"Rust bindings generator '{bindgen}' is too old.", result.stderr)232 self.assertIn(f"Rust bindings generator '{bindgen}' is too old.", result.stderr)
247 233
248 def test_bindgen_bad_version_0_66_0_and_0_66_1(self):
249 for version in ("0.66.0", "0.66.1"):
250 with self.subTest(version=version):
251 bindgen = self.generate_bindgen_version(f"bindgen {version}")
252 result = self.run_script(self.Expected.SUCCESS_WITH_WARNINGS, { "BINDGEN": bindgen })
253 self.assertIn(f"Rust bindings generator '{bindgen}' versions 0.66.0 and 0.66.1 may not", result.stderr)
254
255 def test_bindgen_bad_version_0_66_0_and_0_66_1_patched(self):
256 for version in ("0.66.0", "0.66.1"):
257 with self.subTest(version=version):
258 bindgen = self.generate_bindgen_version(f"bindgen {version}", True)
259 result = self.run_script(self.Expected.SUCCESS, { "BINDGEN": bindgen })
260
261 def test_bindgen_libclang_failure(self):234 def test_bindgen_libclang_failure(self):
262 bindgen = self.generate_bindgen_libclang_failure()235 bindgen = self.generate_bindgen_libclang_failure()
263 result = self.run_script(self.Expected.FAILURE, { "BINDGEN": bindgen })236 result = self.run_script(self.Expected.FAILURE, { "BINDGEN": bindgen })
@@ -275,31 +248,6 @@ else: · 11 unmodified lines
275 result = self.run_script(self.Expected.FAILURE, { "BINDGEN": bindgen })248 result = self.run_script(self.Expected.FAILURE, { "BINDGEN": bindgen })
276 self.assertIn(f"libclang (used by the Rust bindings generator '{bindgen}') is too old.", result.stderr)249 self.assertIn(f"libclang (used by the Rust bindings generator '{bindgen}') is too old.", result.stderr)
277 250
278 def test_bindgen_bad_libclang_concat(self):
279 for (bindgen_version, libclang_version, expected_not_patched) in (
280 ("0.69.4", "18.0.0", self.Expected.SUCCESS),
281 ("0.69.4", "19.1.0", self.Expected.SUCCESS_WITH_WARNINGS),
282 ("0.69.4", "19.2.0", self.Expected.SUCCESS_WITH_WARNINGS),
283
284 ("0.69.5", "18.0.0", self.Expected.SUCCESS),
285 ("0.69.5", "19.1.0", self.Expected.SUCCESS),
286 ("0.69.5", "19.2.0", self.Expected.SUCCESS),
287
288 ("0.70.0", "18.0.0", self.Expected.SUCCESS),
289 ("0.70.0", "19.1.0", self.Expected.SUCCESS),
290 ("0.70.0", "19.2.0", self.Expected.SUCCESS),
291 ):
292 with self.subTest(bindgen_version=bindgen_version, libclang_version=libclang_version):
293 cc = self.generate_clang(f"clang version {libclang_version}")
294 libclang_stderr = f"scripts/rust_is_available_bindgen_libclang.h:2:9: warning: clang version {libclang_version} [-W#pragma-messages], err: false"
295 bindgen = self.generate_bindgen(f"bindgen {bindgen_version}", libclang_stderr)
296 result = self.run_script(expected_not_patched, { "BINDGEN": bindgen, "CC": cc })
297 if expected_not_patched == self.Expected.SUCCESS_WITH_WARNINGS:
298 self.assertIn(f"Rust bindings generator '{bindgen}' < 0.69.5 together with libclang >= 19.1", result.stderr)
299
300 bindgen = self.generate_bindgen(f"bindgen {bindgen_version}", libclang_stderr, libclang_concat_patched=True)
301 result = self.run_script(self.Expected.SUCCESS, { "BINDGEN": bindgen, "CC": cc })
302
303 def test_clang_matches_bindgen_libclang_different_bindgen(self):251 def test_clang_matches_bindgen_libclang_different_bindgen(self):
304 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")252 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")
305 result = self.run_script(self.Expected.SUCCESS_WITH_WARNINGS, { "BINDGEN": bindgen })253 result = self.run_script(self.Expected.SUCCESS_WITH_WARNINGS, { "BINDGEN": bindgen })