258 lines
10 KiB
Plaintext
258 lines
10 KiB
Plaintext
|
#!/usr/bin/env python
|
||
|
|
||
|
# OpenEmbedded Development tool
|
||
|
#
|
||
|
# Copyright (C) 2014 Intel Corporation
|
||
|
#
|
||
|
# This program is free software; you can redistribute it and/or modify
|
||
|
# it under the terms of the GNU General Public License version 2 as
|
||
|
# published by the Free Software Foundation.
|
||
|
#
|
||
|
# This program is distributed in the hope that it will be useful,
|
||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
# GNU General Public License for more details.
|
||
|
#
|
||
|
# You should have received a copy of the GNU General Public License along
|
||
|
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||
|
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||
|
|
||
|
import sys
|
||
|
import os
|
||
|
import argparse
|
||
|
import glob
|
||
|
import re
|
||
|
import ConfigParser
|
||
|
import subprocess
|
||
|
import logging
|
||
|
|
||
|
basepath = ''
|
||
|
workspace = {}
|
||
|
config = None
|
||
|
context = None
|
||
|
|
||
|
|
||
|
scripts_path = os.path.dirname(os.path.realpath(__file__))
|
||
|
lib_path = scripts_path + '/lib'
|
||
|
sys.path = sys.path + [lib_path]
|
||
|
import scriptutils
|
||
|
logger = scriptutils.logger_create('devtool')
|
||
|
|
||
|
plugins = []
|
||
|
|
||
|
|
||
|
class ConfigHandler(object):
|
||
|
config_file = ''
|
||
|
config_obj = None
|
||
|
init_path = ''
|
||
|
workspace_path = ''
|
||
|
|
||
|
def __init__(self, filename):
|
||
|
self.config_file = filename
|
||
|
self.config_obj = ConfigParser.SafeConfigParser()
|
||
|
|
||
|
def get(self, section, option, default=None):
|
||
|
try:
|
||
|
ret = self.config_obj.get(section, option)
|
||
|
except (ConfigParser.NoOptionError, ConfigParser.NoSectionError):
|
||
|
if default != None:
|
||
|
ret = default
|
||
|
else:
|
||
|
raise
|
||
|
return ret
|
||
|
|
||
|
def read(self):
|
||
|
if os.path.exists(self.config_file):
|
||
|
self.config_obj.read(self.config_file)
|
||
|
|
||
|
if self.config_obj.has_option('General', 'init_path'):
|
||
|
pth = self.get('General', 'init_path')
|
||
|
self.init_path = os.path.join(basepath, pth)
|
||
|
if not os.path.exists(self.init_path):
|
||
|
logger.error('init_path %s specified in config file cannot be found' % pth)
|
||
|
return False
|
||
|
else:
|
||
|
self.config_obj.add_section('General')
|
||
|
|
||
|
self.workspace_path = self.get('General', 'workspace_path', os.path.join(basepath, 'workspace'))
|
||
|
return True
|
||
|
|
||
|
|
||
|
def write(self):
|
||
|
logger.debug('writing to config file %s' % self.config_file)
|
||
|
self.config_obj.set('General', 'workspace_path', self.workspace_path)
|
||
|
with open(self.config_file, 'w') as f:
|
||
|
self.config_obj.write(f)
|
||
|
|
||
|
class Context:
|
||
|
def __init__(self, **kwargs):
|
||
|
self.__dict__.update(kwargs)
|
||
|
|
||
|
|
||
|
def read_workspace():
|
||
|
global workspace
|
||
|
workspace = {}
|
||
|
if not os.path.exists(os.path.join(config.workspace_path, 'conf', 'layer.conf')):
|
||
|
if context.fixed_setup:
|
||
|
logger.error("workspace layer not set up")
|
||
|
sys.exit(1)
|
||
|
else:
|
||
|
logger.info('Creating workspace layer in %s' % config.workspace_path)
|
||
|
_create_workspace(config.workspace_path, config, basepath)
|
||
|
|
||
|
logger.debug('Reading workspace in %s' % config.workspace_path)
|
||
|
externalsrc_re = re.compile(r'^EXTERNALSRC(_pn-[a-zA-Z0-9-]*)? =.*$')
|
||
|
for fn in glob.glob(os.path.join(config.workspace_path, 'appends', '*.bbappend')):
|
||
|
pn = os.path.splitext(os.path.basename(fn))[0].split('_')[0]
|
||
|
with open(fn, 'r') as f:
|
||
|
for line in f:
|
||
|
if externalsrc_re.match(line.rstrip()):
|
||
|
splitval = line.split('=', 2)
|
||
|
workspace[pn] = splitval[1].strip('" \n\r\t')
|
||
|
break
|
||
|
|
||
|
def create_workspace(args, config, basepath, workspace):
|
||
|
if args.layerpath:
|
||
|
workspacedir = os.path.abspath(args.layerpath)
|
||
|
else:
|
||
|
workspacedir = os.path.abspath(os.path.join(basepath, 'workspace'))
|
||
|
_create_workspace(workspacedir, config, basepath, args.create_only)
|
||
|
|
||
|
def _create_workspace(workspacedir, config, basepath, create_only=False):
|
||
|
import bb
|
||
|
|
||
|
confdir = os.path.join(workspacedir, 'conf')
|
||
|
if os.path.exists(os.path.join(confdir, 'layer.conf')):
|
||
|
logger.info('Specified workspace already set up, leaving as-is')
|
||
|
else:
|
||
|
# Add a config file
|
||
|
bb.utils.mkdirhier(confdir)
|
||
|
with open(os.path.join(confdir, 'layer.conf'), 'w') as f:
|
||
|
f.write('# ### workspace layer auto-generated by devtool ###\n')
|
||
|
f.write('BBPATH =. "$' + '{LAYERDIR}:"\n')
|
||
|
f.write('BBFILES += "$' + '{LAYERDIR}/recipes/*/*.bb \\\n')
|
||
|
f.write(' $' + '{LAYERDIR}/appends/*.bbappend"\n')
|
||
|
f.write('BBFILE_COLLECTIONS += "workspacelayer"\n')
|
||
|
f.write('BBFILE_PATTERN_workspacelayer = "^$' + '{LAYERDIR}/"\n')
|
||
|
f.write('BBFILE_PATTERN_IGNORE_EMPTY_workspacelayer = "1"\n')
|
||
|
f.write('BBFILE_PRIORITY_workspacelayer = "99"\n')
|
||
|
# Add a README file
|
||
|
with open(os.path.join(workspacedir, 'README'), 'w') as f:
|
||
|
f.write('This layer was created by the OpenEmbedded devtool utility in order to\n')
|
||
|
f.write('contain recipes and bbappends. In most instances you should use the\n')
|
||
|
f.write('devtool utility to manage files within it rather than modifying files\n')
|
||
|
f.write('directly (although recipes added with "devtool add" will often need\n')
|
||
|
f.write('direct modification.)\n')
|
||
|
f.write('\nIf you no longer need to use devtool you can remove the path to this\n')
|
||
|
f.write('workspace layer from your conf/bblayers.conf file (and then delete the\n')
|
||
|
f.write('layer, if you wish).\n')
|
||
|
if not create_only:
|
||
|
# Add the workspace layer to bblayers.conf
|
||
|
bblayers_conf = os.path.join(basepath, 'conf', 'bblayers.conf')
|
||
|
if not os.path.exists(bblayers_conf):
|
||
|
logger.error('Unable to find bblayers.conf')
|
||
|
return -1
|
||
|
bb.utils.edit_bblayers_conf(bblayers_conf, workspacedir, config.workspace_path)
|
||
|
if config.workspace_path != workspacedir:
|
||
|
# Update our config to point to the new location
|
||
|
config.workspace_path = workspacedir
|
||
|
config.write()
|
||
|
|
||
|
|
||
|
def main():
|
||
|
global basepath
|
||
|
global config
|
||
|
global context
|
||
|
|
||
|
context = Context(fixed_setup=False)
|
||
|
|
||
|
# Default basepath
|
||
|
basepath = os.path.dirname(os.path.abspath(__file__))
|
||
|
pth = basepath
|
||
|
while pth != '' and pth != os.sep:
|
||
|
if os.path.exists(os.path.join(pth, '.devtoolbase')):
|
||
|
context.fixed_setup = True
|
||
|
basepath = pth
|
||
|
break
|
||
|
pth = os.path.dirname(pth)
|
||
|
|
||
|
parser = argparse.ArgumentParser(description="OpenEmbedded development tool",
|
||
|
epilog="Use %(prog)s <subcommand> --help to get help on a specific command")
|
||
|
parser.add_argument('--basepath', help='Base directory of SDK / build directory')
|
||
|
parser.add_argument('-d', '--debug', help='Enable debug output', action='store_true')
|
||
|
parser.add_argument('-q', '--quiet', help='Print only errors', action='store_true')
|
||
|
parser.add_argument('--color', choices=['auto', 'always', 'never'], default='auto', help='Colorize output (where %(metavar)s is %(choices)s)', metavar='COLOR')
|
||
|
|
||
|
subparsers = parser.add_subparsers(dest="subparser_name", title='subcommands', metavar='<subcommand>')
|
||
|
|
||
|
if not context.fixed_setup:
|
||
|
parser_create_workspace = subparsers.add_parser('create-workspace',
|
||
|
help='Set up a workspace',
|
||
|
description='Sets up a new workspace. NOTE: other devtool subcommands will create a workspace automatically as needed, so you only need to use %(prog)s if you want to specify where the workspace should be located.')
|
||
|
parser_create_workspace.add_argument('layerpath', nargs='?', help='Path in which the workspace layer should be created')
|
||
|
parser_create_workspace.add_argument('--create-only', action="store_true", help='Only create the workspace layer, do not alter configuration')
|
||
|
parser_create_workspace.set_defaults(func=create_workspace)
|
||
|
|
||
|
scriptutils.load_plugins(logger, plugins, os.path.join(scripts_path, 'lib', 'devtool'))
|
||
|
for plugin in plugins:
|
||
|
if hasattr(plugin, 'register_commands'):
|
||
|
plugin.register_commands(subparsers, context)
|
||
|
|
||
|
args = parser.parse_args()
|
||
|
|
||
|
if args.debug:
|
||
|
logger.setLevel(logging.DEBUG)
|
||
|
elif args.quiet:
|
||
|
logger.setLevel(logging.ERROR)
|
||
|
|
||
|
if args.basepath:
|
||
|
# Override
|
||
|
basepath = args.basepath
|
||
|
elif not context.fixed_setup:
|
||
|
basepath = os.environ.get('BUILDDIR')
|
||
|
if not basepath:
|
||
|
logger.error("This script can only be run after initialising the build environment (e.g. by using oe-init-build-env)")
|
||
|
sys.exit(1)
|
||
|
|
||
|
logger.debug('Using basepath %s' % basepath)
|
||
|
|
||
|
config = ConfigHandler(os.path.join(basepath, 'conf', 'devtool.conf'))
|
||
|
if not config.read():
|
||
|
return -1
|
||
|
|
||
|
bitbake_subdir = config.get('General', 'bitbake_subdir', '')
|
||
|
if bitbake_subdir:
|
||
|
# Normally set for use within the SDK
|
||
|
logger.debug('Using bitbake subdir %s' % bitbake_subdir)
|
||
|
sys.path.insert(0, os.path.join(basepath, bitbake_subdir, 'lib'))
|
||
|
core_meta_subdir = config.get('General', 'core_meta_subdir')
|
||
|
sys.path.insert(0, os.path.join(basepath, core_meta_subdir, 'lib'))
|
||
|
else:
|
||
|
# Standard location
|
||
|
import scriptpath
|
||
|
bitbakepath = scriptpath.add_bitbake_lib_path()
|
||
|
if not bitbakepath:
|
||
|
logger.error("Unable to find bitbake by searching parent directory of this script or PATH")
|
||
|
sys.exit(1)
|
||
|
logger.debug('Using standard bitbake path %s' % bitbakepath)
|
||
|
scriptpath.add_oe_lib_path()
|
||
|
|
||
|
scriptutils.logger_setup_color(logger, args.color)
|
||
|
|
||
|
if args.subparser_name != 'create-workspace':
|
||
|
read_workspace()
|
||
|
|
||
|
ret = args.func(args, config, basepath, workspace)
|
||
|
|
||
|
return ret
|
||
|
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
try:
|
||
|
ret = main()
|
||
|
except Exception:
|
||
|
ret = 1
|
||
|
import traceback
|
||
|
traceback.print_exc(5)
|
||
|
sys.exit(ret)
|