blob: 80f9315a11e426086ed24d2df59331eb10bc84e0 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001# SPDX-License-Identifier: GPL-2.0+
Simon Glassc05694f2013-04-03 11:07:16 +00002# Copyright (c) 2013 The Chromium OS Authors.
3#
Simon Glassc05694f2013-04-03 11:07:16 +00004
Simon Glassc1e1e1d2023-07-19 17:48:30 -06005"""Control module for buildman
6
7This holds the main control logic for buildman, when not running tests.
8"""
9
Simon Glassc05694f2013-04-03 11:07:16 +000010import multiprocessing
11import os
Simon Glassa10ebe12014-09-05 19:00:18 -060012import shutil
Simon Glassc05694f2013-04-03 11:07:16 +000013import sys
14
Simon Glass20751d62022-07-11 19:04:03 -060015from buildman import boards
Simon Glassf0d9c102020-04-17 18:09:02 -060016from buildman import bsettings
Simon Glasse5650a82022-01-22 05:07:33 -070017from buildman import cfgutil
Simon Glassf0d9c102020-04-17 18:09:02 -060018from buildman import toolchain
19from buildman.builder import Builder
Simon Glassa997ea52020-04-17 18:09:04 -060020from patman import gitutil
21from patman import patchstream
Simon Glass131444f2023-02-23 18:18:04 -070022from u_boot_pylib import command
23from u_boot_pylib import terminal
Simon Glass131444f2023-02-23 18:18:04 -070024from u_boot_pylib.terminal import tprint
Simon Glassc05694f2013-04-03 11:07:16 +000025
Simon Glassaf0e29f2023-07-19 17:48:31 -060026TEST_BUILDER = None
27
Simon Glassc1e1e1d2023-07-19 17:48:30 -060028def get_plural(count):
Simon Glassc05694f2013-04-03 11:07:16 +000029 """Returns a plural 's' if count is not 1"""
30 return 's' if count != 1 else ''
31
Simon Glassc1e1e1d2023-07-19 17:48:30 -060032def get_action_summary(is_summary, commits, selected, options):
Simon Glassc05694f2013-04-03 11:07:16 +000033 """Return a string summarising the intended action.
34
35 Returns:
36 Summary string.
37 """
Simon Glassd326ad72014-08-09 15:32:59 -060038 if commits:
39 count = len(commits)
Simon Glassc78ed662019-10-31 07:42:53 -060040 count = (count + options.step - 1) // options.step
Simon Glassaf0e29f2023-07-19 17:48:31 -060041 commit_str = f'{count} commit{get_plural(count)}'
Simon Glassd326ad72014-08-09 15:32:59 -060042 else:
43 commit_str = 'current source'
Simon Glassaf0e29f2023-07-19 17:48:31 -060044 msg = (f"{'Summary of' if is_summary else 'Building'} "
45 f'{commit_str} for {len(selected)} boards')
46 msg += (f' ({options.threads} thread{get_plural(options.threads)}, '
47 f'{options.jobs} job{get_plural(options.jobs)} per thread)')
48 return msg
Simon Glassc05694f2013-04-03 11:07:16 +000049
Simon Glassaf0e29f2023-07-19 17:48:31 -060050# pylint: disable=R0913
Simon Glassf83559c2023-07-19 17:48:36 -060051def show_actions(series, why_selected, boards_selected, output_dir, options,
Simon Glassc1e1e1d2023-07-19 17:48:30 -060052 board_warnings):
Simon Glassc05694f2013-04-03 11:07:16 +000053 """Display a list of actions that we would take, if not a dry run.
54
55 Args:
56 series: Series object
57 why_selected: Dictionary where each key is a buildman argument
Simon Glass6af145f2017-01-23 05:38:56 -070058 provided by the user, and the value is the list of boards
59 brought in by that argument. For example, 'arm' might bring
60 in 400 boards, so in this case the key would be 'arm' and
Simon Glassc05694f2013-04-03 11:07:16 +000061 the value would be a list of board names.
62 boards_selected: Dict of selected boards, key is target name,
63 value is Board object
Simon Glassf83559c2023-07-19 17:48:36 -060064 output_dir (str): Output directory for builder
Simon Glassc05694f2013-04-03 11:07:16 +000065 options: Command line options object
Simon Glassd9eb9f02018-06-11 23:26:46 -060066 board_warnings: List of warnings obtained from board selected
Simon Glassc05694f2013-04-03 11:07:16 +000067 """
68 col = terminal.Color()
Simon Glassc78ed662019-10-31 07:42:53 -060069 print('Dry run, so not doing much. But I would do this:')
70 print()
Simon Glassd326ad72014-08-09 15:32:59 -060071 if series:
72 commits = series.commits
73 else:
74 commits = None
Simon Glassc1e1e1d2023-07-19 17:48:30 -060075 print(get_action_summary(False, commits, boards_selected,
Simon Glassc78ed662019-10-31 07:42:53 -060076 options))
Simon Glassf83559c2023-07-19 17:48:36 -060077 print(f'Build directory: {output_dir}')
Simon Glassd326ad72014-08-09 15:32:59 -060078 if commits:
79 for upto in range(0, len(series.commits), options.step):
80 commit = series.commits[upto]
Simon Glassf45d3742022-01-29 14:14:17 -070081 print(' ', col.build(col.YELLOW, commit.hash[:8], bright=False), end=' ')
Simon Glassc78ed662019-10-31 07:42:53 -060082 print(commit.subject)
83 print()
Simon Glassc05694f2013-04-03 11:07:16 +000084 for arg in why_selected:
85 if arg != 'all':
Simon Glassaf0e29f2023-07-19 17:48:31 -060086 print(arg, f': {len(why_selected[arg])} boards')
Simon Glass6af145f2017-01-23 05:38:56 -070087 if options.verbose:
Simon Glassaf0e29f2023-07-19 17:48:31 -060088 print(f" {' '.join(why_selected[arg])}")
89 print('Total boards to build for each '
90 f"commit: {len(why_selected['all'])}\n")
Simon Glassd9eb9f02018-06-11 23:26:46 -060091 if board_warnings:
92 for warning in board_warnings:
Simon Glassf45d3742022-01-29 14:14:17 -070093 print(col.build(col.YELLOW, warning))
Simon Glassc05694f2013-04-03 11:07:16 +000094
Simon Glassc1e1e1d2023-07-19 17:48:30 -060095def show_toolchain_prefix(brds, toolchains):
Simon Glass48ac42e2019-12-05 15:59:14 -070096 """Show information about a the tool chain used by one or more boards
97
Simon Glass2df44be2020-03-18 09:42:47 -060098 The function checks that all boards use the same toolchain, then prints
99 the correct value for CROSS_COMPILE.
Simon Glass48ac42e2019-12-05 15:59:14 -0700100
101 Args:
102 boards: Boards object containing selected boards
103 toolchains: Toolchains object containing available toolchains
Simon Glass48ac42e2019-12-05 15:59:14 -0700104
105 Return:
106 None on success, string error message otherwise
107 """
Simon Glass127a2392022-07-11 19:04:02 -0600108 board_selected = brds.get_selected_dict()
Simon Glass48ac42e2019-12-05 15:59:14 -0700109 tc_set = set()
Simon Glass5df45222022-07-11 19:04:00 -0600110 for brd in board_selected.values():
Simon Glass48ac42e2019-12-05 15:59:14 -0700111 tc_set.add(toolchains.Select(brd.arch))
112 if len(tc_set) != 1:
113 return 'Supplied boards must share one toolchain'
Simon Glassaf0e29f2023-07-19 17:48:31 -0600114 tchain = tc_set.pop()
115 print(tchain.GetEnvArgs(toolchain.VAR_CROSS_COMPILE))
Simon Glass48ac42e2019-12-05 15:59:14 -0700116 return None
117
Tom Rini93ebd462022-11-09 19:14:53 -0700118def get_allow_missing(opt_allow, opt_no_allow, num_selected, has_branch):
Simon Glassaf0e29f2023-07-19 17:48:31 -0600119 """Figure out whether to allow external blobs
120
121 Uses the allow-missing setting and the provided arguments to decide whether
122 missing external blobs should be allowed
123
124 Args:
125 opt_allow (bool): True if --allow-missing flag is set
126 opt_no_allow (bool): True if --no-allow-missing flag is set
127 num_selected (int): Number of selected board
128 has_branch (bool): True if a git branch (to build) has been provided
129
130 Returns:
131 bool: True to allow missing external blobs, False to produce an error if
132 external blobs are used
133 """
Tom Rini93ebd462022-11-09 19:14:53 -0700134 allow_missing = False
135 am_setting = bsettings.GetGlobalItemValue('allow-missing')
136 if am_setting:
137 if am_setting == 'always':
138 allow_missing = True
139 if 'multiple' in am_setting and num_selected > 1:
140 allow_missing = True
141 if 'branch' in am_setting and has_branch:
142 allow_missing = True
143
144 if opt_allow:
145 allow_missing = True
146 if opt_no_allow:
147 allow_missing = False
148 return allow_missing
149
Simon Glass2183b842023-07-19 17:48:33 -0600150
151def determine_series(count, has_range, branch, git_dir):
152 """Determine the series which is to be built, if any
153
154 Args:
155 count (int): Number of commits in branch
156 has_range (bool): True if a range of commits ('xx..yy') is being built
157 branch (str): Name of branch to build, or None if none
158 git_dir (str): Git directory to use, e.g. './.git'
159
160 Returns:
161 Series: Series to build, or None for none
162
163 Read the metadata from the commits. First look at the upstream commit,
164 then the ones in the branch. We would like to do something like
165 upstream/master~..branch but that isn't possible if upstream/master is
166 a merge commit (it will list all the commits that form part of the
167 merge)
168
169 Conflicting tags are not a problem for buildman, since it does not use
170 them. For example, Series-version is not useful for buildman. On the
171 other hand conflicting tags will cause an error. So allow later tags
172 to overwrite earlier ones by setting allow_overwrite=True
173 """
174 if branch:
175 if count == -1:
176 if has_range:
177 range_expr = branch
178 else:
179 range_expr = gitutil.get_range_in_branch(git_dir, branch)
180 upstream_commit = gitutil.get_upstream(git_dir, branch)
181 series = patchstream.get_metadata_for_list(upstream_commit,
182 git_dir, 1, series=None, allow_overwrite=True)
183
184 series = patchstream.get_metadata_for_list(range_expr,
185 git_dir, None, series, allow_overwrite=True)
186 else:
187 # Honour the count
188 series = patchstream.get_metadata_for_list(branch,
189 git_dir, count, series=None, allow_overwrite=True)
190 else:
191 series = None
192 return series
193
194
Simon Glass6c4beca2023-07-19 17:48:34 -0600195def do_fetch_arch(toolchains, col, fetch_arch):
196 """Handle the --fetch-arch option
197
198 Args:
199 toolchains (Toolchains): Tool chains to use
200 col (terminal.Color): Color object to build
201 fetch_arch (str): Argument passed to the --fetch-arch option
202
203 Returns:
204 int: Return code for buildman
205 """
206 if fetch_arch == 'list':
207 sorted_list = toolchains.ListArchs()
208 print(col.build(
209 col.BLUE,
210 f"Available architectures: {' '.join(sorted_list)}\n"))
211 return 0
212
213 if fetch_arch == 'all':
214 fetch_arch = ','.join(toolchains.ListArchs())
215 print(col.build(col.CYAN,
216 f'\nDownloading toolchains: {fetch_arch}'))
217 for arch in fetch_arch.split(','):
218 print()
219 ret = toolchains.FetchAndInstall(arch)
220 if ret:
221 return ret
222 return 0
223
224
Simon Glassc1e1e1d2023-07-19 17:48:30 -0600225def do_buildman(options, args, toolchains=None, make_func=None, brds=None,
226 clean_dir=False, test_thread_exceptions=False):
Simon Glassc05694f2013-04-03 11:07:16 +0000227 """The main control code for buildman
228
229 Args:
230 options: Command line options object
231 args: Command line arguments (list of strings)
Simon Glassed098bb2014-09-05 19:00:13 -0600232 toolchains: Toolchains to use - this should be a Toolchains()
233 object. If None, then it will be created and scanned
234 make_func: Make function to use for the builder. This is called
235 to execute 'make'. If this is None, the normal function
236 will be used, which calls the 'make' tool with suitable
237 arguments. This setting is useful for tests.
Simon Glass5df45222022-07-11 19:04:00 -0600238 brds: Boards() object to use, containing a list of available
Simon Glasscbd36582014-09-05 19:00:16 -0600239 boards. If this is None it will be created and scanned.
Simon Glassa29b3ea2021-04-11 16:27:25 +1200240 clean_dir: Used for tests only, indicates that the existing output_dir
241 should be removed before starting the build
Simon Glass9bf9a722021-04-11 16:27:27 +1200242 test_thread_exceptions: Uses for tests only, True to make the threads
243 raise an exception instead of reporting their result. This simulates
244 a failure in the code somewhere
Simon Glassc05694f2013-04-03 11:07:16 +0000245 """
Simon Glassaf0e29f2023-07-19 17:48:31 -0600246 # Used so testing can obtain the builder: pylint: disable=W0603
247 global TEST_BUILDER
Simon Glassa10ebe12014-09-05 19:00:18 -0600248
Simon Glass761648b2022-01-29 14:14:11 -0700249 gitutil.setup()
Simon Glass9f1ba0f2016-07-27 20:33:02 -0600250 col = terminal.Color()
Simon Glassc05694f2013-04-03 11:07:16 +0000251
Simon Glass2183b842023-07-19 17:48:33 -0600252 git_dir = os.path.join(options.git, '.git')
Simon Glassc05694f2013-04-03 11:07:16 +0000253
Simon Glassa3d9b4f2016-07-27 20:33:04 -0600254 no_toolchains = toolchains is None
255 if no_toolchains:
Simon Glassf77ca5b2019-01-07 16:44:20 -0700256 toolchains = toolchain.Toolchains(options.override_toolchain)
Simon Glassc05694f2013-04-03 11:07:16 +0000257
Simon Glass7e803e12014-12-01 17:34:06 -0700258 if options.fetch_arch:
Simon Glass6c4beca2023-07-19 17:48:34 -0600259 return do_fetch_arch(toolchains, col, options.fetch_arch)
Simon Glassaf0e29f2023-07-19 17:48:31 -0600260
Simon Glassa3d9b4f2016-07-27 20:33:04 -0600261 if no_toolchains:
262 toolchains.GetSettings()
Simon Glass74579fc2018-11-06 16:02:10 -0700263 toolchains.Scan(options.list_tool_chains and options.verbose)
Simon Glassa3d9b4f2016-07-27 20:33:04 -0600264 if options.list_tool_chains:
265 toolchains.List()
Simon Glassc78ed662019-10-31 07:42:53 -0600266 print()
Simon Glassa3d9b4f2016-07-27 20:33:04 -0600267 return 0
268
Simon Glassd9c98632020-04-17 17:51:32 -0600269 if not options.output_dir:
270 if options.work_in_output:
Simon Glassf45d3742022-01-29 14:14:17 -0700271 sys.exit(col.build(col.RED, '-w requires that you specify -o'))
Simon Glassd9c98632020-04-17 17:51:32 -0600272 options.output_dir = '..'
Simon Glass6029af12020-04-09 15:08:51 -0600273
Simon Glass5e728d42023-07-19 17:48:27 -0600274 nr_cups = options.threads or multiprocessing.cpu_count()
275
Simon Glassc05694f2013-04-03 11:07:16 +0000276 # Work out what subset of the boards we are building
Simon Glass5df45222022-07-11 19:04:00 -0600277 if not brds:
Tom Rini6ef6b3f2019-11-19 15:14:33 -0500278 if not os.path.exists(options.output_dir):
279 os.makedirs(options.output_dir)
Bin Meng0733e202019-10-28 07:24:59 -0700280 board_file = os.path.join(options.output_dir, 'boards.cfg')
Simon Glass09afcb72023-07-19 17:48:28 -0600281 if options.regen_board_list and options.regen_board_list != '-':
282 board_file = options.regen_board_list
Masahiro Yamadae9bc8d22014-07-30 14:08:22 +0900283
Simon Glass20751d62022-07-11 19:04:03 -0600284 brds = boards.Boards()
Simon Glassaf0e29f2023-07-19 17:48:31 -0600285
Simon Glass5e728d42023-07-19 17:48:27 -0600286 if options.maintainer_check:
287 warnings = brds.build_board_list(jobs=nr_cups)[1]
288 if warnings:
289 for warn in warnings:
290 print(warn, file=sys.stderr)
291 return 2
292 return 0
293
Simon Glassaf0e29f2023-07-19 17:48:31 -0600294 okay = brds.ensure_board_list(
295 board_file,
296 options.threads or multiprocessing.cpu_count(),
297 force=options.regen_board_list,
298 quiet=not options.verbose)
Simon Glass0c477b72022-07-11 19:04:04 -0600299 if options.regen_board_list:
Simon Glassaf0e29f2023-07-19 17:48:31 -0600300 return 0 if okay else 2
Simon Glass127a2392022-07-11 19:04:02 -0600301 brds.read_boards(board_file)
Simon Glass924c73a2014-08-28 09:43:41 -0600302
303 exclude = []
304 if options.exclude:
305 for arg in options.exclude:
306 exclude += arg.split(',')
307
Simon Glassd9eb9f02018-06-11 23:26:46 -0600308 if options.boards:
309 requested_boards = []
Simon Glassaf0e29f2023-07-19 17:48:31 -0600310 for brd in options.boards:
311 requested_boards += brd.split(',')
Simon Glassd9eb9f02018-06-11 23:26:46 -0600312 else:
313 requested_boards = None
Simon Glass127a2392022-07-11 19:04:02 -0600314 why_selected, board_warnings = brds.select_boards(args, exclude,
315 requested_boards)
316 selected = brds.get_selected()
Simon Glassaf0e29f2023-07-19 17:48:31 -0600317 if not selected:
Simon Glassf45d3742022-01-29 14:14:17 -0700318 sys.exit(col.build(col.RED, 'No matching boards found'))
Simon Glassc05694f2013-04-03 11:07:16 +0000319
Simon Glass2df44be2020-03-18 09:42:47 -0600320 if options.print_prefix:
Simon Glassc1e1e1d2023-07-19 17:48:30 -0600321 err = show_toolchain_prefix(brds, toolchains)
Simon Glass48ac42e2019-12-05 15:59:14 -0700322 if err:
Simon Glassf45d3742022-01-29 14:14:17 -0700323 sys.exit(col.build(col.RED, err))
Simon Glass48ac42e2019-12-05 15:59:14 -0700324 return 0
325
Simon Glass9b550912019-12-05 15:59:13 -0700326 # Work out how many commits to build. We want to build everything on the
327 # branch. We also build the upstream commit as a control so we can see
328 # problems introduced by the first commit on the branch.
329 count = options.count
330 has_range = options.branch and '..' in options.branch
331 if count == -1:
332 if not options.branch:
333 count = 1
334 else:
335 if has_range:
Simon Glass2183b842023-07-19 17:48:33 -0600336 count, msg = gitutil.count_commits_in_range(git_dir,
337 options.branch)
Simon Glass9b550912019-12-05 15:59:13 -0700338 else:
Simon Glass2183b842023-07-19 17:48:33 -0600339 count, msg = gitutil.count_commits_in_branch(git_dir,
340 options.branch)
Simon Glass9b550912019-12-05 15:59:13 -0700341 if count is None:
Simon Glassf45d3742022-01-29 14:14:17 -0700342 sys.exit(col.build(col.RED, msg))
Simon Glass9b550912019-12-05 15:59:13 -0700343 elif count == 0:
Simon Glassaf0e29f2023-07-19 17:48:31 -0600344 sys.exit(col.build(col.RED,
345 f"Range '{options.branch}' has no commits"))
Simon Glass9b550912019-12-05 15:59:13 -0700346 if msg:
Simon Glassf45d3742022-01-29 14:14:17 -0700347 print(col.build(col.YELLOW, msg))
Simon Glass9b550912019-12-05 15:59:13 -0700348 count += 1 # Build upstream commit also
349
350 if not count:
Simon Glassaf0e29f2023-07-19 17:48:31 -0600351 msg = (f"No commits found to process in branch '{options.branch}': "
352 "set branch's upstream or use -c flag")
Simon Glassba666eb2023-02-23 18:18:11 -0700353 sys.exit(col.build(col.RED, msg))
Simon Glassb6eb8cf2020-03-18 09:42:42 -0600354 if options.work_in_output:
355 if len(selected) != 1:
Simon Glassf45d3742022-01-29 14:14:17 -0700356 sys.exit(col.build(col.RED,
Simon Glassb6eb8cf2020-03-18 09:42:42 -0600357 '-w can only be used with a single board'))
358 if count != 1:
Simon Glassf45d3742022-01-29 14:14:17 -0700359 sys.exit(col.build(col.RED,
Simon Glassb6eb8cf2020-03-18 09:42:42 -0600360 '-w can only be used with a single commit'))
Simon Glass9b550912019-12-05 15:59:13 -0700361
Simon Glass2183b842023-07-19 17:48:33 -0600362 series = determine_series(count, has_range, options.branch, git_dir)
363 if not series and not options.dry_run:
364 options.verbose = True
365 if not options.summary:
366 options.show_errors = True
Simon Glassc05694f2013-04-03 11:07:16 +0000367
368 # By default we have one thread per CPU. But if there are not enough jobs
369 # we can have fewer threads and use a high '-j' value for make.
Simon Glassc635d892021-01-30 22:17:46 -0700370 if options.threads is None:
Simon Glassc05694f2013-04-03 11:07:16 +0000371 options.threads = min(multiprocessing.cpu_count(), len(selected))
372 if not options.jobs:
373 options.jobs = max(1, (multiprocessing.cpu_count() +
Simon Glassc78ed662019-10-31 07:42:53 -0600374 len(selected) - 1) // len(selected))
Simon Glassc05694f2013-04-03 11:07:16 +0000375
376 if not options.step:
377 options.step = len(series.commits) - 1
378
Simon Glass840be732022-01-29 14:14:05 -0700379 gnu_make = command.output(os.path.join(options.git,
Simon Glassc55e0562016-07-25 18:59:00 -0600380 'scripts/show-gnu-make'), raise_on_error=False).rstrip()
Masahiro Yamada1fe610d2014-07-22 11:19:09 +0900381 if not gnu_make:
Masahiro Yamada880828d2014-08-16 00:59:26 +0900382 sys.exit('GNU Make not found')
Masahiro Yamada1fe610d2014-07-22 11:19:09 +0900383
Tom Rini93ebd462022-11-09 19:14:53 -0700384 allow_missing = get_allow_missing(options.allow_missing,
385 options.no_allow_missing, len(selected),
386 options.branch)
387
Simon Glassdbc01c72014-12-01 17:33:52 -0700388 # Create a new builder with the selected options.
389 output_dir = options.output_dir
Simon Glassd326ad72014-08-09 15:32:59 -0600390 if options.branch:
Simon Glass4aeceb92014-09-05 19:00:22 -0600391 dirname = options.branch.replace('/', '_')
Simon Glasse87bde12014-12-01 17:33:55 -0700392 # As a special case allow the board directory to be placed in the
393 # output directory itself rather than any subdirectory.
394 if not options.no_subdirs:
395 output_dir = os.path.join(options.output_dir, dirname)
Lothar Waßmannce6df922018-04-08 05:14:11 -0600396 if clean_dir and os.path.exists(output_dir):
397 shutil.rmtree(output_dir)
Simon Glass02d537a2023-07-19 17:48:37 -0600398
399 # For a dry run, just show our actions as a sanity check
400 if options.dry_run:
401 show_actions(series, why_selected, selected, output_dir, options,
402 board_warnings)
403 return 0
404
Simon Glasse5650a82022-01-22 05:07:33 -0700405 adjust_cfg = cfgutil.convert_list_to_dict(options.adjust_cfg)
406
Simon Glass828d70d2023-02-21 12:40:29 -0700407 # Drop LOCALVERSION_AUTO since it changes the version string on every commit
408 if options.reproducible_builds:
409 # If these are mentioned, leave the local version alone
410 if 'LOCALVERSION' in adjust_cfg or 'LOCALVERSION_AUTO' in adjust_cfg:
411 print('Not dropping LOCALVERSION_AUTO for reproducible build')
412 else:
413 adjust_cfg['LOCALVERSION_AUTO'] = '~'
414
Simon Glass2183b842023-07-19 17:48:33 -0600415 builder = Builder(toolchains, output_dir, git_dir,
Masahiro Yamada1fe610d2014-07-22 11:19:09 +0900416 options.threads, options.jobs, gnu_make=gnu_make, checkout=True,
Simon Glasse87bde12014-12-01 17:33:55 -0700417 show_unknown=options.show_unknown, step=options.step,
Simon Glass655b6102014-12-01 17:34:07 -0700418 no_subdirs=options.no_subdirs, full_path=options.full_path,
Stephen Warren97c96902016-04-11 10:48:44 -0600419 verbose_build=options.verbose_build,
Simon Glass6029af12020-04-09 15:08:51 -0600420 mrproper=options.mrproper,
Simon Glass739e8512016-11-13 14:25:51 -0700421 per_board_out_dir=options.per_board_out_dir,
Simon Glasscde5c302016-11-13 14:25:53 -0700422 config_only=options.config_only,
Daniel Schwierzeck20e2ea92018-01-26 16:31:05 +0100423 squash_config_y=not options.preserve_config_y,
Simon Glassb6eb8cf2020-03-18 09:42:42 -0600424 warnings_as_errors=options.warnings_as_errors,
Simon Glass9bf9a722021-04-11 16:27:27 +1200425 work_in_output=options.work_in_output,
Simon Glasse5650a82022-01-22 05:07:33 -0700426 test_thread_exceptions=test_thread_exceptions,
Tom Rini93ebd462022-11-09 19:14:53 -0700427 adjust_cfg=adjust_cfg,
Simon Glass828d70d2023-02-21 12:40:29 -0700428 allow_missing=allow_missing, no_lto=options.no_lto,
429 reproducible_builds=options.reproducible_builds)
Simon Glassaf0e29f2023-07-19 17:48:31 -0600430 TEST_BUILDER = builder
Simon Glassc05694f2013-04-03 11:07:16 +0000431 builder.force_config_on_failure = not options.quick
Simon Glassed098bb2014-09-05 19:00:13 -0600432 if make_func:
433 builder.do_make = make_func
Simon Glassc05694f2013-04-03 11:07:16 +0000434
Simon Glass02d537a2023-07-19 17:48:37 -0600435 builder.force_build = options.force_build
436 builder.force_build_failures = options.force_build_failures
437 builder.force_reconfig = options.force_reconfig
438 builder.in_tree = options.in_tree
Simon Glassc05694f2013-04-03 11:07:16 +0000439
Simon Glass02d537a2023-07-19 17:48:37 -0600440 # Work out which boards to build
441 board_selected = brds.get_selected_dict()
Simon Glassc05694f2013-04-03 11:07:16 +0000442
Simon Glass02d537a2023-07-19 17:48:37 -0600443 if series:
444 commits = series.commits
445 # Number the commits for test purposes
446 for i, commit in enumerate(commits):
447 commit.sequence = i
448 else:
449 commits = None
Simon Glassd326ad72014-08-09 15:32:59 -0600450
Simon Glass02d537a2023-07-19 17:48:37 -0600451 if not options.ide:
452 tprint(get_action_summary(options.summary, commits, board_selected,
453 options))
Simon Glassc05694f2013-04-03 11:07:16 +0000454
Simon Glass02d537a2023-07-19 17:48:37 -0600455 # We can't show function sizes without board details at present
456 if options.show_bloat:
457 options.show_detail = True
458 builder.SetDisplayOptions(
459 options.show_errors, options.show_sizes, options.show_detail,
460 options.show_bloat, options.list_error_boards, options.show_config,
461 options.show_environment, options.filter_dtb_warnings,
462 options.filter_migration_warnings, options.ide)
463 if options.summary:
464 builder.ShowSummary(commits, board_selected)
465 else:
466 fail, warned, excs = builder.BuildBoards(
467 commits, board_selected, options.keep_outputs, options.verbose)
468 if excs:
469 return 102
470 if fail:
471 return 100
472 if warned and not options.ignore_warnings:
473 return 101
Simon Glassc2f91072014-08-28 09:43:39 -0600474 return 0