summaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rwxr-xr-xscripts/gen-site-config43
-rwxr-xr-xscripts/install-buildtools47
-rw-r--r--scripts/lib/build_perf/html/measurement_chart.html140
-rw-r--r--scripts/lib/build_perf/html/report.html124
-rw-r--r--scripts/lib/build_perf/report.py5
-rwxr-xr-xscripts/lib/devtool/ide_sdk.py2
-rw-r--r--scripts/lib/devtool/standard.py199
-rw-r--r--scripts/lib/devtool/upgrade.py13
-rw-r--r--scripts/lib/recipetool/append.py6
-rw-r--r--scripts/lib/recipetool/create.py2
-rw-r--r--scripts/lib/scriptutils.py15
-rw-r--r--scripts/lib/wic/engine.py2
-rw-r--r--scripts/lib/wic/plugins/source/bootimg-efi.py4
-rwxr-xr-xscripts/makefile-getvar24
-rwxr-xr-xscripts/oe-build-perf-report8
-rwxr-xr-xscripts/oe-setup-build11
16 files changed, 339 insertions, 306 deletions
diff --git a/scripts/gen-site-config b/scripts/gen-site-config
deleted file mode 100755
index 727b809c0f..0000000000
--- a/scripts/gen-site-config
+++ /dev/null
@@ -1,43 +0,0 @@
1#! /bin/sh
2# Copyright (c) 2005-2008 Wind River Systems, Inc.
3#
4# SPDX-License-Identifier: GPL-2.0-only
5#
6
7cat << EOF
8AC_PREREQ(2.57)
9AC_INIT([site_wide],[1.0.0])
10
11EOF
12
13# Disable as endian is set in the default config
14#echo AC_C_BIGENDIAN
15#echo
16
17if [ -e $1/types ] ; then
18 while read type ; do
19 echo "AC_CHECK_SIZEOF([$type])"
20 done < $1/types
21
22 echo
23fi
24
25if [ -e $1/funcs ]; then
26 while read func ; do
27 echo "AC_CHECK_FUNCS([$func])"
28 done < $1/funcs
29
30 echo
31fi
32
33if [ -e $1/headers ]; then
34 while read header ; do
35 echo "AC_CHECK_HEADERS([$header])"
36 done < $1/headers
37
38 echo
39fi
40
41cat << EOF
42AC_OUTPUT
43EOF
diff --git a/scripts/install-buildtools b/scripts/install-buildtools
index 2218f3ffac..5b86c13077 100755
--- a/scripts/install-buildtools
+++ b/scripts/install-buildtools
@@ -56,9 +56,9 @@ PROGNAME = 'install-buildtools'
56logger = scriptutils.logger_create(PROGNAME, stream=sys.stdout) 56logger = scriptutils.logger_create(PROGNAME, stream=sys.stdout)
57 57
58DEFAULT_INSTALL_DIR = os.path.join(os.path.split(scripts_path)[0],'buildtools') 58DEFAULT_INSTALL_DIR = os.path.join(os.path.split(scripts_path)[0],'buildtools')
59DEFAULT_BASE_URL = 'http://downloads.yoctoproject.org/releases/yocto' 59DEFAULT_BASE_URL = 'https://downloads.yoctoproject.org/releases/yocto'
60DEFAULT_RELEASE = 'yocto-4.1' 60DEFAULT_RELEASE = 'yocto-5.0.1'
61DEFAULT_INSTALLER_VERSION = '4.1' 61DEFAULT_INSTALLER_VERSION = '5.0.1'
62DEFAULT_BUILDDATE = '202110XX' 62DEFAULT_BUILDDATE = '202110XX'
63 63
64# Python version sanity check 64# Python version sanity check
@@ -102,6 +102,16 @@ def sha256_file(filename):
102 import hashlib 102 import hashlib
103 return _hasher(hashlib.sha256(), filename) 103 return _hasher(hashlib.sha256(), filename)
104 104
105def remove_quotes(var):
106 """
107 If a variable starts and ends with double quotes, remove them.
108 Assumption: if a variable starts with double quotes, it must also
109 end with them.
110 """
111 if var[0] == '"':
112 var = var[1:-1]
113 return var
114
105 115
106def main(): 116def main():
107 global DEFAULT_INSTALL_DIR 117 global DEFAULT_INSTALL_DIR
@@ -238,19 +248,15 @@ def main():
238 # Verify checksum 248 # Verify checksum
239 if args.check: 249 if args.check:
240 logger.info("Fetching buildtools installer checksum") 250 logger.info("Fetching buildtools installer checksum")
241 checksum_type = "" 251 checksum_type = "sha256sum"
242 for checksum_type in ["md5sum", "sha256sum"]: 252 check_url = "{}.{}".format(buildtools_url, checksum_type)
243 check_url = "{}.{}".format(buildtools_url, checksum_type) 253 checksum_filename = "{}.{}".format(filename, checksum_type)
244 checksum_filename = "{}.{}".format(filename, checksum_type) 254 tmpbuildtools_checksum = os.path.join(tmpsdk_dir, checksum_filename)
245 tmpbuildtools_checksum = os.path.join(tmpsdk_dir, checksum_filename) 255 ret = subprocess.call("wget -q -O %s %s" %
246 ret = subprocess.call("wget -q -O %s %s" % 256 (tmpbuildtools_checksum, check_url), shell=True)
247 (tmpbuildtools_checksum, check_url), shell=True) 257 if ret != 0:
248 if ret == 0: 258 logger.error("Could not download file from %s" % check_url)
249 break 259 return ret
250 else:
251 if ret != 0:
252 logger.error("Could not download file from %s" % check_url)
253 return ret
254 regex = re.compile(r"^(?P<checksum>[0-9a-f]+)\s+(?P<path>.*/)?(?P<filename>.*)$") 260 regex = re.compile(r"^(?P<checksum>[0-9a-f]+)\s+(?P<path>.*/)?(?P<filename>.*)$")
255 with open(tmpbuildtools_checksum, 'rb') as f: 261 with open(tmpbuildtools_checksum, 'rb') as f:
256 original = f.read() 262 original = f.read()
@@ -263,10 +269,7 @@ def main():
263 logger.error("Filename does not match name in checksum") 269 logger.error("Filename does not match name in checksum")
264 return 1 270 return 1
265 checksum = m.group('checksum') 271 checksum = m.group('checksum')
266 if checksum_type == "md5sum": 272 checksum_value = sha256_file(tmpbuildtools)
267 checksum_value = md5_file(tmpbuildtools)
268 else:
269 checksum_value = sha256_file(tmpbuildtools)
270 if checksum == checksum_value: 273 if checksum == checksum_value:
271 logger.info("Checksum success") 274 logger.info("Checksum success")
272 else: 275 else:
@@ -280,7 +283,7 @@ def main():
280 os.chmod(tmpbuildtools, st.st_mode | stat.S_IEXEC) 283 os.chmod(tmpbuildtools, st.st_mode | stat.S_IEXEC)
281 logger.debug(os.stat(tmpbuildtools)) 284 logger.debug(os.stat(tmpbuildtools))
282 if args.directory: 285 if args.directory:
283 install_dir = args.directory 286 install_dir = os.path.abspath(args.directory)
284 ret = subprocess.call("%s -d %s -y" % 287 ret = subprocess.call("%s -d %s -y" %
285 (tmpbuildtools, install_dir), shell=True) 288 (tmpbuildtools, install_dir), shell=True)
286 else: 289 else:
@@ -301,7 +304,7 @@ def main():
301 if match: 304 if match:
302 env_var = match.group('env_var') 305 env_var = match.group('env_var')
303 logger.debug("env_var: %s" % env_var) 306 logger.debug("env_var: %s" % env_var)
304 env_val = match.group('env_val') 307 env_val = remove_quotes(match.group('env_val'))
305 logger.debug("env_val: %s" % env_val) 308 logger.debug("env_val: %s" % env_val)
306 os.environ[env_var] = env_val 309 os.environ[env_var] = env_val
307 310
diff --git a/scripts/lib/build_perf/html/measurement_chart.html b/scripts/lib/build_perf/html/measurement_chart.html
index 65f1a227ad..05bd84e6ce 100644
--- a/scripts/lib/build_perf/html/measurement_chart.html
+++ b/scripts/lib/build_perf/html/measurement_chart.html
@@ -1,50 +1,100 @@
1<script type="text/javascript"> 1<script type="module">
2 chartsDrawing += 1; 2 // Get raw data
3 google.charts.setOnLoadCallback(drawChart_{{ chart_elem_id }}); 3 const rawData = [
4 function drawChart_{{ chart_elem_id }}() { 4 {% for sample in measurement.samples %}
5 var data = new google.visualization.DataTable(); 5 [{{ sample.commit_num }}, {{ sample.mean.gv_value() }}, {{ sample.start_time }}, '{{sample.commit}}'],
6 {% endfor %}
7 ];
6 8
7 // Chart options 9 const convertToMinute = (time) => {
8 var options = { 10 return time[0]*60 + time[1] + time[2]/60 + time[3]/3600;
9 theme : 'material', 11 }
10 legend: 'none',
11 hAxis: { format: '', title: 'Commit number',
12 minValue: {{ chart_opts.haxis.min }},
13 maxValue: {{ chart_opts.haxis.max }} },
14 {% if measurement.type == 'time' %}
15 vAxis: { format: 'h:mm:ss' },
16 {% else %}
17 vAxis: { format: '' },
18 {% endif %}
19 pointSize: 5,
20 chartArea: { left: 80, right: 15 },
21 };
22 12
23 // Define data columns 13 // Update value format to either minutes or leave as size value
24 data.addColumn('number', 'Commit'); 14 const updateValue = (value) => {
25 data.addColumn('{{ measurement.value_type.gv_data_type }}', 15 // Assuming the array values are duration in the format [hours, minutes, seconds, milliseconds]
26 '{{ measurement.value_type.quantity }}'); 16 return Array.isArray(value) ? convertToMinute(value) : value
27 // Add data rows 17 }
28 data.addRows([
29 {% for sample in measurement.samples %}
30 [{{ sample.commit_num }}, {{ sample.mean.gv_value() }}],
31 {% endfor %}
32 ]);
33 18
34 // Finally, draw the chart 19 // Convert raw data to the format: [time, value]
35 chart_div = document.getElementById('{{ chart_elem_id }}'); 20 const data = rawData.map(([commit, value, time]) => {
36 var chart = new google.visualization.LineChart(chart_div); 21 return [
37 google.visualization.events.addListener(chart, 'ready', function () { 22 // The Date object takes values in milliseconds rather than seconds. So to use a Unix timestamp we have to multiply it by 1000.
38 //chart_div = document.getElementById('{{ chart_elem_id }}'); 23 new Date(time * 1000).getTime(),
39 //chart_div.innerHTML = '<img src="' + chart.getImageURI() + '">'; 24 // Assuming the array values are duration in the format [hours, minutes, seconds, milliseconds]
40 png_div = document.getElementById('{{ chart_elem_id }}_png'); 25 updateValue(value)
41 png_div.outerHTML = '<a id="{{ chart_elem_id }}_png" href="' + chart.getImageURI() + '">PNG</a>'; 26 ]
42 console.log("CHART READY: {{ chart_elem_id }}"); 27 });
43 chartsDrawing -= 1; 28
44 if (chartsDrawing == 0) 29 // Set chart options
45 console.log("ALL CHARTS READY"); 30 const option = {
31 tooltip: {
32 trigger: 'axis',
33 enterable: true,
34 position: function (point, params, dom, rect, size) {
35 return [point[0]-150, '10%'];
36 },
37 formatter: function (param) {
38 const value = param[0].value[1]
39 const sample = rawData.filter(([commit, dataValue]) => updateValue(dataValue) === value)
40 // Add commit hash to the tooltip as a link
41 const commitLink = `https://git.yoctoproject.org/poky/commit/?id=${sample[0][3]}`
42 if ('{{ measurement.value_type.quantity }}' == 'time') {
43 const hours = Math.floor(value/60)
44 const minutes = Math.floor(value % 60)
45 const seconds = Math.floor((value * 60) % 60)
46 return `<strong>Duration:</strong> ${hours}:${minutes}:${seconds}, <br/> <strong>Commit number:</strong> <a href="${commitLink}" target="_blank" rel="noreferrer noopener">${sample[0][0]}</a>`
47 }
48 return `<strong>Size:</strong> ${value.toFixed(2)} MB, <br/> <strong>Commit number:</strong> <a href="${commitLink}" target="_blank" rel="noreferrer noopener">${sample[0][0]}</a>`
49 ;}
50 },
51 xAxis: {
52 type: 'time',
53 },
54 yAxis: {
55 name: '{{ measurement.value_type.quantity }}' == 'time' ? 'Duration in minutes' : 'Disk size in MB',
56 type: 'value',
57 min: function(value) {
58 return Math.round(value.min - 0.5);
59 },
60 max: function(value) {
61 return Math.round(value.max + 0.5);
62 }
63 },
64 dataZoom: [
65 {
66 type: 'slider',
67 xAxisIndex: 0,
68 filterMode: 'none'
69 },
70 ],
71 series: [
72 {
73 name: '{{ measurement.value_type.quantity }}',
74 type: 'line',
75 step: 'start',
76 symbol: 'none',
77 data: data
78 }
79 ]
80 };
81
82 // Draw chart
83 const chart_div = document.getElementById('{{ chart_elem_id }}');
84 // Set dark mode
85 let measurement_chart
86 if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
87 measurement_chart= echarts.init(chart_div, 'dark', {
88 height: 320
46 }); 89 });
47 chart.draw(data, options); 90 } else {
48} 91 measurement_chart= echarts.init(chart_div, null, {
92 height: 320
93 });
94 }
95 // Change chart size with browser resize
96 window.addEventListener('resize', function() {
97 measurement_chart.resize();
98 });
99 measurement_chart.setOption(option);
49</script> 100</script>
50
diff --git a/scripts/lib/build_perf/html/report.html b/scripts/lib/build_perf/html/report.html
index d1ba6f2578..537ed3ee52 100644
--- a/scripts/lib/build_perf/html/report.html
+++ b/scripts/lib/build_perf/html/report.html
@@ -3,11 +3,7 @@
3<head> 3<head>
4{# Scripts, for visualization#} 4{# Scripts, for visualization#}
5<!--START-OF-SCRIPTS--> 5<!--START-OF-SCRIPTS-->
6<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script> 6<script src=" https://cdn.jsdelivr.net/npm/echarts@5.5.0/dist/echarts.min.js "></script>
7<script type="text/javascript">
8google.charts.load('current', {'packages':['corechart']});
9var chartsDrawing = 0;
10</script>
11 7
12{# Render measurement result charts #} 8{# Render measurement result charts #}
13{% for test in test_data %} 9{% for test in test_data %}
@@ -23,28 +19,29 @@ var chartsDrawing = 0;
23 19
24{# Styles #} 20{# Styles #}
25<style> 21<style>
22:root {
23 --text: #000;
24 --bg: #fff;
25 --h2heading: #707070;
26 --link: #0000EE;
27 --trtopborder: #9ca3af;
28 --trborder: #e5e7eb;
29 --chartborder: #f0f0f0;
30 }
26.meta-table { 31.meta-table {
27 font-size: 14px; 32 font-size: 14px;
28 text-align: left; 33 text-align: left;
29 border-collapse: collapse; 34 border-collapse: collapse;
30} 35}
31.meta-table tr:nth-child(even){background-color: #f2f2f2}
32meta-table th, .meta-table td {
33 padding: 4px;
34}
35.summary { 36.summary {
36 margin: 0;
37 font-size: 14px; 37 font-size: 14px;
38 text-align: left; 38 text-align: left;
39 border-collapse: collapse; 39 border-collapse: collapse;
40} 40}
41summary th, .meta-table td {
42 padding: 4px;
43}
44.measurement { 41.measurement {
45 padding: 8px 0px 8px 8px; 42 padding: 8px 0px 8px 8px;
46 border: 2px solid #f0f0f0; 43 border: 2px solid var(--chartborder);
47 margin-bottom: 10px; 44 margin: 1.5rem 0;
48} 45}
49.details { 46.details {
50 margin: 0; 47 margin: 0;
@@ -64,18 +61,71 @@ summary th, .meta-table td {
64 background-color: #f0f0f0; 61 background-color: #f0f0f0;
65 margin-left: 10px; 62 margin-left: 10px;
66} 63}
67hr { 64.card-container {
68 color: #f0f0f0; 65 border-bottom-width: 1px;
66 padding: 1.25rem 3rem;
67 box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
68 border-radius: 0.25rem;
69}
70body {
71 font-family: 'Helvetica', sans-serif;
72 margin: 3rem 8rem;
73 background-color: var(--bg);
74 color: var(--text);
75}
76h1 {
77 text-align: center;
69} 78}
70h2 { 79h2 {
71 font-size: 20px; 80 font-size: 1.5rem;
72 margin-bottom: 0px; 81 margin-bottom: 0px;
73 color: #707070; 82 color: var(--h2heading);
83 padding-top: 1.5rem;
74} 84}
75h3 { 85h3 {
76 font-size: 16px; 86 font-size: 1.3rem;
77 margin: 0px; 87 margin: 0px;
78 color: #707070; 88 color: var(--h2heading);
89 padding: 1.5rem 0;
90}
91h4 {
92 font-size: 14px;
93 font-weight: lighter;
94 line-height: 1.2rem;
95 margin: auto;
96 padding-top: 1rem;
97}
98table {
99 margin-top: 1.5rem;
100 line-height: 2rem;
101}
102tr {
103 border-bottom: 1px solid var(--trborder);
104}
105tr:first-child {
106 border-bottom: 1px solid var(--trtopborder);
107}
108tr:last-child {
109 border-bottom: none;
110}
111a {
112 text-decoration: none;
113 font-weight: bold;
114 color: var(--link);
115}
116a:hover {
117 color: #8080ff;
118}
119@media (prefers-color-scheme: dark) {
120 :root {
121 --text: #e9e8fa;
122 --bg: #0F0C28;
123 --h2heading: #B8B7CB;
124 --link: #87cefa;
125 --trtopborder: #394150;
126 --trborder: #212936;
127 --chartborder: #b1b0bf;
128 }
79} 129}
80</style> 130</style>
81 131
@@ -83,13 +133,14 @@ h3 {
83</head> 133</head>
84 134
85{% macro poky_link(commit) -%} 135{% macro poky_link(commit) -%}
86 <a href="http://git.yoctoproject.org/cgit/cgit.cgi/poky/log/?id={{ commit }}">{{ commit[0:11] }}</a> 136 <a href="http://git.yoctoproject.org/cgit/cgit.cgi/poky/log/?id={{ commit }}">{{ commit[0:11] }}</a>
87{%- endmacro %} 137{%- endmacro %}
88 138
89<body><div style="width: 700px"> 139<body><div>
140 <h1 style="text-align: center;">Performance Test Report</h1>
90 {# Test metadata #} 141 {# Test metadata #}
91 <h2>General</h2> 142 <h2>General</h2>
92 <hr> 143 <h4>The table provides an overview of the comparison between two selected commits from the same branch.</h4>
93 <table class="meta-table" style="width: 100%"> 144 <table class="meta-table" style="width: 100%">
94 <tr> 145 <tr>
95 <th></th> 146 <th></th>
@@ -112,19 +163,21 @@ h3 {
112 163
113 {# Test result summary #} 164 {# Test result summary #}
114 <h2>Test result summary</h2> 165 <h2>Test result summary</h2>
115 <hr> 166 <h4>The test summary presents a thorough breakdown of each test conducted on the branch, including details such as build time and disk space consumption. Additionally, it gives insights into the average time taken for test execution, along with absolute and relative values for a better understanding.</h4>
116 <table class="summary" style="width: 100%"> 167 <table class="summary" style="width: 100%">
168 <tr>
169 <th>Test name</th>
170 <th>Measurement description</th>
171 <th>Mean value</th>
172 <th>Absolute difference</th>
173 <th>Relative difference</th>
174 </tr>
117 {% for test in test_data %} 175 {% for test in test_data %}
118 {% if loop.index is even %}
119 {% set row_style = 'style="background-color: #f2f2f2"' %}
120 {% else %}
121 {% set row_style = 'style="background-color: #ffffff"' %}
122 {% endif %}
123 {% if test.status == 'SUCCESS' %} 176 {% if test.status == 'SUCCESS' %}
124 {% for measurement in test.measurements %} 177 {% for measurement in test.measurements %}
125 <tr {{ row_style }}> 178 <tr {{ row_style }}>
126 {% if loop.index == 1 %} 179 {% if loop.index == 1 %}
127 <td>{{ test.name }}: {{ test.description }}</td> 180 <td><a href=#{{test.name}}>{{ test.name }}: {{ test.description }}</a></td>
128 {% else %} 181 {% else %}
129 {# add empty cell in place of the test name#} 182 {# add empty cell in place of the test name#}
130 <td></td> 183 <td></td>
@@ -153,10 +206,12 @@ h3 {
153 </table> 206 </table>
154 207
155 {# Detailed test results #} 208 {# Detailed test results #}
209 <h2>Test details</h2>
210 <h4>The following section provides details of each test, accompanied by charts representing build time and disk usage over time or by commit number.</h4>
156 {% for test in test_data %} 211 {% for test in test_data %}
157 <h2>{{ test.name }}: {{ test.description }}</h2> 212 <h3 style="color: #000;" id={{test.name}}>{{ test.name }}: {{ test.description }}</h3>
158 <hr>
159 {% if test.status == 'SUCCESS' %} 213 {% if test.status == 'SUCCESS' %}
214 <div class="card-container">
160 {% for measurement in test.measurements %} 215 {% for measurement in test.measurements %}
161 <div class="measurement"> 216 <div class="measurement">
162 <h3>{{ measurement.description }}</h3> 217 <h3>{{ measurement.description }}</h3>
@@ -275,7 +330,8 @@ h3 {
275 {% endif %} 330 {% endif %}
276 {% endif %} 331 {% endif %}
277 </div> 332 </div>
278 {% endfor %} 333 {% endfor %}
334 </div>
279 {# Unsuccessful test #} 335 {# Unsuccessful test #}
280 {% else %} 336 {% else %}
281 <span style="font-size: 150%; font-weight: bold; color: red;">{{ test.status }} 337 <span style="font-size: 150%; font-weight: bold; color: red;">{{ test.status }}
diff --git a/scripts/lib/build_perf/report.py b/scripts/lib/build_perf/report.py
index ab77424cc7..f4e6a92e09 100644
--- a/scripts/lib/build_perf/report.py
+++ b/scripts/lib/build_perf/report.py
@@ -294,7 +294,7 @@ class SizeVal(MeasurementVal):
294 return "null" 294 return "null"
295 return self / 1024 295 return self / 1024
296 296
297def measurement_stats(meas, prefix=''): 297def measurement_stats(meas, prefix='', time=0):
298 """Get statistics of a measurement""" 298 """Get statistics of a measurement"""
299 if not meas: 299 if not meas:
300 return {prefix + 'sample_cnt': 0, 300 return {prefix + 'sample_cnt': 0,
@@ -319,6 +319,8 @@ def measurement_stats(meas, prefix=''):
319 stats['quantity'] = val_cls.quantity 319 stats['quantity'] = val_cls.quantity
320 stats[prefix + 'sample_cnt'] = len(values) 320 stats[prefix + 'sample_cnt'] = len(values)
321 321
322 # Add start time for both type sysres and disk usage
323 start_time = time
322 mean_val = val_cls(mean(values)) 324 mean_val = val_cls(mean(values))
323 min_val = val_cls(min(values)) 325 min_val = val_cls(min(values))
324 max_val = val_cls(max(values)) 326 max_val = val_cls(max(values))
@@ -334,6 +336,7 @@ def measurement_stats(meas, prefix=''):
334 stats[prefix + 'max'] = max_val 336 stats[prefix + 'max'] = max_val
335 stats[prefix + 'minus'] = val_cls(mean_val - min_val) 337 stats[prefix + 'minus'] = val_cls(mean_val - min_val)
336 stats[prefix + 'plus'] = val_cls(max_val - mean_val) 338 stats[prefix + 'plus'] = val_cls(max_val - mean_val)
339 stats[prefix + 'start_time'] = start_time
337 340
338 return stats 341 return stats
339 342
diff --git a/scripts/lib/devtool/ide_sdk.py b/scripts/lib/devtool/ide_sdk.py
index 7807b322b3..65873b088d 100755
--- a/scripts/lib/devtool/ide_sdk.py
+++ b/scripts/lib/devtool/ide_sdk.py
@@ -1052,7 +1052,7 @@ def register_commands(subparsers, context):
1052 parser_ide_sdk.add_argument( 1052 parser_ide_sdk.add_argument(
1053 '-I', '--key', help='Specify ssh private key for connection to the target') 1053 '-I', '--key', help='Specify ssh private key for connection to the target')
1054 parser_ide_sdk.add_argument( 1054 parser_ide_sdk.add_argument(
1055 '--skip-bitbake', help='Generate IDE configuration but skip calling bibtake to update the SDK.', action='store_true') 1055 '--skip-bitbake', help='Generate IDE configuration but skip calling bitbake to update the SDK', action='store_true')
1056 parser_ide_sdk.add_argument( 1056 parser_ide_sdk.add_argument(
1057 '-k', '--bitbake-k', help='Pass -k parameter to bitbake', action='store_true') 1057 '-k', '--bitbake-k', help='Pass -k parameter to bitbake', action='store_true')
1058 parser_ide_sdk.add_argument( 1058 parser_ide_sdk.add_argument(
diff --git a/scripts/lib/devtool/standard.py b/scripts/lib/devtool/standard.py
index bd009f44b1..1d0fe13788 100644
--- a/scripts/lib/devtool/standard.py
+++ b/scripts/lib/devtool/standard.py
@@ -387,6 +387,19 @@ def _git_ls_tree(repodir, treeish='HEAD', recursive=False):
387 ret[split[3]] = split[0:3] 387 ret[split[3]] = split[0:3]
388 return ret 388 return ret
389 389
390def _git_modified(repodir):
391 """List the difference between HEAD and the index"""
392 import bb
393 cmd = ['git', 'status', '--porcelain']
394 out, _ = bb.process.run(cmd, cwd=repodir)
395 ret = []
396 if out:
397 for line in out.split("\n"):
398 if line and not line.startswith('??'):
399 ret.append(line[3:])
400 return ret
401
402
390def _git_exclude_path(srctree, path): 403def _git_exclude_path(srctree, path):
391 """Return pathspec (list of paths) that excludes certain path""" 404 """Return pathspec (list of paths) that excludes certain path"""
392 # NOTE: "Filtering out" files/paths in this way is not entirely reliable - 405 # NOTE: "Filtering out" files/paths in this way is not entirely reliable -
@@ -460,32 +473,6 @@ def sync(args, config, basepath, workspace):
460 finally: 473 finally:
461 tinfoil.shutdown() 474 tinfoil.shutdown()
462 475
463def symlink_oelocal_files_srctree(rd, srctree):
464 import oe.patch
465 if os.path.abspath(rd.getVar('S')) == os.path.abspath(rd.getVar('WORKDIR')):
466 # If recipe extracts to ${WORKDIR}, symlink the files into the srctree
467 # (otherwise the recipe won't build as expected)
468 local_files_dir = os.path.join(srctree, 'oe-local-files')
469 addfiles = []
470 for root, _, files in os.walk(local_files_dir):
471 relpth = os.path.relpath(root, local_files_dir)
472 if relpth != '.':
473 bb.utils.mkdirhier(os.path.join(srctree, relpth))
474 for fn in files:
475 if fn == '.gitignore':
476 continue
477 destpth = os.path.join(srctree, relpth, fn)
478 if os.path.exists(destpth):
479 os.unlink(destpth)
480 if relpth != '.':
481 back_relpth = os.path.relpath(local_files_dir, root)
482 os.symlink('%s/oe-local-files/%s/%s' % (back_relpth, relpth, fn), destpth)
483 else:
484 os.symlink('oe-local-files/%s' % fn, destpth)
485 addfiles.append(os.path.join(relpth, fn))
486 if addfiles:
487 oe.patch.GitApplyTree.commitIgnored("Add local file symlinks", dir=srctree, files=addfiles, d=rd)
488
489def _extract_source(srctree, keep_temp, devbranch, sync, config, basepath, workspace, fixed_setup, d, tinfoil, no_overrides=False): 476def _extract_source(srctree, keep_temp, devbranch, sync, config, basepath, workspace, fixed_setup, d, tinfoil, no_overrides=False):
490 """Extract sources of a recipe""" 477 """Extract sources of a recipe"""
491 import oe.recipeutils 478 import oe.recipeutils
@@ -657,9 +644,6 @@ def _extract_source(srctree, keep_temp, devbranch, sync, config, basepath, works
657 elif not os.path.exists(workshareddir): 644 elif not os.path.exists(workshareddir):
658 oe.path.copyhardlinktree(srcsubdir, workshareddir) 645 oe.path.copyhardlinktree(srcsubdir, workshareddir)
659 646
660 tempdir_localdir = os.path.join(tempdir, 'oe-local-files')
661 srctree_localdir = os.path.join(srctree, 'oe-local-files')
662
663 if sync: 647 if sync:
664 try: 648 try:
665 logger.info('Backing up current %s branch as branch: %s.bak' % (devbranch, devbranch)) 649 logger.info('Backing up current %s branch as branch: %s.bak' % (devbranch, devbranch))
@@ -674,29 +658,8 @@ def _extract_source(srctree, keep_temp, devbranch, sync, config, basepath, works
674 except bb.process.ExecutionError as e: 658 except bb.process.ExecutionError as e:
675 raise DevtoolError("Error when syncing source files to local checkout: %s" % str(e)) 659 raise DevtoolError("Error when syncing source files to local checkout: %s" % str(e))
676 660
677 # Move the oe-local-files directory to srctree.
678 # As oe-local-files is not part of the constructed git tree,
679 # removing it directly during the synchronization might surprise
680 # the user. Instead, we move it to oe-local-files.bak and remind
681 # the user in the log message.
682 if os.path.exists(srctree_localdir + '.bak'):
683 shutil.rmtree(srctree_localdir + '.bak')
684
685 if os.path.exists(srctree_localdir):
686 logger.info('Backing up current local file directory %s' % srctree_localdir)
687 shutil.move(srctree_localdir, srctree_localdir + '.bak')
688
689 if os.path.exists(tempdir_localdir):
690 logger.info('Syncing local source files to srctree...')
691 shutil.copytree(tempdir_localdir, srctree_localdir)
692 else: 661 else:
693 # Move oe-local-files directory to srctree
694 if os.path.exists(tempdir_localdir):
695 logger.info('Adding local source files to srctree...')
696 shutil.move(tempdir_localdir, srcsubdir)
697
698 shutil.move(srcsubdir, srctree) 662 shutil.move(srcsubdir, srctree)
699 symlink_oelocal_files_srctree(d, srctree)
700 663
701 if is_kernel_yocto: 664 if is_kernel_yocto:
702 logger.info('Copying kernel config to srctree') 665 logger.info('Copying kernel config to srctree')
@@ -852,34 +815,22 @@ def modify(args, config, basepath, workspace):
852 if (os.path.exists(srcdir) and os.listdir(srcdir)) and (kernelVersion in staging_kerVer and staging_kbranch == kbranch): 815 if (os.path.exists(srcdir) and os.listdir(srcdir)) and (kernelVersion in staging_kerVer and staging_kbranch == kbranch):
853 oe.path.copyhardlinktree(srcdir, srctree) 816 oe.path.copyhardlinktree(srcdir, srctree)
854 workdir = rd.getVar('WORKDIR') 817 workdir = rd.getVar('WORKDIR')
818 unpackdir = rd.getVar('UNPACKDIR')
855 srcsubdir = rd.getVar('S') 819 srcsubdir = rd.getVar('S')
856 localfilesdir = os.path.join(srctree, 'oe-local-files') 820 localfilesdir = os.path.join(srctree, 'oe-local-files')
857 # Move local source files into separate subdir
858 recipe_patches = [os.path.basename(patch) for patch in oe.recipeutils.get_recipe_patches(rd)]
859 local_files = oe.recipeutils.get_recipe_local_files(rd)
860 821
861 for key in local_files.copy(): 822 # Add locally copied files to gitignore as we add back to the metadata directly
862 if key.endswith('scc'): 823 local_files = oe.recipeutils.get_recipe_local_files(rd)
863 sccfile = open(local_files[key], 'r')
864 for l in sccfile:
865 line = l.split()
866 if line and line[0] in ('kconf', 'patch'):
867 cfg = os.path.join(os.path.dirname(local_files[key]), line[-1])
868 if not cfg in local_files.values():
869 local_files[line[-1]] = cfg
870 shutil.copy2(cfg, workdir)
871 sccfile.close()
872
873 # Ignore local files with subdir={BP}
874 srcabspath = os.path.abspath(srcsubdir) 824 srcabspath = os.path.abspath(srcsubdir)
875 local_files = [fname for fname in local_files if os.path.exists(os.path.join(workdir, fname)) and (srcabspath == workdir or not os.path.join(workdir, fname).startswith(srcabspath + os.sep))] 825 local_files = [fname for fname in local_files if
826 os.path.exists(os.path.join(unpackdir, fname)) and
827 srcabspath == unpackdir]
876 if local_files: 828 if local_files:
877 for fname in local_files: 829 with open(os.path.join(srctree, '.gitignore'), 'a+') as f:
878 _move_file(os.path.join(workdir, fname), os.path.join(srctree, 'oe-local-files', fname)) 830 f.write('# Ignore local files, by default. Remove following lines'
879 with open(os.path.join(srctree, 'oe-local-files', '.gitignore'), 'w') as f: 831 'if you want to commit the directory to Git\n')
880 f.write('# Ignore local files, by default. Remove this file if you want to commit the directory to Git\n*\n') 832 for fname in local_files:
881 833 f.write('%s\n' % fname)
882 symlink_oelocal_files_srctree(rd, srctree)
883 834
884 task = 'do_configure' 835 task = 'do_configure'
885 res = tinfoil.build_targets(pn, task, handle_events=True) 836 res = tinfoil.build_targets(pn, task, handle_events=True)
@@ -904,7 +855,10 @@ def modify(args, config, basepath, workspace):
904 (stdout, _) = bb.process.run('git rev-list --reverse %s..HEAD' % initial_revs["."], cwd=srctree) 855 (stdout, _) = bb.process.run('git rev-list --reverse %s..HEAD' % initial_revs["."], cwd=srctree)
905 commits["."] = stdout.split() 856 commits["."] = stdout.split()
906 check_commits = True 857 check_commits = True
907 (stdout, _) = bb.process.run('git submodule --quiet foreach --recursive \'echo `git rev-parse devtool-base` $PWD\'', cwd=srctree) 858 try:
859 (stdout, _) = bb.process.run('git submodule --quiet foreach --recursive \'echo `git rev-parse devtool-base` $PWD\'', cwd=srctree)
860 except bb.process.ExecutionError:
861 stdout = ""
908 for line in stdout.splitlines(): 862 for line in stdout.splitlines():
909 (rev, submodule_path) = line.split() 863 (rev, submodule_path) = line.split()
910 submodule = os.path.relpath(submodule_path, srctree) 864 submodule = os.path.relpath(submodule_path, srctree)
@@ -1475,6 +1429,7 @@ def _export_local_files(srctree, rd, destdir, srctreebase):
1475 # Instead they are directly copied over the original source files (in 1429 # Instead they are directly copied over the original source files (in
1476 # recipe space). 1430 # recipe space).
1477 existing_files = oe.recipeutils.get_recipe_local_files(rd) 1431 existing_files = oe.recipeutils.get_recipe_local_files(rd)
1432
1478 new_set = None 1433 new_set = None
1479 updated = OrderedDict() 1434 updated = OrderedDict()
1480 added = OrderedDict() 1435 added = OrderedDict()
@@ -1491,24 +1446,28 @@ def _export_local_files(srctree, rd, destdir, srctreebase):
1491 if branchname.startswith(override_branch_prefix): 1446 if branchname.startswith(override_branch_prefix):
1492 return (updated, added, removed) 1447 return (updated, added, removed)
1493 1448
1494 local_files_dir = os.path.join(srctreebase, 'oe-local-files') 1449 files = _git_modified(srctree)
1495 git_files = _git_ls_tree(srctree) 1450 #if not files:
1496 if 'oe-local-files' in git_files: 1451 # files = _ls_tree(srctree)
1497 # If tracked by Git, take the files from srctree HEAD. First get 1452 for f in files:
1498 # the tree object of the directory 1453 fullfile = os.path.join(srctree, f)
1499 tmp_index = os.path.join(srctree, '.git', 'index.tmp.devtool') 1454 if os.path.exists(os.path.join(fullfile, ".git")):
1500 tree = git_files['oe-local-files'][2] 1455 # submodules handled elsewhere
1501 bb.process.run(['git', 'checkout', tree, '--', '.'], cwd=srctree, 1456 continue
1502 env=dict(os.environ, GIT_WORK_TREE=destdir, 1457 if f not in existing_files:
1503 GIT_INDEX_FILE=tmp_index)) 1458 added[f] = {}
1504 new_set = list(_git_ls_tree(srctree, tree, True).keys()) 1459 if os.path.isdir(os.path.join(srctree, f)):
1505 elif os.path.isdir(local_files_dir): 1460 shutil.copytree(fullfile, os.path.join(destdir, f))
1506 # If not tracked by Git, just copy from working copy 1461 else:
1507 new_set = _ls_tree(local_files_dir) 1462 shutil.copy2(fullfile, os.path.join(destdir, f))
1508 bb.process.run(['cp', '-ax', 1463 elif not os.path.exists(fullfile):
1509 os.path.join(local_files_dir, '.'), destdir]) 1464 removed[f] = existing_files[f]
1510 else: 1465 elif f in existing_files:
1511 new_set = [] 1466 updated[f] = {'path' : existing_files[f]}
1467 if os.path.isdir(os.path.join(srctree, f)):
1468 shutil.copytree(fullfile, os.path.join(destdir, f))
1469 else:
1470 shutil.copy2(fullfile, os.path.join(destdir, f))
1512 1471
1513 # Special handling for kernel config 1472 # Special handling for kernel config
1514 if bb.data.inherits_class('kernel-yocto', rd): 1473 if bb.data.inherits_class('kernel-yocto', rd):
@@ -1516,17 +1475,14 @@ def _export_local_files(srctree, rd, destdir, srctreebase):
1516 fragment_path = os.path.join(destdir, fragment_fn) 1475 fragment_path = os.path.join(destdir, fragment_fn)
1517 if _create_kconfig_diff(srctree, rd, fragment_path): 1476 if _create_kconfig_diff(srctree, rd, fragment_path):
1518 if os.path.exists(fragment_path): 1477 if os.path.exists(fragment_path):
1519 if fragment_fn not in new_set: 1478 if fragment_fn in removed:
1520 new_set.append(fragment_fn) 1479 del removed[fragment_fn]
1521 # Copy fragment to local-files 1480 if fragment_fn not in updated and fragment_fn not in added:
1522 if os.path.isdir(local_files_dir): 1481 added[fragment_fn] = {}
1523 shutil.copy2(fragment_path, local_files_dir)
1524 else: 1482 else:
1525 if fragment_fn in new_set: 1483 if fragment_fn in updated:
1526 new_set.remove(fragment_fn) 1484 revoved[fragment_fn] = updated[fragment_fn]
1527 # Remove fragment from local-files 1485 del updated[fragment_fn]
1528 if os.path.exists(os.path.join(local_files_dir, fragment_fn)):
1529 os.unlink(os.path.join(local_files_dir, fragment_fn))
1530 1486
1531 # Special handling for cml1, ccmake, etc bbclasses that generated 1487 # Special handling for cml1, ccmake, etc bbclasses that generated
1532 # configuration fragment files that are consumed as source files 1488 # configuration fragment files that are consumed as source files
@@ -1534,42 +1490,13 @@ def _export_local_files(srctree, rd, destdir, srctreebase):
1534 if bb.data.inherits_class(frag_class, rd): 1490 if bb.data.inherits_class(frag_class, rd):
1535 srcpath = os.path.join(rd.getVar('WORKDIR'), frag_name) 1491 srcpath = os.path.join(rd.getVar('WORKDIR'), frag_name)
1536 if os.path.exists(srcpath): 1492 if os.path.exists(srcpath):
1537 if frag_name not in new_set: 1493 if frag_name in removed:
1538 new_set.append(frag_name) 1494 del removed[frag_name]
1495 if frag_name not in updated:
1496 added[frag_name] = {}
1539 # copy fragment into destdir 1497 # copy fragment into destdir
1540 shutil.copy2(srcpath, destdir) 1498 shutil.copy2(srcpath, destdir)
1541 # copy fragment into local files if exists 1499
1542 if os.path.isdir(local_files_dir):
1543 shutil.copy2(srcpath, local_files_dir)
1544
1545 if new_set is not None:
1546 for fname in new_set:
1547 if fname in existing_files:
1548 origpath = existing_files.pop(fname)
1549 workpath = os.path.join(local_files_dir, fname)
1550 if not filecmp.cmp(origpath, workpath):
1551 updated[fname] = {'path' : origpath}
1552 elif fname != '.gitignore':
1553 added[fname] = {}
1554
1555 workdir = rd.getVar('WORKDIR')
1556 s = rd.getVar('S')
1557 if not s.endswith(os.sep):
1558 s += os.sep
1559
1560 if workdir != s:
1561 # Handle files where subdir= was specified
1562 for fname in list(existing_files.keys()):
1563 # FIXME handle both subdir starting with BP and not?
1564 fworkpath = os.path.join(workdir, fname)
1565 if fworkpath.startswith(s):
1566 fpath = os.path.join(srctree, os.path.relpath(fworkpath, s))
1567 if os.path.exists(fpath):
1568 origpath = existing_files.pop(fname)
1569 if not filecmp.cmp(origpath, fpath):
1570 updated[fpath] = {'path' : origpath}
1571
1572 removed = existing_files
1573 return (updated, added, removed) 1500 return (updated, added, removed)
1574 1501
1575 1502
diff --git a/scripts/lib/devtool/upgrade.py b/scripts/lib/devtool/upgrade.py
index fa5b8ef3c7..8e13833b51 100644
--- a/scripts/lib/devtool/upgrade.py
+++ b/scripts/lib/devtool/upgrade.py
@@ -32,7 +32,7 @@ def _run(cmd, cwd=''):
32 32
33def _get_srctree(tmpdir): 33def _get_srctree(tmpdir):
34 srctree = tmpdir 34 srctree = tmpdir
35 dirs = scriptutils.filter_src_subdirs(tmpdir) 35 dirs = os.listdir(tmpdir)
36 if len(dirs) == 1: 36 if len(dirs) == 1:
37 srctree = os.path.join(tmpdir, dirs[0]) 37 srctree = os.path.join(tmpdir, dirs[0])
38 else: 38 else:
@@ -534,6 +534,15 @@ def _generate_license_diff(old_licenses, new_licenses):
534 diff = diff + line 534 diff = diff + line
535 return diff 535 return diff
536 536
537def _run_recipe_update_extra_tasks(pn, rd, tinfoil):
538 tasks = []
539 for task in (rd.getVar('RECIPE_UPDATE_EXTRA_TASKS') or '').split():
540 logger.info('Running extra recipe update task: %s' % task)
541 res = tinfoil.build_targets(pn, task, handle_events=True)
542
543 if not res:
544 raise DevtoolError('Running extra recipe update task %s for %s failed' % (task, pn))
545
537def upgrade(args, config, basepath, workspace): 546def upgrade(args, config, basepath, workspace):
538 """Entry point for the devtool 'upgrade' subcommand""" 547 """Entry point for the devtool 'upgrade' subcommand"""
539 548
@@ -609,6 +618,8 @@ def upgrade(args, config, basepath, workspace):
609 copied, config.workspace_path, rd) 618 copied, config.workspace_path, rd)
610 standard._add_md5(config, pn, af) 619 standard._add_md5(config, pn, af)
611 620
621 _run_recipe_update_extra_tasks(pn, rd, tinfoil)
622
612 update_unlockedsigs(basepath, workspace, args.fixed_setup, [pn]) 623 update_unlockedsigs(basepath, workspace, args.fixed_setup, [pn])
613 624
614 logger.info('Upgraded source extracted to %s' % srctree) 625 logger.info('Upgraded source extracted to %s' % srctree)
diff --git a/scripts/lib/recipetool/append.py b/scripts/lib/recipetool/append.py
index 341e893305..10945d6008 100644
--- a/scripts/lib/recipetool/append.py
+++ b/scripts/lib/recipetool/append.py
@@ -101,7 +101,7 @@ def determine_file_source(targetpath, rd):
101 import oe.recipeutils 101 import oe.recipeutils
102 102
103 # See if it's in do_install for the recipe 103 # See if it's in do_install for the recipe
104 workdir = rd.getVar('WORKDIR') 104 unpackdir = rd.getVar('UNPACKDIR')
105 src_uri = rd.getVar('SRC_URI') 105 src_uri = rd.getVar('SRC_URI')
106 srcfile = '' 106 srcfile = ''
107 modpatches = [] 107 modpatches = []
@@ -113,9 +113,9 @@ def determine_file_source(targetpath, rd):
113 if not srcpath.startswith('/'): 113 if not srcpath.startswith('/'):
114 # Handle non-absolute path 114 # Handle non-absolute path
115 srcpath = os.path.abspath(os.path.join(rd.getVarFlag('do_install', 'dirs').split()[-1], srcpath)) 115 srcpath = os.path.abspath(os.path.join(rd.getVarFlag('do_install', 'dirs').split()[-1], srcpath))
116 if srcpath.startswith(workdir): 116 if srcpath.startswith(unpackdir):
117 # OK, now we have the source file name, look for it in SRC_URI 117 # OK, now we have the source file name, look for it in SRC_URI
118 workdirfile = os.path.relpath(srcpath, workdir) 118 workdirfile = os.path.relpath(srcpath, unpackdir)
119 # FIXME this is where we ought to have some code in the fetcher, because this is naive 119 # FIXME this is where we ought to have some code in the fetcher, because this is naive
120 for item in src_uri.split(): 120 for item in src_uri.split():
121 localpath = bb.fetch2.localpath(item, rd) 121 localpath = bb.fetch2.localpath(item, rd)
diff --git a/scripts/lib/recipetool/create.py b/scripts/lib/recipetool/create.py
index 8e9ff38db6..066366e34f 100644
--- a/scripts/lib/recipetool/create.py
+++ b/scripts/lib/recipetool/create.py
@@ -528,7 +528,7 @@ def create_recipe(args):
528 if ftmpdir and args.keep_temp: 528 if ftmpdir and args.keep_temp:
529 logger.info('Fetch temp directory is %s' % ftmpdir) 529 logger.info('Fetch temp directory is %s' % ftmpdir)
530 530
531 dirlist = scriptutils.filter_src_subdirs(srctree) 531 dirlist = os.listdir(srctree)
532 logger.debug('Directory listing (excluding filtered out):\n %s' % '\n '.join(dirlist)) 532 logger.debug('Directory listing (excluding filtered out):\n %s' % '\n '.join(dirlist))
533 if len(dirlist) == 1: 533 if len(dirlist) == 1:
534 singleitem = os.path.join(srctree, dirlist[0]) 534 singleitem = os.path.join(srctree, dirlist[0])
diff --git a/scripts/lib/scriptutils.py b/scripts/lib/scriptutils.py
index f23e53cba9..81f0b01fa5 100644
--- a/scripts/lib/scriptutils.py
+++ b/scripts/lib/scriptutils.py
@@ -179,6 +179,8 @@ def fetch_url(tinfoil, srcuri, srcrev, destdir, logger, preserve_tmp=False, mirr
179 f.write('SRCREV = "%s"\n' % srcrev) 179 f.write('SRCREV = "%s"\n' % srcrev)
180 f.write('PV = "0.0+"\n') 180 f.write('PV = "0.0+"\n')
181 f.write('WORKDIR = "%s"\n' % tmpworkdir) 181 f.write('WORKDIR = "%s"\n' % tmpworkdir)
182 f.write('UNPACKDIR = "%s"\n' % destdir)
183
182 # Set S out of the way so it doesn't get created under the workdir 184 # Set S out of the way so it doesn't get created under the workdir
183 f.write('S = "%s"\n' % os.path.join(tmpdir, 'emptysrc')) 185 f.write('S = "%s"\n' % os.path.join(tmpdir, 'emptysrc'))
184 if not mirrors: 186 if not mirrors:
@@ -232,10 +234,6 @@ def fetch_url(tinfoil, srcuri, srcrev, destdir, logger, preserve_tmp=False, mirr
232 if e.errno != errno.ENOTEMPTY: 234 if e.errno != errno.ENOTEMPTY:
233 raise 235 raise
234 236
235 bb.utils.mkdirhier(destdir)
236 for fn in os.listdir(tmpworkdir):
237 shutil.move(os.path.join(tmpworkdir, fn), destdir)
238
239 finally: 237 finally:
240 if not preserve_tmp: 238 if not preserve_tmp:
241 shutil.rmtree(tmpdir) 239 shutil.rmtree(tmpdir)
@@ -271,12 +269,3 @@ def is_src_url(param):
271 return True 269 return True
272 return False 270 return False
273 271
274def filter_src_subdirs(pth):
275 """
276 Filter out subdirectories of initial unpacked source trees that we do not care about.
277 Used by devtool and recipetool.
278 """
279 dirlist = os.listdir(pth)
280 filterout = ['git.indirectionsymlink', 'source-date-epoch', 'sstate-install-recipe_qa']
281 dirlist = [x for x in dirlist if x not in filterout]
282 return dirlist
diff --git a/scripts/lib/wic/engine.py b/scripts/lib/wic/engine.py
index 674ccfc244..ce7e6c5d75 100644
--- a/scripts/lib/wic/engine.py
+++ b/scripts/lib/wic/engine.py
@@ -359,7 +359,7 @@ class Disk:
359 Remove files/dirs and their contents from the partition. 359 Remove files/dirs and their contents from the partition.
360 This only applies to ext* partition. 360 This only applies to ext* partition.
361 """ 361 """
362 abs_path = re.sub('\/\/+', '/', path) 362 abs_path = re.sub(r'\/\/+', '/', path)
363 cmd = "{} {} -wR 'rm \"{}\"'".format(self.debugfs, 363 cmd = "{} {} -wR 'rm \"{}\"'".format(self.debugfs,
364 self._get_part_image(pnum), 364 self._get_part_image(pnum),
365 abs_path) 365 abs_path)
diff --git a/scripts/lib/wic/plugins/source/bootimg-efi.py b/scripts/lib/wic/plugins/source/bootimg-efi.py
index 13a9cddf4e..7cc5131541 100644
--- a/scripts/lib/wic/plugins/source/bootimg-efi.py
+++ b/scripts/lib/wic/plugins/source/bootimg-efi.py
@@ -428,10 +428,10 @@ class BootimgEFIPlugin(SourcePlugin):
428 elif source_params['loader'] == 'uefi-kernel': 428 elif source_params['loader'] == 'uefi-kernel':
429 kernel = get_bitbake_var("KERNEL_IMAGETYPE") 429 kernel = get_bitbake_var("KERNEL_IMAGETYPE")
430 if not kernel: 430 if not kernel:
431 raise WicError("Empty KERNEL_IMAGETYPE %s\n" % target) 431 raise WicError("Empty KERNEL_IMAGETYPE")
432 target = get_bitbake_var("TARGET_SYS") 432 target = get_bitbake_var("TARGET_SYS")
433 if not target: 433 if not target:
434 raise WicError("Unknown arch (TARGET_SYS) %s\n" % target) 434 raise WicError("Empty TARGET_SYS")
435 435
436 if re.match("x86_64", target): 436 if re.match("x86_64", target):
437 kernel_efi_image = "bootx64.efi" 437 kernel_efi_image = "bootx64.efi"
diff --git a/scripts/makefile-getvar b/scripts/makefile-getvar
new file mode 100755
index 0000000000..4a07055e68
--- /dev/null
+++ b/scripts/makefile-getvar
@@ -0,0 +1,24 @@
1#! /bin/sh
2
3# Get a variable's value from a makefile:
4#
5# $ makefile-getvar Makefile VARIABLE VARIABLE ...
6#
7# If multiple variables are specified, they will be printed one per line.
8#
9# SPDX-FileCopyrightText: Copyright 2024 Arm Limited and/or its affiliates <open-source-office@arm.com>
10# SPDX-License-Identifier: GPL-2.0-only
11
12set -eu
13
14MAKEFILE=$1
15shift
16
17for VARIABLE in $*; do
18 make -f - $VARIABLE.var <<EOF
19include $MAKEFILE
20
21%.var:
22 @echo \$(\$*)
23EOF
24done
diff --git a/scripts/oe-build-perf-report b/scripts/oe-build-perf-report
index 7812ea4540..6c3c726ee3 100755
--- a/scripts/oe-build-perf-report
+++ b/scripts/oe-build-perf-report
@@ -336,8 +336,12 @@ def print_html_report(data, id_comp, buildstats):
336 test_i = test_data['tests'][test] 336 test_i = test_data['tests'][test]
337 meas_i = test_i['measurements'][meas] 337 meas_i = test_i['measurements'][meas]
338 commit_num = get_data_item(meta, 'layers.meta.commit_count') 338 commit_num = get_data_item(meta, 'layers.meta.commit_count')
339 samples.append(measurement_stats(meas_i)) 339 commit = get_data_item(meta, 'layers.meta.commit')
340 # Add start_time for both test measurement types of sysres and disk usage
341 start_time = test_i['start_time'][0]
342 samples.append(measurement_stats(meas_i, '', start_time))
340 samples[-1]['commit_num'] = commit_num 343 samples[-1]['commit_num'] = commit_num
344 samples[-1]['commit'] = commit
341 345
342 absdiff = samples[-1]['val_cls'](samples[-1]['mean'] - samples[id_comp]['mean']) 346 absdiff = samples[-1]['val_cls'](samples[-1]['mean'] - samples[id_comp]['mean'])
343 reldiff = absdiff * 100 / samples[id_comp]['mean'] 347 reldiff = absdiff * 100 / samples[id_comp]['mean']
@@ -473,7 +477,7 @@ Examine build performance test results from a Git repository"""
473 group.add_argument('--branch', '-B', default='master', help="Branch to find commit in") 477 group.add_argument('--branch', '-B', default='master', help="Branch to find commit in")
474 group.add_argument('--branch2', help="Branch to find comparision revisions in") 478 group.add_argument('--branch2', help="Branch to find comparision revisions in")
475 group.add_argument('--machine', default='qemux86') 479 group.add_argument('--machine', default='qemux86')
476 group.add_argument('--history-length', default=25, type=int, 480 group.add_argument('--history-length', default=300, type=int,
477 help="Number of tested revisions to plot in html report") 481 help="Number of tested revisions to plot in html report")
478 group.add_argument('--commit', 482 group.add_argument('--commit',
479 help="Revision to search for") 483 help="Revision to search for")
diff --git a/scripts/oe-setup-build b/scripts/oe-setup-build
index 5364f2b481..c0476992a2 100755
--- a/scripts/oe-setup-build
+++ b/scripts/oe-setup-build
@@ -91,7 +91,16 @@ def setup_build_env(args):
91 builddir = args.b if args.b else template["buildpath"] 91 builddir = args.b if args.b else template["buildpath"]
92 no_shell = args.no_shell 92 no_shell = args.no_shell
93 coredir = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__)), '..')) 93 coredir = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__)), '..'))
94 cmd = "TEMPLATECONF={} . {} {}".format(template["templatepath"], os.path.join(coredir, 'oe-init-build-env'), builddir) 94 cmd_base = ". {} {}".format(os.path.join(coredir, 'oe-init-build-env'), os.path.abspath(builddir))
95
96 initbuild = os.path.join(builddir, 'init-build-env')
97 if not os.path.exists(initbuild):
98 os.makedirs(builddir, exist_ok=True)
99 with open(initbuild, 'w') as f:
100 f.write(cmd_base)
101 print("\nRun '. {}' to initialize the build in a current shell session.\n".format(initbuild))
102
103 cmd = "TEMPLATECONF={} {}".format(template["templatepath"], cmd_base)
95 if not no_shell: 104 if not no_shell:
96 cmd = cmd + " && {}".format(os.environ['SHELL']) 105 cmd = cmd + " && {}".format(os.environ['SHELL'])
97 print("Running:", cmd) 106 print("Running:", cmd)