tools: moveconfig: Add a new --git-ref option

This option allows the 'make autoconf.mk' step to run against a former
repo state, while the savedefconfig step runs against the current repo
state. This is convenient for the case where something in the Kconfig
has changed such that the defconfig is no longer complete with the new
Kconfigs. This feature allows the .config to be built assuming those old
Kconfigs, but then savedefconfig based on the new state of the Kconfigs.

If in doubt, always specify this switch. It will always do the right
thing even if not required, but if it was required and you don't use it,
the moved configs will be incorrect. When not using this switch, you
must very carefully evaluate that all moved configs are correct.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Masahiro Yamada <yamada.masahiro@socionext.com>
This commit is contained in:
Joe Hershberger 2016-06-10 14:53:32 -05:00 committed by Masahiro Yamada
parent 06cc1d36d0
commit 6b96c1a1ca

View File

@ -143,6 +143,14 @@ Available options
Specify the number of threads to run simultaneously. If not specified, Specify the number of threads to run simultaneously. If not specified,
the number of threads is the same as the number of CPU cores. the number of threads is the same as the number of CPU cores.
-r, --git-ref
Specify the git ref to clone for building the autoconf.mk. If unspecified
use the CWD. This is useful for when changes to the Kconfig affect the
default values and you want to capture the state of the defconfig from
before that change was in effect. If in doubt, specify a ref pre-Kconfig
changes (use HEAD if Kconfig changes are not committed). Worst case it will
take a bit longer to run, but will always do the right thing.
-v, --verbose -v, --verbose
Show any build errors as boards are built Show any build errors as boards are built
@ -584,7 +592,7 @@ class Slot:
for faster processing. for faster processing.
""" """
def __init__(self, configs, options, progress, devnull, make_cmd): def __init__(self, configs, options, progress, devnull, make_cmd, reference_src_dir):
"""Create a new process slot. """Create a new process slot.
Arguments: Arguments:
@ -593,12 +601,15 @@ class Slot:
progress: A progress indicator. progress: A progress indicator.
devnull: A file object of '/dev/null'. devnull: A file object of '/dev/null'.
make_cmd: command name of GNU Make. make_cmd: command name of GNU Make.
reference_src_dir: Determine the true starting config state from this
source tree.
""" """
self.options = options self.options = options
self.progress = progress self.progress = progress
self.build_dir = tempfile.mkdtemp() self.build_dir = tempfile.mkdtemp()
self.devnull = devnull self.devnull = devnull
self.make_cmd = (make_cmd, 'O=' + self.build_dir) self.make_cmd = (make_cmd, 'O=' + self.build_dir)
self.reference_src_dir = reference_src_dir
self.parser = KconfigParser(configs, options, self.build_dir) self.parser = KconfigParser(configs, options, self.build_dir)
self.state = STATE_IDLE self.state = STATE_IDLE
self.failed_boards = [] self.failed_boards = []
@ -636,6 +647,7 @@ class Slot:
self.defconfig = defconfig self.defconfig = defconfig
self.log = '' self.log = ''
self.use_git_ref = True if self.options.git_ref else False
self.do_defconfig() self.do_defconfig()
return True return True
@ -664,9 +676,16 @@ class Slot:
if self.ps.poll() != 0: if self.ps.poll() != 0:
self.handle_error() self.handle_error()
elif self.state == STATE_DEFCONFIG: elif self.state == STATE_DEFCONFIG:
self.do_autoconf() if self.options.git_ref and not self.use_git_ref:
self.do_savedefconfig()
else:
self.do_autoconf()
elif self.state == STATE_AUTOCONF: elif self.state == STATE_AUTOCONF:
self.do_savedefconfig() if self.use_git_ref:
self.use_git_ref = False
self.do_defconfig()
else:
self.do_savedefconfig()
elif self.state == STATE_SAVEDEFCONFIG: elif self.state == STATE_SAVEDEFCONFIG:
self.update_defconfig() self.update_defconfig()
else: else:
@ -689,6 +708,9 @@ class Slot:
cmd = list(self.make_cmd) cmd = list(self.make_cmd)
cmd.append(self.defconfig) cmd.append(self.defconfig)
if self.use_git_ref:
cmd.append('-C')
cmd.append(self.reference_src_dir)
self.ps = subprocess.Popen(cmd, stdout=self.devnull, self.ps = subprocess.Popen(cmd, stdout=self.devnull,
stderr=subprocess.PIPE) stderr=subprocess.PIPE)
self.state = STATE_DEFCONFIG self.state = STATE_DEFCONFIG
@ -708,6 +730,9 @@ class Slot:
cmd.append('CROSS_COMPILE=%s' % self.cross_compile) cmd.append('CROSS_COMPILE=%s' % self.cross_compile)
cmd.append('KCONFIG_IGNORE_DUPLICATES=1') cmd.append('KCONFIG_IGNORE_DUPLICATES=1')
cmd.append('include/config/auto.conf') cmd.append('include/config/auto.conf')
if self.use_git_ref:
cmd.append('-C')
cmd.append(self.reference_src_dir)
self.ps = subprocess.Popen(cmd, stdout=self.devnull, self.ps = subprocess.Popen(cmd, stdout=self.devnull,
stderr=subprocess.PIPE) stderr=subprocess.PIPE)
self.state = STATE_AUTOCONF self.state = STATE_AUTOCONF
@ -784,13 +809,15 @@ class Slots:
"""Controller of the array of subprocess slots.""" """Controller of the array of subprocess slots."""
def __init__(self, configs, options, progress): def __init__(self, configs, options, progress, reference_src_dir):
"""Create a new slots controller. """Create a new slots controller.
Arguments: Arguments:
configs: A list of CONFIGs to move. configs: A list of CONFIGs to move.
options: option flags. options: option flags.
progress: A progress indicator. progress: A progress indicator.
reference_src_dir: Determine the true starting config state from this
source tree.
""" """
self.options = options self.options = options
self.slots = [] self.slots = []
@ -798,7 +825,7 @@ class Slots:
make_cmd = get_make_cmd() make_cmd = get_make_cmd()
for i in range(options.jobs): for i in range(options.jobs):
self.slots.append(Slot(configs, options, progress, devnull, self.slots.append(Slot(configs, options, progress, devnull,
make_cmd)) make_cmd, reference_src_dir))
def add(self, defconfig): def add(self, defconfig):
"""Add a new subprocess if a vacant slot is found. """Add a new subprocess if a vacant slot is found.
@ -855,6 +882,24 @@ class Slots:
for board in failed_boards: for board in failed_boards:
f.write(board + '\n') f.write(board + '\n')
class WorkDir:
def __init__(self):
"""Create a new working directory."""
self.work_dir = tempfile.mkdtemp()
def __del__(self):
"""Delete the working directory
This function makes sure the temporary directory is cleaned away
even if Python suddenly dies due to error. It should be done in here
because it is guaranteed the destructor is always invoked when the
instance of the class gets unreferenced.
"""
shutil.rmtree(self.work_dir)
def get(self):
return self.work_dir
def move_config(configs, options): def move_config(configs, options):
"""Move config options to defconfig files. """Move config options to defconfig files.
@ -871,6 +916,21 @@ def move_config(configs, options):
print 'Move ' + ', '.join(configs), print 'Move ' + ', '.join(configs),
print '(jobs: %d)\n' % options.jobs print '(jobs: %d)\n' % options.jobs
reference_src_dir = ''
if options.git_ref:
work_dir = WorkDir()
reference_src_dir = work_dir.get()
print "Cloning git repo to a separate work directory..."
subprocess.check_output(['git', 'clone', os.getcwd(), '.'],
cwd=reference_src_dir)
print "Checkout '%s' to build the original autoconf.mk." % \
subprocess.check_output(['git', 'rev-parse', '--short',
options.git_ref]).strip()
subprocess.check_output(['git', 'checkout', options.git_ref],
stderr=subprocess.STDOUT,
cwd=reference_src_dir)
if options.defconfigs: if options.defconfigs:
defconfigs = [line.strip() for line in open(options.defconfigs)] defconfigs = [line.strip() for line in open(options.defconfigs)]
for i, defconfig in enumerate(defconfigs): for i, defconfig in enumerate(defconfigs):
@ -888,7 +948,7 @@ def move_config(configs, options):
defconfigs.append(os.path.join(dirpath, filename)) defconfigs.append(os.path.join(dirpath, filename))
progress = Progress(len(defconfigs)) progress = Progress(len(defconfigs))
slots = Slots(configs, options, progress) slots = Slots(configs, options, progress, reference_src_dir)
# Main loop to process defconfig files: # Main loop to process defconfig files:
# Add a new subprocess into a vacant slot. # Add a new subprocess into a vacant slot.
@ -930,6 +990,8 @@ def main():
help='only cleanup the headers') help='only cleanup the headers')
parser.add_option('-j', '--jobs', type='int', default=cpu_count, parser.add_option('-j', '--jobs', type='int', default=cpu_count,
help='the number of jobs to run simultaneously') help='the number of jobs to run simultaneously')
parser.add_option('-r', '--git-ref', type='string',
help='the git ref to clone for building the autoconf.mk')
parser.add_option('-v', '--verbose', action='store_true', default=False, parser.add_option('-v', '--verbose', action='store_true', default=False,
help='show any build errors as boards are built') help='show any build errors as boards are built')
parser.usage += ' CONFIG ...' parser.usage += ' CONFIG ...'