scripts/build-all.py (109 lines of code) (raw):

#!/usr/bin/env python3 from pathlib import Path import subprocess import os exclude_paths=[ "MT3620_M4_Sample_Code", "AzureSphereDevX", "threadx" "AzureIoT_StoreAndForward/src/SimpleFileSystem", "AzureSphereSquirrel/HLCore", "AzureSphereSquirrel/HLCore/squirrel", "BalancingRobot/Software/RTOS/mt3620_m4_software", "CO2_MonitorHealthySpaces/src/AzureSphereDrivers", "IndustrialDeviceController/Software/HighLevelApp/external", "MQTT-C_Client/src/HighLevelApp/MQTT-C", "BalancingRobot/Software/RTOS/threadx", "AzureIoT_StoreAndForward", "AzureEventGrid/MQTT-C/CMakeLists.txt" ] BUILD_OK = "✅ Build OK" BUILD_FAILED = "❌ Build failed" GENERATE_FAILED = "❌ Generate failed" MISSING_PRESETS = "❌ Missing CMakePresets.json" NOT_SPHERE = "🤔 Not an Azure Sphere project (Consider adding to excludes)" class Messages: def __init__(self): self.messages = {} def add(self, category, instance, detail = None): if not category in self.messages.keys(): self.messages[category] = [] self.messages[category] += [ (instance, detail) ] def categories(self): return self.messages.keys() def instances(self, category): if category not in self.messages.keys(): return [] return self.messages[category] class Log: def __init__(self): pass def _log(self, level, message): print(f"::{level}::{message}") def error(self, message): self._log("error", message) def notice(self, message): self._log("notice", message) def should_exclude(path, exclude_paths): for e in exclude_paths: if e in path: return True return False def code(str, lang=None): lang = lang or "" return f"```{lang}\n{str}\n```\n"; def indent(str, amount=1): return "\n".join( (" " * amount) + line for line in str.split('\n') ) def build(cmakelists, log, messages): print(f"Building {cmakelists}...") preset = "ARM-Release" generate_args = [ "cmake", f"--preset {preset}", str(cmakelists) ] generate = subprocess.run( generate_args, capture_output=True) if generate.returncode != 0: detail = indent(code(generate.stdout.decode("utf-8"))) detail += indent(code(generate.stderr.decode("utf-8"))) messages.add(GENERATE_FAILED, p.parent, detail) return False folder = p.parent.joinpath("out").joinpath(preset) build_args = [ "cmake", "--build", folder] build = subprocess.run(build_args, capture_output=True) if build.returncode != 0: detail = indent(code(build.stdout.decode("utf-8"))) detail += indent(code(build.stderr.decode("utf-8"))) messages.add(BUILD_FAILED, p.parent, detail) return False messages.add(BUILD_OK, p.parent) return True cmakelists = list(( path for path in list(Path(".").rglob("CMakeLists.txt")) if not should_exclude(str(path), exclude_paths) )) log = Log() messages = Messages() success = True for p in cmakelists: azsphere_project = False with open(p,"r") as f: for line in f: if "azsphere_target_add_image_package" in line: azsphere_project = True if not azsphere_project: messages.add(NOT_SPHERE, p) continue print(f"Considering {p}...") folder = p.parent if not folder.joinpath("CMakePresets.json").exists(): messages.add(MISSING_PRESETS, folder) success = False continue if not build(p, log, messages): success = False with open(os.environ.get("GITHUB_STEP_SUMMARY", "summary.md"), "w") as summary: for category in (BUILD_OK, BUILD_FAILED, GENERATE_FAILED, MISSING_PRESETS, NOT_SPHERE): sorted_messages = sorted(messages.instances(category), key=lambda i: i[0]) summary.write(f"# {category}\n") if len(sorted_messages) == 0: summary.write("(none)\n") else: for (message, detail) in sorted_messages: summary.write(f" * **{message}**\n") if detail: summary.write(f"{detail}\n") exit(0 if success else -1)