gentree: add ability to create automatic backports
authorJohannes Berg <johannes.berg@intel.com>
Fri, 5 Apr 2013 18:59:02 +0000 (20:59 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Fri, 5 Apr 2013 19:19:32 +0000 (21:19 +0200)
Instead of manually copying code like HDMI and dma-buf,
add the ability to just specify such backports in the
Kconfig file for compat. This will then always update
to the lastest code as well.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
gentree.py
lib/kconfig.py

index 8a918b6bc7752e65149c0350bbb82085434721d0..64dbe3afc83809e78ae98bf99c5a84c1dbae1439 100755 (executable)
@@ -172,6 +172,51 @@ def copy_git_files(srcpath, copy_list, rev, outdir):
             os.chmod(f, int(m, 8))
 
 
+def add_automatic_backports(args):
+    export = re.compile(r'^EXPORT_SYMBOL(_GPL)?\((?P<sym>[^\)]*)\)')
+    bpi = kconfig.get_backport_info(os.path.join(args.outdir, 'compat', 'Kconfig'))
+    for sym, vals in bpi.iteritems():
+        symtype, c_files, h_files = vals
+
+        # first copy files
+        files = []
+        for f in c_files:
+            files.append((f, os.path.join('compat', os.path.basename(f))))
+        for f in h_files:
+            files.append((os.path.join('include', f),
+                          os.path.join('include', os.path.dirname(f), 'backport-' + os.path.basename(f))))
+        if args.git_revision:
+            copy_git_files(args.kerneldir, files, args.git_revision, args.outdir)
+        else:
+            copy_files(args.kerneldir, files, args.outdir)
+
+        # now add the Makefile line
+        mf = open(os.path.join(args.outdir, 'compat', 'Makefile'), 'a+')
+        o_files = [os.path.basename(f)[:-1] + 'o' for f in c_files]
+        if symtype == 'tristate':
+            mf.write('obj-$(CPTCFG_%s) += %s\n' % (sym, ' '.join(o_files)))
+        elif symtype == 'bool':
+            mf.write('compat-$(CPTCFG_%s) += %s\n' % (sym, ' '.join(o_files)))
+
+        # finally create the include file
+        syms = []
+        for f in c_files:
+            for l in open(os.path.join(args.outdir, 'compat', os.path.basename(f)), 'r'):
+                m = export.match(l)
+                if m:
+                    syms.append(m.group('sym'))
+        for f in h_files:
+            outf = open(os.path.join(args.outdir, 'include', f), 'w')
+            outf.write('/* Automatically created during backport process */\n')
+            outf.write('#ifndef CPTCFG_%s\n' % sym)
+            outf.write('#include_next <%s>\n' % f)
+            outf.write('#else\n');
+            for s in syms:
+                outf.write('#undef %s\n' % s)
+                outf.write('#define %s LINUX_BACKPORT(%s)\n' % (s, s))
+            outf.write('#include <%s>\n' % (os.path.dirname(f) + '/backport-' + os.path.basename(f), ))
+            outf.write('#endif /* CPTCFG_%s */\n' % sym)
+
 def git_debug_init(args):
     """
     Initialize a git repository in the output directory and commit the current
@@ -181,7 +226,7 @@ def git_debug_init(args):
     if not args.gitdebug:
         return
     git.init(tree=args.outdir)
-    git.commit_all("Copied code", tree=args.outdir)
+    git.commit_all("Copied backport", tree=args.outdir)
 
 
 def git_debug_snapshot(args, name):
@@ -269,18 +314,26 @@ def process(kerneldir, outdir, copy_list_file, git_revision=None,
     ]]
     if not args.git_revision:
         logwrite('Copy original source files ...')
-        copy_files(os.path.join(source_dir, 'backport'), backport_files, args.outdir)
-        copy_files(args.kerneldir, copy_list, args.outdir)
     else:
         logwrite('Get original source files from git ...')
-        copy_files(os.path.join(source_dir, 'backport'), backport_files, args.outdir)
+    
+    copy_files(os.path.join(source_dir, 'backport'), backport_files, args.outdir)
+
+    git_debug_init(args)
+
+    add_automatic_backports(args)
+    git_debug_snapshot(args, 'Add automatic backports')
+
+    if not args.git_revision:
+        copy_files(args.kerneldir, copy_list, args.outdir)
+    else:
         copy_git_files(args.kerneldir, copy_list, args.git_revision, args.outdir)
 
     # FIXME: should we add a git version of this (e.g. --git-extra-driver)?
     for src, copy_list in args.extra_driver:
         copy_files(src, read_copy_list(open(copy_list, 'r')), args.outdir)
 
-    git_debug_init(args)
+    git_debug_snapshot(args, 'Add driver sources')
 
     logwrite('Apply patches ...')
     patchdirs = []
index 2369f746fa8a2aed07b44a22c4098e71b08eac22..b971c2057e86a0def8f73fa408a6df7c7c770736 100644 (file)
@@ -6,8 +6,10 @@ import os, re
 
 src_line = re.compile(r'^source\s+"?(?P<src>[^\s"]*)"?\s*$')
 tri_line = re.compile(r'^(?P<spc>\s+)tristate')
+bool_line = re.compile(r'^(?P<spc>\s+)bool')
 cfg_line = re.compile(r'^(config|menuconfig)\s+(?P<sym>[^\s]*)')
 sel_line = re.compile(r'^(?P<spc>\s+)select\s+(?P<sym>[^\s]*)\s*$')
+ch_line = re.compile(r'^\s+#(?P<ch>[ch])-file\s*(?P<file>.*)')
 
 class ConfigTree(object):
     def __init__(self, rootfile):
@@ -104,3 +106,51 @@ class ConfigTree(object):
             outf = open(os.path.join(self.basedir, nf), 'w')
             outf.write(out)
             outf.close()
+
+def get_backport_info(filename):
+    """
+    Return a dictionary of
+
+    CONFIG_SYMBOL => (type, C-files, H-files)
+
+    where type is 'bool' or 'tristate' and the C-files/H-files are lists
+    """
+    f = open(filename, 'r')
+    result = {}
+    conf = None
+
+    # trick to always have an empty line last
+    def append_empty(f):
+        for l in f:
+            yield l
+        yield ''
+
+    for line in append_empty(f):
+        m = cfg_line.match(line)
+        if not line.strip() or m:
+            if conf and conf_type and (c_files or h_files):
+                result[conf] = (conf_type, c_files, h_files)
+            conf = None
+            conf_type = None
+            c_files = []
+            h_files = []
+            if m:
+                conf = m.group('sym')
+            continue
+        if not conf:
+            continue
+        m = tri_line.match(line)
+        if m:
+            conf_type = 'tristate'
+            continue
+        m = bool_line.match(line)
+        if m:
+            conf_type = 'bool'
+            continue
+        m = ch_line.match(line)
+        if m:
+            if m.group('ch') == 'c':
+                c_files.append(m.group('file'))
+            elif m.group('ch') == 'h':
+                h_files.append(m.group('file'))
+    return result