diff --git a/HISTORY.rst b/HISTORY.rst index 52bda7be..cec8face 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -7,6 +7,8 @@ PlatformIO 2.0 2.6.0 (2015-12-??) ~~~~~~~~~~~~~~~~~~ +* Install only required packages depending on build environment + (`issue #308 `_) * Added support for Raspberry Pi `WiringPi `__ framework (`issue #372 `_) diff --git a/platformio/__init__.py b/platformio/__init__.py index 0e62f577..547416a9 100644 --- a/platformio/__init__.py +++ b/platformio/__init__.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -VERSION = (2, 6, "0.dev0") +VERSION = (2, 6, "0.dev1") __version__ = ".".join([str(s) for s in VERSION]) __title__ = "platformio" diff --git a/platformio/builder/main.py b/platformio/builder/main.py index 387fed55..26bc853f 100644 --- a/platformio/builder/main.py +++ b/platformio/builder/main.py @@ -57,6 +57,7 @@ commonvars.AddVariables( # package aliases ("PIOPACKAGE_TOOLCHAIN",), + ("PIOPACKAGE_FRAMEWORK",), ("PIOPACKAGE_UPLOADER",), # options diff --git a/platformio/commands/platforms.py b/platformio/commands/platforms.py index 71899117..1a3a6e3a 100644 --- a/platformio/commands/platforms.py +++ b/platformio/commands/platforms.py @@ -38,8 +38,11 @@ def platforms_install(platforms, with_package, without_package, for platform in platforms: p = PlatformFactory.newPlatform(platform) if p.install(with_package, without_package, skip_default_package): - click.secho("The platform '%s' has been successfully installed!" % - platform, fg="green") + click.secho( + "The platform '%s' has been successfully installed!\n" + "The rest of packages will be installed automatically " + "depending on your build environment." % platform, + fg="green") @cli.command("list", short_help="List installed platforms") @@ -131,7 +134,7 @@ def platforms_show(ctx, platform): installed_packages = PackageManager.get_installed() for name in p.get_installed_packages(): data = installed_packages[name] - pkgalias = p.get_pkg_alias(name) + pkgalias = p.get_package_alias(name) click.echo("----------") click.echo("Package: %s" % click.style(name, fg="yellow")) if pkgalias: diff --git a/platformio/commands/run.py b/platformio/commands/run.py index 1a756dfc..1747f25e 100644 --- a/platformio/commands/run.py +++ b/platformio/commands/run.py @@ -181,8 +181,7 @@ class EnvironmentProcessor(object): telemetry.on_run_environment(self.options, build_targets) - # install platform and libs dependencies - _autoinstall_platform(self.cmd_ctx, platform, build_targets) + # install dependent libraries if "lib_install" in self.options: _autoinstall_libs(self.cmd_ctx, self.options['lib_install']) @@ -190,35 +189,6 @@ class EnvironmentProcessor(object): return p.run(build_vars, build_targets, self.verbose_level) -def _autoinstall_platform(ctx, platform, targets): - installed_platforms = PlatformFactory.get_platforms(installed=True).keys() - cmd_options = {} - p = PlatformFactory.newPlatform(platform) - - if "uploadlazy" in targets: - upload_tools = p.pkg_aliases_to_names(["uploader"]) - - # platform without uploaders - if not upload_tools and platform in installed_platforms: - return - # uploaders are already installed - if set(upload_tools) <= set(p.get_installed_packages()): - return - - cmd_options['skip_default_package'] = True - if upload_tools: - cmd_options['with_package'] = ["uploader"] - - elif (platform in installed_platforms and - set(p.get_default_packages()) <= set(p.get_installed_packages())): - return - - if (not app.get_setting("enable_prompts") or - click.confirm("The platform '%s' has not been installed yet. " - "Would you like to install it now?" % platform)): - ctx.invoke(cmd_platforms_install, platforms=[platform], **cmd_options) - - def _autoinstall_libs(ctx, libids_list): require_libs = [int(l.strip()) for l in libids_list.split(",")] installed_libs = [ diff --git a/platformio/platforms/atmelavr.py b/platformio/platforms/atmelavr.py index 25d07a7f..de18ad20 100644 --- a/platformio/platforms/atmelavr.py +++ b/platformio/platforms/atmelavr.py @@ -36,39 +36,35 @@ class AtmelavrPlatform(BasePlatform): }, "tool-avrdude": { - "alias": "uploader", - "default": True + "alias": "uploader" }, "tool-micronucleus": { - "alias": "uploader", - "default": True + "alias": "uploader" }, "framework-arduinoavr": { - "default": True + "alias": "framework" } } def get_name(self): return "Atmel AVR" + def configure_default_packages(self, envoptions, targets): + if envoptions.get("board"): + board = get_boards(envoptions.get("board")) + disable_tool = "tool-micronucleus" + if "digispark" in board['build']['core']: + disable_tool = "tool-avrdude" + del self.PACKAGES[disable_tool]['alias'] + + return BasePlatform.configure_default_packages( + self, envoptions, targets) + def on_run_err(self, line): # pylint: disable=R0201 # fix STDERR "flash written" for avrdude if "avrdude" in line: self.on_run_out(line) else: BasePlatform.on_run_err(self, line) - - def run(self, variables, targets, verbose): - for v in variables: - if "BOARD=" not in v: - continue - disable_tool = "tool-micronucleus" - _, board = v.split("=") - bdata = get_boards(board) - if "digispark" in bdata['build']['core']: - disable_tool = "tool-avrdude" - del self.PACKAGES[disable_tool]['alias'] - break - return BasePlatform.run(self, variables, targets, verbose) diff --git a/platformio/platforms/atmelsam.py b/platformio/platforms/atmelsam.py index 16e3ca51..e1a84170 100644 --- a/platformio/platforms/atmelsam.py +++ b/platformio/platforms/atmelsam.py @@ -37,12 +37,11 @@ class AtmelsamPlatform(BasePlatform): }, "framework-arduinosam": { - "default": True + "alias": "framework" }, "tool-bossac": { - "alias": "uploader", - "default": True + "alias": "uploader" } } diff --git a/platformio/platforms/base.py b/platformio/platforms/base.py index 16c8901c..45f1acf1 100644 --- a/platformio/platforms/base.py +++ b/platformio/platforms/base.py @@ -20,7 +20,7 @@ from os.path import isdir, isfile, join import click -from platformio import exception, util +from platformio import app, exception, util from platformio.app import get_state_item, set_state_item from platformio.pkgmanager import PackageManager @@ -71,6 +71,9 @@ PLATFORM_PACKAGES = { "framework-mbed": [ ("mbed Framework", "http://mbed.org") ], + "framework-wiringpi": [ + ("GPIO Interface library for the Raspberry Pi", "http://wiringpi.com") + ], "sdk-esp8266": [ ("ESP8266 SDK", "http://bbs.espressif.com") ], @@ -258,8 +261,8 @@ class BasePlatform(object): def get_packages(self): return self.PACKAGES - def get_pkg_alias(self, pkgname): - return self.PACKAGES[pkgname].get("alias", None) + def get_package_alias(self, pkgname): + return self.PACKAGES[pkgname].get("alias") def pkg_aliases_to_names(self, aliases): names = [] @@ -267,10 +270,12 @@ class BasePlatform(object): name = alias # lookup by package aliases for _name, _opts in self.get_packages().items(): - if _opts.get("alias", None) == alias: - name = _name - break - names.append(name) + if _opts.get("alias") == alias: + name = None + names.append(_name) + # if alias is the right name + if name: + names.append(name) return names def get_default_packages(self): @@ -281,9 +286,12 @@ class BasePlatform(object): pm = PackageManager() return [n for n in self.get_packages().keys() if pm.is_installed(n)] - def install(self, with_packages, without_packages, skip_default_packages): - with_packages = set(self.pkg_aliases_to_names(with_packages)) - without_packages = set(self.pkg_aliases_to_names(without_packages)) + def install(self, with_packages=None, without_packages=None, + skip_default_packages=False): + with_packages = set( + self.pkg_aliases_to_names(with_packages or [])) + without_packages = set( + self.pkg_aliases_to_names(without_packages or [])) upkgs = with_packages | without_packages ppkgs = set(self.get_packages().keys()) @@ -295,7 +303,7 @@ class BasePlatform(object): if name in without_packages: continue elif (name in with_packages or (not skip_default_packages and - opts['default'])): + opts.get("default"))): requirements.append(name) pm = PackageManager() @@ -347,34 +355,74 @@ class BasePlatform(object): obsolated = pm.get_outdated() return not set(self.get_packages().keys()).isdisjoint(set(obsolated)) + def configure_default_packages(self, envoptions, targets): + # enbale used frameworks + for pkg_name in self.pkg_aliases_to_names(["framework"]): + for framework in envoptions.get("framework", "").split(","): + framework = framework.lower().strip() + if not framework: + continue + if framework in pkg_name: + self.PACKAGES[pkg_name]['default'] = True + + # enable upload tools for upload targets + if (set(["upload", "uploadlazy", "uploadeep", "program"]) + & set(targets)): + for _name, _opts in self.PACKAGES.iteritems(): + if _opts.get("alias") == "uploader": + self.PACKAGES[_name]['default'] = True + elif "uploadlazy" in targets: + # skip all packages, allow only upload tools + self.PACKAGES[_name]['default'] = False + + def install_default_packages(self, targets): + installed_platforms = PlatformFactory.get_platforms( + installed=True).keys() + + if (self.get_type() in installed_platforms and + set(self.get_default_packages()) <= + set(self.get_installed_packages())): + return True + + if (not app.get_setting("enable_prompts") or + self.get_type() in installed_platforms or + click.confirm( + "The platform '%s' has not been installed yet. " + "Would you like to install it now?" % self.get_type())): + return self.install() + else: + raise exception.PlatformNotInstalledYet(self.get_type()) + def run(self, variables, targets, verbose): assert isinstance(variables, list) assert isinstance(targets, list) + envoptions = {} + for v in variables: + _name, _value = v.split("=", 1) + envoptions[_name.lower()] = _value + + self.configure_default_packages(envoptions, targets) + self.install_default_packages(targets) + self._verbose_level = int(verbose) - installed_platforms = PlatformFactory.get_platforms( - installed=True).keys() - installed_packages = PackageManager.get_installed() - - if self.get_type() not in installed_platforms: - raise exception.PlatformNotInstalledYet(self.get_type()) - if "clean" in targets: targets.remove("clean") targets.append("-c") - if not any([v.startswith("BUILD_SCRIPT=") for v in variables]): + if "build_script" not in envoptions: variables.append("BUILD_SCRIPT=%s" % self.get_build_script()) for v in variables: if not v.startswith("BUILD_SCRIPT="): continue - _, path = v.split("=", 2) + _, path = v.split("=", 1) if not isfile(path): raise exception.BuildScriptNotFound(path) # append aliases of the installed packages + installed_packages = PackageManager.get_installed() for name, options in self.get_packages().items(): if "alias" not in options or name not in installed_packages: continue diff --git a/platformio/platforms/espressif.py b/platformio/platforms/espressif.py index 1b4ea3ab..a6784e1a 100644 --- a/platformio/platforms/espressif.py +++ b/platformio/platforms/espressif.py @@ -42,13 +42,19 @@ class EspressifPlatform(BasePlatform): }, "sdk-esp8266": { - "default": True }, "framework-arduinoespressif": { - "default": True + "alias": "framework" } } def get_name(self): return "Espressif" + + def configure_default_packages(self, envoptions, targets): + if not envoptions.get("framework"): + self.PACKAGES['sdk-esp8266']['default'] = True + + return BasePlatform.configure_default_packages( + self, envoptions, targets) diff --git a/platformio/platforms/freescalekinetis.py b/platformio/platforms/freescalekinetis.py index d076fd67..2420309f 100644 --- a/platformio/platforms/freescalekinetis.py +++ b/platformio/platforms/freescalekinetis.py @@ -34,7 +34,7 @@ class FreescalekinetisPlatform(BasePlatform): }, "framework-mbed": { - "default": True + "alias": "framework" } } diff --git a/platformio/platforms/linux_arm.py b/platformio/platforms/linux_arm.py index 87f2c26a..95775976 100644 --- a/platformio/platforms/linux_arm.py +++ b/platformio/platforms/linux_arm.py @@ -12,8 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +from platformio import exception, util from platformio.platforms.base import BasePlatform -from platformio.util import get_systype class Linux_armPlatform(BasePlatform): @@ -34,10 +34,26 @@ class Linux_armPlatform(BasePlatform): "toolchain-gccarmlinuxgnueabi": { "alias": "toolchain", "default": True + }, + + "framework-wiringpi": { + "alias": "framework" } } def __init__(self): - if "linux_arm" in get_systype(): + if "linux_arm" in util.get_systype(): del self.PACKAGES['toolchain-gccarmlinuxgnueabi'] BasePlatform.__init__(self) + + def configure_default_packages(self, envoptions, targets): + if (envoptions.get("framework") == "wiringpi" and + "linux_arm" not in util.get_systype()): + raise exception.PlatformioException( + "PlatformIO does not support temporary cross-compilation " + "for WiringPi framework. Please run PlatformIO directly on " + "Raspberry Pi" + ) + + return BasePlatform.configure_default_packages( + self, envoptions, targets) diff --git a/platformio/platforms/nordicnrf51.py b/platformio/platforms/nordicnrf51.py index cbdca343..b2ef7197 100644 --- a/platformio/platforms/nordicnrf51.py +++ b/platformio/platforms/nordicnrf51.py @@ -36,7 +36,7 @@ class Nordicnrf51Platform(BasePlatform): }, "framework-mbed": { - "default": True + "alias": "framework" } } diff --git a/platformio/platforms/nxplpc.py b/platformio/platforms/nxplpc.py index 80700560..d924ba76 100644 --- a/platformio/platforms/nxplpc.py +++ b/platformio/platforms/nxplpc.py @@ -36,7 +36,7 @@ class NxplpcPlatform(BasePlatform): }, "framework-mbed": { - "default": True + "alias": "framework" } } diff --git a/platformio/platforms/siliconlabsefm32.py b/platformio/platforms/siliconlabsefm32.py index ea3c44d8..889c650f 100644 --- a/platformio/platforms/siliconlabsefm32.py +++ b/platformio/platforms/siliconlabsefm32.py @@ -39,7 +39,7 @@ class Siliconlabsefm32Platform(BasePlatform): }, "framework-mbed": { - "default": True + "alias": "framework" } } diff --git a/platformio/platforms/ststm32.py b/platformio/platforms/ststm32.py index 29cedebe..7aee7f1a 100644 --- a/platformio/platforms/ststm32.py +++ b/platformio/platforms/ststm32.py @@ -40,24 +40,23 @@ class Ststm32Platform(BasePlatform): }, "tool-stlink": { - "alias": "uploader", - "default": True + "alias": "uploader" }, "framework-cmsis": { - "default": True + "alias": "framework" }, "framework-spl": { - "default": True + "alias": "framework" }, "framework-libopencm3": { - "default": True + "alias": "framework" }, "framework-mbed": { - "default": True + "alias": "framework" } } diff --git a/platformio/platforms/teensy.py b/platformio/platforms/teensy.py index 31688f4e..0dcd6351 100644 --- a/platformio/platforms/teensy.py +++ b/platformio/platforms/teensy.py @@ -31,11 +31,9 @@ class TeensyPlatform(BasePlatform): PACKAGES = { "toolchain-atmelavr": { - "default": True }, "toolchain-gccarmnoneeabi": { - "default": True }, "ldscripts": { @@ -43,32 +41,30 @@ class TeensyPlatform(BasePlatform): }, "framework-arduinoteensy": { - "default": True + "alias": "framework" }, "framework-mbed": { - "default": True + "alias": "framework" }, "tool-teensy": { - "alias": "uploader", - "default": True + "alias": "uploader" } } def get_name(self): return "Teensy" - def run(self, variables, targets, verbose): - for v in variables: - if "BOARD=" not in v: - continue - _, board = v.split("=") - bdata = get_boards(board) - if bdata['build']['core'] == "teensy": - tpackage = "toolchain-atmelavr" + def configure_default_packages(self, envoptions, targets): + if envoptions.get("board"): + board = get_boards(envoptions.get("board")) + if board['build']['core'] == "teensy": + name = "toolchain-atmelavr" else: - tpackage = "toolchain-gccarmnoneeabi" - self.PACKAGES[tpackage]['alias'] = "toolchain" - break - return BasePlatform.run(self, variables, targets, verbose) + name = "toolchain-gccarmnoneeabi" + self.PACKAGES[name]['alias'] = "toolchain" + self.PACKAGES[name]['default'] = True + + return BasePlatform.configure_default_packages( + self, envoptions, targets) diff --git a/platformio/platforms/timsp430.py b/platformio/platforms/timsp430.py index e4f7c0e2..ca78e2ca 100644 --- a/platformio/platforms/timsp430.py +++ b/platformio/platforms/timsp430.py @@ -34,16 +34,15 @@ class Timsp430Platform(BasePlatform): }, "tool-mspdebug": { - "alias": "uploader", - "default": True + "alias": "uploader" }, "framework-energiamsp430": { - "default": True + "alias": "framework" }, "framework-arduinomsp430": { - "default": True + "alias": "framework" } } diff --git a/platformio/platforms/titiva.py b/platformio/platforms/titiva.py index 5ba21463..2db28880 100644 --- a/platformio/platforms/titiva.py +++ b/platformio/platforms/titiva.py @@ -38,16 +38,15 @@ class TitivaPlatform(BasePlatform): }, "tool-lm4flash": { - "alias": "uploader", - "default": True + "alias": "uploader" }, "framework-energiativa": { - "default": True + "alias": "framework" }, "framework-libopencm3": { - "default": True + "alias": "framework" } }