Created
March 21, 2015 15:19
-
-
Save twpayne/bdea90725d3d9b6bba1c to your computer and use it in GitHub Desktop.
Rough-and-ready approximation to Arduino's multi-file sketch assembly process
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
import glob | |
import re | |
import os | |
import sys | |
def assemble_paths(paths): | |
"""Assemble multiple files together into a main sketch. paths is a list | |
of paths to individual files, the first element is assumed to be the | |
main file. The assembled file is written to sys.stdout.""" | |
# find all prototypes in all input files | |
prototypes = [] | |
for path in paths: | |
with open(path) as f: | |
m = re.findall( | |
r"""^( | |
(?:\s*[a-z_\d]+){1,2} # return type | |
\s+[a-z_\d]+\s* # name of prototype | |
\([a-z_,\.\*\&\[\]\s\d]*\) # args | |
)\s*\{ # must end with { | |
""", | |
f.read(), | |
re.X | re.M | re.I | |
) | |
prototypes.extend(p.strip() for p in m) | |
# write output file header | |
sys.stdout.write('#include "Arduino.h"\n') | |
# copy the main file, up to the first non comment/preprocessor/blank line | |
f = open(paths[0]) | |
in_comment = False | |
for line in f: | |
if in_comment: | |
if line.find('*/') != -1: | |
in_comment = False | |
else: | |
if line.find('/*') != -1 and line.find('*/') == -1: # start of multi-line comment | |
in_comment = True | |
elif not re.match(r'\s*(#.*|//.*)?$', line, re.M): | |
break | |
sys.stdout.write(line) | |
# write out the prototypes | |
for p in prototypes: | |
sys.stdout.write(p + ';\n') | |
# continue writing out the rest of the main file | |
sys.stdout.write(line) | |
for line in f: | |
sys.stdout.write(line) | |
f.close() | |
# write out the contents of each of the non-main files | |
for path in paths[1:]: | |
with open(path) as g: | |
sys.stdout.write(g.read()) | |
def assemble_directory(directory): | |
"""Assemble multiple files together in a single directory. The assembled | |
file is written to sys.stdout.""" | |
# find all *.ino and *.pde files | |
paths = glob.glob(directory + '/*.ino') | |
paths += glob.glob(directory + '/*.pde') | |
# if there's a file whose name matches the name of the directory then | |
# assume that this the main file, otherwise assume main.cpp | |
main = directory + '/main.cpp' | |
for path in paths: | |
if os.path.splitext(os.path.basename(path))[0] == os.path.basename(directory): | |
main = path | |
break | |
if main in paths: | |
paths.remove(main) | |
return assemble_paths([main] + paths) | |
if __name__ == '__main__': | |
assemble_directory(sys.argv[1]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment