blob: c630c939f6162e737cd93b907d647d95b0a0dab5 [file] [log] [blame]
# 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
# 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 =
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 = [
], capture_output=True)
# Return if no packages are readable.
if not json.load(temp_json)['result']:
def _run_command(command):
_LOG.debug("Running: `%s`", " ".join(command))
result =, capture_output=True)
result.stdout.decode() + result.stderr.decode())
_run_command(["cipd", "init", "-force", core_cache_path.as_posix()])
"cipd", "install", cipd_package_subpath, "-root",
core_cache_path.as_posix(), "-force"
"Available Cache Files:\n%s",
"\n".join([p.as_posix() for p in core_cache_path.glob("*")]))
def install(self, path: Path) -> None:
if self.status(path):
# Otherwise delete current version and reinstall
def info(self, path: Path) -> Sequence[str]:
packages_root = path.parent.resolve()
arduino_package_path = path
arduino_package_name = None
message = [
f'{} 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 = "{}"'
# Search for first valid 'package/version' directory
for hardware_dir in [
path for path in (path / 'hardware').iterdir()
if path.is_dir()
if in ["arduino", "tools"]:
for subdir in [
path for path in hardware_dir.iterdir() if path.is_dir()
if == 'avr' or re.match(r'[0-9.]+',
arduino_package_name = f'{}/{}'
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():