import pathlib
import subprocess
import sys
+from typing import Dict, Iterable, List, Literal, Optional, TypedDict
-def args_crates_cfgs(cfgs):
+def args_crates_cfgs(cfgs: List[str]) -> Dict[str, List[str]]:
crates_cfgs = {}
for cfg in cfgs:
crate, vals = cfg.split("=", 1)
return crates_cfgs
-def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs, core_edition):
+class Dependency(TypedDict):
+ crate: int
+ name: str
+
+
+class Source(TypedDict):
+ include_dirs: List[str]
+ exclude_dirs: List[str]
+
+
+class Crate(TypedDict):
+ display_name: str
+ root_module: str
+ is_workspace_member: bool
+ deps: List[Dependency]
+ cfg: List[str]
+ edition: str
+ env: Dict[str, str]
+
+
+class ProcMacroCrate(Crate):
+ is_proc_macro: Literal[True]
+ proc_macro_dylib_path: str # `pathlib.Path` is not JSON serializable.
+
+
+class CrateWithGenerated(Crate):
+ source: Source
+
+
+def generate_crates(
+ srctree: pathlib.Path,
+ objtree: pathlib.Path,
+ sysroot_src: pathlib.Path,
+ external_src: Optional[pathlib.Path],
+ cfgs: List[str],
+ core_edition: str,
+) -> List[Crate]:
# Generate the configuration list.
cfg = []
with open(objtree / "include" / "generated" / "rustc_cfg") as fd:
# Now fill the crates list -- dependencies need to come first.
#
# Avoid O(n^2) iterations by keeping a map of indexes.
- crates = []
- crates_indexes = {}
+ crates: List[Crate] = []
+ crates_indexes: Dict[str, int] = {}
crates_cfgs = args_crates_cfgs(cfgs)
def build_crate(
- display_name,
- root_module,
- deps,
+ display_name: str,
+ root_module: pathlib.Path,
+ deps: List[str],
*,
- cfg,
- is_workspace_member,
- edition,
- ):
+ cfg: Optional[List[str]],
+ is_workspace_member: Optional[bool],
+ edition: Optional[str],
+ ) -> Crate:
cfg = cfg if cfg is not None else []
is_workspace_member = (
is_workspace_member if is_workspace_member is not None else True
}
def append_proc_macro_crate(
- display_name,
- root_module,
- deps,
+ display_name: str,
+ root_module: pathlib.Path,
+ deps: List[str],
*,
- cfg=None,
- is_workspace_member=None,
- edition=None,
- ):
+ cfg: Optional[List[str]] = None,
+ is_workspace_member: Optional[bool] = None,
+ edition: Optional[str] = None,
+ ) -> None:
crate = build_crate(
display_name,
root_module,
.decode("utf-8")
.strip()
)
- proc_macro_crate = {
+ proc_macro_crate: ProcMacroCrate = {
**crate,
"is_proc_macro": True,
"proc_macro_dylib_path": str(objtree / "rust" / proc_macro_dylib_name),
}
return register_crate(proc_macro_crate)
- def register_crate(crate):
+ def register_crate(crate: Crate) -> None:
crates_indexes[crate["display_name"]] = len(crates)
crates.append(crate)
def append_crate(
- display_name,
- root_module,
- deps,
+ display_name: str,
+ root_module: pathlib.Path,
+ deps: List[str],
*,
- cfg=None,
- is_workspace_member=None,
- edition=None,
- ):
+ cfg: Optional[List[str]] = None,
+ is_workspace_member: Optional[bool] = None,
+ edition: Optional[str] = None,
+ ) -> None:
return register_crate(
build_crate(
display_name,
)
def append_sysroot_crate(
- display_name,
- deps,
+ display_name: str,
+ deps: List[str],
*,
- cfg=None,
- ):
+ cfg: Optional[List[str]] = None,
+ ) -> None:
return append_crate(
display_name,
sysroot_src / display_name / "src" / "lib.rs",
)
def append_crate_with_generated(
- display_name,
- deps,
- ):
+ display_name: str,
+ deps: List[str],
+ ) -> None:
crate = build_crate(
display_name,
srctree / "rust"/ display_name / "lib.rs",
edition=None,
)
crate["env"]["OBJTREE"] = str(objtree.resolve(True))
- crate_with_generated = {
+ crate_with_generated: CrateWithGenerated = {
**crate,
"source": {
"include_dirs": [
append_crate_with_generated("uapi", ["core", "ffi", "pin_init"])
append_crate_with_generated("kernel", ["core", "macros", "build_error", "pin_init", "ffi", "bindings", "uapi"])
- def is_root_crate(build_file, target):
+ def is_root_crate(build_file: pathlib.Path, target: str) -> bool:
try:
return f"{target}.o" in open(build_file).read()
except FileNotFoundError:
# Then, the rest outside of `rust/`.
#
# We explicitly mention the top-level folders we want to cover.
- extra_dirs = map(lambda dir: srctree / dir, ("samples", "drivers"))
+ extra_dirs: Iterable[pathlib.Path] = (
+ srctree / dir for dir in ("samples", "drivers")
+ )
if external_src is not None:
extra_dirs = [external_src]
for folder in extra_dirs:
return crates
-def main():
+def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument('--verbose', '-v', action='store_true')
parser.add_argument('--cfgs', action='append', default=[])
parser.add_argument("sysroot", type=pathlib.Path)
parser.add_argument("sysroot_src", type=pathlib.Path)
parser.add_argument("exttree", type=pathlib.Path, nargs="?")
- args = parser.parse_args()
+
+ class Args(argparse.Namespace):
+ verbose: bool
+ cfgs: List[str]
+ srctree: pathlib.Path
+ objtree: pathlib.Path
+ sysroot: pathlib.Path
+ sysroot_src: pathlib.Path
+ exttree: Optional[pathlib.Path]
+ core_edition: str
+
+ args = parser.parse_args(namespace=Args())
logging.basicConfig(
format="[%(asctime)s] [%(levelname)s] %(message)s",