diff options
author | Jack Rosenthal <jrosenth@chromium.org> | 2021-02-05 12:24:38 -0700 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2021-02-06 01:00:40 +0000 |
commit | 9fc79b2e2d2b3c0119df50afbad81ea541c36519 (patch) | |
tree | 2c26ee5bd251fe8322bfcbc9c791d4995ec3dc3c | |
parent | 08aa55288e75eec80c66efff1a59c14a6048ac5d (diff) | |
download | chrome-ec-9fc79b2e2d2b3c0119df50afbad81ea541c36519.tar.gz |
zephyr: zmake: add board-specific DTS overlays
Allow board-specific DTS overlays to be placed at
zephyr/dts/board-overlays/${BOARD}.dts in any module. Zmake will find
the file and append it to the DTC_OVERLAY_FILE list when discovered.
BUG=b:179491802
BRANCH=none
TEST=provided unit test passes
Signed-off-by: Jack Rosenthal <jrosenth@chromium.org>
Change-Id: I53d4a04b6056689696b4615b5998937dbcf801c4
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2678795
Reviewed-by: Simon Glass <sjg@chromium.org>
-rw-r--r-- | zephyr/dts/board-overlays/native_posix.dts | 6 | ||||
-rw-r--r-- | zephyr/test/i2c/overlay.dts (renamed from zephyr/test/i2c/boards/native_posix.overlay) | 0 | ||||
-rw-r--r-- | zephyr/test/i2c/zmake.yaml | 2 | ||||
-rw-r--r-- | zephyr/test/i2c_dts/overlay.dts (renamed from zephyr/test/i2c_dts/boards/native_posix.overlay) | 0 | ||||
-rw-r--r-- | zephyr/test/i2c_dts/zmake.yaml | 2 | ||||
-rw-r--r-- | zephyr/test/system/overlay.dts (renamed from zephyr/test/system/boards/native_posix.overlay) | 0 | ||||
-rw-r--r-- | zephyr/test/system/zmake.yaml | 2 | ||||
-rw-r--r-- | zephyr/zmake/tests/test_project.py | 82 | ||||
-rw-r--r-- | zephyr/zmake/zmake/project.py | 56 | ||||
-rw-r--r-- | zephyr/zmake/zmake/zmake.py | 3 |
10 files changed, 150 insertions, 3 deletions
diff --git a/zephyr/dts/board-overlays/native_posix.dts b/zephyr/dts/board-overlays/native_posix.dts new file mode 100644 index 0000000000..b8faf65842 --- /dev/null +++ b/zephyr/dts/board-overlays/native_posix.dts @@ -0,0 +1,6 @@ +/* Copyright 2021 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* TODO(sjg): add things */ diff --git a/zephyr/test/i2c/boards/native_posix.overlay b/zephyr/test/i2c/overlay.dts index ec534a1b88..ec534a1b88 100644 --- a/zephyr/test/i2c/boards/native_posix.overlay +++ b/zephyr/test/i2c/overlay.dts diff --git a/zephyr/test/i2c/zmake.yaml b/zephyr/test/i2c/zmake.yaml index 8269f3557e..54e80db400 100644 --- a/zephyr/test/i2c/zmake.yaml +++ b/zephyr/test/i2c/zmake.yaml @@ -8,3 +8,5 @@ supported-zephyr-versions: toolchain: llvm output-type: elf is-test: true +dts-overlays: + - overlay.dts diff --git a/zephyr/test/i2c_dts/boards/native_posix.overlay b/zephyr/test/i2c_dts/overlay.dts index ec534a1b88..ec534a1b88 100644 --- a/zephyr/test/i2c_dts/boards/native_posix.overlay +++ b/zephyr/test/i2c_dts/overlay.dts diff --git a/zephyr/test/i2c_dts/zmake.yaml b/zephyr/test/i2c_dts/zmake.yaml index d0d40dd473..664e8d9177 100644 --- a/zephyr/test/i2c_dts/zmake.yaml +++ b/zephyr/test/i2c_dts/zmake.yaml @@ -8,3 +8,5 @@ supported-zephyr-versions: output-type: elf toolchain: llvm is-test: true +dts-overlays: + - overlay.dts diff --git a/zephyr/test/system/boards/native_posix.overlay b/zephyr/test/system/overlay.dts index 49698a7553..49698a7553 100644 --- a/zephyr/test/system/boards/native_posix.overlay +++ b/zephyr/test/system/overlay.dts diff --git a/zephyr/test/system/zmake.yaml b/zephyr/test/system/zmake.yaml index d0d40dd473..664e8d9177 100644 --- a/zephyr/test/system/zmake.yaml +++ b/zephyr/test/system/zmake.yaml @@ -8,3 +8,5 @@ supported-zephyr-versions: output-type: elf toolchain: llvm is-test: true +dts-overlays: + - overlay.dts diff --git a/zephyr/zmake/tests/test_project.py b/zephyr/zmake/tests/test_project.py new file mode 100644 index 0000000000..a47407e95e --- /dev/null +++ b/zephyr/zmake/tests/test_project.py @@ -0,0 +1,82 @@ +# Copyright 2021 The Chromium OS Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import hypothesis +import hypothesis.strategies as st +import pathlib +import string +import tempfile + +import zmake.project + + +board_names = st.text(alphabet=set(string.ascii_lowercase) | {'_'}, + min_size=1) +sets_of_board_names = st.lists(st.lists(board_names, unique=True)) + + +class TemporaryProject(tempfile.TemporaryDirectory): + """A temporary project wrapper. + + Args: + config: The config dictionary to be used with the project. + """ + def __init__(self, config): + self.config = config + super().__init__() + + def __enter__(self): + project_path = pathlib.Path(super().__enter__()) + return zmake.project.Project(project_path, config_dict=self.config) + + +@hypothesis.given(sets_of_board_names) +@hypothesis.settings(deadline=1000) +def test_find_dts_overlays(modules): + """Test the functionality of find_dts_overlays with multiple + modules, each with sets of board names.""" + + # Recursive function to wind up all the temporary directories and + # call the actual test. + def setup_modules_and_dispatch(modules, test_fn, module_list=()): + if modules: + boards = modules[0] + with tempfile.TemporaryDirectory() as modpath: + modpath = pathlib.Path(modpath) + for board in boards: + dts_path = zmake.project.module_dts_overlay_name( + modpath, board) + dts_path.parent.mkdir(parents=True, exist_ok=True) + dts_path.touch() + setup_modules_and_dispatch( + modules[1:], test_fn, module_list=module_list + (modpath,)) + else: + test_fn(module_list) + + # The actual test case, once temp modules have been setup. + def testcase(module_paths): + # Maps board_name→overlay_files + board_file_mapping = {} + for modpath, board_list in zip(module_paths, modules): + for board in board_list: + file_name = zmake.project.module_dts_overlay_name( + modpath, board) + files = board_file_mapping.get(board, set()) + board_file_mapping[board] = files | {file_name} + + for board, expected_dts_files in board_file_mapping.items(): + with TemporaryProject( + {'board': board, + 'toolchain': 'foo', + 'output-type': 'elf', + 'supported-zephyr-versions': ['v2.4']}) as project: + config = project.find_dts_overlays( + dict(enumerate(module_paths))) + + actual_dts_files = set( + config.cmake_defs.get('DTC_OVERLAY_FILE', '').split(';')) + + assert actual_dts_files == set(map(str, expected_dts_files)) + + setup_modules_and_dispatch(modules, testcase) diff --git a/zephyr/zmake/zmake/project.py b/zephyr/zmake/zmake/project.py index db8e5a2e17..f851c00980 100644 --- a/zephyr/zmake/zmake/project.py +++ b/zephyr/zmake/zmake/project.py @@ -11,6 +11,20 @@ import zmake.output_packers as packers import zmake.util as util +def module_dts_overlay_name(modpath, board_name): + """Given a board name, return the expected DTS overlay path. + + Args: + modpath: the module path as a pathlib.Path object + board_name: the name of the board + + Returns: + A pathlib.Path object to the expected overlay path. + """ + return modpath / 'zephyr' / 'dts' / 'board-overlays' / '{}.dts'.format( + board_name) + + class ProjectConfig: """An object wrapping zmake.yaml.""" validator = jsonschema.Draft7Validator @@ -41,6 +55,12 @@ class ProjectConfig: 'is-test': { 'type': 'boolean', }, + 'dts-overlays': { + 'type': 'array', + 'items': { + 'type': 'string', + }, + }, }, } @@ -70,13 +90,19 @@ class ProjectConfig: def is_test(self): return self.config_dict.get('is-test', False) + @property + def dts_overlays(self): + return self.config_dict.get('dts-overlays', []) + class Project: """An object encapsulating a project directory.""" - def __init__(self, project_dir): + def __init__(self, project_dir, config_dict=None): self.project_dir = project_dir.resolve() - with open(self.project_dir / 'zmake.yaml') as f: - self.config = ProjectConfig(yaml.safe_load(f)) + if not config_dict: + with open(self.project_dir / 'zmake.yaml') as f: + config_dict = yaml.safe_load(f) + self.config = ProjectConfig(config_dict) self.packer = self.config.output_packer(self) def iter_builds(self): @@ -94,3 +120,27 @@ class Project: conf |= build_config.BuildConfig(kconfig_files=[prj_conf]) for build_name, packer_config in self.packer.configs(): yield build_name, conf | packer_config + + def find_dts_overlays(self, modules): + """Find appropriate dts overlays from registered modules. + + Args: + modules: A dictionary of module names mapping to paths. + + Returns: + A BuildConfig with relevant configurations to enable the + found DTS overlay files. + """ + overlays = [] + for module_path in modules.values(): + dts_path = module_dts_overlay_name(module_path, self.config.board) + if dts_path.is_file(): + overlays.append(dts_path.resolve()) + + overlays.extend(self.project_dir / f for f in self.config.dts_overlays) + + if overlays: + return build_config.BuildConfig( + cmake_defs={'DTC_OVERLAY_FILE': ';'.join(map(str, overlays))}) + else: + return build_config.BuildConfig() diff --git a/zephyr/zmake/zmake/zmake.py b/zephyr/zmake/zmake/zmake.py index 8021351a34..2bbe818007 100644 --- a/zephyr/zmake/zmake/zmake.py +++ b/zephyr/zmake/zmake/zmake.py @@ -102,6 +102,8 @@ class Zmake: module_config = zmake.modules.setup_module_symlinks( build_dir / 'modules', module_paths) + dts_overlay_config = project.find_dts_overlays(module_paths) + if not toolchain: toolchain = project.config.toolchain @@ -120,6 +122,7 @@ class Zmake: config = (base_config | toolchain_config | module_config + | dts_overlay_config | build_config) output_dir = build_dir / 'build-{}'.format(build_name) kconfig_file = build_dir / 'kconfig-{}.conf'.format(build_name) |