blob: 35f44c0cf3db5b31374e2d24858ccdb73e152360 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001# SPDX-License-Identifier: GPL-2.0+
Simon Glassfc3fe1c2013-04-03 11:07:16 +00002# Copyright (c) 2013 The Chromium OS Authors.
3#
Simon Glassfc3fe1c2013-04-03 11:07:16 +00004
5import multiprocessing
Simon Glassd85f7902023-02-23 18:18:12 -07006import importlib.resources
Simon Glassfc3fe1c2013-04-03 11:07:16 +00007import os
Simon Glass883a3212014-09-05 19:00:18 -06008import shutil
Simon Glass0ede00f2020-04-17 18:09:02 -06009import subprocess
Simon Glassfc3fe1c2013-04-03 11:07:16 +000010import sys
11
Simon Glassc52bd222022-07-11 19:04:03 -060012from buildman import boards
Simon Glass0ede00f2020-04-17 18:09:02 -060013from buildman import bsettings
Simon Glass2b4806e2022-01-22 05:07:33 -070014from buildman import cfgutil
Simon Glass0ede00f2020-04-17 18:09:02 -060015from buildman import toolchain
16from buildman.builder import Builder
Simon Glassbf776672020-04-17 18:09:04 -060017from patman import gitutil
18from patman import patchstream
Simon Glass4583c002023-02-23 18:18:04 -070019from u_boot_pylib import command
20from u_boot_pylib import terminal
21from u_boot_pylib import tools
22from u_boot_pylib.terminal import tprint
Simon Glassfc3fe1c2013-04-03 11:07:16 +000023
24def GetPlural(count):
25 """Returns a plural 's' if count is not 1"""
26 return 's' if count != 1 else ''
27
Simon Glassfea58582014-08-09 15:32:59 -060028def GetActionSummary(is_summary, commits, selected, options):
Simon Glassfc3fe1c2013-04-03 11:07:16 +000029 """Return a string summarising the intended action.
30
31 Returns:
32 Summary string.
33 """
Simon Glassfea58582014-08-09 15:32:59 -060034 if commits:
35 count = len(commits)
Simon Glassc05aa032019-10-31 07:42:53 -060036 count = (count + options.step - 1) // options.step
Simon Glassfea58582014-08-09 15:32:59 -060037 commit_str = '%d commit%s' % (count, GetPlural(count))
38 else:
39 commit_str = 'current source'
40 str = '%s %s for %d boards' % (
41 'Summary of' if is_summary else 'Building', commit_str,
Simon Glassfc3fe1c2013-04-03 11:07:16 +000042 len(selected))
43 str += ' (%d thread%s, %d job%s per thread)' % (options.threads,
44 GetPlural(options.threads), options.jobs, GetPlural(options.jobs))
45 return str
46
Simon Glass06890362018-06-11 23:26:46 -060047def ShowActions(series, why_selected, boards_selected, builder, options,
48 board_warnings):
Simon Glassfc3fe1c2013-04-03 11:07:16 +000049 """Display a list of actions that we would take, if not a dry run.
50
51 Args:
52 series: Series object
53 why_selected: Dictionary where each key is a buildman argument
Simon Glass8d7523c2017-01-23 05:38:56 -070054 provided by the user, and the value is the list of boards
55 brought in by that argument. For example, 'arm' might bring
56 in 400 boards, so in this case the key would be 'arm' and
Simon Glassfc3fe1c2013-04-03 11:07:16 +000057 the value would be a list of board names.
58 boards_selected: Dict of selected boards, key is target name,
59 value is Board object
60 builder: The builder that will be used to build the commits
61 options: Command line options object
Simon Glass06890362018-06-11 23:26:46 -060062 board_warnings: List of warnings obtained from board selected
Simon Glassfc3fe1c2013-04-03 11:07:16 +000063 """
64 col = terminal.Color()
Simon Glassc05aa032019-10-31 07:42:53 -060065 print('Dry run, so not doing much. But I would do this:')
66 print()
Simon Glassfea58582014-08-09 15:32:59 -060067 if series:
68 commits = series.commits
69 else:
70 commits = None
Simon Glassc05aa032019-10-31 07:42:53 -060071 print(GetActionSummary(False, commits, boards_selected,
72 options))
73 print('Build directory: %s' % builder.base_dir)
Simon Glassfea58582014-08-09 15:32:59 -060074 if commits:
75 for upto in range(0, len(series.commits), options.step):
76 commit = series.commits[upto]
Simon Glass252ac582022-01-29 14:14:17 -070077 print(' ', col.build(col.YELLOW, commit.hash[:8], bright=False), end=' ')
Simon Glassc05aa032019-10-31 07:42:53 -060078 print(commit.subject)
79 print()
Simon Glassfc3fe1c2013-04-03 11:07:16 +000080 for arg in why_selected:
81 if arg != 'all':
Simon Glassc05aa032019-10-31 07:42:53 -060082 print(arg, ': %d boards' % len(why_selected[arg]))
Simon Glass8d7523c2017-01-23 05:38:56 -070083 if options.verbose:
Simon Glassc05aa032019-10-31 07:42:53 -060084 print(' %s' % ' '.join(why_selected[arg]))
85 print(('Total boards to build for each commit: %d\n' %
86 len(why_selected['all'])))
Simon Glass06890362018-06-11 23:26:46 -060087 if board_warnings:
88 for warning in board_warnings:
Simon Glass252ac582022-01-29 14:14:17 -070089 print(col.build(col.YELLOW, warning))
Simon Glassfc3fe1c2013-04-03 11:07:16 +000090
Simon Glasscc2c0d12022-07-11 19:04:00 -060091def ShowToolchainPrefix(brds, toolchains):
Simon Glass57cb9d52019-12-05 15:59:14 -070092 """Show information about a the tool chain used by one or more boards
93
Simon Glass4e9162d2020-03-18 09:42:47 -060094 The function checks that all boards use the same toolchain, then prints
95 the correct value for CROSS_COMPILE.
Simon Glass57cb9d52019-12-05 15:59:14 -070096
97 Args:
98 boards: Boards object containing selected boards
99 toolchains: Toolchains object containing available toolchains
Simon Glass57cb9d52019-12-05 15:59:14 -0700100
101 Return:
102 None on success, string error message otherwise
103 """
Simon Glass6014db62022-07-11 19:04:02 -0600104 board_selected = brds.get_selected_dict()
Simon Glass57cb9d52019-12-05 15:59:14 -0700105 tc_set = set()
Simon Glasscc2c0d12022-07-11 19:04:00 -0600106 for brd in board_selected.values():
Simon Glass57cb9d52019-12-05 15:59:14 -0700107 tc_set.add(toolchains.Select(brd.arch))
108 if len(tc_set) != 1:
109 return 'Supplied boards must share one toolchain'
110 return False
111 tc = tc_set.pop()
Simon Glass4e9162d2020-03-18 09:42:47 -0600112 print(tc.GetEnvArgs(toolchain.VAR_CROSS_COMPILE))
Simon Glass57cb9d52019-12-05 15:59:14 -0700113 return None
114
Tom Rinid7713ad2022-11-09 19:14:53 -0700115def get_allow_missing(opt_allow, opt_no_allow, num_selected, has_branch):
116 allow_missing = False
117 am_setting = bsettings.GetGlobalItemValue('allow-missing')
118 if am_setting:
119 if am_setting == 'always':
120 allow_missing = True
121 if 'multiple' in am_setting and num_selected > 1:
122 allow_missing = True
123 if 'branch' in am_setting and has_branch:
124 allow_missing = True
125
126 if opt_allow:
127 allow_missing = True
128 if opt_no_allow:
129 allow_missing = False
130 return allow_missing
131
Simon Glasscc2c0d12022-07-11 19:04:00 -0600132def DoBuildman(options, args, toolchains=None, make_func=None, brds=None,
Simon Glass8116c782021-04-11 16:27:27 +1200133 clean_dir=False, test_thread_exceptions=False):
Simon Glassfc3fe1c2013-04-03 11:07:16 +0000134 """The main control code for buildman
135
136 Args:
137 options: Command line options object
138 args: Command line arguments (list of strings)
Simon Glassd4144e42014-09-05 19:00:13 -0600139 toolchains: Toolchains to use - this should be a Toolchains()
140 object. If None, then it will be created and scanned
141 make_func: Make function to use for the builder. This is called
142 to execute 'make'. If this is None, the normal function
143 will be used, which calls the 'make' tool with suitable
144 arguments. This setting is useful for tests.
Simon Glasscc2c0d12022-07-11 19:04:00 -0600145 brds: Boards() object to use, containing a list of available
Simon Glass823e60b2014-09-05 19:00:16 -0600146 boards. If this is None it will be created and scanned.
Simon Glass24993312021-04-11 16:27:25 +1200147 clean_dir: Used for tests only, indicates that the existing output_dir
148 should be removed before starting the build
Simon Glass8116c782021-04-11 16:27:27 +1200149 test_thread_exceptions: Uses for tests only, True to make the threads
150 raise an exception instead of reporting their result. This simulates
151 a failure in the code somewhere
Simon Glassfc3fe1c2013-04-03 11:07:16 +0000152 """
Simon Glass883a3212014-09-05 19:00:18 -0600153 global builder
154
Simon Glass48ba5852014-09-05 19:00:11 -0600155 if options.full_help:
Simon Glassd85f7902023-02-23 18:18:12 -0700156 with importlib.resources.path('buildman', 'README.rst') as readme:
157 tools.print_full_help(str(readme))
Simon Glass48ba5852014-09-05 19:00:11 -0600158 return 0
159
Simon Glass0157b182022-01-29 14:14:11 -0700160 gitutil.setup()
Simon Glass713bea32016-07-27 20:33:02 -0600161 col = terminal.Color()
Simon Glassfc3fe1c2013-04-03 11:07:16 +0000162
Simon Glassfc3fe1c2013-04-03 11:07:16 +0000163 options.git_dir = os.path.join(options.git, '.git')
164
Simon Glass7e92e462016-07-27 20:33:04 -0600165 no_toolchains = toolchains is None
166 if no_toolchains:
Simon Glass00beb242019-01-07 16:44:20 -0700167 toolchains = toolchain.Toolchains(options.override_toolchain)
Simon Glassfc3fe1c2013-04-03 11:07:16 +0000168
Simon Glass827e37b2014-12-01 17:34:06 -0700169 if options.fetch_arch:
170 if options.fetch_arch == 'list':
171 sorted_list = toolchains.ListArchs()
Simon Glass252ac582022-01-29 14:14:17 -0700172 print(col.build(col.BLUE, 'Available architectures: %s\n' %
Simon Glassc05aa032019-10-31 07:42:53 -0600173 ' '.join(sorted_list)))
Simon Glass827e37b2014-12-01 17:34:06 -0700174 return 0
175 else:
176 fetch_arch = options.fetch_arch
177 if fetch_arch == 'all':
178 fetch_arch = ','.join(toolchains.ListArchs())
Simon Glass252ac582022-01-29 14:14:17 -0700179 print(col.build(col.CYAN, '\nDownloading toolchains: %s' %
Simon Glassc05aa032019-10-31 07:42:53 -0600180 fetch_arch))
Simon Glass827e37b2014-12-01 17:34:06 -0700181 for arch in fetch_arch.split(','):
Simon Glassc05aa032019-10-31 07:42:53 -0600182 print()
Simon Glass827e37b2014-12-01 17:34:06 -0700183 ret = toolchains.FetchAndInstall(arch)
184 if ret:
185 return ret
186 return 0
187
Simon Glass7e92e462016-07-27 20:33:04 -0600188 if no_toolchains:
189 toolchains.GetSettings()
Simon Glass40232c92018-11-06 16:02:10 -0700190 toolchains.Scan(options.list_tool_chains and options.verbose)
Simon Glass7e92e462016-07-27 20:33:04 -0600191 if options.list_tool_chains:
192 toolchains.List()
Simon Glassc05aa032019-10-31 07:42:53 -0600193 print()
Simon Glass7e92e462016-07-27 20:33:04 -0600194 return 0
195
Simon Glass88daaef2020-04-17 17:51:32 -0600196 if not options.output_dir:
197 if options.work_in_output:
Simon Glass252ac582022-01-29 14:14:17 -0700198 sys.exit(col.build(col.RED, '-w requires that you specify -o'))
Simon Glass88daaef2020-04-17 17:51:32 -0600199 options.output_dir = '..'
Simon Glasseb70a2c2020-04-09 15:08:51 -0600200
Simon Glass7c66ead2019-12-05 15:59:13 -0700201 # Work out what subset of the boards we are building
Simon Glasscc2c0d12022-07-11 19:04:00 -0600202 if not brds:
Simon Glass7c66ead2019-12-05 15:59:13 -0700203 if not os.path.exists(options.output_dir):
204 os.makedirs(options.output_dir)
205 board_file = os.path.join(options.output_dir, 'boards.cfg')
Simon Glass7c66ead2019-12-05 15:59:13 -0700206
Simon Glassc52bd222022-07-11 19:04:03 -0600207 brds = boards.Boards()
Simon Glassadd76e72022-07-11 19:04:08 -0600208 ok = brds.ensure_board_list(board_file,
209 options.threads or multiprocessing.cpu_count(),
210 force=options.regen_board_list,
211 quiet=not options.verbose)
Simon Glassa8a01412022-07-11 19:04:04 -0600212 if options.regen_board_list:
Simon Glassadd76e72022-07-11 19:04:08 -0600213 return 0 if ok else 2
Simon Glass6014db62022-07-11 19:04:02 -0600214 brds.read_boards(board_file)
Simon Glass7c66ead2019-12-05 15:59:13 -0700215
216 exclude = []
217 if options.exclude:
218 for arg in options.exclude:
219 exclude += arg.split(',')
220
221 if options.boards:
222 requested_boards = []
223 for b in options.boards:
224 requested_boards += b.split(',')
225 else:
226 requested_boards = None
Simon Glass6014db62022-07-11 19:04:02 -0600227 why_selected, board_warnings = brds.select_boards(args, exclude,
228 requested_boards)
229 selected = brds.get_selected()
Simon Glass7c66ead2019-12-05 15:59:13 -0700230 if not len(selected):
Simon Glass252ac582022-01-29 14:14:17 -0700231 sys.exit(col.build(col.RED, 'No matching boards found'))
Simon Glass7c66ead2019-12-05 15:59:13 -0700232
Simon Glass4e9162d2020-03-18 09:42:47 -0600233 if options.print_prefix:
Simon Glasscc2c0d12022-07-11 19:04:00 -0600234 err = ShowToolchainPrefix(brds, toolchains)
Simon Glass57cb9d52019-12-05 15:59:14 -0700235 if err:
Simon Glass252ac582022-01-29 14:14:17 -0700236 sys.exit(col.build(col.RED, err))
Simon Glass57cb9d52019-12-05 15:59:14 -0700237 return 0
238
Simon Glassfc3fe1c2013-04-03 11:07:16 +0000239 # Work out how many commits to build. We want to build everything on the
240 # branch. We also build the upstream commit as a control so we can see
241 # problems introduced by the first commit on the branch.
Simon Glassfc3fe1c2013-04-03 11:07:16 +0000242 count = options.count
Simon Glass5abab202014-12-01 17:33:57 -0700243 has_range = options.branch and '..' in options.branch
Simon Glassfc3fe1c2013-04-03 11:07:16 +0000244 if count == -1:
245 if not options.branch:
Simon Glassfea58582014-08-09 15:32:59 -0600246 count = 1
247 else:
Simon Glass5abab202014-12-01 17:33:57 -0700248 if has_range:
Simon Glass0157b182022-01-29 14:14:11 -0700249 count, msg = gitutil.count_commits_in_range(options.git_dir,
Simon Glass5abab202014-12-01 17:33:57 -0700250 options.branch)
251 else:
Simon Glass0157b182022-01-29 14:14:11 -0700252 count, msg = gitutil.count_commits_in_branch(options.git_dir,
Simon Glass5abab202014-12-01 17:33:57 -0700253 options.branch)
Simon Glassfea58582014-08-09 15:32:59 -0600254 if count is None:
Simon Glass252ac582022-01-29 14:14:17 -0700255 sys.exit(col.build(col.RED, msg))
Simon Glass5abab202014-12-01 17:33:57 -0700256 elif count == 0:
Simon Glass252ac582022-01-29 14:14:17 -0700257 sys.exit(col.build(col.RED, "Range '%s' has no commits" %
Simon Glass5abab202014-12-01 17:33:57 -0700258 options.branch))
Simon Glass2a9e2c62014-12-01 17:33:54 -0700259 if msg:
Simon Glass252ac582022-01-29 14:14:17 -0700260 print(col.build(col.YELLOW, msg))
Simon Glassfea58582014-08-09 15:32:59 -0600261 count += 1 # Build upstream commit also
Simon Glassfc3fe1c2013-04-03 11:07:16 +0000262
263 if not count:
Simon Glass8dd7be72023-02-23 18:18:11 -0700264 msg = ("No commits found to process in branch '%s': "
Simon Glassfc3fe1c2013-04-03 11:07:16 +0000265 "set branch's upstream or use -c flag" % options.branch)
Simon Glass8dd7be72023-02-23 18:18:11 -0700266 sys.exit(col.build(col.RED, msg))
Simon Glassd829f122020-03-18 09:42:42 -0600267 if options.work_in_output:
268 if len(selected) != 1:
Simon Glass252ac582022-01-29 14:14:17 -0700269 sys.exit(col.build(col.RED,
Simon Glassd829f122020-03-18 09:42:42 -0600270 '-w can only be used with a single board'))
271 if count != 1:
Simon Glass252ac582022-01-29 14:14:17 -0700272 sys.exit(col.build(col.RED,
Simon Glassd829f122020-03-18 09:42:42 -0600273 '-w can only be used with a single commit'))
Simon Glassfc3fe1c2013-04-03 11:07:16 +0000274
Simon Glassfc3fe1c2013-04-03 11:07:16 +0000275 # Read the metadata from the commits. First look at the upstream commit,
276 # then the ones in the branch. We would like to do something like
277 # upstream/master~..branch but that isn't possible if upstream/master is
278 # a merge commit (it will list all the commits that form part of the
279 # merge)
Simon Glass950a2312014-09-05 19:00:23 -0600280 # Conflicting tags are not a problem for buildman, since it does not use
281 # them. For example, Series-version is not useful for buildman. On the
282 # other hand conflicting tags will cause an error. So allow later tags
283 # to overwrite earlier ones by setting allow_overwrite=True
Simon Glassfea58582014-08-09 15:32:59 -0600284 if options.branch:
Simon Glass3b74ba52014-08-09 15:33:09 -0600285 if count == -1:
Simon Glass5abab202014-12-01 17:33:57 -0700286 if has_range:
287 range_expr = options.branch
288 else:
Simon Glass0157b182022-01-29 14:14:11 -0700289 range_expr = gitutil.get_range_in_branch(options.git_dir,
Simon Glass5abab202014-12-01 17:33:57 -0700290 options.branch)
Simon Glass0157b182022-01-29 14:14:11 -0700291 upstream_commit = gitutil.get_upstream(options.git_dir,
Simon Glass3b74ba52014-08-09 15:33:09 -0600292 options.branch)
Simon Glassd93720e2020-10-29 21:46:19 -0600293 series = patchstream.get_metadata_for_list(upstream_commit,
Simon Glass950a2312014-09-05 19:00:23 -0600294 options.git_dir, 1, series=None, allow_overwrite=True)
Simon Glassfea58582014-08-09 15:32:59 -0600295
Simon Glassd93720e2020-10-29 21:46:19 -0600296 series = patchstream.get_metadata_for_list(range_expr,
Simon Glass950a2312014-09-05 19:00:23 -0600297 options.git_dir, None, series, allow_overwrite=True)
Simon Glass3b74ba52014-08-09 15:33:09 -0600298 else:
299 # Honour the count
Simon Glassd93720e2020-10-29 21:46:19 -0600300 series = patchstream.get_metadata_for_list(options.branch,
Simon Glass950a2312014-09-05 19:00:23 -0600301 options.git_dir, count, series=None, allow_overwrite=True)
Simon Glassfea58582014-08-09 15:32:59 -0600302 else:
303 series = None
Simon Glass8d7523c2017-01-23 05:38:56 -0700304 if not options.dry_run:
305 options.verbose = True
306 if not options.summary:
307 options.show_errors = True
Simon Glassfc3fe1c2013-04-03 11:07:16 +0000308
309 # By default we have one thread per CPU. But if there are not enough jobs
310 # we can have fewer threads and use a high '-j' value for make.
Simon Glassb82492b2021-01-30 22:17:46 -0700311 if options.threads is None:
Simon Glassfc3fe1c2013-04-03 11:07:16 +0000312 options.threads = min(multiprocessing.cpu_count(), len(selected))
313 if not options.jobs:
314 options.jobs = max(1, (multiprocessing.cpu_count() +
Simon Glassc05aa032019-10-31 07:42:53 -0600315 len(selected) - 1) // len(selected))
Simon Glassfc3fe1c2013-04-03 11:07:16 +0000316
317 if not options.step:
318 options.step = len(series.commits) - 1
319
Simon Glassd9800692022-01-29 14:14:05 -0700320 gnu_make = command.output(os.path.join(options.git,
Simon Glass785f1542016-07-25 18:59:00 -0600321 'scripts/show-gnu-make'), raise_on_error=False).rstrip()
Masahiro Yamada99796922014-07-22 11:19:09 +0900322 if not gnu_make:
Masahiro Yamada31e21412014-08-16 00:59:26 +0900323 sys.exit('GNU Make not found')
Masahiro Yamada99796922014-07-22 11:19:09 +0900324
Tom Rinid7713ad2022-11-09 19:14:53 -0700325 allow_missing = get_allow_missing(options.allow_missing,
326 options.no_allow_missing, len(selected),
327 options.branch)
328
Simon Glass05c96b12014-12-01 17:33:52 -0700329 # Create a new builder with the selected options.
330 output_dir = options.output_dir
Simon Glassfea58582014-08-09 15:32:59 -0600331 if options.branch:
Simon Glassf7582ce2014-09-05 19:00:22 -0600332 dirname = options.branch.replace('/', '_')
Simon Glass5971ab52014-12-01 17:33:55 -0700333 # As a special case allow the board directory to be placed in the
334 # output directory itself rather than any subdirectory.
335 if not options.no_subdirs:
336 output_dir = os.path.join(options.output_dir, dirname)
Lothar Waßmann409fc022018-04-08 05:14:11 -0600337 if clean_dir and os.path.exists(output_dir):
338 shutil.rmtree(output_dir)
Simon Glass2b4806e2022-01-22 05:07:33 -0700339 adjust_cfg = cfgutil.convert_list_to_dict(options.adjust_cfg)
340
Simon Glassbfb708a2023-02-21 12:40:29 -0700341 # Drop LOCALVERSION_AUTO since it changes the version string on every commit
342 if options.reproducible_builds:
343 # If these are mentioned, leave the local version alone
344 if 'LOCALVERSION' in adjust_cfg or 'LOCALVERSION_AUTO' in adjust_cfg:
345 print('Not dropping LOCALVERSION_AUTO for reproducible build')
346 else:
347 adjust_cfg['LOCALVERSION_AUTO'] = '~'
348
Simon Glassfc3fe1c2013-04-03 11:07:16 +0000349 builder = Builder(toolchains, output_dir, options.git_dir,
Masahiro Yamada99796922014-07-22 11:19:09 +0900350 options.threads, options.jobs, gnu_make=gnu_make, checkout=True,
Simon Glass5971ab52014-12-01 17:33:55 -0700351 show_unknown=options.show_unknown, step=options.step,
Simon Glassd2ce6582014-12-01 17:34:07 -0700352 no_subdirs=options.no_subdirs, full_path=options.full_path,
Stephen Warrenf79f1e02016-04-11 10:48:44 -0600353 verbose_build=options.verbose_build,
Simon Glasseb70a2c2020-04-09 15:08:51 -0600354 mrproper=options.mrproper,
Simon Glassb50113f2016-11-13 14:25:51 -0700355 per_board_out_dir=options.per_board_out_dir,
Simon Glassb464f8e2016-11-13 14:25:53 -0700356 config_only=options.config_only,
Daniel Schwierzeck2371d1b2018-01-26 16:31:05 +0100357 squash_config_y=not options.preserve_config_y,
Simon Glassd829f122020-03-18 09:42:42 -0600358 warnings_as_errors=options.warnings_as_errors,
Simon Glass8116c782021-04-11 16:27:27 +1200359 work_in_output=options.work_in_output,
Simon Glass2b4806e2022-01-22 05:07:33 -0700360 test_thread_exceptions=test_thread_exceptions,
Tom Rinid7713ad2022-11-09 19:14:53 -0700361 adjust_cfg=adjust_cfg,
Simon Glassbfb708a2023-02-21 12:40:29 -0700362 allow_missing=allow_missing, no_lto=options.no_lto,
363 reproducible_builds=options.reproducible_builds)
Simon Glassfc3fe1c2013-04-03 11:07:16 +0000364 builder.force_config_on_failure = not options.quick
Simon Glassd4144e42014-09-05 19:00:13 -0600365 if make_func:
366 builder.do_make = make_func
Simon Glassfc3fe1c2013-04-03 11:07:16 +0000367
368 # For a dry run, just show our actions as a sanity check
369 if options.dry_run:
Simon Glass06890362018-06-11 23:26:46 -0600370 ShowActions(series, why_selected, selected, builder, options,
371 board_warnings)
Simon Glassfc3fe1c2013-04-03 11:07:16 +0000372 else:
373 builder.force_build = options.force_build
Simon Glass4266dc22014-07-13 12:22:31 -0600374 builder.force_build_failures = options.force_build_failures
Simon Glass97e91522014-07-14 17:51:02 -0600375 builder.force_reconfig = options.force_reconfig
Simon Glass189a4962014-07-14 17:51:03 -0600376 builder.in_tree = options.in_tree
Simon Glassfc3fe1c2013-04-03 11:07:16 +0000377
378 # Work out which boards to build
Simon Glass6014db62022-07-11 19:04:02 -0600379 board_selected = brds.get_selected_dict()
Simon Glassfc3fe1c2013-04-03 11:07:16 +0000380
Simon Glassfea58582014-08-09 15:32:59 -0600381 if series:
382 commits = series.commits
Simon Glass883a3212014-09-05 19:00:18 -0600383 # Number the commits for test purposes
384 for commit in range(len(commits)):
385 commits[commit].sequence = commit
Simon Glassfea58582014-08-09 15:32:59 -0600386 else:
387 commits = None
388
Simon Glassae1a09f2022-07-11 19:03:56 -0600389 if not options.ide:
390 tprint(GetActionSummary(options.summary, commits, board_selected,
391 options))
Simon Glassfc3fe1c2013-04-03 11:07:16 +0000392
Simon Glass7798e222014-09-14 20:23:16 -0600393 # We can't show function sizes without board details at present
394 if options.show_bloat:
395 options.show_detail = True
Simon Glass174592b2020-04-09 15:08:52 -0600396 builder.SetDisplayOptions(
397 options.show_errors, options.show_sizes, options.show_detail,
398 options.show_bloat, options.list_error_boards, options.show_config,
Simon Glass113a8a52020-04-09 15:08:53 -0600399 options.show_environment, options.filter_dtb_warnings,
Simon Glassae1a09f2022-07-11 19:03:56 -0600400 options.filter_migration_warnings, options.ide)
Simon Glassfc3fe1c2013-04-03 11:07:16 +0000401 if options.summary:
Simon Glassb2ea7ab2014-08-09 15:33:02 -0600402 builder.ShowSummary(commits, board_selected)
Simon Glassfc3fe1c2013-04-03 11:07:16 +0000403 else:
Simon Glass8116c782021-04-11 16:27:27 +1200404 fail, warned, excs = builder.BuildBoards(
405 commits, board_selected, options.keep_outputs, options.verbose)
406 if excs:
407 return 102
408 elif fail:
Simon Glassb1e5e6d2020-04-09 10:49:45 -0600409 return 100
Simon Glass7beb43c2020-03-18 09:42:44 -0600410 elif warned and not options.ignore_warnings:
Simon Glassb1e5e6d2020-04-09 10:49:45 -0600411 return 101
Simon Glass2c3deb92014-08-28 09:43:39 -0600412 return 0