blob: 79961120d113267663f614fee290e80406a58bee [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
7
8from west import log
Carles Cufib7c75912019-04-14 21:52:45 +02009from west.configuration import config
Jan Van Winkel4d975db2019-05-04 14:44:56 +020010from zcmake import DEFAULT_CMAKE_GENERATOR, run_cmake, run_build, CMakeCache
Marti Bolivar69099e32019-05-04 13:16:15 -060011from build_helpers import is_zephyr_build, find_build_dir, \
Carles Cufi98980c62019-06-05 16:04:29 +020012 FIND_BUILD_DIR_DESCRIPTION
Marti Bolivar8c447992019-01-30 13:53:40 -070013
Carles Cufi31bdad52019-04-26 21:53:02 +020014from zephyr_ext_common import Forceable
Marti Bolivar8c447992019-01-30 13:53:40 -070015
Carles Cufib7101772019-02-21 15:58:19 +010016_ARG_SEPARATOR = '--'
Marti Bolivarab822642019-01-23 08:31:06 -070017
Marti Bolivar1f5e6d82019-05-01 16:48:04 -060018BUILD_USAGE = '''\
19west build [-h] [-b BOARD] [-d BUILD_DIR]
20 [-t TARGET] [-p {auto, always, never}] [-c] [--cmake-only]
Marti Bolivar3a486a82019-05-04 13:32:36 -060021 [-n] [-o BUILD_OPT] [-f]
22 [source_dir] -- [cmake_opt [cmake_opt ...]]
Marti Bolivar1f5e6d82019-05-01 16:48:04 -060023'''
24
Marti Bolivarab822642019-01-23 08:31:06 -070025BUILD_DESCRIPTION = '''\
26Convenience wrapper for building Zephyr applications.
27
Carles Cufib7101772019-02-21 15:58:19 +010028positional arguments:
Marti Bolivar83a5fd82019-05-04 13:56:36 -060029 source_dir Use this path as the source directory
Carles Cufib7101772019-02-21 15:58:19 +010030 cmake_opt Extra options to pass to CMake; implies -c
31'''
Marti Bolivarab822642019-01-23 08:31:06 -070032
Marti Bolivare6873b82019-06-02 22:48:52 -060033def _banner(msg):
34 log.inf('-- west build: ' + msg, colorize=True)
35
Marti Bolivard1595032019-05-04 13:14:28 -060036def config_get(option, fallback):
37 return config.get('build', option, fallback=fallback)
38
39def config_getboolean(option, fallback):
40 return config.getboolean('build', option, fallback=fallback)
41
Carles Cufib7c75912019-04-14 21:52:45 +020042class AlwaysIfMissing(argparse.Action):
43
Marti Bolivar69099e32019-05-04 13:16:15 -060044 def __call__(self, parser, namespace, values, option_string=None):
45 setattr(namespace, self.dest, values or 'always')
Marti Bolivarab822642019-01-23 08:31:06 -070046
Marti Bolivar8c447992019-01-30 13:53:40 -070047class Build(Forceable):
Marti Bolivarab822642019-01-23 08:31:06 -070048
49 def __init__(self):
50 super(Build, self).__init__(
51 'build',
Marti Bolivar808028b2019-01-28 10:45:02 -070052 # Keep this in sync with the string in west-commands.yml.
Marti Bolivarab822642019-01-23 08:31:06 -070053 'compile a Zephyr application',
54 BUILD_DESCRIPTION,
Carles Cufib7101772019-02-21 15:58:19 +010055 accepts_unknown_args=True)
Marti Bolivarab822642019-01-23 08:31:06 -070056
57 self.source_dir = None
58 '''Source directory for the build, or None on error.'''
59
60 self.build_dir = None
61 '''Final build directory used to run the build, or None on error.'''
62
63 self.created_build_dir = False
64 '''True if the build directory was created; False otherwise.'''
65
66 self.run_cmake = False
67 '''True if CMake was run; False otherwise.
68
69 Note: this only describes CMake runs done by this command. The
70 build system generated by CMake may also update itself due to
71 internal logic.'''
72
73 self.cmake_cache = None
74 '''Final parsed CMake cache for the build, or None on error.'''
75
76 def do_add_parser(self, parser_adder):
77 parser = parser_adder.add_parser(
78 self.name,
79 help=self.help,
80 formatter_class=argparse.RawDescriptionHelpFormatter,
Carles Cufib7101772019-02-21 15:58:19 +010081 description=self.description,
Marti Bolivar1f5e6d82019-05-01 16:48:04 -060082 usage=BUILD_USAGE)
Marti Bolivarab822642019-01-23 08:31:06 -070083
84 # Remember to update scripts/west-completion.bash if you add or remove
85 # flags
86
Marti Bolivar88fb8ba2019-05-04 13:14:57 -060087 parser.add_argument('-b', '--board', help='Board to build for')
Carles Cufib7101772019-02-21 15:58:19 +010088 # Hidden option for backwards compatibility
89 parser.add_argument('-s', '--source-dir', help=argparse.SUPPRESS)
Marti Bolivarab822642019-01-23 08:31:06 -070090 parser.add_argument('-d', '--build-dir',
Carles Cufi98980c62019-06-05 16:04:29 +020091 help='Build directory. ' +
92 FIND_BUILD_DIR_DESCRIPTION +
93 " Otherwise the default build directory is " +
94 "created and used.")
Marti Bolivarab822642019-01-23 08:31:06 -070095 parser.add_argument('-t', '--target',
Marti Bolivar83a5fd82019-05-04 13:56:36 -060096 help='''Build system target to run''')
Carles Cufib7c75912019-04-14 21:52:45 +020097 parser.add_argument('-p', '--pristine', choices=['auto', 'always',
98 'never'], action=AlwaysIfMissing, nargs='?',
Carles Cufi3a88dce2019-04-18 16:46:12 +020099 help='''Control whether the build folder is made
Marti Bolivar83a5fd82019-05-04 13:56:36 -0600100 pristine before running CMake. --pristine is the
101 same as --pristine=always. If 'auto', it will
102 be made pristine only if needed.''')
Marti Bolivarab822642019-01-23 08:31:06 -0700103 parser.add_argument('-c', '--cmake', action='store_true',
104 help='Force CMake to run')
Marti Bolivar1f5e6d82019-05-01 16:48:04 -0600105 parser.add_argument('--cmake-only', action='store_true',
106 help="Just run CMake; don't build. Implies -c.")
Marti Bolivar8465cf22019-05-01 17:24:23 -0600107 parser.add_argument('-n', '--just-print', '--dry-run', '--recon',
108 dest='dry_run', action='store_true',
Marti Bolivar83a5fd82019-05-04 13:56:36 -0600109 help='''Just print the build commands; don't run
110 them''')
Marti Bolivar3a486a82019-05-04 13:32:36 -0600111 parser.add_argument('-o', '--build-opt', default=[], action='append',
112 help='''Options to pass to the build tool.
113 May be given more than once to append multiple
114 values.''')
Marti Bolivar8c447992019-01-30 13:53:40 -0700115 self.add_force_arg(parser)
Marti Bolivarab822642019-01-23 08:31:06 -0700116 return parser
117
Carles Cufib7101772019-02-21 15:58:19 +0100118 def do_run(self, args, remainder):
Marti Bolivarab822642019-01-23 08:31:06 -0700119 self.args = args # Avoid having to pass them around
Marti Bolivar8b9b7e72019-05-23 09:31:31 -0600120 self.config_board = config_get('board', None)
Marti Bolivara1ef6962019-05-01 17:06:15 -0600121 log.dbg('args: {} remainder: {}'.format(args, remainder),
122 level=log.VERBOSE_EXTREME)
Carles Cufib7101772019-02-21 15:58:19 +0100123 # Store legacy -s option locally
124 source_dir = self.args.source_dir
125 self._parse_remainder(remainder)
126 if source_dir:
127 if self.args.source_dir:
128 log.die("source directory specified twice:({} and {})".format(
129 source_dir, self.args.source_dir))
130 self.args.source_dir = source_dir
131 log.dbg('source_dir: {} cmake_opts: {}'.format(self.args.source_dir,
Marti Bolivara1ef6962019-05-01 17:06:15 -0600132 self.args.cmake_opts),
133 level=log.VERBOSE_EXTREME)
Marti Bolivarab822642019-01-23 08:31:06 -0700134 self._sanity_precheck()
135 self._setup_build_dir()
Carles Cufib7c75912019-04-14 21:52:45 +0200136
137 if args.pristine is not None:
138 pristine = args.pristine
139 else:
140 # Load the pristine={auto, always, never} configuration value
Marti Bolivard1595032019-05-04 13:14:28 -0600141 pristine = config_get('pristine', 'never')
Carles Cufib7c75912019-04-14 21:52:45 +0200142 if pristine not in ['auto', 'always', 'never']:
Marti Bolivar69099e32019-05-04 13:16:15 -0600143 log.wrn(
144 'treating unknown build.pristine value "{}" as "never"'.
145 format(pristine))
Carles Cufib7c75912019-04-14 21:52:45 +0200146 pristine = 'never'
147 self.auto_pristine = (pristine == 'auto')
148
149 log.dbg('pristine: {} auto_pristine: {}'.format(pristine,
Marti Bolivara1ef6962019-05-01 17:06:15 -0600150 self.auto_pristine),
151 level=log.VERBOSE_VERY)
Marti Bolivarab822642019-01-23 08:31:06 -0700152 if is_zephyr_build(self.build_dir):
Carles Cufib7c75912019-04-14 21:52:45 +0200153 if pristine == 'always':
Carles Cufi3a88dce2019-04-18 16:46:12 +0200154 self._run_pristine()
Marti Bolivarab822642019-01-23 08:31:06 -0700155 self.run_cmake = True
Carles Cufib7c75912019-04-14 21:52:45 +0200156 else:
157 self._update_cache()
Marti Bolivar1f5e6d82019-05-01 16:48:04 -0600158 if (self.args.cmake or self.args.cmake_opts or
159 self.args.cmake_only):
Carles Cufib7c75912019-04-14 21:52:45 +0200160 self.run_cmake = True
Marti Bolivarab822642019-01-23 08:31:06 -0700161 else:
162 self.run_cmake = True
Carles Cufi98980c62019-06-05 16:04:29 +0200163 self.source_dir = self._find_source_dir()
Marti Bolivarab822642019-01-23 08:31:06 -0700164 self._sanity_check()
165
Marti Bolivar88fb8ba2019-05-04 13:14:57 -0600166 board, origin = self._find_board()
167 self._run_cmake(board, origin, self.args.cmake_opts)
Marti Bolivar1f5e6d82019-05-01 16:48:04 -0600168 if args.cmake_only:
169 return
170
Marti Bolivarab822642019-01-23 08:31:06 -0700171 self._sanity_check()
172 self._update_cache()
173
Carles Cufib7c75912019-04-14 21:52:45 +0200174 self._run_build(args.target)
Marti Bolivarab822642019-01-23 08:31:06 -0700175
Marti Bolivar88fb8ba2019-05-04 13:14:57 -0600176 def _find_board(self):
177 board, origin = None, None
Marti Bolivar88fb8ba2019-05-04 13:14:57 -0600178 if self.cmake_cache:
179 board, origin = (self.cmake_cache.get('CACHED_BOARD'),
180 'CMakeCache.txt')
181 elif self.args.board:
182 board, origin = self.args.board, 'command line'
183 elif 'BOARD' in os.environ:
184 board, origin = os.environ['BOARD'], 'env'
Marti Bolivar8b9b7e72019-05-23 09:31:31 -0600185 elif self.config_board is not None:
186 board, origin = self.config_board, 'configfile'
Marti Bolivar88fb8ba2019-05-04 13:14:57 -0600187 return board, origin
188
Carles Cufib7101772019-02-21 15:58:19 +0100189 def _parse_remainder(self, remainder):
190 self.args.source_dir = None
191 self.args.cmake_opts = None
192 try:
193 # Only one source_dir is allowed, as the first positional arg
194 if remainder[0] != _ARG_SEPARATOR:
195 self.args.source_dir = remainder[0]
196 remainder = remainder[1:]
197 # Only the first argument separator is consumed, the rest are
198 # passed on to CMake
199 if remainder[0] == _ARG_SEPARATOR:
200 remainder = remainder[1:]
Ulf Magnusson5d307c92019-09-02 15:35:56 +0200201 if remainder:
Carles Cufib7101772019-02-21 15:58:19 +0100202 self.args.cmake_opts = remainder
203 except IndexError:
204 return
205
Marti Bolivarab822642019-01-23 08:31:06 -0700206 def _sanity_precheck(self):
207 app = self.args.source_dir
208 if app:
Marti Bolivar8c447992019-01-30 13:53:40 -0700209 self.check_force(
210 os.path.isdir(app),
211 'source directory {} does not exist'.format(app))
212 self.check_force(
213 'CMakeLists.txt' in os.listdir(app),
214 "{} doesn't contain a CMakeLists.txt".format(app))
Marti Bolivarab822642019-01-23 08:31:06 -0700215
216 def _update_cache(self):
217 try:
Carles Cufi31bdad52019-04-26 21:53:02 +0200218 self.cmake_cache = CMakeCache.from_build_dir(self.build_dir)
Marti Bolivarab822642019-01-23 08:31:06 -0700219 except FileNotFoundError:
220 pass
221
222 def _setup_build_dir(self):
223 # Initialize build_dir and created_build_dir attributes.
Marti Bolivar8c447992019-01-30 13:53:40 -0700224 # If we created the build directory, we must run CMake.
Marti Bolivarab822642019-01-23 08:31:06 -0700225 log.dbg('setting up build directory', level=log.VERBOSE_EXTREME)
Carles Cufi98980c62019-06-05 16:04:29 +0200226 # The CMake Cache has not been loaded yet, so this is safe
Ulf Magnusson89efaed2019-09-05 13:44:09 +0200227 board, _ = self._find_board()
Carles Cufi98980c62019-06-05 16:04:29 +0200228 source_dir = self._find_source_dir()
229 app = os.path.split(source_dir)[1]
230 build_dir = find_build_dir(self.args.build_dir, board=board,
231 source_dir=source_dir, app=app)
232 if not build_dir:
233 log.die('Unable to determine a default build folder. Check '
234 'your build.dir-fmt configuration option')
Marti Bolivarab822642019-01-23 08:31:06 -0700235
236 if os.path.exists(build_dir):
237 if not os.path.isdir(build_dir):
238 log.die('build directory {} exists and is not a directory'.
239 format(build_dir))
240 else:
241 os.makedirs(build_dir, exist_ok=False)
242 self.created_build_dir = True
243 self.run_cmake = True
244
245 self.build_dir = build_dir
246
Carles Cufi98980c62019-06-05 16:04:29 +0200247 def _find_source_dir(self):
Marti Bolivarab822642019-01-23 08:31:06 -0700248 # Initialize source_dir attribute, either from command line argument,
249 # implicitly from the build directory's CMake cache, or using the
250 # default (current working directory).
251 log.dbg('setting up source directory', level=log.VERBOSE_EXTREME)
252 if self.args.source_dir:
253 source_dir = self.args.source_dir
254 elif self.cmake_cache:
Marti Bolivaracda2572019-04-10 17:09:17 -0600255 source_dir = self.cmake_cache.get('CMAKE_HOME_DIRECTORY')
Marti Bolivarab822642019-01-23 08:31:06 -0700256 if not source_dir:
Marti Bolivaracda2572019-04-10 17:09:17 -0600257 # This really ought to be there. The build directory
258 # must be corrupted somehow. Let's see what we can do.
259 log.die('build directory', self.build_dir,
260 'CMake cache has no CMAKE_HOME_DIRECTORY;',
261 'please give a source_dir')
Marti Bolivarab822642019-01-23 08:31:06 -0700262 else:
263 source_dir = os.getcwd()
Carles Cufi98980c62019-06-05 16:04:29 +0200264 return os.path.abspath(source_dir)
Marti Bolivarab822642019-01-23 08:31:06 -0700265
Carles Cufib7c75912019-04-14 21:52:45 +0200266 def _sanity_check_source_dir(self):
Marti Bolivarab822642019-01-23 08:31:06 -0700267 if self.source_dir == self.build_dir:
268 # There's no forcing this.
269 log.die('source and build directory {} cannot be the same; '
270 'use --build-dir {} to specify a build directory'.
271 format(self.source_dir, self.build_dir))
272
273 srcrel = os.path.relpath(self.source_dir)
Marti Bolivar8c447992019-01-30 13:53:40 -0700274 self.check_force(
275 not is_zephyr_build(self.source_dir),
276 'it looks like {srcrel} is a build directory: '
277 'did you mean --build-dir {srcrel} instead?'.
278 format(srcrel=srcrel))
279 self.check_force(
280 'CMakeLists.txt' in os.listdir(self.source_dir),
281 'source directory "{srcrel}" does not contain '
282 'a CMakeLists.txt; is this really what you '
283 'want to build? (Use -s SOURCE_DIR to specify '
284 'the application source directory)'.
285 format(srcrel=srcrel))
Carles Cufib7c75912019-04-14 21:52:45 +0200286
287 def _sanity_check(self):
288 # Sanity check the build configuration.
289 # Side effect: may update cmake_cache attribute.
290 log.dbg('sanity checking the build', level=log.VERBOSE_EXTREME)
291 self._sanity_check_source_dir()
292
Marti Bolivarab822642019-01-23 08:31:06 -0700293 if not self.cmake_cache:
294 return # That's all we can check without a cache.
295
296 cached_app = self.cmake_cache.get('APPLICATION_SOURCE_DIR')
297 log.dbg('APPLICATION_SOURCE_DIR:', cached_app,
298 level=log.VERBOSE_EXTREME)
299 source_abs = (os.path.abspath(self.args.source_dir)
300 if self.args.source_dir else None)
301 cached_abs = os.path.abspath(cached_app) if cached_app else None
Marti Bolivar8c447992019-01-30 13:53:40 -0700302
Carles Cufib7c75912019-04-14 21:52:45 +0200303 log.dbg('pristine:', self.auto_pristine, level=log.VERBOSE_EXTREME)
Marti Bolivar8c447992019-01-30 13:53:40 -0700304 # If the build directory specifies a source app, make sure it's
305 # consistent with --source-dir.
306 apps_mismatched = (source_abs and cached_abs and
307 source_abs != cached_abs)
308 self.check_force(
Carles Cufib7c75912019-04-14 21:52:45 +0200309 not apps_mismatched or self.auto_pristine,
Marti Bolivar8c447992019-01-30 13:53:40 -0700310 'Build directory "{}" is for application "{}", but source '
Carles Cufib7c75912019-04-14 21:52:45 +0200311 'directory "{}" was specified; please clean it, use --pristine, '
312 'or use --build-dir to set another build directory'.
Marti Bolivar8c447992019-01-30 13:53:40 -0700313 format(self.build_dir, cached_abs, source_abs))
314 if apps_mismatched:
Marti Bolivarab822642019-01-23 08:31:06 -0700315 self.run_cmake = True # If they insist, we need to re-run cmake.
316
Marti Bolivar8b9b7e72019-05-23 09:31:31 -0600317 # If CACHED_BOARD is not defined, we need some other way to
318 # find the board.
Marti Bolivarab822642019-01-23 08:31:06 -0700319 cached_board = self.cmake_cache.get('CACHED_BOARD')
320 log.dbg('CACHED_BOARD:', cached_board, level=log.VERBOSE_EXTREME)
Marti Bolivar8b9b7e72019-05-23 09:31:31 -0600321 # If apps_mismatched and self.auto_pristine are true, we will
322 # run pristine on the build, invalidating the cached
323 # board. In that case, we need some way of getting the board.
Carles Cufib7c75912019-04-14 21:52:45 +0200324 self.check_force((cached_board and
325 not (apps_mismatched and self.auto_pristine))
Marti Bolivar8b9b7e72019-05-23 09:31:31 -0600326 or self.args.board or self.config_board or
327 os.environ.get('BOARD'),
328 'Cached board not defined, please provide it '
329 '(provide --board, set default with '
330 '"west config build.board <BOARD>", or set '
331 'BOARD in the environment)')
Marti Bolivarab822642019-01-23 08:31:06 -0700332
Marti Bolivar8c447992019-01-30 13:53:40 -0700333 # Check consistency between cached board and --board.
334 boards_mismatched = (self.args.board and cached_board and
335 self.args.board != cached_board)
336 self.check_force(
Carles Cufib7c75912019-04-14 21:52:45 +0200337 not boards_mismatched or self.auto_pristine,
Marti Bolivar8c447992019-01-30 13:53:40 -0700338 'Build directory {} targets board {}, but board {} was specified. '
Carles Cufib7c75912019-04-14 21:52:45 +0200339 '(Clean the directory, use --pristine, or use --build-dir to '
340 'specify a different one.)'.
Marti Bolivar8c447992019-01-30 13:53:40 -0700341 format(self.build_dir, cached_board, self.args.board))
Marti Bolivarab822642019-01-23 08:31:06 -0700342
Carles Cufib7c75912019-04-14 21:52:45 +0200343 if self.auto_pristine and (apps_mismatched or boards_mismatched):
Carles Cufi3a88dce2019-04-18 16:46:12 +0200344 self._run_pristine()
Carles Cufib7c75912019-04-14 21:52:45 +0200345 self.cmake_cache = None
346 log.dbg('run_cmake:', True, level=log.VERBOSE_EXTREME)
347 self.run_cmake = True
348
349 # Tricky corner-case: The user has not specified a build folder but
350 # there was one in the CMake cache. Since this is going to be
351 # invalidated, reset to CWD and re-run the basic tests.
352 if ((boards_mismatched and not apps_mismatched) and
Marti Bolivar69099e32019-05-04 13:16:15 -0600353 (not source_abs and cached_abs)):
Carles Cufi98980c62019-06-05 16:04:29 +0200354 self.source_dir = self._find_source_dir()
Carles Cufib7c75912019-04-14 21:52:45 +0200355 self._sanity_check_source_dir()
356
Marti Bolivar88fb8ba2019-05-04 13:14:57 -0600357 def _run_cmake(self, board, origin, cmake_opts):
Marti Bolivare6873b82019-06-02 22:48:52 -0600358 _banner(
359 '''build configuration:
360 source directory: {}
361 build directory: {}{}
362 BOARD: {}'''.
363 format(self.source_dir, self.build_dir,
364 ' (created)' if self.created_build_dir else '',
365 ('{} (origin: {})'.format(board, origin) if board
366 else 'UNKNOWN')))
Marti Bolivar88fb8ba2019-05-04 13:14:57 -0600367
368 if board is None and config_getboolean('board_warn', True):
369 log.wrn('This looks like a fresh build and BOARD is unknown;',
370 "so it probably won't work. To fix, use",
371 '--board=<your-board>.')
372 log.inf('Note: to silence the above message, run',
373 "'west config build.board_warn false'")
374
Marti Bolivarab822642019-01-23 08:31:06 -0700375 if not self.run_cmake:
Marti Bolivara1ef6962019-05-01 17:06:15 -0600376 log.dbg('Not generating a build system; one is present.')
Marti Bolivarab822642019-01-23 08:31:06 -0700377 return
378
Marti Bolivare6873b82019-06-02 22:48:52 -0600379 _banner('generating a build system')
380
Marti Bolivar88fb8ba2019-05-04 13:14:57 -0600381 if board is not None and origin != 'CMakeCache.txt':
382 cmake_opts = ['-DBOARD={}'.format(board)]
383 else:
384 cmake_opts = []
385 if self.args.cmake_opts:
386 cmake_opts.extend(self.args.cmake_opts)
387
Carles Cufi3c6584d2019-04-14 21:51:16 +0200388 # Invoke CMake from the current working directory using the
389 # -S and -B options (officially introduced in CMake 3.13.0).
390 # This is important because users expect invocations like this
391 # to Just Work:
Marti Bolivarab822642019-01-23 08:31:06 -0700392 #
393 # west build -- -DOVERLAY_CONFIG=relative-path.conf
394 final_cmake_args = ['-B{}'.format(self.build_dir),
Carles Cufi3c6584d2019-04-14 21:51:16 +0200395 '-S{}'.format(self.source_dir),
Marti Bolivarbbe890a2019-05-01 16:53:32 -0600396 '-G{}'.format(config_get('generator',
397 DEFAULT_CMAKE_GENERATOR))]
Marti Bolivarab822642019-01-23 08:31:06 -0700398 if cmake_opts:
399 final_cmake_args.extend(cmake_opts)
Marti Bolivar8465cf22019-05-01 17:24:23 -0600400 run_cmake(final_cmake_args, dry_run=self.args.dry_run)
Carles Cufib7c75912019-04-14 21:52:45 +0200401
Carles Cufi3a88dce2019-04-18 16:46:12 +0200402 def _run_pristine(self):
Marti Bolivare6873b82019-06-02 22:48:52 -0600403 _banner('making build dir {} pristine'.format(self.build_dir))
Carles Cufi3a88dce2019-04-18 16:46:12 +0200404
405 zb = os.environ.get('ZEPHYR_BASE')
406 if not zb:
407 log.die('Internal error: ZEPHYR_BASE not set in the environment, '
408 'and should have been by the main script')
409
410 if not is_zephyr_build(self.build_dir):
Marti Bolivar69099e32019-05-04 13:16:15 -0600411 log.die('Refusing to run pristine on a folder that is not a '
412 'Zephyr build system')
Carles Cufi3a88dce2019-04-18 16:46:12 +0200413
414 cmake_args = ['-P', '{}/cmake/pristine.cmake'.format(zb)]
Marti Bolivar8465cf22019-05-01 17:24:23 -0600415 run_cmake(cmake_args, cwd=self.build_dir, dry_run=self.args.dry_run)
Carles Cufi3a88dce2019-04-18 16:46:12 +0200416
Carles Cufib7c75912019-04-14 21:52:45 +0200417 def _run_build(self, target):
Marti Bolivare6873b82019-06-02 22:48:52 -0600418 if target:
419 _banner('running target {}'.format(target))
420 else:
421 _banner('building application')
Carles Cufib7c75912019-04-14 21:52:45 +0200422 extra_args = ['--target', target] if target else []
Marti Bolivar3a486a82019-05-04 13:32:36 -0600423 if self.args.build_opt:
424 extra_args.append('--')
425 extra_args.extend(self.args.build_opt)
Marti Bolivar0396b6e2019-05-06 18:10:35 -0600426 if self.args.verbose:
427 self._append_verbose_args(extra_args,
428 not bool(self.args.build_opt))
Marti Bolivar8465cf22019-05-01 17:24:23 -0600429 run_build(self.build_dir, extra_args=extra_args,
430 dry_run=self.args.dry_run)
Marti Bolivar0396b6e2019-05-06 18:10:35 -0600431
432 def _append_verbose_args(self, extra_args, add_dashes):
433 # These hacks are only needed for CMake versions earlier than
434 # 3.14. When Zephyr's minimum version is at least that, we can
435 # drop this nonsense and just run "cmake --build BUILD -v".
436 self._update_cache()
437 if not self.cmake_cache:
438 return
439 generator = self.cmake_cache.get('CMAKE_GENERATOR')
440 if not generator:
441 return
442 # Substring matching is for things like "Eclipse CDT4 - Ninja".
443 if 'Ninja' in generator:
444 if add_dashes:
445 extra_args.append('--')
446 extra_args.append('-v')
447 elif generator == 'Unix Makefiles':
448 if add_dashes:
449 extra_args.append('--')
450 extra_args.append('VERBOSE=1')