-#!/usr/bin/env python
+#!/usr/bin/env python2
#
# Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
#
Run 'tools/genboardscfg.py' to create boards.cfg file.
Run 'tools/genboardscfg.py -h' for available options.
+
+This script only works on python 2.6 or later, but not python 3.x.
"""
import errno
REFORMAT_CMD = [os.path.join('tools', 'reformat.py'),
'-i', '-d', '-', '-s', '8']
SHOW_GNU_MAKE = 'scripts/show-gnu-make'
-SLEEP_TIME=0.03
+SLEEP_TIME=0.003
COMMENT_BLOCK = '''#
# List of boards
sys.exit('GNU Make not found')
return ret[0].rstrip()
+def output_is_new():
+ """Check if the boards.cfg file is up to date.
+
+ Returns:
+ True if the boards.cfg file exists and is newer than any of
+ *_defconfig, MAINTAINERS and Kconfig*. False otherwise.
+ """
+ try:
+ ctime = os.path.getctime(BOARD_FILE)
+ except OSError as exception:
+ if exception.errno == errno.ENOENT:
+ # return False on 'No such file or directory' error
+ return False
+ else:
+ raise
+
+ for (dirpath, dirnames, filenames) in os.walk(CONFIG_DIR):
+ for filename in fnmatch.filter(filenames, '*_defconfig'):
+ if fnmatch.fnmatch(filename, '.*'):
+ continue
+ filepath = os.path.join(dirpath, filename)
+ if ctime < os.path.getctime(filepath):
+ return False
+
+ for (dirpath, dirnames, filenames) in os.walk('.'):
+ for filename in filenames:
+ if (fnmatch.fnmatch(filename, '*~') or
+ not fnmatch.fnmatch(filename, 'Kconfig*') and
+ not filename == 'MAINTAINERS'):
+ continue
+ filepath = os.path.join(dirpath, filename)
+ if ctime < os.path.getctime(filepath):
+ return False
+
+ # Detect a board that has been removed since the current boards.cfg
+ # was generated
+ with open(BOARD_FILE) as f:
+ for line in f:
+ if line[0] == '#' or line == '\n':
+ continue
+ defconfig = line.split()[6] + '_defconfig'
+ if not os.path.exists(os.path.join(CONFIG_DIR, defconfig)):
+ return False
+
+ return True
+
### classes ###
class MaintainersDatabase:
Arguments:
output: File object which the result is written to
maintainers_database: An instance of class MaintainersDatabase
+ devnull: file object of 'dev/null'
+ make_cmd: the command name of Make
"""
- self.occupied = False
self.build_dir = tempfile.mkdtemp()
self.devnull = devnull
- self.make_cmd = make_cmd
+ self.ps = subprocess.Popen([make_cmd, 'O=' + self.build_dir,
+ 'allnoconfig'], stdout=devnull)
+ self.occupied = True
self.parser = DotConfigParser(self.build_dir, output,
maintainers_database)
+ self.env = os.environ.copy()
+ self.env['srctree'] = os.getcwd()
+ self.env['UBOOTVERSION'] = 'dummy'
+ self.env['KCONFIG_OBJDIR'] = ''
def __del__(self):
"""Delete the working directory"""
"""
if self.occupied:
return False
- o = 'O=' + self.build_dir
- self.ps = subprocess.Popen([self.make_cmd, o, defconfig],
- stdout=self.devnull)
+
+ with open(os.path.join(self.build_dir, '.tmp_defconfig'), 'w') as f:
+ for line in open(os.path.join(CONFIG_DIR, defconfig)):
+ colon = line.find(':CONFIG_')
+ if colon == -1:
+ f.write(line)
+ else:
+ f.write(line[colon + 1:])
+
+ self.ps = subprocess.Popen([os.path.join('scripts', 'kconfig', 'conf'),
+ '--defconfig=.tmp_defconfig', 'Kconfig'],
+ stdout=self.devnull,
+ cwd=self.build_dir,
+ env=self.env)
+
self.defconfig = defconfig
self.occupied = True
return True
+ def wait(self):
+ """Wait until the current subprocess finishes."""
+ while self.occupied and self.ps.poll() == None:
+ time.sleep(SLEEP_TIME)
+ self.occupied = False
+
def poll(self):
"""Check if the subprocess is running and invoke the .config
parser if the subprocess is terminated.
for i in range(jobs):
self.slots.append(Slot(output, maintainers_database,
devnull, make_cmd))
+ for slot in self.slots:
+ slot.wait()
def add(self, defconfig):
"""Add a new subprocess if a vacant slot is available.
self.in_progress = False
-def gen_boards_cfg(jobs):
+def gen_boards_cfg(jobs=1, force=False):
"""Generate boards.cfg file.
The incomplete boards.cfg is deleted if an error (including
jobs: The number of jobs to run simultaneously
"""
check_top_directory()
+ if not force and output_is_new():
+ print "%s is up to date. Nothing to do." % BOARD_FILE
+ sys.exit(0)
+
generator = BoardsFileGenerator()
generator.generate(jobs)
# Add options here
parser.add_option('-j', '--jobs',
help='the number of jobs to run simultaneously')
+ parser.add_option('-f', '--force', action="store_true", default=False,
+ help='regenerate the output even if it is new')
(options, args) = parser.parse_args()
+
if options.jobs:
try:
jobs = int(options.jobs)
except (OSError, ValueError):
print 'info: failed to get the number of CPUs. Set jobs to 1'
jobs = 1
- gen_boards_cfg(jobs)
+
+ gen_boards_cfg(jobs, force=options.force)
if __name__ == '__main__':
main()