summaryrefslogtreecommitdiffstats
path: root/tinyusb/tools/build_family.py
blob: c4678190462864508e02b09ecfac84ef198c778e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
import os
import glob
import sys
import subprocess
import time

SUCCEEDED = "\033[32msucceeded\033[0m"
FAILED = "\033[31mfailed\033[0m"
SKIPPED = "\033[33mskipped\033[0m"

success_count = 0
fail_count = 0
skip_count = 0
exit_status = 0

total_time = time.monotonic()

build_format = '| {:29} | {:30} | {:18} | {:7} | {:6} | {:6} |'
build_separator = '-' * 106

def filter_with_input(mylist):
    if len(sys.argv) > 1:
        input_args = list(set(mylist).intersection(sys.argv))
        if len(input_args) > 0:
            mylist[:] = input_args

# If examples are not specified in arguments, build all
all_examples = []
for entry in os.scandir("examples/device"):
    if entry.is_dir():
        all_examples.append("device/" + entry.name)
for entry in os.scandir("examples/host"):
    if entry.is_dir():
        all_examples.append("host/" + entry.name)
filter_with_input(all_examples)
all_examples.sort()

# If family are not specified in arguments, build all
all_families = []
for entry in os.scandir("hw/bsp"):
    if entry.is_dir() and os.path.isdir(entry.path + "/boards") and entry.name != "esp32s2" and entry.name != "esp32s3":
        all_families.append(entry.name)
            
filter_with_input(all_families)
all_families.sort()

def build_family(example, family):
    all_boards = []
    for entry in os.scandir("hw/bsp/{}/boards".format(family)):
        if entry.is_dir():
            all_boards.append(entry.name)
    filter_with_input(all_boards)
    all_boards.sort()
    
    for board in all_boards:
        build_board(example, board)
    
def build_board(example, board):
    global success_count, fail_count, skip_count, exit_status
    start_time = time.monotonic()
    flash_size = "-"
    sram_size = "-"

    # Check if board is skipped
    if skip_example(example, board):
        success = SKIPPED
        skip_count += 1
        print(build_format.format(example, board, success, '-', flash_size, sram_size))
    else:   
        #subprocess.run("make -C examples/{} BOARD={} clean".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
        build_result = subprocess.run("make -j -C examples/{} BOARD={} all".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

        if build_result.returncode == 0:
            success = SUCCEEDED
            success_count += 1
            (flash_size, sram_size) = build_size(example, board)
            subprocess.run("make -j -C examples/{} BOARD={} copy-artifact".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
        else:
            exit_status = build_result.returncode
            success = FAILED
            fail_count += 1

        build_duration = time.monotonic() - start_time
        print(build_format.format(example, board, success, "{:.2f}s".format(build_duration), flash_size, sram_size))

        if build_result.returncode != 0:
            print(build_result.stdout.decode("utf-8"))

def build_size(example, board):
    #elf_file = 'examples/device/{}/_build/{}/{}-firmware.elf'.format(example, board, board)
    elf_file = 'examples/{}/_build/{}/*.elf'.format(example, board)
    size_output = subprocess.run('size {}'.format(elf_file), shell=True, stdout=subprocess.PIPE).stdout.decode("utf-8")
    size_list = size_output.split('\n')[1].split('\t')
    flash_size = int(size_list[0])
    sram_size = int(size_list[1]) + int(size_list[2])
    return (flash_size, sram_size)

def skip_example(example, board):
    ex_dir = 'examples/' + example
    
    # family CMake
    board_mk = 'hw/bsp/{}/family.cmake'.format(family)

    # family.mk
    if not os.path.exists(board_mk):
        board_mk = 'hw/bsp/{}/family.mk'.format(family)

    with open(board_mk) as mk:
        mk_contents = mk.read()

        # Skip all OPT_MCU_NONE these are WIP port
        if 'CFG_TUSB_MCU=OPT_MCU_NONE' in mk_contents:
            return 1

        # Skip if CFG_TUSB_MCU in board.mk to match skip file
        for skip_file in glob.iglob(ex_dir + '/.skip.MCU_*'):
            mcu_cflag = 'CFG_TUSB_MCU=OPT_' + os.path.basename(skip_file).split('.')[2]
            if mcu_cflag in mk_contents:
                return 1

        # Build only list, if exists only these MCU are built
        only_list = list(glob.iglob(ex_dir + '/.only.MCU_*'))
        if len(only_list) > 0:
            for only_file in only_list:
                mcu_cflag = 'CFG_TUSB_MCU=OPT_' + os.path.basename(only_file).split('.')[2]
                if mcu_cflag in mk_contents:
                    return 0
            return 1
    return 0

print(build_separator)
print(build_format.format('Example', 'Board', '\033[39mResult\033[0m', 'Time', 'Flash', 'SRAM'))

for example in all_examples:
    print(build_separator)
    for family in all_families:
        build_family(example, family)

total_time = time.monotonic() - total_time
print(build_separator)
print("Build Summary: {} {}, {} {}, {} {} and took {:.2f}s".format(success_count, SUCCEEDED, fail_count, FAILED, skip_count, SKIPPED, total_time))
print(build_separator)

sys.exit(exit_status)