mirror of
https://git.yoctoproject.org/poky
synced 2026-04-26 00:32:12 +02:00
yocto-compat-layer.py: Add script to YP Compatible Layer validation
The yocto-compat-layer script serves as a tool to validate the alignament
of a layer with YP Compatible Layers Programme [1], is based on an RFC
sent to the ML to enable automatic testing of layers [2] that wants to
be YP Compatible.
The tool takes an layer (or set of layers) via command line option -l
and detects what kind of layer is distro, machine or software and then
executes a set of tests against the layer in order to validate the
compatibility.
The tests currently implemented are:
common.test_readme: Test if a README file exists in the layer and isn't
empty.
common.test_parse: Test for execute bitbake -p without errors.
common.test_show_environment: Test for execute bitbake -e without errors.
common.test_signatures: Test executed in BSP and DISTRO layers to review
doesn't comes with recipes that changes the signatures.
bsp.test_bsp_defines_machines: Test if a BSP layers has machines
configurations.
bsp.test_bsp_no_set_machine: Test the BSP layer to doesn't set
machine at adding layer.
distro.test_distro_defines_distros: Test if a DISTRO layers has distro
configurations.
distro.test_distro_no_set_distro: Test the DISTRO layer to doesn't set
distro at adding layer.
Example of usage:
$ source oe-init-build-env
$ yocto-compat-layer.py LAYER_DIR
[YOCTO #10596]
[1] https://www.yoctoproject.org/webform/yocto-project-compatible-registration
[2] https://lists.yoctoproject.org/pipermail/yocto-ab/2016-October/001801.html
(From OE-Core rev: e14596ac33329bc61fe38a6582fa91f76ff5b147)
Signed-off-by: Aníbal Limón <anibal.limon@linux.intel.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
This commit is contained in:
committed by
Richard Purdie
parent
28376f9552
commit
93633edcf8
153
scripts/yocto-compat-layer.py
Executable file
153
scripts/yocto-compat-layer.py
Executable file
@@ -0,0 +1,153 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Yocto Project compatibility layer tool
|
||||
#
|
||||
# Copyright (C) 2017 Intel Corporation
|
||||
# Released under the MIT license (see COPYING.MIT)
|
||||
|
||||
import os
|
||||
import sys
|
||||
import argparse
|
||||
import logging
|
||||
import time
|
||||
import signal
|
||||
import shutil
|
||||
import collections
|
||||
|
||||
scripts_path = os.path.dirname(os.path.realpath(__file__))
|
||||
lib_path = scripts_path + '/lib'
|
||||
sys.path = sys.path + [lib_path]
|
||||
import scriptutils
|
||||
import scriptpath
|
||||
scriptpath.add_oe_lib_path()
|
||||
scriptpath.add_bitbake_lib_path()
|
||||
|
||||
from compatlayer import LayerType, detect_layers, add_layer, get_signatures
|
||||
from oeqa.utils.commands import get_bb_vars
|
||||
|
||||
PROGNAME = 'yocto-compat-layer'
|
||||
DEFAULT_OUTPUT_LOG = '%s-%s.log' % (PROGNAME,
|
||||
time.strftime("%Y%m%d%H%M%S"))
|
||||
OUTPUT_LOG_LINK = "%s.log" % PROGNAME
|
||||
CASES_PATHS = [os.path.join(os.path.abspath(os.path.dirname(__file__)),
|
||||
'lib', 'compatlayer', 'cases')]
|
||||
logger = scriptutils.logger_create(PROGNAME)
|
||||
|
||||
def test_layer_compatibility(td, layer):
|
||||
from compatlayer.context import CompatLayerTestContext
|
||||
logger.info("Starting to analyze: %s" % layer['name'])
|
||||
logger.info("----------------------------------------------------------------------")
|
||||
|
||||
tc = CompatLayerTestContext(td=td, logger=logger, layer=layer)
|
||||
tc.loadTests(CASES_PATHS)
|
||||
return tc.runTests()
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Yocto Project compatibility layer tool",
|
||||
add_help=False)
|
||||
parser.add_argument('layers', metavar='LAYER_DIR', nargs='+',
|
||||
help='Layer to test compatibility with Yocto Project')
|
||||
parser.add_argument('-o', '--output-log',
|
||||
help='Output log default: %s' % DEFAULT_OUTPUT_LOG,
|
||||
action='store', default=DEFAULT_OUTPUT_LOG)
|
||||
|
||||
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('-h', '--help', action='help',
|
||||
default=argparse.SUPPRESS,
|
||||
help='show this help message and exit')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
fh = logging.FileHandler(args.output_log)
|
||||
fh.setFormatter(logging.Formatter("%(levelname)s: %(message)s"))
|
||||
logger.addHandler(fh)
|
||||
if args.debug:
|
||||
logger.setLevel(logging.DEBUG)
|
||||
elif args.quiet:
|
||||
logger.setLevel(logging.ERROR)
|
||||
if os.path.exists(OUTPUT_LOG_LINK):
|
||||
os.unlink(OUTPUT_LOG_LINK)
|
||||
os.symlink(args.output_log, OUTPUT_LOG_LINK)
|
||||
|
||||
if not 'BUILDDIR' in os.environ:
|
||||
logger.error("You must source the environment before run this script.")
|
||||
logger.error("$ source oe-init-build-env")
|
||||
return 1
|
||||
builddir = os.environ['BUILDDIR']
|
||||
bblayersconf = os.path.join(builddir, 'conf', 'bblayers.conf')
|
||||
|
||||
layers = detect_layers(args.layers)
|
||||
if not layers:
|
||||
logger.error("Fail to detect layers")
|
||||
return 1
|
||||
|
||||
logger.info("Detected layers:")
|
||||
for layer in layers:
|
||||
if layer['type'] == LayerType.ERROR_BSP_DISTRO:
|
||||
logger.error("%s: Can't be DISTRO and BSP type at the same time."\
|
||||
" The conf/distro and conf/machine folders was found."\
|
||||
% layer['name'])
|
||||
layers.remove(layer)
|
||||
elif layer['type'] == LayerType.ERROR_NO_LAYER_CONF:
|
||||
logger.error("%s: Don't have conf/layer.conf file."\
|
||||
% layer['name'])
|
||||
layers.remove(layer)
|
||||
else:
|
||||
logger.info("%s: %s, %s" % (layer['name'], layer['type'],
|
||||
layer['path']))
|
||||
if not layers:
|
||||
return 1
|
||||
|
||||
shutil.copyfile(bblayersconf, bblayersconf + '.backup')
|
||||
def cleanup_bblayers(signum, frame):
|
||||
shutil.copyfile(bblayersconf + '.backup', bblayersconf)
|
||||
os.unlink(bblayersconf + '.backup')
|
||||
signal.signal(signal.SIGTERM, cleanup_bblayers)
|
||||
signal.signal(signal.SIGINT, cleanup_bblayers)
|
||||
|
||||
td = {}
|
||||
results = collections.OrderedDict()
|
||||
|
||||
logger.info('')
|
||||
logger.info('Getting initial bitbake variables ...')
|
||||
td['bbvars'] = get_bb_vars()
|
||||
logger.info('Getting initial signatures ...')
|
||||
td['builddir'] = builddir
|
||||
td['sigs'] = get_signatures(td['builddir'])
|
||||
logger.info('')
|
||||
|
||||
for layer in layers:
|
||||
if layer['type'] == LayerType.ERROR_NO_LAYER_CONF or \
|
||||
layer['type'] == LayerType.ERROR_BSP_DISTRO:
|
||||
continue
|
||||
|
||||
shutil.copyfile(bblayersconf + '.backup', bblayersconf)
|
||||
|
||||
add_layer(bblayersconf, layer)
|
||||
result = test_layer_compatibility(td, layer)
|
||||
results[layer['name']] = result
|
||||
|
||||
logger.info('')
|
||||
logger.info('Summary of results:')
|
||||
logger.info('')
|
||||
for layer_name in results:
|
||||
logger.info('%s ... %s' % (layer_name, 'PASS' if \
|
||||
results[layer_name].wasSuccessful() else 'FAIL'))
|
||||
|
||||
cleanup_bblayers(None, None)
|
||||
|
||||
return 0
|
||||
|
||||
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