from __future__ import annotations
import argparse
import logging
import os
import sys
from pathlib import Path
PROJECT_ROOT = Path(__file__).resolve().parents[1]
DEFAULT_OUTPUT = PROJECT_ROOT / ".clangd.local"
TEMPLATE = PROJECT_ROOT / ".clangd.in"
REQUIRED_DIRS = (
"asc/include",
"asc/impl",
"tools/cpudebug/lib/include",
"include/ascendc/highlevel_api",
"include/ascendc/host_api",
)
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(
description="Generate a clangd config from ASCEND_HOME_PATH for a local CANN installation."
)
parser.add_argument(
"--npu-arch",
default="2201",
choices=("2201", "3510"),
help="Value for __NPU_ARCH__.",
)
parser.add_argument(
"--output",
default=str(DEFAULT_OUTPUT),
help="Output config path. Default: .clangd.local",
)
parser.add_argument(
"-f",
"--force",
action="store_true",
help="Overwrite the output file if it already exists.",
)
return parser.parse_args()
def missing_required_dirs(ascend_home_path: Path) -> list[str]:
return [
rel_path
for rel_path in REQUIRED_DIRS
if not (ascend_home_path / rel_path).is_dir()
]
def render_template(ascend_home_path: Path, npu_arch: str) -> str:
template = TEMPLATE.read_text(encoding="utf-8")
return template.replace("@ASCEND_HOME_PATH@", ascend_home_path.as_posix()).replace(
"@NPU_ARCH@", npu_arch
)
def configure_logging() -> None:
logging.basicConfig(level=logging.INFO, format="%(message)s")
def main() -> int:
configure_logging()
args = parse_args()
ascend_home_env = os.environ.get("ASCEND_HOME_PATH")
if not ascend_home_env:
logging.error(
"ASCEND_HOME_PATH is not set. Please source CANN set_env.sh and retry."
)
return 1
ascend_home_path = Path(ascend_home_env).expanduser().resolve()
output = Path(args.output).expanduser()
if not output.is_absolute():
output = PROJECT_ROOT / output
output = output.resolve()
missing = missing_required_dirs(ascend_home_path)
if missing:
logging.error("Missing required CANN directories under ASCEND_HOME_PATH:")
for rel_path in missing:
logging.error(" - %s", ascend_home_path / rel_path)
return 1
if output.exists() and not args.force:
logging.error("%s already exists. Use --force to overwrite it.", output)
return 1
output.parent.mkdir(parents=True, exist_ok=True)
output.write_text(
render_template(ascend_home_path, args.npu_arch), encoding="utf-8"
)
logging.info("Generated %s using ASCEND_HOME_PATH=%s", output, ascend_home_path)
logging.info(
"Copy it to .clangd or point clangd user config to these flags if you want clangd to load it."
)
return 0
if __name__ == "__main__":
sys.exit(main())