Commit | Line | Data |
---|---|---|
8c4555cc MO |
1 | #!/usr/bin/env python3 |
2 | # SPDX-License-Identifier: GPL-2.0 | |
3 | """generate_rust_analyzer - Generates the `rust-project.json` file for `rust-analyzer`. | |
4 | """ | |
5 | ||
6 | import argparse | |
7 | import json | |
8 | import logging | |
9 | import pathlib | |
10 | import sys | |
11 | ||
12 | def generate_crates(srctree, objtree, sysroot_src): | |
13 | # Generate the configuration list. | |
14 | cfg = [] | |
15 | with open(objtree / "include" / "generated" / "rustc_cfg") as fd: | |
16 | for line in fd: | |
17 | line = line.replace("--cfg=", "") | |
18 | line = line.replace("\n", "") | |
19 | cfg.append(line) | |
20 | ||
21 | # Now fill the crates list -- dependencies need to come first. | |
22 | # | |
23 | # Avoid O(n^2) iterations by keeping a map of indexes. | |
24 | crates = [] | |
25 | crates_indexes = {} | |
26 | ||
27 | def append_crate(display_name, root_module, deps, cfg=[], is_workspace_member=True, is_proc_macro=False): | |
28 | crates_indexes[display_name] = len(crates) | |
29 | crates.append({ | |
30 | "display_name": display_name, | |
31 | "root_module": str(root_module), | |
32 | "is_workspace_member": is_workspace_member, | |
33 | "is_proc_macro": is_proc_macro, | |
34 | "deps": [{"crate": crates_indexes[dep], "name": dep} for dep in deps], | |
35 | "cfg": cfg, | |
36 | "edition": "2021", | |
37 | "env": { | |
38 | "RUST_MODFILE": "This is only for rust-analyzer" | |
39 | } | |
40 | }) | |
41 | ||
42 | # First, the ones in `rust/` since they are a bit special. | |
43 | append_crate( | |
44 | "core", | |
45 | sysroot_src / "core" / "src" / "lib.rs", | |
46 | [], | |
47 | is_workspace_member=False, | |
48 | ) | |
49 | ||
50 | append_crate( | |
51 | "compiler_builtins", | |
52 | srctree / "rust" / "compiler_builtins.rs", | |
53 | [], | |
54 | ) | |
55 | ||
56 | append_crate( | |
57 | "alloc", | |
58 | srctree / "rust" / "alloc" / "lib.rs", | |
59 | ["core", "compiler_builtins"], | |
60 | ) | |
61 | ||
62 | append_crate( | |
63 | "macros", | |
64 | srctree / "rust" / "macros" / "lib.rs", | |
65 | [], | |
66 | is_proc_macro=True, | |
67 | ) | |
68 | crates[-1]["proc_macro_dylib_path"] = "rust/libmacros.so" | |
69 | ||
70 | append_crate( | |
71 | "bindings", | |
72 | srctree / "rust"/ "bindings" / "lib.rs", | |
73 | ["core"], | |
74 | cfg=cfg, | |
75 | ) | |
76 | crates[-1]["env"]["OBJTREE"] = str(objtree.resolve(True)) | |
77 | ||
78 | append_crate( | |
79 | "kernel", | |
80 | srctree / "rust" / "kernel" / "lib.rs", | |
81 | ["core", "alloc", "macros", "bindings"], | |
82 | cfg=cfg, | |
83 | ) | |
84 | crates[-1]["source"] = { | |
85 | "include_dirs": [ | |
86 | str(srctree / "rust" / "kernel"), | |
87 | str(objtree / "rust") | |
88 | ], | |
89 | "exclude_dirs": [], | |
90 | } | |
91 | ||
92 | # Then, the rest outside of `rust/`. | |
93 | # | |
94 | # We explicitly mention the top-level folders we want to cover. | |
95 | for folder in ("samples", "drivers"): | |
96 | for path in (srctree / folder).rglob("*.rs"): | |
97 | logging.info("Checking %s", path) | |
98 | name = path.name.replace(".rs", "") | |
99 | ||
100 | # Skip those that are not crate roots. | |
101 | if f"{name}.o" not in open(path.parent / "Makefile").read(): | |
102 | continue | |
103 | ||
104 | logging.info("Adding %s", name) | |
105 | append_crate( | |
106 | name, | |
107 | path, | |
108 | ["core", "alloc", "kernel"], | |
109 | cfg=cfg, | |
110 | ) | |
111 | ||
112 | return crates | |
113 | ||
114 | def main(): | |
115 | parser = argparse.ArgumentParser() | |
116 | parser.add_argument('--verbose', '-v', action='store_true') | |
117 | parser.add_argument("srctree", type=pathlib.Path) | |
118 | parser.add_argument("objtree", type=pathlib.Path) | |
119 | parser.add_argument("sysroot_src", type=pathlib.Path) | |
120 | args = parser.parse_args() | |
121 | ||
122 | logging.basicConfig( | |
123 | format="[%(asctime)s] [%(levelname)s] %(message)s", | |
124 | level=logging.INFO if args.verbose else logging.WARNING | |
125 | ) | |
126 | ||
127 | rust_project = { | |
128 | "crates": generate_crates(args.srctree, args.objtree, args.sysroot_src), | |
129 | "sysroot_src": str(args.sysroot_src), | |
130 | } | |
131 | ||
132 | json.dump(rust_project, sys.stdout, sort_keys=True, indent=4) | |
133 | ||
134 | if __name__ == "__main__": | |
135 | main() |