summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJack Rosenthal <jrosenth@chromium.org>2022-03-16 13:33:38 -0600
committerCommit Bot <commit-bot@chromium.org>2022-03-17 00:08:06 +0000
commit73d2fc626440800e4e92d93b3bd88f0362fa50a2 (patch)
tree7b3b1fd77e46b045a6a4ab11d859c44bd1ab930f
parent5081c7ce7527c977b8eca37fb4a561863d91b75b (diff)
downloadchrome-ec-73d2fc626440800e4e92d93b3bd88f0362fa50a2.tar.gz
zephyr: zmake: Add a syntax to make simple variants of a build
Add a BUILD.py syntax to copy another project and make simple modifications. BUG=b:224998797 BRANCH=none TEST=provided unit test passes Signed-off-by: Jack Rosenthal <jrosenth@chromium.org> Change-Id: I87f0fe6b0e02c3ac34bec6de09d38e620fc293e3 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3530957 Reviewed-by: Jeremy Bettis <jbettis@chromium.org>
-rw-r--r--docs/zephyr/project_config.md20
-rw-r--r--zephyr/zmake/tests/test_project.py26
-rw-r--r--zephyr/zmake/zmake/configlib.py12
-rw-r--r--zephyr/zmake/zmake/project.py46
4 files changed, 94 insertions, 10 deletions
diff --git a/docs/zephyr/project_config.md b/docs/zephyr/project_config.md
index 9f658ef62c..664e7b0c64 100644
--- a/docs/zephyr/project_config.md
+++ b/docs/zephyr/project_config.md
@@ -149,7 +149,7 @@ Below is an example of how programs may wish to structure this in
# found in the LICENSE file.
def register_variant(project_name, chip="it8xx2", extra_dts_overlays=()):
- register_binman_project(
+ return register_binman_project(
project_name=project_name,
zephyr_board=chip,
dts_overlays=[
@@ -172,3 +172,21 @@ register_variant(
extra_dts_overlays=[here / "hayato_gpios.dts"],
)
```
+
+If a project is going to be a simple variant of another project (e.g.,
+project `bar` is exactly identical to project `foo` but has just a few
+device-tree/Kconfig changes), you can spin a new variant using the
+return value of the register functions:
+
+``` python
+foo = register_variant(project_name="foo")
+bar = foo.variant(
+ project_name="bar",
+ dts_overlays=[here / "bar_extras.dts"],
+)
+```
+
+With this simple variant syntax, lists (like Kconfig files and DTS
+overlays) are concatenated. This means it's not possible to remove
+files during variant registration for this syntax, so it's only
+recommended for the simple case.
diff --git a/zephyr/zmake/tests/test_project.py b/zephyr/zmake/tests/test_project.py
index f7688784e7..f4808d14d5 100644
--- a/zephyr/zmake/tests/test_project.py
+++ b/zephyr/zmake/tests/test_project.py
@@ -192,6 +192,32 @@ def test_find_projects_name_conflict(tmp_path):
zmake.project.find_projects(tmp_path)
+def test_register_variant(tmp_path):
+ (tmp_path / "BUILD.py").write_text(
+ """
+some = register_raw_project(
+ project_name="some",
+ zephyr_board="foo",
+ dts_overlays=[here / "gpio.dts"],
+)
+
+some_variant = some.variant(project_name="some-variant", zephyr_board="bar")
+another = some_variant.variant(
+ project_name="another",
+ dts_overlays=[here / "another.dts"],
+)
+ """
+ )
+ projects = zmake.project.find_projects(tmp_path)
+ assert projects["some"].config.zephyr_board == "foo"
+ assert projects["some-variant"].config.zephyr_board == "bar"
+ assert projects["another"].config.zephyr_board == "bar"
+ assert projects["another"].config.dts_overlays == [
+ tmp_path / "gpio.dts",
+ tmp_path / "another.dts",
+ ]
+
+
@pytest.mark.parametrize(
("actual_files", "config_files", "expected_files"),
[
diff --git a/zephyr/zmake/zmake/configlib.py b/zephyr/zmake/zmake/configlib.py
index 1e6223b2cb..a0463f1a86 100644
--- a/zephyr/zmake/zmake/configlib.py
+++ b/zephyr/zmake/zmake/configlib.py
@@ -11,32 +11,32 @@ def _register_project(**kwargs):
kwargs.setdefault(
"project_dir", here # noqa: F821 pylint: disable=undefined-variable
)
- register_project(**kwargs) # noqa: F821 pylint: disable=undefined-variable
+ return register_project(**kwargs) # noqa: F821 pylint: disable=undefined-variable
def register_host_project(**kwargs):
kwargs.setdefault("zephyr_board", "native_posix")
kwargs.setdefault("supported_toolchains", ["llvm", "host"])
kwargs.setdefault("output_packer", zmake.output_packers.ElfPacker)
- _register_project(**kwargs)
+ return _register_project(**kwargs)
def register_host_test(test_name, **kwargs):
kwargs.setdefault("is_test", True)
- register_host_project(project_name="test-{}".format(test_name), **kwargs)
+ return register_host_project(project_name="test-{}".format(test_name), **kwargs)
def register_raw_project(**kwargs):
kwargs.setdefault("supported_toolchains", ["coreboot-sdk", "zephyr"])
kwargs.setdefault("output_packer", zmake.output_packers.RawBinPacker)
- _register_project(**kwargs)
+ return _register_project(**kwargs)
def register_binman_project(**kwargs):
kwargs.setdefault("output_packer", zmake.output_packers.BinmanPacker)
- register_raw_project(**kwargs)
+ return register_raw_project(**kwargs)
def register_npcx_project(**kwargs):
kwargs.setdefault("output_packer", zmake.output_packers.NpcxPacker)
- register_binman_project(**kwargs)
+ return register_binman_project(**kwargs)
diff --git a/zephyr/zmake/zmake/project.py b/zephyr/zmake/zmake/project.py
index b2c36cbb33..b2232bb263 100644
--- a/zephyr/zmake/zmake/project.py
+++ b/zephyr/zmake/zmake/project.py
@@ -6,7 +6,7 @@
import dataclasses
import logging
import pathlib
-from typing import Dict, List
+from typing import Callable, Dict, List
import zmake.build_config as build_config
import zmake.configlib as configlib
@@ -154,6 +154,41 @@ class Project:
)
+@dataclasses.dataclass
+class ProjectRegistrationHandler:
+ """Return value of register_project.
+
+ This is intended to be used to create simple variants of a project
+ like so::
+
+ brd = register_project(project_name="brd", ...)
+ brd_changed = brd.variant(project_name="brd-changed", ...)
+ brd_changed_again = brd_changed.variant(project_name="brd-changed-again", ...)
+ """
+
+ base_config: ProjectConfig
+ register_func: Callable[[], "ProjectRegistrationHandler"]
+
+ def variant(self, **kwargs) -> "ProjectRegistrationHandler":
+ """Register a new variant based on the base config.
+
+ Args:
+ kwargs: Any project config changes. Note lists will be
+ concatenated.
+
+ Returns:
+ Another ProjectRegistrationHandler.
+ """
+ new_config = dataclasses.asdict(self.base_config)
+ for key, value in kwargs.items():
+ if isinstance(value, list):
+ new_config[key] = [*new_config[key], *value]
+ else:
+ new_config[key] = value
+
+ return self.register_func(**new_config)
+
+
def load_config_file(path) -> List[Project]:
"""Load a BUILD.py config file and create associated projects.
@@ -165,8 +200,13 @@ def load_config_file(path) -> List[Project]:
"""
projects: List[Project] = []
- def register_project(**kwargs):
- projects.append(Project(ProjectConfig(**kwargs)))
+ def register_project(**kwargs) -> ProjectRegistrationHandler:
+ config = ProjectConfig(**kwargs)
+ projects.append(Project(config))
+ return ProjectRegistrationHandler(
+ base_config=config,
+ register_func=register_project,
+ )
# The Python environment passed to the config file.
config_globals = {