2016-08-03 22:18:51 +03:00
|
|
|
# Copyright 2014-present PlatformIO <contact@platformio.org>
|
2015-11-18 17:16:17 +02:00
|
|
|
#
|
|
|
|
# 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
|
|
|
|
#
|
|
|
|
# http://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.
|
2014-06-07 13:34:31 +03:00
|
|
|
|
2016-05-10 15:36:00 +03:00
|
|
|
import base64
|
2015-09-01 16:15:04 +03:00
|
|
|
import os
|
2015-02-19 22:02:50 +02:00
|
|
|
import re
|
2014-11-22 23:55:17 +02:00
|
|
|
from imp import load_source
|
2015-12-04 21:06:29 +02:00
|
|
|
from multiprocessing import cpu_count
|
2016-05-26 19:43:36 +03:00
|
|
|
from os.path import basename, dirname, isdir, isfile, join
|
2014-06-07 13:34:31 +03:00
|
|
|
|
2015-02-15 23:53:15 +02:00
|
|
|
import click
|
|
|
|
|
2016-07-17 00:48:59 +03:00
|
|
|
from platformio import app, exception, util
|
2016-07-11 13:27:30 +03:00
|
|
|
from platformio.managers.package import BasePkgManager, PackageManager
|
2016-05-26 19:43:36 +03:00
|
|
|
|
2016-07-11 13:27:30 +03:00
|
|
|
|
|
|
|
class PlatformManager(BasePkgManager):
|
2016-05-26 19:43:36 +03:00
|
|
|
|
2016-07-19 23:49:50 +03:00
|
|
|
def __init__(self, package_dir=None, repositories=None):
|
|
|
|
if not repositories:
|
2016-08-01 17:05:48 +03:00
|
|
|
repositories = [
|
2016-09-15 21:31:56 +03:00
|
|
|
"https://dl.bintray.com/platformio/dl-platforms/manifest.json",
|
2016-08-25 22:57:52 +03:00
|
|
|
"{0}://dl.platformio.org/platforms/manifest.json".format(
|
2016-09-12 02:11:04 +03:00
|
|
|
"https" if app.get_setting("enable_ssl") else "http")
|
2016-08-01 17:05:48 +03:00
|
|
|
]
|
|
|
|
BasePkgManager.__init__(self, package_dir or
|
|
|
|
join(util.get_home_dir(), "platforms"),
|
|
|
|
repositories)
|
2016-05-26 19:43:36 +03:00
|
|
|
|
2016-05-29 23:28:50 +03:00
|
|
|
@property
|
|
|
|
def manifest_name(self):
|
2016-05-26 19:43:36 +03:00
|
|
|
return "platform.json"
|
|
|
|
|
2016-08-26 11:46:59 +03:00
|
|
|
def install(self, # pylint: disable=too-many-arguments
|
|
|
|
name,
|
|
|
|
requirements=None,
|
|
|
|
with_packages=None,
|
|
|
|
without_packages=None,
|
|
|
|
skip_default_package=False,
|
|
|
|
**_):
|
2016-07-18 01:38:35 +03:00
|
|
|
platform_dir = BasePkgManager.install(self, name, requirements)
|
|
|
|
p = PlatformFactory.newPlatform(self.get_manifest_path(platform_dir))
|
2016-08-01 17:05:48 +03:00
|
|
|
p.install_packages(with_packages, without_packages,
|
|
|
|
skip_default_package)
|
2016-05-31 00:22:25 +03:00
|
|
|
self.cleanup_packages(p.packages.keys())
|
2016-05-29 23:28:50 +03:00
|
|
|
return True
|
2016-05-26 19:43:36 +03:00
|
|
|
|
2016-08-05 13:51:28 +03:00
|
|
|
def uninstall(self, name, requirements=None, trigger_event=True):
|
2016-08-01 17:05:48 +03:00
|
|
|
name, requirements, _ = self.parse_pkg_name(name, requirements)
|
2016-05-31 00:22:25 +03:00
|
|
|
p = PlatformFactory.newPlatform(name, requirements)
|
2016-07-11 13:27:30 +03:00
|
|
|
BasePkgManager.uninstall(self, name, requirements)
|
2016-08-05 13:51:28 +03:00
|
|
|
# trigger event is disabled when upgrading operation
|
|
|
|
# don't cleanup packages, "install" will do that
|
|
|
|
if trigger_event:
|
|
|
|
self.cleanup_packages(p.packages.keys())
|
2016-05-29 23:28:50 +03:00
|
|
|
return True
|
2016-05-26 19:43:36 +03:00
|
|
|
|
2016-05-29 00:50:05 +03:00
|
|
|
def update(self, # pylint: disable=arguments-differ
|
2016-08-01 17:05:48 +03:00
|
|
|
name, requirements=None, only_packages=False, only_check=False):
|
|
|
|
name, requirements, _ = self.parse_pkg_name(name, requirements)
|
2016-05-29 23:28:50 +03:00
|
|
|
if not only_packages:
|
2016-08-01 17:05:48 +03:00
|
|
|
BasePkgManager.update(self, name, requirements, only_check)
|
2016-05-31 00:22:25 +03:00
|
|
|
p = PlatformFactory.newPlatform(name, requirements)
|
2016-08-01 17:05:48 +03:00
|
|
|
p.update_packages(only_check)
|
2016-08-29 22:25:38 +03:00
|
|
|
self.cleanup_packages(p.packages.keys())
|
2016-05-29 23:28:50 +03:00
|
|
|
return True
|
2016-05-26 19:43:36 +03:00
|
|
|
|
2016-05-29 23:28:50 +03:00
|
|
|
def is_outdated(self, name, requirements=None):
|
2016-08-02 19:10:29 +03:00
|
|
|
if BasePkgManager.is_outdated(self, name, requirements):
|
|
|
|
return True
|
2016-05-29 23:28:50 +03:00
|
|
|
p = PlatformFactory.newPlatform(name, requirements)
|
2016-08-02 19:10:29 +03:00
|
|
|
return p.are_outdated_packages()
|
2016-05-29 23:28:50 +03:00
|
|
|
|
2016-05-31 00:22:25 +03:00
|
|
|
def cleanup_packages(self, names):
|
2016-05-29 23:28:50 +03:00
|
|
|
self.reset_cache()
|
|
|
|
deppkgs = {}
|
|
|
|
for manifest in PlatformManager().get_installed():
|
2016-08-01 17:05:48 +03:00
|
|
|
p = PlatformFactory.newPlatform(manifest['name'],
|
|
|
|
manifest['version'])
|
2016-05-29 23:28:50 +03:00
|
|
|
for pkgname, pkgmanifest in p.get_installed_packages().items():
|
|
|
|
if pkgname not in deppkgs:
|
|
|
|
deppkgs[pkgname] = set()
|
|
|
|
deppkgs[pkgname].add(pkgmanifest['version'])
|
|
|
|
|
2016-08-01 17:05:48 +03:00
|
|
|
pm = PackageManager(join(util.get_home_dir(), "packages"))
|
2016-05-29 23:28:50 +03:00
|
|
|
for manifest in pm.get_installed():
|
2016-05-31 00:22:25 +03:00
|
|
|
if manifest['name'] not in names:
|
2016-05-29 23:28:50 +03:00
|
|
|
continue
|
2016-05-31 00:22:25 +03:00
|
|
|
if (manifest['name'] not in deppkgs or
|
|
|
|
manifest['version'] not in deppkgs[manifest['name']]):
|
2016-05-29 23:28:50 +03:00
|
|
|
pm.uninstall(
|
|
|
|
manifest['name'], manifest['version'], trigger_event=False)
|
|
|
|
|
|
|
|
self.reset_cache()
|
|
|
|
return True
|
2016-05-26 19:43:36 +03:00
|
|
|
|
|
|
|
def get_installed_boards(self):
|
|
|
|
boards = []
|
|
|
|
for manifest in self.get_installed():
|
2016-07-18 01:38:35 +03:00
|
|
|
p = PlatformFactory.newPlatform(
|
|
|
|
self.get_manifest_path(manifest['__pkg_dir']))
|
2016-06-08 13:34:49 +03:00
|
|
|
for config in p.get_boards().values():
|
|
|
|
boards.append(config.get_brief_data())
|
2016-05-26 19:43:36 +03:00
|
|
|
return boards
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
@util.memoized
|
|
|
|
def get_registered_boards():
|
2016-09-14 22:32:35 +03:00
|
|
|
return util.get_api_result("/boards", cache_valid="365d")
|
2015-03-14 00:02:09 +02:00
|
|
|
|
2016-09-14 14:46:10 +03:00
|
|
|
def board_config(self, id_):
|
|
|
|
for manifest in self.get_installed_boards():
|
|
|
|
if manifest['id'] == id_:
|
|
|
|
return manifest
|
|
|
|
for manifest in self.get_registered_boards():
|
|
|
|
if manifest['id'] == id_:
|
|
|
|
return manifest
|
|
|
|
raise exception.UnknownBoard(id_)
|
|
|
|
|
2015-03-14 00:02:09 +02:00
|
|
|
|
2014-06-07 13:34:31 +03:00
|
|
|
class PlatformFactory(object):
|
|
|
|
|
2014-11-24 21:36:44 +02:00
|
|
|
@staticmethod
|
2016-05-26 19:43:36 +03:00
|
|
|
def get_clsname(name):
|
2016-09-15 01:30:51 +03:00
|
|
|
name = re.sub(r"[^\da-z\_]+", "", name, flags=re.I)
|
2016-05-26 19:43:36 +03:00
|
|
|
return "%s%sPlatform" % (name.upper()[0], name.lower()[1:])
|
2014-11-24 21:36:44 +02:00
|
|
|
|
2014-11-22 23:55:17 +02:00
|
|
|
@staticmethod
|
2016-05-26 19:43:36 +03:00
|
|
|
def load_module(name, path):
|
2014-11-29 22:39:44 +02:00
|
|
|
module = None
|
|
|
|
try:
|
2016-08-01 17:05:48 +03:00
|
|
|
module = load_source("platformio.managers.platform.%s" % name,
|
|
|
|
path)
|
2014-11-29 22:39:44 +02:00
|
|
|
except ImportError:
|
2016-05-26 19:43:36 +03:00
|
|
|
raise exception.UnknownPlatform(name)
|
2014-11-29 22:39:44 +02:00
|
|
|
return module
|
|
|
|
|
|
|
|
@classmethod
|
2016-05-26 19:43:36 +03:00
|
|
|
def newPlatform(cls, name, requirements=None):
|
|
|
|
platform_dir = None
|
|
|
|
if name.endswith("platform.json") and isfile(name):
|
|
|
|
platform_dir = dirname(name)
|
|
|
|
name = util.load_json(name)['name']
|
|
|
|
else:
|
2016-08-05 13:51:28 +03:00
|
|
|
if not requirements and "@" in name:
|
|
|
|
name, requirements = name.rsplit("@", 1)
|
2016-08-29 22:06:37 +03:00
|
|
|
platform_dir = PlatformManager().get_package_dir(name,
|
|
|
|
requirements)
|
2016-05-28 22:51:33 +03:00
|
|
|
|
2016-05-26 19:43:36 +03:00
|
|
|
if not platform_dir:
|
2016-08-01 17:05:48 +03:00
|
|
|
raise exception.UnknownPlatform(name if not requirements else
|
|
|
|
"%s@%s" % (name, requirements))
|
2016-05-26 19:43:36 +03:00
|
|
|
|
|
|
|
platform_cls = None
|
|
|
|
if isfile(join(platform_dir, "platform.py")):
|
|
|
|
platform_cls = getattr(
|
|
|
|
cls.load_module(name, join(platform_dir, "platform.py")),
|
2016-08-01 17:05:48 +03:00
|
|
|
cls.get_clsname(name))
|
2016-05-26 19:43:36 +03:00
|
|
|
else:
|
|
|
|
platform_cls = type(
|
2016-08-01 17:05:48 +03:00
|
|
|
str(cls.get_clsname(name)), (PlatformBase, ), {})
|
2016-05-26 19:43:36 +03:00
|
|
|
|
|
|
|
_instance = platform_cls(join(platform_dir, "platform.json"))
|
2016-05-30 14:31:58 +03:00
|
|
|
assert isinstance(_instance, PlatformBase)
|
2016-05-26 19:43:36 +03:00
|
|
|
return _instance
|
|
|
|
|
|
|
|
|
|
|
|
class PlatformPackagesMixin(object):
|
|
|
|
|
2016-08-01 17:05:48 +03:00
|
|
|
def install_packages(self,
|
|
|
|
with_packages=None,
|
|
|
|
without_packages=None,
|
|
|
|
skip_default_package=False,
|
2016-08-21 00:31:58 +03:00
|
|
|
silent=False):
|
2016-08-01 17:05:48 +03:00
|
|
|
with_packages = set(self.pkg_types_to_names(with_packages or []))
|
|
|
|
without_packages = set(self.pkg_types_to_names(without_packages or []))
|
2015-04-23 14:11:30 +01:00
|
|
|
|
2016-05-26 19:43:36 +03:00
|
|
|
upkgs = with_packages | without_packages
|
2016-05-29 23:28:50 +03:00
|
|
|
ppkgs = set(self.packages.keys())
|
2016-05-26 19:43:36 +03:00
|
|
|
if not upkgs.issubset(ppkgs):
|
|
|
|
raise exception.UnknownPackage(", ".join(upkgs - ppkgs))
|
|
|
|
|
2016-05-29 23:28:50 +03:00
|
|
|
for name, opts in self.packages.items():
|
2016-05-26 19:43:36 +03:00
|
|
|
if name in without_packages:
|
|
|
|
continue
|
|
|
|
elif (name in with_packages or
|
2016-08-01 17:05:48 +03:00
|
|
|
not (skip_default_package or opts.get("optional", False))):
|
|
|
|
if any([s in opts.get("version", "") for s in ("\\", "/")]):
|
|
|
|
self.pm.install(
|
2016-08-21 00:31:58 +03:00
|
|
|
"%s=%s" % (name, opts['version']), silent=silent)
|
2016-08-01 17:05:48 +03:00
|
|
|
else:
|
2016-08-21 00:31:58 +03:00
|
|
|
self.pm.install(name, opts.get("version"), silent=silent)
|
2014-11-22 23:55:17 +02:00
|
|
|
|
2016-05-26 19:43:36 +03:00
|
|
|
return True
|
2014-11-22 23:55:17 +02:00
|
|
|
|
2016-08-29 22:06:37 +03:00
|
|
|
def get_installed_packages(self):
|
|
|
|
items = {}
|
|
|
|
for name, opts in self.packages.items():
|
|
|
|
package = self.pm.get_package(name, opts['version'])
|
|
|
|
if package:
|
|
|
|
items[name] = package
|
|
|
|
return items
|
|
|
|
|
2016-08-01 17:05:48 +03:00
|
|
|
def update_packages(self, only_check=False):
|
2016-07-09 19:01:43 +03:00
|
|
|
for name in self.get_installed_packages():
|
2016-08-01 17:05:48 +03:00
|
|
|
self.pm.update(name, self.packages[name]['version'], only_check)
|
2016-05-26 19:43:36 +03:00
|
|
|
|
|
|
|
def are_outdated_packages(self):
|
|
|
|
for name, opts in self.get_installed_packages().items():
|
2016-05-29 23:28:50 +03:00
|
|
|
if (opts['version'] != self.pm.get_latest_repo_version(
|
|
|
|
name, self.packages[name].get("version"))):
|
2016-05-26 19:43:36 +03:00
|
|
|
return True
|
|
|
|
return False
|
2014-06-07 13:34:31 +03:00
|
|
|
|
2016-08-29 22:06:37 +03:00
|
|
|
def get_package_dir(self, name):
|
|
|
|
return self.pm.get_package_dir(name,
|
|
|
|
self.packages[name].get("version"))
|
|
|
|
|
|
|
|
def get_package_version(self, name):
|
|
|
|
package = self.pm.get_package(name, self.packages[name].get("version"))
|
|
|
|
return package['version'] if package else None
|
|
|
|
|
2014-06-07 13:34:31 +03:00
|
|
|
|
2016-05-29 00:50:05 +03:00
|
|
|
class PlatformRunMixin(object):
|
2014-06-07 13:34:31 +03:00
|
|
|
|
2016-09-10 17:27:47 +03:00
|
|
|
LINE_ERROR_RE = re.compile(r"(^|\s+)error:?\s+", re.I)
|
2015-02-19 22:02:50 +02:00
|
|
|
|
2016-08-21 19:27:38 +03:00
|
|
|
def run(self, variables, targets, silent, verbose):
|
2016-05-29 00:50:05 +03:00
|
|
|
assert isinstance(variables, dict)
|
|
|
|
assert isinstance(targets, list)
|
|
|
|
|
|
|
|
self.configure_default_packages(variables, targets)
|
2016-08-21 00:31:58 +03:00
|
|
|
self.install_packages(silent=True)
|
2016-05-29 00:50:05 +03:00
|
|
|
|
2016-08-21 19:27:38 +03:00
|
|
|
self.silent = silent
|
|
|
|
self.verbose = verbose or app.get_setting("force_verbose")
|
2016-05-29 00:50:05 +03:00
|
|
|
|
|
|
|
if "clean" in targets:
|
2016-07-17 00:48:59 +03:00
|
|
|
targets = ["-c", "."]
|
2016-05-29 00:50:05 +03:00
|
|
|
|
|
|
|
variables['platform_manifest'] = self.manifest_path
|
|
|
|
|
|
|
|
if "build_script" not in variables:
|
|
|
|
variables['build_script'] = self.get_build_script()
|
|
|
|
if not isfile(variables['build_script']):
|
|
|
|
raise exception.BuildScriptNotFound(variables['build_script'])
|
|
|
|
|
|
|
|
result = self._run_scons(variables, targets)
|
|
|
|
assert "returncode" in result
|
|
|
|
|
|
|
|
return result
|
|
|
|
|
|
|
|
def _run_scons(self, variables, targets):
|
|
|
|
cmd = [
|
2016-08-29 20:20:12 +03:00
|
|
|
util.get_pythonexe_path(),
|
2016-08-01 17:05:48 +03:00
|
|
|
join(self.get_package_dir("tool-scons"), "script", "scons"), "-Q",
|
|
|
|
"-j %d" % self.get_job_nums(), "--warn=no-no-parallel-support",
|
2016-05-29 00:50:05 +03:00
|
|
|
"-f", join(util.get_source_dir(), "builder", "main.py")
|
2016-07-17 00:48:59 +03:00
|
|
|
]
|
2016-08-27 19:30:38 +03:00
|
|
|
cmd.append("PIOVERBOSE=%d" % (1 if self.verbose else 0))
|
2016-07-17 00:48:59 +03:00
|
|
|
cmd += targets
|
2016-05-29 00:50:05 +03:00
|
|
|
|
|
|
|
# encode and append variables
|
|
|
|
for key, value in variables.items():
|
|
|
|
cmd.append("%s=%s" % (key.upper(), base64.b64encode(value)))
|
|
|
|
|
2016-08-29 20:20:12 +03:00
|
|
|
util.copy_pythonpath_to_osenv()
|
2016-05-29 00:50:05 +03:00
|
|
|
result = util.exec_command(
|
|
|
|
cmd,
|
|
|
|
stdout=util.AsyncPipe(self.on_run_out),
|
2016-08-01 17:05:48 +03:00
|
|
|
stderr=util.AsyncPipe(self.on_run_err))
|
2016-05-29 00:50:05 +03:00
|
|
|
return result
|
|
|
|
|
|
|
|
def on_run_out(self, line):
|
2016-10-05 22:40:19 +03:00
|
|
|
if "`buildprog' is up to date." in line:
|
|
|
|
return
|
2016-07-17 00:48:59 +03:00
|
|
|
self._echo_line(line, level=1)
|
2016-05-29 00:50:05 +03:00
|
|
|
|
|
|
|
def on_run_err(self, line):
|
|
|
|
is_error = self.LINE_ERROR_RE.search(line) is not None
|
2016-07-17 00:48:59 +03:00
|
|
|
self._echo_line(line, level=3 if is_error else 2)
|
2016-05-29 00:50:05 +03:00
|
|
|
|
2016-08-21 19:27:38 +03:00
|
|
|
def _echo_line(self, line, level):
|
2016-09-02 18:45:19 +03:00
|
|
|
if line.startswith("scons: "):
|
|
|
|
line = line[7:]
|
2016-05-29 00:50:05 +03:00
|
|
|
assert 1 <= level <= 3
|
2016-08-21 19:27:38 +03:00
|
|
|
if self.silent and (level < 2 or not line):
|
|
|
|
return
|
2016-07-17 00:48:59 +03:00
|
|
|
fg = (None, "yellow", "red")[level - 1]
|
|
|
|
if level == 1 and "is up to date" in line:
|
2016-05-29 00:50:05 +03:00
|
|
|
fg = "green"
|
2016-07-17 00:48:59 +03:00
|
|
|
click.secho(line, fg=fg, err=level > 1)
|
2016-05-29 00:50:05 +03:00
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def get_job_nums():
|
|
|
|
try:
|
|
|
|
return cpu_count()
|
|
|
|
except NotImplementedError:
|
|
|
|
return 1
|
|
|
|
|
|
|
|
|
2016-05-30 14:31:58 +03:00
|
|
|
class PlatformBase(PlatformPackagesMixin, PlatformRunMixin):
|
2016-05-29 00:50:05 +03:00
|
|
|
|
|
|
|
_BOARDS_CACHE = {}
|
|
|
|
|
2016-05-26 19:43:36 +03:00
|
|
|
def __init__(self, manifest_path):
|
|
|
|
self._BOARDS_CACHE = {}
|
|
|
|
self.manifest_path = manifest_path
|
2016-05-29 23:28:50 +03:00
|
|
|
self._manifest = util.load_json(manifest_path)
|
2016-05-26 19:43:36 +03:00
|
|
|
|
|
|
|
self.pm = PackageManager(
|
2016-08-01 17:05:48 +03:00
|
|
|
join(util.get_home_dir(), "packages"),
|
|
|
|
self._manifest.get("packageRepositories"))
|
2016-05-26 19:43:36 +03:00
|
|
|
|
2016-08-21 19:27:38 +03:00
|
|
|
self.silent = False
|
|
|
|
self.verbose = False
|
2014-06-07 13:34:31 +03:00
|
|
|
|
2016-05-29 23:28:50 +03:00
|
|
|
@property
|
|
|
|
def name(self):
|
|
|
|
return self._manifest['name']
|
2015-03-16 14:15:57 +02:00
|
|
|
|
2016-05-29 23:28:50 +03:00
|
|
|
@property
|
|
|
|
def title(self):
|
|
|
|
return self._manifest['title']
|
2014-11-22 23:55:17 +02:00
|
|
|
|
2016-05-29 23:28:50 +03:00
|
|
|
@property
|
|
|
|
def description(self):
|
|
|
|
return self._manifest['description']
|
2015-03-16 12:47:43 +02:00
|
|
|
|
2016-05-29 23:28:50 +03:00
|
|
|
@property
|
|
|
|
def version(self):
|
|
|
|
return self._manifest['version']
|
2016-05-26 19:43:36 +03:00
|
|
|
|
2016-05-29 23:28:50 +03:00
|
|
|
@property
|
|
|
|
def homepage(self):
|
|
|
|
return self._manifest.get("homepage")
|
|
|
|
|
2016-09-03 16:26:52 +03:00
|
|
|
@property
|
|
|
|
def vendor_url(self):
|
|
|
|
return self._manifest.get("url")
|
|
|
|
|
2016-05-29 23:28:50 +03:00
|
|
|
@property
|
|
|
|
def license(self):
|
|
|
|
return self._manifest.get("license")
|
|
|
|
|
|
|
|
@property
|
|
|
|
def frameworks(self):
|
|
|
|
return self._manifest.get("frameworks")
|
|
|
|
|
|
|
|
@property
|
|
|
|
def manifest(self):
|
|
|
|
return self._manifest
|
|
|
|
|
|
|
|
@property
|
|
|
|
def packages(self):
|
2016-08-10 15:50:01 +03:00
|
|
|
if "packages" not in self._manifest:
|
|
|
|
self._manifest['packages'] = {}
|
|
|
|
return self._manifest['packages']
|
2016-05-26 19:43:36 +03:00
|
|
|
|
|
|
|
def get_dir(self):
|
|
|
|
return dirname(self.manifest_path)
|
|
|
|
|
|
|
|
def get_build_script(self):
|
|
|
|
main_script = join(self.get_dir(), "builder", "main.py")
|
|
|
|
if isfile(main_script):
|
|
|
|
return main_script
|
|
|
|
raise NotImplementedError()
|
2014-06-12 23:29:47 +03:00
|
|
|
|
2015-08-09 19:05:16 +03:00
|
|
|
def is_embedded(self):
|
2016-05-29 23:28:50 +03:00
|
|
|
for opts in self.packages.values():
|
2016-05-26 19:43:36 +03:00
|
|
|
if opts.get("type") == "uploader":
|
2015-08-09 19:05:16 +03:00
|
|
|
return True
|
|
|
|
return False
|
|
|
|
|
2016-05-26 19:43:36 +03:00
|
|
|
def get_boards(self, id_=None):
|
2016-06-08 13:34:49 +03:00
|
|
|
|
|
|
|
def _append_board(board_id, manifest_path):
|
|
|
|
config = PlatformBoardConfig(manifest_path)
|
|
|
|
if "platform" in config and config.get("platform") != self.name:
|
|
|
|
return
|
|
|
|
elif ("platforms" in config and
|
|
|
|
self.name not in config.get("platforms")):
|
|
|
|
return
|
|
|
|
config.manifest['platform'] = self.name
|
|
|
|
self._BOARDS_CACHE[board_id] = config
|
|
|
|
|
2016-10-31 17:41:01 +02:00
|
|
|
bdirs = [
|
|
|
|
util.get_projectboards_dir(),
|
|
|
|
join(util.get_home_dir(), "boards"),
|
|
|
|
join(self.get_dir(), "boards"),
|
|
|
|
]
|
|
|
|
|
2016-05-26 19:43:36 +03:00
|
|
|
if id_ is None:
|
2016-06-08 13:34:49 +03:00
|
|
|
for boards_dir in bdirs:
|
|
|
|
if not isdir(boards_dir):
|
2016-05-26 19:43:36 +03:00
|
|
|
continue
|
2016-06-08 13:34:49 +03:00
|
|
|
for item in sorted(os.listdir(boards_dir)):
|
|
|
|
_id = item[:-5]
|
|
|
|
if not item.endswith(".json") or _id in self._BOARDS_CACHE:
|
|
|
|
continue
|
|
|
|
_append_board(_id, join(boards_dir, item))
|
2016-05-26 19:43:36 +03:00
|
|
|
else:
|
|
|
|
if id_ not in self._BOARDS_CACHE:
|
2016-06-08 13:34:49 +03:00
|
|
|
for boards_dir in bdirs:
|
2016-06-08 14:00:40 +03:00
|
|
|
if not isdir(boards_dir):
|
|
|
|
continue
|
|
|
|
manifest_path = join(boards_dir, "%s.json" % id_)
|
2016-06-08 13:34:49 +03:00
|
|
|
if not isfile(manifest_path):
|
|
|
|
continue
|
|
|
|
_append_board(id_, manifest_path)
|
|
|
|
if id_ not in self._BOARDS_CACHE:
|
|
|
|
raise exception.UnknownBoard(id_)
|
2016-05-26 19:43:36 +03:00
|
|
|
return self._BOARDS_CACHE[id_] if id_ else self._BOARDS_CACHE
|
|
|
|
|
|
|
|
def board_config(self, id_):
|
|
|
|
return self.get_boards(id_)
|
|
|
|
|
|
|
|
def get_package_type(self, name):
|
2016-05-29 23:28:50 +03:00
|
|
|
return self.packages[name].get("type")
|
2014-07-30 23:39:01 +03:00
|
|
|
|
2016-05-26 19:43:36 +03:00
|
|
|
def pkg_types_to_names(self, types):
|
2014-07-30 23:08:36 +03:00
|
|
|
names = []
|
2016-05-26 19:43:36 +03:00
|
|
|
for type_ in types:
|
|
|
|
name = type_
|
|
|
|
# lookup by package types
|
2016-05-29 23:28:50 +03:00
|
|
|
for _name, _opts in self.packages.items():
|
2016-05-26 19:43:36 +03:00
|
|
|
if _opts.get("type") == type_:
|
2015-12-15 15:58:52 +02:00
|
|
|
name = None
|
|
|
|
names.append(_name)
|
2016-05-26 19:43:36 +03:00
|
|
|
# if type is the right name
|
2015-12-15 15:58:52 +02:00
|
|
|
if name:
|
|
|
|
names.append(name)
|
2014-07-30 23:08:36 +03:00
|
|
|
return names
|
2014-07-30 22:40:11 +03:00
|
|
|
|
2016-05-10 15:36:00 +03:00
|
|
|
def configure_default_packages(self, variables, targets):
|
2016-09-26 22:15:08 +03:00
|
|
|
# enable used frameworks
|
2016-10-26 18:35:43 +03:00
|
|
|
frameworks = variables.get("pioframework", [])
|
|
|
|
if not isinstance(frameworks, list):
|
|
|
|
frameworks = frameworks.split(", ")
|
|
|
|
for framework in frameworks:
|
2016-07-06 15:27:46 +03:00
|
|
|
if not self.frameworks:
|
|
|
|
continue
|
2016-05-26 19:43:36 +03:00
|
|
|
framework = framework.lower().strip()
|
2016-05-29 23:28:50 +03:00
|
|
|
if not framework or framework not in self.frameworks:
|
2016-05-26 19:43:36 +03:00
|
|
|
continue
|
2016-05-29 23:28:50 +03:00
|
|
|
_pkg_name = self.frameworks[framework]['package']
|
|
|
|
self.packages[_pkg_name]['optional'] = False
|
2015-12-15 15:58:52 +02:00
|
|
|
|
|
|
|
# enable upload tools for upload targets
|
2015-12-15 20:25:59 +02:00
|
|
|
if any(["upload" in t for t in targets] + ["program" in targets]):
|
2016-05-29 23:28:50 +03:00
|
|
|
for _name, _opts in self.packages.iteritems():
|
2016-05-26 19:43:36 +03:00
|
|
|
if _opts.get("type") == "uploader":
|
2016-05-29 23:28:50 +03:00
|
|
|
self.packages[_name]['optional'] = False
|
2016-10-04 01:24:38 +03:00
|
|
|
elif "nobuild" in targets:
|
2015-12-15 15:58:52 +02:00
|
|
|
# skip all packages, allow only upload tools
|
2016-05-29 23:28:50 +03:00
|
|
|
self.packages[_name]['optional'] = True
|
2015-12-15 15:58:52 +02:00
|
|
|
|
2016-10-11 00:06:09 +03:00
|
|
|
if "__test" in targets and "tool-unity" not in self.packages:
|
2016-05-30 14:31:58 +03:00
|
|
|
self.packages['tool-unity'] = {
|
2016-08-10 15:50:01 +03:00
|
|
|
"version": "~1.20302.1",
|
2016-05-30 14:31:58 +03:00
|
|
|
"optional": False
|
|
|
|
}
|
2016-09-10 18:49:59 +03:00
|
|
|
if "tool-scons" not in self.packages:
|
|
|
|
self.packages['tool-scons'] = {
|
|
|
|
"version": self._manifest.get("engines", {}).get(
|
|
|
|
"scons", ">=2.3.0,<2.6.0"),
|
|
|
|
"optional": False
|
|
|
|
}
|
2016-05-30 14:31:58 +03:00
|
|
|
|
2016-05-26 19:43:36 +03:00
|
|
|
|
|
|
|
class PlatformBoardConfig(object):
|
|
|
|
|
|
|
|
def __init__(self, manifest_path):
|
2016-06-08 13:34:49 +03:00
|
|
|
self._id = basename(manifest_path)[:-5]
|
|
|
|
assert isfile(manifest_path)
|
2016-05-26 19:43:36 +03:00
|
|
|
self.manifest_path = manifest_path
|
2016-08-24 23:03:41 +03:00
|
|
|
try:
|
|
|
|
self._manifest = util.load_json(manifest_path)
|
|
|
|
except ValueError:
|
|
|
|
raise exception.InvalidBoardManifest(manifest_path)
|
2016-08-26 01:29:26 +03:00
|
|
|
if not set(["name", "url", "vendor"]) <= set(self._manifest.keys()):
|
|
|
|
raise exception.PlatformioException(
|
|
|
|
"Please specify name, url and vendor fields for " +
|
|
|
|
manifest_path)
|
2016-05-26 19:43:36 +03:00
|
|
|
|
|
|
|
def get(self, path, default=None):
|
|
|
|
try:
|
2016-05-29 23:28:50 +03:00
|
|
|
value = self._manifest
|
2016-05-26 19:43:36 +03:00
|
|
|
for k in path.split("."):
|
|
|
|
value = value[k]
|
|
|
|
return value
|
|
|
|
except KeyError:
|
|
|
|
if default is not None:
|
|
|
|
return default
|
|
|
|
else:
|
|
|
|
raise KeyError("Invalid board option '%s'" % path)
|
|
|
|
|
|
|
|
def __contains__(self, key):
|
|
|
|
try:
|
|
|
|
self.get(key)
|
|
|
|
return True
|
|
|
|
except KeyError:
|
|
|
|
return False
|
|
|
|
|
2016-06-08 13:34:49 +03:00
|
|
|
@property
|
2016-09-13 17:36:20 +03:00
|
|
|
def id(self):
|
2016-06-08 13:34:49 +03:00
|
|
|
return self._id
|
|
|
|
|
2016-09-13 17:36:20 +03:00
|
|
|
@property
|
|
|
|
def id_(self):
|
|
|
|
return self.id
|
|
|
|
|
2016-06-08 13:34:49 +03:00
|
|
|
@property
|
|
|
|
def manifest(self):
|
2016-05-29 23:28:50 +03:00
|
|
|
return self._manifest
|
2016-06-08 13:34:49 +03:00
|
|
|
|
|
|
|
def get_brief_data(self):
|
|
|
|
return {
|
2016-09-13 17:36:20 +03:00
|
|
|
"id": self.id,
|
2016-06-08 13:34:49 +03:00
|
|
|
"name": self._manifest['name'],
|
|
|
|
"platform": self._manifest.get("platform"),
|
|
|
|
"mcu": self._manifest.get("build", {}).get("mcu", "").upper(),
|
2016-08-11 19:20:54 +03:00
|
|
|
"fcpu":
|
|
|
|
int(self._manifest.get("build", {}).get("f_cpu", "0L")[:-1]),
|
2016-06-08 13:34:49 +03:00
|
|
|
"ram": self._manifest.get("upload", {}).get("maximum_ram_size", 0),
|
|
|
|
"rom": self._manifest.get("upload", {}).get("maximum_size", 0),
|
|
|
|
"frameworks": self._manifest.get("frameworks"),
|
|
|
|
"vendor": self._manifest['vendor'],
|
|
|
|
"url": self._manifest['url']
|
|
|
|
}
|