build_utils.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. import subprocess
  2. import pathlib
  3. import time
  4. build_format = '| {:29} | {:30} | {:18} | {:7} | {:6} | {:6} |'
  5. SUCCEEDED = "\033[32msucceeded\033[0m"
  6. FAILED = "\033[31mfailed\033[0m"
  7. SKIPPED = "\033[33mskipped\033[0m"
  8. def skip_example(example, board):
  9. ex_dir = pathlib.Path('examples/') / example
  10. bsp = pathlib.Path("hw/bsp")
  11. if (bsp / board / "board.mk").exists():
  12. # board without family
  13. board_dir = bsp / board
  14. family = ""
  15. mk_contents = ""
  16. else:
  17. # board within family
  18. board_dir = list(bsp.glob("*/boards/" + board))
  19. if not board_dir:
  20. # Skip unknown boards
  21. return True
  22. board_dir = list(board_dir)[0]
  23. family_dir = board_dir.parent.parent
  24. family = family_dir.name
  25. # family CMake
  26. family_mk = family_dir / "family.cmake"
  27. # family.mk
  28. if not family_mk.exists():
  29. family_mk = family_dir / "family.mk"
  30. mk_contents = family_mk.read_text()
  31. # Find the mcu, first in family mk then board mk
  32. if "CFG_TUSB_MCU=OPT_MCU_" not in mk_contents:
  33. board_mk = board_dir / "board.cmake"
  34. if not board_mk.exists():
  35. board_mk = board_dir / "board.mk"
  36. mk_contents = board_mk.read_text()
  37. for token in mk_contents.split():
  38. if "CFG_TUSB_MCU=OPT_MCU_" in token:
  39. # Strip " because cmake files has them.
  40. token = token.strip("\"")
  41. _, opt_mcu = token.split("=")
  42. mcu = opt_mcu[len("OPT_MCU_"):]
  43. # Skip all OPT_MCU_NONE these are WIP port
  44. if mcu == "NONE":
  45. return True
  46. skip_file = ex_dir / "skip.txt"
  47. only_file = ex_dir / "only.txt"
  48. if skip_file.exists() and only_file.exists():
  49. raise RuntimeError("Only have a skip or only file. Not both.")
  50. elif skip_file.exists():
  51. skips = skip_file.read_text().split()
  52. return ("mcu:" + mcu in skips or
  53. "board:" + board in skips or
  54. "family:" + family in skips)
  55. elif only_file.exists():
  56. onlys = only_file.read_text().split()
  57. return not ("mcu:" + mcu in onlys or
  58. "board:" + board in onlys or
  59. "family:" + family in onlys)
  60. return False
  61. def build_example(example, board):
  62. start_time = time.monotonic()
  63. flash_size = "-"
  64. sram_size = "-"
  65. # succeeded, failed, skipped
  66. ret = [0, 0, 0]
  67. # Check if board is skipped
  68. if skip_example(example, board):
  69. status = SKIPPED
  70. ret[2] = 1
  71. print(build_format.format(example, board, status, '-', flash_size, sram_size))
  72. else:
  73. build_result = subprocess.run("make -j -C examples/{} BOARD={} all".format(example, board), shell=True,
  74. stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
  75. if build_result.returncode == 0:
  76. status = SUCCEEDED
  77. ret[0] = 1
  78. (flash_size, sram_size) = build_size(example, board)
  79. subprocess.run("make -j -C examples/{} BOARD={} copy-artifact".format(example, board), shell=True,
  80. stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
  81. else:
  82. status = FAILED
  83. ret[1] = 1
  84. build_duration = time.monotonic() - start_time
  85. print(build_format.format(example, board, status, "{:.2f}s".format(build_duration), flash_size, sram_size))
  86. if build_result.returncode != 0:
  87. print(build_result.stdout.decode("utf-8"))
  88. return ret
  89. def build_size(example, board):
  90. elf_file = 'examples/{}/_build/{}/*.elf'.format(example, board)
  91. size_output = subprocess.run('size {}'.format(elf_file), shell=True, stdout=subprocess.PIPE).stdout.decode("utf-8")
  92. size_list = size_output.split('\n')[1].split('\t')
  93. flash_size = int(size_list[0])
  94. sram_size = int(size_list[1]) + int(size_list[2])
  95. return (flash_size, sram_size)