1 # Copyright 2020 The Pigweed Authors
3 # Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 # use this file except in compliance with the License. You may obtain a copy of
7 # https://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 # License for the specific language governing permissions and limitations under
14 """Install and check status of teensy-core."""
21 from pathlib import Path
22 from typing import Sequence
24 from pw_arduino_build import core_installer
26 import pw_package.package_manager
28 _LOG: logging.Logger = logging.getLogger(__name__)
31 class ArduinoCore(pw_package.package_manager.Package):
32 """Install and check status of arduino cores."""
33 def __init__(self, core_name, *args, **kwargs):
34 super().__init__(*args, name=core_name, **kwargs)
36 def status(self, path: Path) -> bool:
37 return (path / 'hardware').is_dir()
39 def populate_download_cache_from_cipd(self, path: Path) -> None:
40 """Check for arduino core availability in pigweed_internal cipd."""
41 package_path = path.parent.resolve()
43 core_cache_path = package_path / ".cache" / core_name
44 core_cache_path.mkdir(parents=True, exist_ok=True)
46 cipd_package_subpath = "pigweed_internal/third_party/"
47 cipd_package_subpath += core_name
48 cipd_package_subpath += "/${platform}"
50 # Check if teensy cipd package is readable
52 with tempfile.NamedTemporaryFile(prefix='cipd',
53 delete=True) as temp_json:
54 cipd_acl_check_command = [
62 subprocess.run(cipd_acl_check_command, capture_output=True)
63 # Return if no packages are readable.
64 if not json.load(temp_json)['result']:
67 def _run_command(command):
68 _LOG.debug("Running: `%s`", " ".join(command))
69 result = subprocess.run(command, capture_output=True)
70 _LOG.debug("Output:\n%s",
71 result.stdout.decode() + result.stderr.decode())
73 _run_command(["cipd", "init", "-force", core_cache_path.as_posix()])
75 "cipd", "install", cipd_package_subpath, "-root",
76 core_cache_path.as_posix(), "-force"
80 "Available Cache Files:\n%s",
81 "\n".join([p.as_posix() for p in core_cache_path.glob("*")]))
83 def install(self, path: Path) -> None:
84 self.populate_download_cache_from_cipd(path)
88 # Otherwise delete current version and reinstall
89 core_installer.install_core(path.parent.resolve().as_posix(),
92 def info(self, path: Path) -> Sequence[str]:
93 packages_root = path.parent.resolve()
94 arduino_package_path = path
95 arduino_package_name = None
98 f'{self.name} currently installed in: {path}',
100 # Make gn args sample copy/paste-able by omitting the starting timestamp
101 # and INF log on each line.
103 'Enable by running "gn args out" and adding these lines:',
104 f' pw_arduino_build_CORE_PATH = "{packages_root}"',
105 f' pw_arduino_build_CORE_NAME = "{self.name}"'
108 # Search for first valid 'package/version' directory
109 for hardware_dir in [
110 path for path in (path / 'hardware').iterdir()
113 if path.name in ["arduino", "tools"]:
116 path for path in hardware_dir.iterdir() if path.is_dir()
118 if subdir.name == 'avr' or re.match(r'[0-9.]+', subdir.name):
119 arduino_package_name = f'{hardware_dir.name}/{subdir.name}'
122 if arduino_package_name:
124 f' pw_arduino_build_PACKAGE_NAME = "{arduino_package_name}"',
125 ' pw_arduino_build_BOARD = "BOARD_NAME"'
127 message += ["\n".join(message_gn_args)]
129 'Where BOARD_NAME is any supported board.',
130 # Have arduino_builder command appear on it's own line.
131 'List available boards by running:\n'
133 f'--arduino-package-path {arduino_package_path} '
134 f'--arduino-package-name {arduino_package_name} list-boards'
139 for arduino_core_name in core_installer.supported_cores():
140 pw_package.package_manager.register(ArduinoCore, name=arduino_core_name)