+# a dict with some useful additional getters
+class AdvancedDict(dict):
+ def getstr(self, name, default = None):
+ if not name in self: return default
+ val = self[name]
+ if len(val) != 1: raise Exception('%s is a list, but it should not' % name)
+ return val[0]
+
+ def getint(self, name, default = None):
+ return int(self.getstr(name, default))
+
+ def getbool(self, name, default = None):
+ val = self.getstr(name, default)
+ if isinstance(val, bool): return val # already a bool
+ return val.lower() in ('true', 'yes', 'on', '1')
+
+# create a safe-to-call shell command from the array
+def safeCall(*args):
+ res = ""
+ for arg in args:
+ assert arg.find("'") < 0 # ' is not supported
+ if len(res): res += " "
+ res += "'"+arg+"'"
+ return res
+
+# Load a section-less config file: maps parameter names to strings or lists of strings (which are comma-separated or in separate lines)
+# Lines starting with spaces are continuation lines
+def loadConfigFile(file):
+ import shlex
+ # read config file
+ with open(file) as file:
+ result = AdvancedDict()
+ curKey = None
+ for line in file:
+ isCont = len(line) and line[0].isspace() # remember if we were a continuation line
+ if isCont and curKey is None:
+ raise Exception("Invalid config: Starting with continuation line")
+ line = line.strip()
+ if not len(line) or line.startswith("#"): continue # skip empty and comment lines
+ if isCont:
+ # continuation line
+ result[curKey].append(shlex.split(line))
+ else:
+ # option line
+ pos = line.index("=") # will raise exception when substring is not found
+ curKey = line[:pos].strip()
+ value = line[pos+1:]
+ result[curKey] = shlex.split(value)
+ # add some convencience get functions
+ return result
+
+# representation of a build system
+class BuildSystem:
+ def __init__(self, ruleMaker, buildDepends = [], binaryDepends = []):
+ self.ruleMaker = ruleMaker
+ self.buildDepends = buildDepends
+ self.binaryDepends = binaryDepends
+