Skip to content

Commit b7c7591

Browse files
carlescufinashif
authored andcommitted
west: build: Add new pristine cmd-line and config option
Add a new command-line and build config option, `pristine`, that the user can pass to `west build` or set in its configuration file(s) in order to automatically trigger a pristine build on every build or whenever west considers it required. The option can take the following values: - never: Never run the target - always: Always run the pristine target before building - auto: Run the pristine target when required With `auto`, the pristine target will be run when running west with an existing build folder containing a build system and: - Selecting a different board from the one currently in the build system - Selecting a different application from the one currently in the build system Signed-off-by: Carles Cufi <[email protected]>
1 parent 3c6584d commit b7c7591

File tree

3 files changed

+118
-16
lines changed

3 files changed

+118
-16
lines changed

doc/guides/west/build-flash-debug.rst

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,18 @@ Additionally you can specify the build system target using the ``--target``
7373
You can list all targets with ``ninja help`` (or ``west build -t help``) inside
7474
the build folder.
7575

76+
A clean build can be triggered by using the ``--pristine`` (or ``-p``) option.
77+
This is particularly handy if you want to switch source dirs or boards without
78+
using a different build dir::
79+
80+
west build -b qemu_x86 samples/philosophers
81+
west build -p -b reel_board samples/hello_world
82+
83+
If you are unsure about whether the command-line parameters you supply to
84+
``west build`` require a clean build you can let west decide for you by using
85+
the ``auto`` setting in the ``--pristine`` option::
86+
87+
west build -p auto -b reel_board samples/hello_world
7688

7789
Finally, you can add additional arguments to the CMake invocation performed by
7890
``west build`` by supplying additional parameters (after a ``--``) to the

doc/guides/west/config.rst

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,3 +150,29 @@ commands.
150150
environment overrides the value of the ``zephyr.base`` configuration
151151
option. If set to ``"configfile"``, the configuration option wins
152152
instead.
153+
154+
Zephyr Extension Commands Configuration Options
155+
-----------------------------------------------
156+
157+
The following table documents configuration options supported by zephyr's
158+
extension commands (found in :file:`scripts/west_commands`).
159+
.. NOTE: docs authors: keep this table sorted by section, then option.
160+
161+
.. list-table::
162+
:widths: 10 30
163+
:header-rows: 1
164+
165+
* - Option
166+
- Description
167+
* - ``build.pristine``
168+
- String. Controls the way in which ``west build`` may run the ``pristine``
169+
target before building. Can take the following values:
170+
171+
- ``never`` (default): Never automatically run the ``pristine`` target.
172+
- ``auto``: ``west build`` will automatically run the ``pristine``
173+
target before building, if a build system is present and the build
174+
will fail otherwise (e.g. the user has specified a different board or
175+
application from the one previously used to make the build
176+
directory).
177+
- ``always``: Always run the ``pristine`` target before building, if
178+
a build system is present.

scripts/west_commands/build.py

Lines changed: 80 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
from west import log
99
from west import cmake
10+
from west.configuration import config
1011
from west.build import DEFAULT_CMAKE_GENERATOR, is_zephyr_build
1112

