add doit.sh
[openwrt/staging/blogic.git] / gentree.py
index dd7af84a4ffa1d19858beccb93250550dea1fd1c..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):
     """
@@ -30,7 +31,10 @@ class Bp_Identity(object):
     are added, how we actually use the others for regular printing will
     need to be considered.
     """
-    def __init__(self, integrate=False, kconfig_prefix='CPTCFG_', project_prefix=''):
+    def __init__(self, integrate=False, kconfig_prefix='CPTCFG_',
+                 project_prefix='', project_dir='',
+                 target_dir='', target_dir_name='',
+                 kconfig_source_var=None):
         self.integrate = integrate
         self.kconfig_prefix = kconfig_prefix
         self.kconfig_prefix_resafe = re.escape(kconfig_prefix)
@@ -38,6 +42,14 @@ class Bp_Identity(object):
         self.project_prefix_resafe = re.escape(project_prefix)
         self.full_prefix = kconfig_prefix + project_prefix
         self.full_prefix_resafe = re.escape(self.full_prefix)
+        self.project_dir = project_dir
+        self.target_dir = target_dir
+        self.target_dir_name = target_dir_name
+        self.kconfig_source_var = kconfig_source_var
+        if self.kconfig_source_var:
+            self.kconfig_source_var_resafe = re.escape(self.kconfig_source_var)
+        else:
+            self.kconfig_source_var_resafe = None
 
 def read_copy_list(copyfile):
     """
@@ -217,15 +229,18 @@ def automatic_backport_mangle_c_file(name):
     return name.replace('/', '-')
 
 
-def add_automatic_backports(args, bpid):
+def add_automatic_backports(args):
     disable_list = []
     export = re.compile(r'^EXPORT_SYMBOL(_GPL)?\((?P<sym>[^\)]*)\)')
-    bpi = kconfig.get_backport_info(os.path.join(args.outdir, 'compat', 'Kconfig'))
-    configtree = kconfig.ConfigTree(os.path.join(args.outdir, 'Kconfig'))
+    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
@@ -238,41 +253,41 @@ def add_automatic_backports(args, bpid):
             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)
+            copy_git_files(args.kerneldir, files, args.git_revision, args.bpid.target_dir)
         else:
-            copy_files(args.kerneldir, files, args.outdir)
+            copy_files(args.kerneldir, files, args.bpid.target_dir)
 
         # now add the Makefile line
-        mf = open(os.path.join(args.outdir, 'compat', 'Makefile'), 'a+')
+        mf = open(os.path.join(args.bpid.target_dir, 'compat', 'Makefile'), 'a+')
         o_files = [automatic_backport_mangle_c_file(f)[:-1] + 'o' for f in c_files]
         if symtype == 'tristate':
             if not module_name:
                 raise Exception('backporting a module requires a #module-name')
             for of in o_files:
                 mf.write('%s-objs += %s\n' % (module_name, of))
-            mf.write('obj-$(%s%s) += %s.o\n' % (bpid.full_prefix, sym, module_name))
+            mf.write('obj-$(%s%s) += %s.o\n' % (args.bpid.full_prefix, sym, module_name))
         elif symtype == 'bool':
-            mf.write('compat-$(%s%s) += %s\n' % (bpid.full_prefix, sym, ' '.join(o_files)))
+            mf.write('compat-$(%s%s) += %s\n' % (args.bpid.full_prefix, 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',
+            for l in open(os.path.join(args.bpid.target_dir, 'compat',
                                        automatic_backport_mangle_c_file(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 = open(os.path.join(args.bpid.target_dir, 'include', f), 'w')
             outf.write('/* Automatically created during backport process */\n')
-            outf.write('#ifndef %s%s\n' % (bpid.full_prefix, sym))
+            outf.write('#ifndef %s%s\n' % (args.bpid.full_prefix, 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 /* %s%s */\n' % (bpid.full_prefix, sym))
+            outf.write('#endif /* %s%s */\n' % (args.bpid.full_prefix, sym))
     return disable_list
 
 def git_debug_init(args):
@@ -283,8 +298,11 @@ def git_debug_init(args):
     """
     if not args.gitdebug:
         return
