diff --git a/.gitignore b/.gitignore index 80abc34..eea7a0b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ #Ignore files created by automatic test script *.ino.h build-include.txt +tools/script/build diff --git a/STM32/libraries/HardwareTest/examples/AutomaticCompilation/Blink/Blink.ino b/STM32/libraries/HardwareTest/examples/AutomaticCompilation/Blink/Blink.ino new file mode 100644 index 0000000..31cdefe --- /dev/null +++ b/STM32/libraries/HardwareTest/examples/AutomaticCompilation/Blink/Blink.ino @@ -0,0 +1,14 @@ +//Automatic testing compilation of blink sketch + +#ifndef LED_BUILTIN + #define LED_BUILTIN 0 +#endif + +void setup() { + pinMode(LED_BUILTIN, OUTPUT); +} + +void loop() { + digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); + delay(1000); +} diff --git a/STM32/libraries/HardwareTest/examples/AutomaticCompilation/Empty/Empty.ino b/STM32/libraries/HardwareTest/examples/AutomaticCompilation/Empty/Empty.ino new file mode 100644 index 0000000..c82c046 --- /dev/null +++ b/STM32/libraries/HardwareTest/examples/AutomaticCompilation/Empty/Empty.ino @@ -0,0 +1,8 @@ +//Automatic testing compilation of empty sketch + +void setup() { +} + +void loop() { +} + diff --git a/tools/script/board.py b/tools/script/board.py index 067febf..cac35c2 100644 --- a/tools/script/board.py +++ b/tools/script/board.py @@ -49,9 +49,9 @@ for line in boardLines: for id in set(del_boards): del boards[id] -for (id, board) in boards.iteritems(): +for (id, board) in boards.items(): variant_dir = board["build.variant"] - with open(config.arch_dir + "variants/" + variant_dir + "/variant.h") as f: + with open(config.arch_dir + "variants/" + variant_dir + "/variant.h", encoding='utf-8') as f: variant_lines = f.read().splitlines() board["variant_lines"] = variant_lines diff --git a/tools/script/build.html b/tools/script/build.html new file mode 100644 index 0000000..e29414c --- /dev/null +++ b/tools/script/build.html @@ -0,0 +1,93 @@ + + + + + + + + Compilation results for:

+

Compiler version:

+

+ Commit date: (hash: ) +

