west: build: Configurable build folder format
Add the possibility of configuring the build folder format in west's configuration system. The build.dir-fmt configuration option controls how west will create build folders when not specified, the following parameters are currently accepted: - board: The board name - source_dir: The relative path from CWD to the source directory - app: The name of the source directory If CWD is below source_dir in the directory hierarchy then source_dir is set to an empty string. This means that if one sets: [build] dir-fmt = build/{board}/{source_dir} Then when building samples/hello_world from zephyr's root for the reel_board the build folder will be: ./build/reel_board/samples/hello_world but when building it from inside the samples/hello_world folder it will instead be: ./build/reel_board Fixes https://github.com/zephyrproject-rtos/west/issues/124 Signed-off-by: Carles Cufi <carles.cufi@nordicsemi.no> Signed-off-by: Marti Bolivar <marti.bolivar@nordicsemi.no>
This commit is contained in:
parent
49c4b1c303
commit
98980c6b7c
|
@ -32,19 +32,15 @@ Building: ``west build``
|
|||
The ``build`` command helps you build Zephyr applications from source. You can
|
||||
use :ref:`west config <west-config-cmd>` to configure its behavior.
|
||||
|
||||
This command attempts to "do what you mean" when run from a Zephyr application
|
||||
source or build directory:
|
||||
Its default behavior tries to "do what you mean":
|
||||
|
||||
- When you run ``west build`` in an existing build directory, the board, source
|
||||
directory, etc. are obtained from the CMake cache, and that build directory
|
||||
is re-compiled.
|
||||
- If there is a Zephyr build directory named :file:`build` in your current
|
||||
working directory, it is incrementally re-compiled. The same is true if you
|
||||
run ``west build`` from a Zephyr build directory.
|
||||
|
||||
- The same is true if a Zephyr build directory named :file:`build` exists in
|
||||
your current working directory.
|
||||
|
||||
- Otherwise, the source directory defaults to the current working directory, so
|
||||
running ``west build`` from a Zephyr application's source directory compiles
|
||||
it.
|
||||
- Otherwise, if you run ``west build`` from a Zephyr application's source
|
||||
directory and no build directory is found, a new one is created and the
|
||||
application is compiled in it.
|
||||
|
||||
Basics
|
||||
======
|
||||
|
@ -66,15 +62,23 @@ exactly the same name you would supply to CMake if you were to invoke it with:
|
|||
|
||||
A build directory named :file:`build` will be created, and the application will
|
||||
be compiled there after ``west build`` runs CMake to create a build system in
|
||||
that directory. If you run ``west build`` with an existing build directory, the
|
||||
application is incrementally re-compiled without re-running CMake (you can
|
||||
force CMake to run again with ``--cmake``).
|
||||
that directory. If ``west build`` finds an existing build directory, the
|
||||
application is incrementally re-compiled there without re-running CMake. You
|
||||
can force CMake to run again with ``--cmake``.
|
||||
|
||||
You don't need to use the ``--board`` option if you've already got an existing
|
||||
build directory; ``west build`` can figure out the board from the CMake cache.
|
||||
For new builds, the ``--board`` option, :envvar:`BOARD` environment variable,
|
||||
or ``build.board`` configuration option are checked (in that order).
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
Here are some ``west build`` usage examples, grouped by area.
|
||||
|
||||
Setting a Default Board
|
||||
-----------------------
|
||||
|
||||
To configure ``west build`` to build for the ``reel_board`` by default::
|
||||
|
||||
west config build.board reel_board
|
||||
|
@ -82,15 +86,36 @@ To configure ``west build`` to build for the ``reel_board`` by default::
|
|||
(You can use any other board supported by Zephyr here; it doesn't have to be
|
||||
``reel_board``.)
|
||||
|
||||
To use another build directory, use ``--build-dir`` (or ``-d``)::
|
||||
.. _west-building-dirs:
|
||||
|
||||
west build -b <BOARD> --build-dir path/to/build/directory
|
||||
Setting Source and Build Directories
|
||||
------------------------------------
|
||||
|
||||
To specify the application source directory explicitly, give its path as a
|
||||
To set the application source directory explicitly, give its path as a
|
||||
positional argument::
|
||||
|
||||
west build -b <BOARD> path/to/source/directory
|
||||
|
||||
To set the build directory explicitly, use ``--build-dir`` (or ``-d``)::
|
||||
|
||||
west build -b <BOARD> --build-dir path/to/build/directory
|
||||
|
||||
To change the default build directory from :file:`build`, use the
|
||||
``build.dir-fmt`` configuration option. This lets you name build
|
||||
directories using format strings, like this::
|
||||
|
||||
west config build.dir-fmt "build/{board}/{app}"
|
||||
|
||||
With the above, running ``west build -b reel_board samples/hello_world`` will
|
||||
use build directory :file:`build/reel_board/hello_world`. See
|
||||
:ref:`west-building-config` for more details on this option.
|
||||
|
||||
Controlling the Build System
|
||||
----------------------------
|
||||
|
||||
There are several ways to control the build system generated and used by ``west
|
||||
build``.
|
||||
|
||||
To specify the build system target to run, use ``--target`` (or ``-t``).
|
||||
|
||||
For example, on host platforms with QEMU, you can use the ``run`` target to
|
||||
|
@ -125,7 +150,6 @@ To let west decide for you if a pristine build is needed, use ``-p auto``::
|
|||
You can run ``west config build.pristine auto`` to make this setting
|
||||
permanent.
|
||||
|
||||
|
||||
.. _west-building-generator:
|
||||
|
||||
To add additional arguments to the CMake invocation performed by ``west
|
||||
|
@ -159,6 +183,8 @@ To force a CMake re-run, use the ``--cmake`` (or ``--c``) option::
|
|||
|
||||
west build -c
|
||||
|
||||
.. _west-building-config:
|
||||
|
||||
Configuration Options
|
||||
=====================
|
||||
|
||||
|
@ -179,6 +205,16 @@ You can :ref:`configure <west-config-cmd>` ``west build`` using these options.
|
|||
* - ``build.board_warn``
|
||||
- Boolean, default ``true``. If ``false``, disables warnings when
|
||||
``west build`` can't figure out the target board.
|
||||
* - ``build.dir-fmt``
|
||||
- String, default ``build``. The build folder format string, used by
|
||||
west whenever it needs to create or locate a build folder. The currently
|
||||
available arguments are:
|
||||
|
||||
- ``board``: The board name
|
||||
- ``source_dir``: The relative path from the current working directory
|
||||
to the source directory. If the current working directory is inside
|
||||
the source directory this will be set to an empty string.
|
||||
- ``app``: The name of the source directory.
|
||||
* - ``build.generator``
|
||||
- String, default ``Ninja``. The `CMake Generator`_ to use to create a
|
||||
build system. (To set a generator for a single build, see the
|
||||
|
@ -219,10 +255,10 @@ To specify the build directory, use ``--build-dir`` (or ``-d``)::
|
|||
|
||||
west flash --build-dir path/to/build/directory
|
||||
|
||||
Since the build directory defaults to :file:`build`, if you do not specify
|
||||
a build directory but a folder named :file:`build` is present, that will be
|
||||
used, allowing you to flash from outside the :file:`build` folder with no
|
||||
additional parameters.
|
||||
If you don't specify the build directory, ``west flash`` searches for one in
|
||||
:file:`build`, then the current working directory. If you set the
|
||||
``build.dir-fmt`` configuration option (see :ref:`west-building-dirs`), ``west
|
||||
flash`` searches there instead of :file:`build`.
|
||||
|
||||
Choosing a Runner
|
||||
=================
|
||||
|
@ -315,10 +351,10 @@ To specify the build directory, use ``--build-dir`` (or ``-d``)::
|
|||
west debug --build-dir path/to/build/directory
|
||||
west debugserver --build-dir path/to/build/directory
|
||||
|
||||
Since the build directory defaults to :file:`build`, if you do not specify
|
||||
a build directory but a folder named :file:`build` is present, that will be
|
||||
used, allowing you to debug from outside the :file:`build` folder with no
|
||||
additional parameters.
|
||||
If you don't specify the build directory, these commands search for one in
|
||||
:file:`build`, then the current working directory. If you set the
|
||||
``build.dir-fmt`` configuration option (see :ref:`west-building-dirs`), ``west
|
||||
debug`` searches there instead of :file:`build`.
|
||||
|
||||
Choosing a Runner
|
||||
=================
|
||||
|
|
|
@ -9,7 +9,7 @@ from west import log
|
|||
from west.configuration import config
|
||||
from zcmake import DEFAULT_CMAKE_GENERATOR, run_cmake, run_build, CMakeCache
|
||||
from build_helpers import is_zephyr_build, find_build_dir, \
|
||||
BUILD_DIR_DESCRIPTION
|
||||
FIND_BUILD_DIR_DESCRIPTION
|
||||
|
||||
from zephyr_ext_common import Forceable
|
||||
|
||||
|
@ -85,8 +85,10 @@ class Build(Forceable):
|
|||
# Hidden option for backwards compatibility
|
||||
parser.add_argument('-s', '--source-dir', help=argparse.SUPPRESS)
|
||||
parser.add_argument('-d', '--build-dir',
|
||||
help=BUILD_DIR_DESCRIPTION +
|
||||
" Always created if it doesn't exist.")
|
||||
help='Build directory. ' +
|
||||
FIND_BUILD_DIR_DESCRIPTION +
|
||||
" Otherwise the default build directory is " +
|
||||
"created and used.")
|
||||
parser.add_argument('-t', '--target',
|
||||
help='''Build system target to run''')
|
||||
parser.add_argument('-p', '--pristine', choices=['auto', 'always',
|
||||
|
@ -155,7 +157,7 @@ class Build(Forceable):
|
|||
self.run_cmake = True
|
||||
else:
|
||||
self.run_cmake = True
|
||||
self._setup_source_dir()
|
||||
self.source_dir = self._find_source_dir()
|
||||
self._sanity_check()
|
||||
|
||||
board, origin = self._find_board()
|
||||
|
@ -218,7 +220,15 @@ class Build(Forceable):
|
|||
# Initialize build_dir and created_build_dir attributes.
|
||||
# If we created the build directory, we must run CMake.
|
||||
log.dbg('setting up build directory', level=log.VERBOSE_EXTREME)
|
||||
build_dir = find_build_dir(self.args.build_dir)
|
||||
# The CMake Cache has not been loaded yet, so this is safe
|
||||
board, origin = self._find_board()
|
||||
source_dir = self._find_source_dir()
|
||||
app = os.path.split(source_dir)[1]
|
||||
build_dir = find_build_dir(self.args.build_dir, board=board,
|
||||
source_dir=source_dir, app=app)
|
||||
if not build_dir:
|
||||
log.die('Unable to determine a default build folder. Check '
|
||||
'your build.dir-fmt configuration option')
|
||||
|
||||
if os.path.exists(build_dir):
|
||||
if not os.path.isdir(build_dir):
|
||||
|
@ -231,7 +241,7 @@ class Build(Forceable):
|
|||
|
||||
self.build_dir = build_dir
|
||||
|
||||
def _setup_source_dir(self):
|
||||
def _find_source_dir(self):
|
||||
# Initialize source_dir attribute, either from command line argument,
|
||||
# implicitly from the build directory's CMake cache, or using the
|
||||
# default (current working directory).
|
||||
|
@ -248,7 +258,7 @@ class Build(Forceable):
|
|||
'please give a source_dir')
|
||||
else:
|
||||
source_dir = os.getcwd()
|
||||
self.source_dir = os.path.abspath(source_dir)
|
||||
return os.path.abspath(source_dir)
|
||||
|
||||
def _sanity_check_source_dir(self):
|
||||
if self.source_dir == self.build_dir:
|
||||
|
@ -338,7 +348,7 @@ class Build(Forceable):
|
|||
# invalidated, reset to CWD and re-run the basic tests.
|
||||
if ((boards_mismatched and not apps_mismatched) and
|
||||
(not source_abs and cached_abs)):
|
||||
self._setup_source_dir()
|
||||
self.source_dir = self._find_source_dir()
|
||||
self._sanity_check_source_dir()
|
||||
|
||||
def _run_cmake(self, board, origin, cmake_opts):
|
||||
|
|
|
@ -13,6 +13,8 @@ See build.py for the build command itself.
|
|||
import zcmake
|
||||
import os
|
||||
from west import log
|
||||
from west.configuration import config
|
||||
from west.util import escapes_directory
|
||||
|
||||
DEFAULT_BUILD_DIR = 'build'
|
||||
'''Name of the default Zephyr build directory.'''
|
||||
|
@ -20,31 +22,61 @@ DEFAULT_BUILD_DIR = 'build'
|
|||
DEFAULT_CMAKE_GENERATOR = 'Ninja'
|
||||
'''Name of the default CMake generator.'''
|
||||
|
||||
BUILD_DIR_DESCRIPTION = '''\
|
||||
Build directory. If not given, {}/ is used; otherwise if the current directory
|
||||
is a Zephyr build directory, it is used.'''.format(DEFAULT_BUILD_DIR)
|
||||
FIND_BUILD_DIR_DESCRIPTION = '''\
|
||||
If not given, the default build directory ({}/ unless the
|
||||
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):
|
||||
# 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
|
||||
source_dir = kwargs.get('source_dir')
|
||||
if source_dir:
|
||||
if escapes_directory(cwd, source_dir):
|
||||
kwargs['source_dir'] = os.path.relpath(source_dir, cwd)
|
||||
else:
|
||||
# no meaningful relative path possible
|
||||
kwargs['source_dir'] = ''
|
||||
|
||||
def find_build_dir(dir):
|
||||
return fmt.format(**kwargs)
|
||||
|
||||
def find_build_dir(dir, **kwargs):
|
||||
'''Heuristic for finding a build directory.
|
||||
|
||||
If the given argument is truthy, it is returned. Otherwise if the
|
||||
DEFAULT_BUILD_DIR is a build directory, it is returned. Next, if
|
||||
the current working directory is a build directory, it is
|
||||
returned. Finally, DEFAULT_BUILD_DIR is returned.'''
|
||||
The default build directory is computed by reading the build.dir-fmt
|
||||
configuration option, defaulting to DEFAULT_BUILD_DIR if not set. It might
|
||||
be None if the build.dir-fmt configuration option is set but cannot be
|
||||
resolved.
|
||||
If the given argument is truthy, it is returned. Otherwise, if
|
||||
the default build folder is a build directory, it is returned.
|
||||
Next, if the current working directory is a build directory, it is
|
||||
returned. Finally, the default build directory is returned (may be None).
|
||||
'''
|
||||
|
||||
if dir:
|
||||
build_dir = dir
|
||||
else:
|
||||
cwd = os.getcwd()
|
||||
default = os.path.join(cwd, DEFAULT_BUILD_DIR)
|
||||
if is_zephyr_build(default):
|
||||
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
|
||||
if default and is_zephyr_build(default):
|
||||
build_dir = default
|
||||
elif is_zephyr_build(cwd):
|
||||
build_dir = cwd
|
||||
else:
|
||||
build_dir = DEFAULT_BUILD_DIR
|
||||
return os.path.abspath(build_dir)
|
||||
|
||||
build_dir = default
|
||||
log.dbg('build dir: {}'.format(build_dir), level=log.VERBOSE_EXTREME)
|
||||
if build_dir:
|
||||
return os.path.abspath(build_dir)
|
||||
else:
|
||||
return None
|
||||
|
||||
def is_zephyr_build(path):
|
||||
'''Return true if and only if `path` appears to be a valid Zephyr
|
||||
|
|
|
@ -13,7 +13,8 @@ import textwrap
|
|||
from west import cmake
|
||||
from west import log
|
||||
from west import util
|
||||
from build_helpers import find_build_dir, is_zephyr_build
|
||||
from build_helpers import find_build_dir, is_zephyr_build, \
|
||||
FIND_BUILD_DIR_DESCRIPTION
|
||||
from west.commands import CommandContextError
|
||||
|
||||
from runners import get_runner_cls, ZephyrBinaryRunner
|
||||
|
@ -43,10 +44,8 @@ def add_parser_common(parser_adder, command):
|
|||
group = parser.add_argument_group(title='General Options')
|
||||
|
||||
group.add_argument('-d', '--build-dir',
|
||||
help='''Build directory to obtain runner information
|
||||
from. If not given, this command tries to use build/
|
||||
and then the current working directory, in that
|
||||
order.''')
|
||||
help='Build directory to obtain runner information ' +
|
||||
'from. ' + FIND_BUILD_DIR_DESCRIPTION)
|
||||
group.add_argument('-c', '--cmake-cache',
|
||||
help='''Path to CMake cache file containing runner
|
||||
configuration (this is generated by the Zephyr
|
||||
|
@ -130,12 +129,17 @@ def _build_dir(args, die_if_none=True):
|
|||
|
||||
dir = find_build_dir(None)
|
||||
|
||||
if is_zephyr_build(dir):
|
||||
if dir and is_zephyr_build(dir):
|
||||
return dir
|
||||
elif die_if_none:
|
||||
log.die('--build-dir was not given, and neither {} '
|
||||
'nor {} are zephyr build directories.'.
|
||||
format(getcwd(), dir))
|
||||
msg = '--build-dir was not given, '
|
||||
if dir:
|
||||
msg = msg + 'and neither {} nor {} are zephyr build directories.'
|
||||
else:
|
||||
msg = msg + ('{} is not a build directory and the default build '
|
||||
'directory cannot be determined. Check your '
|
||||
'build.dir-fmt configuration option')
|
||||
log.die(msg.format(getcwd(), dir))
|
||||
else:
|
||||
return None
|
||||
|
||||
|
|
Loading…
Reference in a new issue