-    git.init(tree=args.outdir)
-    git.commit_all("Copied backport", tree=args.outdir)
+    # Git supports re-initialization, although not well documented it can
+    # reset config stuff, lets avoid that if the tree already exists.
+    if not os.path.exists(os.path.join(args.bpid.project_dir, '.git')):
+        git.init(tree=args.bpid.project_dir)
+    git.commit_all("Copied backport", tree=args.bpid.project_dir)
 
 
 def git_debug_snapshot(args, name):
@@ -293,7 +311,7 @@ def git_debug_snapshot(args, name):
     """
     if not args.gitdebug:
         return
-    git.commit_all(name, tree=args.outdir)
+    git.commit_all(name, tree=args.bpid.project_dir)
 
 def get_rel_spec_stable(rel):
     """
@@ -426,12 +444,12 @@ def upload_release(args, rel_prep, logwrite=lambda x:None):
     if (rel_prep['stable']):
         korg_path += "/stable"
 
-    parent = os.path.dirname(args.outdir)
-    release = os.path.basename(args.outdir)
+    parent = os.path.dirname(args.bpid.project_dir)
+    release = os.path.basename(args.bpid.project_dir)
     tar_name = parent + '/' + release + ".tar"
     gzip_name = tar_name + ".gz"
 
-    create_tar_and_gz(tar_name, args.outdir)
+    create_tar_and_gz(tar_name, args.bpid.project_dir)
 
     logwrite(gpg.sign(tar_name, extra_args=['--armor', '--detach-sign']))
 
@@ -531,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')
@@ -551,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)
 
@@ -576,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,
@@ -583,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]
@@ -607,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)
 
@@ -626,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",
@@ -656,13 +678,43 @@ def _main():
                              'of changes done by Coccinelle.')
     args = parser.parse_args()
 
+    # When building a package we use CPTCFG as we can rely on the
+    # fact that kconfig treats CONFIG_ as an environment variable
+    # requring less changes on code. For kernel integration we use
+    # the longer CONFIG_BACKPORT given that we'll be sticking to
+    # the kernel symbol namespace, to address that we do a final
+    # search / replace. Technically its possible to rely on the
+    # same prefix for packaging as with kernel integration but
+    # there are already some users of the CPTCFG prefix.
+    bpid = None
+    if args.integrate:
+        bpid = Bp_Identity(integrate = args.integrate,
+                           kconfig_prefix = 'CONFIG_',
+                           project_prefix = 'BACKPORT_',
+                           project_dir = args.outdir,
+                           target_dir = os.path.join(args.outdir, 'backports/'),
+                           target_dir_name = 'backports/',
+                           kconfig_source_var = '$BACKPORT_DIR',
+                           )
+    else:
+        bpid = Bp_Identity(integrate = args.integrate,
+                           kconfig_prefix = 'CPTCFG_',
+                           project_prefix = '',
+                           project_dir = args.outdir,
+                           target_dir = args.outdir,
+                           target_dir_name = '',
+                           kconfig_source_var = '$BACKPORT_DIR',
+                           )
+
     def logwrite(msg):
         sys.stdout.write(msg)
         sys.stdout.write('\n')
         sys.stdout.flush()
 
