]> rtime.felk.cvut.cz Git - omk.git/commitdiff
omkbuild.py: Makefile.rules are constructed by replacing include directives in snippets
authorMichal Sojka <sojkam1@fel.cvut.cz>
Mon, 29 Dec 2008 19:31:15 +0000 (20:31 +0100)
committerMichal Sojka <sojkam1@fel.cvut.cz>
Mon, 29 Dec 2008 19:45:56 +0000 (20:45 +0100)
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
omkbuild.py
snippets/Makefile
snippets/Makefile.rules.linux [new file with mode: 0644]
snippets/base

index ef2541eda365d3d33f6f9fdca9c9357ab1d360c3..4c2f7261a468eb23071a5f8031bc181b806bcd5d 100644 (file)
--- 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
index 7f01c3b5064478d5164891bbb52902c6e7095188..68e555eb32d256afcc9f31f15cdec650113f2b93 100755 (executable)
@@ -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@<snippet file name><EOL>. This mark
-     is used for splitting modified Makefile.rules back to the
-     original snippets. If <snippet file name> starts with __, it is
-     ignored during splitting.
+     special mark of the form:
+
+       #OMK:<snippet file name>[@<included from snippet>]<EOL>
+
+     This mark is used for splitting modified Makefile.rules back to
+     the original snippets. If <snippet file name> 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()
index 409b863e3b07831194a468345835702293e7a013..dbd9b51f0d6b119e3bf2d35c5a74c5200b16b1b1 100644 (file)
@@ -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 (file)
index 0000000..11f502f
--- /dev/null
@@ -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
index c782cfec68fddb078f19da66bda10de5d3d9df3e..31a1929722208dae547f5c610c831700de9abadf 100644 (file)
@@ -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