From a4cca91b92217edd98f86518a095b2c5a7c48b06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Cab=C3=A9?= Date: Tue, 17 Sep 2024 16:26:29 +0200 Subject: [PATCH] doc: Add board catalog MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit wip Signed-off-by: Benjamin Cabé --- boards/index.rst | 326 +++++++++++++++++++++++++++++ doc/CMakeLists.txt | 29 ++- doc/Makefile | 8 +- doc/_scripts/gen_boards_catalog.py | 158 ++++++++++++++ doc/conf.py | 1 + 5 files changed, 517 insertions(+), 5 deletions(-) create mode 100644 doc/_scripts/gen_boards_catalog.py diff --git a/boards/index.rst b/boards/index.rst index 77814350d9ed23..3b0cdc5b2646ef 100644 --- a/boards/index.rst +++ b/boards/index.rst @@ -16,9 +16,335 @@ available under :zephyr_file:`doc/templates/board.tmpl`. .. toctree:: :maxdepth: 2 :glob: + :hidden: */index +.. raw:: html + + + +
+ + + + + +
+ +
+ +
+ +
+ + + +:download:`Raw board catalog <_catalog/board_catalog.json>`. + .. _boards-shields: Shields diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index bcabb520a79a3f..d6f47e6d0d9c55 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -16,6 +16,7 @@ set(SPHINXOPTS "-j auto -W --keep-going -T" CACHE STRING "Default Sphinx Options set(SPHINXOPTS_EXTRA "" CACHE STRING "Extra Sphinx Options (added to defaults)") set(LATEXMKOPTS "-halt-on-error -no-shell-escape" CACHE STRING "Default latexmk options") set(DT_TURBO_MODE OFF CACHE BOOL "Enable DT turbo mode") +set(BOARDS_TURBO_MODE OFF CACHE BOOL "Enable Boards turbo mode") set(DOC_TAG "development" CACHE STRING "Documentation tag") set(DTS_ROOTS "${ZEPHYR_BASE}" CACHE STRING "DT bindings root folders") @@ -146,6 +147,30 @@ add_custom_target( set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${GEN_DEVICETREE_REST_SCRIPT}) +#------------------------------------------------------------------------------- +# boards catalog + +set(GEN_BOARDS_CATALOG_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/_scripts/gen_boards_catalog.py) + +set(GEN_BOARDS_ARGS) +if(BOARDS_TURBO_MODE) + list(APPEND GEN_BOARDS_ARGS --turbo-mode) +endif() + +add_custom_target( + boards-catalog + COMMAND ${CMAKE_COMMAND} -E env + PYTHONPATH=${ZEPHYR_BASE}/scripts/dts/python-devicetree/src${SEP}$ENV{PYTHONPATH}:${ZEPHYR_BASE}/scripts + ZEPHYR_BASE=${ZEPHYR_BASE} + ${PYTHON_EXECUTABLE} ${GEN_BOARDS_CATALOG_SCRIPT} + ${GEN_BOARDS_ARGS} + ${DOCS_SRC_DIR}/boards/_catalog + VERBATIM + USES_TERMINAL + COMMENT "Generating Boards catalog documentation..." +) + + #------------------------------------------------------------------------------- # html @@ -172,7 +197,7 @@ set_target_properties( ADDITIONAL_CLEAN_FILES "${DOCS_SRC_DIR};${DOCS_HTML_DIR};${DOCS_DOCTREE_DIR}" ) -add_dependencies(html devicetree) +add_dependencies(html devicetree boards-catalog) #------------------------------------------------------------------------------- # html-live @@ -202,7 +227,7 @@ set_target_properties( ADDITIONAL_CLEAN_FILES "${DOCS_SRC_DIR};${DOCS_HTML_DIR};${DOCS_DOCTREE_DIR}" ) -add_dependencies(html-live devicetree) +add_dependencies(html-live devicetree boards-catalog) #------------------------------------------------------------------------------- # pdf diff --git a/doc/Makefile b/doc/Makefile index e1dd82d59cb6ec..298c43ca423231 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -8,6 +8,7 @@ SPHINXOPTS ?= -j auto -W --keep-going -T SPHINXOPTS_EXTRA ?= LATEXMKOPTS ?= -halt-on-error -no-shell-escape DT_TURBO_MODE ?= 0 +BOARDS_TURBO_MODE ?= 0 # ------------------------------------------------------------------------------ # Documentation targets @@ -15,10 +16,10 @@ DT_TURBO_MODE ?= 0 .PHONY: configure clean html html-fast html-live html-live-fast latex pdf doxygen html-fast: - ${MAKE} html DT_TURBO_MODE=1 + ${MAKE} html DT_TURBO_MODE=1 BOARDS_TURBO_MODE=1 html-live-fast: - ${MAKE} html-live DT_TURBO_MODE=1 + ${MAKE} html-live DT_TURBO_MODE=1 BOARDS_TURBO_MODE=1 html html-live latex pdf linkcheck doxygen: configure cmake --build ${BUILDDIR} --target $@ @@ -32,7 +33,8 @@ configure: -DSPHINXOPTS="${SPHINXOPTS}" \ -DSPHINXOPTS_EXTRA="${SPHINXOPTS_EXTRA}" \ -DLATEXMKOPTS="${LATEXMKOPTS}" \ - -DDT_TURBO_MODE=${DT_TURBO_MODE} + -DDT_TURBO_MODE=${DT_TURBO_MODE} \ + -DBOARDS_TURBO_MODE=${BOARDS_TURBO_MODE} clean: cmake --build ${BUILDDIR} --target clean diff --git a/doc/_scripts/gen_boards_catalog.py b/doc/_scripts/gen_boards_catalog.py new file mode 100644 index 00000000000000..802fa37a1fce8b --- /dev/null +++ b/doc/_scripts/gen_boards_catalog.py @@ -0,0 +1,158 @@ +# Copyright (c) 2024 The Linux Foundation +# SPDX-License-Identifier: Apache-2.0 + +import argparse +import json +import logging +import os +import subprocess +import sys +from collections import namedtuple +from pathlib import Path + +import list_boards +import pykwalify +import yaml +import zephyr_module +from devicetree import edtlib +from gen_devicetree_rest import VndLookup + +ZEPHYR_BASE = Path(__file__).parents[2] + + +def main(): + """ + Generate a board_catalog.json file that contains information about all the boards in the Zephyr + tree. + """ + + logging.basicConfig(level=logging.INFO) + logging.info("Generating board catalog...") + + pykwalify.init_logging(1) + + parser = argparse.ArgumentParser(description="Generate boards catalog", allow_abbrev=False) + # right now, turbo mode is a no-op, but it will be used in the future + parser.add_argument("--turbo-mode", action="store_true", help="Enable turbo mode") + parser.add_argument("out_dir", help="output files are generated here") + args = parser.parse_args() + + os.makedirs(args.out_dir, exist_ok=True) + + # Load the vendor lookup table + vnd_lookup = VndLookup(ZEPHYR_BASE / "dts/bindings/vendor-prefixes.txt", []) + + module_settings = { + "arch_root": [ZEPHYR_BASE], + "board_root": [ZEPHYR_BASE], + "soc_root": [ZEPHYR_BASE], + } + + for module in zephyr_module.parse_modules(ZEPHYR_BASE): + for key in module_settings: + root = module.meta.get("build", {}).get("settings", {}).get(key) + if root is not None: + module_settings[key].append(Path(module.project) / root) + + Args = namedtuple("args", ["arch_roots", "board_roots", "soc_roots", "board_dir", "board"]) + args_find_boards = Args( + arch_roots=module_settings["arch_root"], + board_roots=module_settings["board_root"], + soc_roots=module_settings["soc_root"], + board_dir=ZEPHYR_BASE / "boards", + board=None, + ) + + boards = list_boards.find_v2_boards(args_find_boards) + print(f"Found {len(boards)} boards") + + board_catalog = {} + + for board in boards: + # board.vendor is often incorrect, instead, deduce vendor from containing folder + for folder in board.dir.parents: + if vnd_lookup.vnd2vendor.get(folder.name): + vendor_prefix = folder.name + vendor = vnd_lookup.vnd2vendor.get(folder.name) + break + + name = board.name + + qualifiers = list_boards.board_v2_qualifiers(board) + if len(qualifiers) == 1: + qualifiers = [""] + + for q in qualifiers: + if q == "": + full_name = f"{board.name}" + else: + full_name = f"{board.name}_{q.replace('/', '_')}" + + # load the twister file for the board + twister_file = board.dir / f"{full_name}.yaml" + + try: + with open(twister_file, "r") as f: + board_data = yaml.safe_load(f) + board_dir = board.dir + board_human_readable_name = board_data.get("name") + board_description = board_data.get("description") + arch = board_data.get("arch") + ram = board_data.get("ram") + flash = board_data.get("flash") + + img_exts = ["jpg", "webp", "png"] + img_file = None + + # Try to find the image file with the exact name and extension + img_file = next( + (file for ext in img_exts for file in board.dir.glob(f"**/{name}.{ext}")), + None, + ) + + # If not found, try to find an image file that contains the board name + if not img_file: + img_file = next( + ( + file + for ext in img_exts + for file in board.dir.glob(f"**/*{name}*.{ext}") + ), + None, + ) + + # If still not found, try to find any image file with the given extensions + if not img_file: + img_file = next( + (file for ext in img_exts for file in board.dir.glob(f"**/*.{ext}")), + None, + ) + + if img_file: + img_file = Path("../_images") / img_file.name + + print(board_dir.relative_to(ZEPHYR_BASE).as_posix()) + + board_catalog[full_name] = { + "dir": board_dir.relative_to(ZEPHYR_BASE).as_posix(), + "board_name": name, + "name": board_human_readable_name, + "vendor_prefix": vendor_prefix, + "vendor": vendor, + "description": board_description, + "arch": arch, + "ram": ram, + "flash": flash, + "image": img_file.as_posix() if img_file else "", + } + + except FileNotFoundError: + pass + + with open(f"{args.out_dir}/board_catalog.json", "w") as f: + json.dump(board_catalog, f, indent=4) + + +if __name__ == "__main__": + main() + sys.exit(0) diff --git a/doc/conf.py b/doc/conf.py index 17a73ec79ec5dc..bf7c35fb18b5ab 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -300,6 +300,7 @@ ] external_content_keep = [ "reference/kconfig/*", + "boards/_catalog/**/*", "develop/manifest/index.rst", "build/dts/api/bindings.rst", "build/dts/api/bindings/**/*",