#!/usr/bin/env python # # Copyright (C) 2019 by Maxim Prokhorov # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from __future__ import print_function import time import glob import argparse import atexit import subprocess import os import sys import datetime from espurna_utils.display import clr, print_warning, Color def restore_source_tree(files): cmd = ["git", "checkout", "-f", "--"] cmd.extend(files) subprocess.check_call(cmd) def try_remove(path): try: os.remove(path) except: # pylint: disable=bare-except print_warning("Please manually remove the file `{}`".format(path)) total_time = 0 def print_total_time(): print() print( clr( Color.BOLD, "> Total time: {}".format(datetime.timedelta(seconds=total_time)), ) ) def run_configurations(args, configurations): cmd = ["platformio", "run"] if not args.no_silent: cmd.extend(["-s"]) cmd.extend(["-e", args.environment]) for cfg in configurations: print(clr(Color.BOLD, "> Building {}".format(cfg)), flush=True) with open(args.custom_h, "w") as custom_h: def write(line): sys.stdout.write(line) custom_h.write(line) name, _ = os.path.splitext(cfg) name = os.path.basename(name) write('#define MANUFACTURER "TEST_BUILD"\n') write('#define DEVICE "{}"\n'.format(name.upper())) with open(cfg, "r") as cfg_file: for line in cfg_file: write(line) os_env = os.environ.copy() os_env["PLATFORMIO_SRC_BUILD_FLAGS"] = "-DUSE_CUSTOM_H" os_env["PLATFORMIO_BUILD_CACHE_DIR"] = "test/pio_cache" if not args.no_single_source: os_env["ESPURNA_BUILD_SINGLE_SOURCE"] = "1" start = time.time() subprocess.check_call(cmd, env=os_env) diff = time.time() - start global total_time total_time += diff print( clr( Color.BOLD, "> {}: {} bytes, {}".format( cfg, os.stat( os.path.join(".pio", "build", args.environment, "firmware.bin") ).st_size, datetime.timedelta(seconds=diff), ), ), flush=True, ) def main(args): if os.path.exists(args.custom_h): raise SystemExit( clr( Color.YELLOW, "{} already exists, please run this script in a git-worktree(1) or a separate directory".format( args.custom_h ), ) ) configurations = [] if not args.no_default: configurations = list(glob.glob(args.default_configurations)) configurations.extend(x for x in (args.add or [])) if not configurations: raise SystemExit(clr(Color.YELLOW, "No configurations selected")) if len(configurations) > 1: atexit.register(print_total_time) print(clr(Color.BOLD, "> Selected configurations:")) for cfg in configurations: print(cfg) if args.list: return if not args.environment: raise SystemExit(clr(Color.YELLOW, "No environment selected")) print(clr(Color.BOLD, "> Selected environment: {}".format(args.environment))) atexit.register(try_remove, args.custom_h) run_configurations(args, configurations) if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument( "-l", "--list", action="store_true", help="List selected configurations" ) parser.add_argument( "--custom-h", default="espurna/config/custom.h", help="Header that will be included in by the config/all.h", ) parser.add_argument( "-n", "--no-default", action="store_true", help="Do not use default configurations (--default-configurations=...)", ) parser.add_argument( "-a", "--add", action="append", help="Add path to selected configurations (can specify multiple times)", ) parser.add_argument("-e", "--environment", help="PIO environment") parser.add_argument( "--default-configurations", default="test/build/*.h", help="(glob) default configuration headers", ) parser.add_argument( "--no-silent", action="store_true", help="Do not silence pio-run" ) parser.add_argument( "--no-single-source", action="store_true", help="Disable 'unity' build" ) main(parser.parse_args())