Skip to content

Commit 03d0ed0

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 03d0ed0

File tree

4 files changed

+89
-7
lines changed

4 files changed

+89
-7
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 workspace.
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: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,8 @@ def do_run(self, args, remainder):
236236

237237
build_info_path = self.build_dir
238238
build_info_file = os.path.join(build_info_path, BUILD_INFO_LOG)
239-
west_workspace = west_topdir(self.source_dir)
239+
cwd = os.getcwd()
240+
west_workspace = west_topdir(cwd)
240241
if not os.path.exists(build_info_path):
241242
os.makedirs(build_info_path)
242243
if not os.path.exists(build_info_file):
@@ -456,16 +457,29 @@ def _update_cache(self):
456457
with contextlib.suppress(FileNotFoundError):
457458
self.cmake_cache = CMakeCache.from_build_dir(self.build_dir)
458459

460+
def _get_dir_fmt_context(self):
461+
cwd = os.getcwd()
462+
west_ws = west_topdir(cwd)
463+
board, _ = self._find_board()
464+
source_dir = self._find_source_dir()
465+
source_dir_ws = os.path.relpath(source_dir, west_ws)
466+
app = os.path.split(source_dir)[1]
467+
return {
468+
"app" : app,
469+
"board" : board,
470+
"source_dir" : source_dir,
471+
"source_dir_ws" : source_dir_ws,
472+
"west_ws" : west_ws
473+
}
474+
459475
def _setup_build_dir(self):
460476
# Initialize build_dir and created_build_dir attributes.
461477
# If we created the build directory, we must run CMake.
462478
self.dbg('setting up build directory', level=Verbosity.DBG_EXTREME)
463479
# 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)
480+
481+
context = self._get_dir_fmt_context()
482+
build_dir = find_build_dir(self.args.build_dir, **context)
469483
if not build_dir:
470484
self.die('Unable to determine a default build folder. Check '
471485
'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)