1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
#!/usr/bin/env python3
#
# ---------------------------------------------------------------------------------------------------------------------
# SPDX-License-Identifier: MIT
# ---------------------------------------------------------------------------------------------------------------------
#
# Given a layer or layer.conf path, print the layer metadata
import contextlib
import os
import signal
import sys
from operator import itemgetter
class Terminate(BaseException):
pass
def sigterm_exception(signum, stackframe):
raise Terminate()
def setup_command_import(command, relpath='../lib'):
"""Set up sys.path based on the location of a binary in the PATH """
PATH = os.getenv('PATH').split(':')
cmd_paths = [os.path.join(path, relpath)
for path in PATH if os.path.exists(os.path.join(path, command))]
if not cmd_paths:
raise ImportError("Unable to locate bb, please ensure PATH is set correctly.")
sys.path[0:0] = cmd_paths
@contextlib.contextmanager
def status(message, outfile=sys.stderr):
"""Show the user what we're doing, and whether we succeed"""
outfile.write('{0}..'.format(message))
outfile.flush()
try:
yield
except KeyboardInterrupt:
outfile.write('.interrupted\n')
raise
except Terminate:
outfile.write('.terminated\n')
raise
except BaseException:
outfile.write('.failed\n')
raise
outfile.write('.done\n')
class LayerError(Exception):
pass
def get_layer_data(layer_path, lconf=None, data=None):
if lconf is None:
lconf = os.path.join(layer_path, 'conf', 'layer.conf')
if data is None:
ldata = bb.data.init()
bb.parse.init_parser(ldata)
else:
ldata = data.createCopy()
ldata.setVar('LAYERDIR', layer_path)
try:
ldata = bb.parse.handle(lconf, ldata, include=True)
except BaseException as exc:
raise LayerError(exc)
ldata.expandVarref('LAYERDIR')
collections = (ldata.getVar('BBFILE_COLLECTIONS', True) or '').split()
if not collections:
name = os.path.basename(layer_path)
collections = [name]
for name in collections:
priority = ldata.getVar('BBFILE_PRIORITY_%s' % name, True)
pattern = ldata.getVar('BBFILE_PATTERN_%s' % name, True)
depends = ldata.getVar('LAYERDEPENDS_%s' % name, True)
yield name, priority, layer_path, pattern, depends
def print_layer_data(cmdline_opts):
if len(cmdline_opts) < 1:
return "Usage: bb-print-layer-data LCONF|LAYERDIR [LCONF|LAYERDIR..]\n"
setup_command_import('bitbake')
try:
import bb
except ImportError as exc:
sys.exit("Unable to import 'bb' python package: %s" % exc)
import bb.parse
import bb.data
data = bb.data.init()
bb.parse.init_parser(data)
collections = set()
for layer_path in cmdline_opts:
if os.path.isdir(layer_path):
lconf = os.path.join(layer_path, 'conf', 'layer.conf')
else:
lconf = layer_path
layer_path = os.path.dirname(os.path.dirname(lconf))
with status("Parsing {0}".format(lconf)):
collections |= set(get_layer_data(layer_path, lconf, data))
priority_key = lambda i: int(i[1]) if i[1] is not None else None
for name, priority, layer_path, pattern, depends in sorted(collections, key=priority_key):
print("{0}: {1}|{2}|{3}|{4}".format(name, priority or '', layer_path, pattern or '', depends or ''))
if __name__ == '__main__':
signal.signal(signal.SIGTERM, sigterm_exception)
try:
sys.exit(print_layer_data(sys.argv[1:]) or 0)
except KeyboardInterrupt:
signal.signal(signal.SIGINT, signal.SIG_DFL)
os.kill(os.getpid(), signal.SIGINT)
except Terminate:
signal.signal(signal.SIGTERM, signal.SIG_DFL)
os.kill(os.getpid(), signal.SIGTERM)
|