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: )
+
+
+
+
+ Target |
+ Sketch |
+
+ Flash bytes |
+ RAM bytes |
+
+ Data |
+ |
+
+
+
+
+
+
+
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.