From 1a974f19f07e156a251ef5f9b4be4131dae1aca9 Mon Sep 17 00:00:00 2001 From: Michal Sojka Date: Mon, 29 Dec 2008 20:31:15 +0100 Subject: [PATCH] omkbuild.py: Makefile.rules are constructed by replacing include directives in snippets This allows for better structured rules and increases readability of snippets. It is also possible to test rules without "compiling" them by omkbuild.py as include directive is interpreted by make in the same way. --- Makefile | 6 +- omkbuild.py | 120 ++++++++++++++++++++++++---------- snippets/Makefile | 18 ++++- snippets/Makefile.rules.linux | 9 +++ snippets/base | 1 + 5 files changed, 114 insertions(+), 40 deletions(-) create mode 100644 snippets/Makefile.rules.linux diff --git a/Makefile b/Makefile index ef2541e..4c2f726 100644 --- a/Makefile +++ b/Makefile @@ -4,12 +4,10 @@ all: buildrules buildrules: - chmod +x omkbuild.py - ./omkbuild.py --all + $(MAKE) -C snippets $@ split: - chmod +x omkbuild.py - cd snippets; ../omkbuild.py --split=../Makefile.rules + $(MAKE) -C snippets $@ RULES_TO_SPLIT=../Makefile.rules test tests: $(MAKE) -C tests diff --git a/omkbuild.py b/omkbuild.py index 7f01c3b..68e555e 100755 --- a/omkbuild.py +++ b/omkbuild.py @@ -23,10 +23,16 @@ Snippet syntax: as they are in snippets i.e. copyrights, documentations and rules. * On the first line of each part of the Makefile.rules, there is - special mark of the form #OMK@. This mark - is used for splitting modified Makefile.rules back to the - original snippets. If starts with __, it is - ignored during splitting. + special mark of the form: + + #OMK:[@] + + This mark is used for splitting modified Makefile.rules back to + the original snippets. If starts with __, it + is ignored during splitting. + + * Toplevel snippet has name in the forb Makefile.rules.* and no + other (included) snippet has such name. """ from optparse import OptionParser @@ -199,24 +205,71 @@ class Snippets: s += snip.getDiff(other[snip.name]) return s +# Include directoves matching this r.e. will be replaced by this script +reInclude = re.compile("^include ([^ ]*) #omkbuild") + class MakefileRules(LineList): def __init__(self): self.snippets = Snippets() self.rules = LineList() - def combine(self): - """Combine self.snippets and produces self.rules""" + def _includeSnippets(self, filename, baseFileName="", onlyLoadSnippets=False): + """Recursively traverses snippets according to include + directives. If onlyLoadSnippets is True, self.rules is not + modified ...""" + + if onlyLoadSnippets: + if filename in self.snippets: + sys.stderr.write("Error: Snippet included more than once\n") + # This is not allowed becouse it would cause problems + # during spliting + sys.exit(1) + self.snippets += Snippet(filename) + + lines = self.snippets[filename]['code'] + + addMarker = 1 # The first line of the snippet should be marked + for line in lines: + match = reInclude.match(line) + if match: + # Include other snippet + self._includeSnippets(match.group(1).strip(),\ + filename, + onlyLoadSnippets) + addMarker = 2 # The next line after include should be marked + else: + # Add this line to rules + if addMarker: + if addMarker==1: + line = string.rstrip(line).ljust(80)+" #OMK:%s@%s\n"%(filename,baseFileName) + elif addMarker==2: + line = string.rstrip(line).ljust(80)+" #OMK:%s\n"%(filename) + addMarker = 0 + if not onlyLoadSnippets: + self.rules += [line] + + def combineFrom(self, topLevelSnippet, onlyCheck=False): + """Produces self.rules from the topLevelSnippet and all + snippets included directly or indirectly from it.""" self.rules = LineList() - for type in ['legal', 'doc', 'code']: + if not onlyCheck: + self._includeSnippets(topLevelSnippet, onlyLoadSnippets=True) + + # Append legal and doc parts + for type in ['legal', 'doc']: for snip in self.snippets: lines = snip[type] if len(lines) == 0: continue firstLine = string.rstrip(lines[0]) - self.rules += [firstLine.ljust(60)+" #OMK@%s\n"%snip.name] + self.rules += [firstLine.ljust(80)+" #OMK:%s\n"%snip.name] self.rules += lines[1:] #self.rules += ['a'] # test error + # Append code parts + self._includeSnippets(topLevelSnippet) + + def split(self): """Split self.rules to the original snippets in self.snippets.""" self.snippets = Snippets() @@ -226,7 +279,7 @@ class MakefileRules(LineList): def _getSnipDicts(self): """Split self.rules to the original snippets, which are returened as dictionary of LineLists.""" - snipBegin = re.compile("^(.*)#OMK@(.*)$") + snipBegin = re.compile("^(.*)#OMK:([^@]*)(?:@(.*))?\n$") snipDict = dict() currentLinesList = None @@ -235,6 +288,11 @@ class MakefileRules(LineList): if match: line = match.group(1).rstrip() + "\n" snipName = match.group(2) + includedFrom = match.group(3) + if includedFrom: + if not includedFrom in snipDict: snipDict[includedFrom] = LineList() + snipDict[includedFrom].append("include %s #omkbuild\n" % snipName); + if not snipName in snipDict: snipDict[snipName] = LineList() currentLinesList = snipDict[snipName] @@ -247,7 +305,7 @@ class MakefileRules(LineList): def parseCommandLine(): parser = OptionParser(usage = """ - %prog [-o FILE] snippet1 snippet2 ... build Makefile.rules from snippets + %prog [-o FILE] top-level-snippet build Makefile.rules from the top-level-snippet and included ones %prog [-o - ] -s Makfile.rules """) parser.add_option("-s", "--split", @@ -256,19 +314,15 @@ def parseCommandLine(): parser.add_option("-o", "--output", action="store", dest="output", default=False, metavar="RULES", help="Write Makefile.rules to file RULES") - parser.add_option("-a", "--all", - action="store_true", dest="all", - help="Rebuild all rules acording to rulesdef.py") (options, args) = parser.parse_args() + if len(args) > 1: + parser.print_help() + sys.exit(1) return options, args -def buildRules(fnames, output, name): +def buildRules(topLevelSnippet, output): rules = MakefileRules() - snip_rule_type = Snippet(name="__type") - snip_rule_type.addCodeLine("OMK_RULES_TYPE=%s\n" % name) - rules.snippets += snip_rule_type - rules.snippets.loadFromFiles(fnames) - rules.combine() + rules.combineFrom(topLevelSnippet) rulesCheck = MakefileRules() rulesCheck.rules = rules.rules @@ -292,10 +346,19 @@ def splitRules(rulesFN, output): rulesCheck = MakefileRules() rulesCheck.snippets = rules.snippets - rulesCheck.combine() + + topLevelSnippet = None + for snip in rules.snippets: + if snip.name.startswith("Makefile.rules."): + topLevelSnippet = snip.name + if not topLevelSnippet: + sys.stderr.write("No toplevel snippet (Makefile.rules.*) found\n") + sys.exit(1) + + rulesCheck.combineFrom(topLevelSnippet, onlyCheck=True) # The comparsion is not that simple. The order of rules might be - # different. + # different. FIXME: Is this still true? # if rules.rules != rulesCheck.rules: # sys.stderr.write("Consistency error:\n") # diff = rules.rules.getDiff(rulesCheck.rules) @@ -312,23 +375,12 @@ def splitRules(rulesFN, output): f.writelines(snip.asLinesList()) f.close() -def buildAllRules(): - import rulesdef - os.chdir(snippetsDir) - for rules in rulesdef.rules: - print 'Building rules: %s' % rules - outputDir = os.path.join(sys.path[0], rulesDir, rules) - if not os.path.isdir(outputDir): os.makedirs(outputDir) - buildRules(rulesdef.rules[rules], os.path.join(outputDir, 'Makefile.rules'), rules) - def main(): (options, args) = parseCommandLine() - if options.all: - buildAllRules() - elif options.split: + if options.split: splitRules(options.split, options.output) else: - buildRules(args, options.output) + buildRules(args[0], options.output) if __name__ == "__main__": main() diff --git a/snippets/Makefile b/snippets/Makefile index 409b863..dbd9b51 100644 --- a/snippets/Makefile +++ b/snippets/Makefile @@ -1,2 +1,16 @@ -all: - $(MAKE) -C .. \ No newline at end of file +all: buildrules + +.PHONY: FORCE + +../rules/%/Makefile.rules: Makefile.rules.% FORCE + python ../omkbuild.py -o $@ $< + +TOP_LEVEL_SNIPPETS = $(filter-out %~,$(wildcard Makefile.rules.*)) +RULE_TYPES = $(TOP_LEVEL_SNIPPETS:Makefile.rules.%=%) + +buildrules: $(RULE_TYPES:%=../rules/%/Makefile.rules) + +RULES_TO_SPLIT ?= Makefile.rules + +split: + python ../omkbuild.py --split=$(RULES_TO_SPLIT) diff --git a/snippets/Makefile.rules.linux b/snippets/Makefile.rules.linux new file mode 100644 index 0000000..11f502f --- /dev/null +++ b/snippets/Makefile.rules.linux @@ -0,0 +1,9 @@ +# Test comment in the beginning +include base #omkbuild +# Test comment in the middle +include include #omkbuild +include linux #omkbuild +include config_h #omkbuild +include qt #omkbuild +include sources-list #omkbuild +# Test comment at the end diff --git a/snippets/base b/snippets/base index bb1af3b..e7fb2e5 100644 --- a/snippets/base +++ b/snippets/base @@ -8,6 +8,7 @@ # The OMK build system is distributed under the GNU General Public # License. See file COPYING for details. # +# # input variables # V .. if set to 1, full command text is shown else short form is used # W .. whole tree - if set to 1, make is always called from the top-level directory -- 2.39.2