ardupilot/Tools/scripts/board_list.py

264 lines
8.5 KiB
Python
Executable File

#!/usr/bin/env python3
import os
import re
import fnmatch
from collections.abc import Collection
'''
list of boards for build_binaries.py and custom build server
AP_FLAKE8_CLEAN
'''
class Board(object):
def __init__(self, name):
self.name = name
self.is_ap_periph = False
self.toolchain = 'arm-none-eabi' # FIXME: try to remove this?
self.hal = None # filled in below
self.autobuild_targets = [
'Tracker',
'Blimp',
'Copter',
'Heli',
'Plane',
'Rover',
'Sub',
]
SITL_toolchain = {
"SITL_x86_64_linux_gnu": "x86_64-linux-gnu",
"SITL_arm_linux_gnueabihf": "arm-linux-gnueabihf",
}
if name in SITL_toolchain:
self.toolchain = SITL_toolchain[name]
def in_boardlist(boards : Collection[str], board : str) -> bool:
'''return true if board is in a collection of wildcard patterns'''
for pattern in boards:
if fnmatch.fnmatch(board, pattern):
return True
return False
class BoardList(object):
def set_hwdef_dir(self):
# work out wheer the hwdef files exist. This file
# (board_list.py) is copied into place on the autotest server,
# so it isn't always in the same relative position to the
# hwdef directories!
found = False
for relpath_bit in [
os.path.join("..", "..", "libraries"),
'libraries',
]:
probe = os.path.join(
os.path.dirname(os.path.realpath(__file__)),
relpath_bit, "AP_HAL_ChibiOS", "hwdef"
)
if os.path.exists(probe):
found = True
break
if not found:
raise ValueError("Did not find hwdef_dir")
realpath = os.path.join(
os.path.dirname(os.path.realpath(__file__)),
relpath_bit
)
self.hwdef_dir = []
for haldir in 'AP_HAL_ChibiOS', 'AP_HAL_Linux', 'AP_HAL_ESP32':
self.hwdef_dir.append(os.path.join(realpath, haldir, "hwdef"))
def __init__(self):
self.set_hwdef_dir()
# no hwdefs for Linux boards - yet?
self.boards = [
Board("SITL_x86_64_linux_gnu"),
Board("SITL_arm_linux_gnueabihf"),
]
for b in self.boards:
b.hal = "AP_HAL_SITL"
for hwdef_dir in self.hwdef_dir:
self.add_hwdefs_from_hwdef_dir(hwdef_dir)
def add_hwdefs_from_hwdef_dir(self, hwdef_dir):
for adir in os.listdir(hwdef_dir):
if adir is None:
continue
if not os.path.isdir(os.path.join(hwdef_dir, adir)):
continue
if adir in ["scripts", "common", "STM32CubeConf"]:
continue
filepath = os.path.join(hwdef_dir, adir, "hwdef.dat")
if not os.path.exists(filepath):
continue
filepath = os.path.join(hwdef_dir, adir, "hwdef.dat")
# FIXME: we really should be using hwdef.py to parse
# these, but it's too slow. We use board_list in some
# places we can't afford to be slow.
text = self.read_hwdef(filepath)
board = Board(adir)
self.boards.append(board)
board_toolchain_set = False
for line in text:
if re.match(r"^\s*env AP_PERIPH 1", line):
board.is_ap_periph = 1
if re.match(r"^\s*env AP_PERIPH_HEAVY 1", line):
board.is_ap_periph = 1
# a hwdef can specify which vehicles this target is valid for:
match = re.match(r"AUTOBUILD_TARGETS\s*(.*)", line)
if match is not None:
mname = match.group(1)
if mname.lower() == 'none':
board.autobuild_targets = []
else:
board.autobuild_targets = [
x.rstrip().lstrip().lower() for x in mname.split(",")
]
m = re.match(r"\s*env\s*TOOLCHAIN\s*([-\w]+)\s*", line)
if m is not None:
board.toolchain = m.group(1)
board_toolchain_set = True
if board.toolchain == 'native':
board.toolchain = None
# toolchain not in hwdef; make up some defaults:
if not board_toolchain_set:
if "Linux" in hwdef_dir:
board.toolchain = 'arm-linux-gnueabihf'
elif "ChibiOS" in hwdef_dir:
board.toolchain = 'arm-none-eabi'
elif "ESP32" in hwdef_dir:
board.toolchain = 'xtensa-esp32-elf'
else:
raise ValueError(f"Unable to determine toolchain for {hwdef_dir}")
if "Linux" in hwdef_dir:
board.hal = "Linux"
elif "ChibiOS" in hwdef_dir:
board.hal = "ChibiOS"
elif "ESP32" in hwdef_dir:
board.hal = "ESP32"
else:
raise ValueError(f"Unable to determine HAL for {hwdef_dir}")
def read_hwdef(self, filepath):
fh = open(filepath)
ret = []
text = fh.readlines()
for line in text:
m = re.match(r"^\s*include\s+(.+)\s*$", line)
if m is not None:
ret += self.read_hwdef(os.path.join(os.path.dirname(filepath), m.group(1)))
else:
ret += [line]
return ret
def find_autobuild_boards(self, build_target=None, skip : Collection[str] = None):
ret = []
for board in self.boards:
if board.is_ap_periph:
continue
ret.append(board.name)
# these were missing in the original list for unknown reasons.
# Omitting them for backwards-compatability here - but we
# should probably have a line in the hwdef indicating they
# shouldn't be auto-built...
if skip is None:
skip = [
# IOMCU:
"iomcu",
'iomcu_f103_8MHz',
# bdshot
"fmuv3-bdshot",
# renamed to KakuteH7Mini-Nand
"KakuteH7Miniv2",
# renamed to AtomRCF405NAVI
"AtomRCF405"
# other
"crazyflie2",
"CubeOrange-joey",
"luminousbee4",
"MazzyStarDrone",
"omnibusf4pro-one",
"skyviper-f412-rev1",
"SkystarsH7HD",
"*-ODID",
"*-ODID-heli",
]
ret = filter(lambda x : not in_boardlist(skip, x), ret)
# if the caller has supplied a vehicle to limit to then we do that here:
if build_target is not None:
# Slow down: n^2 algorithm ahead
newret = []
for x in ret:
for b in self.boards:
if b.name.lower() != x.lower():
continue
if build_target.lower() not in [y.lower() for y in b.autobuild_targets]:
continue
newret.append(x)
ret = newret
return sorted(list(ret))
def find_ap_periph_boards(self, skip : Collection[str] = None):
if skip is None:
skip = [
"CubeOrange-periph-heavy",
"f103-HWESC",
"f103-Trigger",
"G4-ESC",
]
ret = []
for x in self.boards:
if not x.is_ap_periph:
continue
if in_boardlist(skip, x.name):
continue
ret.append(x.name)
return sorted(list(ret))
AUTOBUILD_BOARDS = BoardList().find_autobuild_boards()
AP_PERIPH_BOARDS = BoardList().find_ap_periph_boards()
if __name__ == '__main__':
import argparse
parser = argparse.ArgumentParser(description='list boards to build')
parser.add_argument('target')
parser.add_argument('--per-line', action='store_true', default=False, help='list one per line for use with xargs')
args = parser.parse_args()
board_list = BoardList()
target = args.target
if target == "AP_Periph":
blist = board_list.find_ap_periph_boards()
else:
blist = board_list.find_autobuild_boards(target)
blist = sorted(blist)
if args.per_line:
for b in blist:
print(b)
else:
print(blist)