Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'rust-analyzer-v7.1' of https://github.com/Rust-for-Linux/linux into rust-next

Pull rust-analyzer updates from Tamir Duberstein:

- 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.

* tag 'rust-analyzer-v7.1' of https://github.com/Rust-for-Linux/linux:
scripts: generate_rust_analyzer.py: reduce cfg plumbing
scripts: generate_rust_analyzer.py: rename cfg to generated_cfg
scripts: generate_rust_analyzer.py: avoid FD leak
scripts: generate_rust_analyzer.py: define scripts
scripts: generate_rust_analyzer.py: identify crates explicitly
scripts: generate_rust_analyzer.py: add type hints
scripts: generate_rust_analyzer.py: drop `"is_proc_macro": false`
scripts: generate_rust_analyzer.py: extract `{build,register}_crate`

+211 -77
+2
rust/Makefile
··· 610 610 --cfgs='proc_macro2=$(proc_macro2-cfgs)' \ 611 611 --cfgs='quote=$(quote-cfgs)' \ 612 612 --cfgs='syn=$(syn-cfgs)' \ 613 + --cfgs='pin_init_internal=$(pin_init_internal-cfgs)' \ 614 + --cfgs='pin_init=$(pin_init-cfgs)' \ 613 615 $(realpath $(srctree)) $(realpath $(objtree)) \ 614 616 $(rustc_sysroot) $(RUST_LIB_SRC) $(if $(KBUILD_EXTMOD),$(srcroot)) \ 615 617 > rust-project.json
+209 -77
scripts/generate_rust_analyzer.py
··· 10 10 import pathlib 11 11 import subprocess 12 12 import sys 13 + from typing import Dict, Iterable, List, Literal, Optional, TypedDict 13 14 14 - def args_crates_cfgs(cfgs): 15 + def args_crates_cfgs(cfgs: List[str]) -> Dict[str, List[str]]: 15 16 crates_cfgs = {} 16 17 for cfg in cfgs: 17 18 crate, vals = cfg.split("=", 1) ··· 20 19 21 20 return crates_cfgs 22 21 23 - def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs, core_edition): 22 + class Dependency(TypedDict): 23 + crate: int 24 + name: str 25 + 26 + 27 + class Source(TypedDict): 28 + include_dirs: List[str] 29 + exclude_dirs: List[str] 30 + 31 + 32 + class Crate(TypedDict): 33 + display_name: str 34 + root_module: str 35 + is_workspace_member: bool 36 + deps: List[Dependency] 37 + cfg: List[str] 38 + edition: str 39 + env: Dict[str, str] 40 + 41 + 42 + class ProcMacroCrate(Crate): 43 + is_proc_macro: Literal[True] 44 + proc_macro_dylib_path: str # `pathlib.Path` is not JSON serializable. 45 + 46 + 47 + class CrateWithGenerated(Crate): 48 + source: Source 49 + 50 + 51 + def generate_crates( 52 + srctree: pathlib.Path, 53 + objtree: pathlib.Path, 54 + sysroot_src: pathlib.Path, 55 + external_src: Optional[pathlib.Path], 56 + cfgs: List[str], 57 + core_edition: str, 58 + ) -> List[Crate]: 24 59 # Generate the configuration list. 25 - cfg = [] 60 + generated_cfg = [] 26 61 with open(objtree / "include" / "generated" / "rustc_cfg") as fd: 27 62 for line in fd: 28 63 line = line.replace("--cfg=", "") 29 64 line = line.replace("\n", "") 30 - cfg.append(line) 65 + generated_cfg.append(line) 31 66 32 - # Now fill the crates list -- dependencies need to come first. 33 - # 34 - # Avoid O(n^2) iterations by keeping a map of indexes. 35 - crates = [] 36 - crates_indexes = {} 67 + # Now fill the crates list. 68 + crates: List[Crate] = [] 37 69 crates_cfgs = args_crates_cfgs(cfgs) 38 70 39 - def append_crate(display_name, root_module, deps, cfg=[], is_workspace_member=True, is_proc_macro=False, edition="2021"): 40 - crate = { 71 + def build_crate( 72 + display_name: str, 73 + root_module: pathlib.Path, 74 + deps: List[Dependency], 75 + *, 76 + cfg: Optional[List[str]], 77 + is_workspace_member: Optional[bool], 78 + edition: Optional[str], 79 + ) -> Crate: 80 + cfg = cfg if cfg is not None else crates_cfgs.get(display_name, []) 81 + is_workspace_member = ( 82 + is_workspace_member if is_workspace_member is not None else True 83 + ) 84 + edition = edition if edition is not None else "2021" 85 + return { 41 86 "display_name": display_name, 42 87 "root_module": str(root_module), 43 88 "is_workspace_member": is_workspace_member, 44 - "is_proc_macro": is_proc_macro, 45 - "deps": [{"crate": crates_indexes[dep], "name": dep} for dep in deps], 89 + "deps": deps, 46 90 "cfg": cfg, 47 91 "edition": edition, 48 92 "env": { 49 93 "RUST_MODFILE": "This is only for rust-analyzer" 50 94 } 51 95 } 52 - if is_proc_macro: 53 - proc_macro_dylib_name = subprocess.check_output( 54 - [os.environ["RUSTC"], "--print", "file-names", "--crate-name", display_name, "--crate-type", "proc-macro", "-"], 96 + 97 + def append_proc_macro_crate( 98 + display_name: str, 99 + root_module: pathlib.Path, 100 + deps: List[Dependency], 101 + *, 102 + cfg: Optional[List[str]] = None, 103 + is_workspace_member: Optional[bool] = None, 104 + edition: Optional[str] = None, 105 + ) -> Dependency: 106 + crate = build_crate( 107 + display_name, 108 + root_module, 109 + deps, 110 + cfg=cfg, 111 + is_workspace_member=is_workspace_member, 112 + edition=edition, 113 + ) 114 + proc_macro_dylib_name = ( 115 + subprocess.check_output( 116 + [ 117 + os.environ["RUSTC"], 118 + "--print", 119 + "file-names", 120 + "--crate-name", 121 + display_name, 122 + "--crate-type", 123 + "proc-macro", 124 + "-", 125 + ], 55 126 stdin=subprocess.DEVNULL, 56 - ).decode('utf-8').strip() 57 - crate["proc_macro_dylib_path"] = f"{objtree}/rust/{proc_macro_dylib_name}" 58 - crates_indexes[display_name] = len(crates) 127 + ) 128 + .decode("utf-8") 129 + .strip() 130 + ) 131 + proc_macro_crate: ProcMacroCrate = { 132 + **crate, 133 + "is_proc_macro": True, 134 + "proc_macro_dylib_path": str(objtree / "rust" / proc_macro_dylib_name), 135 + } 136 + return register_crate(proc_macro_crate) 137 + 138 + def register_crate(crate: Crate) -> Dependency: 139 + index = len(crates) 59 140 crates.append(crate) 141 + return {"crate": index, "name": crate["display_name"]} 142 + 143 + def append_crate( 144 + display_name: str, 145 + root_module: pathlib.Path, 146 + deps: List[Dependency], 147 + *, 148 + cfg: Optional[List[str]] = None, 149 + is_workspace_member: Optional[bool] = None, 150 + edition: Optional[str] = None, 151 + ) -> Dependency: 152 + return register_crate( 153 + build_crate( 154 + display_name, 155 + root_module, 156 + deps, 157 + cfg=cfg, 158 + is_workspace_member=is_workspace_member, 159 + edition=edition, 160 + ) 161 + ) 60 162 61 163 def append_sysroot_crate( 62 - display_name, 63 - deps, 64 - cfg=[], 65 - ): 66 - append_crate( 164 + display_name: str, 165 + deps: List[Dependency], 166 + *, 167 + cfg: Optional[List[str]] = None, 168 + ) -> Dependency: 169 + return append_crate( 67 170 display_name, 68 171 sysroot_src / display_name / "src" / "lib.rs", 69 172 deps, 70 - cfg, 173 + cfg=cfg, 71 174 is_workspace_member=False, 72 175 # Miguel Ojeda writes: 73 176 # ··· 203 98 # NB: sysroot crates reexport items from one another so setting up our transitive dependencies 204 99 # here is important for ensuring that rust-analyzer can resolve symbols. The sources of truth 205 100 # for this dependency graph are `(sysroot_src / crate / "Cargo.toml" for crate in crates)`. 206 - append_sysroot_crate("core", [], cfg=crates_cfgs.get("core", [])) 207 - append_sysroot_crate("alloc", ["core"]) 208 - append_sysroot_crate("std", ["alloc", "core"]) 209 - append_sysroot_crate("proc_macro", ["core", "std"]) 101 + core = append_sysroot_crate("core", []) 102 + alloc = append_sysroot_crate("alloc", [core]) 103 + std = append_sysroot_crate("std", [alloc, core]) 104 + proc_macro = append_sysroot_crate("proc_macro", [core, std]) 210 105 211 - append_crate( 106 + compiler_builtins = append_crate( 212 107 "compiler_builtins", 213 108 srctree / "rust" / "compiler_builtins.rs", 214 - ["core"], 109 + [core], 215 110 ) 216 111 217 - append_crate( 112 + proc_macro2 = append_crate( 218 113 "proc_macro2", 219 114 srctree / "rust" / "proc-macro2" / "lib.rs", 220 - ["core", "alloc", "std", "proc_macro"], 221 - cfg=crates_cfgs["proc_macro2"], 115 + [core, alloc, std, proc_macro], 222 116 ) 223 117 224 - append_crate( 118 + quote = append_crate( 225 119 "quote", 226 120 srctree / "rust" / "quote" / "lib.rs", 227 - ["core", "alloc", "std", "proc_macro", "proc_macro2"], 228 - cfg=crates_cfgs["quote"], 121 + [core, alloc, std, proc_macro, proc_macro2], 229 122 edition="2018", 230 123 ) 231 124 232 - append_crate( 125 + syn = append_crate( 233 126 "syn", 234 127 srctree / "rust" / "syn" / "lib.rs", 235 - ["std", "proc_macro", "proc_macro2", "quote"], 236 - cfg=crates_cfgs["syn"], 128 + [std, proc_macro, proc_macro2, quote], 237 129 ) 238 130 239 - append_crate( 131 + macros = append_proc_macro_crate( 240 132 "macros", 241 133 srctree / "rust" / "macros" / "lib.rs", 242 - ["std", "proc_macro", "proc_macro2", "quote", "syn"], 243 - is_proc_macro=True, 134 + [std, proc_macro, proc_macro2, quote, syn], 244 135 ) 245 136 246 - append_crate( 137 + build_error = append_crate( 247 138 "build_error", 248 139 srctree / "rust" / "build_error.rs", 249 - ["core", "compiler_builtins"], 140 + [core, compiler_builtins], 250 141 ) 251 142 252 - append_crate( 143 + pin_init_internal = append_proc_macro_crate( 253 144 "pin_init_internal", 254 145 srctree / "rust" / "pin-init" / "internal" / "src" / "lib.rs", 255 - ["std", "proc_macro", "proc_macro2", "quote", "syn"], 256 - cfg=["kernel"], 257 - is_proc_macro=True, 146 + [std, proc_macro, proc_macro2, quote, syn], 258 147 ) 259 148 260 - append_crate( 149 + pin_init = append_crate( 261 150 "pin_init", 262 151 srctree / "rust" / "pin-init" / "src" / "lib.rs", 263 - ["core", "compiler_builtins", "pin_init_internal", "macros"], 264 - cfg=["kernel"], 152 + [core, compiler_builtins, pin_init_internal, macros], 265 153 ) 266 154 267 - append_crate( 155 + ffi = append_crate( 268 156 "ffi", 269 157 srctree / "rust" / "ffi.rs", 270 - ["core", "compiler_builtins"], 158 + [core, compiler_builtins], 271 159 ) 272 160 273 161 def append_crate_with_generated( 274 - display_name, 275 - deps, 276 - ): 277 - append_crate( 162 + display_name: str, 163 + deps: List[Dependency], 164 + ) -> Dependency: 165 + crate = build_crate( 278 166 display_name, 279 167 srctree / "rust"/ display_name / "lib.rs", 280 168 deps, 281 - cfg=cfg, 169 + cfg=generated_cfg, 170 + is_workspace_member=True, 171 + edition=None, 282 172 ) 283 - crates[-1]["env"]["OBJTREE"] = str(objtree.resolve(True)) 284 - crates[-1]["source"] = { 285 - "include_dirs": [ 286 - str(srctree / "rust" / display_name), 287 - str(objtree / "rust") 288 - ], 289 - "exclude_dirs": [], 173 + crate["env"]["OBJTREE"] = str(objtree.resolve(True)) 174 + crate_with_generated: CrateWithGenerated = { 175 + **crate, 176 + "source": { 177 + "include_dirs": [ 178 + str(srctree / "rust" / display_name), 179 + str(objtree / "rust"), 180 + ], 181 + "exclude_dirs": [], 182 + }, 290 183 } 184 + return register_crate(crate_with_generated) 291 185 292 - append_crate_with_generated("bindings", ["core", "ffi", "pin_init"]) 293 - append_crate_with_generated("uapi", ["core", "ffi", "pin_init"]) 294 - append_crate_with_generated("kernel", ["core", "macros", "build_error", "pin_init", "ffi", "bindings", "uapi"]) 186 + bindings = append_crate_with_generated("bindings", [core, ffi, pin_init]) 187 + uapi = append_crate_with_generated("uapi", [core, ffi, pin_init]) 188 + kernel = append_crate_with_generated( 189 + "kernel", [core, macros, build_error, pin_init, ffi, bindings, uapi] 190 + ) 295 191 296 - def is_root_crate(build_file, target): 192 + scripts = srctree / "scripts" 193 + makefile = (scripts / "Makefile").read_text() 194 + for path in scripts.glob("*.rs"): 195 + name = path.stem 196 + if f"{name}-rust" not in makefile: 197 + continue 198 + append_crate( 199 + name, 200 + path, 201 + [std], 202 + ) 203 + 204 + def is_root_crate(build_file: pathlib.Path, target: str) -> bool: 297 205 try: 298 - return f"{target}.o" in open(build_file).read() 206 + contents = build_file.read_text() 299 207 except FileNotFoundError: 300 208 return False 209 + return f"{target}.o" in contents 301 210 302 211 # Then, the rest outside of `rust/`. 303 212 # 304 213 # We explicitly mention the top-level folders we want to cover. 305 - extra_dirs = map(lambda dir: srctree / dir, ("samples", "drivers")) 214 + extra_dirs: Iterable[pathlib.Path] = ( 215 + srctree / dir for dir in ("samples", "drivers") 216 + ) 306 217 if external_src is not None: 307 218 extra_dirs = [external_src] 308 219 for folder in extra_dirs: 309 220 for path in folder.rglob("*.rs"): 310 221 logging.info("Checking %s", path) 311 - name = path.name.replace(".rs", "") 222 + name = path.stem 312 223 313 224 # Skip those that are not crate roots. 314 225 if not is_root_crate(path.parent / "Makefile", name) and \ ··· 335 214 append_crate( 336 215 name, 337 216 path, 338 - ["core", "kernel", "pin_init"], 339 - cfg=cfg, 217 + [core, kernel, pin_init], 218 + cfg=generated_cfg, 340 219 ) 341 220 342 221 return crates 343 222 344 - def main(): 223 + def main() -> None: 345 224 parser = argparse.ArgumentParser() 346 225 parser.add_argument('--verbose', '-v', action='store_true') 347 226 parser.add_argument('--cfgs', action='append', default=[]) ··· 351 230 parser.add_argument("sysroot", type=pathlib.Path) 352 231 parser.add_argument("sysroot_src", type=pathlib.Path) 353 232 parser.add_argument("exttree", type=pathlib.Path, nargs="?") 354 - args = parser.parse_args() 233 + 234 + class Args(argparse.Namespace): 235 + verbose: bool 236 + cfgs: List[str] 237 + srctree: pathlib.Path 238 + objtree: pathlib.Path 239 + sysroot: pathlib.Path 240 + sysroot_src: pathlib.Path 241 + exttree: Optional[pathlib.Path] 242 + core_edition: str 243 + 244 + args = parser.parse_args(namespace=Args()) 355 245 356 246 logging.basicConfig( 357 247 format="[%(asctime)s] [%(levelname)s] %(message)s",