add doit.sh
[openwrt/staging/blogic.git] / gentree.py
index 71e52e44c6b6b0e3c1c209bcae9ee949a7e1afd4..816674b3193f4fb0f9a668c1d045668bcd11aa4a 100755 (executable)
@@ -16,6 +16,7 @@ from lib import bpgpg as gpg
 from lib import bpkup as kup
 from lib.tempdir import tempdir
 from lib import bpreqs as reqs
+from lib import bpversion as gen_version
 
 class Bp_Identity(object):
     """
@@ -233,10 +234,13 @@ def add_automatic_backports(args):
     export = re.compile(r'^EXPORT_SYMBOL(_GPL)?\((?P<sym>[^\)]*)\)')
     bpi = kconfig.get_backport_info(os.path.join(args.bpid.target_dir, 'compat', 'Kconfig'))
     configtree = kconfig.ConfigTree(os.path.join(args.bpid.target_dir, 'Kconfig'), args.bpid)
+    ignore=['Kconfig.kernel', 'Kconfig.versions']
+    configtree.verify_sources(ignore=ignore)
+    git_debug_snapshot(args, "verify sources for automatic backports")
     all_selects = configtree.all_selects()
     for sym, vals in bpi.items():
-        if sym.startswith('BACKPORT_BUILD_'):
-            if not sym[15:] in all_selects:
+        if sym.startswith('BPAUTO_BUILD_'):
+            if not sym[13:] in all_selects:
                 disable_list.append(sym)
                 continue
         symtype, module_name, c_files, h_files = vals
@@ -545,7 +549,7 @@ def apply_patches(args, desc, source_dir, patch_src, target_dir, logwrite=lambda
                 logwrite("Failed to apply changes from %s" % print_name)
                 for line in output:
                     logwrite('> %s' % line)
-            raise Exception('Patch failed')
+            return 2
 
         if args.refresh:
             pfilef = open(pfile + '.tmp', 'a')
@@ -565,7 +569,7 @@ def apply_patches(args, desc, source_dir, patch_src, target_dir, logwrite=lambda
                     logwrite("Failed to diff to refresh %s" % print_name)
                     pfilef.close()
                     os.unlink(pfile + '.tmp')
-                    raise Exception('Refresh failed')
+                    return 2
             pfilef.close()
             os.rename(pfile + '.tmp', pfile)
 
@@ -590,6 +594,7 @@ def apply_patches(args, desc, source_dir, patch_src, target_dir, logwrite=lambda
         print_name = cocci_file[prefix_len:]
         if args.verbose:
             logwrite("Applying SmPL patch %s" % print_name)
+            logwrite(" %s" % cmd)
         sprocess = subprocess.Popen(cmd,
                                     stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
                                     close_fds=True, universal_newlines=True,
@@ -597,8 +602,8 @@ def apply_patches(args, desc, source_dir, patch_src, target_dir, logwrite=lambda
         output = sprocess.communicate()[0]
         sprocess.wait()
         if sprocess.returncode != 0:
-            logwrite("Failed to process SmPL patch %s" % print_name)
-            raise Exception('SmPL patch failed')
+            logwrite("Failed to process SmPL patch %s with %i" % (print_name, sprocess.returncode))
+            return 2
         output = output.split('\n')
         if output[-1] == '':
             output = output[:-1]
@@ -621,7 +626,7 @@ def _main():
     # Our binary requirements go here
     req = reqs.Req()
     req.require('git')
-    req.coccinelle('1.0.0-rc21')
+    req.coccinelle('1.0.6')
     if not req.reqs_match():
         sys.exit(1)
 
@@ -640,11 +645,14 @@ def _main():
                              'and we use git ls-tree to get the files.')
     parser.add_argument('--clean', const=True, default=False, action="store_const",
                         help='Clean output directory instead of erroring if it isn\'t empty')
+    parser.add_argument('--integrate', const=True, default=False, action="store_const",
+                        help='Integrate a future backported kernel solution into ' +
+                             'an older kernel tree source directory.')
     parser.add_argument('--refresh', const=True, default=False, action="store_const",
                         help='Refresh patches as they are applied, the source dir will be modified!')
     parser.add_argument('--base-name', metavar='<name>', type=str, default='Linux',
                         help='name of base tree, default just "Linux"')
-    parser.add_argument('--gitdebug', const=True, default=False, action="store_const",
+    parser.add_argument('--gitdebug', '--git-debug', const=True, default=False, action="store_const",
                         help='Use git, in the output tree, to debug the various transformation steps ' +
                              'that the tree generation makes (apply patches, ...)')
     parser.add_argument('--verbose', const=True, default=False, action="store_const",
@@ -679,9 +687,8 @@ def _main():
     # same prefix for packaging as with kernel integration but
     # there are already some users of the CPTCFG prefix.
     bpid = None
-    integrate = False
-    if integrate:
-        bpid = Bp_Identity(integrate = integrate,
+    if args.integrate:
+        bpid = Bp_Identity(integrate = args.integrate,
                            kconfig_prefix = 'CONFIG_',
                            project_prefix = 'BACKPORT_',
                            project_dir = args.outdir,
@@ -690,7 +697,7 @@ def _main():
                            kconfig_source_var = '$BACKPORT_DIR',
                            )
     else:
-        bpid = Bp_Identity(integrate = integrate,
+        bpid = Bp_Identity(integrate = args.integrate,
                            kconfig_prefix = 'CPTCFG_',
                            project_prefix = '',
                            project_dir = args.outdir,
@@ -764,6 +771,11 @@ def process(kerneldir, copy_list_file, git_revision=None,
                 test_cocci, profile_cocci)
     rel_prep = None
 
+    if bpid.integrate:
+        if args.kup_test or args.test_cocci or args.profile_cocci or args.refresh:
+            logwrite('Cannot use integration with:\n\tkup_test\n\ttest_cocci\n\tprofile_cocci\n\trefresh\n');
+            sys.exit(1)
+
     # start processing ...
     if (args.kup or args.kup_test):
         git_paranoia(source_dir, logwrite)
@@ -798,6 +810,10 @@ def process(kerneldir, copy_list_file, git_revision=None,
     check_output_dir(bpid.target_dir, args.clean)
 
     # do the copy
+    backport_integrate_files = [
+            ('Makefile.kernel', 'Makefile'),
+            ('Kconfig.integrate', 'Kconfig'),
+            ]
     backport_package_files = [(x, x) for x in [
         'Makefile',
         'kconf/',
@@ -819,6 +835,8 @@ def process(kerneldir, copy_list_file, git_revision=None,
 
     if not bpid.integrate:
         backport_files += backport_package_files
+    else:
+        backport_files += backport_integrate_files
 
     if not args.git_revision:
         logwrite('Copy original source files ...')
@@ -843,6 +861,42 @@ def process(kerneldir, copy_list_file, git_revision=None,
     git_debug_snapshot(args, 'Add driver sources')
 
     disable_list = add_automatic_backports(args)
+    if git_tracked_version:
+        backports_version = "(see git)"
+        kernel_version = "(see git)"
+    else:
+        backports_version = git.describe(tree=source_dir, extra_args=['--long'])
+        kernel_version = git.describe(rev=args.git_revision or 'HEAD',
+                                      tree=args.kerneldir,
+                                      extra_args=['--long'])
+
+    if not bpid.integrate:
+        f = open(os.path.join(bpid.target_dir, 'versions'), 'w')
+        f.write('BACKPORTS_VERSION="%s"\n' % backports_version)
+        f.write('BACKPORTED_KERNEL_VERSION="%s"\n' % kernel_version)
+        f.write('BACKPORTED_KERNEL_NAME="%s"\n' % args.base_name)
+        if git_tracked_version:
+            f.write('BACKPORTS_GIT_TRACKED="backport tracker ID: $(shell git rev-parse HEAD 2>/dev/null || echo \'not built in git tree\')"\n')
+        f.close()
+        git_debug_snapshot(args, "add versions files")
+    else:
+        kconf_regexes = [
+                (re.compile(r'.*(?P<key>%%BACKPORT_DIR%%)'), '%%BACKPORT_DIR%%', 'backports/'),
+                (re.compile(r'.*(?P<key>%%BACKPORTS_VERSION%%).*'), '%%BACKPORTS_VERSION%%', backports_version),
+                (re.compile(r'.*(?P<key>%%BACKPORTED_KERNEL_VERSION%%).*'), '%%BACKPORTED_KERNEL_VERSION%%', kernel_version),
+                (re.compile(r'.*(?P<key>%%BACKPORTED_KERNEL_NAME%%).*'), '%%BACKPORTED_KERNEL_NAME%%', args.base_name),
+        ]
+        out = ''
+        for l in open(os.path.join(bpid.target_dir, 'Kconfig'), 'r'):
+            for r in kconf_regexes:
+                m = r[0].match(l)
+                if m:
+                    l = re.sub(r'(' + r[1] + ')', r'' + r[2] + '', l)
+            out += l
+        outf = open(os.path.join(bpid.target_dir, 'Kconfig'), 'w')
+        outf.write(out)
+        outf.close()
+        git_debug_snapshot(args, "modify top level backports/Kconfig with backports identity")
 
     if disable_list:
         # No need to verify_sources() as compat's Kconfig has no 'source' call
@@ -850,11 +904,28 @@ def process(kerneldir, copy_list_file, git_revision=None,
         bpcfg.disable_symbols(disable_list)
     git_debug_snapshot(args, 'Add automatic backports')
 
-    apply_patches(args, "backport", source_dir, 'patches', bpid.target_dir, logwrite)
+    failure = apply_patches(args, "backport", source_dir, 'patches', bpid.target_dir, logwrite)
+    if failure:
+        return failure
+
+    # Kernel integration requires Kconfig.versions already generated for you,
+    # we cannot do this for a package as we have no idea what kernel folks
+    # will be using.
+    if bpid.integrate:
+        kver = gen_version.kernelversion(bpid.project_dir)
+        rel_specs = gen_version.get_rel_spec_stable(kver)
+        if not rel_specs:
+            logwrite('Cannot parse source kernel version, update parser')
+            sys.exit(1)
+        data = gen_version.genkconfig_versions(rel_specs)
+        fo = open(os.path.join(bpid.target_dir, 'Kconfig.versions'), 'w')
+        fo.write(data)
+        fo.close()
+        git_debug_snapshot(args, "generate kernel version requirement Kconfig file")
 
     # some post-processing is required
     configtree = kconfig.ConfigTree(os.path.join(bpid.target_dir, 'Kconfig'), bpid)
-    ignore=['Kconfig.kernel', 'Kconfig.versions']
+    ignore=['Kconfig.kernel', 'Kconfig.versions', 'Kconfig.local']
 
     configtree.verify_sources(ignore=ignore)
     git_debug_snapshot(args, "verify sources on top level backports Kconfig")
@@ -869,36 +940,37 @@ def process(kerneldir, copy_list_file, git_revision=None,
         configtree.force_tristate_modular()
         git_debug_snapshot(args, "force tristate options modular")
 
+    ignore = [os.path.join(bpid.target_dir, x) for x in [
+                'Kconfig.package.hacks',
+                'Kconfig.versions',
+                'Kconfig.local',
+                'Kconfig',
+                ]
+            ]
+    configtree.adjust_backported_configs(ignore=ignore, orig_symbols=orig_symbols)
+    git_debug_snapshot(args, "adjust backports config symbols we port")
+
     configtree.modify_selects()
     git_debug_snapshot(args, "convert select to depends on")
 
-    # write the versioning file
-    if git_tracked_version:
-        backports_version = "(see git)"
-        kernel_version = "(see git)"
-    else:
-        backports_version = git.describe(tree=source_dir, extra_args=['--long'])
-        kernel_version = git.describe(rev=args.git_revision or 'HEAD',
-                                      tree=args.kerneldir,
-                                      extra_args=['--long'])
-    f = open(os.path.join(bpid.target_dir, 'versions'), 'w')
-    f.write('BACKPORTS_VERSION="%s"\n' % backports_version)
-    f.write('BACKPORTED_KERNEL_VERSION="%s"\n' % kernel_version)
-    f.write('BACKPORTED_KERNEL_NAME="%s"\n' % args.base_name)
-    if git_tracked_version:
-        f.write('BACKPORTS_GIT_TRACKED="backport tracker ID: $(shell git rev-parse HEAD 2>/dev/null || echo \'not built in git tree\')"\n')
-    f.close()
-    git_debug_snapshot(args, "add versions files")
-
     symbols = configtree.symbols()
 
     # write local symbol list -- needed during packaging build
     if not bpid.integrate:
-        f = open(os.path.join(bpid.target_dir, '.local-symbols'), 'w')
+        f = open(os.path.join(bpid.target_dir, 'local-symbols'), 'w')
         for sym in symbols:
             f.write('%s=\n' % sym)
         f.close()
         git_debug_snapshot(args, "add symbols files")
+    # also write Kconfig.local, representing all local symbols
+    # with a BACKPORTED_ prefix
+    f = open(os.path.join(bpid.target_dir, 'Kconfig.local'), 'w')
+    for sym in symbols:
+        f.write('config BACKPORTED_%s\n' % sym)
+        f.write('\ttristate\n')
+        f.write('\tdefault %s\n' % sym)
+    f.close()
+    git_debug_snapshot(args, "add Kconfig.local")
 
     # add defconfigs that we want
     defconfigs_dir = os.path.join(source_dir, 'backport', 'defconfigs')
@@ -926,8 +998,15 @@ def process(kerneldir, copy_list_file, git_revision=None,
 
     # rewrite Makefile and source symbols
 
+    # symbols we know only we can provide under the backport project prefix
+    # for which we need an exception.
+    skip_orig_syms = [ bpid.project_prefix + x for x in [
+            'INTEGRATE',
+            ]
+    ]
+    parse_orig_syms = [x for x in orig_symbols if x not in skip_orig_syms ]
     regexes = []
-    for some_symbols in [orig_symbols[i:i + 50] for i in range(0, len(orig_symbols), 50)]:
+    for some_symbols in [parse_orig_syms[i:i + 50] for i in range(0, len(parse_orig_syms), 50)]:
         r = 'CONFIG_((' + '|'.join([s + '(_MODULE)?' for s in some_symbols]) + ')([^A-Za-z0-9_]|$))'
         regexes.append(re.compile(r, re.MULTILINE))
     for root, dirs, files in os.walk(bpid.target_dir):
@@ -938,6 +1017,8 @@ def process(kerneldir, copy_list_file, git_revision=None,
             data = open(os.path.join(root, f), 'r').read()
             for r in regexes:
                 data = r.sub(r'' + bpid.full_prefix + '\\1', data)
+            # we have an absolue path in $(src) since we compile out of tree
+            data = re.sub(r'\$\(srctree\)/\$\(src\)', '$(src)', data)
             data = re.sub(r'\$\(srctree\)', '$(backport_srctree)', data)
             data = re.sub(r'-Idrivers', '-I$(backport_srctree)/drivers', data)
             if bpid.integrate:
@@ -949,7 +1030,10 @@ def process(kerneldir, copy_list_file, git_revision=None,
     git_debug_snapshot(args, "rename config symbol / srctree usage")
 
     # disable unbuildable Kconfig symbols and stuff Makefiles that doesn't exist
-    maketree = make.MakeTree(os.path.join(bpid.target_dir, 'Makefile.kernel'))
+    if bpid.integrate:
+        maketree = make.MakeTree(os.path.join(bpid.target_dir, 'Makefile'))
+    else:
+        maketree = make.MakeTree(os.path.join(bpid.target_dir, 'Makefile.kernel'))
     disable_kconfig = []
     disable_makefile = []
     for sym in maketree.get_impossible_symbols():
@@ -970,7 +1054,7 @@ def process(kerneldir, copy_list_file, git_revision=None,
             elif (dep == "DISABLE"):
                     new.append('BACKPORT_DISABLED_KCONFIG_OPTION')
             else:
-                    new.append('!BACKPORT_KERNEL_%s' % dep.replace('.', '_'))
+                    new.append('!KERNEL_%s' % dep.replace('.', '_'))
         if bpid.integrate:
             deplist[sym] = ["BACKPORT_" + x for x in new]
         else:
@@ -988,7 +1072,7 @@ def process(kerneldir, copy_list_file, git_revision=None,
     # groups -- 50 seemed safer and is still fast)
     regexes = []
     for some_symbols in [disable_makefile[i:i + 50] for i in range(0, len(disable_makefile), 50)]:
-        r = '^([^#].*((' + bpid.full_prefix_resafe + '|CONFIG_)(' + '|'.join([s for s in some_symbols]) + ')))'
+        r = '^(([^#].*((' + bpid.full_prefix_resafe + '|CONFIG_)(' + '|'.join([s for s in some_symbols]) + ')))\W)'
         regexes.append(re.compile(r, re.MULTILINE))
     for f in maketree.get_makefiles():
         data = open(f, 'r').read()
@@ -999,6 +1083,17 @@ def process(kerneldir, copy_list_file, git_revision=None,
         fo.close()
     git_debug_snapshot(args, "disable unsatisfied Makefile parts")
 
+    if bpid.integrate:
+        f = open(os.path.join(bpid.project_dir, 'Kconfig'), 'a')
+        f.write('source "backports/Kconfig"\n')
+        f.close()
+        git_debug_snapshot(args, "hooked backport to top level Kconfig")
+
+        failure = apply_patches(args, "integration", source_dir, 'integration-patches/',
+                                bpid.project_dir, logwrite)
+        if failure:
+            return failure
+
     if (args.kup or args.kup_test):
         req = reqs.Req()
         req.kup()