blob: 88753ae7f5d0df108a3c1665365d39d14be2c761 [file] [log] [blame]
Martí Bolívar8bd6d082020-12-09 12:03:19 -08001#!/usr/bin/env python3
2
3# Copyright (c) 2020 Nordic Semiconductor ASA
4# SPDX-License-Identifier: Apache-2.0
5
6import argparse
7from collections import defaultdict
8import itertools
9from pathlib import Path
10from typing import NamedTuple
11
12ZEPHYR_BASE = Path(__file__).resolve().parents[1]
13
14#
15# This is shared code between the build system's 'boards' target
16# and the 'west boards' extension command. If you change it, make
17# sure to test both ways it can be used.
18#
19# (It's done this way to keep west optional, making it possible to run
20# 'ninja boards' in a build directory without west installed.)
21#
22
23class Board(NamedTuple):
24 name: str
25 arch: str
26 dir: Path
27
28def board_key(board):
29 return board.name
30
31def find_arch2boards(args):
32 arch2board_set = find_arch2board_set(args)
33 return {arch: sorted(arch2board_set[arch], key=board_key)
34 for arch in arch2board_set}
35
36def find_boards(args):
37 return sorted(itertools.chain(*find_arch2board_set(args).values()),
38 key=board_key)
39
40def find_arch2board_set(args):
41 arches = sorted(find_arches(args))
42 ret = defaultdict(set)
43
44 for root in itertools.chain([ZEPHYR_BASE], args.board_roots):
45 for arch, boards in find_arch2board_set_in(root, arches).items():
46 ret[arch] |= boards
47
48 return ret
49
50def find_arches(args):
51 arch_set = find_arches_in(ZEPHYR_BASE)
52
53 for root in args.arch_roots:
54 arch_set |= find_arches_in(root)
55
56 return arch_set
57
58def find_arches_in(root):
59 ret = set()
60 arch = root / 'arch'
61 common = arch / 'common'
62
63 if not arch.is_dir():
64 return ret
65
66 for maybe_arch in arch.iterdir():
67 if not maybe_arch.is_dir() or maybe_arch == common:
68 continue
69 ret.add(maybe_arch.name)
70
71 return ret
72
73def find_arch2board_set_in(root, arches):
74 ret = defaultdict(set)
75 boards = root / 'boards'
76
77 for arch in arches:
Marcin Niestroj35c882d2021-05-08 15:36:19 +020078 if not (boards / arch).is_dir():
79 continue
80
Martí Bolívar8bd6d082020-12-09 12:03:19 -080081 for maybe_board in (boards / arch).iterdir():
82 if not maybe_board.is_dir():
83 continue
84 for maybe_defconfig in maybe_board.iterdir():
85 file_name = maybe_defconfig.name
86 if file_name.endswith('_defconfig'):
87 board_name = file_name[:-len('_defconfig')]
88 ret[arch].add(Board(board_name, arch, maybe_board))
89
90 return ret
91
92def parse_args():
93 parser = argparse.ArgumentParser()
94 add_args(parser)
95 return parser.parse_args()
96
97def add_args(parser):
98 # Remember to update west-completion.bash if you add or remove
99 # flags
100 parser.add_argument("--arch-root", dest='arch_roots', default=[],
101 type=Path, action='append',
102 help='''add an architecture root (ZEPHYR_BASE is
103 always present), may be given more than once''')
104 parser.add_argument("--board-root", dest='board_roots', default=[],
105 type=Path, action='append',
106 help='''add a board root (ZEPHYR_BASE is always
107 present), may be given more than once''')
108
109def dump_boards(arch2boards):
110 for arch, boards in arch2boards.items():
111 print(f'{arch}:')
112 for board in boards:
113 print(f' {board.name}')
114
115if __name__ == '__main__':
116 dump_boards(find_arch2boards(parse_args()))