User | Revision | Line number | New contents of line |
switches |
0:0e018d759a2a
|
1
|
"""
|
switches |
0:0e018d759a2a
|
2
|
mbed SDK
|
switches |
0:0e018d759a2a
|
3
|
Copyright (c) 2011-2016 ARM Limited
|
switches |
0:0e018d759a2a
|
4
|
|
switches |
0:0e018d759a2a
|
5
|
Licensed under the Apache License, Version 2.0 (the "License");
|
switches |
0:0e018d759a2a
|
6
|
you may not use this file except in compliance with the License.
|
switches |
0:0e018d759a2a
|
7
|
You may obtain a copy of the License at
|
switches |
0:0e018d759a2a
|
8
|
|
switches |
0:0e018d759a2a
|
9
|
http://www.apache.org/licenses/LICENSE-2.0
|
switches |
0:0e018d759a2a
|
10
|
|
switches |
0:0e018d759a2a
|
11
|
Unless required by applicable law or agreed to in writing, software
|
switches |
0:0e018d759a2a
|
12
|
distributed under the License is distributed on an "AS IS" BASIS,
|
switches |
0:0e018d759a2a
|
13
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
switches |
0:0e018d759a2a
|
14
|
See the License for the specific language governing permissions and
|
switches |
0:0e018d759a2a
|
15
|
limitations under the License.
|
switches |
0:0e018d759a2a
|
16
|
"""
|
switches |
0:0e018d759a2a
|
17
|
|
switches |
0:0e018d759a2a
|
18
|
import re
|
switches |
0:0e018d759a2a
|
19
|
import tempfile
|
switches |
0:0e018d759a2a
|
20
|
from types import ListType
|
switches |
0:0e018d759a2a
|
21
|
from shutil import rmtree
|
switches |
0:0e018d759a2a
|
22
|
from os.path import join, exists, dirname, basename, abspath, normpath
|
switches |
0:0e018d759a2a
|
23
|
from os import linesep, remove
|
switches |
0:0e018d759a2a
|
24
|
from time import time
|
switches |
0:0e018d759a2a
|
25
|
|
switches |
0:0e018d759a2a
|
26
|
from tools.utils import mkdir, run_cmd, run_cmd_ext, NotSupportedException,\
|
switches |
0:0e018d759a2a
|
27
|
ToolException, InvalidReleaseTargetException
|
switches |
0:0e018d759a2a
|
28
|
from tools.paths import MBED_CMSIS_PATH, MBED_TARGETS_PATH, MBED_LIBRARIES,\
|
switches |
0:0e018d759a2a
|
29
|
MBED_HEADER, MBED_DRIVERS, MBED_PLATFORM, MBED_HAL, MBED_CONFIG_FILE,\
|
switches |
0:0e018d759a2a
|
30
|
MBED_LIBRARIES_DRIVERS, MBED_LIBRARIES_PLATFORM, MBED_LIBRARIES_HAL,\
|
switches |
0:0e018d759a2a
|
31
|
BUILD_DIR
|
switches |
0:0e018d759a2a
|
32
|
from tools.targets import TARGET_NAMES, TARGET_MAP
|
switches |
0:0e018d759a2a
|
33
|
from tools.libraries import Library
|
switches |
0:0e018d759a2a
|
34
|
from tools.toolchains import TOOLCHAIN_CLASSES
|
switches |
0:0e018d759a2a
|
35
|
from jinja2 import FileSystemLoader
|
switches |
0:0e018d759a2a
|
36
|
from jinja2.environment import Environment
|
switches |
0:0e018d759a2a
|
37
|
from tools.config import Config
|
switches |
0:0e018d759a2a
|
38
|
|
switches |
0:0e018d759a2a
|
39
|
RELEASE_VERSIONS = ['2', '5']
|
switches |
0:0e018d759a2a
|
40
|
|
switches |
0:0e018d759a2a
|
41
|
def prep_report(report, target_name, toolchain_name, id_name):
|
switches |
0:0e018d759a2a
|
42
|
"""Setup report keys
|
switches |
0:0e018d759a2a
|
43
|
|
switches |
0:0e018d759a2a
|
44
|
Positional arguments:
|
switches |
0:0e018d759a2a
|
45
|
report - the report to fill
|
switches |
0:0e018d759a2a
|
46
|
target_name - the target being used
|
switches |
0:0e018d759a2a
|
47
|
toolchain_name - the toolchain being used
|
switches |
0:0e018d759a2a
|
48
|
id_name - the name of the executable or library being built
|
switches |
0:0e018d759a2a
|
49
|
"""
|
switches |
0:0e018d759a2a
|
50
|
if not target_name in report:
|
switches |
0:0e018d759a2a
|
51
|
report[target_name] = {}
|
switches |
0:0e018d759a2a
|
52
|
|
switches |
0:0e018d759a2a
|
53
|
if not toolchain_name in report[target_name]:
|
switches |
0:0e018d759a2a
|
54
|
report[target_name][toolchain_name] = {}
|
switches |
0:0e018d759a2a
|
55
|
|
switches |
0:0e018d759a2a
|
56
|
if not id_name in report[target_name][toolchain_name]:
|
switches |
0:0e018d759a2a
|
57
|
report[target_name][toolchain_name][id_name] = []
|
switches |
0:0e018d759a2a
|
58
|
|
switches |
0:0e018d759a2a
|
59
|
def prep_properties(properties, target_name, toolchain_name, vendor_label):
|
switches |
0:0e018d759a2a
|
60
|
"""Setup test properties
|
switches |
0:0e018d759a2a
|
61
|
|
switches |
0:0e018d759a2a
|
62
|
Positional arguments:
|
switches |
0:0e018d759a2a
|
63
|
properties - the dict to fill
|
switches |
0:0e018d759a2a
|
64
|
target_name - the target the test is targeting
|
switches |
0:0e018d759a2a
|
65
|
toolchain_name - the toolchain that will compile the test
|
switches |
0:0e018d759a2a
|
66
|
vendor_label - the vendor
|
switches |
0:0e018d759a2a
|
67
|
"""
|
switches |
0:0e018d759a2a
|
68
|
if not target_name in properties:
|
switches |
0:0e018d759a2a
|
69
|
properties[target_name] = {}
|
switches |
0:0e018d759a2a
|
70
|
|
switches |
0:0e018d759a2a
|
71
|
if not toolchain_name in properties[target_name]:
|
switches |
0:0e018d759a2a
|
72
|
properties[target_name][toolchain_name] = {}
|
switches |
0:0e018d759a2a
|
73
|
|
switches |
0:0e018d759a2a
|
74
|
properties[target_name][toolchain_name]["target"] = target_name
|
switches |
0:0e018d759a2a
|
75
|
properties[target_name][toolchain_name]["vendor"] = vendor_label
|
switches |
0:0e018d759a2a
|
76
|
properties[target_name][toolchain_name]["toolchain"] = toolchain_name
|
switches |
0:0e018d759a2a
|
77
|
|
switches |
0:0e018d759a2a
|
78
|
def create_result(target_name, toolchain_name, id_name, description):
|
switches |
0:0e018d759a2a
|
79
|
"""Create a result dictionary
|
switches |
0:0e018d759a2a
|
80
|
|
switches |
0:0e018d759a2a
|
81
|
Positional arguments:
|
switches |
0:0e018d759a2a
|
82
|
target_name - the target being built for
|
switches |
0:0e018d759a2a
|
83
|
toolchain_name - the toolchain doing the building
|
switches |
0:0e018d759a2a
|
84
|
id_name - the name of the executable or library being built
|
switches |
0:0e018d759a2a
|
85
|
description - a human readable description of what's going on
|
switches |
0:0e018d759a2a
|
86
|
"""
|
switches |
0:0e018d759a2a
|
87
|
cur_result = {}
|
switches |
0:0e018d759a2a
|
88
|
cur_result["target_name"] = target_name
|
switches |
0:0e018d759a2a
|
89
|
cur_result["toolchain_name"] = toolchain_name
|
switches |
0:0e018d759a2a
|
90
|
cur_result["id"] = id_name
|
switches |
0:0e018d759a2a
|
91
|
cur_result["description"] = description
|
switches |
0:0e018d759a2a
|
92
|
cur_result["elapsed_time"] = 0
|
switches |
0:0e018d759a2a
|
93
|
cur_result["output"] = ""
|
switches |
0:0e018d759a2a
|
94
|
|
switches |
0:0e018d759a2a
|
95
|
return cur_result
|
switches |
0:0e018d759a2a
|
96
|
|
switches |
0:0e018d759a2a
|
97
|
def add_result_to_report(report, result):
|
switches |
0:0e018d759a2a
|
98
|
"""Add a single result to a report dictionary
|
switches |
0:0e018d759a2a
|
99
|
|
switches |
0:0e018d759a2a
|
100
|
Positional arguments:
|
switches |
0:0e018d759a2a
|
101
|
report - the report to append to
|
switches |
0:0e018d759a2a
|
102
|
result - the result to append
|
switches |
0:0e018d759a2a
|
103
|
"""
|
switches |
0:0e018d759a2a
|
104
|
target = result["target_name"]
|
switches |
0:0e018d759a2a
|
105
|
toolchain = result["toolchain_name"]
|
switches |
0:0e018d759a2a
|
106
|
id_name = result['id']
|
switches |
0:0e018d759a2a
|
107
|
result_wrap = {0: result}
|
switches |
0:0e018d759a2a
|
108
|
report[target][toolchain][id_name].append(result_wrap)
|
switches |
0:0e018d759a2a
|
109
|
|
switches |
0:0e018d759a2a
|
110
|
def get_config(src_paths, target, toolchain_name):
|
switches |
0:0e018d759a2a
|
111
|
"""Get the configuration object for a target-toolchain combination
|
switches |
0:0e018d759a2a
|
112
|
|
switches |
0:0e018d759a2a
|
113
|
Positional arguments:
|
switches |
0:0e018d759a2a
|
114
|
src_paths - paths to scan for the configuration files
|
switches |
0:0e018d759a2a
|
115
|
target - the device we are building for
|
switches |
0:0e018d759a2a
|
116
|
toolchain_name - the string that identifies the build tools
|
switches |
0:0e018d759a2a
|
117
|
"""
|
switches |
0:0e018d759a2a
|
118
|
# Convert src_paths to a list if needed
|
switches |
0:0e018d759a2a
|
119
|
if type(src_paths) != ListType:
|
switches |
0:0e018d759a2a
|
120
|
src_paths = [src_paths]
|
switches |
0:0e018d759a2a
|
121
|
|
switches |
0:0e018d759a2a
|
122
|
# Pass all params to the unified prepare_resources()
|
switches |
0:0e018d759a2a
|
123
|
toolchain = prepare_toolchain(src_paths, target, toolchain_name)
|
switches |
0:0e018d759a2a
|
124
|
|
switches |
0:0e018d759a2a
|
125
|
# Scan src_path for config files
|
switches |
0:0e018d759a2a
|
126
|
resources = toolchain.scan_resources(src_paths[0])
|
switches |
0:0e018d759a2a
|
127
|
for path in src_paths[1:]:
|
switches |
0:0e018d759a2a
|
128
|
resources.add(toolchain.scan_resources(path))
|
switches |
0:0e018d759a2a
|
129
|
|
switches |
0:0e018d759a2a
|
130
|
# Update configuration files until added features creates no changes
|
switches |
0:0e018d759a2a
|
131
|
prev_features = set()
|
switches |
0:0e018d759a2a
|
132
|
while True:
|
switches |
0:0e018d759a2a
|
133
|
# Update the configuration with any .json files found while scanning
|
switches |
0:0e018d759a2a
|
134
|
toolchain.config.add_config_files(resources.json_files)
|
switches |
0:0e018d759a2a
|
135
|
|
switches |
0:0e018d759a2a
|
136
|
# Add features while we find new ones
|
switches |
0:0e018d759a2a
|
137
|
features = toolchain.config.get_features()
|
switches |
0:0e018d759a2a
|
138
|
if features == prev_features:
|
switches |
0:0e018d759a2a
|
139
|
break
|
switches |
0:0e018d759a2a
|
140
|
|
switches |
0:0e018d759a2a
|
141
|
for feature in features:
|
switches |
0:0e018d759a2a
|
142
|
if feature in resources.features:
|
switches |
0:0e018d759a2a
|
143
|
resources += resources.features[feature]
|
switches |
0:0e018d759a2a
|
144
|
|
switches |
0:0e018d759a2a
|
145
|
prev_features = features
|
switches |
0:0e018d759a2a
|
146
|
toolchain.config.validate_config()
|
switches |
0:0e018d759a2a
|
147
|
|
switches |
0:0e018d759a2a
|
148
|
cfg, macros = toolchain.config.get_config_data()
|
switches |
0:0e018d759a2a
|
149
|
features = toolchain.config.get_features()
|
switches |
0:0e018d759a2a
|
150
|
return cfg, macros, features
|
switches |
0:0e018d759a2a
|
151
|
|
switches |
0:0e018d759a2a
|
152
|
def is_official_target(target_name, version):
|
switches |
0:0e018d759a2a
|
153
|
""" Returns True, None if a target is part of the official release for the
|
switches |
0:0e018d759a2a
|
154
|
given version. Return False, 'reason' if a target is not part of the
|
switches |
0:0e018d759a2a
|
155
|
official release for the given version.
|
switches |
0:0e018d759a2a
|
156
|
|
switches |
0:0e018d759a2a
|
157
|
Positional arguments:
|
switches |
0:0e018d759a2a
|
158
|
target_name - Name if the target (ex. 'K64F')
|
switches |
0:0e018d759a2a
|
159
|
version - The release version string. Should be a string contained within
|
switches |
0:0e018d759a2a
|
160
|
RELEASE_VERSIONS
|
switches |
0:0e018d759a2a
|
161
|
"""
|
switches |
0:0e018d759a2a
|
162
|
|
switches |
0:0e018d759a2a
|
163
|
result = True
|
switches |
0:0e018d759a2a
|
164
|
reason = None
|
switches |
0:0e018d759a2a
|
165
|
target = TARGET_MAP[target_name]
|
switches |
0:0e018d759a2a
|
166
|
|
switches |
0:0e018d759a2a
|
167
|
if hasattr(target, 'release_versions') \
|
switches |
0:0e018d759a2a
|
168
|
and version in target.release_versions:
|
switches |
0:0e018d759a2a
|
169
|
if version == '2':
|
switches |
0:0e018d759a2a
|
170
|
# For version 2, either ARM or uARM toolchain support is required
|
switches |
0:0e018d759a2a
|
171
|
required_toolchains = set(['ARM', 'uARM'])
|
switches |
0:0e018d759a2a
|
172
|
|
switches |
0:0e018d759a2a
|
173
|
if not len(required_toolchains.intersection(
|
switches |
0:0e018d759a2a
|
174
|
set(target.supported_toolchains))) > 0:
|
switches |
0:0e018d759a2a
|
175
|
result = False
|
switches |
0:0e018d759a2a
|
176
|
reason = ("Target '%s' must support " % target.name) + \
|
switches |
0:0e018d759a2a
|
177
|
("one of the folowing toolchains to be included in the") + \
|
switches |
0:0e018d759a2a
|
178
|
((" mbed 2.0 official release: %s" + linesep) %
|
switches |
0:0e018d759a2a
|
179
|
", ".join(required_toolchains)) + \
|
switches |
0:0e018d759a2a
|
180
|
("Currently it is only configured to support the ") + \
|
switches |
0:0e018d759a2a
|
181
|
("following toolchains: %s" %
|
switches |
0:0e018d759a2a
|
182
|
", ".join(target.supported_toolchains))
|
switches |
0:0e018d759a2a
|
183
|
|
switches |
0:0e018d759a2a
|
184
|
elif version == '5':
|
switches |
0:0e018d759a2a
|
185
|
# For version 5, ARM, GCC_ARM, and IAR toolchain support is required
|
switches |
0:0e018d759a2a
|
186
|
required_toolchains = set(['ARM', 'GCC_ARM', 'IAR'])
|
switches |
0:0e018d759a2a
|
187
|
required_toolchains_sorted = list(required_toolchains)
|
switches |
0:0e018d759a2a
|
188
|
required_toolchains_sorted.sort()
|
switches |
0:0e018d759a2a
|
189
|
supported_toolchains = set(target.supported_toolchains)
|
switches |
0:0e018d759a2a
|
190
|
supported_toolchains_sorted = list(supported_toolchains)
|
switches |
0:0e018d759a2a
|
191
|
supported_toolchains_sorted.sort()
|
switches |
0:0e018d759a2a
|
192
|
|
switches |
0:0e018d759a2a
|
193
|
if not required_toolchains.issubset(supported_toolchains):
|
switches |
0:0e018d759a2a
|
194
|
result = False
|
switches |
0:0e018d759a2a
|
195
|
reason = ("Target '%s' must support " % target.name) + \
|
switches |
0:0e018d759a2a
|
196
|
("ALL of the folowing toolchains to be included in the") + \
|
switches |
0:0e018d759a2a
|
197
|
((" mbed OS 5.0 official release: %s" + linesep) %
|
switches |
0:0e018d759a2a
|
198
|
", ".join(required_toolchains_sorted)) + \
|
switches |
0:0e018d759a2a
|
199
|
("Currently it is only configured to support the ") + \
|
switches |
0:0e018d759a2a
|
200
|
("following toolchains: %s" %
|
switches |
0:0e018d759a2a
|
201
|
", ".join(supported_toolchains_sorted))
|
switches |
0:0e018d759a2a
|
202
|
|
switches |
0:0e018d759a2a
|
203
|
elif not target.default_lib == 'std':
|
switches |
0:0e018d759a2a
|
204
|
result = False
|
switches |
0:0e018d759a2a
|
205
|
reason = ("Target '%s' must set the " % target.name) + \
|
switches |
0:0e018d759a2a
|
206
|
("'default_lib' to 'std' to be included in the ") + \
|
switches |
0:0e018d759a2a
|
207
|
("mbed OS 5.0 official release." + linesep) + \
|
switches |
0:0e018d759a2a
|
208
|
("Currently it is set to '%s'" % target.default_lib)
|
switches |
0:0e018d759a2a
|
209
|
|
switches |
0:0e018d759a2a
|
210
|
else:
|
switches |
0:0e018d759a2a
|
211
|
result = False
|
switches |
0:0e018d759a2a
|
212
|
reason = ("Target '%s' has set an invalid release version of '%s'" %
|
switches |
0:0e018d759a2a
|
213
|
version) + \
|
switches |
0:0e018d759a2a
|
214
|
("Please choose from the following release versions: %s" %
|
switches |
0:0e018d759a2a
|
215
|
', '.join(RELEASE_VERSIONS))
|
switches |
0:0e018d759a2a
|
216
|
|
switches |
0:0e018d759a2a
|
217
|
else:
|
switches |
0:0e018d759a2a
|
218
|
result = False
|
switches |
0:0e018d759a2a
|
219
|
if not hasattr(target, 'release_versions'):
|
switches |
0:0e018d759a2a
|
220
|
reason = "Target '%s' " % target.name
|
switches |
0:0e018d759a2a
|
221
|
reason += "does not have the 'release_versions' key set"
|
switches |
0:0e018d759a2a
|
222
|
elif not version in target.release_versions:
|
switches |
0:0e018d759a2a
|
223
|
reason = "Target '%s' does not contain the version '%s' " % \
|
switches |
0:0e018d759a2a
|
224
|
(target.name, version)
|
switches |
0:0e018d759a2a
|
225
|
reason += "in its 'release_versions' key"
|
switches |
0:0e018d759a2a
|
226
|
|
switches |
0:0e018d759a2a
|
227
|
return result, reason
|
switches |
0:0e018d759a2a
|
228
|
|
switches |
0:0e018d759a2a
|
229
|
def transform_release_toolchains(toolchains, version):
|
switches |
0:0e018d759a2a
|
230
|
""" Given a list of toolchains and a release version, return a list of
|
switches |
0:0e018d759a2a
|
231
|
only the supported toolchains for that release
|
switches |
0:0e018d759a2a
|
232
|
|
switches |
0:0e018d759a2a
|
233
|
Positional arguments:
|
switches |
0:0e018d759a2a
|
234
|
toolchains - The list of toolchains
|
switches |
0:0e018d759a2a
|
235
|
version - The release version string. Should be a string contained within
|
switches |
0:0e018d759a2a
|
236
|
RELEASE_VERSIONS
|
switches |
0:0e018d759a2a
|
237
|
"""
|
switches |
0:0e018d759a2a
|
238
|
if version == '5':
|
switches |
0:0e018d759a2a
|
239
|
return ['ARM', 'GCC_ARM', 'IAR']
|
switches |
0:0e018d759a2a
|
240
|
else:
|
switches |
0:0e018d759a2a
|
241
|
return toolchains
|
switches |
0:0e018d759a2a
|
242
|
|
switches |
0:0e018d759a2a
|
243
|
|
switches |
0:0e018d759a2a
|
244
|
def get_mbed_official_release(version):
|
switches |
0:0e018d759a2a
|
245
|
""" Given a release version string, return a tuple that contains a target
|
switches |
0:0e018d759a2a
|
246
|
and the supported toolchains for that release.
|
switches |
0:0e018d759a2a
|
247
|
Ex. Given '2', return (('LPC1768', ('ARM', 'GCC_ARM')),
|
switches |
0:0e018d759a2a
|
248
|
('K64F', ('ARM', 'GCC_ARM')), ...)
|
switches |
0:0e018d759a2a
|
249
|
|
switches |
0:0e018d759a2a
|
250
|
Positional arguments:
|
switches |
0:0e018d759a2a
|
251
|
version - The version string. Should be a string contained within
|
switches |
0:0e018d759a2a
|
252
|
RELEASE_VERSIONS
|
switches |
0:0e018d759a2a
|
253
|
"""
|
switches |
0:0e018d759a2a
|
254
|
|
switches |
0:0e018d759a2a
|
255
|
mbed_official_release = (
|
switches |
0:0e018d759a2a
|
256
|
tuple(
|
switches |
0:0e018d759a2a
|
257
|
tuple(
|
switches |
0:0e018d759a2a
|
258
|
[
|
switches |
0:0e018d759a2a
|
259
|
TARGET_MAP[target].name,
|
switches |
0:0e018d759a2a
|
260
|
tuple(transform_release_toolchains(
|
switches |
0:0e018d759a2a
|
261
|
TARGET_MAP[target].supported_toolchains, version))
|
switches |
0:0e018d759a2a
|
262
|
]
|
switches |
0:0e018d759a2a
|
263
|
) for target in TARGET_NAMES \
|
switches |
0:0e018d759a2a
|
264
|
if (hasattr(TARGET_MAP[target], 'release_versions')
|
switches |
0:0e018d759a2a
|
265
|
and version in TARGET_MAP[target].release_versions)
|
switches |
0:0e018d759a2a
|
266
|
)
|
switches |
0:0e018d759a2a
|
267
|
)
|
switches |
0:0e018d759a2a
|
268
|
|
switches |
0:0e018d759a2a
|
269
|
for target in mbed_official_release:
|
switches |
0:0e018d759a2a
|
270
|
is_official, reason = is_official_target(target[0], version)
|
switches |
0:0e018d759a2a
|
271
|
|
switches |
0:0e018d759a2a
|
272
|
if not is_official:
|
switches |
0:0e018d759a2a
|
273
|
raise InvalidReleaseTargetException(reason)
|
switches |
0:0e018d759a2a
|
274
|
|
switches |
0:0e018d759a2a
|
275
|
return mbed_official_release
|
switches |
0:0e018d759a2a
|
276
|
|
switches |
0:0e018d759a2a
|
277
|
|
switches |
0:0e018d759a2a
|
278
|
def prepare_toolchain(src_paths, target, toolchain_name,
|
switches |
0:0e018d759a2a
|
279
|
macros=None, clean=False, jobs=1,
|
switches |
0:0e018d759a2a
|
280
|
notify=None, silent=False, verbose=False,
|
switches |
0:0e018d759a2a
|
281
|
extra_verbose=False, config=None,
|
switches |
0:0e018d759a2a
|
282
|
app_config=None, build_profile=None):
|
switches |
0:0e018d759a2a
|
283
|
""" Prepares resource related objects - toolchain, target, config
|
switches |
0:0e018d759a2a
|
284
|
|
switches |
0:0e018d759a2a
|
285
|
Positional arguments:
|
switches |
0:0e018d759a2a
|
286
|
src_paths - the paths to source directories
|
switches |
0:0e018d759a2a
|
287
|
target - ['LPC1768', 'LPC11U24', 'LPC2368', etc.]
|
switches |
0:0e018d759a2a
|
288
|
toolchain_name - ['ARM', 'uARM', 'GCC_ARM', 'GCC_CR']
|
switches |
0:0e018d759a2a
|
289
|
|
switches |
0:0e018d759a2a
|
290
|
Keyword arguments:
|
switches |
0:0e018d759a2a
|
291
|
macros - additional macros
|
switches |
0:0e018d759a2a
|
292
|
clean - Rebuild everything if True
|
switches |
0:0e018d759a2a
|
293
|
jobs - how many compilers we can run at once
|
switches |
0:0e018d759a2a
|
294
|
notify - Notify function for logs
|
switches |
0:0e018d759a2a
|
295
|
silent - suppress printing of progress indicators
|
switches |
0:0e018d759a2a
|
296
|
verbose - Write the actual tools command lines used if True
|
switches |
0:0e018d759a2a
|
297
|
extra_verbose - even more output!
|
switches |
0:0e018d759a2a
|
298
|
config - a Config object to use instead of creating one
|
switches |
0:0e018d759a2a
|
299
|
app_config - location of a chosen mbed_app.json file
|
switches |
0:0e018d759a2a
|
300
|
build_profile - a dict of flags that will be passed to the compiler
|
switches |
0:0e018d759a2a
|
301
|
"""
|
switches |
0:0e018d759a2a
|
302
|
|
switches |
0:0e018d759a2a
|
303
|
# We need to remove all paths which are repeated to avoid
|
switches |
0:0e018d759a2a
|
304
|
# multiple compilations and linking with the same objects
|
switches |
0:0e018d759a2a
|
305
|
src_paths = [src_paths[0]] + list(set(src_paths[1:]))
|
switches |
0:0e018d759a2a
|
306
|
|
switches |
0:0e018d759a2a
|
307
|
# If the configuration object was not yet created, create it now
|
switches |
0:0e018d759a2a
|
308
|
config = config or Config(target, src_paths, app_config=app_config)
|
switches |
0:0e018d759a2a
|
309
|
target = config.target
|
switches |
0:0e018d759a2a
|
310
|
|
switches |
0:0e018d759a2a
|
311
|
# Toolchain instance
|
switches |
0:0e018d759a2a
|
312
|
try:
|
switches |
0:0e018d759a2a
|
313
|
toolchain = TOOLCHAIN_CLASSES[toolchain_name](
|
switches |
0:0e018d759a2a
|
314
|
target, notify, macros, silent,
|
switches |
0:0e018d759a2a
|
315
|
extra_verbose=extra_verbose, build_profile=build_profile)
|
switches |
0:0e018d759a2a
|
316
|
except KeyError:
|
switches |
0:0e018d759a2a
|
317
|
raise KeyError("Toolchain %s not supported" % toolchain_name)
|
switches |
0:0e018d759a2a
|
318
|
|
switches |
0:0e018d759a2a
|
319
|
toolchain.config = config
|
switches |
0:0e018d759a2a
|
320
|
toolchain.jobs = jobs
|
switches |
0:0e018d759a2a
|
321
|
toolchain.build_all = clean
|
switches |
0:0e018d759a2a
|
322
|
toolchain.VERBOSE = verbose
|
switches |
0:0e018d759a2a
|
323
|
|
switches |
0:0e018d759a2a
|
324
|
return toolchain
|
switches |
0:0e018d759a2a
|
325
|
|
switches |
0:0e018d759a2a
|
326
|
def scan_resources(src_paths, toolchain, dependencies_paths=None,
|
switches |
0:0e018d759a2a
|
327
|
inc_dirs=None, base_path=None):
|
switches |
0:0e018d759a2a
|
328
|
""" Scan resources using initialized toolcain
|
switches |
0:0e018d759a2a
|
329
|
|
switches |
0:0e018d759a2a
|
330
|
Positional arguments
|
switches |
0:0e018d759a2a
|
331
|
src_paths - the paths to source directories
|
switches |
0:0e018d759a2a
|
332
|
toolchain - valid toolchain object
|
switches |
0:0e018d759a2a
|
333
|
dependencies_paths - dependency paths that we should scan for include dirs
|
switches |
0:0e018d759a2a
|
334
|
inc_dirs - additional include directories which should be added to
|
switches |
0:0e018d759a2a
|
335
|
the scanner resources
|
switches |
0:0e018d759a2a
|
336
|
"""
|
switches |
0:0e018d759a2a
|
337
|
|
switches |
0:0e018d759a2a
|
338
|
# Scan src_path
|
switches |
0:0e018d759a2a
|
339
|
resources = toolchain.scan_resources(src_paths[0], base_path=base_path)
|
switches |
0:0e018d759a2a
|
340
|
for path in src_paths[1:]:
|
switches |
0:0e018d759a2a
|
341
|
resources.add(toolchain.scan_resources(path, base_path=base_path))
|
switches |
0:0e018d759a2a
|
342
|
|
switches |
0:0e018d759a2a
|
343
|
# Scan dependency paths for include dirs
|
switches |
0:0e018d759a2a
|
344
|
if dependencies_paths is not None:
|
switches |
0:0e018d759a2a
|
345
|
for path in dependencies_paths:
|
switches |
0:0e018d759a2a
|
346
|
lib_resources = toolchain.scan_resources(path)
|
switches |
0:0e018d759a2a
|
347
|
resources.inc_dirs.extend(lib_resources.inc_dirs)
|
switches |
0:0e018d759a2a
|
348
|
|
switches |
0:0e018d759a2a
|
349
|
# Add additional include directories if passed
|
switches |
0:0e018d759a2a
|
350
|
if inc_dirs:
|
switches |
0:0e018d759a2a
|
351
|
if type(inc_dirs) == ListType:
|
switches |
0:0e018d759a2a
|
352
|
resources.inc_dirs.extend(inc_dirs)
|
switches |
0:0e018d759a2a
|
353
|
else:
|
switches |
0:0e018d759a2a
|
354
|
resources.inc_dirs.append(inc_dirs)
|
switches |
0:0e018d759a2a
|
355
|
|
switches |
0:0e018d759a2a
|
356
|
# Load resources into the config system which might expand/modify resources
|
switches |
0:0e018d759a2a
|
357
|
# based on config data
|
switches |
0:0e018d759a2a
|
358
|
resources = toolchain.config.load_resources(resources)
|
switches |
0:0e018d759a2a
|
359
|
|
switches |
0:0e018d759a2a
|
360
|
# Set the toolchain's configuration data
|
switches |
0:0e018d759a2a
|
361
|
toolchain.set_config_data(toolchain.config.get_config_data())
|
switches |
0:0e018d759a2a
|
362
|
|
switches |
0:0e018d759a2a
|
363
|
return resources
|
switches |
0:0e018d759a2a
|
364
|
|
switches |
0:0e018d759a2a
|
365
|
def build_project(src_paths, build_path, target, toolchain_name,
|
switches |
0:0e018d759a2a
|
366
|
libraries_paths=None, linker_script=None,
|
switches |
0:0e018d759a2a
|
367
|
clean=False, notify=None, verbose=False, name=None,
|
switches |
0:0e018d759a2a
|
368
|
macros=None, inc_dirs=None, jobs=1, silent=False,
|
switches |
0:0e018d759a2a
|
369
|
report=None, properties=None, project_id=None,
|
switches |
0:0e018d759a2a
|
370
|
project_description=None, extra_verbose=False, config=None,
|
switches |
0:0e018d759a2a
|
371
|
app_config=None, build_profile=None):
|
switches |
0:0e018d759a2a
|
372
|
""" Build a project. A project may be a test or a user program.
|
switches |
0:0e018d759a2a
|
373
|
|
switches |
0:0e018d759a2a
|
374
|
Positional arguments:
|
switches |
0:0e018d759a2a
|
375
|
src_paths - a path or list of paths that contain all files needed to build
|
switches |
0:0e018d759a2a
|
376
|
the project
|
switches |
0:0e018d759a2a
|
377
|
build_path - the directory where all of the object files will be placed
|
switches |
0:0e018d759a2a
|
378
|
target - the MCU or board that the project will compile for
|
switches |
0:0e018d759a2a
|
379
|
toolchain_name - the name of the build tools
|
switches |
0:0e018d759a2a
|
380
|
|
switches |
0:0e018d759a2a
|
381
|
Keyword arguments:
|
switches |
0:0e018d759a2a
|
382
|
libraries_paths - The location of libraries to include when linking
|
switches |
0:0e018d759a2a
|
383
|
linker_script - the file that drives the linker to do it's job
|
switches |
0:0e018d759a2a
|
384
|
clean - Rebuild everything if True
|
switches |
0:0e018d759a2a
|
385
|
notify - Notify function for logs
|
switches |
0:0e018d759a2a
|
386
|
verbose - Write the actual tools command lines used if True
|
switches |
0:0e018d759a2a
|
387
|
name - the name of the project
|
switches |
0:0e018d759a2a
|
388
|
macros - additional macros
|
switches |
0:0e018d759a2a
|
389
|
inc_dirs - additional directories where include files may be found
|
switches |
0:0e018d759a2a
|
390
|
jobs - how many compilers we can run at once
|
switches |
0:0e018d759a2a
|
391
|
silent - suppress printing of progress indicators
|
switches |
0:0e018d759a2a
|
392
|
report - a dict where a result may be appended
|
switches |
0:0e018d759a2a
|
393
|
properties - UUUUHHHHH beats me
|
switches |
0:0e018d759a2a
|
394
|
project_id - the name put in the report
|
switches |
0:0e018d759a2a
|
395
|
project_description - the human-readable version of what this thing does
|
switches |
0:0e018d759a2a
|
396
|
extra_verbose - even more output!
|
switches |
0:0e018d759a2a
|
397
|
config - a Config object to use instead of creating one
|
switches |
0:0e018d759a2a
|
398
|
app_config - location of a chosen mbed_app.json file
|
switches |
0:0e018d759a2a
|
399
|
build_profile - a dict of flags that will be passed to the compiler
|
switches |
0:0e018d759a2a
|
400
|
"""
|
switches |
0:0e018d759a2a
|
401
|
|
switches |
0:0e018d759a2a
|
402
|
# Convert src_path to a list if needed
|
switches |
0:0e018d759a2a
|
403
|
if type(src_paths) != ListType:
|
switches |
0:0e018d759a2a
|
404
|
src_paths = [src_paths]
|
switches |
0:0e018d759a2a
|
405
|
# Extend src_paths wiht libraries_paths
|
switches |
0:0e018d759a2a
|
406
|
if libraries_paths is not None:
|
switches |
0:0e018d759a2a
|
407
|
src_paths.extend(libraries_paths)
|
switches |
0:0e018d759a2a
|
408
|
inc_dirs.extend(map(dirname, libraries_paths))
|
switches |
0:0e018d759a2a
|
409
|
|
switches |
0:0e018d759a2a
|
410
|
# Build Directory
|
switches |
0:0e018d759a2a
|
411
|
if clean and exists(build_path):
|
switches |
0:0e018d759a2a
|
412
|
rmtree(build_path)
|
switches |
0:0e018d759a2a
|
413
|
mkdir(build_path)
|
switches |
0:0e018d759a2a
|
414
|
|
switches |
0:0e018d759a2a
|
415
|
# Pass all params to the unified prepare_toolchain()
|
switches |
0:0e018d759a2a
|
416
|
toolchain = prepare_toolchain(
|
switches |
0:0e018d759a2a
|
417
|
src_paths, target, toolchain_name, macros=macros, clean=clean,
|
switches |
0:0e018d759a2a
|
418
|
jobs=jobs, notify=notify, silent=silent, verbose=verbose,
|
switches |
0:0e018d759a2a
|
419
|
extra_verbose=extra_verbose, config=config, app_config=app_config,
|
switches |
0:0e018d759a2a
|
420
|
build_profile=build_profile)
|
switches |
0:0e018d759a2a
|
421
|
|
switches |
0:0e018d759a2a
|
422
|
# The first path will give the name to the library
|
switches |
0:0e018d759a2a
|
423
|
if name is None:
|
switches |
0:0e018d759a2a
|
424
|
name = basename(normpath(abspath(src_paths[0])))
|
switches |
0:0e018d759a2a
|
425
|
toolchain.info("Building project %s (%s, %s)" %
|
switches |
0:0e018d759a2a
|
426
|
(name, toolchain.target.name, toolchain_name))
|
switches |
0:0e018d759a2a
|
427
|
|
switches |
0:0e018d759a2a
|
428
|
# Initialize reporting
|
switches |
0:0e018d759a2a
|
429
|
if report != None:
|
switches |
0:0e018d759a2a
|
430
|
start = time()
|
switches |
0:0e018d759a2a
|
431
|
# If project_id is specified, use that over the default name
|
switches |
0:0e018d759a2a
|
432
|
id_name = project_id.upper() if project_id else name.upper()
|
switches |
0:0e018d759a2a
|
433
|
description = project_description if project_description else name
|
switches |
0:0e018d759a2a
|
434
|
vendor_label = toolchain.target.extra_labels[0]
|
switches |
0:0e018d759a2a
|
435
|
prep_report(report, toolchain.target.name, toolchain_name, id_name)
|
switches |
0:0e018d759a2a
|
436
|
cur_result = create_result(toolchain.target.name, toolchain_name,
|
switches |
0:0e018d759a2a
|
437
|
id_name, description)
|
switches |
0:0e018d759a2a
|
438
|
if properties != None:
|
switches |
0:0e018d759a2a
|
439
|
prep_properties(properties, toolchain.target.name, toolchain_name,
|
switches |
0:0e018d759a2a
|
440
|
vendor_label)
|
switches |
0:0e018d759a2a
|
441
|
|
switches |
0:0e018d759a2a
|
442
|
try:
|
switches |
0:0e018d759a2a
|
443
|
# Call unified scan_resources
|
switches |
0:0e018d759a2a
|
444
|
resources = scan_resources(src_paths, toolchain, inc_dirs=inc_dirs)
|
switches |
0:0e018d759a2a
|
445
|
|
switches |
0:0e018d759a2a
|
446
|
# Change linker script if specified
|
switches |
0:0e018d759a2a
|
447
|
if linker_script is not None:
|
switches |
0:0e018d759a2a
|
448
|
resources.linker_script = linker_script
|
switches |
0:0e018d759a2a
|
449
|
|
switches |
0:0e018d759a2a
|
450
|
# Compile Sources
|
switches |
0:0e018d759a2a
|
451
|
objects = toolchain.compile_sources(resources, build_path,
|
switches |
0:0e018d759a2a
|
452
|
resources.inc_dirs)
|
switches |
0:0e018d759a2a
|
453
|
resources.objects.extend(objects)
|
switches |
0:0e018d759a2a
|
454
|
|
switches |
0:0e018d759a2a
|
455
|
# Link Program
|
switches |
0:0e018d759a2a
|
456
|
res, _ = toolchain.link_program(resources, build_path, name)
|
switches |
0:0e018d759a2a
|
457
|
|
switches |
0:0e018d759a2a
|
458
|
memap_instance = getattr(toolchain, 'memap_instance', None)
|
switches |
0:0e018d759a2a
|
459
|
memap_table = ''
|
switches |
0:0e018d759a2a
|
460
|
if memap_instance:
|
switches |
0:0e018d759a2a
|
461
|
# Write output to stdout in text (pretty table) format
|
switches |
0:0e018d759a2a
|
462
|
memap_table = memap_instance.generate_output('table')
|
switches |
0:0e018d759a2a
|
463
|
|
switches |
0:0e018d759a2a
|
464
|
if not silent:
|
switches |
0:0e018d759a2a
|
465
|
print memap_table
|
switches |
0:0e018d759a2a
|
466
|
|
switches |
0:0e018d759a2a
|
467
|
# Write output to file in JSON format
|
switches |
0:0e018d759a2a
|
468
|
map_out = join(build_path, name + "_map.json")
|
switches |
0:0e018d759a2a
|
469
|
memap_instance.generate_output('json', map_out)
|
switches |
0:0e018d759a2a
|
470
|
|
switches |
0:0e018d759a2a
|
471
|
# Write output to file in CSV format for the CI
|
switches |
0:0e018d759a2a
|
472
|
map_csv = join(build_path, name + "_map.csv")
|
switches |
0:0e018d759a2a
|
473
|
memap_instance.generate_output('csv-ci', map_csv)
|
switches |
0:0e018d759a2a
|
474
|
|
switches |
0:0e018d759a2a
|
475
|
resources.detect_duplicates(toolchain)
|
switches |
0:0e018d759a2a
|
476
|
|
switches |
0:0e018d759a2a
|
477
|
if report != None:
|
switches |
0:0e018d759a2a
|
478
|
end = time()
|
switches |
0:0e018d759a2a
|
479
|
cur_result["elapsed_time"] = end - start
|
switches |
0:0e018d759a2a
|
480
|
cur_result["output"] = toolchain.get_output() + memap_table
|
switches |
0:0e018d759a2a
|
481
|
cur_result["result"] = "OK"
|
switches |
0:0e018d759a2a
|
482
|
cur_result["memory_usage"] = toolchain.map_outputs
|
switches |
0:0e018d759a2a
|
483
|
|
switches |
0:0e018d759a2a
|
484
|
add_result_to_report(report, cur_result)
|
switches |
0:0e018d759a2a
|
485
|
|
switches |
0:0e018d759a2a
|
486
|
return res
|
switches |
0:0e018d759a2a
|
487
|
|
switches |
0:0e018d759a2a
|
488
|
except Exception as exc:
|
switches |
0:0e018d759a2a
|
489
|
if report != None:
|
switches |
0:0e018d759a2a
|
490
|
end = time()
|
switches |
0:0e018d759a2a
|
491
|
|
switches |
0:0e018d759a2a
|
492
|
if isinstance(exc, NotSupportedException):
|
switches |
0:0e018d759a2a
|
493
|
cur_result["result"] = "NOT_SUPPORTED"
|
switches |
0:0e018d759a2a
|
494
|
else:
|
switches |
0:0e018d759a2a
|
495
|
cur_result["result"] = "FAIL"
|
switches |
0:0e018d759a2a
|
496
|
|
switches |
0:0e018d759a2a
|
497
|
cur_result["elapsed_time"] = end - start
|
switches |
0:0e018d759a2a
|
498
|
|
switches |
0:0e018d759a2a
|
499
|
toolchain_output = toolchain.get_output()
|
switches |
0:0e018d759a2a
|
500
|
if toolchain_output:
|
switches |
0:0e018d759a2a
|
501
|
cur_result["output"] += toolchain_output
|
switches |
0:0e018d759a2a
|
502
|
|
switches |
0:0e018d759a2a
|
503
|
add_result_to_report(report, cur_result)
|
switches |
0:0e018d759a2a
|
504
|
|
switches |
0:0e018d759a2a
|
505
|
# Let Exception propagate
|
switches |
0:0e018d759a2a
|
506
|
raise
|
switches |
0:0e018d759a2a
|
507
|
|
switches |
0:0e018d759a2a
|
508
|
def build_library(src_paths, build_path, target, toolchain_name,
|
switches |
0:0e018d759a2a
|
509
|
dependencies_paths=None, name=None, clean=False,
|
switches |
0:0e018d759a2a
|
510
|
archive=True, notify=None, verbose=False, macros=None,
|
switches |
0:0e018d759a2a
|
511
|
inc_dirs=None, jobs=1, silent=False, report=None,
|
switches |
0:0e018d759a2a
|
512
|
properties=None, extra_verbose=False, project_id=None,
|
switches |
0:0e018d759a2a
|
513
|
remove_config_header_file=False, app_config=None,
|
switches |
0:0e018d759a2a
|
514
|
build_profile=None):
|
switches |
0:0e018d759a2a
|
515
|
""" Build a library
|
switches |
0:0e018d759a2a
|
516
|
|
switches |
0:0e018d759a2a
|
517
|
Positional arguments:
|
switches |
0:0e018d759a2a
|
518
|
src_paths - a path or list of paths that contain all files needed to build
|
switches |
0:0e018d759a2a
|
519
|
the library
|
switches |
0:0e018d759a2a
|
520
|
build_path - the directory where all of the object files will be placed
|
switches |
0:0e018d759a2a
|
521
|
target - the MCU or board that the project will compile for
|
switches |
0:0e018d759a2a
|
522
|
toolchain_name - the name of the build tools
|
switches |
0:0e018d759a2a
|
523
|
|
switches |
0:0e018d759a2a
|
524
|
Keyword arguments:
|
switches |
0:0e018d759a2a
|
525
|
dependencies_paths - The location of libraries to include when linking
|
switches |
0:0e018d759a2a
|
526
|
name - the name of the library
|
switches |
0:0e018d759a2a
|
527
|
clean - Rebuild everything if True
|
switches |
0:0e018d759a2a
|
528
|
archive - whether the library will create an archive file
|
switches |
0:0e018d759a2a
|
529
|
notify - Notify function for logs
|
switches |
0:0e018d759a2a
|
530
|
verbose - Write the actual tools command lines used if True
|
switches |
0:0e018d759a2a
|
531
|
macros - additional macros
|
switches |
0:0e018d759a2a
|
532
|
inc_dirs - additional directories where include files may be found
|
switches |
0:0e018d759a2a
|
533
|
jobs - how many compilers we can run at once
|
switches |
0:0e018d759a2a
|
534
|
silent - suppress printing of progress indicators
|
switches |
0:0e018d759a2a
|
535
|
report - a dict where a result may be appended
|
switches |
0:0e018d759a2a
|
536
|
properties - UUUUHHHHH beats me
|
switches |
0:0e018d759a2a
|
537
|
extra_verbose - even more output!
|
switches |
0:0e018d759a2a
|
538
|
project_id - the name that goes in the report
|
switches |
0:0e018d759a2a
|
539
|
remove_config_header_file - delete config header file when done building
|
switches |
0:0e018d759a2a
|
540
|
app_config - location of a chosen mbed_app.json file
|
switches |
0:0e018d759a2a
|
541
|
build_profile - a dict of flags that will be passed to the compiler
|
switches |
0:0e018d759a2a
|
542
|
"""
|
switches |
0:0e018d759a2a
|
543
|
|
switches |
0:0e018d759a2a
|
544
|
# Convert src_path to a list if needed
|
switches |
0:0e018d759a2a
|
545
|
if type(src_paths) != ListType:
|
switches |
0:0e018d759a2a
|
546
|
src_paths = [src_paths]
|
switches |
0:0e018d759a2a
|
547
|
|
switches |
0:0e018d759a2a
|
548
|
# Build path
|
switches |
0:0e018d759a2a
|
549
|
if archive:
|
switches |
0:0e018d759a2a
|
550
|
# Use temp path when building archive
|
switches |
0:0e018d759a2a
|
551
|
tmp_path = join(build_path, '.temp')
|
switches |
0:0e018d759a2a
|
552
|
mkdir(tmp_path)
|
switches |
0:0e018d759a2a
|
553
|
else:
|
switches |
0:0e018d759a2a
|
554
|
tmp_path = build_path
|
switches |
0:0e018d759a2a
|
555
|
|
switches |
0:0e018d759a2a
|
556
|
# Clean the build directory
|
switches |
0:0e018d759a2a
|
557
|
if clean and exists(tmp_path):
|
switches |
0:0e018d759a2a
|
558
|
rmtree(tmp_path)
|
switches |
0:0e018d759a2a
|
559
|
mkdir(tmp_path)
|
switches |
0:0e018d759a2a
|
560
|
|
switches |
0:0e018d759a2a
|
561
|
# Pass all params to the unified prepare_toolchain()
|
switches |
0:0e018d759a2a
|
562
|
toolchain = prepare_toolchain(
|
switches |
0:0e018d759a2a
|
563
|
src_paths, target, toolchain_name, macros=macros, clean=clean,
|
switches |
0:0e018d759a2a
|
564
|
jobs=jobs, notify=notify, silent=silent, verbose=verbose,
|
switches |
0:0e018d759a2a
|
565
|
extra_verbose=extra_verbose, app_config=app_config,
|
switches |
0:0e018d759a2a
|
566
|
build_profile=build_profile)
|
switches |
0:0e018d759a2a
|
567
|
|
switches |
0:0e018d759a2a
|
568
|
# The first path will give the name to the library
|
switches |
0:0e018d759a2a
|
569
|
if name is None:
|
switches |
0:0e018d759a2a
|
570
|
name = basename(normpath(abspath(src_paths[0])))
|
switches |
0:0e018d759a2a
|
571
|
toolchain.info("Building library %s (%s, %s)" %
|
switches |
0:0e018d759a2a
|
572
|
(name, toolchain.target.name, toolchain_name))
|
switches |
0:0e018d759a2a
|
573
|
|
switches |
0:0e018d759a2a
|
574
|
# Initialize reporting
|
switches |
0:0e018d759a2a
|
575
|
if report != None:
|
switches |
0:0e018d759a2a
|
576
|
start = time()
|
switches |
0:0e018d759a2a
|
577
|
# If project_id is specified, use that over the default name
|
switches |
0:0e018d759a2a
|
578
|
id_name = project_id.upper() if project_id else name.upper()
|
switches |
0:0e018d759a2a
|
579
|
description = name
|
switches |
0:0e018d759a2a
|
580
|
vendor_label = toolchain.target.extra_labels[0]
|
switches |
0:0e018d759a2a
|
581
|
prep_report(report, toolchain.target.name, toolchain_name, id_name)
|
switches |
0:0e018d759a2a
|
582
|
cur_result = create_result(toolchain.target.name, toolchain_name,
|
switches |
0:0e018d759a2a
|
583
|
id_name, description)
|
switches |
0:0e018d759a2a
|
584
|
if properties != None:
|
switches |
0:0e018d759a2a
|
585
|
prep_properties(properties, toolchain.target.name, toolchain_name,
|
switches |
0:0e018d759a2a
|
586
|
vendor_label)
|
switches |
0:0e018d759a2a
|
587
|
|
switches |
0:0e018d759a2a
|
588
|
for src_path in src_paths:
|
switches |
0:0e018d759a2a
|
589
|
if not exists(src_path):
|
switches |
0:0e018d759a2a
|
590
|
error_msg = "The library source folder does not exist: %s", src_path
|
switches |
0:0e018d759a2a
|
591
|
if report != None:
|
switches |
0:0e018d759a2a
|
592
|
cur_result["output"] = error_msg
|
switches |
0:0e018d759a2a
|
593
|
cur_result["result"] = "FAIL"
|
switches |
0:0e018d759a2a
|
594
|
add_result_to_report(report, cur_result)
|
switches |
0:0e018d759a2a
|
595
|
raise Exception(error_msg)
|
switches |
0:0e018d759a2a
|
596
|
|
switches |
0:0e018d759a2a
|
597
|
try:
|
switches |
0:0e018d759a2a
|
598
|
# Call unified scan_resources
|
switches |
0:0e018d759a2a
|
599
|
resources = scan_resources(src_paths, toolchain,
|
switches |
0:0e018d759a2a
|
600
|
dependencies_paths=dependencies_paths,
|
switches |
0:0e018d759a2a
|
601
|
inc_dirs=inc_dirs)
|
switches |
0:0e018d759a2a
|
602
|
|
switches |
0:0e018d759a2a
|
603
|
|
switches |
0:0e018d759a2a
|
604
|
# Copy headers, objects and static libraries - all files needed for
|
switches |
0:0e018d759a2a
|
605
|
# static lib
|
switches |
0:0e018d759a2a
|
606
|
toolchain.copy_files(resources.headers, build_path, resources=resources)
|
switches |
0:0e018d759a2a
|
607
|
toolchain.copy_files(resources.objects, build_path, resources=resources)
|
switches |
0:0e018d759a2a
|
608
|
toolchain.copy_files(resources.libraries, build_path,
|
switches |
0:0e018d759a2a
|
609
|
resources=resources)
|
switches |
0:0e018d759a2a
|
610
|
toolchain.copy_files(resources.json_files, build_path,
|
switches |
0:0e018d759a2a
|
611
|
resources=resources)
|
switches |
0:0e018d759a2a
|
612
|
if resources.linker_script:
|
switches |
0:0e018d759a2a
|
613
|
toolchain.copy_files(resources.linker_script, build_path,
|
switches |
0:0e018d759a2a
|
614
|
resources=resources)
|
switches |
0:0e018d759a2a
|
615
|
|
switches |
0:0e018d759a2a
|
616
|
if resources.hex_files:
|
switches |
0:0e018d759a2a
|
617
|
toolchain.copy_files(resources.hex_files, build_path,
|
switches |
0:0e018d759a2a
|
618
|
resources=resources)
|
switches |
0:0e018d759a2a
|
619
|
|
switches |
0:0e018d759a2a
|
620
|
# Compile Sources
|
switches |
0:0e018d759a2a
|
621
|
objects = toolchain.compile_sources(resources, abspath(tmp_path),
|
switches |
0:0e018d759a2a
|
622
|
resources.inc_dirs)
|
switches |
0:0e018d759a2a
|
623
|
resources.objects.extend(objects)
|
switches |
0:0e018d759a2a
|
624
|
|
switches |
0:0e018d759a2a
|
625
|
if archive:
|
switches |
0:0e018d759a2a
|
626
|
toolchain.build_library(objects, build_path, name)
|
switches |
0:0e018d759a2a
|
627
|
|
switches |
0:0e018d759a2a
|
628
|
if remove_config_header_file:
|
switches |
0:0e018d759a2a
|
629
|
config_header_path = toolchain.get_config_header()
|
switches |
0:0e018d759a2a
|
630
|
if config_header_path:
|
switches |
0:0e018d759a2a
|
631
|
remove(config_header_path)
|
switches |
0:0e018d759a2a
|
632
|
|
switches |
0:0e018d759a2a
|
633
|
if report != None:
|
switches |
0:0e018d759a2a
|
634
|
end = time()
|
switches |
0:0e018d759a2a
|
635
|
cur_result["elapsed_time"] = end - start
|
switches |
0:0e018d759a2a
|
636
|
cur_result["output"] = toolchain.get_output()
|
switches |
0:0e018d759a2a
|
637
|
cur_result["result"] = "OK"
|
switches |
0:0e018d759a2a
|
638
|
|
switches |
0:0e018d759a2a
|
639
|
|
switches |
0:0e018d759a2a
|
640
|
add_result_to_report(report, cur_result)
|
switches |
0:0e018d759a2a
|
641
|
return True
|
switches |
0:0e018d759a2a
|
642
|
|
switches |
0:0e018d759a2a
|
643
|
except Exception as exc:
|
switches |
0:0e018d759a2a
|
644
|
if report != None:
|
switches |
0:0e018d759a2a
|
645
|
end = time()
|
switches |
0:0e018d759a2a
|
646
|
|
switches |
0:0e018d759a2a
|
647
|
if isinstance(exc, ToolException):
|
switches |
0:0e018d759a2a
|
648
|
cur_result["result"] = "FAIL"
|
switches |
0:0e018d759a2a
|
649
|
elif isinstance(exc, NotSupportedException):
|
switches |
0:0e018d759a2a
|
650
|
cur_result["result"] = "NOT_SUPPORTED"
|
switches |
0:0e018d759a2a
|
651
|
|
switches |
0:0e018d759a2a
|
652
|
cur_result["elapsed_time"] = end - start
|
switches |
0:0e018d759a2a
|
653
|
|
switches |
0:0e018d759a2a
|
654
|
toolchain_output = toolchain.get_output()
|
switches |
0:0e018d759a2a
|
655
|
if toolchain_output:
|
switches |
0:0e018d759a2a
|
656
|
cur_result["output"] += toolchain_output
|
switches |
0:0e018d759a2a
|
657
|
|
switches |
0:0e018d759a2a
|
658
|
add_result_to_report(report, cur_result)
|
switches |
0:0e018d759a2a
|
659
|
|
switches |
0:0e018d759a2a
|
660
|
# Let Exception propagate
|
switches |
0:0e018d759a2a
|
661
|
raise
|
switches |
0:0e018d759a2a
|
662
|
|
switches |
0:0e018d759a2a
|
663
|
######################
|
switches |
0:0e018d759a2a
|
664
|
### Legacy methods ###
|
switches |
0:0e018d759a2a
|
665
|
######################
|
switches |
0:0e018d759a2a
|
666
|
|
switches |
0:0e018d759a2a
|
667
|
def build_lib(lib_id, target, toolchain_name, verbose=False,
|
switches |
0:0e018d759a2a
|
668
|
clean=False, macros=None, notify=None, jobs=1, silent=False,
|
switches |
0:0e018d759a2a
|
669
|
report=None, properties=None, extra_verbose=False,
|
switches |
0:0e018d759a2a
|
670
|
build_profile=None):
|
switches |
0:0e018d759a2a
|
671
|
""" Legacy method for building mbed libraries
|
switches |
0:0e018d759a2a
|
672
|
|
switches |
0:0e018d759a2a
|
673
|
Positional arguments:
|
switches |
0:0e018d759a2a
|
674
|
lib_id - the library's unique identifier
|
switches |
0:0e018d759a2a
|
675
|
target - the MCU or board that the project will compile for
|
switches |
0:0e018d759a2a
|
676
|
toolchain_name - the name of the build tools
|
switches |
0:0e018d759a2a
|
677
|
|
switches |
0:0e018d759a2a
|
678
|
Keyword arguments:
|
switches |
0:0e018d759a2a
|
679
|
clean - Rebuild everything if True
|
switches |
0:0e018d759a2a
|
680
|
verbose - Write the actual tools command lines used if True
|
switches |
0:0e018d759a2a
|
681
|
macros - additional macros
|
switches |
0:0e018d759a2a
|
682
|
notify - Notify function for logs
|
switches |
0:0e018d759a2a
|
683
|
jobs - how many compilers we can run at once
|
switches |
0:0e018d759a2a
|
684
|
silent - suppress printing of progress indicators
|
switches |
0:0e018d759a2a
|
685
|
report - a dict where a result may be appended
|
switches |
0:0e018d759a2a
|
686
|
properties - UUUUHHHHH beats me
|
switches |
0:0e018d759a2a
|
687
|
extra_verbose - even more output!
|
switches |
0:0e018d759a2a
|
688
|
build_profile - a dict of flags that will be passed to the compiler
|
switches |
0:0e018d759a2a
|
689
|
"""
|
switches |
0:0e018d759a2a
|
690
|
lib = Library(lib_id)
|
switches |
0:0e018d759a2a
|
691
|
if not lib.is_supported(target, toolchain_name):
|
switches |
0:0e018d759a2a
|
692
|
print('Library "%s" is not yet supported on target %s with toolchain %s'
|
switches |
0:0e018d759a2a
|
693
|
% (lib_id, target.name, toolchain_name))
|
switches |
0:0e018d759a2a
|
694
|
return False
|
switches |
0:0e018d759a2a
|
695
|
|
switches |
0:0e018d759a2a
|
696
|
# We need to combine macros from parameter list with macros from library
|
switches |
0:0e018d759a2a
|
697
|
# definition
|
switches |
0:0e018d759a2a
|
698
|
lib_macros = lib.macros if lib.macros else []
|
switches |
0:0e018d759a2a
|
699
|
if macros:
|
switches |
0:0e018d759a2a
|
700
|
macros.extend(lib_macros)
|
switches |
0:0e018d759a2a
|
701
|
else:
|
switches |
0:0e018d759a2a
|
702
|
macros = lib_macros
|
switches |
0:0e018d759a2a
|
703
|
|
switches |
0:0e018d759a2a
|
704
|
src_paths = lib.source_dir
|
switches |
0:0e018d759a2a
|
705
|
build_path = lib.build_dir
|
switches |
0:0e018d759a2a
|
706
|
dependencies_paths = lib.dependencies
|
switches |
0:0e018d759a2a
|
707
|
inc_dirs = lib.inc_dirs
|
switches |
0:0e018d759a2a
|
708
|
inc_dirs_ext = lib.inc_dirs_ext
|
switches |
0:0e018d759a2a
|
709
|
|
switches |
0:0e018d759a2a
|
710
|
if type(src_paths) != ListType:
|
switches |
0:0e018d759a2a
|
711
|
src_paths = [src_paths]
|
switches |
0:0e018d759a2a
|
712
|
|
switches |
0:0e018d759a2a
|
713
|
# The first path will give the name to the library
|
switches |
0:0e018d759a2a
|
714
|
name = basename(src_paths[0])
|
switches |
0:0e018d759a2a
|
715
|
|
switches |
0:0e018d759a2a
|
716
|
if report != None:
|
switches |
0:0e018d759a2a
|
717
|
start = time()
|
switches |
0:0e018d759a2a
|
718
|
id_name = name.upper()
|
switches |
0:0e018d759a2a
|
719
|
description = name
|
switches |
0:0e018d759a2a
|
720
|
vendor_label = target.extra_labels[0]
|
switches |
0:0e018d759a2a
|
721
|
cur_result = None
|
switches |
0:0e018d759a2a
|
722
|
prep_report(report, target.name, toolchain_name, id_name)
|
switches |
0:0e018d759a2a
|
723
|
cur_result = create_result(target.name, toolchain_name, id_name,
|
switches |
0:0e018d759a2a
|
724
|
description)
|
switches |
0:0e018d759a2a
|
725
|
|
switches |
0:0e018d759a2a
|
726
|
if properties != None:
|
switches |
0:0e018d759a2a
|
727
|
prep_properties(properties, target.name, toolchain_name,
|
switches |
0:0e018d759a2a
|
728
|
vendor_label)
|
switches |
0:0e018d759a2a
|
729
|
|
switches |
0:0e018d759a2a
|
730
|
for src_path in src_paths:
|
switches |
0:0e018d759a2a
|
731
|
if not exists(src_path):
|
switches |
0:0e018d759a2a
|
732
|
error_msg = "The library source folder does not exist: %s", src_path
|
switches |
0:0e018d759a2a
|
733
|
|
switches |
0:0e018d759a2a
|
734
|
if report != None:
|
switches |
0:0e018d759a2a
|
735
|
cur_result["output"] = error_msg
|
switches |
0:0e018d759a2a
|
736
|
cur_result["result"] = "FAIL"
|
switches |
0:0e018d759a2a
|
737
|
add_result_to_report(report, cur_result)
|
switches |
0:0e018d759a2a
|
738
|
|
switches |
0:0e018d759a2a
|
739
|
raise Exception(error_msg)
|
switches |
0:0e018d759a2a
|
740
|
|
switches |
0:0e018d759a2a
|
741
|
try:
|
switches |
0:0e018d759a2a
|
742
|
# Toolchain instance
|
switches |
0:0e018d759a2a
|
743
|
toolchain = TOOLCHAIN_CLASSES[toolchain_name](
|
switches |
0:0e018d759a2a
|
744
|
target, macros=macros, notify=notify, silent=silent,
|
switches |
0:0e018d759a2a
|
745
|
extra_verbose=extra_verbose, build_profile=build_profile)
|
switches |
0:0e018d759a2a
|
746
|
toolchain.VERBOSE = verbose
|
switches |
0:0e018d759a2a
|
747
|
toolchain.jobs = jobs
|
switches |
0:0e018d759a2a
|
748
|
toolchain.build_all = clean
|
switches |
0:0e018d759a2a
|
749
|
|
switches |
0:0e018d759a2a
|
750
|
toolchain.info("Building library %s (%s, %s)" %
|
switches |
0:0e018d759a2a
|
751
|
(name.upper(), target.name, toolchain_name))
|
switches |
0:0e018d759a2a
|
752
|
|
switches |
0:0e018d759a2a
|
753
|
# Take into account the library configuration (MBED_CONFIG_FILE)
|
switches |
0:0e018d759a2a
|
754
|
config = Config(target)
|
switches |
0:0e018d759a2a
|
755
|
toolchain.config = config
|
switches |
0:0e018d759a2a
|
756
|
config.add_config_files([MBED_CONFIG_FILE])
|
switches |
0:0e018d759a2a
|
757
|
|
switches |
0:0e018d759a2a
|
758
|
# Scan Resources
|
switches |
0:0e018d759a2a
|
759
|
resources = []
|
switches |
0:0e018d759a2a
|
760
|
for src_path in src_paths:
|
switches |
0:0e018d759a2a
|
761
|
resources.append(toolchain.scan_resources(src_path))
|
switches |
0:0e018d759a2a
|
762
|
|
switches |
0:0e018d759a2a
|
763
|
# Add extra include directories / files which are required by library
|
switches |
0:0e018d759a2a
|
764
|
# This files usually are not in the same directory as source files so
|
switches |
0:0e018d759a2a
|
765
|
# previous scan will not include them
|
switches |
0:0e018d759a2a
|
766
|
if inc_dirs_ext is not None:
|
switches |
0:0e018d759a2a
|
767
|
for inc_ext in inc_dirs_ext:
|
switches |
0:0e018d759a2a
|
768
|
resources.append(toolchain.scan_resources(inc_ext))
|
switches |
0:0e018d759a2a
|
769
|
|
switches |
0:0e018d759a2a
|
770
|
# Dependencies Include Paths
|
switches |
0:0e018d759a2a
|
771
|
dependencies_include_dir = []
|
switches |
0:0e018d759a2a
|
772
|
if dependencies_paths is not None:
|
switches |
0:0e018d759a2a
|
773
|
for path in dependencies_paths:
|
switches |
0:0e018d759a2a
|
774
|
lib_resources = toolchain.scan_resources(path)
|
switches |
0:0e018d759a2a
|
775
|
dependencies_include_dir.extend(lib_resources.inc_dirs)
|
switches |
0:0e018d759a2a
|
776
|
dependencies_include_dir.extend(map(dirname, lib_resources.inc_dirs))
|
switches |
0:0e018d759a2a
|
777
|
|
switches |
0:0e018d759a2a
|
778
|
if inc_dirs:
|
switches |
0:0e018d759a2a
|
779
|
dependencies_include_dir.extend(inc_dirs)
|
switches |
0:0e018d759a2a
|
780
|
|
switches |
0:0e018d759a2a
|
781
|
# Add other discovered configuration data to the configuration object
|
switches |
0:0e018d759a2a
|
782
|
for res in resources:
|
switches |
0:0e018d759a2a
|
783
|
config.load_resources(res)
|
switches |
0:0e018d759a2a
|
784
|
toolchain.set_config_data(toolchain.config.get_config_data())
|
switches |
0:0e018d759a2a
|
785
|
|
switches |
0:0e018d759a2a
|
786
|
# Create the desired build directory structure
|
switches |
0:0e018d759a2a
|
787
|
bin_path = join(build_path, toolchain.obj_path)
|
switches |
0:0e018d759a2a
|
788
|
mkdir(bin_path)
|
switches |
0:0e018d759a2a
|
789
|
tmp_path = join(build_path, '.temp', toolchain.obj_path)
|
switches |
0:0e018d759a2a
|
790
|
mkdir(tmp_path)
|
switches |
0:0e018d759a2a
|
791
|
|
switches |
0:0e018d759a2a
|
792
|
# Copy Headers
|
switches |
0:0e018d759a2a
|
793
|
for resource in resources:
|
switches |
0:0e018d759a2a
|
794
|
toolchain.copy_files(resource.headers, build_path,
|
switches |
0:0e018d759a2a
|
795
|
resources=resource)
|
switches |
0:0e018d759a2a
|
796
|
|
switches |
0:0e018d759a2a
|
797
|
dependencies_include_dir.extend(
|
switches |
0:0e018d759a2a
|
798
|
toolchain.scan_resources(build_path).inc_dirs)
|
switches |
0:0e018d759a2a
|
799
|
|
switches |
0:0e018d759a2a
|
800
|
# Compile Sources
|
switches |
0:0e018d759a2a
|
801
|
objects = []
|
switches |
0:0e018d759a2a
|
802
|
for resource in resources:
|
switches |
0:0e018d759a2a
|
803
|
objects.extend(toolchain.compile_sources(resource, tmp_path,
|
switches |
0:0e018d759a2a
|
804
|
dependencies_include_dir))
|
switches |
0:0e018d759a2a
|
805
|
|
switches |
0:0e018d759a2a
|
806
|
needed_update = toolchain.build_library(objects, bin_path, name)
|
switches |
0:0e018d759a2a
|
807
|
|
switches |
0:0e018d759a2a
|
808
|
if report != None and needed_update:
|
switches |
0:0e018d759a2a
|
809
|
end = time()
|
switches |
0:0e018d759a2a
|
810
|
cur_result["elapsed_time"] = end - start
|
switches |
0:0e018d759a2a
|
811
|
cur_result["output"] = toolchain.get_output()
|
switches |
0:0e018d759a2a
|
812
|
cur_result["result"] = "OK"
|
switches |
0:0e018d759a2a
|
813
|
|
switches |
0:0e018d759a2a
|
814
|
add_result_to_report(report, cur_result)
|
switches |
0:0e018d759a2a
|
815
|
return True
|
switches |
0:0e018d759a2a
|
816
|
|
switches |
0:0e018d759a2a
|
817
|
except Exception:
|
switches |
0:0e018d759a2a
|
818
|
if report != None:
|
switches |
0:0e018d759a2a
|
819
|
end = time()
|
switches |
0:0e018d759a2a
|
820
|
cur_result["result"] = "FAIL"
|
switches |
0:0e018d759a2a
|
821
|
cur_result["elapsed_time"] = end - start
|
switches |
0:0e018d759a2a
|
822
|
|
switches |
0:0e018d759a2a
|
823
|
toolchain_output = toolchain.get_output()
|
switches |
0:0e018d759a2a
|
824
|
if toolchain_output:
|
switches |
0:0e018d759a2a
|
825
|
cur_result["output"] += toolchain_output
|
switches |
0:0e018d759a2a
|
826
|
|
switches |
0:0e018d759a2a
|
827
|
add_result_to_report(report, cur_result)
|
switches |
0:0e018d759a2a
|
828
|
|
switches |
0:0e018d759a2a
|
829
|
# Let Exception propagate
|
switches |
0:0e018d759a2a
|
830
|
raise
|
switches |
0:0e018d759a2a
|
831
|
|
switches |
0:0e018d759a2a
|
832
|
# We do have unique legacy conventions about how we build and package the mbed
|
switches |
0:0e018d759a2a
|
833
|
# library
|
switches |
0:0e018d759a2a
|
834
|
def build_mbed_libs(target, toolchain_name, verbose=False,
|
switches |
0:0e018d759a2a
|
835
|
clean=False, macros=None, notify=None, jobs=1, silent=False,
|
switches |
0:0e018d759a2a
|
836
|
report=None, properties=None, extra_verbose=False,
|
switches |
0:0e018d759a2a
|
837
|
build_profile=None):
|
switches |
0:0e018d759a2a
|
838
|
""" Function returns True is library was built and false if building was
|
switches |
0:0e018d759a2a
|
839
|
skipped
|
switches |
0:0e018d759a2a
|
840
|
|
switches |
0:0e018d759a2a
|
841
|
Positional arguments:
|
switches |
0:0e018d759a2a
|
842
|
target - the MCU or board that the project will compile for
|
switches |
0:0e018d759a2a
|
843
|
toolchain_name - the name of the build tools
|
switches |
0:0e018d759a2a
|
844
|
|
switches |
0:0e018d759a2a
|
845
|
Keyword arguments:
|
switches |
0:0e018d759a2a
|
846
|
verbose - Write the actual tools command lines used if True
|
switches |
0:0e018d759a2a
|
847
|
clean - Rebuild everything if True
|
switches |
0:0e018d759a2a
|
848
|
macros - additional macros
|
switches |
0:0e018d759a2a
|
849
|
notify - Notify function for logs
|
switches |
0:0e018d759a2a
|
850
|
jobs - how many compilers we can run at once
|
switches |
0:0e018d759a2a
|
851
|
silent - suppress printing of progress indicators
|
switches |
0:0e018d759a2a
|
852
|
report - a dict where a result may be appended
|
switches |
0:0e018d759a2a
|
853
|
properties - UUUUHHHHH beats me
|
switches |
0:0e018d759a2a
|
854
|
extra_verbose - even more output!
|
switches |
0:0e018d759a2a
|
855
|
build_profile - a dict of flags that will be passed to the compiler
|
switches |
0:0e018d759a2a
|
856
|
"""
|
switches |
0:0e018d759a2a
|
857
|
|
switches |
0:0e018d759a2a
|
858
|
if report != None:
|
switches |
0:0e018d759a2a
|
859
|
start = time()
|
switches |
0:0e018d759a2a
|
860
|
id_name = "MBED"
|
switches |
0:0e018d759a2a
|
861
|
description = "mbed SDK"
|
switches |
0:0e018d759a2a
|
862
|
vendor_label = target.extra_labels[0]
|
switches |
0:0e018d759a2a
|
863
|
cur_result = None
|
switches |
0:0e018d759a2a
|
864
|
prep_report(report, target.name, toolchain_name, id_name)
|
switches |
0:0e018d759a2a
|
865
|
cur_result = create_result(target.name, toolchain_name, id_name,
|
switches |
0:0e018d759a2a
|
866
|
description)
|
switches |
0:0e018d759a2a
|
867
|
|
switches |
0:0e018d759a2a
|
868
|
if properties != None:
|
switches |
0:0e018d759a2a
|
869
|
prep_properties(properties, target.name, toolchain_name,
|
switches |
0:0e018d759a2a
|
870
|
vendor_label)
|
switches |
0:0e018d759a2a
|
871
|
|
switches |
0:0e018d759a2a
|
872
|
# Check toolchain support
|
switches |
0:0e018d759a2a
|
873
|
if toolchain_name not in target.supported_toolchains:
|
switches |
0:0e018d759a2a
|
874
|
supported_toolchains_text = ", ".join(target.supported_toolchains)
|
switches |
0:0e018d759a2a
|
875
|
print('%s target is not yet supported by toolchain %s' %
|
switches |
0:0e018d759a2a
|
876
|
(target.name, toolchain_name))
|
switches |
0:0e018d759a2a
|
877
|
print('%s target supports %s toolchain%s' %
|
switches |
0:0e018d759a2a
|
878
|
(target.name, supported_toolchains_text, 's'
|
switches |
0:0e018d759a2a
|
879
|
if len(target.supported_toolchains) > 1 else ''))
|
switches |
0:0e018d759a2a
|
880
|
|
switches |
0:0e018d759a2a
|
881
|
if report != None:
|
switches |
0:0e018d759a2a
|
882
|
cur_result["result"] = "SKIP"
|
switches |
0:0e018d759a2a
|
883
|
add_result_to_report(report, cur_result)
|
switches |
0:0e018d759a2a
|
884
|
|
switches |
0:0e018d759a2a
|
885
|
return False
|
switches |
0:0e018d759a2a
|
886
|
|
switches |
0:0e018d759a2a
|
887
|
try:
|
switches |
0:0e018d759a2a
|
888
|
# Toolchain
|
switches |
0:0e018d759a2a
|
889
|
toolchain = TOOLCHAIN_CLASSES[toolchain_name](
|
switches |
0:0e018d759a2a
|
890
|
target, macros=macros, notify=notify, silent=silent,
|
switches |
0:0e018d759a2a
|
891
|
extra_verbose=extra_verbose, build_profile=build_profile)
|
switches |
0:0e018d759a2a
|
892
|
toolchain.VERBOSE = verbose
|
switches |
0:0e018d759a2a
|
893
|
toolchain.jobs = jobs
|
switches |
0:0e018d759a2a
|
894
|
toolchain.build_all = clean
|
switches |
0:0e018d759a2a
|
895
|
|
switches |
0:0e018d759a2a
|
896
|
# Take into account the library configuration (MBED_CONFIG_FILE)
|
switches |
0:0e018d759a2a
|
897
|
config = Config(target)
|
switches |
0:0e018d759a2a
|
898
|
toolchain.config = config
|
switches |
0:0e018d759a2a
|
899
|
config.add_config_files([MBED_CONFIG_FILE])
|
switches |
0:0e018d759a2a
|
900
|
toolchain.set_config_data(toolchain.config.get_config_data())
|
switches |
0:0e018d759a2a
|
901
|
|
switches |
0:0e018d759a2a
|
902
|
# Source and Build Paths
|
switches |
0:0e018d759a2a
|
903
|
build_target = join(MBED_LIBRARIES, "TARGET_" + target.name)
|
switches |
0:0e018d759a2a
|
904
|
build_toolchain = join(build_target, "TOOLCHAIN_" + toolchain.name)
|
switches |
0:0e018d759a2a
|
905
|
mkdir(build_toolchain)
|
switches |
0:0e018d759a2a
|
906
|
|
switches |
0:0e018d759a2a
|
907
|
tmp_path = join(MBED_LIBRARIES, '.temp', toolchain.obj_path)
|
switches |
0:0e018d759a2a
|
908
|
mkdir(tmp_path)
|
switches |
0:0e018d759a2a
|
909
|
|
switches |
0:0e018d759a2a
|
910
|
# CMSIS
|
switches |
0:0e018d759a2a
|
911
|
toolchain.info("Building library %s (%s, %s)" %
|
switches |
0:0e018d759a2a
|
912
|
('CMSIS', target.name, toolchain_name))
|
switches |
0:0e018d759a2a
|
913
|
cmsis_src = MBED_CMSIS_PATH
|
switches |
0:0e018d759a2a
|
914
|
resources = toolchain.scan_resources(cmsis_src)
|
switches |
0:0e018d759a2a
|
915
|
|
switches |
0:0e018d759a2a
|
916
|
toolchain.copy_files(resources.headers, build_target)
|
switches |
0:0e018d759a2a
|
917
|
toolchain.copy_files(resources.linker_script, build_toolchain)
|
switches |
0:0e018d759a2a
|
918
|
toolchain.copy_files(resources.bin_files, build_toolchain)
|
switches |
0:0e018d759a2a
|
919
|
|
switches |
0:0e018d759a2a
|
920
|
objects = toolchain.compile_sources(resources, tmp_path)
|
switches |
0:0e018d759a2a
|
921
|
toolchain.copy_files(objects, build_toolchain)
|
switches |
0:0e018d759a2a
|
922
|
|
switches |
0:0e018d759a2a
|
923
|
# mbed
|
switches |
0:0e018d759a2a
|
924
|
toolchain.info("Building library %s (%s, %s)" %
|
switches |
0:0e018d759a2a
|
925
|
('MBED', target.name, toolchain_name))
|
switches |
0:0e018d759a2a
|
926
|
|
switches |
0:0e018d759a2a
|
927
|
# Common Headers
|
switches |
0:0e018d759a2a
|
928
|
toolchain.copy_files([MBED_HEADER], MBED_LIBRARIES)
|
switches |
0:0e018d759a2a
|
929
|
library_incdirs = [dirname(MBED_LIBRARIES), MBED_LIBRARIES]
|
switches |
0:0e018d759a2a
|
930
|
|
switches |
0:0e018d759a2a
|
931
|
for dir, dest in [(MBED_DRIVERS, MBED_LIBRARIES_DRIVERS),
|
switches |
0:0e018d759a2a
|
932
|
(MBED_PLATFORM, MBED_LIBRARIES_PLATFORM),
|
switches |
0:0e018d759a2a
|
933
|
(MBED_HAL, MBED_LIBRARIES_HAL)]:
|
switches |
0:0e018d759a2a
|
934
|
resources = toolchain.scan_resources(dir)
|
switches |
0:0e018d759a2a
|
935
|
toolchain.copy_files(resources.headers, dest)
|
switches |
0:0e018d759a2a
|
936
|
library_incdirs.append(dest)
|
switches |
0:0e018d759a2a
|
937
|
|
switches |
0:0e018d759a2a
|
938
|
# Target specific sources
|
switches |
0:0e018d759a2a
|
939
|
hal_src = MBED_TARGETS_PATH
|
switches |
0:0e018d759a2a
|
940
|
hal_implementation = toolchain.scan_resources(hal_src)
|
switches |
0:0e018d759a2a
|
941
|
toolchain.copy_files(hal_implementation.headers +
|
switches |
0:0e018d759a2a
|
942
|
hal_implementation.hex_files +
|
switches |
0:0e018d759a2a
|
943
|
hal_implementation.libraries +
|
switches |
0:0e018d759a2a
|
944
|
[MBED_CONFIG_FILE],
|
switches |
0:0e018d759a2a
|
945
|
build_target, resources=hal_implementation)
|
switches |
0:0e018d759a2a
|
946
|
toolchain.copy_files(hal_implementation.linker_script, build_toolchain)
|
switches |
0:0e018d759a2a
|
947
|
toolchain.copy_files(hal_implementation.bin_files, build_toolchain)
|
switches |
0:0e018d759a2a
|
948
|
incdirs = toolchain.scan_resources(build_target).inc_dirs
|
switches |
0:0e018d759a2a
|
949
|
objects = toolchain.compile_sources(hal_implementation, tmp_path,
|
switches |
0:0e018d759a2a
|
950
|
library_incdirs + incdirs)
|
switches |
0:0e018d759a2a
|
951
|
toolchain.copy_files(objects, build_toolchain)
|
switches |
0:0e018d759a2a
|
952
|
|
switches |
0:0e018d759a2a
|
953
|
# Common Sources
|
switches |
0:0e018d759a2a
|
954
|
mbed_resources = None
|
switches |
0:0e018d759a2a
|
955
|
for dir in [MBED_DRIVERS, MBED_PLATFORM, MBED_HAL]:
|
switches |
0:0e018d759a2a
|
956
|
mbed_resources += toolchain.scan_resources(dir)
|
switches |
0:0e018d759a2a
|
957
|
|
switches |
0:0e018d759a2a
|
958
|
objects = toolchain.compile_sources(mbed_resources, tmp_path,
|
switches |
0:0e018d759a2a
|
959
|
library_incdirs + incdirs)
|
switches |
0:0e018d759a2a
|
960
|
|
switches |
0:0e018d759a2a
|
961
|
# A number of compiled files need to be copied as objects as opposed to
|
switches |
0:0e018d759a2a
|
962
|
# way the linker search for symbols in archives. These are:
|
switches |
0:0e018d759a2a
|
963
|
# - retarget.o: to make sure that the C standard lib symbols get
|
switches |
0:0e018d759a2a
|
964
|
# overridden
|
switches |
0:0e018d759a2a
|
965
|
# - board.o: mbed_die is weak
|
switches |
0:0e018d759a2a
|
966
|
# - mbed_overrides.o: this contains platform overrides of various
|
switches |
0:0e018d759a2a
|
967
|
# weak SDK functions
|
switches |
0:0e018d759a2a
|
968
|
separate_names, separate_objects = ['retarget.o', 'board.o',
|
switches |
0:0e018d759a2a
|
969
|
'mbed_overrides.o'], []
|
switches |
0:0e018d759a2a
|
970
|
|
switches |
0:0e018d759a2a
|
971
|
for obj in objects:
|
switches |
0:0e018d759a2a
|
972
|
for name in separate_names:
|
switches |
0:0e018d759a2a
|
973
|
if obj.endswith(name):
|
switches |
0:0e018d759a2a
|
974
|
separate_objects.append(obj)
|
switches |
0:0e018d759a2a
|
975
|
|
switches |
0:0e018d759a2a
|
976
|
for obj in separate_objects:
|
switches |
0:0e018d759a2a
|
977
|
objects.remove(obj)
|
switches |
0:0e018d759a2a
|
978
|
|
switches |
0:0e018d759a2a
|
979
|
toolchain.build_library(objects, build_toolchain, "mbed")
|
switches |
0:0e018d759a2a
|
980
|
|
switches |
0:0e018d759a2a
|
981
|
for obj in separate_objects:
|
switches |
0:0e018d759a2a
|
982
|
toolchain.copy_files(obj, build_toolchain)
|
switches |
0:0e018d759a2a
|
983
|
|
switches |
0:0e018d759a2a
|
984
|
if report != None:
|
switches |
0:0e018d759a2a
|
985
|
end = time()
|
switches |
0:0e018d759a2a
|
986
|
cur_result["elapsed_time"] = end - start
|
switches |
0:0e018d759a2a
|
987
|
cur_result["output"] = toolchain.get_output()
|
switches |
0:0e018d759a2a
|
988
|
cur_result["result"] = "OK"
|
switches |
0:0e018d759a2a
|
989
|
|
switches |
0:0e018d759a2a
|
990
|
add_result_to_report(report, cur_result)
|
switches |
0:0e018d759a2a
|
991
|
|
switches |
0:0e018d759a2a
|
992
|
return True
|
switches |
0:0e018d759a2a
|
993
|
|
switches |
0:0e018d759a2a
|
994
|
except Exception as exc:
|
switches |
0:0e018d759a2a
|
995
|
if report != None:
|
switches |
0:0e018d759a2a
|
996
|
end = time()
|
switches |
0:0e018d759a2a
|
997
|
cur_result["result"] = "FAIL"
|
switches |
0:0e018d759a2a
|
998
|
cur_result["elapsed_time"] = end - start
|
switches |
0:0e018d759a2a
|
999
|
|
switches |
0:0e018d759a2a
|
1000
|
toolchain_output = toolchain.get_output()
|
switches |
0:0e018d759a2a
|
1001
|
if toolchain_output:
|
switches |
0:0e018d759a2a
|
1002
|
cur_result["output"] += toolchain_output
|
switches |
0:0e018d759a2a
|
1003
|
|
switches |
0:0e018d759a2a
|
1004
|
cur_result["output"] += str(exc)
|
switches |
0:0e018d759a2a
|
1005
|
|
switches |
0:0e018d759a2a
|
1006
|
add_result_to_report(report, cur_result)
|
switches |
0:0e018d759a2a
|
1007
|
|
switches |
0:0e018d759a2a
|
1008
|
# Let Exception propagate
|
switches |
0:0e018d759a2a
|
1009
|
raise
|
switches |
0:0e018d759a2a
|
1010
|
|
switches |
0:0e018d759a2a
|
1011
|
|
switches |
0:0e018d759a2a
|
1012
|
def get_unique_supported_toolchains(release_targets=None):
|
switches |
0:0e018d759a2a
|
1013
|
""" Get list of all unique toolchains supported by targets
|
switches |
0:0e018d759a2a
|
1014
|
|
switches |
0:0e018d759a2a
|
1015
|
Keyword arguments:
|
switches |
0:0e018d759a2a
|
1016
|
release_targets - tuple structure returned from get_mbed_official_release().
|
switches |
0:0e018d759a2a
|
1017
|
If release_targets is not specified, then it queries all
|
switches |
0:0e018d759a2a
|
1018
|
known targets
|
switches |
0:0e018d759a2a
|
1019
|
"""
|
switches |
0:0e018d759a2a
|
1020
|
unique_supported_toolchains = []
|
switches |
0:0e018d759a2a
|
1021
|
|
switches |
0:0e018d759a2a
|
1022
|
if not release_targets:
|
switches |
0:0e018d759a2a
|
1023
|
for target in TARGET_NAMES:
|
switches |
0:0e018d759a2a
|
1024
|
for toolchain in TARGET_MAP[target].supported_toolchains:
|
switches |
0:0e018d759a2a
|
1025
|
if toolchain not in unique_supported_toolchains:
|
switches |
0:0e018d759a2a
|
1026
|
unique_supported_toolchains.append(toolchain)
|
switches |
0:0e018d759a2a
|
1027
|
else:
|
switches |
0:0e018d759a2a
|
1028
|
for target in release_targets:
|
switches |
0:0e018d759a2a
|
1029
|
for toolchain in target[1]:
|
switches |
0:0e018d759a2a
|
1030
|
if toolchain not in unique_supported_toolchains:
|
switches |
0:0e018d759a2a
|
1031
|
unique_supported_toolchains.append(toolchain)
|
switches |
0:0e018d759a2a
|
1032
|
|
switches |
0:0e018d759a2a
|
1033
|
return unique_supported_toolchains
|
switches |
0:0e018d759a2a
|
1034
|
|
switches |
0:0e018d759a2a
|
1035
|
|
switches |
0:0e018d759a2a
|
1036
|
def mcu_toolchain_matrix(verbose_html=False, platform_filter=None,
|
switches |
0:0e018d759a2a
|
1037
|
release_version='5'):
|
switches |
0:0e018d759a2a
|
1038
|
""" Shows target map using prettytable
|
switches |
0:0e018d759a2a
|
1039
|
|
switches |
0:0e018d759a2a
|
1040
|
Keyword arguments:
|
switches |
0:0e018d759a2a
|
1041
|
verbose_html - emit html instead of a simple table
|
switches |
0:0e018d759a2a
|
1042
|
platform_filter - remove results that match the string
|
switches |
0:0e018d759a2a
|
1043
|
release_version - get the matrix for this major version number
|
switches |
0:0e018d759a2a
|
1044
|
"""
|
switches |
0:0e018d759a2a
|
1045
|
# Only use it in this function so building works without extra modules
|
switches |
0:0e018d759a2a
|
1046
|
from prettytable import PrettyTable
|
switches |
0:0e018d759a2a
|
1047
|
|
switches |
0:0e018d759a2a
|
1048
|
if isinstance(release_version, basestring):
|
switches |
0:0e018d759a2a
|
1049
|
# Force release_version to lowercase if it is a string
|
switches |
0:0e018d759a2a
|
1050
|
release_version = release_version.lower()
|
switches |
0:0e018d759a2a
|
1051
|
else:
|
switches |
0:0e018d759a2a
|
1052
|
# Otherwise default to printing all known targets and toolchains
|
switches |
0:0e018d759a2a
|
1053
|
release_version = 'all'
|
switches |
0:0e018d759a2a
|
1054
|
|
switches |
0:0e018d759a2a
|
1055
|
|
switches |
0:0e018d759a2a
|
1056
|
version_release_targets = {}
|
switches |
0:0e018d759a2a
|
1057
|
version_release_target_names = {}
|
switches |
0:0e018d759a2a
|
1058
|
|
switches |
0:0e018d759a2a
|
1059
|
for version in RELEASE_VERSIONS:
|
switches |
0:0e018d759a2a
|
1060
|
version_release_targets[version] = get_mbed_official_release(version)
|
switches |
0:0e018d759a2a
|
1061
|
version_release_target_names[version] = [x[0] for x in
|
switches |
0:0e018d759a2a
|
1062
|
version_release_targets[
|
switches |
0:0e018d759a2a
|
1063
|
version]]
|
switches |
0:0e018d759a2a
|
1064
|
|
switches |
0:0e018d759a2a
|
1065
|
if release_version in RELEASE_VERSIONS:
|
switches |
0:0e018d759a2a
|
1066
|
release_targets = version_release_targets[release_version]
|
switches |
0:0e018d759a2a
|
1067
|
else:
|
switches |
0:0e018d759a2a
|
1068
|
release_targets = None
|
switches |
0:0e018d759a2a
|
1069
|
|
switches |
0:0e018d759a2a
|
1070
|
unique_supported_toolchains = get_unique_supported_toolchains(
|
switches |
0:0e018d759a2a
|
1071
|
release_targets)
|
switches |
0:0e018d759a2a
|
1072
|
prepend_columns = ["Target"] + ["mbed OS %s" % x for x in RELEASE_VERSIONS]
|
switches |
0:0e018d759a2a
|
1073
|
|
switches |
0:0e018d759a2a
|
1074
|
# All tests status table print
|
switches |
0:0e018d759a2a
|
1075
|
columns = prepend_columns + unique_supported_toolchains
|
switches |
0:0e018d759a2a
|
1076
|
table_printer = PrettyTable(columns)
|
switches |
0:0e018d759a2a
|
1077
|
# Align table
|
switches |
0:0e018d759a2a
|
1078
|
for col in columns:
|
switches |
0:0e018d759a2a
|
1079
|
table_printer.align[col] = "c"
|
switches |
0:0e018d759a2a
|
1080
|
table_printer.align["Target"] = "l"
|
switches |
0:0e018d759a2a
|
1081
|
|
switches |
0:0e018d759a2a
|
1082
|
perm_counter = 0
|
switches |
0:0e018d759a2a
|
1083
|
target_counter = 0
|
switches |
0:0e018d759a2a
|
1084
|
|
switches |
0:0e018d759a2a
|
1085
|
target_names = []
|
switches |
0:0e018d759a2a
|
1086
|
|
switches |
0:0e018d759a2a
|
1087
|
if release_targets:
|
switches |
0:0e018d759a2a
|
1088
|
target_names = [x[0] for x in release_targets]
|
switches |
0:0e018d759a2a
|
1089
|
else:
|
switches |
0:0e018d759a2a
|
1090
|
target_names = TARGET_NAMES
|
switches |
0:0e018d759a2a
|
1091
|
|
switches |
0:0e018d759a2a
|
1092
|
for target in sorted(target_names):
|
switches |
0:0e018d759a2a
|
1093
|
if platform_filter is not None:
|
switches |
0:0e018d759a2a
|
1094
|
# FIlter out platforms using regex
|
switches |
0:0e018d759a2a
|
1095
|
if re.search(platform_filter, target) is None:
|
switches |
0:0e018d759a2a
|
1096
|
continue
|
switches |
0:0e018d759a2a
|
1097
|
target_counter += 1
|
switches |
0:0e018d759a2a
|
1098
|
|
switches |
0:0e018d759a2a
|
1099
|
row = [target] # First column is platform name
|
switches |
0:0e018d759a2a
|
1100
|
|
switches |
0:0e018d759a2a
|
1101
|
for version in RELEASE_VERSIONS:
|
switches |
0:0e018d759a2a
|
1102
|
if target in version_release_target_names[version]:
|
switches |
0:0e018d759a2a
|
1103
|
text = "Supported"
|
switches |
0:0e018d759a2a
|
1104
|
else:
|
switches |
0:0e018d759a2a
|
1105
|
text = "-"
|
switches |
0:0e018d759a2a
|
1106
|
row.append(text)
|
switches |
0:0e018d759a2a
|
1107
|
|
switches |
0:0e018d759a2a
|
1108
|
for unique_toolchain in unique_supported_toolchains:
|
switches |
0:0e018d759a2a
|
1109
|
if unique_toolchain in TARGET_MAP[target].supported_toolchains:
|
switches |
0:0e018d759a2a
|
1110
|
text = "Supported"
|
switches |
0:0e018d759a2a
|
1111
|
perm_counter += 1
|
switches |
0:0e018d759a2a
|
1112
|
else:
|
switches |
0:0e018d759a2a
|
1113
|
text = "-"
|
switches |
0:0e018d759a2a
|
1114
|
|
switches |
0:0e018d759a2a
|
1115
|
row.append(text)
|
switches |
0:0e018d759a2a
|
1116
|
table_printer.add_row(row)
|
switches |
0:0e018d759a2a
|
1117
|
|
switches |
0:0e018d759a2a
|
1118
|
result = table_printer.get_html_string() if verbose_html \
|
switches |
0:0e018d759a2a
|
1119
|
else table_printer.get_string()
|
switches |
0:0e018d759a2a
|
1120
|
result += "\n"
|
switches |
0:0e018d759a2a
|
1121
|
result += "Supported targets: %d\n"% (target_counter)
|
switches |
0:0e018d759a2a
|
1122
|
if target_counter == 1:
|
switches |
0:0e018d759a2a
|
1123
|
result += "Supported toolchains: %d"% (perm_counter)
|
switches |
0:0e018d759a2a
|
1124
|
return result
|
switches |
0:0e018d759a2a
|
1125
|
|
switches |
0:0e018d759a2a
|
1126
|
|
switches |
0:0e018d759a2a
|
1127
|
def get_target_supported_toolchains(target):
|
switches |
0:0e018d759a2a
|
1128
|
""" Returns target supported toolchains list
|
switches |
0:0e018d759a2a
|
1129
|
|
switches |
0:0e018d759a2a
|
1130
|
Positional arguments:
|
switches |
0:0e018d759a2a
|
1131
|
target - the target to get the supported toolchains of
|
switches |
0:0e018d759a2a
|
1132
|
"""
|
switches |
0:0e018d759a2a
|
1133
|
return TARGET_MAP[target].supported_toolchains if target in TARGET_MAP \
|
switches |
0:0e018d759a2a
|
1134
|
else None
|
switches |
0:0e018d759a2a
|
1135
|
|
switches |
0:0e018d759a2a
|
1136
|
|
switches |
0:0e018d759a2a
|
1137
|
def static_analysis_scan(target, toolchain_name, cppcheck_cmd,
|
switches |
0:0e018d759a2a
|
1138
|
cppcheck_msg_format, verbose=False,
|
switches |
0:0e018d759a2a
|
1139
|
clean=False, macros=None, notify=None, jobs=1,
|
switches |
0:0e018d759a2a
|
1140
|
extra_verbose=False, build_profile=None):
|
switches |
0:0e018d759a2a
|
1141
|
"""Perform static analysis on a target and toolchain combination
|
switches |
0:0e018d759a2a
|
1142
|
|
switches |
0:0e018d759a2a
|
1143
|
Positional arguments:
|
switches |
0:0e018d759a2a
|
1144
|
target - the target to fake the build for
|
switches |
0:0e018d759a2a
|
1145
|
toolchain_name - pretend you would compile with this toolchain
|
switches |
0:0e018d759a2a
|
1146
|
cppcheck_cmd - the command used to do static analysis
|
switches |
0:0e018d759a2a
|
1147
|
cppcheck_msg_format - the format of the check messages
|
switches |
0:0e018d759a2a
|
1148
|
|
switches |
0:0e018d759a2a
|
1149
|
Keyword arguments:
|
switches |
0:0e018d759a2a
|
1150
|
verbose - more printing!
|
switches |
0:0e018d759a2a
|
1151
|
clean - start from a clean slate
|
switches |
0:0e018d759a2a
|
1152
|
macros - extra macros to compile with
|
switches |
0:0e018d759a2a
|
1153
|
notify - the notification event handling function
|
switches |
0:0e018d759a2a
|
1154
|
jobs - number of commands to run at once
|
switches |
0:0e018d759a2a
|
1155
|
extra_verbose - even moar printing
|
switches |
0:0e018d759a2a
|
1156
|
build_profile - a dict of flags that will be passed to the compiler
|
switches |
0:0e018d759a2a
|
1157
|
"""
|
switches |
0:0e018d759a2a
|
1158
|
# Toolchain
|
switches |
0:0e018d759a2a
|
1159
|
toolchain = TOOLCHAIN_CLASSES[toolchain_name](target, macros=macros,
|
switches |
0:0e018d759a2a
|
1160
|
notify=notify,
|
switches |
0:0e018d759a2a
|
1161
|
extra_verbose=extra_verbose,
|
switches |
0:0e018d759a2a
|
1162
|
build_profile=build_profile)
|
switches |
0:0e018d759a2a
|
1163
|
toolchain.VERBOSE = verbose
|
switches |
0:0e018d759a2a
|
1164
|
toolchain.jobs = jobs
|
switches |
0:0e018d759a2a
|
1165
|
toolchain.build_all = clean
|
switches |
0:0e018d759a2a
|
1166
|
|
switches |
0:0e018d759a2a
|
1167
|
# Source and Build Paths
|
switches |
0:0e018d759a2a
|
1168
|
build_target = join(MBED_LIBRARIES, "TARGET_" + target.name)
|
switches |
0:0e018d759a2a
|
1169
|
build_toolchain = join(build_target, "TOOLCHAIN_" + toolchain.name)
|
switches |
0:0e018d759a2a
|
1170
|
mkdir(build_toolchain)
|
switches |
0:0e018d759a2a
|
1171
|
|
switches |
0:0e018d759a2a
|
1172
|
tmp_path = join(MBED_LIBRARIES, '.temp', toolchain.obj_path)
|
switches |
0:0e018d759a2a
|
1173
|
mkdir(tmp_path)
|
switches |
0:0e018d759a2a
|
1174
|
|
switches |
0:0e018d759a2a
|
1175
|
# CMSIS
|
switches |
0:0e018d759a2a
|
1176
|
toolchain.info("Static analysis for %s (%s, %s)" %
|
switches |
0:0e018d759a2a
|
1177
|
('CMSIS', target.name, toolchain_name))
|
switches |
0:0e018d759a2a
|
1178
|
cmsis_src = MBED_CMSIS_PATH
|
switches |
0:0e018d759a2a
|
1179
|
resources = toolchain.scan_resources(cmsis_src)
|
switches |
0:0e018d759a2a
|
1180
|
|
switches |
0:0e018d759a2a
|
1181
|
# Copy files before analysis
|
switches |
0:0e018d759a2a
|
1182
|
toolchain.copy_files(resources.headers, build_target)
|
switches |
0:0e018d759a2a
|
1183
|
toolchain.copy_files(resources.linker_script, build_toolchain)
|
switches |
0:0e018d759a2a
|
1184
|
|
switches |
0:0e018d759a2a
|
1185
|
# Gather include paths, c, cpp sources and macros to transfer to cppcheck
|
switches |
0:0e018d759a2a
|
1186
|
# command line
|
switches |
0:0e018d759a2a
|
1187
|
includes = ["-I%s"% i for i in resources.inc_dirs]
|
switches |
0:0e018d759a2a
|
1188
|
includes.append("-I%s"% str(build_target))
|
switches |
0:0e018d759a2a
|
1189
|
c_sources = " ".join(resources.c_sources)
|
switches |
0:0e018d759a2a
|
1190
|
cpp_sources = " ".join(resources.cpp_sources)
|
switches |
0:0e018d759a2a
|
1191
|
macros = ["-D%s"% s for s in toolchain.get_symbols() + toolchain.macros]
|
switches |
0:0e018d759a2a
|
1192
|
|
switches |
0:0e018d759a2a
|
1193
|
includes = [inc.strip() for inc in includes]
|
switches |
0:0e018d759a2a
|
1194
|
macros = [mac.strip() for mac in macros]
|
switches |
0:0e018d759a2a
|
1195
|
|
switches |
0:0e018d759a2a
|
1196
|
check_cmd = cppcheck_cmd
|
switches |
0:0e018d759a2a
|
1197
|
check_cmd += cppcheck_msg_format
|
switches |
0:0e018d759a2a
|
1198
|
check_cmd += includes
|
switches |
0:0e018d759a2a
|
1199
|
check_cmd += macros
|
switches |
0:0e018d759a2a
|
1200
|
|
switches |
0:0e018d759a2a
|
1201
|
# We need to pass some params via file to avoid "command line too long in
|
switches |
0:0e018d759a2a
|
1202
|
# some OSs"
|
switches |
0:0e018d759a2a
|
1203
|
tmp_file = tempfile.NamedTemporaryFile(delete=False)
|
switches |
0:0e018d759a2a
|
1204
|
tmp_file.writelines(line + '\n' for line in c_sources.split())
|
switches |
0:0e018d759a2a
|
1205
|
tmp_file.writelines(line + '\n' for line in cpp_sources.split())
|
switches |
0:0e018d759a2a
|
1206
|
tmp_file.close()
|
switches |
0:0e018d759a2a
|
1207
|
check_cmd += ["--file-list=%s"% tmp_file.name]
|
switches |
0:0e018d759a2a
|
1208
|
|
switches |
0:0e018d759a2a
|
1209
|
_stdout, _stderr, _ = run_cmd(check_cmd)
|
switches |
0:0e018d759a2a
|
1210
|
if verbose:
|
switches |
0:0e018d759a2a
|
1211
|
print _stdout
|
switches |
0:0e018d759a2a
|
1212
|
print _stderr
|
switches |
0:0e018d759a2a
|
1213
|
|
switches |
0:0e018d759a2a
|
1214
|
# =========================================================================
|
switches |
0:0e018d759a2a
|
1215
|
|
switches |
0:0e018d759a2a
|
1216
|
# MBED
|
switches |
0:0e018d759a2a
|
1217
|
toolchain.info("Static analysis for %s (%s, %s)" %
|
switches |
0:0e018d759a2a
|
1218
|
('MBED', target.name, toolchain_name))
|
switches |
0:0e018d759a2a
|
1219
|
|
switches |
0:0e018d759a2a
|
1220
|
# Common Headers
|
switches |
0:0e018d759a2a
|
1221
|
toolchain.copy_files([MBED_HEADER], MBED_LIBRARIES)
|
switches |
0:0e018d759a2a
|
1222
|
toolchain.copy_files(toolchain.scan_resources(MBED_DRIVERS).headers,
|
switches |
0:0e018d759a2a
|
1223
|
MBED_LIBRARIES)
|
switches |
0:0e018d759a2a
|
1224
|
toolchain.copy_files(toolchain.scan_resources(MBED_PLATFORM).headers,
|
switches |
0:0e018d759a2a
|
1225
|
MBED_LIBRARIES)
|
switches |
0:0e018d759a2a
|
1226
|
toolchain.copy_files(toolchain.scan_resources(MBED_HAL).headers,
|
switches |
0:0e018d759a2a
|
1227
|
MBED_LIBRARIES)
|
switches |
0:0e018d759a2a
|
1228
|
|
switches |
0:0e018d759a2a
|
1229
|
# Target specific sources
|
switches |
0:0e018d759a2a
|
1230
|
hal_src = join(MBED_TARGETS_PATH, "hal")
|
switches |
0:0e018d759a2a
|
1231
|
hal_implementation = toolchain.scan_resources(hal_src)
|
switches |
0:0e018d759a2a
|
1232
|
|
switches |
0:0e018d759a2a
|
1233
|
# Copy files before analysis
|
switches |
0:0e018d759a2a
|
1234
|
toolchain.copy_files(hal_implementation.headers +
|
switches |
0:0e018d759a2a
|
1235
|
hal_implementation.hex_files, build_target,
|
switches |
0:0e018d759a2a
|
1236
|
resources=hal_implementation)
|
switches |
0:0e018d759a2a
|
1237
|
incdirs = toolchain.scan_resources(build_target)
|
switches |
0:0e018d759a2a
|
1238
|
|
switches |
0:0e018d759a2a
|
1239
|
target_includes = ["-I%s" % i for i in incdirs.inc_dirs]
|
switches |
0:0e018d759a2a
|
1240
|
target_includes.append("-I%s"% str(build_target))
|
switches |
0:0e018d759a2a
|
1241
|
target_includes.append("-I%s"% str(hal_src))
|
switches |
0:0e018d759a2a
|
1242
|
target_c_sources = " ".join(incdirs.c_sources)
|
switches |
0:0e018d759a2a
|
1243
|
target_cpp_sources = " ".join(incdirs.cpp_sources)
|
switches |
0:0e018d759a2a
|
1244
|
target_macros = ["-D%s"% s for s in
|
switches |
0:0e018d759a2a
|
1245
|
toolchain.get_symbols() + toolchain.macros]
|
switches |
0:0e018d759a2a
|
1246
|
|
switches |
0:0e018d759a2a
|
1247
|
# Common Sources
|
switches |
0:0e018d759a2a
|
1248
|
mbed_resources = toolchain.scan_resources(MBED_COMMON)
|
switches |
0:0e018d759a2a
|
1249
|
|
switches |
0:0e018d759a2a
|
1250
|
# Gather include paths, c, cpp sources and macros to transfer to cppcheck
|
switches |
0:0e018d759a2a
|
1251
|
# command line
|
switches |
0:0e018d759a2a
|
1252
|
mbed_includes = ["-I%s" % i for i in mbed_resources.inc_dirs]
|
switches |
0:0e018d759a2a
|
1253
|
mbed_includes.append("-I%s"% str(build_target))
|
switches |
0:0e018d759a2a
|
1254
|
mbed_includes.append("-I%s"% str(MBED_DRIVERS))
|
switches |
0:0e018d759a2a
|
1255
|
mbed_includes.append("-I%s"% str(MBED_PLATFORM))
|
switches |
0:0e018d759a2a
|
1256
|
mbed_includes.append("-I%s"% str(MBED_HAL))
|
switches |
0:0e018d759a2a
|
1257
|
mbed_c_sources = " ".join(mbed_resources.c_sources)
|
switches |
0:0e018d759a2a
|
1258
|
mbed_cpp_sources = " ".join(mbed_resources.cpp_sources)
|
switches |
0:0e018d759a2a
|
1259
|
|
switches |
0:0e018d759a2a
|
1260
|
target_includes = [inc.strip() for inc in target_includes]
|
switches |
0:0e018d759a2a
|
1261
|
mbed_includes = [inc.strip() for inc in mbed_includes]
|
switches |
0:0e018d759a2a
|
1262
|
target_macros = [mac.strip() for mac in target_macros]
|
switches |
0:0e018d759a2a
|
1263
|
|
switches |
0:0e018d759a2a
|
1264
|
check_cmd = cppcheck_cmd
|
switches |
0:0e018d759a2a
|
1265
|
check_cmd += cppcheck_msg_format
|
switches |
0:0e018d759a2a
|
1266
|
check_cmd += target_includes
|
switches |
0:0e018d759a2a
|
1267
|
check_cmd += mbed_includes
|
switches |
0:0e018d759a2a
|
1268
|
check_cmd += target_macros
|
switches |
0:0e018d759a2a
|
1269
|
|
switches |
0:0e018d759a2a
|
1270
|
# We need to pass some parames via file to avoid "command line too long in
|
switches |
0:0e018d759a2a
|
1271
|
# some OSs"
|
switches |
0:0e018d759a2a
|
1272
|
tmp_file = tempfile.NamedTemporaryFile(delete=False)
|
switches |
0:0e018d759a2a
|
1273
|
tmp_file.writelines(line + '\n' for line in target_c_sources.split())
|
switches |
0:0e018d759a2a
|
1274
|
tmp_file.writelines(line + '\n' for line in target_cpp_sources.split())
|
switches |
0:0e018d759a2a
|
1275
|
tmp_file.writelines(line + '\n' for line in mbed_c_sources.split())
|
switches |
0:0e018d759a2a
|
1276
|
tmp_file.writelines(line + '\n' for line in mbed_cpp_sources.split())
|
switches |
0:0e018d759a2a
|
1277
|
tmp_file.close()
|
switches |
0:0e018d759a2a
|
1278
|
check_cmd += ["--file-list=%s"% tmp_file.name]
|
switches |
0:0e018d759a2a
|
1279
|
|
switches |
0:0e018d759a2a
|
1280
|
_stdout, _stderr, _ = run_cmd_ext(check_cmd)
|
switches |
0:0e018d759a2a
|
1281
|
if verbose:
|
switches |
0:0e018d759a2a
|
1282
|
print _stdout
|
switches |
0:0e018d759a2a
|
1283
|
print _stderr
|
switches |
0:0e018d759a2a
|
1284
|
|
switches |
0:0e018d759a2a
|
1285
|
|
switches |
0:0e018d759a2a
|
1286
|
def static_analysis_scan_lib(lib_id, target, toolchain, cppcheck_cmd,
|
switches |
0:0e018d759a2a
|
1287
|
cppcheck_msg_format, verbose=False,
|
switches |
0:0e018d759a2a
|
1288
|
clean=False, macros=None, notify=None, jobs=1,
|
switches |
0:0e018d759a2a
|
1289
|
extra_verbose=False, build_profile=None):
|
switches |
0:0e018d759a2a
|
1290
|
"""Perform static analysis on a library as if it were to be compiled for a
|
switches |
0:0e018d759a2a
|
1291
|
particular target and toolchain combination
|
switches |
0:0e018d759a2a
|
1292
|
"""
|
switches |
0:0e018d759a2a
|
1293
|
lib = Library(lib_id)
|
switches |
0:0e018d759a2a
|
1294
|
if lib.is_supported(target, toolchain):
|
switches |
0:0e018d759a2a
|
1295
|
static_analysis_scan_library(
|
switches |
0:0e018d759a2a
|
1296
|
lib.source_dir, lib.build_dir, target, toolchain, cppcheck_cmd,
|
switches |
0:0e018d759a2a
|
1297
|
cppcheck_msg_format, lib.dependencies, verbose=verbose,
|
switches |
0:0e018d759a2a
|
1298
|
clean=clean, macros=macros, notify=notify, jobs=jobs,
|
switches |
0:0e018d759a2a
|
1299
|
extra_verbose=extra_verbose, build_profile=build_profile)
|
switches |
0:0e018d759a2a
|
1300
|
else:
|
switches |
0:0e018d759a2a
|
1301
|
print('Library "%s" is not yet supported on target %s with toolchain %s'
|
switches |
0:0e018d759a2a
|
1302
|
% (lib_id, target.name, toolchain))
|
switches |
0:0e018d759a2a
|
1303
|
|
switches |
0:0e018d759a2a
|
1304
|
|
switches |
0:0e018d759a2a
|
1305
|
def static_analysis_scan_library(src_paths, build_path, target, toolchain_name,
|
switches |
0:0e018d759a2a
|
1306
|
cppcheck_cmd, cppcheck_msg_format,
|
switches |
0:0e018d759a2a
|
1307
|
dependencies_paths=None,
|
switches |
0:0e018d759a2a
|
1308
|
name=None, clean=False, notify=None,
|
switches |
0:0e018d759a2a
|
1309
|
verbose=False, macros=None, jobs=1,
|
switches |
0:0e018d759a2a
|
1310
|
extra_verbose=False, build_profile=None):
|
switches |
0:0e018d759a2a
|
1311
|
""" Function scans library for statically detectable defects
|
switches |
0:0e018d759a2a
|
1312
|
|
switches |
0:0e018d759a2a
|
1313
|
Positional arguments:
|
switches |
0:0e018d759a2a
|
1314
|
src_paths - the list of library paths to scan
|
switches |
0:0e018d759a2a
|
1315
|
build_path - the location directory of result files
|
switches |
0:0e018d759a2a
|
1316
|
target - the target to fake the build for
|
switches |
0:0e018d759a2a
|
1317
|
toolchain_name - pretend you would compile with this toolchain
|
switches |
0:0e018d759a2a
|
1318
|
cppcheck_cmd - the command used to do static analysis
|
switches |
0:0e018d759a2a
|
1319
|
cppcheck_msg_format - the format of the check messages
|
switches |
0:0e018d759a2a
|
1320
|
|
switches |
0:0e018d759a2a
|
1321
|
Keyword arguments:
|
switches |
0:0e018d759a2a
|
1322
|
dependencies_paths - the paths to sources that this library depends on
|
switches |
0:0e018d759a2a
|
1323
|
name - the name of this library
|
switches |
0:0e018d759a2a
|
1324
|
clean - start from a clean slate
|
switches |
0:0e018d759a2a
|
1325
|
notify - the notification event handling function
|
switches |
0:0e018d759a2a
|
1326
|
verbose - more printing!
|
switches |
0:0e018d759a2a
|
1327
|
macros - extra macros to compile with
|
switches |
0:0e018d759a2a
|
1328
|
jobs - number of commands to run at once
|
switches |
0:0e018d759a2a
|
1329
|
extra_verbose - even moar printing
|
switches |
0:0e018d759a2a
|
1330
|
build_profile - a dict of flags that will be passed to the compiler
|
switches |
0:0e018d759a2a
|
1331
|
"""
|
switches |
0:0e018d759a2a
|
1332
|
if type(src_paths) != ListType:
|
switches |
0:0e018d759a2a
|
1333
|
src_paths = [src_paths]
|
switches |
0:0e018d759a2a
|
1334
|
|
switches |
0:0e018d759a2a
|
1335
|
for src_path in src_paths:
|
switches |
0:0e018d759a2a
|
1336
|
if not exists(src_path):
|
switches |
0:0e018d759a2a
|
1337
|
raise Exception("The library source folder does not exist: %s",
|
switches |
0:0e018d759a2a
|
1338
|
src_path)
|
switches |
0:0e018d759a2a
|
1339
|
|
switches |
0:0e018d759a2a
|
1340
|
# Toolchain instance
|
switches |
0:0e018d759a2a
|
1341
|
toolchain = TOOLCHAIN_CLASSES[toolchain_name](target, macros=macros,
|
switches |
0:0e018d759a2a
|
1342
|
notify=notify,
|
switches |
0:0e018d759a2a
|
1343
|
extra_verbose=extra_verbose,
|
switches |
0:0e018d759a2a
|
1344
|
build_profile=build_profile)
|
switches |
0:0e018d759a2a
|
1345
|
toolchain.VERBOSE = verbose
|
switches |
0:0e018d759a2a
|
1346
|
toolchain.jobs = jobs
|
switches |
0:0e018d759a2a
|
1347
|
|
switches |
0:0e018d759a2a
|
1348
|
# The first path will give the name to the library
|
switches |
0:0e018d759a2a
|
1349
|
name = basename(src_paths[0])
|
switches |
0:0e018d759a2a
|
1350
|
toolchain.info("Static analysis for library %s (%s, %s)" %
|
switches |
0:0e018d759a2a
|
1351
|
(name.upper(), target.name, toolchain_name))
|
switches |
0:0e018d759a2a
|
1352
|
|
switches |
0:0e018d759a2a
|
1353
|
# Scan Resources
|
switches |
0:0e018d759a2a
|
1354
|
resources = []
|
switches |
0:0e018d759a2a
|
1355
|
for src_path in src_paths:
|
switches |
0:0e018d759a2a
|
1356
|
resources.append(toolchain.scan_resources(src_path))
|
switches |
0:0e018d759a2a
|
1357
|
|
switches |
0:0e018d759a2a
|
1358
|
# Dependencies Include Paths
|
switches |
0:0e018d759a2a
|
1359
|
dependencies_include_dir = []
|
switches |
0:0e018d759a2a
|
1360
|
if dependencies_paths is not None:
|
switches |
0:0e018d759a2a
|
1361
|
for path in dependencies_paths:
|
switches |
0:0e018d759a2a
|
1362
|
lib_resources = toolchain.scan_resources(path)
|
switches |
0:0e018d759a2a
|
1363
|
dependencies_include_dir.extend(lib_resources.inc_dirs)
|
switches |
0:0e018d759a2a
|
1364
|
|
switches |
0:0e018d759a2a
|
1365
|
# Create the desired build directory structure
|
switches |
0:0e018d759a2a
|
1366
|
bin_path = join(build_path, toolchain.obj_path)
|
switches |
0:0e018d759a2a
|
1367
|
mkdir(bin_path)
|
switches |
0:0e018d759a2a
|
1368
|
tmp_path = join(build_path, '.temp', toolchain.obj_path)
|
switches |
0:0e018d759a2a
|
1369
|
mkdir(tmp_path)
|
switches |
0:0e018d759a2a
|
1370
|
|
switches |
0:0e018d759a2a
|
1371
|
# Gather include paths, c, cpp sources and macros to transfer to cppcheck
|
switches |
0:0e018d759a2a
|
1372
|
# command line
|
switches |
0:0e018d759a2a
|
1373
|
includes = ["-I%s" % i for i in dependencies_include_dir + src_paths]
|
switches |
0:0e018d759a2a
|
1374
|
c_sources = " "
|
switches |
0:0e018d759a2a
|
1375
|
cpp_sources = " "
|
switches |
0:0e018d759a2a
|
1376
|
macros = ['-D%s' % s for s in toolchain.get_symbols() + toolchain.macros]
|
switches |
0:0e018d759a2a
|
1377
|
|
switches |
0:0e018d759a2a
|
1378
|
# Copy Headers
|
switches |
0:0e018d759a2a
|
1379
|
for resource in resources:
|
switches |
0:0e018d759a2a
|
1380
|
toolchain.copy_files(resource.headers, build_path, resources=resource)
|
switches |
0:0e018d759a2a
|
1381
|
includes += ["-I%s" % i for i in resource.inc_dirs]
|
switches |
0:0e018d759a2a
|
1382
|
c_sources += " ".join(resource.c_sources) + " "
|
switches |
0:0e018d759a2a
|
1383
|
cpp_sources += " ".join(resource.cpp_sources) + " "
|
switches |
0:0e018d759a2a
|
1384
|
|
switches |
0:0e018d759a2a
|
1385
|
dependencies_include_dir.extend(
|
switches |
0:0e018d759a2a
|
1386
|
toolchain.scan_resources(build_path).inc_dirs)
|
switches |
0:0e018d759a2a
|
1387
|
|
switches |
0:0e018d759a2a
|
1388
|
includes = [inc.strip() for inc in includes]
|
switches |
0:0e018d759a2a
|
1389
|
macros = [mac.strip() for mac in macros]
|
switches |
0:0e018d759a2a
|
1390
|
|
switches |
0:0e018d759a2a
|
1391
|
check_cmd = cppcheck_cmd
|
switches |
0:0e018d759a2a
|
1392
|
check_cmd += cppcheck_msg_format
|
switches |
0:0e018d759a2a
|
1393
|
check_cmd += includes
|
switches |
0:0e018d759a2a
|
1394
|
check_cmd += macros
|
switches |
0:0e018d759a2a
|
1395
|
|
switches |
0:0e018d759a2a
|
1396
|
# We need to pass some parameters via file to avoid "command line too long
|
switches |
0:0e018d759a2a
|
1397
|
# in some OSs". A temporary file is created to store e.g. cppcheck list of
|
switches |
0:0e018d759a2a
|
1398
|
# files for command line
|
switches |
0:0e018d759a2a
|
1399
|
tmp_file = tempfile.NamedTemporaryFile(delete=False)
|
switches |
0:0e018d759a2a
|
1400
|
tmp_file.writelines(line + '\n' for line in c_sources.split())
|
switches |
0:0e018d759a2a
|
1401
|
tmp_file.writelines(line + '\n' for line in cpp_sources.split())
|
switches |
0:0e018d759a2a
|
1402
|
tmp_file.close()
|
switches |
0:0e018d759a2a
|
1403
|
check_cmd += ["--file-list=%s"% tmp_file.name]
|
switches |
0:0e018d759a2a
|
1404
|
|
switches |
0:0e018d759a2a
|
1405
|
# This will allow us to grab result from both stdio and stderr outputs (so
|
switches |
0:0e018d759a2a
|
1406
|
# we can show them) We assume static code analysis tool is outputting
|
switches |
0:0e018d759a2a
|
1407
|
# defects on STDERR
|
switches |
0:0e018d759a2a
|
1408
|
_stdout, _stderr, _ = run_cmd_ext(check_cmd)
|
switches |
0:0e018d759a2a
|
1409
|
if verbose:
|
switches |
0:0e018d759a2a
|
1410
|
print _stdout
|
switches |
0:0e018d759a2a
|
1411
|
print _stderr
|
switches |
0:0e018d759a2a
|
1412
|
|
switches |
0:0e018d759a2a
|
1413
|
|
switches |
0:0e018d759a2a
|
1414
|
def print_build_results(result_list, build_name):
|
switches |
0:0e018d759a2a
|
1415
|
""" Generate result string for build results
|
switches |
0:0e018d759a2a
|
1416
|
|
switches |
0:0e018d759a2a
|
1417
|
Positional arguments:
|
switches |
0:0e018d759a2a
|
1418
|
result_list - the list of results to print
|
switches |
0:0e018d759a2a
|
1419
|
build_name - the name of the build we are printing result for
|
switches |
0:0e018d759a2a
|
1420
|
"""
|
switches |
0:0e018d759a2a
|
1421
|
result = ""
|
switches |
0:0e018d759a2a
|
1422
|
if len(result_list) > 0:
|
switches |
0:0e018d759a2a
|
1423
|
result += build_name + "\n"
|
switches |
0:0e018d759a2a
|
1424
|
result += "\n".join([" * %s" % f for f in result_list])
|
switches |
0:0e018d759a2a
|
1425
|
result += "\n"
|
switches |
0:0e018d759a2a
|
1426
|
return result
|
switches |
0:0e018d759a2a
|
1427
|
|
switches |
0:0e018d759a2a
|
1428
|
def print_build_memory_usage(report):
|
switches |
0:0e018d759a2a
|
1429
|
""" Generate result table with memory usage values for build results
|
switches |
0:0e018d759a2a
|
1430
|
Aggregates (puts together) reports obtained from self.get_memory_summary()
|
switches |
0:0e018d759a2a
|
1431
|
|
switches |
0:0e018d759a2a
|
1432
|
Positional arguments:
|
switches |
0:0e018d759a2a
|
1433
|
report - Report generated during build procedure.
|
switches |
0:0e018d759a2a
|
1434
|
"""
|
switches |
0:0e018d759a2a
|
1435
|
from prettytable import PrettyTable
|
switches |
0:0e018d759a2a
|
1436
|
columns_text = ['name', 'target', 'toolchain']
|
switches |
0:0e018d759a2a
|
1437
|
columns_int = ['static_ram', 'stack', 'heap', 'total_ram', 'total_flash']
|
switches |
0:0e018d759a2a
|
1438
|
table = PrettyTable(columns_text + columns_int)
|
switches |
0:0e018d759a2a
|
1439
|
|
switches |
0:0e018d759a2a
|
1440
|
for col in columns_text:
|
switches |
0:0e018d759a2a
|
1441
|
table.align[col] = 'l'
|
switches |
0:0e018d759a2a
|
1442
|
|
switches |
0:0e018d759a2a
|
1443
|
for col in columns_int:
|
switches |
0:0e018d759a2a
|
1444
|
table.align[col] = 'r'
|
switches |
0:0e018d759a2a
|
1445
|
|
switches |
0:0e018d759a2a
|
1446
|
for target in report:
|
switches |
0:0e018d759a2a
|
1447
|
for toolchain in report[target]:
|
switches |
0:0e018d759a2a
|
1448
|
for name in report[target][toolchain]:
|
switches |
0:0e018d759a2a
|
1449
|
for dlist in report[target][toolchain][name]:
|
switches |
0:0e018d759a2a
|
1450
|
for dlistelem in dlist:
|
switches |
0:0e018d759a2a
|
1451
|
# Get 'memory_usage' record and build table with
|
switches |
0:0e018d759a2a
|
1452
|
# statistics
|
switches |
0:0e018d759a2a
|
1453
|
record = dlist[dlistelem]
|
switches |
0:0e018d759a2a
|
1454
|
if 'memory_usage' in record and record['memory_usage']:
|
switches |
0:0e018d759a2a
|
1455
|
# Note that summary should be in the last record of
|
switches |
0:0e018d759a2a
|
1456
|
# 'memory_usage' section. This is why we are
|
switches |
0:0e018d759a2a
|
1457
|
# grabbing last "[-1]" record.
|
switches |
0:0e018d759a2a
|
1458
|
row = [
|
switches |
0:0e018d759a2a
|
1459
|
record['description'],
|
switches |
0:0e018d759a2a
|
1460
|
record['target_name'],
|
switches |
0:0e018d759a2a
|
1461
|
record['toolchain_name'],
|
switches |
0:0e018d759a2a
|
1462
|
record['memory_usage'][-1]['summary'][
|
switches |
0:0e018d759a2a
|
1463
|
'static_ram'],
|
switches |
0:0e018d759a2a
|
1464
|
record['memory_usage'][-1]['summary']['stack'],
|
switches |
0:0e018d759a2a
|
1465
|
record['memory_usage'][-1]['summary']['heap'],
|
switches |
0:0e018d759a2a
|
1466
|
record['memory_usage'][-1]['summary'][
|
switches |
0:0e018d759a2a
|
1467
|
'total_ram'],
|
switches |
0:0e018d759a2a
|
1468
|
record['memory_usage'][-1]['summary'][
|
switches |
0:0e018d759a2a
|
1469
|
'total_flash'],
|
switches |
0:0e018d759a2a
|
1470
|
]
|
switches |
0:0e018d759a2a
|
1471
|
table.add_row(row)
|
switches |
0:0e018d759a2a
|
1472
|
|
switches |
0:0e018d759a2a
|
1473
|
result = "Memory map breakdown for built projects (values in Bytes):\n"
|
switches |
0:0e018d759a2a
|
1474
|
result += table.get_string(sortby='name')
|
switches |
0:0e018d759a2a
|
1475
|
return result
|
switches |
0:0e018d759a2a
|
1476
|
|
switches |
0:0e018d759a2a
|
1477
|
def write_build_report(build_report, template_filename, filename):
|
switches |
0:0e018d759a2a
|
1478
|
"""Write a build report to disk using a template file
|
switches |
0:0e018d759a2a
|
1479
|
|
switches |
0:0e018d759a2a
|
1480
|
Positional arguments:
|
switches |
0:0e018d759a2a
|
1481
|
build_report - a report generated by the build system
|
switches |
0:0e018d759a2a
|
1482
|
template_filename - a file that contains the template for the style of build
|
switches |
0:0e018d759a2a
|
1483
|
report
|
switches |
0:0e018d759a2a
|
1484
|
filename - the location on disk to write the file to
|
switches |
0:0e018d759a2a
|
1485
|
"""
|
switches |
0:0e018d759a2a
|
1486
|
build_report_failing = []
|
switches |
0:0e018d759a2a
|
1487
|
build_report_passing = []
|
switches |
0:0e018d759a2a
|
1488
|
|
switches |
0:0e018d759a2a
|
1489
|
for report in build_report:
|
switches |
0:0e018d759a2a
|
1490
|
if len(report["failing"]) > 0:
|
switches |
0:0e018d759a2a
|
1491
|
build_report_failing.append(report)
|
switches |
0:0e018d759a2a
|
1492
|
else:
|
switches |
0:0e018d759a2a
|
1493
|
build_report_passing.append(report)
|
switches |
0:0e018d759a2a
|
1494
|
|
switches |
0:0e018d759a2a
|
1495
|
env = Environment(extensions=['jinja2.ext.with_'])
|
switches |
0:0e018d759a2a
|
1496
|
env.loader = FileSystemLoader('ci_templates')
|
switches |
0:0e018d759a2a
|
1497
|
template = env.get_template(template_filename)
|
switches |
0:0e018d759a2a
|
1498
|
|
switches |
0:0e018d759a2a
|
1499
|
with open(filename, 'w+') as placeholder:
|
switches |
0:0e018d759a2a
|
1500
|
placeholder.write(template.render(
|
switches |
0:0e018d759a2a
|
1501
|
failing_builds=build_report_failing,
|
switches |
0:0e018d759a2a
|
1502
|
passing_builds=build_report_passing))
|