VERSION = '0.1'
+SKIP_CONFIGS = (
+ # CONFIG_VERSION_SIGNATURE is dynamically set during the build
+ 'CONFIG_VERSION_SIGNATURE',
+ # Allow to use a different version of gcc
+ 'CONFIG_CC_VERSION_TEXT',
+)
+
def make_parser():
parser = argparse.ArgumentParser(
description='Manage Ubuntu kernel .config and annotations',
help='Convert annotations to .config format')
ga.add_argument('--import', '-i', action='store',
metavar="FILE", dest='import_file',
- help='Import a .config into annotations')
+ help='Import a full .config for a specific arch and flavour into annotations')
+ ga.add_argument('--update', '-u', action='store',
+ metavar="FILE", dest='update_file',
+ help='Import a partial .config into annotations (only resync configs specified in FILE)')
ga.add_argument('--check', '-k', action='store',
metavar="FILE", dest='check_file',
help='Validate kernel .config with annotations')
print(a.to_config(conf))
def do_import(args):
- # Determine arch and flavour
if args.arch is None:
- arg_fail('error: --arch is required with --import')
+ arg_fail('error: --arch and --flavour are required with --import')
+ if args.flavour is None:
+ arg_fail('error: --arch and --flavour are required with --import')
+ if args.config is not None:
+ arg_fail('error: --config cannot be used with --import (try --update)')
# Merge with the current annotations
+ a = Annotation(args.file)
c = KConfig(args.import_file)
+ a.update(c, arch=args.arch, flavour=args.flavour)
+
+ # Save back to annotations
+ a.save(args.file)
+
+def do_update(args):
+ if args.arch is None:
+ arg_fail('error: --arch is required with --update')
+
+ # Merge with the current annotations
a = Annotation(args.file)
- a.update(c, arch=args.arch, flavour=args.flavour, config=args.config)
+ c = KConfig(args.update_file)
+ if args.config is None:
+ configs = list(set(c.config.keys()) - set(SKIP_CONFIGS))
+ a.update(c, arch=args.arch, flavour=args.flavour, configs=configs)
# Save back to annotations
a.save(args.file)
c_configs = c.config.keys()
# Validate .config against annotations
- SKIP_CONFIGS = (
- # CONFIG_VERSION_SIGNATURE is dynamically set during the build
- 'CONFIG_VERSION_SIGNATURE',
- # Allow to use a different version of gcc
- 'CONFIG_CC_VERSION_TEXT',
- )
for conf in a_configs | c_configs:
if conf in SKIP_CONFIGS:
continue
do_export(args)
elif args.import_file:
do_import(args)
+ elif args.update_file:
+ do_update(args)
elif args.check_file:
do_check(args)
raise Exception(str(e) + f', line = {line}')
return config
- def update(self, c: KConfig, arch: str, flavour: str = None, config: str = None):
+ def update(self, c: KConfig, arch: str, flavour: str = None, configs: list = []):
""" Merge configs from a Kconfig object into Annotation object """
# Determine if we need to import all configs or a single config
- if config is None:
- a_configs = self.search_config(arch=arch, flavour=flavour).keys()
- c_configs = c.config.keys()
- else:
- a_configs = c_configs = {config}
+ if not configs:
+ configs = c.config.keys()
+ configs |= self.search_config(arch=arch, flavour=flavour).keys()
# Import configs from the Kconfig object into Annotations
if flavour is not None:
flavour = arch + f'-{flavour}'
else:
flavour = arch
- for conf in c_configs | a_configs:
+ for conf in configs:
if conf in c.config:
val = c.config[conf]
else:
continue
arch = m.group(1)
if arch not in self.config[conf]['policy']:
- self.config[conf]['policy'][arch] = self.config[conf]['policy'][flavour]
+ continue
if self.config[conf]['policy'][flavour] == self.config[conf]['policy'][arch]:
del self.config[conf]['policy'][flavour]
tmp_a = Annotation(fname)
# Only save local differences (preserve includes)
- for conf in self.config:
+ for conf in sorted(self.config):
old_val = tmp_a.config[conf] if conf in tmp_a.config else None
new_val = self.config[conf]
if old_val != new_val: