blob: 89532a281e87ed0fb0148b7dc2666608579b1b32 [file] [log] [blame]
Marti Bolivarab822642019-01-23 08:31:06 -07001# Copyright (c) 2018 Foundries.io
2#
3# SPDX-License-Identifier: Apache-2.0
4
5import argparse
6import os
Martí Bolívar0186ead2019-12-09 11:05:11 -08007import shlex
Marti Bolivarab822642019-01-23 08:31:06 -07008
9from west import log
Carles Cufib7c75912019-04-14 21:52:45 +020010from west.configuration import config
Jan Van Winkel4d975db2019-05-04 14:44:56 +020011from zcmake import DEFAULT_CMAKE_GENERATOR, run_cmake, run_build, CMakeCache
Marti Bolivar69099e32019-05-04 13:16:15 -060012from build_helpers import is_zephyr_build, find_build_dir, \
Carles Cufi98980c62019-06-05 16:04:29 +020013 FIND_BUILD_DIR_DESCRIPTION
Marti Bolivar8c447992019-01-30 13:53:40 -070014
Carles Cufi31bdad52019-04-26 21:53:02 +020015from zephyr_ext_common import Forceable
Marti Bolivar8c447992019-01-30 13:53:40 -070016
Carles Cufib7101772019-02-21 15:58:19 +010017_ARG_SEPARATOR = '--'
Marti Bolivarab822642019-01-23 08:31:06 -070018
Marti Bolivar1f5e6d82019-05-01 16:48:04 -060019BUILD_USAGE = '''\
20west build [-h] [-b BOARD] [-d BUILD_DIR]
21 [-t TARGET] [-p {auto, always, never}] [-c] [--cmake-only]
Marti Bolivar3a486a82019-05-04 13:32:36 -060022 [-n] [-o BUILD_OPT] [-f]
23 [source_dir] -- [cmake_opt [cmake_opt ...]]
Marti Bolivar1f5e6d82019-05-01 16:48:04 -060024'''
25
Marti Bolivarab822642019-01-23 08:31:06 -070026BUILD_DESCRIPTION = '''\
27Convenience wrapper for building Zephyr applications.
28
Carles Cufib7101772019-02-21 15:58:19 +010029positional arguments:
Marti Bolivar83a5fd82019-05-04 13:56:36 -060030 source_dir Use this path as the source directory
Carles Cufib7101772019-02-21 15:58:19 +010031 cmake_opt Extra options to pass to CMake; implies -c
32'''
Marti Bolivarab822642019-01-23 08:31:06 -070033
Marti Bolivare6873b82019-06-02 22:48:52 -060034def _banner(msg):
35 log.inf('-- west build: ' + msg, colorize=True)
36
Marti Bolivard1595032019-05-04 13:14:28 -060037def config_get(option, fallback):
38 return config.get('build', option, fallback=fallback)
39
40def config_getboolean(option, fallback):
41 return config.getboolean('build', option, fallback=fallback)
42
Carles Cufib7c75912019-04-14 21:52:45 +020043class AlwaysIfMissing(argparse.Action):
44
Marti Bolivar69099e32019-05-04 13:16:15 -060045 def __call__(self, parser, namespace, values, option_string=None):
46 setattr(namespace, self.dest, values or 'always')
Marti Bolivarab822642019-01-23 08:31:06 -070047
Marti Bolivar8c447992019-01-30 13:53:40 -070048class Build(Forceable):
Marti Bolivarab822642019-01-23 08:31:06 -070049
50 def __init__(self):
51 super(Build, self).__init__(
52 'build',
Marti Bolivar808028b2019-01-28 10:45:02 -070053 # Keep this in sync with the string in west-commands.yml.
Marti Bolivarab822642019-01-23 08:31:06 -070054 'compile a Zephyr application',
55 BUILD_DESCRIPTION,
Carles Cufib7101772019-02-21 15:58:19 +010056 accepts_unknown_args=True)
Marti Bolivarab822642019-01-23 08:31:06 -070057
58 self.source_dir = None
59 '''Source directory for the build, or None on error.'''
60
61 self.build_dir = None
62 '''Final build directory used to run the build, or None on error.'''
63
64 self.created_build_dir = False
65 '''True if the build directory was created; False otherwise.'''
66
67 self.run_cmake = False
68 '''True if CMake was run; False otherwise.
69
70 Note: this only describes CMake runs done by this command. The
71 build system generated by CMake may also update itself due to
72 internal logic.'''
73
74 self.cmake_cache = None
75 '''Final parsed CMake cache for the build, or None on error.'''
76
77 def do_add_parser(self, parser_adder):
78 parser = parser_adder.add_parser(
79 self.name,
80 help=self.help,
81 formatter_class=argparse.RawDescriptionHelpFormatter,
Carles Cufib7101772019-02-21 15:58:19 +010082 description=self.description,
Marti Bolivar1f5e6d82019-05-01 16:48:04 -060083 usage=BUILD_USAGE)
Marti Bolivarab822642019-01-23 08:31:06 -070084
85 # Remember to update scripts/west-completion.bash if you add or remove
86 # flags
87
Marti Bolivar88fb8ba2019-05-04 13:14:57 -060088 parser.add_argument('-b', '--board', help='Board to build for')
Carles Cufib7101772019-02-21 15:58:19 +010089 # Hidden option for backwards compatibility
90 parser.add_argument('-s', '--source-dir', help=argparse.SUPPRESS)
Marti Bolivarab822642019-01-23 08:31:06 -070091 parser.add_argument('-d', '--build-dir',
Carles Cufi98980c62019-06-05 16:04:29 +020092 help='Build directory. ' +
93 FIND_BUILD_DIR_DESCRIPTION +
94 " Otherwise the default build directory is " +
95 "created and used.")
Marti Bolivarab822642019-01-23 08:31:06 -070096 parser.add_argument('-t', '--target',
Marti Bolivar83a5fd82019-05-04 13:56:36 -060097 help='''Build system target to run''')
Carles Cufib7c75912019-04-14 21:52:45 +020098 parser.add_argument('-p', '--pristine', choices=['auto', 'always',
99 'never'], action=AlwaysIfMissing, nargs='?',
Carles Cufi3a88dce2019-04-18 16:46:12 +0200100 help='''Control whether the build folder is made
Marti Bolivar83a5fd82019-05-04 13:56:36 -0600101 pristine before running CMake. --pristine is the
102 same as --pristine=always. If 'auto', it will
103 be made pristine only if needed.''')
Marti Bolivarab822642019-01-23 08:31:06 -0700104 parser.add_argument('-c', '--cmake', action='store_true',
105 help='Force CMake to run')
Marti Bolivar1f5e6d82019-05-01 16:48:04 -0600106 parser.add_argument('--cmake-only', action='store_true',
107 help="Just run CMake; don't build. Implies -c.")
Marti Bolivar8465cf22019-05-01 17:24:23 -0600108 parser.add_argument('-n', '--just-print', '--dry-run', '--recon',
109 dest='dry_run', action='store_true',
Marti Bolivar83a5fd82019-05-04 13:56:36 -0600110 help='''Just print the build commands; don't run
111 them''')
Marti Bolivar3a486a82019-05-04 13:32:36 -0600112 parser.add_argument('-o', '--build-opt', default=[], action='append',
113 help='''Options to pass to the build tool.
114 May be given more than once to append multiple
115 values.''')
Marti Bolivar8c447992019-01-30 13:53:40 -0700116 self.add_force_arg(parser)
Marti Bolivarab822642019-01-23 08:31:06 -0700117 return parser
118
Carles Cufib7101772019-02-21 15:58:19 +0100119 def do_run(self, args, remainder):
Marti Bolivarab822642019-01-23 08:31:06 -0700120 self.args = args # Avoid having to pass them around
Marti Bolivar8b9b7e72019-05-23 09:31:31 -0600121 self.config_board = config_get('board', None)
Marti Bolivara1ef6962019-05-01 17:06:15 -0600122 log.dbg('args: {} remainder: {}'.format(args, remainder),
123 level=log.VERBOSE_EXTREME)
Carles Cufib7101772019-02-21 15:58:19 +0100124 # Store legacy -s option locally
125 source_dir = self.args.source_dir
126 self._parse_remainder(remainder)
127 if source_dir:
128 if self.args.source_dir:
129 log.die("source directory specified twice:({} and {})".format(
130 source_dir, self.args.source_dir))
131 self.args.source_dir = source_dir
132 log.dbg('source_dir: {} cmake_opts: {}'.format(self.args.source_dir,
Marti Bolivara1ef6962019-05-01 17:06:15 -0600133 self.args.cmake_opts),
134 level=log.VERBOSE_EXTREME)
Marti Bolivarab822642019-01-23 08:31:06 -0700135 self._sanity_precheck()
136 self._setup_build_dir()
Carles Cufib7c75912019-04-14 21:52:45 +0200137
138 if args.pristine is not None:
139 pristine = args.pristine
140 else:
141 # Load the pristine={auto, always, never} configuration value
Marti Bolivard1595032019-05-04 13:14:28 -0600142 pristine = config_get('pristine', 'never')
Carles Cufib7c75912019-04-14 21:52:45 +0200143 if pristine not in ['auto', 'always', 'never']:
Marti Bolivar69099e32019-05-04 13:16:15 -0600144 log.wrn(
145 'treating unknown build.pristine value "{}" as "never"'.
146 format(pristine))
Carles Cufib7c75912019-04-14 21:52:45 +0200147 pristine = 'never'
148 self.auto_pristine = (pristine == 'auto')
149
150 log.dbg('pristine: {} auto_pristine: {}'.format(pristine,
Marti Bolivara1ef6962019-05-01 17:06:15 -0600151 self.auto_pristine),
152 level=log.VERBOSE_VERY)
Marti Bolivarab822642019-01-23 08:31:06 -0700153 if is_zephyr_build(self.build_dir):
Carles Cufib7c75912019-04-14 21:52:45 +0200154 if pristine == 'always':
Carles Cufi3a88dce2019-04-18 16:46:12 +0200155 self._run_pristine()
Marti Bolivarab822642019-01-23 08:31:06 -0700156 self.run_cmake = True
Carles Cufib7c75912019-04-14 21:52:45 +0200157 else:
158 self._update_cache()
Marti Bolivar1f5e6d82019-05-01 16:48:04 -0600159 if (self.args.cmake or self.args.cmake_opts or
160 self.args.cmake_only):
Carles Cufib7c75912019-04-14 21:52:45 +0200161 self.run_cmake = True
Marti Bolivarab822642019-01-23 08:31:06 -0700162 else:
163 self.run_cmake = True
Carles Cufi98980c62019-06-05 16:04:29 +0200164 self.source_dir = self._find_source_dir()
Marti Bolivarab822642019-01-23 08:31:06 -0700165 self._sanity_check()
166
Marti Bolivar88fb8ba2019-05-04 13:14:57 -0600167 board, origin = self._find_board()
168 self._run_cmake(board, origin, self.args.cmake_opts)
Marti Bolivar1f5e6d82019-05-01 16:48:04 -0600169 if args.cmake_only:
170 return
171
Marti Bolivarab822642019-01-23 08:31:06 -0700172 self._sanity_check()
173 self._update_cache()
174
Carles Cufib7c75912019-04-14 21:52:45 +0200175 self._run_build(args.target)
Marti Bolivarab822642019-01-23 08:31:06 -0700176
Marti Bolivar88fb8ba2019-05-04 13:14:57 -0600177 def _find_board(self):
178 board, origin = None, None
Marti Bolivar88fb8ba2019-05-04 13:14:57 -0600179 if self.cmake_cache:
180 board, origin = (self.cmake_cache.get('CACHED_BOARD'),
181 'CMakeCache.txt')
182 elif self.args.board:
183 board, origin = self.args.board, 'command line'
184 elif 'BOARD' in os.environ:
185 board, origin = os.environ['BOARD'], 'env'
Marti Bolivar8b9b7e72019-05-23 09:31:31 -0600186 elif self.config_board is not None:
187 board, origin = self.config_board, 'configfile'
Marti Bolivar88fb8ba2019-05-04 13:14:57 -0600188 return board, origin
189
Carles Cufib7101772019-02-21 15:58:19 +0100190 def _parse_remainder(self, remainder):
191 self.args.source_dir = None
192 self.args.cmake_opts = None
193 try:
194 # Only one source_dir is allowed, as the first positional arg
195 if remainder[0] != _ARG_SEPARATOR:
196 self.args.source_dir = remainder[0]
197 remainder = remainder[1:]
198 # Only the first argument separator is consumed, the rest are
199 # passed on to CMake
200 if remainder[0] == _ARG_SEPARATOR:
201 remainder = remainder[1:]
Ulf Magnusson5d307c92019-09-02 15:35:56 +0200202 if remainder:
Carles Cufib7101772019-02-21 15:58:19 +0100203 self.args.cmake_opts = remainder
204 except IndexError:
205 return
206
Marti Bolivarab822642019-01-23 08:31:06 -0700207 def _sanity_precheck(self):
208 app = self.args.source_dir
209 if app:
Marti Bolivar8c447992019-01-30 13:53:40 -0700210 self.check_force(
211 os.path.isdir(app),
212 'source directory {} does not exist'.format(app))
213 self.check_force(
214 'CMakeLists.txt' in os.listdir(app),
215 "{} doesn't contain a CMakeLists.txt".format(app))
Marti Bolivarab822642019-01-23 08:31:06 -0700216
217 def _update_cache(self):
218 try:
Carles Cufi31bdad52019-04-26 21:53:02 +0200219 self.cmake_cache = CMakeCache.from_build_dir(self.build_dir)
Marti Bolivarab822642019-01-23 08:31:06 -0700220 except FileNotFoundError:
221 pass
222
223 def _setup_build_dir(self):
224 # Initialize build_dir and created_build_dir attributes.
Marti Bolivar8c447992019-01-30 13:53:40 -0700225 # If we created the build directory, we must run CMake.
Marti Bolivarab822642019-01-23 08:31:06 -0700226 log.dbg('setting up build directory', level=log.VERBOSE_EXTREME)
Carles Cufi98980c62019-06-05 16:04:29 +0200227 # The CMake Cache has not been loaded yet, so this is safe
Ulf Magnusson89efaed2019-09-05 13:44:09 +0200228 board, _ = self._find_board()
Carles Cufi98980c62019-06-05 16:04:29 +0200229 source_dir = self._find_source_dir()
230 app = os.path.split(source_dir)[1]
231 build_dir = find_build_dir(self.args.build_dir, board=board,
232 source_dir=source_dir, app=app)
233 if not build_dir:
234 log.die('Unable to determine a default build folder. Check '
235 'your build.dir-fmt configuration option')
Marti Bolivarab822642019-01-23 08:31:06 -0700236
237 if os.path.exists(build_dir):
238 if not os.path.isdir(build_dir):
239 log.die('build directory {} exists and is not a directory'.
240 format(build_dir))
241 else:
242 os.makedirs(build_dir, exist_ok=False)
243 self.created_build_dir = True
244 self.run_cmake = True
245
246 self.build_dir = build_dir
247
Carles Cufi98980c62019-06-05 16:04:29 +0200248 def _find_source_dir(self):
Marti Bolivarab822642019-01-23 08:31:06 -0700249 # Initialize source_dir attribute, either from command line argument,
250 # implicitly from the build directory's CMake cache, or using the
251 # default (current working directory).
252 log.dbg('setting up source directory', level=log.VERBOSE_EXTREME)
253 if self.args.source_dir:
254 source_dir = self.args.source_dir
255 elif self.cmake_cache:
Marti Bolivaracda2572019-04-10 17:09:17 -0600256 source_dir = self.cmake_cache.get('CMAKE_HOME_DIRECTORY')
Marti Bolivarab822642019-01-23 08:31:06 -0700257 if not source_dir:
Marti Bolivaracda2572019-04-10 17:09:17 -0600258 # This really ought to be there. The build directory
259 # must be corrupted somehow. Let's see what we can do.
260 log.die('build directory', self.build_dir,
261 'CMake cache has no CMAKE_HOME_DIRECTORY;',
262 'please give a source_dir')
Marti Bolivarab822642019-01-23 08:31:06 -0700263 else:
264 source_dir = os.getcwd()
Carles Cufi98980c62019-06-05 16:04:29 +0200265 return os.path.abspath(source_dir)
Marti Bolivarab822642019-01-23 08:31:06 -0700266
Carles Cufib7c75912019-04-14 21:52:45 +0200267 def _sanity_check_source_dir(self):
Marti Bolivarab822642019-01-23 08:31:06 -0700268 if self.source_dir == self.build_dir:
269 # There's no forcing this.
270 log.die('source and build directory {} cannot be the same; '
271 'use --build-dir {} to specify a build directory'.
272 format(self.source_dir, self.build_dir))
273
274 srcrel = os.path.relpath(self.source_dir)
Marti Bolivar8c447992019-01-30 13:53:40 -0700275 self.check_force(
276 not is_zephyr_build(self.source_dir),
277 'it looks like {srcrel} is a build directory: '
278 'did you mean --build-dir {srcrel} instead?'.
279 format(srcrel=srcrel))
280 self.check_force(
281 'CMakeLists.txt' in os.listdir(self.source_dir),
282 'source directory "{srcrel}" does not contain '
283 'a CMakeLists.txt; is this really what you '
284 'want to build? (Use -s SOURCE_DIR to specify '
285 'the application source directory)'.
286 format(srcrel=srcrel))
Carles Cufib7c75912019-04-14 21:52:45 +0200287
288 def _sanity_check(self):
289 # Sanity check the build configuration.
290 # Side effect: may update cmake_cache attribute.
291 log.dbg('sanity checking the build', level=log.VERBOSE_EXTREME)
292 self._sanity_check_source_dir()
293
Marti Bolivarab822642019-01-23 08:31:06 -0700294 if not self.cmake_cache:
295 return # That's all we can check without a cache.
296
297 cached_app = self.cmake_cache.get('APPLICATION_SOURCE_DIR')
298 log.dbg('APPLICATION_SOURCE_DIR:', cached_app,
299 level=log.VERBOSE_EXTREME)
300 source_abs = (os.path.abspath(self.args.source_dir)
301 if self.args.source_dir else None)
302 cached_abs = os.path.abspath(cached_app) if cached_app else None
Marti Bolivar8c447992019-01-30 13:53:40 -0700303
Carles Cufib7c75912019-04-14 21:52:45 +0200304 log.dbg('pristine:', self.auto_pristine, level=log.VERBOSE_EXTREME)
Marti Bolivar8c447992019-01-30 13:53:40 -0700305 # If the build directory specifies a source app, make sure it's
306 # consistent with --source-dir.
307 apps_mismatched = (source_abs and cached_abs and
308 source_abs != cached_abs)
309 self.check_force(
Carles Cufib7c75912019-04-14 21:52:45 +0200310 not apps_mismatched or self.auto_pristine,
Marti Bolivar8c447992019-01-30 13:53:40 -0700311 'Build directory "{}" is for application "{}", but source '
Carles Cufib7c75912019-04-14 21:52:45 +0200312 'directory "{}" was specified; please clean it, use --pristine, '
313 'or use --build-dir to set another build directory'.
Marti Bolivar8c447992019-01-30 13:53:40 -0700314 format(self.build_dir, cached_abs, source_abs))
315 if apps_mismatched:
Marti Bolivarab822642019-01-23 08:31:06 -0700316 self.run_cmake = True # If they insist, we need to re-run cmake.
317
Marti Bolivar8b9b7e72019-05-23 09:31:31 -0600318 # If CACHED_BOARD is not defined, we need some other way to
319 # find the board.
Marti Bolivarab822642019-01-23 08:31:06 -0700320 cached_board = self.cmake_cache.get('CACHED_BOARD')
321 log.dbg('CACHED_BOARD:', cached_board, level=log.VERBOSE_EXTREME)
Marti Bolivar8b9b7e72019-05-23 09:31:31 -0600322 # If apps_mismatched and self.auto_pristine are true, we will
323 # run pristine on the build, invalidating the cached
324 # board. In that case, we need some way of getting the board.
Carles Cufib7c75912019-04-14 21:52:45 +0200325 self.check_force((cached_board and
326 not (apps_mismatched and self.auto_pristine))
Marti Bolivar8b9b7e72019-05-23 09:31:31 -0600327 or self.args.board or self.config_board or
328 os.environ.get('BOARD'),
329 'Cached board not defined, please provide it '
330 '(provide --board, set default with '
331 '"west config build.board <BOARD>", or set '
332 'BOARD in the environment)')
Marti Bolivarab822642019-01-23 08:31:06 -0700333
Marti Bolivar8c447992019-01-30 13:53:40 -0700334 # Check consistency between cached board and --board.
335 boards_mismatched = (self.args.board and cached_board and
336 self.args.board != cached_board)
337 self.check_force(
Carles Cufib7c75912019-04-14 21:52:45 +0200338 not boards_mismatched or self.auto_pristine,
Marti Bolivar8c447992019-01-30 13:53:40 -0700339 'Build directory {} targets board {}, but board {} was specified. '
Carles Cufib7c75912019-04-14 21:52:45 +0200340 '(Clean the directory, use --pristine, or use --build-dir to '
341 'specify a different one.)'.
Marti Bolivar8c447992019-01-30 13:53:40 -0700342 format(self.build_dir, cached_board, self.args.board))
Marti Bolivarab822642019-01-23 08:31:06 -0700343
Carles Cufib7c75912019-04-14 21:52:45 +0200344 if self.auto_pristine and (apps_mismatched or boards_mismatched):
Carles Cufi3a88dce2019-04-18 16:46:12 +0200345 self._run_pristine()
Carles Cufib7c75912019-04-14 21:52:45 +0200346 self.cmake_cache = None
347 log.dbg('run_cmake:', True, level=log.VERBOSE_EXTREME)
348 self.run_cmake = True
349
350 # Tricky corner-case: The user has not specified a build folder but
351 # there was one in the CMake cache. Since this is going to be
352 # invalidated, reset to CWD and re-run the basic tests.
353 if ((boards_mismatched and not apps_mismatched) and
Marti Bolivar69099e32019-05-04 13:16:15 -0600354 (not source_abs and cached_abs)):
Carles Cufi98980c62019-06-05 16:04:29 +0200355 self.source_dir = self._find_source_dir()
Carles Cufib7c75912019-04-14 21:52:45 +0200356 self._sanity_check_source_dir()
357
Marti Bolivar88fb8ba2019-05-04 13:14:57 -0600358 def _run_cmake(self, board, origin, cmake_opts):
Marti Bolivare6873b82019-06-02 22:48:52 -0600359 _banner(
360 '''build configuration:
361 source directory: {}
362 build directory: {}{}
363 BOARD: {}'''.
364 format(self.source_dir, self.build_dir,
365 ' (created)' if self.created_build_dir else '',
366 ('{} (origin: {})'.format(board, origin) if board
367 else 'UNKNOWN')))
Marti Bolivar88fb8ba2019-05-04 13:14:57 -0600368
369 if board is None and config_getboolean('board_warn', True):
370 log.wrn('This looks like a fresh build and BOARD is unknown;',
371 "so it probably won't work. To fix, use",
372 '--board=<your-board>.')
373 log.inf('Note: to silence the above message, run',
374 "'west config build.board_warn false'")
375
Marti Bolivarab822642019-01-23 08:31:06 -0700376 if not self.run_cmake:
Marti Bolivara1ef6962019-05-01 17:06:15 -0600377 log.dbg('Not generating a build system; one is present.')
Marti Bolivarab822642019-01-23 08:31:06 -0700378 return
379
Marti Bolivare6873b82019-06-02 22:48:52 -0600380 _banner('generating a build system')
381
Marti Bolivar88fb8ba2019-05-04 13:14:57 -0600382 if board is not None and origin != 'CMakeCache.txt':
383 cmake_opts = ['-DBOARD={}'.format(board)]
384 else:
385 cmake_opts = []
386 if self.args.cmake_opts:
387 cmake_opts.extend(self.args.cmake_opts)
388
Martí Bolívar0186ead2019-12-09 11:05:11 -0800389 user_args = config_get('cmake-args', None)
390 if user_args:
391 cmake_opts.extend(shlex.split(user_args))
392
Carles Cufi3c6584d2019-04-14 21:51:16 +0200393 # Invoke CMake from the current working directory using the
394 # -S and -B options (officially introduced in CMake 3.13.0).
395 # This is important because users expect invocations like this
396 # to Just Work:
Marti Bolivarab822642019-01-23 08:31:06 -0700397 #
398 # west build -- -DOVERLAY_CONFIG=relative-path.conf
399 final_cmake_args = ['-B{}'.format(self.build_dir),
Carles Cufi3c6584d2019-04-14 21:51:16 +0200400 '-S{}'.format(self.source_dir),
Marti Bolivarbbe890a2019-05-01 16:53:32 -0600401 '-G{}'.format(config_get('generator',
402 DEFAULT_CMAKE_GENERATOR))]
Marti Bolivarab822642019-01-23 08:31:06 -0700403 if cmake_opts:
404 final_cmake_args.extend(cmake_opts)
Marti Bolivar8465cf22019-05-01 17:24:23 -0600405 run_cmake(final_cmake_args, dry_run=self.args.dry_run)
Carles Cufib7c75912019-04-14 21:52:45 +0200406
Carles Cufi3a88dce2019-04-18 16:46:12 +0200407 def _run_pristine(self):
Marti Bolivare6873b82019-06-02 22:48:52 -0600408 _banner('making build dir {} pristine'.format(self.build_dir))
Carles Cufi3a88dce2019-04-18 16:46:12 +0200409
410 zb = os.environ.get('ZEPHYR_BASE')
411 if not zb:
412 log.die('Internal error: ZEPHYR_BASE not set in the environment, '
413 'and should have been by the main script')
414
415 if not is_zephyr_build(self.build_dir):
Marti Bolivar69099e32019-05-04 13:16:15 -0600416 log.die('Refusing to run pristine on a folder that is not a '
417 'Zephyr build system')
Carles Cufi3a88dce2019-04-18 16:46:12 +0200418
419 cmake_args = ['-P', '{}/cmake/pristine.cmake'.format(zb)]
Marti Bolivar8465cf22019-05-01 17:24:23 -0600420 run_cmake(cmake_args, cwd=self.build_dir, dry_run=self.args.dry_run)
Carles Cufi3a88dce2019-04-18 16:46:12 +0200421
Carles Cufib7c75912019-04-14 21:52:45 +0200422 def _run_build(self, target):
Marti Bolivare6873b82019-06-02 22:48:52 -0600423 if target:
424 _banner('running target {}'.format(target))
425 else:
426 _banner('building application')
Carles Cufib7c75912019-04-14 21:52:45 +0200427 extra_args = ['--target', target] if target else []
Marti Bolivar3a486a82019-05-04 13:32:36 -0600428 if self.args.build_opt:
429 extra_args.append('--')
430 extra_args.extend(self.args.build_opt)
Marti Bolivar0396b6e2019-05-06 18:10:35 -0600431 if self.args.verbose:
432 self._append_verbose_args(extra_args,
433 not bool(self.args.build_opt))
Marti Bolivar8465cf22019-05-01 17:24:23 -0600434 run_build(self.build_dir, extra_args=extra_args,
435 dry_run=self.args.dry_run)
Marti Bolivar0396b6e2019-05-06 18:10:35 -0600436
437 def _append_verbose_args(self, extra_args, add_dashes):
438 # These hacks are only needed for CMake versions earlier than
439 # 3.14. When Zephyr's minimum version is at least that, we can
440 # drop this nonsense and just run "cmake --build BUILD -v".
441 self._update_cache()
442 if not self.cmake_cache:
443 return
444 generator = self.cmake_cache.get('CMAKE_GENERATOR')
445 if not generator:
446 return
447 # Substring matching is for things like "Eclipse CDT4 - Ninja".
448 if 'Ninja' in generator:
449 if add_dashes:
450 extra_args.append('--')
451 extra_args.append('-v')
452 elif generator == 'Unix Makefiles':
453 if add_dashes:
454 extra_args.append('--')
455 extra_args.append('VERBOSE=1')