-    return process(args.kerneldir, args.outdir, args.copy_list,
-                   git_revision=args.git_revision, clean=args.clean,
+    return process(args.kerneldir, args.copy_list,
+                   git_revision=args.git_revision,
+                   bpid=bpid,
+                   clean=args.clean,
                    refresh=args.refresh, base_name=args.base_name,
                    gitdebug=args.gitdebug, verbose=args.verbose,
                    extra_driver=args.extra_driver,
@@ -672,7 +724,8 @@ def _main():
                    profile_cocci=args.profile_cocci,
                    logwrite=logwrite)
 
-def process(kerneldir, outdir, copy_list_file, git_revision=None,
+def process(kerneldir, copy_list_file, git_revision=None,
+            bpid=None,
             clean=False, refresh=False, base_name="Linux", gitdebug=False,
             verbose=False, extra_driver=[], kup=False,
             kup_test=False,
@@ -681,16 +734,16 @@ def process(kerneldir, outdir, copy_list_file, git_revision=None,
             logwrite=lambda x:None,
             git_tracked_version=False):
     class Args(object):
-        def __init__(self, kerneldir, outdir, copy_list_file,
-                     git_revision, clean, refresh, base_name,
+        def __init__(self, kerneldir, copy_list_file,
+                     git_revision, bpid, clean, refresh, base_name,
                      gitdebug, verbose, extra_driver, kup,
                      kup_test,
                      test_cocci,
                      profile_cocci):
             self.kerneldir = kerneldir
-            self.outdir = outdir
             self.copy_list = copy_list_file
             self.git_revision = git_revision
+            self.bpid = bpid
             self.clean = clean
             self.refresh = refresh
             self.base_name = base_name
@@ -712,30 +765,16 @@ def process(kerneldir, outdir, copy_list_file, git_revision=None,
         else:
             logwrite('Validated tree: %s' % tree)
 
-    args = Args(kerneldir, outdir, copy_list_file,
-                git_revision, clean, refresh, base_name,
+    args = Args(kerneldir, copy_list_file,
+                git_revision, bpid, clean, refresh, base_name,
                 gitdebug, verbose, extra_driver, kup, kup_test,
                 test_cocci, profile_cocci)
     rel_prep = None
-    integrate = False
 
-    # When building a package we use CPTCFG as we can rely on the
-    # fact that kconfig treats CONFIG_ as an environment variable
-    # requring less changes on code. For kernel integration we use
-    # the longer CONFIG_BACKPORT given that we'll be sticking to
-    # the kernel symbol namespace, to address that we do a final
-    # search / replace. Technically its possible to rely on the
-    # same prefix for packaging as with kernel integration but
-    # there are already some users of the CPTCFG prefix.
-    bpid = None
-    if integrate:
-        bpid = Bp_Identity(integrate = integrate,
-                           kconfig_prefix = 'CONFIG_',
-                           project_prefix = 'BACKPORT_')
-    else:
-        bpid = Bp_Identity(integrate = integrate,
-                           kconfig_prefix = 'CPTCFG_',
-                           project_prefix = '')
+    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):
@@ -743,7 +782,7 @@ def process(kerneldir, outdir, copy_list_file, git_revision=None,
         git_paranoia(kerneldir, logwrite)
 
         rel_describe = git.describe(rev=None, tree=source_dir, extra_args=['--dirty'])
-        release = os.path.basename(args.outdir)
+        release = os.path.basename(bpid.target_dir)
         version = release.replace("backports-", "")
 
         rel_prep = get_rel_prep(version)
@@ -768,91 +807,174 @@ def process(kerneldir, outdir, copy_list_file, git_revision=None,
     deplist = read_dependencies(os.path.join(source_dir, 'dependencies'))
 
     # validate output directory
-    check_output_dir(args.outdir, args.clean)
+    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/',
+        'Makefile.real',
+        'Makefile.kernel',
+        'Kconfig.package.hacks',
+        'scripts/',
+        '.blacklist.map',
+        '.gitignore',
+        'Makefile.build'] ]
+    backport_package_files += [
+            ('Kconfig.package', 'Kconfig'),
+            ]
     backport_files = [(x, x) for x in [
-        'Kconfig', 'Kconfig.package.hacks',
-        'Makefile', 'Makefile.build', 'Makefile.kernel', '.gitignore',
-        'Makefile.real', 'compat/', 'backport-include/', 'kconf/',
-        'scripts/', '.blacklist.map',
+        'Kconfig.sources',
+        'compat/',
+        'backport-include/',
     ]]
+
+    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 ...')
     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, bpid.target_dir)
 
     git_debug_init(args)
 
     if not args.git_revision:
-        copy_files(args.kerneldir, copy_list, args.outdir)
+        copy_files(args.kerneldir, copy_list, bpid.target_dir)
     else:
-        copy_git_files(args.kerneldir, copy_list, args.git_revision, args.outdir)
+        copy_git_files(args.kerneldir, copy_list, args.git_revision, bpid.target_dir)
 
     # FIXME: should we add a git version of this (e.g. --git-extra-driver)?
     for src, copy_list in args.extra_driver:
         if (args.kup or args.kup_test):
             git_paranoia(src)
-        copy_files(src, read_copy_list(open(copy_list, 'r')), args.outdir)
+        copy_files(src, read_copy_list(open(copy_list, 'r')), bpid.target_dir)
 
     git_debug_snapshot(args, 'Add driver sources')
 
-    disable_list = add_automatic_backports(args, bpid)
+    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:
-        bpcfg = kconfig.ConfigTree(os.path.join(args.outdir, 'compat', 'Kconfig'))
+        # No need to verify_sources() as compat's Kconfig has no 'source' call
+        bpcfg = kconfig.ConfigTree(os.path.join(bpid.target_dir, 'compat', 'Kconfig'), bpid)
         bpcfg.disable_symbols(disable_list)
     git_debug_snapshot(args, 'Add automatic backports')
 
-    apply_patches(args, "backport", source_dir, 'patches', args.outdir, 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(args.outdir, 'Kconfig'))
+    configtree = kconfig.ConfigTree(os.path.join(bpid.target_dir, 'Kconfig'), bpid)
+    ignore=['Kconfig.kernel', 'Kconfig.versions', 'Kconfig.local']
+
+    configtree.verify_sources(ignore=ignore)
+    git_debug_snapshot(args, "verify sources on top level backports Kconfig")
+
     orig_symbols = configtree.symbols()
 
     logwrite('Modify Kconfig tree ...')
-    configtree.prune_sources(ignore=['Kconfig.kernel', 'Kconfig.versions'])
+    configtree.prune_sources(ignore=ignore)
     git_debug_snapshot(args, "prune Kconfig tree")
 
     if not bpid.integrate:
         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(args.outdir, '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(args.outdir, '.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')
-    os.mkdir(os.path.join(args.outdir, 'defconfigs'))
+    os.mkdir(os.path.join(bpid.target_dir, 'defconfigs'))
     for dfbase in os.listdir(defconfigs_dir):
         copy_defconfig = True
         dfsrc = os.path.join(defconfigs_dir, dfbase)
@@ -868,7 +990,7 @@ def process(kerneldir, outdir, copy_list_file, git_revision=None,
                 copy_defconfig = False
                 break
         if copy_defconfig:
-            shutil.copy(dfsrc, os.path.join(args.outdir, 'defconfigs', dfbase))
+            shutil.copy(dfsrc, os.path.join(bpid.target_dir, 'defconfigs', dfbase))
 
     git_debug_snapshot(args, "add (useful) defconfig files")
 
@@ -876,11 +998,18 @@ def process(kerneldir, outdir, 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(args.outdir):
+    for root, dirs, files in os.walk(bpid.target_dir):
         # don't go into .git dir (possible debug thing)
         if '.git' in dirs:
             dirs.remove('.git')
@@ -888,6 +1017,8 @@ def process(kerneldir, outdir, 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:
@@ -899,7 +1030,10 @@ def process(kerneldir, outdir, 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(args.outdir, '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():
@@ -920,7 +1054,7 @@ def process(kerneldir, outdir, 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:
@@ -938,7 +1072,7 @@ def process(kerneldir, outdir, 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()
@@ -949,6 +1083,17 @@ def process(kerneldir, outdir, 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()