Skip to content

Commit 411e776

Browse files
scripts: west_commands: extend build.dir-fmt format args
build.dir-fmt format string arguments are extended. New format args are 'west_ws' (absolute path to the west workspace directory) and 'source_dir_ws' (relative path of the source directory to the west workspace). Signed-off-by: Thorsten Klein <[email protected]>
1 parent ab2622f commit 411e776

File tree

4 files changed

+86
-6
lines changed

4 files changed

+86
-6
lines changed

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,11 +395,14 @@ You can :ref:`configure <west-config-cmd>` ``west build`` using these options.
395395
west whenever it needs to create or locate a build folder. The currently
396396
available arguments are:
397397

398+
- ``west_ws``: The absolute path from the west workspace.
398399
- ``board``: The board name
399400
- ``source_dir``: The relative path from the current working directory
400401
to the source directory. If the current working directory is inside
401402
the source directory this will be set to an empty string.
402403
- ``app``: The name of the source directory.
404+
- ``source_dir_ws``: The relative path from the source directory
405+
to the west topdir.
403406
* - ``build.generator``
404407
- String, default ``Ninja``. The `CMake Generator`_ to use to create a
405408
build system. (To set a generator for a single build, see the

scripts/west_commands/build.py

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -456,16 +456,28 @@ def _update_cache(self):
456456
with contextlib.suppress(FileNotFoundError):
457457
self.cmake_cache = CMakeCache.from_build_dir(self.build_dir)
458458

459+
def _get_dir_fmt_context(self):
460+
board, _ = self._find_board()
461+
source_dir = self._find_source_dir()
462+
app = os.path.split(source_dir)[1]
463+
west_ws = west_topdir(source_dir)
464+
source_dir_ws = os.path.relpath(source_dir, west_ws)
465+
return {
466+
"west_ws" : west_ws,
467+
"board" : board,
468+
"app" : app,
469+
"source_dir" : source_dir,
470+
"source_dir_ws" : source_dir_ws
471+
}
472+
459473
def _setup_build_dir(self):
460474
# Initialize build_dir and created_build_dir attributes.
461475
# If we created the build directory, we must run CMake.
462476
self.dbg('setting up build directory', level=Verbosity.DBG_EXTREME)
463477
# The CMake Cache has not been loaded yet, so this is safe
464-
board, _ = self._find_board()
465-
source_dir = self._find_source_dir()
466-
app = os.path.split(source_dir)[1]
467-
build_dir = find_build_dir(self.args.build_dir, board=board,
468-
source_dir=source_dir, app=app)
478+
479+
context = self._get_dir_fmt_context()
480+
build_dir = find_build_dir(self.args.build_dir, **context)
469481
if not build_dir:
470482
self.die('Unable to determine a default build folder. Check '
471483
'your build.dir-fmt configuration option')

scripts/west_commands/build_helpers.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import zcmake
1818
from west import log
1919
from west.configuration import config
20-
from west.util import escapes_directory
20+
from west.util import escapes_directory, west_topdir
2121

2222
# Domains.py must be imported from the pylib directory, since
2323
# twister also uses the implementation
@@ -40,9 +40,14 @@
4040
def _resolve_build_dir(fmt, guess, cwd, **kwargs):
4141
# Remove any None values, we do not want 'None' as a string
4242
kwargs = {k: v for k, v in kwargs.items() if v is not None}
43+
cwd = os.getcwd()
44+
west_workspace = west_topdir(cwd)
45+
kwargs['west_ws'] = west_workspace
4346
# Check if source_dir is below cwd first
4447
source_dir = kwargs.get('source_dir')
4548
if source_dir:
49+
source_dir_ws = os.path.relpath(source_dir, west_workspace)
50+
kwargs['source_dir_ws'] = source_dir_ws
4651
if escapes_directory(cwd, source_dir):
4752
kwargs['source_dir'] = os.path.relpath(source_dir, cwd)
4853
else:

scripts/west_commands/tests/test_build.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
from argparse import Namespace
66

77
from build import Build
8+
from pathlib import Path
9+
from west.configuration import config
10+
import configparser
11+
import os
812
import pytest
913

1014
TEST_CASES = [
@@ -55,3 +59,59 @@ def test_parse_remainder(test_case):
5559
b._parse_remainder(test_case['r'])
5660
assert b.args.source_dir == test_case['s']
5761
assert b.args.cmake_opts == test_case['c']
62+
63+
64+
cwd = Path(os.getcwd())
65+
west_ws_dir = cwd.parent
66+
67+
DIR_FMT_ARGS = Namespace(board='native_sim', source_dir=os.path.join("any", "project", "app"))
68+
69+
TEST_CASES_DIR_FMT = [
70+
# Test Case data:
71+
# (test_config, build_dir,
72+
# expected)
73+
({}, None,
74+
cwd / "build"),
75+
({}, "specified",
76+
cwd / "specified"),
77+
({'dir-fmt': 'specified'}, None,
78+
cwd / "specified"),
79+
({'dir-fmt': '{west_ws}/build'}, None,
80+
west_ws_dir / "build"),
81+
({'dir-fmt': 'build/{board}'}, None,
82+
cwd / "build" / "native_sim"),
83+
({'dir-fmt': 'build/{app}'}, None,
84+
cwd / "build" / "app"),
85+
({'dir-fmt': 'build/{source_dir}'}, None,
86+
os.path.abspath(cwd / "build" / os.path.relpath(DIR_FMT_ARGS.source_dir, cwd))),
87+
({'dir-fmt': 'build/{source_dir_ws}'}, None,
88+
os.path.abspath(cwd / "build" / os.path.relpath(DIR_FMT_ARGS.source_dir, west_ws_dir)))
89+
]
90+
91+
@pytest.mark.parametrize('test_case', TEST_CASES_DIR_FMT)
92+
def test_dir_fmt(monkeypatch, test_case):
93+
# mock some default functions
94+
monkeypatch.setattr(configparser.ConfigParser, "read", lambda self, filenames: None)
95+
monkeypatch.setattr("os.makedirs", lambda *a, **kw: None)
96+
monkeypatch.setattr("build_helpers.west_topdir", lambda *a, **kw: str(west_ws_dir))
97+
monkeypatch.setattr("build.west_topdir", lambda *a, **kw: str(west_ws_dir))
98+
99+
# extract data from the test case
100+
test_config, build_dir, expected = test_case
101+
102+
# set up Build
103+
b = Build()
104+
b.args = DIR_FMT_ARGS
105+
b.args.build_dir = build_dir
106+
107+
# apply given test_config
108+
if not config.has_section('build'):
109+
config.add_section('build')
110+
for k, v in test_config.items():
111+
config.set('build', k, v)
112+
113+
# run the build-dir setup
114+
b._setup_build_dir()
115+
116+
# check for expected build-dir
117+
assert Path(expected) == Path(b.build_dir)

0 commit comments

Comments
 (0)