forked from ARMmbed/mbed-os
-
Notifications
You must be signed in to change notification settings - Fork 1
/
build_everything.py
239 lines (189 loc) · 10.5 KB
/
build_everything.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
#! /usr/bin/env python
"""
mbed SDK
Copyright (c) 2011-2013 ARM Limited
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
import sys
from time import time
from os.path import join, abspath, dirname, normpath
from optparse import OptionParser
import json
# Be sure that the tools directory is in the search path
ROOT = abspath(join(dirname(__file__), ".."))
sys.path.insert(0, ROOT)
from tools.build_api import build_library
from tools.build_api import write_build_report
from tools.targets import TARGET_MAP, TARGET_NAMES
from tools.toolchains import TOOLCHAINS
from tools.test_exporters import ReportExporter, ResultExporterType
from tools.test_api import find_tests, build_tests, test_spec_from_test_builds
from tools.build_release import OFFICIAL_MBED_LIBRARY_BUILD
if __name__ == '__main__':
try:
parser = OptionParser()
parser.add_option("--source", dest="source_dir",
default=None, help="The source (input) directory (for sources other than tests). Defaults to current directory.", action="append")
parser.add_option("--build", dest="build_dir",
default=None, help="The build (output) directory")
parser.add_option('-c', '--clean',
dest='clean',
metavar=False,
action="store_true",
help='Clean the build directory')
parser.add_option('-a', '--all', dest="all", default=False, action="store_true",
help="Build every target (including unofficial targets) and with each of the supported toolchains")
parser.add_option('-o', '--official', dest="official_only", default=False, action="store_true",
help="Build using only the official toolchain for each target")
parser.add_option("-D", "",
action="append",
dest="macros",
help="Add a macro definition")
parser.add_option("-j", "--jobs", type="int", dest="jobs",
default=0, help="Number of concurrent jobs. Default: 0/auto (based on host machine's number of CPUs)")
parser.add_option("-v", "--verbose", action="store_true", dest="verbose",
default=False, help="Verbose diagnostic output")
parser.add_option("-t", "--toolchains", dest="toolchains", help="Use toolchains names separated by comma")
parser.add_option("-p", "--platforms", dest="platforms", default="", help="Build only for the platform namesseparated by comma")
parser.add_option("", "--config", action="store_true", dest="list_config",
default=False, help="List the platforms and toolchains in the release in JSON")
parser.add_option("", "--test-spec", dest="test_spec",
default=None, help="Destination path for a test spec file that can be used by the Greentea automated test tool")
parser.add_option("", "--build-report-junit", dest="build_report_junit", help="Output the build results to an junit xml file")
parser.add_option("--continue-on-build-fail", action="store_true", dest="continue_on_build_fail",
default=False, help="Continue trying to build all tests if a build failure occurs")
options, args = parser.parse_args()
# Get set of valid targets
all_platforms = set(TARGET_NAMES)
bad_platforms = set()
platforms = set()
if options.platforms != "":
platforms = set(options.platforms.split(","))
bad_platforms = platforms.difference(all_platforms)
platforms = platforms.intersection(all_platforms)
elif options.all:
platforms = all_platforms
else:
platforms = set(x[0] for x in OFFICIAL_MBED_LIBRARY_BUILD)
bad_platforms = platforms.difference(all_platforms)
platforms = platforms.intersection(all_platforms)
for bad_platform in bad_platforms:
print "Platform '%s' is not a valid platform. Skipping." % bad_platform
if options.platforms:
print "Limiting build to the following platforms: %s" % ",".join(platforms)
# Get set of valid toolchains
all_toolchains = set(TOOLCHAINS)
bad_toolchains = set()
toolchains = set()
if options.toolchains:
toolchains = set(options.toolchains.split(","))
bad_toolchains = toolchains.difference(all_toolchains)
toolchains = toolchains.intersection(all_toolchains)
else:
toolchains = all_toolchains
for bad_toolchain in bad_toolchains:
print "Toolchain '%s' is not a valid toolchain. Skipping." % bad_toolchain
if options.toolchains:
print "Limiting build to the following toolchains: %s" % ",".join(toolchains)
build_config = {}
for platform in platforms:
target = TARGET_MAP[platform]
if options.official_only:
default_toolchain = getattr(target, 'default_toolchain', 'ARM')
build_config[platform] = list(toolchains.intersection(set([default_toolchain])))
else:
build_config[platform] = list(toolchains.intersection(set(target.supported_toolchains)))
if options.list_config:
print json.dumps(build_config, indent=4)
sys.exit(0)
# Ensure build directory is set
if not options.build_dir:
print "[ERROR] You must specify a build path"
sys.exit(1)
# Default base source path is the current directory
base_source_paths = options.source_dir
if not base_source_paths:
base_source_paths = ['.']
start = time()
build_report = {}
build_properties = {}
test_builds = {}
total_build_success = True
for target_name, target_toolchains in build_config.iteritems():
target = TARGET_MAP[target_name]
for target_toolchain in target_toolchains:
library_build_success = True
try:
build_directory = join(options.build_dir, target_name, target_toolchain)
# Build sources
build_library(base_source_paths, build_directory, target, target_toolchain,
jobs=options.jobs,
clean=options.clean,
report=build_report,
properties=build_properties,
name="mbed-os",
macros=options.macros,
verbose=options.verbose,
archive=False)
except Exception, e:
library_build_success = False
print "Failed to build library"
print e
if options.continue_on_build_fail or library_build_success:
# Build all the tests
all_tests = find_tests(base_source_paths[0], target_name, toolchain_name)
test_build_success, test_build = build_tests(all_tests, [build_directory], build_directory, target, target_toolchain,
clean=options.clean,
report=build_report,
properties=build_properties,
macros=options.macros,
verbose=options.verbose,
jobs=options.jobs,
continue_on_build_fail=options.continue_on_build_fail)
if not test_build_success:
total_build_success = False
print "Failed to build some tests, check build log for details"
test_builds.update(test_build)
else:
total_build_success = False
break
# If a path to a test spec is provided, write it to a file
if options.test_spec:
test_spec_data = test_spec_from_test_builds(test_builds)
# Create the target dir for the test spec if necessary
# mkdir will not create the dir if it already exists
test_spec_dir = dirname(options.test_spec)
if test_spec_dir:
mkdir(test_spec_dir)
try:
with open(options.test_spec, 'w') as f:
f.write(json.dumps(test_spec_data, indent=2))
except IOError, e:
print "[ERROR] Error writing test spec to file"
print e
# If a path to a JUnit build report spec is provided, write it to a file
if options.build_report_junit:
report_exporter = ReportExporter(ResultExporterType.JUNIT)
report_exporter.report_to_file(build_report, options.build_report_junit, test_suite_properties=build_properties)
print "\n\nCompleted in: (%.2f)s" % (time() - start)
print_report_exporter = ReportExporter(ResultExporterType.PRINT, package="build")
status = print_report_exporter.report(build_report)
if status:
sys.exit(0)
else:
sys.exit(1)
except KeyboardInterrupt, e:
print "\n[CTRL+c] exit"
except Exception,e:
import traceback
traceback.print_exc(file=sys.stdout)
print "[ERROR] %s" % str(e)
sys.exit(1)