Austin Schuh | 41baf20 | 2022-01-01 14:33:40 -0800 | [diff] [blame^] | 1 | import os |
| 2 | import glob |
| 3 | import sys |
| 4 | import subprocess |
| 5 | import time |
| 6 | |
| 7 | SUCCEEDED = "\033[32msucceeded\033[0m" |
| 8 | FAILED = "\033[31mfailed\033[0m" |
| 9 | SKIPPED = "\033[33mskipped\033[0m" |
| 10 | |
| 11 | success_count = 0 |
| 12 | fail_count = 0 |
| 13 | skip_count = 0 |
| 14 | exit_status = 0 |
| 15 | |
| 16 | total_time = time.monotonic() |
| 17 | |
| 18 | build_format = '| {:29} | {:30} | {:18} | {:7} | {:6} | {:6} |' |
| 19 | build_separator = '-' * 106 |
| 20 | |
| 21 | def filter_with_input(mylist): |
| 22 | if len(sys.argv) > 1: |
| 23 | input_args = list(set(mylist).intersection(sys.argv)) |
| 24 | if len(input_args) > 0: |
| 25 | mylist[:] = input_args |
| 26 | |
| 27 | # If examples are not specified in arguments, build all |
| 28 | all_examples = [] |
| 29 | for entry in os.scandir("examples/device"): |
| 30 | if entry.is_dir(): |
| 31 | all_examples.append("device/" + entry.name) |
| 32 | for entry in os.scandir("examples/host"): |
| 33 | if entry.is_dir(): |
| 34 | all_examples.append("host/" + entry.name) |
| 35 | filter_with_input(all_examples) |
| 36 | all_examples.sort() |
| 37 | |
| 38 | # If boards are not specified in arguments, build all |
| 39 | all_boards = [] |
| 40 | for entry in os.scandir("hw/bsp"): |
| 41 | if entry.is_dir() and os.path.exists(entry.path + "/board.mk"): |
| 42 | all_boards.append(entry.name) |
| 43 | filter_with_input(all_boards) |
| 44 | all_boards.sort() |
| 45 | |
| 46 | def build_board(example, board): |
| 47 | global success_count, fail_count, skip_count, exit_status |
| 48 | start_time = time.monotonic() |
| 49 | flash_size = "-" |
| 50 | sram_size = "-" |
| 51 | |
| 52 | # Check if board is skipped |
| 53 | if skip_example(example, board): |
| 54 | success = SKIPPED |
| 55 | skip_count += 1 |
| 56 | print(build_format.format(example, board, success, '-', flash_size, sram_size)) |
| 57 | else: |
| 58 | subprocess.run("make -C examples/{} BOARD={} clean".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) |
| 59 | build_result = subprocess.run("make -j -C examples/{} BOARD={} all".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) |
| 60 | |
| 61 | if build_result.returncode == 0: |
| 62 | success = SUCCEEDED |
| 63 | success_count += 1 |
| 64 | (flash_size, sram_size) = build_size(example, board) |
| 65 | else: |
| 66 | exit_status = build_result.returncode |
| 67 | success = FAILED |
| 68 | fail_count += 1 |
| 69 | |
| 70 | build_duration = time.monotonic() - start_time |
| 71 | print(build_format.format(example, board, success, "{:.2f}s".format(build_duration), flash_size, sram_size)) |
| 72 | |
| 73 | if build_result.returncode != 0: |
| 74 | print(build_result.stdout.decode("utf-8")) |
| 75 | |
| 76 | def build_size(example, board): |
| 77 | #elf_file = 'examples/device/{}/_build/{}/{}-firmware.elf'.format(example, board, board) |
| 78 | elf_file = 'examples/{}/_build/{}/*.elf'.format(example, board) |
| 79 | size_output = subprocess.run('size {}'.format(elf_file), shell=True, stdout=subprocess.PIPE).stdout.decode("utf-8") |
| 80 | size_list = size_output.split('\n')[1].split('\t') |
| 81 | flash_size = int(size_list[0]) |
| 82 | sram_size = int(size_list[1]) + int(size_list[2]) |
| 83 | return (flash_size, sram_size) |
| 84 | |
| 85 | def skip_example(example, board): |
| 86 | ex_dir = 'examples/' + example |
| 87 | board_mk = 'hw/bsp/{}/board.mk'.format(board) |
| 88 | with open(board_mk) as mk: |
| 89 | mk_contents = mk.read() |
| 90 | |
| 91 | # Skip all OPT_MCU_NONE these are WIP port |
| 92 | if '-DCFG_TUSB_MCU=OPT_MCU_NONE' in mk_contents: |
| 93 | return 1 |
| 94 | |
| 95 | # Skip if CFG_TUSB_MCU in board.mk to match skip file |
| 96 | for skip_file in glob.iglob(ex_dir + '/.skip.MCU_*'): |
| 97 | mcu_cflag = '-DCFG_TUSB_MCU=OPT_' + os.path.basename(skip_file).split('.')[2] |
| 98 | if mcu_cflag in mk_contents: |
| 99 | return 1 |
| 100 | |
| 101 | # Build only list, if exists only these MCU are built |
| 102 | only_list = list(glob.iglob(ex_dir + '/.only.MCU_*')) |
| 103 | if len(only_list) > 0: |
| 104 | for only_file in only_list: |
| 105 | mcu_cflag = '-DCFG_TUSB_MCU=OPT_' + os.path.basename(only_file).split('.')[2] |
| 106 | if mcu_cflag in mk_contents: |
| 107 | return 0 |
| 108 | return 1 |
| 109 | |
| 110 | return 0 |
| 111 | |
| 112 | print(build_separator) |
| 113 | print(build_format.format('Example', 'Board', '\033[39mResult\033[0m', 'Time', 'Flash', 'SRAM')) |
| 114 | |
| 115 | for example in all_examples: |
| 116 | print(build_separator) |
| 117 | for board in all_boards: |
| 118 | build_board(example, board) |
| 119 | |
| 120 | total_time = time.monotonic() - total_time |
| 121 | print(build_separator) |
| 122 | print("Build Summary: {} {}, {} {}, {} {} and took {:.2f}s".format(success_count, SUCCEEDED, fail_count, FAILED, skip_count, SKIPPED, total_time)) |
| 123 | print(build_separator) |
| 124 | |
| 125 | sys.exit(exit_status) |