west: runners: Guess build folder
When using a build folder format with build.dir-fmt that includes any parameters that need resolving, the west runners cannot find the folder since the required information (board, source dir or app) is not available. Add a very simple heuristic to support the case where a build folder starts with a hardcoded prefix (for example 'build/') and a single build is present under that prefix. The heuristic is gated behind a new configuration option: build.guess-dir Signed-off-by: Carles Cufi <carles.cufi@nordicsemi.no>
This commit is contained in:
parent
2192f1d0a4
commit
41f1f648f6
|
@ -219,6 +219,16 @@ You can :ref:`configure <west-config-cmd>` ``west build`` using these options.
|
|||
- String, default ``Ninja``. The `CMake Generator`_ to use to create a
|
||||
build system. (To set a generator for a single build, see the
|
||||
:ref:`above example <west-building-generator>`)
|
||||
* - ``build.guess-dir``
|
||||
- String, instructs west whether to try to guess what build folder to use
|
||||
when ``build.dir-fmt`` is in use and not enough information is available
|
||||
to resolve the build folder name. Can take these values:
|
||||
|
||||
- ``never`` (default): Never try to guess, bail out instead and
|
||||
require the user to provide a build folder with ``-d``.
|
||||
- ``runners``: Try to guess the folder when using any of the 'runner'
|
||||
commands. These are typically all commands that invoke an external
|
||||
tool, such as ``flash`` and ``debug``.
|
||||
* - ``build.pristine``
|
||||
- String. Controls the way in which ``west build`` may clean the build
|
||||
folder before building. Can take the following values:
|
||||
|
|
|
@ -12,6 +12,7 @@ See build.py for the build command itself.
|
|||
|
||||
import zcmake
|
||||
import os
|
||||
from pathlib import Path
|
||||
from west import log
|
||||
from west.configuration import config
|
||||
from west.util import escapes_directory
|
||||
|
@ -28,7 +29,7 @@ build.dir-fmt configuration variable is set) and the current directory are
|
|||
checked, in that order. If one is a Zephyr build directory, it is used.
|
||||
'''.format(DEFAULT_BUILD_DIR)
|
||||
|
||||
def _resolve_build_dir(fmt, cwd, **kwargs):
|
||||
def _resolve_build_dir(fmt, guess, cwd, **kwargs):
|
||||
# Remove any None values, we do not want 'None' as a string
|
||||
kwargs = {k: v for k, v in kwargs.items() if v is not None}
|
||||
# Check if source_dir is below cwd first
|
||||
|
@ -40,9 +41,38 @@ def _resolve_build_dir(fmt, cwd, **kwargs):
|
|||
# no meaningful relative path possible
|
||||
kwargs['source_dir'] = ''
|
||||
|
||||
return fmt.format(**kwargs)
|
||||
try:
|
||||
return fmt.format(**kwargs)
|
||||
except KeyError:
|
||||
if not guess:
|
||||
return None
|
||||
|
||||
def find_build_dir(dir, **kwargs):
|
||||
# Guess the build folder by iterating through all sub-folders from the
|
||||
# root of the format string and trying to resolve. If resolving fails,
|
||||
# proceed to iterate over subfolders only if there is a single folder
|
||||
# present on each iteration.
|
||||
parts = Path(fmt).parts
|
||||
b = Path('.')
|
||||
for p in parts:
|
||||
# default to cwd in the first iteration
|
||||
curr = b
|
||||
b = b.joinpath(p)
|
||||
try:
|
||||
# if fmt is an absolute path, the first iteration will always
|
||||
# resolve '/'
|
||||
b = Path(str(b).format(**kwargs))
|
||||
except KeyError:
|
||||
# Missing key, check sub-folders and match if a single one exists
|
||||
while True:
|
||||
dirs = [f for f in curr.iterdir() if f.is_dir()]
|
||||
if len(dirs) != 1:
|
||||
return None
|
||||
curr = dirs[0]
|
||||
if is_zephyr_build(str(curr)):
|
||||
return str(curr)
|
||||
return str(b)
|
||||
|
||||
def find_build_dir(dir, guess=False, **kwargs):
|
||||
'''Heuristic for finding a build directory.
|
||||
|
||||
The default build directory is computed by reading the build.dir-fmt
|
||||
|
@ -60,12 +90,8 @@ def find_build_dir(dir, **kwargs):
|
|||
else:
|
||||
cwd = os.getcwd()
|
||||
default = config.get('build', 'dir-fmt', fallback=DEFAULT_BUILD_DIR)
|
||||
try:
|
||||
default = _resolve_build_dir(default, cwd, **kwargs)
|
||||
log.dbg('config dir-fmt: {}'.format(default),
|
||||
level=log.VERBOSE_EXTREME)
|
||||
except KeyError:
|
||||
default = None
|
||||
default = _resolve_build_dir(default, guess, cwd, **kwargs)
|
||||
log.dbg('config dir-fmt: {}'.format(default), level=log.VERBOSE_EXTREME)
|
||||
if default and is_zephyr_build(default):
|
||||
build_dir = default
|
||||
elif is_zephyr_build(cwd):
|
||||
|
|
|
@ -19,6 +19,7 @@ from west import util
|
|||
from build_helpers import find_build_dir, is_zephyr_build, \
|
||||
FIND_BUILD_DIR_DESCRIPTION
|
||||
from west.commands import CommandError
|
||||
from west.configuration import config
|
||||
|
||||
from runners import get_runner_cls, ZephyrBinaryRunner, MissingProgram
|
||||
|
||||
|
@ -170,7 +171,9 @@ def _build_dir(args, die_if_none=True):
|
|||
if args.build_dir:
|
||||
return args.build_dir
|
||||
|
||||
dir = find_build_dir(None)
|
||||
guess = config.get('build', 'guess-dir', fallback='never')
|
||||
guess = True if guess == 'runners' else False
|
||||
dir = find_build_dir(None, guess)
|
||||
|
||||
if dir and is_zephyr_build(dir):
|
||||
return dir
|
||||
|
|
Loading…
Reference in a new issue