+ + + + + + + + + + + + + + +
TargetSketchFlash bytesRAM bytesData
+ + + diff --git a/tools/script/run_build.py b/tools/script/run_build.py new file mode 100644 index 0000000..5ff9642 --- /dev/null +++ b/tools/script/run_build.py @@ -0,0 +1,235 @@ +# Compile from command line + +# Example: python run_build.py -v MapleMini_F103CB -s STM32/libraries\HardwareTest\examples\AutomaticCompilation\Basic\Basic.ino -i + +import sys +sys.dont_write_bytecode = True + +import subprocess +import os +import fnmatch +import shutil +import errno +import argparse +import board +import json +import hashlib + +#print(board.boards) +#exit(-1) + +hardware_root = os.path.abspath('../../../') +stm32generic_root = os.path.abspath('../../') +arch_root = os.path.join(stm32generic_root, 'STM32') +tools_root = os.path.join(stm32generic_root, 'tools') + +arduino_builder_default = "C:\\Program Files (x86)\\Arduino\\arduino-builder.exe" +arm_gcc_path_default = "C:\\Users\\" + str(os.environ.get('USERNAME')) + "\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\arm-none-eabi-gcc\\4.8.3-2014q1" + +git_hash = subprocess.check_output(['git', 'rev-parse', '--short', 'HEAD']).decode("ascii").strip() +git_date = subprocess.check_output(['git', 'show', '-s', '--format=%ci']).decode("ascii").strip() + +def build(args, build_target, sketch_path, build_path): + print("Building: ", sketch_path) + print("Variant: ", build_target) + print("Build path: ", build_path) + + already_compiled = os.path.join(build_path, "already_compiled.txt") + + if os.path.exists(already_compiled) and args.ignore_already_compiled: + return + + if os.path.exists(build_path): + shutil.rmtree(build_path) + + os.makedirs(build_path, exist_ok = True) + + command = [] + command.append(args.arduino_builder) + + command.append("-hardware") + command.append(hardware_root) + + command.append("-hardware") + command.append(os.path.dirname(args.arduino_builder) + "/hardware") + + command.append("-tools") + command.append(os.path.dirname(args.arduino_builder) + "/tools-builder") + + command.append("-ide-version=10606") + + command.append("-fqbn") + command.append(build_target) + + + #command.append("-warnings=all") + + command.append("-verbose") + + command.append("-build-path") + command.append(os.path.abspath(build_path)) + + command.append("-prefs") + command.append("runtime.tools.arm-none-eabi-gcc.path=" + args.arm_gcc_path) + + command.append(sketch_path) + + print(command) + + with open(os.path.join(build_path, "stdout.txt"), "w") as stdout, open(os.path.join(build_path, "stderr.txt"), "w") as stderr: + proc = subprocess.Popen(command, stdout = stdout, stderr = stderr) + #proc = subprocess.Popen(command) + + proc.wait() + + for dir in os.listdir(build_path): + if os.path.isdir(os.path.join(build_path, dir)): + shutil.rmtree(os.path.join(build_path, dir)) + + with open(os.path.join(build_path, "disassembly.asm"), "w") as f: + proc = subprocess.Popen([os.path.join(args.arm_gcc_path, "bin", "arm-none-eabi-objdump"), '-d', os.path.join(build_path, os.path.basename(sketch_path) + ".elf")], stdout = f) + + with open(os.path.join(build_path, "nm.txt"), "w") as f: + proc = subprocess.Popen([os.path.join(args.arm_gcc_path, "bin", "arm-none-eabi-nm"), '-S', '--size-sort', '-t', 'd', os.path.join(build_path, os.path.basename(sketch_path) + ".elf")], stdout = f) + + with open(already_compiled, "w") as f: + f.write("Compilation finished") + + +def process_stdout(args, build_target, sketch_path, build_path): + with open(os.path.join(build_path, "stdout.txt")) as f: + lines = f.readlines() + + flash = None + ram = None + + for line in lines: + if 'Sketch uses' in line: + flash = line.split(' ')[2] + if 'Global variables use ' in line: + ram = line.split(' ')[3] + + print("Result: ", flash, ram) + print("--------") + return (flash, ram) + + +def find_inos(path): + ret = [] + for root, dirnames, filenames in os.walk(path): + for filename in fnmatch.filter(filenames, '*.ino'): + ret.append(os.path.join(root, filename)) + return ret + + +def run(args, build_target, sketch): + sketch_path = sketch + + if not sketch.startswith('/'): + sketch_path = stm32generic_root + '/' + sketch + + hash = hashlib.sha256(sketch.encode('utf-8')).hexdigest()[:10].strip() + + build_path = os.path.join(os.path.abspath("."), "build", build_target.replace(":", "_").replace(",", "_").replace("=", "_"), git_hash, hash) + + build(args, build_target, sketch_path, build_path) + return {"build_path": build_path, "result": process_stdout(args, build_target, sketch_path, build_path)} + +def run_manual(args): + for variant in args.variant: + for sketch in args.sketch: + build_target = "STM32GENERIC:STM32:" + variant + + result = run(args, build_target, sketch) + + key = build_target + "|" + git_hash + "|" + sketch + results[key] = result + +def run_auto(args): + + variants = [ + "MapleMini_F103CB:upload_method=STLinkMethod,usb=Disabled", + "MapleMini_F103CB:upload_method=STLinkMethod,usb=SerialUSB", + "MapleMini_F103CB:upload_method=DFUUploadMethod2,usb=Disabled", + "MapleMini_F103CB:upload_method=DFUUploadMethod2,usb=SerialUSB", + + "BluePill:upload_method=STLinkMethod,usb=SerialUSB", + + "BLACK_F407XX:upload_method=STLinkMethod,usb=Disabled,subboard=BLACK_F407VE", + "BLACK_F407XX:upload_method=STLinkMethod,usb=SerialUSB,subboard=BLACK_F407VE", + + + "BLACK_F407XX:upload_method=STLinkMethod,usb=SerialUSB,subboard=BLACK_F407VE", + ] + + for variant in board.boards: + if 'Nucleo' in variant: # Nucleo 64 + if variant[11] == 'R': + variants.append('NUCLEO_64:subboard=' + variant) + else: + variants.append('NUCLEO_144:subboard=' + variant) + + if 'DISCOVERY' in variant: + variants.append(variant) + + for variant in variants: + inos = [] + inos.extend(find_inos(os.path.join(stm32generic_root, "STM32/libraries/HardwareTest/examples/AutomaticCompilation"))) + inos.extend(find_inos(os.path.join(stm32generic_root, "STM32/libraries/BoardExamples/examples/all_boards"))) + inos.extend(find_inos(os.path.join(stm32generic_root, "STM32/libraries/HardwareTimer/examples"))) + inos.extend(find_inos(os.path.join(stm32generic_root, "STM32/libraries/FreeRTOS/examples"))) + inos.extend(find_inos(os.path.join(stm32generic_root, "STM32/libraries/EEPROM/examples"))) + + for sketch in inos: + build_target = "STM32GENERIC:STM32:" + variant + + sketch = os.path.relpath(sketch, stm32generic_root) + + result = run(args, build_target, sketch) + + key = build_target + "|" + git_hash + "|" + sketch + results[key] = result + +parser = argparse.ArgumentParser(description='Process some integers.') + +parser.add_argument('-v', '--variant', choices = board.boards, action = 'append', default = []) +parser.add_argument('-s', '--sketch', action = 'append', default = []) +parser.add_argument('-b', '--arduino_builder', default = arduino_builder_default) +parser.add_argument('-g', '--arm_gcc_path', default = arm_gcc_path_default) +parser.add_argument('-i', '--ignore_already_compiled', action="store_true") +parser.add_argument('-a', '--auto', action="store_true") +parser.add_argument('-o', '--output') + +args = parser.parse_args() + +if not args.auto and (not args.variant or not args.sketch): + print("error: Please specify either -a or -v + -s") + parser.print_help() + exit(-1) + +if not os.path.exists(args.arduino_builder): + print("error: " + args.arduino_builder + " does not exist") + print(" please use -b to set") + exit(-1) + +if not os.path.exists(args.arduino_builder): + print("error: " + args.arm_gcc_path + " does not exist") + print(" please use -g to set") + exit(-1) + +results = {} +if not args.auto: + run_manual(args) +else: + run_auto(args) + +compiler = os.path.basename(os.path.dirname(args.arm_gcc_path)) + " " + os.path.basename(args.arm_gcc_path) + +json_data = {"core": "STM32GENERIC", "compiler": compiler, "git_date": git_date, "git_hash": git_hash, "results": results} + +with open("build/STM32GENERIC-" + git_hash + ".json", "w") as f: + json.dump(json_data, f, indent=4) + +if args.output: + with open(args.output, "w") as f: + json.dump(json_data, f, indent=4) diff --git a/tools/test/README.md b/tools/test/README.md new file mode 100644 index 0000000..6056a7c --- /dev/null +++ b/tools/test/README.md @@ -0,0 +1 @@ +Deprecated, use tools/script/run_build.py instead.