diff --git a/HISTORY.rst b/HISTORY.rst index c9416975..b672ab6c 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -4,6 +4,36 @@ Release Notes PlatformIO 3.0 -------------- +3.5.2 (2018-03-13) +~~~~~~~~~~~~~~~~~~ + +* `PlatformIO Home `__ - + interact with PlatformIO ecosystem using modern and cross-platform GUI: + + - Multiple themes (Dark & Light) + - Ability to specify a name for new project + +* Control `PIO Unified Debugger `__ + and its firmware loading mode using + `debug_load_mode `__ option +* Added aliases (off, light, strict) for + `LDF Compatibility Mode `__ +* Search for a library using PIO Library Registry ID ``id:X`` (e.g. ``pio lib search id:13``) +* Show device system information (MCU, Frequency, RAM, Flash, Debugging tools) + in a build log +* Show all available upload protocols before firmware uploading in a build log +* Handle "os.mbed.com" URL as a Mercurial (hg) repository +* Improved support for old mbed libraries without manifest +* Fixed project generator for Qt Creator IDE + (`issue #1303 `_, + `issue #1323 `_) +* Mark project source and library directories for CLion IDE + (`issue #1359 `_, + `issue #1345 `_, + `issue #897 `_) +* Fixed issue with duplicated "include" records when generating data for IDE + (`issue #1301 `_) + 3.5.1 (2018-01-18) ~~~~~~~~~~~~~~~~~~ @@ -492,7 +522,7 @@ PlatformIO 2.0 * Added support for `emonPi `__, the OpenEnergyMonitor system (`issue #687 `_) -* Added support for `SPL `__ +* Added support for `SPL `__ framework for STM32F0 boards (`issue #683 `_) * Added support for `Arduboy DevKit `__, the game system @@ -1183,7 +1213,7 @@ PlatformIO 1.0 1.5.0 (2015-05-15) ~~~~~~~~~~~~~~~~~~ -* Added support of `Framework mbed `_ +* Added support of `Framework mbed `_ for Teensy 3.1 (`issue #183 `_) * Added GDB as alternative uploader to `ststm32 `__ platform @@ -1268,9 +1298,9 @@ PlatformIO 1.0 `ststm32 `__ development platform * Created new `Frameworks `__ - page in documentation and added to `PlatformIO Web Site `_ + page in documentation and added to `PlatformIO Web Site `_ (`issue #115 `_) -* Introduced online `Embedded Boards Explorer `_ +* Introduced online `Embedded Boards Explorer `_ * Automatically append define ``-DPLATFORMIO=%version%`` to builder (`issue #105 `_) * Renamed ``stm32`` development platform to diff --git a/README.rst b/README.rst index 82898d08..bfb2ebf9 100644 --- a/README.rst +++ b/README.rst @@ -18,101 +18,104 @@ PlatformIO :alt: License .. image:: https://img.shields.io/PlatformIO/Community.png :alt: Community Forums - :target: https://community.platformio.org + :target: https://community.platformio.org?utm_source=github&utm_medium=core .. image:: https://img.shields.io/PlatformIO/Plus.png?color=orange :alt: PlatformIO Plus: Professional solutions for an awesome open source PlatformIO ecosystem - :target: https://pioplus.com + :target: https://platformio.org/pricing?utm_source=github&utm_medium=core -**Quick Links:** `Home Page `_ | -`PlatformIO Plus `_ | -`PlatformIO IDE `_ | +**Quick Links:** `Home Page `_ | +`PlatformIO Plus `_ | +`PlatformIO IDE `_ | `Project Examples `_ | -`Docs `_ | -`Donate `_ | -`Contact Us `_ +`Docs `_ | +`Donate `_ | +`Contact Us `_ **Social:** `Twitter `_ | `Facebook `_ | `Hackaday `_ | `Bintray `_ | -`Community `_ +`Community `_ .. image:: https://raw.githubusercontent.com/platformio/platformio-web/develop/app/images/platformio-ide-laptop.png - :target: http://platformio.org + :target: https://platformio.org?utm_source=github&utm_medium=core -`PlatformIO `_ is an open source ecosystem for IoT +`PlatformIO `_ is an open source ecosystem for IoT development. Cross-platform IDE and unified debugger. Remote unit testing and firmware updates. Get Started ----------- -* `What is PlatformIO? `_ +* `What is PlatformIO? `_ Products -------- -* `PlatformIO IDE `_ -* `PlatformIO Core `_ -* `PIO Remote™ `_ -* `PIO Unified Debugger `_ -* `PIO Unit Testing `_ -* `PIO Delivery™ `_ -* `Cloud Builder `_ +* `PlatformIO IDE `_ +* `PlatformIO Core (CLI) `_ +* `PIO Remote™ `_ +* `PIO Unified Debugger `_ +* `PIO Unit Testing `_ +* `PIO Delivery™ `_ +* `Cloud Builder `_ Registry -------- -* `Libraries `_ -* `Development Platforms `_ -* `Frameworks `_ -* `Embedded Boards `_ +* `Libraries `_ +* `Development Platforms `_ +* `Frameworks `_ +* `Embedded Boards `_ Solutions --------- -* `Library Manager `_ -* `Cloud IDEs Integration `_ -* `Standalone IDEs Integration `_ -* `Continuous Integration `_ +* `Library Manager `_ +* `Cloud IDEs Integration `_ +* `Standalone IDEs Integration `_ +* `Continuous Integration `_ Development Platforms --------------------- -* `Atmel AVR `_ -* `Atmel SAM `_ -* `Espressif 32 `_ -* `Espressif 8266 `_ -* `Freescale Kinetis `_ -* `Intel ARC32 `_ -* `Lattice iCE40 `_ -* `Maxim 32 `_ -* `Microchip PIC32 `_ -* `Nordic nRF51 `_ -* `Nordic nRF52 `_ -* `NXP LPC `_ -* `Silicon Labs EFM32 `_ -* `ST STM32 `_ -* `Teensy `_ -* `TI MSP430 `_ -* `TI Tiva `_ -* `WIZNet W7500 `_ +* `Atmel AVR `_ +* `Atmel SAM `_ +* `Espressif 32 `_ +* `Espressif 8266 `_ +* `Freescale Kinetis `_ +* `Intel ARC32 `_ +* `Lattice iCE40 `_ +* `Maxim 32 `_ +* `Microchip PIC32 `_ +* `Nordic nRF51 `_ +* `Nordic nRF52 `_ +* `NXP LPC `_ +* `Silicon Labs EFM32 `_ +* `ST STM32 `_ +* `Teensy `_ +* `TI MSP430 `_ +* `TI Tiva `_ +* `WIZNet W7500 `_ Frameworks ---------- -* `Arduino `_ -* `ARTIK SDK `_ -* `CMSIS `_ -* `Energia `_ -* `ESP-IDF `_ -* `libOpenCM3 `_ -* `mbed `_ -* `Pumbaa `_ -* `Simba `_ -* `SPL `_ -* `STM32Cube `_ -* `WiringPi `_ +* `Arduino `_ +* `ARTIK SDK `_ +* `CMSIS `_ +* `Energia `_ +* `ESP-IDF `_ +* `ESP8266 Non-OS SDK `_ +* `ESP8266 RTOS SDK `_ +* `libOpenCM3 `_ +* `mbed `_ +* `Pumbaa `_ +* `Simba `_ +* `SPL `_ +* `STM32Cube `_ +* `Tizen RT `_ +* `WiringPi `_ Contributing ------------ diff --git a/docs b/docs index 2e04299a..e9e78d04 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit 2e04299a170b3654d9f4ec3c78392fb9202e829b +Subproject commit e9e78d043e4a1ba699f3e8e2b12bfeeeb18b1bd7 diff --git a/examples b/examples index 2d081875..db8b4f3c 160000 --- a/examples +++ b/examples @@ -1 +1 @@ -Subproject commit 2d08187562e83b2b3d3a2d9f4d124c25f2629506 +Subproject commit db8b4f3c77cf9694986eb55280038c37dd43548a diff --git a/platformio/__init__.py b/platformio/__init__.py index db38e271..1a98a778 100644 --- a/platformio/__init__.py +++ b/platformio/__init__.py @@ -14,7 +14,7 @@ import sys -VERSION = (3, 5, 1) +VERSION = (3, 5, 2) __version__ = ".".join([str(s) for s in VERSION]) __title__ = "platformio" @@ -24,7 +24,7 @@ __description__ = ( "Remote unit testing and firmware updates. " "Arduino, ARM mbed, Espressif (ESP8266/ESP32), STM32, PIC32, nRF51/nRF52, " "FPGA, CMSIS, SPL, AVR, Samsung ARTIK, libOpenCM3") -__url__ = "http://platformio.org" +__url__ = "https://platformio.org" __author__ = "Ivan Kravets" __email__ = "me@ikravets.com" diff --git a/platformio/app.py b/platformio/app.py index f6015d36..8ca1ba4c 100644 --- a/platformio/app.py +++ b/platformio/app.py @@ -141,7 +141,7 @@ class ContentCache(object): self._db_path = None self._lockfile = None - self.cache_dir = cache_dir or join(util.get_home_dir(), ".cache") + self.cache_dir = cache_dir or util.get_cache_dir() self._db_path = join(self.cache_dir, "db.data") def __enter__(self): diff --git a/platformio/builder/main.py b/platformio/builder/main.py index c729e4af..04a19eba 100644 --- a/platformio/builder/main.py +++ b/platformio/builder/main.py @@ -20,7 +20,7 @@ from os.path import expanduser, join from time import time from SCons.Script import (ARGUMENTS, COMMAND_LINE_TARGETS, DEFAULT_TARGETS, - AllowSubstExceptions, AlwaysBuild, + Action, AllowSubstExceptions, AlwaysBuild, DefaultEnvironment, Variables) from platformio import util @@ -64,7 +64,11 @@ commonvars.AddVariables( ("UPLOAD_PROTOCOL",), ("UPLOAD_SPEED",), ("UPLOAD_FLAGS",), - ("UPLOAD_RESETMETHOD",) + ("UPLOAD_RESETMETHOD",), + + # debug options + ("DEBUG_TOOL",), + ) # yapf: disable @@ -75,7 +79,7 @@ MULTILINE_VARS = [ DEFAULT_ENV_OPTIONS = dict( tools=[ - "ar", "as", "gcc", "g++", "gnulink", "platformio", "pioplatform", + "ar", "gas", "gcc", "g++", "gnulink", "platformio", "pioplatform", "piowinhooks", "piolib", "pioupload", "piomisc", "pioide" ], # yapf: disable toolpath=[join(util.get_source_dir(), "builder", "tools")], @@ -182,3 +186,7 @@ if "idedata" in COMMAND_LINE_TARGETS: "See explanation in FAQ > Troubleshooting > Building\n" "http://docs.platformio.org/page/faq.html\n\n") env.Exit(1) + +env.AddPreAction(["upload", "program"], + Action(lambda source, target, env: env.PrintUploadInfo(), + "Configuring upload protocol...")) diff --git a/platformio/builder/tools/pioide.py b/platformio/builder/tools/pioide.py index 726d52dd..e3f98ca4 100644 --- a/platformio/builder/tools/pioide.py +++ b/platformio/builder/tools/pioide.py @@ -53,7 +53,13 @@ def _dump_includes(env): if unity_dir: includes.append(unity_dir) - return includes + # remove dupicates + result = [] + for item in includes: + if item not in result: + result.append(item) + + return result def _get_gcc_defines(env): diff --git a/platformio/builder/tools/piolib.py b/platformio/builder/tools/piolib.py index f20b6b08..b865771b 100644 --- a/platformio/builder/tools/piolib.py +++ b/platformio/builder/tools/piolib.py @@ -23,7 +23,6 @@ import sys from glob import glob from os.path import (basename, commonprefix, dirname, isdir, isfile, join, realpath, sep) -from platform import system import SCons.Scanner from SCons.Script import ARGUMENTS, COMMAND_LINE_TARGETS, DefaultEnvironment @@ -57,10 +56,9 @@ class LibBuilderFactory(object): @staticmethod def get_used_frameworks(env, path): - if any([ + if any( isfile(join(path, fname)) - for fname in ("library.properties", "keywords.txt") - ]): + for fname in ("library.properties", "keywords.txt")): return ["arduino"] if isfile(join(path, "module.json")): @@ -83,14 +81,21 @@ class LibBuilderFactory(object): class LibBuilderBase(object): + IS_WINDOWS = "windows" in util.get_systype() + LDF_MODES = ["off", "chain", "deep", "chain+", "deep+"] LDF_MODE_DEFAULT = "chain" - COMPAT_MODES = [0, 1, 2] - COMPAT_MODE_DEFAULT = 1 + COMPAT_MODES = ["off", "light", "strict"] + COMPAT_MODE_DEFAULT = "light" CLASSIC_SCANNER = SCons.Scanner.C.CScanner() - ADVANCED_SCANNER = SCons.Scanner.C.CScanner(advanced=True) + CCONDITIONAL_SCANNER = SCons.Scanner.C.CConditionalScanner() + # Max depth of nested includes: + # -1 = unlimited + # 0 - disabled nesting + # >0 - number of allowed nested includes + CCONDITIONAL_SCANNER_DEPTH = 99 PARSE_SRC_BY_H_NAME = True _INCLUDE_DIRS_CACHE = None @@ -120,7 +125,7 @@ class LibBuilderBase(object): def __contains__(self, path): p1 = self.path p2 = path - if system() == "Windows": + if self.IS_WINDOWS: p1 = p1.lower() p2 = p2.lower() return commonprefix((p1 + sep, p2)) == p1 + sep @@ -156,7 +161,7 @@ class LibBuilderBase(object): @property def include_dir(self): - if not all([isdir(join(self.path, d)) for d in ("include", "src")]): + if not all(isdir(join(self.path, d)) for d in ("include", "src")): return None return join(self.path, "include") @@ -230,12 +235,15 @@ class LibBuilderBase(object): @staticmethod def validate_compat_mode(mode): - try: - mode = int(mode) - assert mode in LibBuilderBase.COMPAT_MODES + if isinstance(mode, basestring): + mode = mode.strip().lower() + if mode in LibBuilderBase.COMPAT_MODES: return mode - except (AssertionError, ValueError): - return LibBuilderBase.COMPAT_MODE_DEFAULT + try: + return LibBuilderBase.COMPAT_MODES[int(mode)] + except (IndexError, ValueError): + pass + return LibBuilderBase.COMPAT_MODE_DEFAULT def is_platforms_compatible(self, platforms): return True @@ -340,17 +348,18 @@ class LibBuilderBase(object): for path in self._validate_search_files(search_files): try: assert "+" in self.lib_ldf_mode - incs = self.env.File(path).get_found_includes( - self.env, LibBuilderBase.ADVANCED_SCANNER, - tuple(include_dirs)) + incs = LibBuilderBase.CCONDITIONAL_SCANNER( + self.env.File(path), + self.env, + tuple(include_dirs), + depth=self.CCONDITIONAL_SCANNER_DEPTH) except Exception as e: # pylint: disable=broad-except if self.verbose and "+" in self.lib_ldf_mode: sys.stderr.write( "Warning! Classic Pre Processor is used for `%s`, " "advanced has failed with `%s`\n" % (path, e)) - _incs = self.env.File(path).get_found_includes( - self.env, LibBuilderBase.CLASSIC_SCANNER, - tuple(include_dirs)) + _incs = LibBuilderBase.CLASSIC_SCANNER( + self.env.File(path), self.env, tuple(include_dirs)) incs = [] for inc in _incs: incs.append(inc) @@ -517,8 +526,20 @@ class MbedLibBuilder(LibBuilderBase): include_dirs = LibBuilderBase.get_include_dirs(self) if self.path not in include_dirs: include_dirs.append(self.path) + + # library with module.json for p in self._manifest.get("extraIncludes", []): include_dirs.append(join(self.path, p)) + + # old mbed library without manifest, add to CPPPATH all folders + if not self._manifest: + for root, _, __ in os.walk(self.path): + part = root.replace(self.path, "").lower() + if any(s in part for s in ("%s." % sep, "test", "example")): + continue + if root not in include_dirs: + include_dirs.append(root) + return include_dirs def is_frameworks_compatible(self, frameworks): @@ -731,13 +752,13 @@ def GetLibBuilders(env): # pylint: disable=too-many-branches if verbose: sys.stderr.write("Ignored library %s\n" % lb.path) return None - if compat_mode > 1 and not lb.is_platforms_compatible( + if compat_mode == "strict" and not lb.is_platforms_compatible( env['PIOPLATFORM']): if verbose: sys.stderr.write( "Platform incompatible library %s\n" % lb.path) return False - if compat_mode > 0 and "PIOFRAMEWORK" in env and \ + if compat_mode == "light" and "PIOFRAMEWORK" in env and \ not lb.is_frameworks_compatible(env.get("PIOFRAMEWORK", [])): if verbose: sys.stderr.write( @@ -783,9 +804,8 @@ def GetLibBuilders(env): # pylint: disable=too-many-branches def BuildProjectLibraries(env): - lib_builders = env.GetLibBuilders() - def correct_found_libs(): + def correct_found_libs(lib_builders): # build full dependency graph found_lbs = [lb for lb in lib_builders if lb.dependent] for lb in lib_builders: @@ -803,7 +823,7 @@ def BuildProjectLibraries(env): vcs_info = lb.vcs_info if lb.version: title += " v%s" % lb.version - if vcs_info: + if vcs_info and vcs_info.get("version"): title += " #%s" % vcs_info.get("version") sys.stdout.write("%s|-- %s" % (margin, title)) if int(ARGUMENTS.get("PIOVERBOSE", 0)): @@ -816,20 +836,25 @@ def BuildProjectLibraries(env): if lb.depbuilders: print_deps_tree(lb, level + 1) - print "Collected %d compatible libraries" % len(lib_builders) - print "Scanning dependencies..." - project = ProjectAsLibBuilder(env, "$PROJECT_DIR") project.env = env + ldf_mode = LibBuilderBase.lib_ldf_mode.fget(project) + + print "Library Dependency Finder -> http://bit.ly/configure-pio-ldf" + print "LDF MODES: FINDER(%s) COMPATIBILITY(%s)" % (ldf_mode, + project.lib_compat_mode) + + lib_builders = env.GetLibBuilders() + print "Collected %d compatible libraries" % len(lib_builders) + + print "Scanning dependencies..." project.search_deps_recursive() - if (LibBuilderBase.validate_ldf_mode( - env.get("LIB_LDF_MODE", LibBuilderBase.LDF_MODE_DEFAULT)) - .startswith("chain") and project.depbuilders): - correct_found_libs() + if ldf_mode.startswith("chain") and project.depbuilders: + correct_found_libs(lib_builders) if project.depbuilders: - print "Library Dependency Graph ( http://bit.ly/configure-pio-ldf )" + print "Dependency Graph" print_deps_tree(project) else: print "No dependencies" diff --git a/platformio/builder/tools/pioplatform.py b/platformio/builder/tools/pioplatform.py index 02519dbe..6a77bc74 100644 --- a/platformio/builder/tools/pioplatform.py +++ b/platformio/builder/tools/pioplatform.py @@ -41,8 +41,9 @@ def PioPlatform(env): def BoardConfig(env, board=None): p = initPioPlatform(env['PLATFORM_MANIFEST']) try: - assert env.get("BOARD", board), "BoardConfig: Board is not defined" - config = p.board_config(board if board else env.get("BOARD")) + board = board or env.get("BOARD") + assert board, "BoardConfig: Board is not defined" + config = p.board_config(board) except (AssertionError, exception.UnknownBoard) as e: sys.stderr.write("Error: %s\n" % str(e)) env.Exit(1) @@ -97,6 +98,56 @@ def LoadPioPlatform(env, variables): env.Replace(LDSCRIPT_PATH=board_config.get("build.ldscript")) +def PrintConfiguration(env): # pylint: disable=too-many-branches + platform_data = ["PLATFORM: %s >" % env.PioPlatform().title] + system_data = ["SYSTEM:"] + mcu = env.subst("$BOARD_MCU") + f_cpu = env.subst("$BOARD_F_CPU") + if mcu: + system_data.append(mcu.upper()) + if f_cpu: + f_cpu = int("".join([c for c in str(f_cpu) if c.isdigit()])) + system_data.append("%dMHz" % (f_cpu / 1000000)) + + debug_tools = None + if "BOARD" in env: + board_config = env.BoardConfig() + platform_data.append(board_config.get("name")) + + debug_tools = board_config.get("debug", {}).get("tools") + ram = board_config.get("upload", {}).get("maximum_ram_size") + flash = board_config.get("upload", {}).get("maximum_size") + system_data.append("%s RAM (%s Flash)" % (util.format_filesize(ram), + util.format_filesize(flash))) + + if platform_data: + print " ".join(platform_data) + if system_data: + print " ".join(system_data) + + # Debugging + if not debug_tools: + return + + data = [ + "CURRENT(%s)" % board_config.get_debug_tool_name( + env.subst("$DEBUG_TOOL")) + ] + onboard = [] + external = [] + for key, value in debug_tools.items(): + if value.get("onboard"): + onboard.append(key) + else: + external.append(key) + if onboard: + data.append("ON-BOARD(%s)" % ", ".join(sorted(onboard))) + if external: + data.append("EXTERNAL(%s)" % ", ".join(sorted(external))) + + print "DEBUG: %s" % " ".join(data) + + def exists(_): return True @@ -106,4 +157,5 @@ def generate(env): env.AddMethod(BoardConfig) env.AddMethod(GetFrameworkScript) env.AddMethod(LoadPioPlatform) + env.AddMethod(PrintConfiguration) return env diff --git a/platformio/builder/tools/pioupload.py b/platformio/builder/tools/pioupload.py index ab7b27ca..7bc036fb 100644 --- a/platformio/builder/tools/pioupload.py +++ b/platformio/builder/tools/pioupload.py @@ -18,7 +18,6 @@ import sys from fnmatch import fnmatch from os import environ from os.path import isfile, join -from platform import system from shutil import copyfile from time import sleep @@ -114,10 +113,10 @@ def AutodetectUploadPort(*args, **kwargs): # pylint: disable=unused-argument mbed_pages = [ join(item['path'], n) for n in ("mbed.htm", "mbed.html") ] - if any([isfile(p) for p in mbed_pages]): + if any(isfile(p) for p in mbed_pages): return item['path'] if item['name'] \ - and any([l in item['name'].lower() for l in msdlabels]): + and any(l in item['name'].lower() for l in msdlabels): return item['path'] return None @@ -133,7 +132,8 @@ def AutodetectUploadPort(*args, **kwargs): # pylint: disable=unused-argument port = item['port'] if upload_protocol.startswith("blackmagic") \ and "GDB" in item['description']: - return port + return ("\\\\.\\%s" % port if "windows" in util.get_systype() + and port.startswith("COM") and len(port) > 4 else port) for hwid in board_hwids: hwid_str = ("%s:%s" % (hwid[0], hwid[1])).replace("0x", "") if hwid_str in item['hwid']: @@ -144,19 +144,20 @@ def AutodetectUploadPort(*args, **kwargs): # pylint: disable=unused-argument print env.subst("Use manually specified: $UPLOAD_PORT") return - if "mbed" in env.subst("$PIOFRAMEWORK") \ - and not env.subst("$UPLOAD_PROTOCOL"): + if (env.subst("$UPLOAD_PROTOCOL") == "mbed" + or ("mbed" in env.subst("$PIOFRAMEWORK") + and not env.subst("$UPLOAD_PROTOCOL"))): env.Replace(UPLOAD_PORT=_look_for_mbed_disk()) else: - if (system() == "Linux" and not any([ + if ("linux" in util.get_systype() and not any([ isfile("/etc/udev/rules.d/99-platformio-udev.rules"), isfile("/lib/udev/rules.d/99-platformio-udev.rules") ])): sys.stderr.write( "\nWarning! Please install `99-platformio-udev.rules` and " "check that your board's PID and VID are listed in the rules." - "\n https://raw.githubusercontent.com/platformio/platformio" - "/develop/scripts/99-platformio-udev.rules\n") + "\n http://docs.platformio.org/en/latest/faq.html" + "#platformio-udev-rules\n") env.Replace(UPLOAD_PORT=_look_for_serial_port()) if env.subst("$UPLOAD_PORT"): @@ -212,6 +213,18 @@ def CheckUploadSize(_, target, source, env): # pylint: disable=W0613,W0621 env.Exit(1) +def PrintUploadInfo(env): + configured = env.subst("$UPLOAD_PROTOCOL") + available = [configured] if configured else [] + if "BOARD" in env: + available.extend(env.BoardConfig().get("upload", {}).get( + "protocols", [])) + if available: + print "AVAILABLE: %s" % ", ".join(sorted(available)) + if configured: + print "CURRENT: upload_protocol = %s" % configured + + def exists(_): return True @@ -223,4 +236,5 @@ def generate(env): env.AddMethod(AutodetectUploadPort) env.AddMethod(UploadToDisk) env.AddMethod(CheckUploadSize) + env.AddMethod(PrintUploadInfo) return env diff --git a/platformio/builder/tools/platformio.py b/platformio/builder/tools/platformio.py index f9dd5386..da82de85 100644 --- a/platformio/builder/tools/platformio.py +++ b/platformio/builder/tools/platformio.py @@ -20,10 +20,9 @@ from glob import glob from os import sep, walk from os.path import basename, dirname, isdir, join, realpath -from SCons.Action import Action +from SCons import Action, Builder, Util from SCons.Script import (COMMAND_LINE_TARGETS, AlwaysBuild, DefaultEnvironment, SConscript) -from SCons.Util import case_sensitive_suffixes, is_Sequence from platformio.util import glob_escape, pioversion_to_intstr @@ -33,6 +32,16 @@ SRC_BUILD_EXT = SRC_C_EXT + ["S", "spp", "SPP", "sx", "s", "asm", "ASM"] SRC_FILTER_DEFAULT = ["+<*>", "-<.git%s>" % sep, "-" % sep] +def scons_patched_match_splitext(path, suffixes=None): + """ + Patch SCons Builder, append $OBJSUFFIX to the end of each target + """ + tokens = Util.splitext(path) + if suffixes and tokens[1] and tokens[1] in suffixes: + return (path, tokens[1]) + return tokens + + def BuildProgram(env): def _append_pio_macros(): @@ -42,8 +51,10 @@ def BuildProgram(env): _append_pio_macros() - # fix ASM handling under non-casitive OS - if not case_sensitive_suffixes(".s", ".S"): + env.PrintConfiguration() + + # fix ASM handling under non case-sensitive OS + if not Util.case_sensitive_suffixes(".s", ".S"): env.Replace(AS="$CC", ASCOM="$ASPPCOM") if "__debug" in COMMAND_LINE_TARGETS: @@ -63,12 +74,12 @@ def BuildProgram(env): # restore PIO macros if it was deleted by framework _append_pio_macros() - # build dependent libs - env.Append(LIBS=env.BuildProjectLibraries()) + # build dependent libs; place them before built-in libs + env.Prepend(LIBS=env.BuildProjectLibraries()) # append specified LD_SCRIPT if ("LDSCRIPT_PATH" in env - and not any(["-Wl,-T" in f for f in env['LINKFLAGS']])): + and not any("-Wl,-T" in f for f in env['LINKFLAGS'])): env.Append(LINKFLAGS=['-Wl,-T"$LDSCRIPT_PATH"']) # enable "cyclic reference" for linker @@ -99,7 +110,8 @@ def BuildProgram(env): program = env.Program( join("$BUILD_DIR", env.subst("$PROGNAME")), env['PIOBUILDFILES']) - checksize_action = Action(env.CheckUploadSize, "Checking program size") + checksize_action = Action.Action(env.CheckUploadSize, + "Checking program size") AlwaysBuild(env.Alias("checkprogsize", program, checksize_action)) if set(["upload", "program"]) & set(COMMAND_LINE_TARGETS): env.AddPostAction(program, checksize_action) @@ -114,7 +126,7 @@ def ProcessFlags(env, flags): # pylint: disable=too-many-branches flags = " ".join(flags) parsed_flags = env.ParseFlags(str(flags)) for flag in parsed_flags.pop("CPPDEFINES"): - if not is_Sequence(flag): + if not Util.is_Sequence(flag): env.Append(CPPDEFINES=flag) continue _key, _value = flag[:2] @@ -256,6 +268,8 @@ def BuildFrameworks(env, frameworks): for f in frameworks: if f in ("arduino", "energia"): + # Arduino IDE appends .o the end of filename + Builder.match_splitext = scons_patched_match_splitext env.ConvertInoToCpp() if f in board_frameworks: diff --git a/platformio/commands/boards.py b/platformio/commands/boards.py index e4921354..5764b9f8 100644 --- a/platformio/commands/boards.py +++ b/platformio/commands/boards.py @@ -16,6 +16,7 @@ import json import click +from platformio import util from platformio.managers.platform import PlatformManager @@ -60,22 +61,13 @@ def print_boards(boards): click.echo("-" * terminal_width) for board in boards: - ram_size = board['ram'] - if ram_size >= 1024: - if ram_size % 1024: - ram_size = "%.1fkB" % (ram_size / 1024.0) - else: - ram_size = "%dkB" % (ram_size / 1024) - else: - ram_size = "%dB" % ram_size - click.echo( BOARDLIST_TPL.format( type=click.style(board['id'], fg="cyan"), mcu=board['mcu'], - frequency="%dMhz" % (board['fcpu'] / 1000000), - flash="%dkB" % (board['rom'] / 1024), - ram=ram_size, + frequency="%dMHz" % (board['fcpu'] / 1000000), + flash=util.format_filesize(board['rom']), + ram=util.format_filesize(board['ram']), name=board['name'])) diff --git a/platformio/commands/init.py b/platformio/commands/init.py index 7cfc0672..dadf3e77 100644 --- a/platformio/commands/init.py +++ b/platformio/commands/init.py @@ -231,8 +231,14 @@ def init_ci_conf(project_dir): # python: # - "2.7" # +# sudo: false +# cache: +# directories: +# - "~/.platformio" +# # install: # - pip install -U platformio +# - platformio update # # script: # - platformio run @@ -246,6 +252,11 @@ def init_ci_conf(project_dir): # python: # - "2.7" # +# sudo: false +# cache: +# directories: +# - "~/.platformio" +# # env: # - PLATFORMIO_CI_SRC=path/to/test/file.c # - PLATFORMIO_CI_SRC=examples/file.ino @@ -253,6 +264,7 @@ def init_ci_conf(project_dir): # # install: # - pip install -U platformio +# - platformio update # # script: # - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/platformio/commands/lib.py b/platformio/commands/lib.py index 87f87d7c..ee2ec01d 100644 --- a/platformio/commands/lib.py +++ b/platformio/commands/lib.py @@ -186,6 +186,7 @@ def print_lib_item(item): @click.argument("query", required=False, nargs=-1) @click.option("--json-output", is_flag=True) @click.option("--page", type=click.INT, default=1) +@click.option("--id", multiple=True) @click.option("-n", "--name", multiple=True) @click.option("-a", "--author", multiple=True) @click.option("-k", "--keyword", multiple=True) @@ -428,7 +429,7 @@ def lib_stats(json_output): time.strftime("%c", util.parse_date(item['date'])) if "date" in item else ""), url=click.style( - "http://platformio.org/lib/show/%s/%s" % + "https://platformio.org/lib/show/%s/%s" % (item['id'], quote(item['name'])), fg="blue"))) @@ -437,7 +438,7 @@ def lib_stats(json_output): printitem_tpl.format( name=click.style(name, fg="cyan"), url=click.style( - "http://platformio.org/lib/search?query=" + + "https://platformio.org/lib/search?query=" + quote("keyword:%s" % name), fg="blue"))) diff --git a/platformio/commands/platform.py b/platformio/commands/platform.py index 8fcc70b0..f6307be5 100644 --- a/platformio/commands/platform.py +++ b/platformio/commands/platform.py @@ -195,7 +195,7 @@ def platform_frameworks(query, json_output): if query and query.lower() not in search_data.lower(): continue framework['homepage'] = ( - "http://platformio.org/frameworks/" + framework['name']) + "https://platformio.org/frameworks/" + framework['name']) framework['platforms'] = [ platform['name'] for platform in _get_registry_platforms() if framework['name'] in platform['frameworks'] diff --git a/platformio/commands/run.py b/platformio/commands/run.py index f75a07c9..c0aab27f 100644 --- a/platformio/commands/run.py +++ b/platformio/commands/run.py @@ -71,14 +71,14 @@ def cli(ctx, environment, target, upload_port, project_dir, silent, verbose, fg="yellow") config = util.load_project_config() - check_project_defopts(config) - assert check_project_envs(config, environment) - env_default = None if config.has_option("platformio", "env_default"): env_default = util.parse_conf_multi_values( config.get("platformio", "env_default")) + check_project_defopts(config) + check_project_envs(config, environment or env_default) + results = [] start_time = time() for section in config.sections(): @@ -111,7 +111,7 @@ def cli(ctx, environment, target, upload_port, project_dir, silent, verbose, "nobuild" not in ep.get_build_targets(): ctx.invoke(cmd_device_monitor) - found_error = any([status is False for (_, status) in results]) + found_error = any(status is False for (_, status) in results) if (found_error or not silent) and len(results) > 1: click.echo() @@ -124,25 +124,33 @@ def cli(ctx, environment, target, upload_port, project_dir, silent, verbose, class EnvironmentProcessor(object): - KNOWN_OPTIONS = ("platform", "framework", "board", "board_mcu", - "board_f_cpu", "board_f_flash", "board_flash_mode", - "build_flags", "src_build_flags", "build_unflags", - "src_filter", "extra_scripts", "targets", "upload_port", - "upload_protocol", "upload_speed", "upload_flags", - "upload_resetmethod", "lib_deps", "lib_ignore", - "lib_extra_dirs", "lib_ldf_mode", "lib_compat_mode", - "lib_archive", "piotest", "test_transport", "test_filter", - "test_ignore", "test_port", "test_speed", "debug_tool", - "debug_port", "debug_init_cmds", "debug_extra_cmds", - "debug_server", "debug_init_break", "debug_load_cmd", - "monitor_port", "monitor_baud", "monitor_rts", - "monitor_dtr") + DEFAULT_DUMP_OPTIONS = ("platform", "framework", "board") + + KNOWN_PLATFORMIO_OPTIONS = ("env_default", "home_dir", "lib_dir", + "libdeps_dir", "include_dir", "src_dir", + "build_dir", "data_dir", "test_dir", + "boards_dir", "lib_extra_dirs") + + KNOWN_ENV_OPTIONS = ("platform", "framework", "board", "board_mcu", + "board_f_cpu", "board_f_flash", "board_flash_mode", + "build_flags", "src_build_flags", "build_unflags", + "src_filter", "extra_scripts", "targets", + "upload_port", "upload_protocol", "upload_speed", + "upload_flags", "upload_resetmethod", "lib_deps", + "lib_ignore", "lib_extra_dirs", "lib_ldf_mode", + "lib_compat_mode", "lib_archive", "piotest", + "test_transport", "test_filter", "test_ignore", + "test_port", "test_speed", "debug_tool", "debug_port", + "debug_init_cmds", "debug_extra_cmds", "debug_server", + "debug_init_break", "debug_load_cmd", + "debug_load_mode", "monitor_port", "monitor_baud", + "monitor_rts", "monitor_dtr") IGNORE_BUILD_OPTIONS = ("test_transport", "test_filter", "test_ignore", - "test_port", "test_speed", "debug_tool", - "debug_port", "debug_init_cmds", - "debug_extra_cmds", "debug_server", - "debug_init_break", "debug_load_cmd", + "test_port", "test_speed", "debug_port", + "debug_init_cmds", "debug_extra_cmds", + "debug_server", "debug_init_break", + "debug_load_cmd", "debug_load_mode", "monitor_port", "monitor_baud", "monitor_rts", "monitor_dtr") @@ -176,19 +184,19 @@ class EnvironmentProcessor(object): def process(self): terminal_width, _ = click.get_terminal_size() start_time = time() + env_dump = [] for k, v in self.options.items(): self.options[k] = self.options[k].strip() + if self.verbose or k in self.DEFAULT_DUMP_OPTIONS: + env_dump.append( + "%s: %s" % (k, ", ".join(util.parse_conf_multi_values(v)))) if not self.silent: click.echo("[%s] Processing %s (%s)" % (datetime.now().strftime("%c"), click.style(self.name, fg="cyan", bold=True), - "; ".join([ - "%s: %s" % - (k, ", ".join(util.parse_conf_multi_values(v))) - for k, v in self.options.items() - ]))) + "; ".join(env_dump))) click.secho("-" * terminal_width, bold=True) self.options = self._validate_options(self.options) @@ -229,7 +237,7 @@ class EnvironmentProcessor(object): v = self.RENAMED_PLATFORMS[v] # warn about unknown options - if k not in self.KNOWN_OPTIONS and not k.startswith("custom_"): + if k not in self.KNOWN_ENV_OPTIONS and not k.startswith("custom_"): click.secho( "Detected non-PlatformIO `%s` option in `[env:%s]` section" % (k, self.name), @@ -379,10 +387,8 @@ def print_summary(results, start_time): def check_project_defopts(config): if not config.has_section("platformio"): return True - known = ("env_default", "home_dir", "lib_dir", "libdeps_dir", "src_dir", - "build_dir", "data_dir", "test_dir", "boards_dir", - "lib_extra_dirs") - unknown = set([k for k, _ in config.items("platformio")]) - set(known) + unknown = set([k for k, _ in config.items("platformio")]) - set( + EnvironmentProcessor.KNOWN_PLATFORMIO_OPTIONS) if not unknown: return True click.secho( @@ -392,18 +398,19 @@ def check_project_defopts(config): return False -def check_project_envs(config, environments): +def check_project_envs(config, environments=None): if not config.sections(): raise exception.ProjectEnvsNotAvailable() known = set([s[4:] for s in config.sections() if s.startswith("env:")]) - unknown = set(environments) - known + unknown = set(environments or []) - known if unknown: raise exception.UnknownEnvNames(", ".join(unknown), ", ".join(known)) return True def calculate_project_hash(): + check_suffixes = (".c", ".cc", ".cpp", ".h", ".hpp", ".s", ".S") structure = [__version__] for d in (util.get_projectsrc_dir(), util.get_projectlib_dir()): if not isdir(d): @@ -411,6 +418,6 @@ def calculate_project_hash(): for root, _, files in walk(d): for f in files: path = join(root, f) - if not any([s in path for s in (".git", ".svn", ".pioenvs")]): + if path.endswith(check_suffixes): structure.append(path) - return sha1(",".join(sorted(structure))).hexdigest() if structure else "" + return sha1(",".join(sorted(structure))).hexdigest() diff --git a/platformio/commands/upgrade.py b/platformio/commands/upgrade.py index 97014d2b..3c54764b 100644 --- a/platformio/commands/upgrade.py +++ b/platformio/commands/upgrade.py @@ -12,7 +12,9 @@ # See the License for the specific language governing permissions and # limitations under the License. +import os import re +from zipfile import ZipFile import click import requests @@ -36,12 +38,9 @@ def cli(dev): # kill all PIO Home servers, they block `pioplus` binary shutdown_servers() - to_develop = dev or not all([c.isdigit() for c in __version__ if c != "."]) - cmds = ([ - "pip", "install", "--upgrade", - "https://github.com/platformio/platformio-core/archive/develop.zip" - if to_develop else "platformio" - ], ["platformio", "--version"]) + to_develop = dev or not all(c.isdigit() for c in __version__ if c != ".") + cmds = (["pip", "install", "--upgrade", + get_pip_package(to_develop)], ["platformio", "--version"]) cmd = None r = None @@ -69,7 +68,7 @@ def cli(dev): if not r: raise exception.UpgradeError("\n".join([str(cmd), str(e)])) permission_errors = ("permission denied", "not permitted") - if (any([m in r['err'].lower() for m in permission_errors]) + if (any(m in r['err'].lower() for m in permission_errors) and "windows" not in util.get_systype()): click.secho( """ @@ -92,6 +91,29 @@ WARNING! Don't use `sudo` for the rest PlatformIO commands. return True +def get_pip_package(to_develop): + if not to_develop: + return "platformio" + dl_url = ("https://github.com/platformio/" + "platformio-core/archive/develop.zip") + cache_dir = util.get_cache_dir() + if not os.path.isdir(cache_dir): + os.makedirs(cache_dir) + pkg_name = os.path.join(cache_dir, "piocoredevelop.zip") + try: + with open(pkg_name, "w") as fp: + r = util.exec_command( + ["curl", "-fsSL", dl_url], stdout=fp, universal_newlines=True) + assert r['returncode'] == 0 + # check ZIP structure + with ZipFile(pkg_name) as zp: + assert zp.testzip() is None + return pkg_name + except: # pylint: disable=bare-except + pass + return dl_url + + def get_latest_version(): try: if not str(VERSION[2]).isdigit(): diff --git a/platformio/downloader.py b/platformio/downloader.py index 4dc84a83..df9f65a2 100644 --- a/platformio/downloader.py +++ b/platformio/downloader.py @@ -48,7 +48,7 @@ class FileDownloader(object): "'", "") self._fname = self._fname.encode("utf8") else: - self._fname = url.split("/")[-1] + self._fname = [p for p in url.split("/") if p][-1] self._progressbar = None self._destination = self._fname diff --git a/platformio/exception.py b/platformio/exception.py index 073ea4f7..afedf5a9 100644 --- a/platformio/exception.py +++ b/platformio/exception.py @@ -98,8 +98,8 @@ class UndefinedPackageVersion(PlatformioException): class PackageInstallError(PlatformioException): MESSAGE = ("Could not install '{0}' with version requirements '{1}' " - "for your system '{2}'.\n" - "More details: http://bit.ly/faq-package-manager") + "for your system '{2}'.\n\n" + "Please try this solution -> http://bit.ly/faq-package-manager") class FDUnrecognizedStatusCode(PlatformioException): @@ -238,3 +238,15 @@ class CygwinEnvDetected(PlatformioException): MESSAGE = ("PlatformIO does not work within Cygwin environment. " "Use native Terminal instead.") + + +class DebugSupportError(PlatformioException): + + MESSAGE = ("Currently, PlatformIO does not support debugging for `{0}`.\n" + "Please mail contact@pioplus.com or visit " + "< http://docs.platformio.org/page/plus/debugging.html >") + + +class DebugInvalidOptions(PlatformioException): + + pass diff --git a/platformio/ide/projectgenerator.py b/platformio/ide/projectgenerator.py index e1d5b12a..cde75693 100644 --- a/platformio/ide/projectgenerator.py +++ b/platformio/ide/projectgenerator.py @@ -30,11 +30,8 @@ class ProjectGenerator(object): self.project_dir = project_dir self.ide = ide self.env_name = env_name + self._tplvars = {} - - with util.cd(self.project_dir): - self.project_src_dir = util.get_projectsrc_dir() - self._gather_tplvars() @staticmethod @@ -92,7 +89,7 @@ class ProjectGenerator(object): def get_src_files(self): result = [] with util.cd(self.project_dir): - for root, _, files in os.walk(self.project_src_dir): + for root, _, files in os.walk(util.get_projectsrc_dir()): for f in files: result.append(relpath(join(root, f))) return result @@ -153,26 +150,21 @@ class ProjectGenerator(object): def _gather_tplvars(self): self._tplvars.update(self.get_project_env()) self._tplvars.update(self.get_project_build_data()) - self._tplvars.update({ - "project_name": - self.get_project_name(), - "src_files": - self.get_src_files(), - "user_home_dir": - abspath(expanduser("~")), - "project_dir": - self.project_dir, - "project_src_dir": - self.project_src_dir, - "systype": - util.get_systype(), - "platformio_path": - self._fix_os_path(util.where_is_program("platformio")), - "env_pathsep": - os.pathsep, - "env_path": - self._fix_os_path(os.getenv("PATH")) - }) + with util.cd(self.project_dir): + self._tplvars.update({ + "project_name": self.get_project_name(), + "src_files": self.get_src_files(), + "user_home_dir": abspath(expanduser("~")), + "project_dir": self.project_dir, + "project_src_dir": util.get_projectsrc_dir(), + "project_lib_dir": util.get_projectlib_dir(), + "project_libdeps_dir": util.get_projectlibdeps_dir(), + "systype": util.get_systype(), + "platformio_path": self._fix_os_path( + util.where_is_program("platformio")), + "env_pathsep": os.pathsep, + "env_path": self._fix_os_path(os.getenv("PATH")) + }) # yapf: disable @staticmethod def _fix_os_path(path): diff --git a/platformio/ide/tpls/clion/.idea/misc.xml.tpl b/platformio/ide/tpls/clion/.idea/misc.xml.tpl new file mode 100644 index 00000000..2b0c16ca --- /dev/null +++ b/platformio/ide/tpls/clion/.idea/misc.xml.tpl @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/platformio/ide/tpls/clion/CMakeLists.txt.tpl b/platformio/ide/tpls/clion/CMakeLists.txt.tpl index 075bc805..63274c43 100644 --- a/platformio/ide/tpls/clion/CMakeLists.txt.tpl +++ b/platformio/ide/tpls/clion/CMakeLists.txt.tpl @@ -51,18 +51,4 @@ add_custom_target( WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) -if(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/lib) - add_custom_target( - CODE_COMPLETION_PIOLIB - SOURCES lib - ) -endif() - -if(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/.piolibdeps) - add_custom_target( - CODE_COMPLETION_PIOLIBDEPS - SOURCES .piolibdeps - ) -endif() - add_executable(${PROJECT_NAME} ${SRC_LIST}) diff --git a/platformio/ide/tpls/clion/CMakeListsPrivate.txt.tpl b/platformio/ide/tpls/clion/CMakeListsPrivate.txt.tpl index 6efdb036..3c4bed47 100644 --- a/platformio/ide/tpls/clion/CMakeListsPrivate.txt.tpl +++ b/platformio/ide/tpls/clion/CMakeListsPrivate.txt.tpl @@ -24,4 +24,4 @@ include_directories("{{include.replace("\\", "/")}}") % end % end -FILE(GLOB_RECURSE SRC_LIST "{{project_src_dir.replace("\\", "/")}}/*.*") +FILE(GLOB_RECURSE SRC_LIST "{{project_src_dir.replace("\\", "/")}}/*.*" "{{project_lib_dir.replace("\\", "/")}}/*.*" "{{project_libdeps_dir.replace("\\", "/")}}/*.*") diff --git a/platformio/ide/tpls/qtcreator/platformio.pro.tpl b/platformio/ide/tpls/qtcreator/platformio.pro.tpl index 1ef5f8eb..19abc468 100644 --- a/platformio/ide/tpls/qtcreator/platformio.pro.tpl +++ b/platformio/ide/tpls/qtcreator/platformio.pro.tpl @@ -14,7 +14,8 @@ INCLUDEPATH += "{{include}}" % end % for define in defines: -DEFINES += {{!define}} +% tokens = define.split("##", 1) +DEFINES += "{{tokens[0].strip()}}" % end OTHER_FILES += platformio.ini diff --git a/platformio/ide/tpls/visualstudio/platformio.vcxproj.filters.tpl b/platformio/ide/tpls/visualstudio/platformio.vcxproj.filters.tpl index d66bb4be..b29cb31f 100644 --- a/platformio/ide/tpls/visualstudio/platformio.vcxproj.filters.tpl +++ b/platformio/ide/tpls/visualstudio/platformio.vcxproj.filters.tpl @@ -15,7 +15,7 @@ % for file in src_files: - % if any([file.endswith(".%s" % e) for e in ("h", "hh", "hpp", "inc")]): + % if any(file.endswith(".%s" % e) for e in ("h", "hh", "hpp", "inc")): Header Files diff --git a/platformio/ide/tpls/visualstudio/platformio.vcxproj.tpl b/platformio/ide/tpls/visualstudio/platformio.vcxproj.tpl index b27a7ab2..82a011ad 100644 --- a/platformio/ide/tpls/visualstudio/platformio.vcxproj.tpl +++ b/platformio/ide/tpls/visualstudio/platformio.vcxproj.tpl @@ -60,7 +60,7 @@ % for file in src_files: - % if any([file.endswith(".%s" % e) for e in ("h", "hh", "hpp", "inc")]): + % if any(file.endswith(".%s" % e) for e in ("h", "hh", "hpp", "inc")): Header Files diff --git a/platformio/ide/tpls/vscode/.gitignore.tpl b/platformio/ide/tpls/vscode/.gitignore.tpl index f92113ad..6a010304 100644 --- a/platformio/ide/tpls/vscode/.gitignore.tpl +++ b/platformio/ide/tpls/vscode/.gitignore.tpl @@ -1,4 +1,5 @@ .pioenvs .piolibdeps +.vscode/.browse.c_cpp.db* .vscode/c_cpp_properties.json .vscode/launch.json diff --git a/platformio/ide/tpls/vscode/.vscode/c_cpp_properties.json.tpl b/platformio/ide/tpls/vscode/.vscode/c_cpp_properties.json.tpl index ced616b7..d428393d 100644 --- a/platformio/ide/tpls/vscode/.vscode/c_cpp_properties.json.tpl +++ b/platformio/ide/tpls/vscode/.vscode/c_cpp_properties.json.tpl @@ -18,7 +18,7 @@ ], "browse": { "limitSymbolsToIncludedHeaders": true, - "databaseFilename": "", + "databaseFilename": "${workspaceRoot}/.vscode/.browse.c_cpp.db", "path": [ % for include in includes: "{{include.replace('\\\\', '/').replace('\\', '/').replace('"', '\\"')}}", diff --git a/platformio/ide/tpls/vscode/.vscode/launch.json.tpl b/platformio/ide/tpls/vscode/.vscode/launch.json.tpl index 409c1b98..788edc2a 100644 --- a/platformio/ide/tpls/vscode/.vscode/launch.json.tpl +++ b/platformio/ide/tpls/vscode/.vscode/launch.json.tpl @@ -9,7 +9,9 @@ "name": "PlatformIO Debugger", "target": "{{prog_path.replace('\\\\', '/').replace('\\', '/').replace('"', '\\"')}}", "gdbpath": "{{join(dirname(platformio_path), "piodebuggdb").replace('\\\\', '/').replace('\\', '/').replace('"', '\\"')}}", - "autorun": [ "source .pioinit" ] + "autorun": [ "source .pioinit" ], + "preLaunchTask": "PlatformIO: Pre-Debug", + "internalConsoleOptions": "openOnSessionStart" } ] } \ No newline at end of file diff --git a/platformio/maintenance.py b/platformio/maintenance.py index abbd7ca2..35f0e173 100644 --- a/platformio/maintenance.py +++ b/platformio/maintenance.py @@ -222,7 +222,7 @@ def after_upgrade(ctx): click.echo( "- %s PlatformIO IDE for IoT development > %s" % (click.style("try", fg="cyan"), - click.style("http://platformio.org/platformio-ide", fg="cyan"))) + click.style("https://platformio.org/platformio-ide", fg="cyan"))) if not util.is_ci(): click.echo("- %s us with PlatformIO Plus > %s" % (click.style("support", fg="cyan"), diff --git a/platformio/managers/core.py b/platformio/managers/core.py index 3d1e8721..9f3cc628 100644 --- a/platformio/managers/core.py +++ b/platformio/managers/core.py @@ -21,11 +21,11 @@ from platformio import __version__, exception, util from platformio.managers.package import PackageManager CORE_PACKAGES = { - "contrib-piohome": ">=0.6.1,<2", - "contrib-pysite": ">=0.1.2,<2", - "tool-pioplus": ">=0.13.3,<2", + "contrib-piohome": ">=0.7.1,<2", + "contrib-pysite": ">=0.1.5,<2", + "tool-pioplus": ">=0.14.5,<2", "tool-unity": "~1.20302.1", - "tool-scons": "~3.20501.2" + "tool-scons": "~2.20501.4" } PIOPLUS_AUTO_UPDATES_MAX = 100 diff --git a/platformio/managers/lib.py b/platformio/managers/lib.py index 09c5ef12..c1e5ab96 100644 --- a/platformio/managers/lib.py +++ b/platformio/managers/lib.py @@ -282,7 +282,7 @@ class LibraryManager(BasePkgManager): raise exception.LibNotFound(str(filters)) if not silent: click.echo("Found: %s" % click.style( - "http://platformio.org/lib/show/{id}/{name}".format( + "https://platformio.org/lib/show/{id}/{name}".format( **lib_info), fg="blue")) return int(lib_info['id']) @@ -365,7 +365,7 @@ class LibraryManager(BasePkgManager): for filters in self.normalize_dependencies(manifest['dependencies']): assert "name" in filters - if any([s in filters.get("version", "") for s in ("\\", "/")]): + if any(s in filters.get("version", "") for s in ("\\", "/")): self.install( "{name}={version}".format(**filters), silent=silent, @@ -420,6 +420,6 @@ def get_builtin_libs(storage_names=None): @util.memoized def is_builtin_lib(name): for storage in get_builtin_libs(): - if any([l.get("name") == name for l in storage['items']]): + if any(l.get("name") == name for l in storage['items']): return True return False diff --git a/platformio/managers/package.py b/platformio/managers/package.py index 0b1e0ad1..905b756a 100644 --- a/platformio/managers/package.py +++ b/platformio/managers/package.py @@ -553,7 +553,9 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin): hg_conditions = [ # Handle Developer Mbed URL # (https://developer.mbed.org/users/user/code/package/) - text.startswith("https://developer.mbed.org") + # (https://os.mbed.com/users/user/code/package/) + text.startswith("https://developer.mbed.org"), + text.startswith("https://os.mbed.com") ] if any(git_conditions): url = "git+" + text diff --git a/platformio/managers/platform.py b/platformio/managers/platform.py index b3090705..f147b762 100644 --- a/platformio/managers/platform.py +++ b/platformio/managers/platform.py @@ -427,10 +427,10 @@ class PlatformRunMixin(object): """.format(filename=filename, filename_styled=click.style(filename, fg="cyan"), link=click.style( - "http://platformio.org/lib/search?query=header:%s" % quote( + "https://platformio.org/lib/search?query=header:%s" % quote( filename, safe=""), fg="blue"), - dots="*" * (55 + len(filename))) + dots="*" * (56 + len(filename))) click.echo(banner, err=True) @staticmethod @@ -563,9 +563,9 @@ class PlatformBase( # pylint: disable=too-many-public-methods if not isdir(boards_dir): continue manifest_path = join(boards_dir, "%s.json" % id_) - if not isfile(manifest_path): - continue - _append_board(id_, manifest_path) + if isfile(manifest_path): + _append_board(id_, manifest_path) + break if id_ not in self._BOARDS_CACHE: raise exception.UnknownBoard(id_) return self._BOARDS_CACHE[id_] if id_ else self._BOARDS_CACHE @@ -684,9 +684,11 @@ class PlatformBoardConfig(object): "mcu": self._manifest.get("build", {}).get("mcu", "").upper(), "fcpu": - int( - re.sub(r"[^\d]+", "", - self._manifest.get("build", {}).get("f_cpu", "0L"))), + int("".join([ + c for c in str( + self._manifest.get("build", {}).get("f_cpu", "0L")) + if c.isdigit() + ])), "ram": self._manifest.get("upload", {}).get("maximum_ram_size", 0), "rom": @@ -713,3 +715,33 @@ class PlatformBoardConfig(object): if key in ("default", "onboard"): tools[name][key] = value return {"tools": tools} + + def get_debug_tool_name(self, custom=None): + debug_tools = self._manifest.get("debug", {}).get("tools") + tool_name = custom + if tool_name == "custom": + return tool_name + if not debug_tools: + raise exception.DebugSupportError(self._manifest['name']) + if tool_name: + if tool_name in debug_tools: + return tool_name + raise exception.DebugInvalidOptions( + "Unknown debug tool `%s`. Please use one of `%s` or `custom`" % + (tool_name, ", ".join(sorted(debug_tools.keys())))) + + # automatically select best tool + data = {"default": [], "onboard": [], "external": []} + for key, value in debug_tools.items(): + if value.get("default"): + data['default'].append(key) + elif value.get("onboard"): + data['onboard'].append(key) + data['external'].append(key) + + for key, value in data.items(): + if not value: + continue + return sorted(value)[0] + + assert any(item for item in data) diff --git a/platformio/util.py b/platformio/util.py index 53c23918..459b85e2 100644 --- a/platformio/util.py +++ b/platformio/util.py @@ -253,6 +253,11 @@ def get_home_dir(): return home_dir +def get_cache_dir(): + return get_project_optional_dir("cache_dir", join(get_home_dir(), + ".cache")) + + def get_source_dir(): curpath = abspath(__file__) if not isfile(curpath): @@ -431,7 +436,7 @@ def get_serial_ports(filter_hwid=False): for p, d, h in comports(): if not p: continue - if platform.system() == "Windows": + if "windows" in get_systype(): try: d = unicode(d, errors="ignore") except TypeError: @@ -443,7 +448,7 @@ def get_serial_ports(filter_hwid=False): return result # fix for PySerial - if not result and platform.system() == "Darwin": + if not result and "darwin" in get_systype(): for p in glob("/dev/tty.*"): result.append({"port": p, "description": "n/a", "hwid": "n/a"}) return result @@ -455,7 +460,7 @@ get_serialports = get_serial_ports def get_logical_devices(): items = [] - if platform.system() == "Windows": + if "windows" in get_systype(): try: result = exec_command( ["wmic", "logicaldisk", "get", "name,VolumeName"]).get( @@ -743,6 +748,23 @@ def parse_date(datestr): return time.strptime(datestr) +def format_filesize(filesize): + base = 1024 + unit = 0 + suffix = "B" + filesize = float(filesize) + if filesize < base: + return "%d%s" % (filesize, suffix) + for i, suffix in enumerate("KMGTPEZY"): + unit = base**(i + 2) + if filesize >= unit: + continue + if filesize % (base**(i + 1)): + return "%.2f%sB" % ((base * filesize / unit), suffix) + break + return "%d%sB" % ((base * filesize / unit), suffix) + + def rmtree_(path): def _onerror(_, name, __): diff --git a/scripts/98-openocd-udev.rules b/scripts/98-openocd-udev.rules deleted file mode 100644 index c6ff3083..00000000 --- a/scripts/98-openocd-udev.rules +++ /dev/null @@ -1,163 +0,0 @@ -# UDEV Rules for debug adapters/boards supported by OpenOCD - -# -# INSTALLATION -# - -# -# The latest version of this file may be found at: -# https://github.com/platformio/platformio-core/blob/develop/scripts/98-openocd-udev.rules -# -# This file must be placed at: -# /etc/udev/rules.d/98-openocd-udev.rules (preferred location) -# or -# /lib/udev/rules.d/98-openocd-udev.rules (req'd on some broken systems) -# -# To install, type this command in a terminal: -# sudo cp 98-openocd-udev.rules /etc/udev/rules.d/98-openocd-udev.rules -# -# Restart "udev" management tool: -# sudo service udev restart -# or -# sudo udevadm control --reload-rules -# sudo udevadm trigger -# -# Ubuntu/Debian users may need to add own “username” to the “dialout” group if -# they are not “root”, doing this issuing a -# sudo usermod -a -G dialout $USER -# sudo usermod -a -G plugdev $USER -# -# After this file is installed, physically unplug and reconnect your adapter/board. - -ACTION!="add|change", GOTO="openocd_rules_end" -SUBSYSTEM!="usb|tty|hidraw", GOTO="openocd_rules_end" - -# Please keep this list sorted by VID:PID - -# opendous and estick -ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="204f", MODE="660", GROUP="plugdev", TAG+="uaccess" - -# Original FT232/FT245 VID:PID -ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", MODE="660", GROUP="plugdev", TAG+="uaccess" - -# Original FT2232 VID:PID -ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6010", MODE="660", GROUP="plugdev", TAG+="uaccess" - -# Original FT4232 VID:PID -ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6011", MODE="660", GROUP="plugdev", TAG+="uaccess" - -# Original FT232H VID:PID -ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6014", MODE="660", GROUP="plugdev", TAG+="uaccess" - -# DISTORTEC JTAG-lock-pick Tiny 2 -ATTRS{idVendor}=="0403", ATTRS{idProduct}=="8220", MODE="660", GROUP="plugdev", TAG+="uaccess" - -# TUMPA, TUMPA Lite -ATTRS{idVendor}=="0403", ATTRS{idProduct}=="8a98", MODE="660", GROUP="plugdev", TAG+="uaccess" -ATTRS{idVendor}=="0403", ATTRS{idProduct}=="8a99", MODE="660", GROUP="plugdev", TAG+="uaccess" - -# XDS100v2 -ATTRS{idVendor}=="0403", ATTRS{idProduct}=="a6d0", MODE="660", GROUP="plugdev", TAG+="uaccess" - -# Xverve Signalyzer Tool (DT-USB-ST), Signalyzer LITE (DT-USB-SLITE) -ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bca0", MODE="660", GROUP="plugdev", TAG+="uaccess" -ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bca1", MODE="660", GROUP="plugdev", TAG+="uaccess" - -# TI/Luminary Stellaris Evaluation Board FTDI (several) -ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bcd9", MODE="660", GROUP="plugdev", TAG+="uaccess" - -# TI/Luminary Stellaris In-Circuit Debug Interface FTDI (ICDI) Board -ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bcda", MODE="660", GROUP="plugdev", TAG+="uaccess" - -# egnite Turtelizer 2 -ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bdc8", MODE="660", GROUP="plugdev", TAG+="uaccess" - -# Section5 ICEbear -ATTRS{idVendor}=="0403", ATTRS{idProduct}=="c140", MODE="660", GROUP="plugdev", TAG+="uaccess" -ATTRS{idVendor}=="0403", ATTRS{idProduct}=="c141", MODE="660", GROUP="plugdev", TAG+="uaccess" - -# Amontec JTAGkey and JTAGkey-tiny -ATTRS{idVendor}=="0403", ATTRS{idProduct}=="cff8", MODE="660", GROUP="plugdev", TAG+="uaccess" - -# TI ICDI -ATTRS{idVendor}=="0451", ATTRS{idProduct}=="c32a", MODE="660", GROUP="plugdev", TAG+="uaccess" - -# STLink v1 -ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3744", MODE="660", GROUP="plugdev", TAG+="uaccess" - -# STLink v2 -ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3748", MODE="660", GROUP="plugdev", TAG+="uaccess" - -# STLink v2-1 -ATTRS{idVendor}=="0483", ATTRS{idProduct}=="374b", MODE="660", GROUP="plugdev", TAG+="uaccess" - -# Hilscher NXHX Boards -ATTRS{idVendor}=="0640", ATTRS{idProduct}=="0028", MODE="660", GROUP="plugdev", TAG+="uaccess" - -# Hitex STR9-comStick -ATTRS{idVendor}=="0640", ATTRS{idProduct}=="002c", MODE="660", GROUP="plugdev", TAG+="uaccess" - -# Hitex STM32-PerformanceStick -ATTRS{idVendor}=="0640", ATTRS{idProduct}=="002d", MODE="660", GROUP="plugdev", TAG+="uaccess" - -# Altera USB Blaster -ATTRS{idVendor}=="09fb", ATTRS{idProduct}=="6001", MODE="660", GROUP="plugdev", TAG+="uaccess" - -# Amontec JTAGkey-HiSpeed -ATTRS{idVendor}=="0fbb", ATTRS{idProduct}=="1000", MODE="660", GROUP="plugdev", TAG+="uaccess" - -# SEGGER J-Link -ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0101", MODE="660", GROUP="plugdev", TAG+="uaccess" -ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0102", MODE="660", GROUP="plugdev", TAG+="uaccess" -ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0103", MODE="660", GROUP="plugdev", TAG+="uaccess" -ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0104", MODE="660", GROUP="plugdev", TAG+="uaccess" -ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0105", MODE="660", GROUP="plugdev", TAG+="uaccess" -ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0107", MODE="660", GROUP="plugdev", TAG+="uaccess" -ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0108", MODE="660", GROUP="plugdev", TAG+="uaccess" -ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1010", MODE="660", GROUP="plugdev", TAG+="uaccess" -ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1011", MODE="660", GROUP="plugdev", TAG+="uaccess" -ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1012", MODE="660", GROUP="plugdev", TAG+="uaccess" -ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1013", MODE="660", GROUP="plugdev", TAG+="uaccess" -ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1014", MODE="660", GROUP="plugdev", TAG+="uaccess" -ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1015", MODE="660", GROUP="plugdev", TAG+="uaccess" -ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1016", MODE="660", GROUP="plugdev", TAG+="uaccess" -ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1017", MODE="660", GROUP="plugdev", TAG+="uaccess" -ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1018", MODE="660", GROUP="plugdev", TAG+="uaccess" - -# Raisonance RLink -ATTRS{idVendor}=="138e", ATTRS{idProduct}=="9000", MODE="660", GROUP="plugdev", TAG+="uaccess" - -# Debug Board for Neo1973 -ATTRS{idVendor}=="1457", ATTRS{idProduct}=="5118", MODE="660", GROUP="plugdev", TAG+="uaccess" - -# Olimex ARM-USB-OCD -ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="0003", MODE="660", GROUP="plugdev", TAG+="uaccess" - -# Olimex ARM-USB-OCD-TINY -ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="0004", MODE="660", GROUP="plugdev", TAG+="uaccess" - -# Olimex ARM-JTAG-EW -ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="001e", MODE="660", GROUP="plugdev", TAG+="uaccess" - -# Olimex ARM-USB-OCD-TINY-H -ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="002a", MODE="660", GROUP="plugdev", TAG+="uaccess" - -# Olimex ARM-USB-OCD-H -ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="002b", MODE="660", GROUP="plugdev", TAG+="uaccess" - -# USBprog with OpenOCD firmware -ATTRS{idVendor}=="1781", ATTRS{idProduct}=="0c63", MODE="660", GROUP="plugdev", TAG+="uaccess" - -# TI/Luminary Stellaris In-Circuit Debug Interface (ICDI) Board -ATTRS{idVendor}=="1cbe", ATTRS{idProduct}=="00fd", MODE="660", GROUP="plugdev", TAG+="uaccess" - -# Marvell Sheevaplug -ATTRS{idVendor}=="9e88", ATTRS{idProduct}=="9e8f", MODE="660", GROUP="plugdev", TAG+="uaccess" - -# Keil Software, Inc. ULink -ATTRS{idVendor}=="c251", ATTRS{idProduct}=="2710", MODE="660", GROUP="plugdev", TAG+="uaccess" - -# CMSIS-DAP compatible adapters -ATTRS{product}=="*CMSIS-DAP*", MODE="660", GROUP="plugdev", TAG+="uaccess" - -LABEL="openocd_rules_end" diff --git a/scripts/99-platformio-udev.rules b/scripts/99-platformio-udev.rules index 5703cd26..6daaf922 100644 --- a/scripts/99-platformio-udev.rules +++ b/scripts/99-platformio-udev.rules @@ -12,35 +12,17 @@ # See the License for the specific language governing permissions and # limitations under the License. +##################################################################################### # # INSTALLATION # +# Please visit > http://docs.platformio.org/en/latest/faq.html#platformio-udev-rules +# +##################################################################################### -# UDEV Rules for PlatformIO supported boards, http://platformio.org/boards # -# The latest version of this file may be found at: -# https://github.com/platformio/platformio-core/blob/develop/scripts/99-platformio-udev.rules +# Boards # -# This file must be placed at: -# /etc/udev/rules.d/99-platformio-udev.rules (preferred location) -# or -# /lib/udev/rules.d/99-platformio-udev.rules (req'd on some broken systems) -# -# To install, type this command in a terminal: -# sudo cp 99-platformio-udev.rules /etc/udev/rules.d/99-platformio-udev.rules -# -# Restart "udev" management tool: -# sudo service udev restart -# or -# sudo udevadm control --reload-rules -# sudo udevadm trigger -# -# Ubuntu/Debian users may need to add own “username” to the “dialout” group if -# they are not “root”, doing this issuing a -# sudo usermod -a -G dialout $USER -# sudo usermod -a -G plugdev $USER -# -# After this file is installed, physically unplug and reconnect your board. # CP210X USB UART SUBSYSTEMS=="usb", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", MODE:="0666" @@ -89,9 +71,137 @@ SUBSYSTEMS=="usb", ATTRS{idVendor}=="1cbe", ATTRS{idProduct}=="00fd", MODE="0666 #TI MSP430 Launchpad SUBSYSTEMS=="usb", ATTRS{idVendor}=="0451", ATTRS{idProduct}=="f432", MODE="0666" -# CMSIS-DAP compatible adapters -ATTRS{product}=="*CMSIS-DAP*", MODE="664", GROUP="plugdev" + +# +# Debuggers +# # Black Magic Probe SUBSYSTEM=="tty", ATTRS{interface}=="Black Magic GDB Server" SUBSYSTEM=="tty", ATTRS{interface}=="Black Magic UART Port" + +# opendous and estick +ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="204f", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Original FT232/FT245 VID:PID +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Original FT2232 VID:PID +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6010", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Original FT4232 VID:PID +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6011", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Original FT232H VID:PID +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6014", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# DISTORTEC JTAG-lock-pick Tiny 2 +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="8220", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# TUMPA, TUMPA Lite +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="8a98", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="8a99", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# XDS100v2 +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="a6d0", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Xverve Signalyzer Tool (DT-USB-ST), Signalyzer LITE (DT-USB-SLITE) +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bca0", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bca1", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# TI/Luminary Stellaris Evaluation Board FTDI (several) +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bcd9", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# TI/Luminary Stellaris In-Circuit Debug Interface FTDI (ICDI) Board +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bcda", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# egnite Turtelizer 2 +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bdc8", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Section5 ICEbear +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="c140", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="c141", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Amontec JTAGkey and JTAGkey-tiny +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="cff8", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# TI ICDI +ATTRS{idVendor}=="0451", ATTRS{idProduct}=="c32a", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# STLink v1 +ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3744", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# STLink v2 +ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3748", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# STLink v2-1 +ATTRS{idVendor}=="0483", ATTRS{idProduct}=="374b", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Hilscher NXHX Boards +ATTRS{idVendor}=="0640", ATTRS{idProduct}=="0028", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Hitex STR9-comStick +ATTRS{idVendor}=="0640", ATTRS{idProduct}=="002c", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Hitex STM32-PerformanceStick +ATTRS{idVendor}=="0640", ATTRS{idProduct}=="002d", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Altera USB Blaster +ATTRS{idVendor}=="09fb", ATTRS{idProduct}=="6001", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Amontec JTAGkey-HiSpeed +ATTRS{idVendor}=="0fbb", ATTRS{idProduct}=="1000", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# SEGGER J-Link +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0101", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0102", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0103", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0104", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0105", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0107", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0108", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1010", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1011", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1012", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1013", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1014", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1015", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1016", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1017", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1018", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Raisonance RLink +ATTRS{idVendor}=="138e", ATTRS{idProduct}=="9000", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Debug Board for Neo1973 +ATTRS{idVendor}=="1457", ATTRS{idProduct}=="5118", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Olimex ARM-USB-OCD +ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="0003", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Olimex ARM-USB-OCD-TINY +ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="0004", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Olimex ARM-JTAG-EW +ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="001e", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Olimex ARM-USB-OCD-TINY-H +ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="002a", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Olimex ARM-USB-OCD-H +ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="002b", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# USBprog with OpenOCD firmware +ATTRS{idVendor}=="1781", ATTRS{idProduct}=="0c63", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# TI/Luminary Stellaris In-Circuit Debug Interface (ICDI) Board +ATTRS{idVendor}=="1cbe", ATTRS{idProduct}=="00fd", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Marvell Sheevaplug +ATTRS{idVendor}=="9e88", ATTRS{idProduct}=="9e8f", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Keil Software, Inc. ULink +ATTRS{idVendor}=="c251", ATTRS{idProduct}=="2710", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# CMSIS-DAP compatible adapters +ATTRS{product}=="*CMSIS-DAP*", MODE="660", GROUP="plugdev", TAG+="uaccess" diff --git a/scripts/docspregen.py b/scripts/docspregen.py index 585b9ea2..9d1c2371 100644 --- a/scripts/docspregen.py +++ b/scripts/docspregen.py @@ -12,8 +12,9 @@ # See the License for the specific language governing permissions and # limitations under the License. -from math import ceil -from os.path import dirname, isfile, join, realpath +import os +import urlparse +from os.path import dirname, isdir, isfile, join, realpath from sys import exit as sys_exit from sys import path @@ -36,39 +37,48 @@ def is_compat_platform_and_framework(platform, framework): return False -def generate_boards(boards, extend_debug=False): +def campaign_url(url, source="platformio", medium="docs"): + data = urlparse.urlparse(url) + query = data.query + if query: + query += "&" + query += "utm_source=%s&utm_medium=%s" % (source, medium) + return urlparse.urlunparse( + urlparse.ParseResult(data.scheme, data.netloc, data.path, data.params, + query, data.fragment)) - def _round_memory_size(size): - if size == 1: - return 1 - - size = ceil(size) - for b in (64, 32, 16, 8, 4, 2, 1): - if b < size: - return int(ceil(size / b) * b) - assert NotImplemented() +def generate_boards(boards, extend_debug=False, skip_columns=None): + columns = [ + ("ID", "``{id}``"), + ("Name", "`{name} <{url}>`_"), + ("Platform", ":ref:`{platform_title} `"), + ("Debug", "{debug}"), + ("MCU", "{mcu}"), + ("Frequency", "{f_cpu:d}MHz"), + ("Flash", "{rom}"), + ("RAM", "{ram}"), + ] platforms = {m['name']: m['title'] for m in PLATFORM_MANIFESTS} - lines = [] lines.append(""" .. list-table:: :header-rows: 1 +""") - * - ID - - Name - - Platform - - Debug - - Microcontroller - - Frequency - - Flash - - RAM""") + # add header + for (name, template) in columns: + if skip_columns and name in skip_columns: + continue + prefix = " * - " if name == "ID" else " - " + lines.append(prefix + name) for data in sorted(boards, key=lambda item: item['id']): - debug = [":ref:`Yes `" if data['debug'] else ""] + debug = [":ref:`Yes `" if data['debug'] else "No"] if extend_debug and data['debug']: - debug = [] + debug_onboard = [] + debug_external = [] for name, options in data['debug']['tools'].items(): attrs = [] if options.get("default"): @@ -77,32 +87,81 @@ def generate_boards(boards, extend_debug=False): attrs.append("on-board") tool = ":ref:`debugging_tool_%s`" % name if attrs: - debug.append("%s (%s)" % (tool, ", ".join(attrs))) + tool = "%s (%s)" % (tool, ", ".join(attrs)) + if options.get("onboard"): + debug_onboard.append(tool) else: - debug.append(tool) + debug_external.append(tool) + debug = sorted(debug_onboard) + sorted(debug_external) - board_ram = float(data['ram']) / 1024 - lines.append(""" - * - ``{id}`` - - `{name} <{url}>`_ - - :ref:`{platform_title} ` - - {debug} - - {mcu} - - {f_cpu:d} MHz - - {rom} Kb - - {ram} Kb""".format( + variables = dict( id=data['id'], name=data['name'], platform=data['platform'], platform_title=platforms[data['platform']], debug=", ".join(debug), - url=data['url'], + url=campaign_url(data['url']), mcu=data['mcu'].upper(), f_cpu=int(data['fcpu']) / 1000000, - ram=int(board_ram) if board_ram % 1 == 0 else board_ram, - rom=_round_memory_size(data['rom'] / 1024))) + ram=util.format_filesize(data['ram']), + rom=util.format_filesize(data['rom'])) - return "\n".join(lines + [""]) + for (name, template) in columns: + if skip_columns and name in skip_columns: + continue + prefix = " * - " if name == "ID" else " - " + lines.append(prefix + template.format(**variables)) + + if lines: + lines.append("") + + return lines + + +def generate_debug_boards(boards, skip_columns=None): + lines = [] + onboard_debug = [ + b for b in boards if b['debug'] and any( + t.get("onboard") for (_, t) in b['debug']['tools'].items()) + ] + external_debug = [ + b for b in boards if b['debug'] and b not in onboard_debug + ] + if onboard_debug or external_debug: + lines.append(""" +Debugging +--------- + +:ref:`piodebug` - "1-click" solution for debugging with a zero configuration. + +Supported debugging tools are listed in "Debug" column. For more detailed +information, please scroll table by horizontal. +You can switch between debugging :ref:`debugging_tools` using +:ref:`projectconf_debug_tool` options. +""") + if onboard_debug: + lines.append(""" +On-Board tools +~~~~~~~~~~~~~~ + +Boards listed below have on-board debugging tools and **ARE READY** for debugging! +You do not need to use/buy external debugger. +""") + lines.extend( + generate_boards( + onboard_debug, extend_debug=True, skip_columns=skip_columns)) + if external_debug: + lines.append(""" +External tools +~~~~~~~~~~~~~~ + +Boards listed below are compatible with :ref:`piodebug` but depend on external +debugging tools. See "Debug" column for compatible debugging tools. +""") + lines.extend( + generate_boards( + external_debug, extend_debug=True, skip_columns=skip_columns)) + return lines def generate_packages(platform, packagenames, is_embedded): @@ -124,7 +183,7 @@ Packages * - `{name} <{url}>`__ - {description}""".format( name=name, - url=API_PACKAGES[name]['url'], + url=campaign_url(API_PACKAGES[name]['url']), description=API_PACKAGES[name]['description'])) if is_embedded: @@ -132,8 +191,7 @@ Packages .. warning:: **Linux Users**: - * Install "udev" rules file `99-platformio-udev.rules `_ - (an instruction is located inside a file). + * Install "udev" rules :ref:`faq_udev_rules` * Raspberry Pi users, please read this article `Enable serial port on Raspberry Pi `__. """) @@ -160,8 +218,13 @@ Packages return "\n".join(lines) -def generate_platform(name): +def generate_platform(name, has_extra=False): print "Processing platform: %s" % name + + compatible_boards = [ + board for board in BOARDS if name in board['platform'] + ] + lines = [] lines.append( @@ -188,16 +251,79 @@ def generate_platform(name): lines.append(p.description) lines.append(""" For more detailed information please visit `vendor site <%s>`_.""" % - p.vendor_url) + campaign_url(p.vendor_url)) lines.append(""" .. contents:: Contents - :local:""") + :local: + :depth: 1 +""") + + # + # Extra + # + if has_extra: + lines.append(".. include:: %s_extra.rst" % p.name) + + # + # Examples + # + lines.append(""" +Examples +-------- + +Examples are listed from `%s development platform repository <%s>`_: +""" % (p.title, + campaign_url( + "https://github.com/platformio/platform-%s/tree/develop/examples" % + p.name))) + examples_dir = join(p.get_dir(), "examples") + if isdir(examples_dir): + for eitem in os.listdir(examples_dir): + if not isdir(join(examples_dir, eitem)): + continue + url = ("https://github.com/platformio/platform-%s" + "/tree/develop/examples/%s" % (p.name, eitem)) + lines.append("* `%s <%s>`_" % (eitem, campaign_url(url))) + + # + # Debugging + # + if compatible_boards: + lines.extend( + generate_debug_boards( + compatible_boards, skip_columns=["Platform"])) + + # + # Development version of dev/platform + # + lines.append(""" +Stable and upstream versions +---------------------------- + +You can switch between `stable releases `__ +of {title} development platform and the latest upstream version using +:ref:`projectconf_env_platform` option as described below: + +.. code-block:: ini + + ; Custom stable version + [env:stable] + platform ={name}@x.y.z + board = ... + ... + + ; The latest upstream/development version + [env:upstream] + platform = https://github.com/platformio/platform-{name}.git + board = ... + ... +""".format(name=p.name, title=p.title)) # # Packages # - _packages_content = generate_packages(name, - p.packages.keys(), p.is_embedded()) + _packages_content = generate_packages(name, p.packages.keys(), + p.is_embedded()) if _packages_content: lines.append(_packages_content) @@ -226,31 +352,28 @@ Frameworks # # Boards # - vendors = {} - for board in BOARDS: - vendor = board['vendor'] - if name in board['platform']: - if vendor in vendors: - vendors[vendor].append(board) - else: - vendors[vendor] = [board] + if compatible_boards: + vendors = {} + for board in compatible_boards: + if board['vendor'] not in vendors: + vendors[board['vendor']] = [] + vendors[board['vendor']].append(board) - if vendors: lines.append(""" Boards ------ .. note:: * You can list pre-configured boards by :ref:`cmd_boards` command or - `PlatformIO Boards Explorer `_ + `PlatformIO Boards Explorer `_ * For more detailed ``board`` information please scroll tables below by horizontal. """) - for vendor, boards in sorted(vendors.iteritems()): - lines.append(str(vendor)) - lines.append("~" * len(vendor)) - lines.append(generate_boards(boards)) + for vendor, boards in sorted(vendors.items()): + lines.append(str(vendor)) + lines.append("~" * len(vendor)) + lines.extend(generate_boards(boards, skip_columns=["Platform"])) return "\n".join(lines) @@ -262,13 +385,24 @@ def update_platform_docs(): dirname(realpath(__file__)), "..", "docs", "platforms") rst_path = join(platforms_dir, "%s.rst" % name) with open(rst_path, "w") as f: - f.write(generate_platform(name)) - if isfile(join(platforms_dir, "%s_extra.rst" % name)): - f.write("\n.. include:: %s_extra.rst\n" % name) + f.write( + generate_platform(name, + isfile( + join(platforms_dir, + "%s_extra.rst" % name)))) -def generate_framework(type_, data): +def generate_framework(type_, data, has_extra=False): print "Processing framework: %s" % type_ + + compatible_platforms = [ + m for m in PLATFORM_MANIFESTS + if is_compat_platform_and_framework(m['name'], type_) + ] + compatible_boards = [ + board for board in BOARDS if type_ in board['frameworks'] + ] + lines = [] lines.append( @@ -294,13 +428,38 @@ def generate_framework(type_, data): lines.append(data['description']) lines.append(""" For more detailed information please visit `vendor site <%s>`_. -""" % data['url']) +""" % campaign_url(data['url'])) lines.append(""" .. contents:: Contents - :local:""") + :local: + :depth: 1""") - lines.append(""" + # Extra + if has_extra: + lines.append(".. include:: %s_extra.rst" % type_) + + # + # Debugging + # + if compatible_boards: + lines.extend(generate_debug_boards(compatible_boards)) + + if compatible_platforms: + # examples + lines.append(""" +Examples +-------- +""") + for manifest in compatible_platforms: + lines.append("* `%s for %s <%s>`_" % ( + data['title'], manifest['title'], + campaign_url( + "https://github.com/platformio/platform-%s/tree/develop/examples" + % manifest['name']))) + + # Platforms + lines.append(""" Platforms --------- .. list-table:: @@ -309,43 +468,35 @@ Platforms * - Name - Description""") - _found_platform = False - for manifest in PLATFORM_MANIFESTS: - if not is_compat_platform_and_framework(manifest['name'], type_): - continue - _found_platform = True - p = PlatformFactory.newPlatform(manifest['name']) - lines.append( - """ + for manifest in compatible_platforms: + p = PlatformFactory.newPlatform(manifest['name']) + lines.append(""" * - :ref:`platform_{type_}` - - {description}""" - .format(type_=manifest['name'], description=p.description)) - if not _found_platform: - del lines[-1] + - {description}""".format( + type_=manifest['name'], description=p.description)) - lines.append(""" + # + # Boards + # + if compatible_boards: + vendors = {} + for board in compatible_boards: + if board['vendor'] not in vendors: + vendors[board['vendor']] = [] + vendors[board['vendor']].append(board) + lines.append(""" Boards ------ .. note:: * You can list pre-configured boards by :ref:`cmd_boards` command or - `PlatformIO Boards Explorer `_ + `PlatformIO Boards Explorer `_ * For more detailed ``board`` information please scroll tables below by horizontal. """) - - vendors = {} - for data in BOARDS: - frameworks = data['frameworks'] or [] - vendor = data['vendor'] - if type_ in frameworks: - if vendor in vendors: - vendors[vendor].append(data) - else: - vendors[vendor] = [data] - for vendor, boards in sorted(vendors.iteritems()): - lines.append(str(vendor)) - lines.append("~" * len(vendor)) - lines.append(generate_boards(boards)) + for vendor, boards in sorted(vendors.items()): + lines.append(str(vendor)) + lines.append("~" * len(vendor)) + lines.extend(generate_boards(boards)) return "\n".join(lines) @@ -356,9 +507,11 @@ def update_framework_docs(): dirname(realpath(__file__)), "..", "docs", "frameworks") rst_path = join(frameworks_dir, "%s.rst" % name) with open(rst_path, "w") as f: - f.write(generate_framework(name, framework)) - if isfile(join(frameworks_dir, "%s_extra.rst" % name)): - f.write("\n.. include:: %s_extra.rst\n" % name) + f.write( + generate_framework(name, framework, + isfile( + join(frameworks_dir, + "%s_extra.rst" % name)))) def update_create_platform_doc(): @@ -424,7 +577,7 @@ popular embedded boards and IDE. .. note:: * You can list pre-configured boards by :ref:`cmd_boards` command or - `PlatformIO Boards Explorer `_ + `PlatformIO Boards Explorer `_ * For more detailed ``board`` information please scroll tables below by horizontal. """) @@ -444,7 +597,7 @@ popular embedded boards and IDE. for vendor, boards in sorted(vendors.iteritems()): lines.append(str(vendor)) lines.append("~" * len(vendor)) - lines.append(generate_boards(boards)) + lines.extend(generate_boards(boards)) emboards_rst = join( dirname(realpath(__file__)), "..", "docs", "platforms", @@ -484,11 +637,10 @@ Platforms if manifest['name'] not in platforms: continue p = PlatformFactory.newPlatform(manifest['name']) - lines.append( - """ + lines.append(""" * - :ref:`platform_{type_}` - - {description}""" - .format(type_=manifest['name'], description=p.description)) + - {description}""".format( + type_=manifest['name'], description=p.description)) # Frameworks lines.append(""" @@ -517,11 +669,11 @@ Boards for vendor, boards in sorted(vendors.iteritems()): lines.append(str(vendor)) lines.append("~" * len(vendor)) - lines.append(generate_boards(boards, extend_debug=True)) + lines.extend(generate_boards(boards, extend_debug=True)) with open( - join(util.get_source_dir(), "..", "docs", "plus", - "debugging.rst"), "r+") as fp: + join(util.get_source_dir(), "..", "docs", "plus", "debugging.rst"), + "r+") as fp: content = fp.read() fp.seek(0) fp.truncate() @@ -529,12 +681,66 @@ Boards "\n".join(lines)) +def update_examples_readme(): + examples_dir = join(util.get_source_dir(), "..", "examples") + + # Platforms + embedded = [] + desktop = [] + for manifest in PLATFORM_MANIFESTS: + p = PlatformFactory.newPlatform(manifest['name']) + url = campaign_url( + "http://docs.platformio.org/en/latest/platforms/%s.html#examples" % + p.name, + source="github", + medium="examples") + line = "* [%s](%s)" % (p.title, url) + if p.is_embedded(): + embedded.append(line) + else: + desktop.append(line) + + # Frameworks + frameworks = [] + for framework in API_FRAMEWORKS: + url = campaign_url( + "http://docs.platformio.org/en/latest/frameworks/%s.html#examples" + % framework['name'], + source="github", + medium="examples") + frameworks.append("* [%s](%s)" % (framework['title'], url)) + + with open(join(examples_dir, "README.md"), "w") as fp: + fp.write("""# PlatformIO Project Examples + +- [Development platforms](#development-platforms): + - [Embedded](#embedded) + - [Desktop](#desktop) +- [Frameworks](#frameworks) + +## Development platforms + +### Embedded + +%s + +### Desktop + +%s + +## Frameworks + +%s +""" % ("\n".join(embedded), "\n".join(desktop), "\n".join(frameworks))) + + def main(): update_create_platform_doc() update_platform_docs() update_framework_docs() update_embedded_boards() update_debugging() + update_examples_readme() if __name__ == "__main__": diff --git a/scripts/install_devplatforms.py b/scripts/install_devplatforms.py new file mode 100644 index 00000000..58d28bd1 --- /dev/null +++ b/scripts/install_devplatforms.py @@ -0,0 +1,32 @@ +# Copyright (c) 2014-present PlatformIO +# +# 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. + +import json +import subprocess +import sys + + +def main(): + platforms = json.loads( + subprocess.check_output( + ["platformio", "platform", "search", "--json-output"])) + for platform in platforms: + if platform['forDesktop']: + continue + subprocess.check_call( + ["platformio", "platform", "install", platform['repository']]) + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/tests/commands/test_ci.py b/tests/commands/test_ci.py index 2ab76544..ec4077ba 100644 --- a/tests/commands/test_ci.py +++ b/tests/commands/test_ci.py @@ -15,6 +15,7 @@ from os.path import join from platformio.commands.ci import cli as cmd_ci +from platformio.commands.lib import cli as cmd_lib def test_ci_empty(clirunner): @@ -25,27 +26,31 @@ def test_ci_empty(clirunner): def test_ci_boards(clirunner, validate_cliresult): result = clirunner.invoke(cmd_ci, [ - join("examples", "atmelavr", "arduino-internal-libs", "src", - "ChatServer.ino"), "-b", "uno", "-b", "leonardo" + join("examples", "wiring-blink", "src", "main.cpp"), "-b", "uno", "-b", + "leonardo" ]) validate_cliresult(result) def test_ci_project_conf(clirunner, validate_cliresult): - project_dir = join("examples", "atmelavr", "arduino-internal-libs") + project_dir = join("examples", "wiring-blink") result = clirunner.invoke(cmd_ci, [ - join(project_dir, "src", "ChatServer.ino"), "--project-conf", + join(project_dir, "src", "main.cpp"), "--project-conf", join(project_dir, "platformio.ini") ]) validate_cliresult(result) - assert all([s in result.output for s in ("ethernet", "leonardo", "yun")]) + assert "uno" in result.output -def test_ci_lib_and_board(clirunner, validate_cliresult): - example_dir = join("examples", "atmelavr", "arduino-external-libs") +def test_ci_lib_and_board(clirunner, tmpdir_factory, validate_cliresult): + storage_dir = str(tmpdir_factory.mktemp("lib")) + result = clirunner.invoke( + cmd_lib, ["--storage-dir", storage_dir, "install", "1@2.3.2"]) + validate_cliresult(result) + result = clirunner.invoke(cmd_ci, [ - join(example_dir, "lib", "OneWire", "examples", "DS2408_Switch", + join(storage_dir, "OneWire_ID1", "examples", "DS2408_Switch", "DS2408_Switch.pde"), "-l", - join(example_dir, "lib", "OneWire"), "-b", "uno" + join(storage_dir, "OneWire_ID1"), "-b", "uno" ]) validate_cliresult(result) diff --git a/tests/commands/test_lib.py b/tests/commands/test_lib.py index 8513d401..12debd8c 100644 --- a/tests/commands/test_lib.py +++ b/tests/commands/test_lib.py @@ -253,7 +253,7 @@ def test_lib_show(clirunner, validate_cliresult): validate_cliresult(result) assert all( [s in result.output for s in ("ArduinoJson", "Arduino", "Atmel AVR")]) - result = clirunner.invoke(cmd_lib, ["show", "OneWire"]) + result = clirunner.invoke(cmd_lib, ["show", "OneWire", "--json-output"]) validate_cliresult(result) assert "OneWire" in result.output @@ -270,7 +270,7 @@ def test_lib_stats(clirunner, validate_cliresult): validate_cliresult(result) assert all([ s in result.output - for s in ("UPDATED", "POPULAR", "http://platformio.org/lib/show") + for s in ("UPDATED", "POPULAR", "https://platformio.org/lib/show") ]) result = clirunner.invoke(cmd_lib, ["stats", "--json-output"]) diff --git a/tests/conftest.py b/tests/conftest.py index 5b8103c9..02d16069 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -24,8 +24,8 @@ from platformio import util def validate_cliresult(): def decorator(result): - assert result.exit_code == 0 - assert not result.exception + assert result.exit_code == 0, result.output + assert not result.exception, result.output return decorator diff --git a/tests/ino2cpp/basic/basic.ino b/tests/ino2cpp/basic/basic.ino index 88ac301c..0c5d7511 100644 --- a/tests/ino2cpp/basic/basic.ino +++ b/tests/ino2cpp/basic/basic.ino @@ -48,3 +48,5 @@ void myFunction(struct Item *item) { void fooCallback(){ } + +// юнікод diff --git a/tests/test_examples.py b/tests/test_examples.py index 4d2a1a52..20e9cb63 100644 --- a/tests/test_examples.py +++ b/tests/test_examples.py @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +import random from glob import glob from os import listdir, walk from os.path import dirname, getsize, isdir, isfile, join, normpath @@ -19,17 +20,32 @@ from os.path import dirname, getsize, isdir, isfile, join, normpath import pytest from platformio import util +from platformio.managers.platform import PlatformFactory, PlatformManager def pytest_generate_tests(metafunc): if "pioproject_dir" not in metafunc.fixturenames: return - example_dirs = normpath(join(dirname(__file__), "..", "examples")) - project_dirs = [] - for root, _, files in walk(example_dirs): - if "platformio.ini" not in files or ".skiptest" in files: + examples_dirs = [] + + # repo examples + examples_dirs.append(normpath(join(dirname(__file__), "..", "examples"))) + + # dev/platforms + for manifest in PlatformManager().get_installed(): + p = PlatformFactory.newPlatform(manifest['__pkg_dir']) + if not p.is_embedded(): continue - project_dirs.append(root) + examples_dir = join(p.get_dir(), "examples") + assert isdir(examples_dir) + examples_dirs.append(examples_dir) + + project_dirs = [] + for examples_dir in examples_dirs: + for root, _, files in walk(examples_dir): + if "platformio.ini" not in files or ".skiptest" in files: + continue + project_dirs.append(root) project_dirs.sort() metafunc.parametrize("pioproject_dir", project_dirs) @@ -41,7 +57,14 @@ def test_run(pioproject_dir): if isdir(build_dir): util.rmtree_(build_dir) - result = util.exec_command(["platformio", "--force", "run"]) + env_names = [] + for section in util.load_project_config().sections(): + if section.startswith("env:"): + env_names.append(section[4:]) + + result = util.exec_command( + ["platformio", "run", "-e", + random.choice(env_names)]) if result['returncode'] != 0: pytest.fail(result) diff --git a/tests/test_maintenance.py b/tests/test_maintenance.py index 667c1563..ec9d749a 100644 --- a/tests/test_maintenance.py +++ b/tests/test_maintenance.py @@ -44,9 +44,7 @@ def test_after_upgrade_2_to_3(clirunner, validate_cliresult, result = clirunner.invoke(cli_pio, ["settings", "get"]) validate_cliresult(result) - assert "upgraded to 3" - assert isolated_pio_home.join("platforms", "native", - "platform.json").check() + assert "upgraded to 3" in result.output # check PlatformIO 3.0 boards assert board_ids == set([p.basename[:-5] for p in boards.listdir()]) diff --git a/tests/test_managers.py b/tests/test_managers.py index 6fe2f273..ee2d5df1 100644 --- a/tests/test_managers.py +++ b/tests/test_managers.py @@ -82,6 +82,11 @@ def test_pkg_input_parser(): ("package", None, "hg+https://developer.mbed.org/users/user/code/package/") ], + [ + "https://os.mbed.com/users/user/code/package/", + ("package", None, + "hg+https://os.mbed.com/users/user/code/package/") + ], [ "https://github.com/user/package#v1.2.3", ("package", None, "git+https://github.com/user/package#v1.2.3") diff --git a/tox.ini b/tox.ini index f1196266..26327fd7 100644 --- a/tox.ini +++ b/tox.ini @@ -58,6 +58,9 @@ deps = pytest commands = {envpython} --version + {envpython} -c "print 'travis_fold:start:install_devplatforms'" + {envpython} scripts/install_devplatforms.py + {envpython} -c "print 'travis_fold:end:install_devplatforms'" py.test -v --basetemp="{envtmpdir}" tests [testenv:skipexamples]