summaryrefslogtreecommitdiffstats
path: root/scripts/yocto-check-layer
diff options
context:
space:
mode:
authorPaul Eggleton <paul.eggleton@linux.intel.com>2017-09-19 15:57:07 +1200
committerRichard Purdie <richard.purdie@linuxfoundation.org>2017-09-21 11:34:19 +0100
commitb32174e58e89119e3ca2315030629a6580ccbd52 (patch)
tree1be70a32209bd098988f1d60cd7ce496329129d0 /scripts/yocto-check-layer
parent455877548e7a685f0dacf3b10056ff85c7aeedf2 (diff)
downloadpoky-b32174e58e89119e3ca2315030629a6580ccbd52.tar.gz
scripts: rename yocto-compat-layer to remove "compatible" nomenclature
"Yocto Project Compatible" [1] is a programme which requires you meet specific criteria including going through an application process - it is not sufficient simply to run the script we have created here and have it produce no warnings/errors. To avoid people being confused by the fact that this script uses the term "compatible" or variations thereof, substitute usage of that word with "check" instead. The functionality of the script is unchanged. [1] https://www.yoctoproject.org/ecosystem/yocto-project-branding-program (From OE-Core rev: 2a6126a115f10750ea89f95629d3699ad41c5665) Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com> Signed-off-by: Ross Burton <ross.burton@intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'scripts/yocto-check-layer')
-rwxr-xr-xscripts/yocto-check-layer208
1 files changed, 208 insertions, 0 deletions
diff --git a/scripts/yocto-check-layer b/scripts/yocto-check-layer
new file mode 100755
index 0000000000..5a4fd752ca
--- /dev/null
+++ b/scripts/yocto-check-layer
@@ -0,0 +1,208 @@
1#!/usr/bin/env python3
2
3# Yocto Project layer checking tool
4#
5# Copyright (C) 2017 Intel Corporation
6# Released under the MIT license (see COPYING.MIT)
7
8import os
9import sys
10import argparse
11import logging
12import time
13import signal
14import shutil
15import collections
16
17scripts_path = os.path.dirname(os.path.realpath(__file__))
18lib_path = scripts_path + '/lib'
19sys.path = sys.path + [lib_path]
20import scriptutils
21import scriptpath
22scriptpath.add_oe_lib_path()
23scriptpath.add_bitbake_lib_path()
24
25from checklayer import LayerType, detect_layers, add_layer, add_layer_dependencies, get_signatures
26from oeqa.utils.commands import get_bb_vars
27
28PROGNAME = 'yocto-check-layer'
29CASES_PATHS = [os.path.join(os.path.abspath(os.path.dirname(__file__)),
30 'lib', 'checklayer', 'cases')]
31logger = scriptutils.logger_create(PROGNAME, stream=sys.stdout)
32
33def test_layer(td, layer, test_software_layer_signatures):
34 from checklayer.context import CheckLayerTestContext
35 logger.info("Starting to analyze: %s" % layer['name'])
36 logger.info("----------------------------------------------------------------------")
37
38 tc = CheckLayerTestContext(td=td, logger=logger, layer=layer, test_software_layer_signatures=test_software_layer_signatures)
39 tc.loadTests(CASES_PATHS)
40 return tc.runTests()
41
42def main():
43 parser = argparse.ArgumentParser(
44 description="Yocto Project layer checking tool",
45 add_help=False)
46 parser.add_argument('layers', metavar='LAYER_DIR', nargs='+',
47 help='Layer to check')
48 parser.add_argument('-o', '--output-log',
49 help='File to output log (optional)', action='store')
50 parser.add_argument('--dependency', nargs="+",
51 help='Layers to process for dependencies', action='store')
52 parser.add_argument('--machines', nargs="+",
53 help='List of MACHINEs to be used during testing', action='store')
54 parser.add_argument('--additional-layers', nargs="+",
55 help='List of additional layers to add during testing', action='store')
56 group = parser.add_mutually_exclusive_group()
57 group.add_argument('--with-software-layer-signature-check', action='store_true', dest='test_software_layer_signatures',
58 default=True,
59 help='check that software layers do not change signatures (on by default)')
60 group.add_argument('--without-software-layer-signature-check', action='store_false', dest='test_software_layer_signatures',
61 help='disable signature checking for software layers')
62 parser.add_argument('-n', '--no-auto', help='Disable auto layer discovery',
63 action='store_true')
64 parser.add_argument('-d', '--debug', help='Enable debug output',
65 action='store_true')
66 parser.add_argument('-q', '--quiet', help='Print only errors',
67 action='store_true')
68
69 parser.add_argument('-h', '--help', action='help',
70 default=argparse.SUPPRESS,
71 help='show this help message and exit')
72
73 args = parser.parse_args()
74
75 if args.output_log:
76 fh = logging.FileHandler(args.output_log)
77 fh.setFormatter(logging.Formatter("%(levelname)s: %(message)s"))
78 logger.addHandler(fh)
79 if args.debug:
80 logger.setLevel(logging.DEBUG)
81 elif args.quiet:
82 logger.setLevel(logging.ERROR)
83
84 if not 'BUILDDIR' in os.environ:
85 logger.error("You must source the environment before run this script.")
86 logger.error("$ source oe-init-build-env")
87 return 1
88 builddir = os.environ['BUILDDIR']
89 bblayersconf = os.path.join(builddir, 'conf', 'bblayers.conf')
90
91 layers = detect_layers(args.layers, args.no_auto)
92 if not layers:
93 logger.error("Fail to detect layers")
94 return 1
95 if args.additional_layers:
96 additional_layers = detect_layers(args.additional_layers, args.no_auto)
97 else:
98 additional_layers = []
99 if args.dependency:
100 dep_layers = detect_layers(args.dependency, args.no_auto)
101 dep_layers = dep_layers + layers
102 else:
103 dep_layers = layers
104
105 logger.info("Detected layers:")
106 for layer in layers:
107 if layer['type'] == LayerType.ERROR_BSP_DISTRO:
108 logger.error("%s: Can't be DISTRO and BSP type at the same time."\
109 " The conf/distro and conf/machine folders was found."\
110 % layer['name'])
111 layers.remove(layer)
112 elif layer['type'] == LayerType.ERROR_NO_LAYER_CONF:
113 logger.error("%s: Don't have conf/layer.conf file."\
114 % layer['name'])
115 layers.remove(layer)
116 else:
117 logger.info("%s: %s, %s" % (layer['name'], layer['type'],
118 layer['path']))
119 if not layers:
120 return 1
121
122 shutil.copyfile(bblayersconf, bblayersconf + '.backup')
123 def cleanup_bblayers(signum, frame):
124 shutil.copyfile(bblayersconf + '.backup', bblayersconf)
125 os.unlink(bblayersconf + '.backup')
126 signal.signal(signal.SIGTERM, cleanup_bblayers)
127 signal.signal(signal.SIGINT, cleanup_bblayers)
128
129 td = {}
130 results = collections.OrderedDict()
131 results_status = collections.OrderedDict()
132
133 layers_tested = 0
134 for layer in layers:
135 if layer['type'] == LayerType.ERROR_NO_LAYER_CONF or \
136 layer['type'] == LayerType.ERROR_BSP_DISTRO:
137 continue
138
139 logger.info('')
140 logger.info("Setting up for %s(%s), %s" % (layer['name'], layer['type'],
141 layer['path']))
142
143 shutil.copyfile(bblayersconf + '.backup', bblayersconf)
144
145 missing_dependencies = not add_layer_dependencies(bblayersconf, layer, dep_layers, logger)
146 if not missing_dependencies:
147 for additional_layer in additional_layers:
148 if not add_layer_dependencies(bblayersconf, additional_layer, dep_layers, logger):
149 missing_dependencies = True
150 break
151 if not add_layer_dependencies(bblayersconf, layer, dep_layers, logger) or \
152 any(map(lambda additional_layer: not add_layer_dependencies(bblayersconf, additional_layer, dep_layers, logger),
153 additional_layers)):
154 logger.info('Skipping %s due to missing dependencies.' % layer['name'])
155 results[layer['name']] = None
156 results_status[layer['name']] = 'SKIPPED (Missing dependencies)'
157 layers_tested = layers_tested + 1
158 continue
159
160 if any(map(lambda additional_layer: not add_layer(bblayersconf, additional_layer, dep_layers, logger),
161 additional_layers)):
162 logger.info('Skipping %s due to missing additional layers.' % layer['name'])
163 results[layer['name']] = None
164 results_status[layer['name']] = 'SKIPPED (Missing additional layers)'
165 layers_tested = layers_tested + 1
166 continue
167
168 logger.info('Getting initial bitbake variables ...')
169 td['bbvars'] = get_bb_vars()
170 logger.info('Getting initial signatures ...')
171 td['builddir'] = builddir
172 td['sigs'], td['tunetasks'] = get_signatures(td['builddir'])
173 td['machines'] = args.machines
174
175 if not add_layer(bblayersconf, layer, dep_layers, logger):
176 logger.info('Skipping %s ???.' % layer['name'])
177 results[layer['name']] = None
178 results_status[layer['name']] = 'SKIPPED (Unknown)'
179 layers_tested = layers_tested + 1
180 continue
181
182 result = test_layer(td, layer, args.test_software_layer_signatures)
183 results[layer['name']] = result
184 results_status[layer['name']] = 'PASS' if results[layer['name']].wasSuccessful() else 'FAIL'
185 layers_tested = layers_tested + 1
186
187 ret = 0
188 if layers_tested:
189 logger.info('')
190 logger.info('Summary of results:')
191 logger.info('')
192 for layer_name in results_status:
193 logger.info('%s ... %s' % (layer_name, results_status[layer_name]))
194 if not results[layer_name] or not results[layer_name].wasSuccessful():
195 ret = 2 # ret = 1 used for initialization errors
196
197 cleanup_bblayers(None, None)
198
199 return ret
200
201if __name__ == '__main__':
202 try:
203 ret = main()
204 except Exception:
205 ret = 1
206 import traceback
207 traceback.print_exc()
208 sys.exit(ret)