Complete Yocto mirror with license table for TQMa6UL (2038-compliance)
- 264 license table entries with exact download URLs (224/264 resolved) - Complete sources/ directory with all BitBake recipes - Build configuration: tqma6ul-multi-mba6ulx, spaetzle (musl) - Full traceability for Softwarefreigabeantrag - GCC 13.4.0, Linux 6.6.102, U-Boot 2023.04, musl 1.2.4 - License distribution: GPL-2.0 (24), MIT (23), GPL-2.0+ (18), BSD-3 (16)
This commit is contained in:
355
sources/poky/scripts/devtool
Executable file
355
sources/poky/scripts/devtool
Executable file
@@ -0,0 +1,355 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# OpenEmbedded Development tool
|
||||
#
|
||||
# Copyright (C) 2014-2015 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
#
|
||||
|
||||
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]
|
||||
from devtool import DevtoolError, setup_tinfoil
|
||||
import scriptutils
|
||||
import argparse_oe
|
||||
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.ConfigParser()
|
||||
|
||||
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)
|
||||
|
||||
def set(self, section, option, value):
|
||||
if not self.config_obj.has_section(section):
|
||||
self.config_obj.add_section(section)
|
||||
self.config_obj.set(section, option, value)
|
||||
|
||||
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)
|
||||
if not context.fixed_setup:
|
||||
_enable_workspace_layer(config.workspace_path, config, basepath)
|
||||
|
||||
logger.debug('Reading workspace in %s' % config.workspace_path)
|
||||
externalsrc_re = re.compile(r'^EXTERNALSRC(:pn-([^ =]+))? *= *"([^"]*)"$')
|
||||
for fn in glob.glob(os.path.join(config.workspace_path, 'appends', '*.bbappend')):
|
||||
with open(fn, 'r') as f:
|
||||
pnvalues = {}
|
||||
pn = None
|
||||
for line in f:
|
||||
res = externalsrc_re.match(line.rstrip())
|
||||
if res:
|
||||
recipepn = os.path.splitext(os.path.basename(fn))[0].split('_')[0]
|
||||
pn = res.group(2) or recipepn
|
||||
# Find the recipe file within the workspace, if any
|
||||
bbfile = os.path.basename(fn).replace('.bbappend', '.bb').replace('%', '*')
|
||||
recipefile = glob.glob(os.path.join(config.workspace_path,
|
||||
'recipes',
|
||||
recipepn,
|
||||
bbfile))
|
||||
if recipefile:
|
||||
recipefile = recipefile[0]
|
||||
pnvalues['srctree'] = res.group(3)
|
||||
pnvalues['bbappend'] = fn
|
||||
pnvalues['recipefile'] = recipefile
|
||||
elif line.startswith('# srctreebase: '):
|
||||
pnvalues['srctreebase'] = line.split(':', 1)[1].strip()
|
||||
if pnvalues:
|
||||
if not pn:
|
||||
raise DevtoolError("Found *.bbappend in %s, but could not determine EXTERNALSRC:pn-*. "
|
||||
"Maybe still using old syntax?" % config.workspace_path)
|
||||
if not pnvalues.get('srctreebase', None):
|
||||
pnvalues['srctreebase'] = pnvalues['srctree']
|
||||
logger.debug('Found recipe %s' % pnvalues)
|
||||
workspace[pn] = pnvalues
|
||||
|
||||
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'))
|
||||
layerseries = None
|
||||
if args.layerseries:
|
||||
layerseries = args.layerseries
|
||||
_create_workspace(workspacedir, config, basepath, layerseries)
|
||||
if not args.create_only:
|
||||
_enable_workspace_layer(workspacedir, config, basepath)
|
||||
|
||||
def _create_workspace(workspacedir, config, basepath, layerseries=None):
|
||||
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:
|
||||
if not layerseries:
|
||||
tinfoil = setup_tinfoil(config_only=True, basepath=basepath)
|
||||
try:
|
||||
layerseries = tinfoil.config_data.getVar('LAYERSERIES_CORENAMES')
|
||||
finally:
|
||||
tinfoil.shutdown()
|
||||
|
||||
# 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')
|
||||
f.write('LAYERSERIES_COMPAT_workspacelayer = "%s"\n' % layerseries)
|
||||
# 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 that are currently being worked on. The idea\n')
|
||||
f.write('is that the contents is temporary - once you have finished working on a\n')
|
||||
f.write('recipe you use the appropriate method to move the files you have been\n')
|
||||
f.write('working on to a proper layer. 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 or the workspace layer\'s contents\n')
|
||||
f.write('you can remove the path to this workspace layer from your conf/bblayers.conf\n')
|
||||
f.write('file (and then delete the layer, if you wish).\n')
|
||||
f.write('\nNote that by default, if devtool fetches and unpacks source code, it\n')
|
||||
f.write('will place it in a subdirectory of a "sources" subdirectory of the\n')
|
||||
f.write('layer. If you prefer it to be elsewhere you can specify the source\n')
|
||||
f.write('tree path on the command line.\n')
|
||||
|
||||
def _enable_workspace_layer(workspacedir, config, basepath):
|
||||
"""Ensure the workspace layer is in bblayers.conf"""
|
||||
import bb
|
||||
bblayers_conf = os.path.join(basepath, 'conf', 'bblayers.conf')
|
||||
if not os.path.exists(bblayers_conf):
|
||||
logger.error('Unable to find bblayers.conf')
|
||||
return
|
||||
if os.path.abspath(workspacedir) != os.path.abspath(config.workspace_path):
|
||||
removedir = config.workspace_path
|
||||
else:
|
||||
removedir = None
|
||||
_, added = bb.utils.edit_bblayers_conf(bblayers_conf, workspacedir, removedir)
|
||||
if added:
|
||||
logger.info('Enabling workspace layer in bblayers.conf')
|
||||
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
|
||||
|
||||
if sys.getfilesystemencoding() != "utf-8":
|
||||
sys.exit("Please use a locale setting which supports utf-8.\nPython can't change the filesystem locale after loading so we need a utf-8 when python starts or things won't work.")
|
||||
|
||||
context = Context(fixed_setup=False)
|
||||
|
||||
# Default basepath
|
||||
basepath = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
parser = argparse_oe.ArgumentParser(description="OpenEmbedded development tool",
|
||||
add_help=False,
|
||||
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('--bbpath', help='Explicitly specify the BBPATH, rather than getting it from the metadata')
|
||||
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')
|
||||
|
||||
global_args, unparsed_args = parser.parse_known_args()
|
||||
|
||||
# Help is added here rather than via add_help=True, as we don't want it to
|
||||
# be handled by parse_known_args()
|
||||
parser.add_argument('-h', '--help', action='help', default=argparse.SUPPRESS,
|
||||
help='show this help message and exit')
|
||||
|
||||
if global_args.debug:
|
||||
logger.setLevel(logging.DEBUG)
|
||||
elif global_args.quiet:
|
||||
logger.setLevel(logging.ERROR)
|
||||
|
||||
if global_args.basepath:
|
||||
# Override
|
||||
basepath = global_args.basepath
|
||||
if os.path.exists(os.path.join(basepath, '.devtoolbase')):
|
||||
context.fixed_setup = True
|
||||
else:
|
||||
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)
|
||||
|
||||
if 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
|
||||
context.config = config
|
||||
|
||||
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, global_args.color)
|
||||
|
||||
if global_args.bbpath is None:
|
||||
try:
|
||||
tinfoil = setup_tinfoil(config_only=True, basepath=basepath)
|
||||
try:
|
||||
global_args.bbpath = tinfoil.config_data.getVar('BBPATH')
|
||||
finally:
|
||||
tinfoil.shutdown()
|
||||
except bb.BBHandledException:
|
||||
return 2
|
||||
|
||||
# Search BBPATH first to allow layers to override plugins in scripts_path
|
||||
pluginpaths = [os.path.join(path, 'lib', 'devtool') for path in global_args.bbpath.split(':') + [scripts_path]]
|
||||
context.pluginpaths = pluginpaths
|
||||
for pluginpath in pluginpaths:
|
||||
scriptutils.load_plugins(logger, plugins, pluginpath)
|
||||
|
||||
subparsers = parser.add_subparsers(dest="subparser_name", title='subcommands', metavar='<subcommand>')
|
||||
subparsers.required = True
|
||||
|
||||
subparsers.add_subparser_group('sdk', 'SDK maintenance', -2)
|
||||
subparsers.add_subparser_group('advanced', 'Advanced', -1)
|
||||
subparsers.add_subparser_group('starting', 'Beginning work on a recipe', 100)
|
||||
subparsers.add_subparser_group('info', 'Getting information')
|
||||
subparsers.add_subparser_group('working', 'Working on a recipe in the workspace')
|
||||
subparsers.add_subparser_group('testbuild', 'Testing changes on target')
|
||||
|
||||
if not context.fixed_setup:
|
||||
parser_create_workspace = subparsers.add_parser('create-workspace',
|
||||
help='Set up workspace in an alternative location',
|
||||
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.',
|
||||
group='advanced')
|
||||
parser_create_workspace.add_argument('layerpath', nargs='?', help='Path in which the workspace layer should be created')
|
||||
parser_create_workspace.add_argument('--layerseries', help='Layer series the workspace should be set to be compatible with')
|
||||
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, no_workspace=True)
|
||||
|
||||
for plugin in plugins:
|
||||
if hasattr(plugin, 'register_commands'):
|
||||
plugin.register_commands(subparsers, context)
|
||||
|
||||
args = parser.parse_args(unparsed_args, namespace=global_args)
|
||||
|
||||
try:
|
||||
if not getattr(args, 'no_workspace', False):
|
||||
read_workspace()
|
||||
|
||||
ret = args.func(args, config, basepath, workspace)
|
||||
except DevtoolError as err:
|
||||
if str(err):
|
||||
logger.error(str(err))
|
||||
ret = err.exitcode
|
||||
except argparse_oe.ArgumentUsageError as ae:
|
||||
parser.error_subcommand(ae.message, ae.subcommand)
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
ret = main()
|
||||
except Exception:
|
||||
ret = 1
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
sys.exit(ret)
|
||||
Reference in New Issue
Block a user