summaryrefslogtreecommitdiff
path: root/tools/build_utils.py
blob: 5d735bc17a35dfba7d595739f06b2599e46cf78e (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
import subprocess
import pathlib
import time

build_format = '| {:29} | {:30} | {:18} | {:7} | {:6} | {:6} |'

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


def skip_example(example, board):
    ex_dir = pathlib.Path('examples/') / example
    bsp = pathlib.Path("hw/bsp")

    if (bsp / board / "board.mk").exists():
        # board without family
        board_dir = bsp / board
        family = ""
        mk_contents = ""
    else:
        # board within family
        board_dir = list(bsp.glob("*/boards/" + board))
        if not board_dir:
            # Skip unknown boards
            return True

        board_dir = list(board_dir)[0]

        family_dir = board_dir.parent.parent
        family = family_dir.name

        # family.mk
        family_mk = family_dir / "family.mk"
        mk_contents = family_mk.read_text()

    # Find the mcu, first in family mk then board mk
    if "CFG_TUSB_MCU=OPT_MCU_" not in mk_contents:
        board_mk = board_dir / "board.cmake"
        if not board_mk.exists():
            board_mk = board_dir / "board.mk"

        mk_contents = board_mk.read_text()

    mcu = "NONE"
    for token in mk_contents.split():
        if "CFG_TUSB_MCU=OPT_MCU_" in token:
            # Strip " because cmake files has them.
            token = token.strip("\"")
            _, opt_mcu = token.split("=")
            mcu = opt_mcu[len("OPT_MCU_"):]
            break
        if "esp32s2" in token:
            mcu = "ESP32S2"
            break
        if "esp32s3" in token:
            mcu = "ESP32S3"
            break

    # Skip all OPT_MCU_NONE these are WIP port
    if mcu == "NONE":
        return True

    skip_file = ex_dir / "skip.txt"
    only_file = ex_dir / "only.txt"

    if skip_file.exists() and only_file.exists():
        raise RuntimeError("Only have a skip or only file. Not both.")
    elif skip_file.exists():
        skips = skip_file.read_text().split()
        return ("mcu:" + mcu in skips or
                "board:" + board in skips or
                "family:" + family in skips)
    elif only_file.exists():
        onlys = only_file.read_text().split()
        return not ("mcu:" + mcu in onlys or
                    "board:" + board in onlys or
                    "family:" + family in onlys)

    return False


def build_example(example, board, make_option):
    start_time = time.monotonic()
    flash_size = "-"
    sram_size = "-"

    # succeeded, failed, skipped
    ret = [0, 0, 0]

    make_cmd = "make -j -C examples/{} BOARD={} {}".format(example, board, make_option)

    # Check if board is skipped
    if skip_example(example, board):
        status = SKIPPED
        ret[2] = 1
        print(build_format.format(example, board, status, '-', flash_size, sram_size))
    else:
        #subprocess.run(make_cmd + " clean", shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
        build_result = subprocess.run(make_cmd + " all", shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

        if build_result.returncode == 0:
            status = SUCCEEDED
            ret[0] = 1
            (flash_size, sram_size) = build_size(make_cmd)
            #subprocess.run(make_cmd + " copy-artifact", shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
        else:
            status = FAILED
            ret[1] = 1

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

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

    return ret


def build_size(make_cmd):
    size_output = subprocess.run(make_cmd + ' size', shell=True, stdout=subprocess.PIPE).stdout.decode("utf-8").splitlines()
    for i, l in enumerate(size_output):
        text_title = 'text	   data	    bss	    dec'
        if text_title in l:
            size_list = size_output[i+1].split('\t')
            flash_size = int(size_list[0])
            sram_size = int(size_list[1]) + int(size_list[2])
            return (flash_size, sram_size)

    return (0, 0)