print("running extra script...") import os import sys import inspect import gzip import shutil Import("env") GEN_DIR = 'lib/generated' OWN_FILE = "extra_script.py" INDEXJS = "index.js" INDEXCSS = "index.css" # embedded files definition is generated inside here EMBEDDED_INCLUDE="embeddedfiles.h" def basePath(): #see: https://stackoverflow.com/questions/16771894/python-nameerror-global-name-file-is-not-defined return os.path.dirname(inspect.getfile(lambda: None)) def is_current(infile, outfile): if os.path.exists(outfile): otime = os.path.getmtime(outfile) itime = os.path.getmtime(infile) if (otime >= itime): own = os.path.join(basePath(), OWN_FILE) if os.path.exists(own): owntime = os.path.getmtime(own) if owntime > otime: return False print(f"{outfile} is newer than {infile}, no need to recreate") return True return False def compress_file(infile, outfile): if is_current(infile, outfile): return print(f"compressing {infile}") with open(infile, 'rb') as f_in: with gzip.open(outfile, 'wb') as f_out: shutil.copyfileobj(f_in, f_out) def write_file_if_changed(filename, data): """ Create or update file if it not contains data as content """ if os.path.exists(filename): changetype = 'updating' with open(filename, 'r') as fh: if fh.read() == data: print(f"{filename} is up to date") return False else: changetype = 'generating' print(f"#{changetype} {filename}") with open(filename, 'w') as fh: fh.write(data) return True def get_embedded_files(env): filelist = [] efiles = env.GetProjectOption("board_build.embed_files") for f in efiles.split("\n"): if f == '': continue filelist.append(f) return filelist def get_content_type(fn): if (fn.endswith('.gz')): fn = fn[0:-3] if (fn.endswith('html')): return "text/html" if (fn.endswith('json')): return "application/json" if (fn.endswith('js')): return "text/javascript" if (fn.endswith('css')): return "text/css" if (fn.endswith('png')): return "image/png" if (fn.endswith('jpg') or fn.endswith('jpeg')): return "image/jpeg" return "application/octet-stream" def join_files(target, filename, dirlist): """ Join files named filename within different directories into one single gzip archive (located in generated dir) """ print("joinfiles: {} into {} from dirs [{}]".format(filename, target, ','.join(dirlist))) flist = [] for dir in dirlist: fn = os.path.join(dir, filename) if os.path.exists(fn): flist.append(fn) current = False if os.path.exists(target): current = True for f in flist: if not is_current(f, target): current = False break if current: print(f"{target} is up to date") return print(f"creating {target}") # add multiple files with gzip.open(target, "wb") as oh: for fn in flist: print("adding {} to {}".format(fn, target)) with open(fn, "rb") as rh: shutil.copyfileobj(rh, oh) def prebuild(env): print("#prebuild running") # directory for dynamically generated files gendir = os.path.join(basePath(), GEN_DIR) if not os.path.exists(gendir): os.makedirs(gendir) if not os.path.isdir(gendir): print("unable to create directory {}".format(gendir)) sys.exit(1) # join static web server files # only useful for different task dirs with custom configs # join_files(os.path.join(gendir, INDEXJS+".gz"), INDEXJS, ["web"]) # join_files(os.path.join(gendir, INDEXCSS+".gz"), INDEXCSS, ["web"]) # platformio defined embedded files as list pio_embedded = get_embedded_files(env) filedefs = [] for ef in pio_embedded: print(f"#checking embedded file {ef}") # files are defined with relative path to platformio.ini # the name can be with extension gz or without (dn, fn) = os.path.split(ef) pureName = fn if pureName.endswith('.gz'): pureName = pureName[0:-3] usname = ef.replace('/','_').replace('.','_') # sanitize filenames filedefs.append((pureName, usname, get_content_type(pureName))) infile = os.path.join(basePath(), "web", pureName) if os.path.exists(infile): compress_file(infile, ef) else: print("#WARNING: infile {infile} for {ef} not found") # generate c-header file for embedding zip files content = "" for entry in filedefs: content += 'EMBED_GZ_FILE("{}", {}, "{}");\n'.format(*entry) write_file_if_changed(os.path.join(gendir, EMBEDDED_INCLUDE), content) print("#prescript...") prebuild(env)