CONFIG_CMD_USB bool n
CONFIG_SYS_TEXT_BASE hex 0x00000000
+Next you must edit the Kconfig to add the menu entries for the configs
+you are moving.
+
And then run this tool giving the file name of the recipe
$ tools/moveconfig.py recipe
Surround each portion of the log with escape sequences to display it
in color on the terminal.
+ -d, --defconfigs
+ Specify a file containing a list of defconfigs to move
+
-n, --dry-run
Peform a trial run that does not make any changes. It is useful to
see what is going to happen before one actually runs it.
Exit immediately if Make exits with a non-zero status while processing
a defconfig file.
+ -H, --headers-only
+ Only cleanup the headers; skip the defconfig processing
+
-j, --jobs
Specify the number of threads to run simultaneously. If not specified,
the number of threads is the same as the number of CPU cores.
+ -v, --verbose
+ Show any build errors as boards are built
+
To see the complete list of supported options, run
$ tools/moveconfig.py -h
STATE_IDLE = 0
STATE_DEFCONFIG = 1
STATE_AUTOCONF = 2
+STATE_SAVEDEFCONFIG = 3
ACTION_MOVE = 0
ACTION_DEFAULT_VALUE = 1
patterns.append(re.compile(r'#\s*define\s+%s\W' % config))
patterns.append(re.compile(r'#\s*undef\s+%s\W' % config))
- for (dirpath, dirnames, filenames) in os.walk('include'):
- for filename in filenames:
- if not fnmatch.fnmatch(filename, '*~'):
- cleanup_one_header(os.path.join(dirpath, filename), patterns,
- dry_run)
+ for dir in 'include', 'arch', 'board':
+ for (dirpath, dirnames, filenames) in os.walk(dir):
+ for filename in filenames:
+ if not fnmatch.fnmatch(filename, '*~'):
+ cleanup_one_header(os.path.join(dirpath, filename),
+ patterns, dry_run)
### classes ###
class KconfigParser:
return CROSS_COMPILE.get(arch, '')
- def parse_one_config(self, config_attr, defconfig_lines,
- dotconfig_lines, autoconf_lines):
+ def parse_one_config(self, config_attr, defconfig_lines, autoconf_lines):
"""Parse .config, defconfig, include/autoconf.mk for one config.
This function looks for the config options in the lines from
config_attr: A dictionary including the name, the type,
and the default value of the target config.
defconfig_lines: lines from the original defconfig file.
- dotconfig_lines: lines from the .config file.
autoconf_lines: lines from the include/autoconf.mk file.
Returns:
else:
default = config + '=' + config_attr['default']
- for line in defconfig_lines + dotconfig_lines:
+ for line in defconfig_lines:
line = line.rstrip()
if line.startswith(config + '=') or line == not_set:
return (ACTION_ALREADY_EXIST, line)
with open(defconfig_path) as f:
defconfig_lines = f.readlines()
- with open(dotconfig_path) as f:
- dotconfig_lines = f.readlines()
-
with open(autoconf_path) as f:
autoconf_lines = f.readlines()
for config_attr in self.config_attrs:
result = self.parse_one_config(config_attr, defconfig_lines,
- dotconfig_lines, autoconf_lines)
+ autoconf_lines)
results.append(result)
log = ''
print log,
if not self.options.dry_run:
- with open(defconfig_path, 'a') as f:
+ with open(dotconfig_path, 'a') as f:
for (action, value) in results:
if action == ACTION_MOVE:
f.write(value + '\n')
pass
shutil.rmtree(self.build_dir)
- def add(self, defconfig):
+ def add(self, defconfig, num, total):
"""Assign a new subprocess for defconfig and add it to the slot.
If the slot is vacant, create a new subprocess for processing the
return False
cmd = list(self.make_cmd)
cmd.append(defconfig)
- self.ps = subprocess.Popen(cmd, stdout=self.devnull)
+ self.ps = subprocess.Popen(cmd, stdout=self.devnull,
+ stderr=subprocess.PIPE)
self.defconfig = defconfig
self.state = STATE_DEFCONFIG
+ self.num = num
+ self.total = total
return True
def poll(self):
return False
if self.ps.poll() != 0:
-
+ errmsg = 'Failed to process.'
+ errout = self.ps.stderr.read()
+ if errout.find('gcc: command not found') != -1:
+ errmsg = 'Compiler not found ('
+ errmsg += color_text(self.options.color, COLOR_YELLOW,
+ self.cross_compile)
+ errmsg += color_text(self.options.color, COLOR_LIGHT_RED,
+ ')')
print >> sys.stderr, log_msg(self.options.color,
COLOR_LIGHT_RED,
self.defconfig,
- "failed to process.")
+ errmsg),
+ if self.options.verbose:
+ print >> sys.stderr, color_text(self.options.color,
+ COLOR_LIGHT_CYAN, errout)
if self.options.exit_on_error:
sys.exit("Exit on error.")
else:
if self.state == STATE_AUTOCONF:
self.parser.update_defconfig(self.defconfig)
+
+ print ' %d defconfigs out of %d\r' % (self.num + 1, self.total),
+ sys.stdout.flush()
+
+ """Save off the defconfig in a consistent way"""
+ cmd = list(self.make_cmd)
+ cmd.append('savedefconfig')
+ self.ps = subprocess.Popen(cmd, stdout=self.devnull,
+ stderr=subprocess.PIPE)
+ self.state = STATE_SAVEDEFCONFIG
+ return False
+
+ if self.state == STATE_SAVEDEFCONFIG:
+ defconfig_path = os.path.join(self.build_dir, 'defconfig')
+ shutil.move(defconfig_path,
+ os.path.join('configs', self.defconfig))
self.state = STATE_IDLE
return True
- cross_compile = self.parser.get_cross_compile()
+ self.cross_compile = self.parser.get_cross_compile()
cmd = list(self.make_cmd)
- if cross_compile:
- cmd.append('CROSS_COMPILE=%s' % cross_compile)
+ if self.cross_compile:
+ cmd.append('CROSS_COMPILE=%s' % self.cross_compile)
+ cmd.append('KCONFIG_IGNORE_DUPLICATES=1')
cmd.append('include/config/auto.conf')
- self.ps = subprocess.Popen(cmd, stdout=self.devnull)
+ """This will be screen-scraped, so be sure the expected text will be
+ returned consistently on every machine by setting LANG=C"""
+ self.ps = subprocess.Popen(cmd, stdout=self.devnull,
+ env=dict(os.environ, LANG='C'),
+ stderr=subprocess.PIPE)
self.state = STATE_AUTOCONF
return False
for i in range(options.jobs):
self.slots.append(Slot(config_attrs, options, devnull, make_cmd))
- def add(self, defconfig):
+ def add(self, defconfig, num, total):
"""Add a new subprocess if a vacant slot is found.
Arguments:
Return True on success or False on failure
"""
for slot in self.slots:
- if slot.add(defconfig):
+ if slot.add(defconfig, num, total):
return True
return False
print >> sys.stderr, color_text(self.options.color,
COLOR_LIGHT_RED, line)
+ with open('moveconfig.failed', 'w') as f:
+ for board in failed_boards:
+ f.write(board + '\n')
+
def move_config(config_attrs, options):
"""Move config options to defconfig files.
the type, and the default value of the target config.
options: option flags
"""
- check_top_directory()
-
if len(config_attrs) == 0:
print 'Nothing to do. exit.'
sys.exit(0)
config_attr['type'],
config_attr['default'])
- # All the defconfig files to be processed
- defconfigs = []
- for (dirpath, dirnames, filenames) in os.walk('configs'):
- dirpath = dirpath[len('configs') + 1:]
- for filename in fnmatch.filter(filenames, '*_defconfig'):
- defconfigs.append(os.path.join(dirpath, filename))
+ if options.defconfigs:
+ defconfigs = [line.strip() for line in open(options.defconfigs)]
+ for i, defconfig in enumerate(defconfigs):
+ if not defconfig.endswith('_defconfig'):
+ defconfigs[i] = defconfig + '_defconfig'
+ if not os.path.exists(os.path.join('configs', defconfigs[i])):
+ sys.exit('%s - defconfig does not exist. Stopping.' %
+ defconfigs[i])
+ else:
+ # All the defconfig files to be processed
+ defconfigs = []
+ for (dirpath, dirnames, filenames) in os.walk('configs'):
+ dirpath = dirpath[len('configs') + 1:]
+ for filename in fnmatch.filter(filenames, '*_defconfig'):
+ defconfigs.append(os.path.join(dirpath, filename))
slots = Slots(config_attrs, options)
# Main loop to process defconfig files:
# Add a new subprocess into a vacant slot.
# Sleep if there is no available slot.
- for defconfig in defconfigs:
- while not slots.add(defconfig):
+ for i, defconfig in enumerate(defconfigs):
+ while not slots.add(defconfig, i, len(defconfigs)):
while not slots.available():
# No available slot: sleep for a while
time.sleep(SLEEP_TIME)
while not slots.empty():
time.sleep(SLEEP_TIME)
+ print ''
slots.show_failed_boards()
- cleanup_headers(config_attrs, options.dry_run)
-
def bad_recipe(filename, linenum, msg):
"""Print error message with the file name and the line number and exit."""
sys.exit("%s: line %d: error : " % (filename, linenum) + msg)
# Add options here
parser.add_option('-c', '--color', action='store_true', default=False,
help='display the log in color')
+ parser.add_option('-d', '--defconfigs', type='string',
+ help='a file containing a list of defconfigs to move')
parser.add_option('-n', '--dry-run', action='store_true', default=False,
help='perform a trial run (show log with no changes)')
parser.add_option('-e', '--exit-on-error', action='store_true',
default=False,
help='exit immediately on any error')
+ parser.add_option('-H', '--headers-only', dest='cleanup_headers_only',
+ action='store_true', default=False,
+ help='only cleanup the headers')
parser.add_option('-j', '--jobs', type='int', default=cpu_count,
help='the number of jobs to run simultaneously')
+ parser.add_option('-v', '--verbose', action='store_true', default=False,
+ help='show any build errors as boards are built')
parser.usage += ' recipe_file\n\n' + \
'The recipe_file should describe config options you want to move.\n' + \
'Each line should contain config_name, type, default_value\n\n' + \
update_cross_compile()
- move_config(config_attrs, options)
+ check_top_directory()
+
+ if not options.cleanup_headers_only:
+ move_config(config_attrs, options)
+
+ cleanup_headers(config_attrs, options.dry_run)
if __name__ == '__main__':
main()