diff options
Diffstat (limited to 'pw_package/py/pw_package/packages/arduino_core.py')
-rw-r--r-- | pw_package/py/pw_package/packages/arduino_core.py | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/pw_package/py/pw_package/packages/arduino_core.py b/pw_package/py/pw_package/packages/arduino_core.py new file mode 100644 index 000000000..994c95cc9 --- /dev/null +++ b/pw_package/py/pw_package/packages/arduino_core.py @@ -0,0 +1,140 @@ +# Copyright 2020 The Pigweed Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. +"""Install and check status of teensy-core.""" + +import json +import logging +import re +import subprocess +import tempfile +from pathlib import Path +from typing import Sequence + +from pw_arduino_build import core_installer + +import pw_package.package_manager + +_LOG: logging.Logger = logging.getLogger(__name__) + + +class ArduinoCore(pw_package.package_manager.Package): + """Install and check status of arduino cores.""" + def __init__(self, core_name, *args, **kwargs): + super().__init__(*args, name=core_name, **kwargs) + + def status(self, path: Path) -> bool: + return (path / 'hardware').is_dir() + + def populate_download_cache_from_cipd(self, path: Path) -> None: + """Check for arduino core availability in pigweed_internal cipd.""" + package_path = path.parent.resolve() + core_name = self.name + core_cache_path = package_path / ".cache" / core_name + core_cache_path.mkdir(parents=True, exist_ok=True) + + cipd_package_subpath = "pigweed_internal/third_party/" + cipd_package_subpath += core_name + cipd_package_subpath += "/${platform}" + + # Check if teensy cipd package is readable + + with tempfile.NamedTemporaryFile(prefix='cipd', + delete=True) as temp_json: + cipd_acl_check_command = [ + "cipd", + "acl-check", + cipd_package_subpath, + "-reader", + "-json-output", + temp_json.name, + ] + subprocess.run(cipd_acl_check_command, capture_output=True) + # Return if no packages are readable. + if not json.load(temp_json)['result']: + return + + def _run_command(command): + _LOG.debug("Running: `%s`", " ".join(command)) + result = subprocess.run(command, capture_output=True) + _LOG.debug("Output:\n%s", + result.stdout.decode() + result.stderr.decode()) + + _run_command(["cipd", "init", "-force", core_cache_path.as_posix()]) + _run_command([ + "cipd", "install", cipd_package_subpath, "-root", + core_cache_path.as_posix(), "-force" + ]) + + _LOG.debug( + "Available Cache Files:\n%s", + "\n".join([p.as_posix() for p in core_cache_path.glob("*")])) + + def install(self, path: Path) -> None: + self.populate_download_cache_from_cipd(path) + + if self.status(path): + return + # Otherwise delete current version and reinstall + core_installer.install_core(path.parent.resolve().as_posix(), + self.name) + + def info(self, path: Path) -> Sequence[str]: + packages_root = path.parent.resolve() + arduino_package_path = path + arduino_package_name = None + + message = [ + f'{self.name} currently installed in: {path}', + ] + # Make gn args sample copy/paste-able by omitting the starting timestamp + # and INF log on each line. + message_gn_args = [ + 'Enable by running "gn args out" and adding these lines:', + f' pw_arduino_build_CORE_PATH = "{packages_root}"', + f' pw_arduino_build_CORE_NAME = "{self.name}"' + ] + + # Search for first valid 'package/version' directory + for hardware_dir in [ + path for path in (path / 'hardware').iterdir() + if path.is_dir() + ]: + if path.name in ["arduino", "tools"]: + continue + for subdir in [ + path for path in hardware_dir.iterdir() if path.is_dir() + ]: + if subdir.name == 'avr' or re.match(r'[0-9.]+', subdir.name): + arduino_package_name = f'{hardware_dir.name}/{subdir.name}' + break + + if arduino_package_name: + message_gn_args += [ + f' pw_arduino_build_PACKAGE_NAME = "{arduino_package_name}"', + ' pw_arduino_build_BOARD = "BOARD_NAME"' + ] + message += ["\n".join(message_gn_args)] + message += [ + 'Where BOARD_NAME is any supported board.', + # Have arduino_builder command appear on it's own line. + 'List available boards by running:\n' + ' arduino_builder ' + f'--arduino-package-path {arduino_package_path} ' + f'--arduino-package-name {arduino_package_name} list-boards' + ] + return message + + +for arduino_core_name in core_installer.supported_cores(): + pw_package.package_manager.register(ArduinoCore, name=arduino_core_name) |