blob: 92478f92a7c08287d4a7d6d96fa28c4a48d97a6d [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
Martí Bolívar8bd6d082020-12-09 12:03:19 -080012#
13# This is shared code between the build system's 'boards' target
14# and the 'west boards' extension command. If you change it, make
15# sure to test both ways it can be used.
16#
17# (It's done this way to keep west optional, making it possible to run
18# 'ninja boards' in a build directory without west installed.)
19#
20
21class Board(NamedTuple):
22 name: str
23 arch: str
24 dir: Path
25
26def board_key(board):
27 return board.name
28
29def find_arch2boards(args):
30 arch2board_set = find_arch2board_set(args)
31 return {arch: sorted(arch2board_set[arch], key=board_key)
32 for arch in arch2board_set}
33
34def find_boards(args):
35 return sorted(itertools.chain(*find_arch2board_set(args).values()),
36 key=board_key)
37
38def find_arch2board_set(args):
39 arches = sorted(find_arches(args))
40 ret = defaultdict(set)
41
Torsten Rasmussenc3620c82022-08-05 09:54:47 +020042 for root in args.board_roots:
Martí Bolívar8bd6d082020-12-09 12:03:19 -080043 for arch, boards in find_arch2board_set_in(root, arches).items():
44 ret[arch] |= boards
45
46 return ret
47
48def find_arches(args):
Torsten Rasmussenc3620c82022-08-05 09:54:47 +020049 arch_set = set()
Martí Bolívar8bd6d082020-12-09 12:03:19 -080050
51 for root in args.arch_roots:
52 arch_set |= find_arches_in(root)
53
54 return arch_set
55
56def find_arches_in(root):
57 ret = set()
58 arch = root / 'arch'
59 common = arch / 'common'
60
61 if not arch.is_dir():
62 return ret
63
64 for maybe_arch in arch.iterdir():
65 if not maybe_arch.is_dir() or maybe_arch == common:
66 continue
67 ret.add(maybe_arch.name)
68
69 return ret
70
71def find_arch2board_set_in(root, arches):
72 ret = defaultdict(set)
73 boards = root / 'boards'
74
75 for arch in arches:
Marcin Niestroj35c882d2021-05-08 15:36:19 +020076 if not (boards / arch).is_dir():
77 continue
78
Martí Bolívar8bd6d082020-12-09 12:03:19 -080079 for maybe_board in (boards / arch).iterdir():
80 if not maybe_board.is_dir():
81 continue
82 for maybe_defconfig in maybe_board.iterdir():
83 file_name = maybe_defconfig.name
84 if file_name.endswith('_defconfig'):
85 board_name = file_name[:-len('_defconfig')]
86 ret[arch].add(Board(board_name, arch, maybe_board))
87
88 return ret
89
90def parse_args():
91 parser = argparse.ArgumentParser()
92 add_args(parser)
93 return parser.parse_args()
94
95def add_args(parser):
96 # Remember to update west-completion.bash if you add or remove
97 # flags
98 parser.add_argument("--arch-root", dest='arch_roots', default=[],
99 type=Path, action='append',
Torsten Rasmussenc3620c82022-08-05 09:54:47 +0200100 help='add an architecture root, may be given more than once')
Martí Bolívar8bd6d082020-12-09 12:03:19 -0800101 parser.add_argument("--board-root", dest='board_roots', default=[],
102 type=Path, action='append',
Torsten Rasmussenc3620c82022-08-05 09:54:47 +0200103 help='add a board root, may be given more than once')
Martí Bolívar8bd6d082020-12-09 12:03:19 -0800104
105def dump_boards(arch2boards):
106 for arch, boards in arch2boards.items():
107 print(f'{arch}:')
108 for board in boards:
109 print(f' {board.name}')
110
111if __name__ == '__main__':
112 dump_boards(find_arch2boards(parse_args()))