scripts/generate_rust_analyzer.py | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-)
From: Jesung Yang <y.j3ms.n@gmail.com>
Use the `cfg_groups` field to aggregate common configurations into a
single project-level definition. This avoids repeating identical `cfg`s
across crates.
As a result, the size of the generated `rust-project.json` is reduced
from 11MiB to 406KiB (about 96% reduction).
Signed-off-by: Jesung Yang <y.j3ms.n@gmail.com>
---
This patch depends on [1] to ensure it merges cleanly without conflicts.
[1] https://lore.kernel.org/rust-for-linux/20260101-ra-fix-primitive-v1-1-def809357b4e@gmail.com/
---
scripts/generate_rust_analyzer.py | 34 ++++++++++++++++++++--------------
1 file changed, 20 insertions(+), 14 deletions(-)
diff --git a/scripts/generate_rust_analyzer.py b/scripts/generate_rust_analyzer.py
index 6178a53516ec35f308897e65c5001edd81b0d3dd..2a8578fb784d08b2a5e628bfab935080759d2dce 100755
--- a/scripts/generate_rust_analyzer.py
+++ b/scripts/generate_rust_analyzer.py
@@ -19,15 +19,7 @@ def args_crates_cfgs(cfgs):
return crates_cfgs
-def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs):
- # Generate the configuration list.
- cfg = []
- with open(objtree / "include" / "generated" / "rustc_cfg") as fd:
- for line in fd:
- line = line.replace("--cfg=", "")
- line = line.replace("\n", "")
- cfg.append(line)
-
+def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs, kernel_cfg_group):
# Now fill the crates list -- dependencies need to come first.
#
# Avoid O(n^2) iterations by keeping a map of indexes.
@@ -35,7 +27,7 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs):
crates_indexes = {}
crates_cfgs = args_crates_cfgs(cfgs)
- def append_crate(display_name, root_module, deps, cfg=[], crate_attrs=[], is_workspace_member=True, is_proc_macro=False, edition="2021"):
+ def append_crate(display_name, root_module, deps, cfg=[], cfg_groups=[], crate_attrs=[], is_workspace_member=True, is_proc_macro=False, edition="2021"):
crate = {
"display_name": display_name,
"root_module": str(root_module),
@@ -48,6 +40,8 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs):
"RUST_MODFILE": "This is only for rust-analyzer"
}
}
+ if len(cfg_groups) > 0:
+ crate["cfg_groups"] = cfg_groups
if len(crate_attrs) > 0:
crate["crate_attrs"] = crate_attrs
if is_proc_macro:
@@ -134,7 +128,7 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs):
display_name,
srctree / "rust"/ display_name / "lib.rs",
deps,
- cfg=cfg,
+ cfg_groups=[kernel_cfg_group],
crate_attrs=crate_attrs,
)
crates[-1]["env"]["OBJTREE"] = str(objtree.resolve(True))
@@ -189,7 +183,7 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs):
name,
path,
["kernel"],
- cfg=cfg,
+ cfg_groups=[kernel_cfg_group],
crate_attrs=["no_std"],
)
@@ -214,10 +208,22 @@ def main():
# Making sure that the `sysroot` and `sysroot_src` belong to the same toolchain.
assert args.sysroot in args.sysroot_src.parents
+ # Generate the configuration list.
+ cfg = []
+ with open(args.objtree / "include" / "generated" / "rustc_cfg") as fd:
+ for line in fd:
+ line = line.replace("--cfg=", "")
+ line = line.replace("\n", "")
+ cfg.append(line)
+ kernel_cfg_group = "kernel"
+
rust_project = {
- "crates": generate_crates(args.srctree, args.objtree, args.sysroot_src, args.exttree, args.cfgs),
+ "crates": generate_crates(args.srctree, args.objtree, args.sysroot_src, args.exttree, args.cfgs, kernel_cfg_group),
"sysroot": str(args.sysroot),
- "sysroot_src": str(args.sysroot_src)
+ "sysroot_src": str(args.sysroot_src),
+ "cfg_groups": {
+ kernel_cfg_group: cfg,
+ },
}
json.dump(rust_project, sys.stdout, sort_keys=True, indent=4)
---
base-commit: f8f9c1f4d0c7a64600e2ca312dec824a0bc2f1da
change-id: 20260101-rust-project-reduce-size-d829a7a708ae
prerequisite-change-id: 20260101-ra-fix-primitive-78154fe8173f:v1
prerequisite-patch-id: 0544fdf5522949047a81c3580960183375574fd3
Best regards,
--
Jesung Yang <y.j3ms.n@gmail.com>
On Thu, Jan 1, 2026 at 3:22 AM Jesung Yang via B4 Relay
<devnull+y.j3ms.n.gmail.com@kernel.org> wrote:
>
> From: Jesung Yang <y.j3ms.n@gmail.com>
>
> Use the `cfg_groups` field to aggregate common configurations into a
> single project-level definition. This avoids repeating identical `cfg`s
> across crates.
>
> As a result, the size of the generated `rust-project.json` is reduced
> from 11MiB to 406KiB (about 96% reduction).
>
> Signed-off-by: Jesung Yang <y.j3ms.n@gmail.com>
> ---
> This patch depends on [1] to ensure it merges cleanly without conflicts.
>
> [1] https://lore.kernel.org/rust-for-linux/20260101-ra-fix-primitive-v1-1-def809357b4e@gmail.com/
> ---
> scripts/generate_rust_analyzer.py | 34 ++++++++++++++++++++--------------
> 1 file changed, 20 insertions(+), 14 deletions(-)
>
> diff --git a/scripts/generate_rust_analyzer.py b/scripts/generate_rust_analyzer.py
> index 6178a53516ec35f308897e65c5001edd81b0d3dd..2a8578fb784d08b2a5e628bfab935080759d2dce 100755
> --- a/scripts/generate_rust_analyzer.py
> +++ b/scripts/generate_rust_analyzer.py
> @@ -19,15 +19,7 @@ def args_crates_cfgs(cfgs):
>
> return crates_cfgs
>
> -def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs):
> - # Generate the configuration list.
> - cfg = []
> - with open(objtree / "include" / "generated" / "rustc_cfg") as fd:
> - for line in fd:
> - line = line.replace("--cfg=", "")
> - line = line.replace("\n", "")
> - cfg.append(line)
> -
> +def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs, kernel_cfg_group):
> # Now fill the crates list -- dependencies need to come first.
> #
> # Avoid O(n^2) iterations by keeping a map of indexes.
> @@ -35,7 +27,7 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs):
> crates_indexes = {}
> crates_cfgs = args_crates_cfgs(cfgs)
>
> - def append_crate(display_name, root_module, deps, cfg=[], crate_attrs=[], is_workspace_member=True, is_proc_macro=False, edition="2021"):
> + def append_crate(display_name, root_module, deps, cfg=[], cfg_groups=[], crate_attrs=[], is_workspace_member=True, is_proc_macro=False, edition="2021"):
> crate = {
> "display_name": display_name,
> "root_module": str(root_module),
> @@ -48,6 +40,8 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs):
> "RUST_MODFILE": "This is only for rust-analyzer"
> }
> }
> + if len(cfg_groups) > 0:
> + crate["cfg_groups"] = cfg_groups
> if len(crate_attrs) > 0:
> crate["crate_attrs"] = crate_attrs
> if is_proc_macro:
> @@ -134,7 +128,7 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs):
> display_name,
> srctree / "rust"/ display_name / "lib.rs",
> deps,
> - cfg=cfg,
> + cfg_groups=[kernel_cfg_group],
> crate_attrs=crate_attrs,
> )
> crates[-1]["env"]["OBJTREE"] = str(objtree.resolve(True))
> @@ -189,7 +183,7 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs):
> name,
> path,
> ["kernel"],
> - cfg=cfg,
> + cfg_groups=[kernel_cfg_group],
> crate_attrs=["no_std"],
> )
>
> @@ -214,10 +208,22 @@ def main():
> # Making sure that the `sysroot` and `sysroot_src` belong to the same toolchain.
> assert args.sysroot in args.sysroot_src.parents
>
> + # Generate the configuration list.
> + cfg = []
> + with open(args.objtree / "include" / "generated" / "rustc_cfg") as fd:
> + for line in fd:
> + line = line.replace("--cfg=", "")
> + line = line.replace("\n", "")
> + cfg.append(line)
> + kernel_cfg_group = "kernel"
> +
> rust_project = {
> - "crates": generate_crates(args.srctree, args.objtree, args.sysroot_src, args.exttree, args.cfgs),
> + "crates": generate_crates(args.srctree, args.objtree, args.sysroot_src, args.exttree, args.cfgs, kernel_cfg_group),
> "sysroot": str(args.sysroot),
> - "sysroot_src": str(args.sysroot_src)
> + "sysroot_src": str(args.sysroot_src),
> + "cfg_groups": {
> + kernel_cfg_group: cfg,
> + },
> }
>
> json.dump(rust_project, sys.stdout, sort_keys=True, indent=4)
>
> ---
> base-commit: f8f9c1f4d0c7a64600e2ca312dec824a0bc2f1da
> change-id: 20260101-rust-project-reduce-size-d829a7a708ae
> prerequisite-change-id: 20260101-ra-fix-primitive-78154fe8173f:v1
> prerequisite-patch-id: 0544fdf5522949047a81c3580960183375574fd3
>
> Best regards,
> --
> Jesung Yang <y.j3ms.n@gmail.com>
FWIW this was previously sent in
https://lore.kernel.org/all/20250424-rust-analyzer-host-v6-13-40e67fe5c38a@gmail.com/
back in April.
On Thu, 01 Jan 2026 08:21:24 +0000
Jesung Yang via B4 Relay <devnull+y.j3ms.n.gmail.com@kernel.org> wrote:
> From: Jesung Yang <y.j3ms.n@gmail.com>
>
> Use the `cfg_groups` field to aggregate common configurations into a
> single project-level definition. This avoids repeating identical `cfg`s
> across crates.
>
> As a result, the size of the generated `rust-project.json` is reduced
> from 11MiB to 406KiB (about 96% reduction).
This feature is not available with Rust Analyzer 1.78.
Best,
Gary
>
> Signed-off-by: Jesung Yang <y.j3ms.n@gmail.com>
> ---
> This patch depends on [1] to ensure it merges cleanly without conflicts.
>
> [1] https://lore.kernel.org/rust-for-linux/20260101-ra-fix-primitive-v1-1-def809357b4e@gmail.com/
> ---
> scripts/generate_rust_analyzer.py | 34 ++++++++++++++++++++--------------
> 1 file changed, 20 insertions(+), 14 deletions(-)
>
> diff --git a/scripts/generate_rust_analyzer.py b/scripts/generate_rust_analyzer.py
> index 6178a53516ec35f308897e65c5001edd81b0d3dd..2a8578fb784d08b2a5e628bfab935080759d2dce 100755
> --- a/scripts/generate_rust_analyzer.py
> +++ b/scripts/generate_rust_analyzer.py
> @@ -19,15 +19,7 @@ def args_crates_cfgs(cfgs):
>
> return crates_cfgs
>
> -def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs):
> - # Generate the configuration list.
> - cfg = []
> - with open(objtree / "include" / "generated" / "rustc_cfg") as fd:
> - for line in fd:
> - line = line.replace("--cfg=", "")
> - line = line.replace("\n", "")
> - cfg.append(line)
> -
> +def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs, kernel_cfg_group):
> # Now fill the crates list -- dependencies need to come first.
> #
> # Avoid O(n^2) iterations by keeping a map of indexes.
> @@ -35,7 +27,7 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs):
> crates_indexes = {}
> crates_cfgs = args_crates_cfgs(cfgs)
>
> - def append_crate(display_name, root_module, deps, cfg=[], crate_attrs=[], is_workspace_member=True, is_proc_macro=False, edition="2021"):
> + def append_crate(display_name, root_module, deps, cfg=[], cfg_groups=[], crate_attrs=[], is_workspace_member=True, is_proc_macro=False, edition="2021"):
> crate = {
> "display_name": display_name,
> "root_module": str(root_module),
> @@ -48,6 +40,8 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs):
> "RUST_MODFILE": "This is only for rust-analyzer"
> }
> }
> + if len(cfg_groups) > 0:
> + crate["cfg_groups"] = cfg_groups
> if len(crate_attrs) > 0:
> crate["crate_attrs"] = crate_attrs
> if is_proc_macro:
> @@ -134,7 +128,7 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs):
> display_name,
> srctree / "rust"/ display_name / "lib.rs",
> deps,
> - cfg=cfg,
> + cfg_groups=[kernel_cfg_group],
> crate_attrs=crate_attrs,
> )
> crates[-1]["env"]["OBJTREE"] = str(objtree.resolve(True))
> @@ -189,7 +183,7 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs):
> name,
> path,
> ["kernel"],
> - cfg=cfg,
> + cfg_groups=[kernel_cfg_group],
> crate_attrs=["no_std"],
> )
>
> @@ -214,10 +208,22 @@ def main():
> # Making sure that the `sysroot` and `sysroot_src` belong to the same toolchain.
> assert args.sysroot in args.sysroot_src.parents
>
> + # Generate the configuration list.
> + cfg = []
> + with open(args.objtree / "include" / "generated" / "rustc_cfg") as fd:
> + for line in fd:
> + line = line.replace("--cfg=", "")
> + line = line.replace("\n", "")
> + cfg.append(line)
> + kernel_cfg_group = "kernel"
> +
> rust_project = {
> - "crates": generate_crates(args.srctree, args.objtree, args.sysroot_src, args.exttree, args.cfgs),
> + "crates": generate_crates(args.srctree, args.objtree, args.sysroot_src, args.exttree, args.cfgs, kernel_cfg_group),
> "sysroot": str(args.sysroot),
> - "sysroot_src": str(args.sysroot_src)
> + "sysroot_src": str(args.sysroot_src),
> + "cfg_groups": {
> + kernel_cfg_group: cfg,
> + },
> }
>
> json.dump(rust_project, sys.stdout, sort_keys=True, indent=4)
>
> ---
> base-commit: f8f9c1f4d0c7a64600e2ca312dec824a0bc2f1da
> change-id: 20260101-rust-project-reduce-size-d829a7a708ae
> prerequisite-change-id: 20260101-ra-fix-primitive-78154fe8173f:v1
> prerequisite-patch-id: 0544fdf5522949047a81c3580960183375574fd3
>
> Best regards,
On Fri, Jan 2, 2026 at 7:09 AM Gary Guo <gary@garyguo.net> wrote: > > On Thu, 01 Jan 2026 08:21:24 +0000 > Jesung Yang via B4 Relay <devnull+y.j3ms.n.gmail.com@kernel.org> wrote: > > > From: Jesung Yang <y.j3ms.n@gmail.com> > > > > Use the `cfg_groups` field to aggregate common configurations into a > > single project-level definition. This avoids repeating identical `cfg`s > > across crates. > > > > As a result, the size of the generated `rust-project.json` is reduced > > from 11MiB to 406KiB (about 96% reduction). > > This feature is not available with Rust Analyzer 1.78. I suspect you are referring to the rust-analyzer component shipped via rustup when the 1.78 toolchain is active. Do we apply our MSRV policy to rust-analyzer as well? The latest rust-analyzer release supports older Rust versions, including 1.78. In practice, I believe many people who rely on a language server use the version provided by their editor extension or IDE, which is usually the most recent release. AFAIK, it is actually more difficult to use an old release of rust-analyzer, as it often requires extra setup to manually downgrade or pin the version. By the way, thanks for pointing this out! Best regards, Jesung
On Fri, 2 Jan 2026 10:04:08 +0900 Jesung Yang <y.j3ms.n@gmail.com> wrote: > On Fri, Jan 2, 2026 at 7:09 AM Gary Guo <gary@garyguo.net> wrote: > > > > On Thu, 01 Jan 2026 08:21:24 +0000 > > Jesung Yang via B4 Relay <devnull+y.j3ms.n.gmail.com@kernel.org> wrote: > > > > > From: Jesung Yang <y.j3ms.n@gmail.com> > > > > > > Use the `cfg_groups` field to aggregate common configurations into a > > > single project-level definition. This avoids repeating identical `cfg`s > > > across crates. > > > > > > As a result, the size of the generated `rust-project.json` is reduced > > > from 11MiB to 406KiB (about 96% reduction). > > > > This feature is not available with Rust Analyzer 1.78. > > I suspect you are referring to the rust-analyzer component shipped via > rustup when the 1.78 toolchain is active. > > Do we apply our MSRV policy to rust-analyzer as well? The latest > rust-analyzer release supports older Rust versions, including 1.78. This statement is not generally true. Rust analyzer needs the ability to talk directly with proc macro dylibs and AFAIK it only retains limited backward compatibility with old rustc versions. https://rust-analyzer.github.io/book/installation.html also mentions that the only officially supported version is the latest stable and users are recommended to use older Rust analyzer versions with older compilers. > practice, I believe many people who rely on a language server use the > version provided by their editor extension or IDE, which is usually the > most recent release. AFAIK, it is actually more difficult to use an old > release of rust-analyzer, as it often requires extra setup to manually > downgrade or pin the version. Many editors just use rust analyzer binaries in the PATH, which can quite often be the one provided by rustup. I guess the "IDE" you're talking about here is VSCode, and I just configure it to use the one in path too, instead of the binary shipped with the extension. This the Rust analyzer version string of the one that I am using: rust-analyzer 1.78.0 (9b00956 2024-04-29) So I'd say while your change is desired, we need to wait until we bump MSRV to a high enough version as I suspect there're a lot more developers that use Rust analyzer in the same way I do. Best, Gary
On Fri, Jan 2, 2026 at 7:36 PM Gary Guo <gary@garyguo.net> wrote: > > On Fri, 2 Jan 2026 10:04:08 +0900 > Jesung Yang <y.j3ms.n@gmail.com> wrote: > > > On Fri, Jan 2, 2026 at 7:09 AM Gary Guo <gary@garyguo.net> wrote: > > > > > > On Thu, 01 Jan 2026 08:21:24 +0000 > > > Jesung Yang via B4 Relay <devnull+y.j3ms.n.gmail.com@kernel.org> wrote: > > > > > > > From: Jesung Yang <y.j3ms.n@gmail.com> > > > > > > > > Use the `cfg_groups` field to aggregate common configurations into a > > > > single project-level definition. This avoids repeating identical `cfg`s > > > > across crates. > > > > > > > > As a result, the size of the generated `rust-project.json` is reduced > > > > from 11MiB to 406KiB (about 96% reduction). > > > > > > This feature is not available with Rust Analyzer 1.78. > > > > I suspect you are referring to the rust-analyzer component shipped via > > rustup when the 1.78 toolchain is active. > > > > Do we apply our MSRV policy to rust-analyzer as well? The latest > > rust-analyzer release supports older Rust versions, including 1.78. > > This statement is not generally true. Rust analyzer needs the ability to > talk directly with proc macro dylibs and AFAIK it only retains limited > backward compatibility with old rustc versions. > > https://rust-analyzer.github.io/book/installation.html also mentions that > the only officially supported version is the latest stable and users are > recommended to use older Rust analyzer versions with older compilers. You're right, I missed that point. > > practice, I believe many people who rely on a language server use the > > version provided by their editor extension or IDE, which is usually the > > most recent release. AFAIK, it is actually more difficult to use an old > > release of rust-analyzer, as it often requires extra setup to manually > > downgrade or pin the version. > > Many editors just use rust analyzer binaries in the PATH, which can quite > often be the one provided by rustup. I guess the "IDE" you're talking > about here is VSCode, and I just configure it to use the one in path too, > instead of the binary shipped with the extension. > > This the Rust analyzer version string of the one that I am using: > > rust-analyzer 1.78.0 (9b00956 2024-04-29) > > So I'd say while your change is desired, we need to wait until we bump > MSRV to a high enough version as I suspect there're a lot more developers > that use Rust analyzer in the same way I do. Overall, I think I overlooked the diversity of local setups; I was indeed focused on the VSCode extension's default behavior. Thanks! Best regards, Jesung
On Fri, Jan 2, 2026 at 11:36 AM Gary Guo <gary@garyguo.net> wrote: > > So I'd say while your change is desired, we need to wait until we bump > MSRV to a high enough version as I suspect there're a lot more developers > that use Rust analyzer in the same way I do. Yeah, distributions likely provide the rust-analyzer that works well with their `rustc`, thus older ones in some cases. Perhaps we should support several versions, just like for the rest of the toolchain, i.e. query the version in the Python script and act based on that. Cheers, Miguel
On Fri, Jan 2, 2026 at 7:56 PM Miguel Ojeda <miguel.ojeda.sandonis@gmail.com> wrote: [...] > > Perhaps we should support several versions, just like for the rest of > the toolchain, i.e. query the version in the Python script and act > based on that. I could give that a try if you feel the benefits of supporting multiple versions justify the added maintenance burden. Best regards, Jesung
© 2016 - 2026 Red Hat, Inc.