114 lines
3.2 KiB
Python
114 lines
3.2 KiB
Python
|
#!/usr/bin/env python3
|
||
|
|
||
|
# Copyright (c) 2020 Nordic Semiconductor ASA
|
||
|
# SPDX-License-Identifier: Apache-2.0
|
||
|
|
||
|
import argparse
|
||
|
from collections import defaultdict
|
||
|
import itertools
|
||
|
from pathlib import Path
|
||
|
from typing import NamedTuple
|
||
|
|
||
|
ZEPHYR_BASE = Path(__file__).resolve().parents[1]
|
||
|
|
||
|
#
|
||
|
# This is shared code between the build system's 'boards' target
|
||
|
# and the 'west boards' extension command. If you change it, make
|
||
|
# sure to test both ways it can be used.
|
||
|
#
|
||
|
# (It's done this way to keep west optional, making it possible to run
|
||
|
# 'ninja boards' in a build directory without west installed.)
|
||
|
#
|
||
|
|
||
|
class Board(NamedTuple):
|
||
|
name: str
|
||
|
arch: str
|
||
|
dir: Path
|
||
|
|
||
|
def board_key(board):
|
||
|
return board.name
|
||
|
|
||
|
def find_arch2boards(args):
|
||
|
arch2board_set = find_arch2board_set(args)
|
||
|
return {arch: sorted(arch2board_set[arch], key=board_key)
|
||
|
for arch in arch2board_set}
|
||
|
|
||
|
def find_boards(args):
|
||
|
return sorted(itertools.chain(*find_arch2board_set(args).values()),
|
||
|
key=board_key)
|
||
|
|
||
|
def find_arch2board_set(args):
|
||
|
arches = sorted(find_arches(args))
|
||
|
ret = defaultdict(set)
|
||
|
|
||
|
for root in itertools.chain([ZEPHYR_BASE], args.board_roots):
|
||
|
for arch, boards in find_arch2board_set_in(root, arches).items():
|
||
|
ret[arch] |= boards
|
||
|
|
||
|
return ret
|
||
|
|
||
|
def find_arches(args):
|
||
|
arch_set = find_arches_in(ZEPHYR_BASE)
|
||
|
|
||
|
for root in args.arch_roots:
|
||
|
arch_set |= find_arches_in(root)
|
||
|
|
||
|
return arch_set
|
||
|
|
||
|
def find_arches_in(root):
|
||
|
ret = set()
|
||
|
arch = root / 'arch'
|
||
|
common = arch / 'common'
|
||
|
|
||
|
if not arch.is_dir():
|
||
|
return ret
|
||
|
|
||
|
for maybe_arch in arch.iterdir():
|
||
|
if not maybe_arch.is_dir() or maybe_arch == common:
|
||
|
continue
|
||
|
ret.add(maybe_arch.name)
|
||
|
|
||
|
return ret
|
||
|
|
||
|
def find_arch2board_set_in(root, arches):
|
||
|
ret = defaultdict(set)
|
||
|
boards = root / 'boards'
|
||
|
|
||
|
for arch in arches:
|
||
|
for maybe_board in (boards / arch).iterdir():
|
||
|
if not maybe_board.is_dir():
|
||
|
continue
|
||
|
for maybe_defconfig in maybe_board.iterdir():
|
||
|
file_name = maybe_defconfig.name
|
||
|
if file_name.endswith('_defconfig'):
|
||
|
board_name = file_name[:-len('_defconfig')]
|
||
|
ret[arch].add(Board(board_name, arch, maybe_board))
|
||
|
|
||
|
return ret
|
||
|
|
||
|
def parse_args():
|
||
|
parser = argparse.ArgumentParser()
|
||
|
add_args(parser)
|
||
|
return parser.parse_args()
|
||
|
|
||
|
def add_args(parser):
|
||
|
# Remember to update west-completion.bash if you add or remove
|
||
|
# flags
|
||
|
parser.add_argument("--arch-root", dest='arch_roots', default=[],
|
||
|
type=Path, action='append',
|
||
|
help='''add an architecture root (ZEPHYR_BASE is
|
||
|
always present), may be given more than once''')
|
||
|
parser.add_argument("--board-root", dest='board_roots', default=[],
|
||
|
type=Path, action='append',
|
||
|
help='''add a board root (ZEPHYR_BASE is always
|
||
|
present), may be given more than once''')
|
||
|
|
||
|
def dump_boards(arch2boards):
|
||
|
for arch, boards in arch2boards.items():
|
||
|
print(f'{arch}:')
|
||
|
for board in boards:
|
||
|
print(f' {board.name}')
|
||
|
|
||
|
if __name__ == '__main__':
|
||
|
dump_boards(find_arch2boards(parse_args()))
|