mirror of
https://github.com/ArduPilot/ardupilot.git
synced 2025-12-13 06:38:23 -06:00
163 lines
5.5 KiB
Python
Executable File
163 lines
5.5 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
from __future__ import annotations
|
|
|
|
'''
|
|
Look at the difference between this and its merge-base with master
|
|
|
|
for each new hwdef file, build the board
|
|
|
|
AP_FLAKE8_CLEAN
|
|
'''
|
|
|
|
import optparse
|
|
import os
|
|
import shutil
|
|
|
|
from dataclasses import dataclass
|
|
from typing import Set
|
|
|
|
import board_list
|
|
from build_script_base import BuildScriptBase
|
|
|
|
|
|
class TestNewBoards(BuildScriptBase):
|
|
def __init__(self, master_branch: str = "master") -> None:
|
|
super().__init__()
|
|
self.master_branch: str = master_branch
|
|
|
|
def progress_prefix(self) -> str:
|
|
'''pretty-print progress'''
|
|
return 'TNB'
|
|
|
|
def get_new_hwdef_paths(self) -> Set[str]:
|
|
'''returns list of newly added hwdef filepaths relative to the root.
|
|
Only .dat files for both main and bootloader firmwares'''
|
|
current_commitish = self.find_current_git_branch_or_sha1()
|
|
merge_base = self.find_git_branch_merge_base(current_commitish, self.master_branch)
|
|
delta_files = self.run_git([
|
|
'diff',
|
|
'--name-status',
|
|
f"{merge_base}",
|
|
], show_output=False)
|
|
|
|
ret = set()
|
|
|
|
for line in delta_files.split("\n"):
|
|
if not line:
|
|
continue
|
|
parts = line.split(None, 1)
|
|
if len(parts) != 2:
|
|
continue
|
|
status, filepath = parts
|
|
# Only process added files (status 'A')
|
|
if status != 'A':
|
|
continue
|
|
if "/hwdef/" not in filepath:
|
|
continue
|
|
if not filepath.endswith(("hwdef.dat", "hwdef-bl.dat")):
|
|
continue
|
|
|
|
ret.add(filepath)
|
|
|
|
return ret
|
|
|
|
def build_board(self, board : board_list.Board):
|
|
self.run_waf(["configure", "--board", board.name], show_output=False)
|
|
if board.is_ap_periph:
|
|
self.run_waf(["AP_Periph"], show_output=False)
|
|
else:
|
|
for t in board.autobuild_targets:
|
|
t = t.lower()
|
|
if t == 'tracker':
|
|
t = 'antennatracker'
|
|
self.run_waf([t], show_output=False)
|
|
|
|
def build_bootloader(self, board : board_list.Board) -> None:
|
|
if not board.is_ap_periph:
|
|
# hopefully temporary hack so you can build bootloader
|
|
# after building other vehicles without a clean:
|
|
dsdl_generated_path = os.path.join('build', board.name, "modules", "DroneCAN", "libcanard", "dsdlc_generated")
|
|
self.progress(f"HACK: Removing ({dsdl_generated_path})")
|
|
shutil.rmtree(dsdl_generated_path, ignore_errors=True)
|
|
self.run_waf([
|
|
"configure",
|
|
"--board",
|
|
board.name,
|
|
"--bootloader"
|
|
], show_output=False)
|
|
self.run_waf(["bootloader"], show_output=False)
|
|
|
|
def run(self) -> None:
|
|
hwdef_filepaths = self.get_new_hwdef_paths()
|
|
|
|
@dataclass
|
|
class BoardToTest():
|
|
test_bootloader: bool = False
|
|
test_vehicles: bool = False
|
|
|
|
# Extract unique board names and track if bootloader hwdef was added
|
|
boards_to_test = {} # board_name -> has_bootloader
|
|
for hwdef_filepath in hwdef_filepaths:
|
|
self.progress(f"New hwdef: {hwdef_filepath}")
|
|
# Extract board name from path like libraries/AP_HAL_ChibiOS/hwdef/BoardName/hwdef.dat
|
|
parts = hwdef_filepath.split('/')
|
|
if 'hwdef' not in parts:
|
|
raise ValueError(f"hwdef not found in path: {hwdef_filepath}")
|
|
hwdef_idx = parts.index('hwdef')
|
|
if hwdef_idx + 1 >= len(parts):
|
|
raise ValueError(f"No board name after hwdef in path: {hwdef_filepath}")
|
|
board_name = parts[hwdef_idx + 1]
|
|
if board_name not in boards_to_test:
|
|
boards_to_test[board_name] = BoardToTest()
|
|
if hwdef_filepath.endswith('hwdef-bl.dat'):
|
|
boards_to_test[board_name].test_bootloader = True
|
|
else:
|
|
boards_to_test[board_name].test_vehicles = True
|
|
|
|
# Build each unique board (find it in board list as an additional check)
|
|
bl = board_list.BoardList()
|
|
for board_name in sorted(boards_to_test.keys()):
|
|
# Find the board object
|
|
board = None
|
|
for b in bl.boards:
|
|
if b.name == board_name:
|
|
board = b
|
|
break
|
|
|
|
if board is None:
|
|
raise ValueError(f"Board {board_name} not found in board list")
|
|
|
|
# Skip ESP32 boards - CI machine can't build them
|
|
if board.hal == "ESP32":
|
|
self.progress(f"Skipping ESP32 board {board.name}")
|
|
continue
|
|
|
|
self.progress(f"Building board {board.name}")
|
|
if boards_to_test[board_name].test_vehicles:
|
|
self.build_board(board)
|
|
|
|
# Build bootloader if a bootloader hwdef file was added
|
|
if boards_to_test[board_name].test_bootloader:
|
|
self.progress(f"Building bootloader for {board.name}")
|
|
self.build_bootloader(board)
|
|
|
|
|
|
def main():
|
|
parser = optparse.OptionParser("test_new_boards.py")
|
|
parser.add_option("",
|
|
"--master-branch",
|
|
type="string",
|
|
default="master",
|
|
help="master branch to use")
|
|
cmd_opts, cmd_args = parser.parse_args()
|
|
|
|
tnb = TestNewBoards(
|
|
master_branch=cmd_opts.master_branch,
|
|
)
|
|
tnb.run()
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|