1213
from zephyr_ext_common import find_build_dir, Forceable, BUILD_DIR_DESCRIPTION
@@ -52,6 +53,10 @@
5253
cmake_opt Extra options to pass to CMake; implies -c
5354
'''
5455

56+
class AlwaysIfMissing(argparse.Action):
57+
58+
def __call__(self, parser, namespace, values, option_string=None):
59+
setattr(namespace, self.dest, values or 'always')
5560

5661
class Build(Forceable):
5762

@@ -89,7 +94,7 @@ def do_add_parser(self, parser_adder):
8994
formatter_class=argparse.RawDescriptionHelpFormatter,
9095
description=self.description,
9196
usage='''west build [-h] [-b BOARD] [-d BUILD_DIR]
92-
[-t TARGET] [-c] [-f] [source_dir]
97+
[-t TARGET] [-p {auto, always, never}] [-c] [-f] [source_dir]
9398
-- [cmake_opt [cmake_opt ...]]''')
9499

95100
# Remember to update scripts/west-completion.bash if you add or remove
@@ -106,6 +111,17 @@ def do_add_parser(self, parser_adder):
106111
parser.add_argument('-t', '--target',
107112
help='''Override the build system target (e.g.
108113
'clean', 'pristine', etc.)''')
114+
parser.add_argument('-p', '--pristine', choices=['auto', 'always',
115+
'never'], action=AlwaysIfMissing, nargs='?',
116+
help='''Control whether the pristine target is run
117+
before building if a build system is present in the
118+
build dir. --pristine is the same as
119+
--pristine=always. If set to auto, the pristine
120+
target will be run only if required based on the
121+
existing build system and the options provided.
122+
This allows for reusing a build folder even if it
123+
contains build files for a different board or
124+
application.''')
109125
parser.add_argument('-c', '--cmake', action='store_true',
110126
help='Force CMake to run')
111127
self.add_force_arg(parser)
@@ -127,10 +143,29 @@ def do_run(self, args, remainder):
127143
self.args.cmake_opts))
128144
self._sanity_precheck()
129145
self._setup_build_dir()
146+
147+
if args.pristine is not None:
148+
pristine = args.pristine
149+
else:
150+
# Load the pristine={auto, always, never} configuration value
151+
pristine = config.get('build', 'pristine', fallback='never')
152+
if pristine not in ['auto', 'always', 'never']:
153+
log.wrn('treating unknown build.pristine value "{}" as "never"'.
154+
format(pristine))
155+
pristine = 'never'
156+
self.auto_pristine = (pristine == 'auto')
157+
158+
log.dbg('pristine: {} auto_pristine: {}'.format(pristine,
159+
self.auto_pristine))
130160
if is_zephyr_build(self.build_dir):
131-
self._update_cache()
132-
if self.args.cmake or self.args.cmake_opts:
161+
if pristine == 'always':
162+
log.inf('Making build dir {} pristine'.format(self.build_dir))
163+
self._run_build('pristine')
133164
self.run_cmake = True
165+
else:
166+
self._update_cache()
167+
if self.args.cmake or self.args.cmake_opts:
168+
self.run_cmake = True
134169
else:
135170
self.run_cmake = True
136171
self._setup_source_dir()
@@ -154,8 +189,7 @@ def do_run(self, args, remainder):
154189
self._sanity_check()
155190
self._update_cache()
156191

157-
extra_args = ['--target', args.target] if args.target else []
158-
cmake.run_build(self.build_dir, extra_args=extra_args)
192+
self._run_build(args.target)
159193

160194
def _parse_remainder(self, remainder):
161195
self.args.source_dir = None
@@ -226,10 +260,7 @@ def _setup_source_dir(self):
226260
source_dir = os.getcwd()
227261
self.source_dir = os.path.abspath(source_dir)
228262

229-
def _sanity_check(self):
230-
# Sanity check the build configuration.
231-
# Side effect: may update cmake_cache attribute.
232-
log.dbg('sanity checking the build', level=log.VERBOSE_EXTREME)
263+
def _sanity_check_source_dir(self):
233264
if self.source_dir == self.build_dir:
234265
# There's no forcing this.
235266
log.die('source and build directory {} cannot be the same; '
@@ -249,6 +280,13 @@ def _sanity_check(self):
249280
'want to build? (Use -s SOURCE_DIR to specify '
250281
'the application source directory)'.
251282
format(srcrel=srcrel))
283+
284+
def _sanity_check(self):
285+
# Sanity check the build configuration.
286+
# Side effect: may update cmake_cache attribute.
287+
log.dbg('sanity checking the build', level=log.VERBOSE_EXTREME)
288+
self._sanity_check_source_dir()
289+
252290
self.check_force(
253291
is_zephyr_build(self.build_dir) or self.args.board,
254292
'this looks like a new or clean build, please provide --board')
@@ -263,15 +301,16 @@ def _sanity_check(self):
263301
if self.args.source_dir else None)
264302
cached_abs = os.path.abspath(cached_app) if cached_app else None
265303

304+
log.dbg('pristine:', self.auto_pristine, level=log.VERBOSE_EXTREME)
266305
# If the build directory specifies a source app, make sure it's
267306
# consistent with --source-dir.
268307
apps_mismatched = (source_abs and cached_abs and
269308
source_abs != cached_abs)
270309
self.check_force(
271-
not apps_mismatched,
310+
not apps_mismatched or self.auto_pristine,
272311
'Build directory "{}" is for application "{}", but source '
273-
'directory "{}" was specified; please clean it or use --build-dir '
274-
'to set another build directory'.
312+
'directory "{}" was specified; please clean it, use --pristine, '
313+
'or use --build-dir to set another build directory'.
275314
format(self.build_dir, cached_abs, source_abs))
276315
if apps_mismatched:
277316
self.run_cmake = True # If they insist, we need to re-run cmake.
@@ -280,19 +319,40 @@ def _sanity_check(self):
280319
# command line.
281320
cached_board = self.cmake_cache.get('CACHED_BOARD')
282321
log.dbg('CACHED_BOARD:', cached_board, level=log.VERBOSE_EXTREME)
283-
self.check_force(cached_board or self.args.board,
322+
# If app_mismatched and pristine are true we will run pristine on the
323+
# build, invalidating the cached board. Whenever we run pristine we
324+
# require the user to provide all the require inputs again.
325+
self.check_force((cached_board and
326+
not (apps_mismatched and self.auto_pristine))
327+
or self.args.board,
284328
'Cached board not defined, please provide --board')
285329

286330
# Check consistency between cached board and --board.
287331
boards_mismatched = (self.args.board and cached_board and
288332
self.args.board != cached_board)
289333
self.check_force(
290-
not boards_mismatched,
334+
not boards_mismatched or self.auto_pristine,
291335
'Build directory {} targets board {}, but board {} was specified. '
292-
'(Clean the directory or use --build-dir to specify a different '
293-
'one.)'.
336+
'(Clean the directory, use --pristine, or use --build-dir to '
337+
'specify a different one.)'.
294338
format(self.build_dir, cached_board, self.args.board))
295339

340+
if self.auto_pristine and (apps_mismatched or boards_mismatched):
341+
log.inf('Making build dir {} pristine'.format(self.build_dir))
342+
self._run_build('pristine')
343+
self.cmake_cache = None
344+
log.dbg('run_cmake:', True, level=log.VERBOSE_EXTREME)
345+
self.run_cmake = True
346+
347+
# Tricky corner-case: The user has not specified a build folder but
348+
# there was one in the CMake cache. Since this is going to be
349+
# invalidated, reset to CWD and re-run the basic tests.
350+
if ((boards_mismatched and not apps_mismatched) and
351+
(not source_abs and cached_abs)):
352+
self._setup_source_dir()
353+
self._sanity_check_source_dir()
354+
355+
296356
def _run_cmake(self, cmake_opts):
297357
if not self.run_cmake:
298358
log.dbg('not running cmake; build system is present')
@@ -312,3 +372,7 @@ def _run_cmake(self, cmake_opts):
312372
if cmake_opts:
313373
final_cmake_args.extend(cmake_opts)
314374
cmake.run_cmake(final_cmake_args)
375+
376+
def _run_build(self, target):
377+
extra_args = ['--target', target] if target else []
378+
cmake.run_build(self.build_dir, extra_args=extra_args)

0 commit comments

Comments
 (0)