def run(self, variables=None, targets=None, silent=False, verbose=False, jobs=2): timer_start = timer() if not variables: variables = { "pioenv": self.build.env, "project_config": self.project_config.path } if not targets: targets = [] try: options = self.project_config.items(env=self.build.env, as_dict=True) platform = options["platform"] logger.debug(f"Building {self.build.env} for {platform}") except KeyError: logger.error(f"Couldn't find platform for: {self.build.env}") self.build.state = State.FAILED return self.build try: factory = PlatformFactory.new(platform) except UnknownPlatform: self.platform_install(platform=platform, skip_default_package=True) factory = PlatformFactory.new(platform) log_combined = self.build.file_log.open("w") with redirect_stdout(log_combined), redirect_stderr(log_combined): self.build.state = State.BUILDING run = factory.run(variables, targets, silent, verbose, jobs) if run and run["returncode"] == 0: self.gather_files([open(self.firmware_filename, "rb")]) self.build.state = State.SUCCESS else: self.build.state = State.FAILED timer_end = timer() duration = float(timer_end - timer_start) self.build.duration = duration return self.build
def remove_unnecessary_platform_packages(dry_run=False): candidates = [] required = set() core_packages = get_installed_core_packages() for platform in PlatformPackageManager().get_installed(): p = PlatformFactory.new(platform) for pkg in p.get_installed_packages(with_optional=True): required.add(pkg) pm = ToolPackageManager() for pkg in pm.get_installed(): skip_conds = [ pkg.metadata.spec.url, os.path.isfile(os.path.join(pkg.path, ".piokeep")), pkg in required, pkg in core_packages, ] if not any(skip_conds): candidates.append(pkg) if dry_run: return candidates for pkg in candidates: pm.uninstall(pkg) return candidates
def cleanup_packages(self, names): self.memcache_reset() deppkgs = {} for platform in PlatformPackageManager().get_installed(): p = PlatformFactory.new(platform) for pkg in p.get_installed_packages(): if pkg.metadata.name not in deppkgs: deppkgs[pkg.metadata.name] = set() deppkgs[pkg.metadata.name].add(pkg.metadata.version) pm = ToolPackageManager() for pkg in pm.get_installed(): if pkg.metadata.name not in names: continue if ( pkg.metadata.name not in deppkgs or pkg.metadata.version not in deppkgs[pkg.metadata.name] ): try: pm.uninstall(pkg.metadata.spec) except UnknownPackageError: pass self.memcache_reset() return True
def PioPlatform(env): variables = env.GetProjectOptions(as_dict=True) if "framework" in variables: # support PIO Core 3.0 dev/platforms variables["pioframework"] = variables["framework"] p = PlatformFactory.new(os.path.dirname(env["PLATFORM_MANIFEST"])) p.configure_default_packages(variables, COMMAND_LINE_TARGETS) return p
def _get_installed_platform_data(platform, with_boards=True, expose_packages=True): p = PlatformFactory.new(platform) data = dict( name=p.name, title=p.title, description=p.description, version=p.version, homepage=p.homepage, url=p.homepage, repository=p.repository_url, license=p.license, forDesktop=not p.is_embedded(), frameworks=sorted(list(p.frameworks) if p.frameworks else []), packages=list(p.packages) if p.packages else [], ) # if dump to API # del data['version'] # return data # overwrite VCS version and add extra fields manifest = PlatformPackageManager().legacy_load_manifest( os.path.dirname(p.manifest_path)) assert manifest for key in manifest: if key == "version" or key.startswith("__"): data[key] = manifest[key] if with_boards: data["boards"] = [c.get_brief_data() for c in p.get_boards().values()] if not data["packages"] or not expose_packages: return data data["packages"] = [] installed_pkgs = { pkg.metadata.name: p.pm.load_manifest(pkg) for pkg in p.get_installed_packages() } for name, options in p.packages.items(): item = dict( name=name, type=p.get_package_type(name), requirements=options.get("version"), optional=options.get("optional") is True, ) if name in installed_pkgs: for key, value in installed_pkgs[name].items(): if key not in ("url", "version", "description"): continue item[key] = value if key == "version": item["originalVersion"] = get_original_version(value) data["packages"].append(item) return data
def get_installed_boards(self): boards = [] for pkg in self.get_installed(): p = PlatformFactory.new(pkg) for config in p.get_boards().values(): board = config.get_brief_data() if board not in boards: boards.append(board) return boards
def update_boards(): lines = [] lines.append(RST_COPYRIGHT) lines.append(".. _boards:") lines.append("") lines.append("Boards") lines.append("======") lines.append(""" Rapid Embedded Development, Continuous and IDE integration in a few steps with PlatformIO thanks to built-in project generator for the most popular embedded boards and IDE. .. note:: * You can list pre-configured boards by :ref:`cmd_boards` command or `PlatformIO Boards Explorer <https://platformio.org/boards>`_ * For more detailed ``board`` information please scroll tables below by horizontal. """) platforms = {} for data in BOARDS: platform = data["platform"] if platform in platforms: platforms[platform].append(data) else: platforms[platform] = [data] for platform, boards in sorted(platforms.items()): p = PlatformFactory.new(platform) lines.append(p.title) lines.append("-" * len(p.title)) lines.append(""" .. toctree:: :maxdepth: 1 """) for board in sorted(boards, key=lambda item: item["name"]): lines.append(" %s/%s" % (platform, board["id"])) lines.append("") emboards_rst = join(DOCS_ROOT_DIR, "boards", "index.rst") with open(emboards_rst, "w") as f: f.write("\n".join(lines)) # individual board page for data in BOARDS: # if data['id'] != "m5stack-core-esp32": # continue rst_path = join(DOCS_ROOT_DIR, "boards", data["platform"], "%s.rst" % data["id"]) if not isdir(dirname(rst_path)): os.makedirs(dirname(rst_path)) update_embedded_board(rst_path, data)
def update( # pylint: disable=arguments-differ, too-many-arguments self, from_spec, to_spec=None, only_check=False, silent=False, show_incompatible=True, only_packages=False, ): pkg = self.get_package(from_spec) if not pkg or not pkg.metadata: raise UnknownPackageError(from_spec) p = PlatformFactory.new(pkg) pkgs_before = [item.metadata.name for item in p.get_installed_packages()] new_pkg = None missed_pkgs = set() if not only_packages: new_pkg = super(PlatformPackageManager, self).update( from_spec, to_spec, only_check=only_check, silent=silent, show_incompatible=show_incompatible, ) p = PlatformFactory.new(new_pkg) missed_pkgs = set(pkgs_before) & set(p.packages) missed_pkgs -= set( item.metadata.name for item in p.get_installed_packages() ) p.update_packages(only_check) self.cleanup_packages(list(p.packages)) if missed_pkgs: p.install_packages( with_packages=list(missed_pkgs), skip_default_package=True ) return new_pkg or pkg
def uninstall(self, spec, silent=False, skip_dependencies=False): pkg = self.get_package(spec) if not pkg or not pkg.metadata: raise UnknownPackageError(spec) p = PlatformFactory.new(pkg) assert super(PlatformPackageManager, self).uninstall(pkg, silent=silent, skip_dependencies=True) if not skip_dependencies: p.uninstall_python_packages() p.on_uninstalled() return pkg
def process(self): if "platform" not in self.options: raise UndefinedEnvPlatformError(self.name) build_vars = self.get_build_variables() build_targets = list(self.get_build_targets()) # skip monitor target, we call it above if "monitor" in build_targets: build_targets.remove("monitor") try: p = PlatformFactory.new(self.options["platform"]) except UnknownPlatform: self.cmd_ctx.invoke( cmd_platform_install, platforms=[self.options["platform"]], skip_default_package=True, ) p = PlatformFactory.new(self.options["platform"]) result = p.run(build_vars, build_targets, self.silent, self.verbose, self.jobs) return result["returncode"] == 0
def platform_update( # pylint: disable=too-many-locals, too-many-arguments platforms, only_packages, only_check, dry_run, silent, json_output): pm = PlatformPackageManager() platforms = platforms or pm.get_installed() only_check = dry_run or only_check if only_check and json_output: result = [] for platform in platforms: spec = None pkg = None if isinstance(platform, PackageItem): pkg = platform else: spec = PackageSpec(platform) pkg = pm.get_package(spec) if not pkg: continue outdated = pm.outdated(pkg, spec) if (not outdated.is_outdated(allow_incompatible=True) and not PlatformFactory.new(pkg).are_outdated_packages()): continue data = _get_installed_platform_data(pkg, with_boards=False, expose_packages=False) if outdated.is_outdated(allow_incompatible=True): data["versionLatest"] = (str(outdated.latest) if outdated.latest else None) result.append(data) return click.echo(dump_json_to_unicode(result)) # cleanup cached board and platform lists cleanup_content_cache("http") for platform in platforms: click.echo("Platform %s" % click.style( platform.metadata.name if isinstance(platform, PackageItem) else platform, fg="cyan", )) click.echo("--------") pm.update(platform, only_packages=only_packages, only_check=only_check, silent=silent) click.echo() return True
def generate_platforms_contents(platforms): if not platforms: return [] lines = [] lines.append(""" Platforms --------- .. list-table:: :header-rows: 1 * - Name - Description""") for name in sorted(platforms): p = PlatformFactory.new(name) lines.append(""" * - :ref:`platform_{name}` - {description}""".format(name=p.name, description=p.description)) return lines
def get_builtin_libs(storage_names=None): # pylint: disable=import-outside-toplevel from platformio.package.manager.library import LibraryPackageManager items = [] storage_names = storage_names or [] pm = PlatformPackageManager() for pkg in pm.get_installed(): p = PlatformFactory.new(pkg) for storage in p.get_lib_storages(): if storage_names and storage["name"] not in storage_names: continue lm = LibraryPackageManager(storage["path"]) items.append({ "name": storage["name"], "path": storage["path"], "items": lm.legacy_get_installed(), }) return items
def pytest_generate_tests(metafunc): if "pioproject_dir" not in metafunc.fixturenames: return examples_dirs = [] # repo examples examples_dirs.append( os.path.normpath(os.path.join(os.path.dirname(__file__), "..", "examples")) ) # dev/platforms for pkg in PlatformPackageManager().get_installed(): p = PlatformFactory.new(pkg) examples_dir = os.path.join(p.get_dir(), "examples") if os.path.isdir(examples_dir): examples_dirs.append(examples_dir) project_dirs = [] for examples_dir in examples_dirs: candidates = {} for root, _, files in os.walk(examples_dir): if "platformio.ini" not in files or ".skiptest" in files: continue if "zephyr-" in root and PY2: continue group = os.path.basename(root) if "-" in group: group = group.split("-", 1)[0] if group not in candidates: candidates[group] = [] candidates[group].append(root) project_dirs.extend( [random.choice(examples) for examples in candidates.values() if examples] ) metafunc.parametrize("pioproject_dir", sorted(project_dirs))
def get_test_port(self): # if test port is specified manually or in config if self.options.get("test_port"): return self.options.get("test_port") if self.env_options.get("test_port"): return self.env_options.get("test_port") assert set(["platform", "board"]) & set(self.env_options.keys()) p = PlatformFactory.new(self.env_options["platform"]) board_hwids = p.board_config(self.env_options["board"]).get( "build.hwids", []) port = None elapsed = 0 while elapsed < 5 and not port: for item in util.get_serialports(): port = item["port"] for hwid in board_hwids: hwid_str = ("%s:%s" % (hwid[0], hwid[1])).replace("0x", "") if hwid_str in item["hwid"]: return port # check if port is already configured try: serial.Serial(port, timeout=self.SERIAL_TIMEOUT).close() except serial.SerialException: port = None if not port: sleep(0.25) elapsed += 0.25 if not port: raise exception.PlatformioException( "Please specify `test_port` for environment or use " "global `--test-port` option.") return port
def install( # pylint: disable=arguments-differ, too-many-arguments self, spec, with_packages=None, without_packages=None, skip_default_package=False, with_all_packages=False, silent=False, force=False, ): pkg = super(PlatformPackageManager, self).install(spec, silent=silent, force=force, skip_dependencies=True) try: p = PlatformFactory.new(pkg) p.ensure_engine_compatible() except IncompatiblePlatform as e: super(PlatformPackageManager, self).uninstall(pkg, silent=silent, skip_dependencies=True) raise e if with_all_packages: with_packages = list(p.packages) p.install_packages( with_packages, without_packages, skip_default_package, silent=silent, force=force, ) p.install_python_packages() p.on_installed() return pkg
def is_embedded_platform(name): if not name: return False return PlatformFactory.new(name).is_embedded()
def update_project_examples(): platform_readme_tpl = """ # {title}: development platform for [PlatformIO](https://platformio.org) {description} * [Home](https://platformio.org/platforms/{name}) (home page in PlatformIO Registry) * [Documentation](https://docs.platformio.org/page/platforms/{name}.html) (advanced usage, packages, boards, frameworks, etc.) # Examples {examples} """ framework_readme_tpl = """ # {title}: framework for [PlatformIO](https://platformio.org) {description} * [Home](https://platformio.org/frameworks/{name}) (home page in PlatformIO Registry) * [Documentation](https://docs.platformio.org/page/frameworks/{name}.html) # Examples {examples} """ project_examples_dir = join(fs.get_source_dir(), "..", "examples") framework_examples_md_lines = {} embedded = [] desktop = [] for manifest in PLATFORM_MANIFESTS: p = PlatformFactory.new(manifest["name"]) github_url = p.repository_url[:-4] # Platform README platform_examples_dir = join(p.get_dir(), "examples") examples_md_lines = [] if isdir(platform_examples_dir): for item in sorted(os.listdir(platform_examples_dir)): example_dir = join(platform_examples_dir, item) if not isdir(example_dir) or not os.listdir(example_dir): continue url = "%s/tree/master/examples/%s" % (github_url, item) examples_md_lines.append("* [%s](%s)" % (item, url)) readme_dir = join(project_examples_dir, "platforms", p.name) if not isdir(readme_dir): os.makedirs(readme_dir) with open(join(readme_dir, "README.md"), "w") as fp: fp.write( platform_readme_tpl.format( name=p.name, title=p.title, description=p.description, examples="\n".join(examples_md_lines), )) # Framework README for framework in API_FRAMEWORKS: if not is_compat_platform_and_framework(p.name, framework["name"]): continue if framework["name"] not in framework_examples_md_lines: framework_examples_md_lines[framework["name"]] = [] lines = [] lines.append("- [%s](%s)" % (p.title, github_url)) lines.extend(" %s" % l for l in examples_md_lines) lines.append("") framework_examples_md_lines[framework["name"]].extend(lines) # Root README line = "* [%s](%s)" % (p.title, "%s/tree/master/examples" % github_url) if p.is_embedded(): embedded.append(line) else: desktop.append(line) # Frameworks frameworks = [] for framework in API_FRAMEWORKS: if framework["name"] not in framework_examples_md_lines: continue readme_dir = join(project_examples_dir, "frameworks", framework["name"]) if not isdir(readme_dir): os.makedirs(readme_dir) with open(join(readme_dir, "README.md"), "w") as fp: fp.write( framework_readme_tpl.format( name=framework["name"], title=framework["title"], description=framework["description"], examples="\n".join( framework_examples_md_lines[framework["name"]]), )) url = campaign_url( "https://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(project_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 update_embedded_board(rst_path, board): platform = PlatformFactory.new(board["platform"]) board_config = platform.board_config(board["id"]) board_manifest_url = platform.repository_url assert board_manifest_url if board_manifest_url.endswith(".git"): board_manifest_url = board_manifest_url[:-4] board_manifest_url += "/blob/master/boards/%s.json" % board["id"] variables = dict( id=board["id"], name=board["name"], platform=board["platform"], platform_description=platform.description, url=campaign_url(board["url"]), mcu=board_config.get("build", {}).get("mcu", ""), mcu_upper=board["mcu"].upper(), f_cpu=board["fcpu"], f_cpu_mhz=int(int(board["fcpu"]) / 1000000), ram=fs.humanize_file_size(board["ram"]), rom=fs.humanize_file_size(board["rom"]), vendor=board["vendor"], board_manifest_url=board_manifest_url, upload_protocol=board_config.get("upload.protocol", ""), ) lines = [RST_COPYRIGHT] lines.append(".. _board_{platform}_{id}:".format(**variables)) lines.append("") lines.append(board["name"]) lines.append("=" * len(board["name"])) lines.append(""" .. contents:: Hardware -------- Platform :ref:`platform_{platform}`: {platform_description} .. list-table:: * - **Microcontroller** - {mcu_upper} * - **Frequency** - {f_cpu_mhz:d}MHz * - **Flash** - {rom} * - **RAM** - {ram} * - **Vendor** - `{vendor} <{url}>`__ """.format(**variables)) # # Configuration # lines.append(""" Configuration ------------- Please use ``{id}`` ID for :ref:`projectconf_env_board` option in :ref:`projectconf`: .. code-block:: ini [env:{id}] platform = {platform} board = {id} You can override default {name} settings per build environment using ``board_***`` option, where ``***`` is a JSON object path from board manifest `{id}.json <{board_manifest_url}>`_. For example, ``board_build.mcu``, ``board_build.f_cpu``, etc. .. code-block:: ini [env:{id}] platform = {platform} board = {id} ; change microcontroller board_build.mcu = {mcu} ; change MCU frequency board_build.f_cpu = {f_cpu}L """.format(**variables)) # # Uploading # upload_protocols = board_config.get("upload.protocols", []) if len(upload_protocols) > 1: lines.append(""" Uploading --------- %s supports the next uploading protocols: """ % board["name"]) for protocol in sorted(upload_protocols): lines.append("* ``%s``" % protocol) lines.append(""" Default protocol is ``%s``""" % variables["upload_protocol"]) lines.append(""" You can change upload protocol using :ref:`projectconf_upload_protocol` option: .. code-block:: ini [env:{id}] platform = {platform} board = {id} upload_protocol = {upload_protocol} """.format(**variables)) # # Debugging # lines.append("Debugging") lines.append("---------") if not board.get("debug"): lines.append( ":ref:`piodebug` currently does not support {name} board.".format( **variables)) else: default_debug_tool = board_config.get_debug_tool_name() has_onboard_debug = any( t.get("onboard") for (_, t) in board["debug"]["tools"].items()) lines.append(""" :ref:`piodebug` - "1-click" solution for debugging with a zero configuration. .. warning:: You will need to install debug tool drivers depending on your system. Please click on compatible debug tool below for the further instructions and configuration information. You can switch between debugging :ref:`debugging_tools` using :ref:`projectconf_debug_tool` option in :ref:`projectconf`. """) if has_onboard_debug: lines.append( "{name} has on-board debug probe and **IS READY** for " "debugging. You don't need to use/buy external debug probe.". format(**variables)) else: lines.append( "{name} does not have on-board debug probe and **IS NOT " "READY** for debugging. You will need to use/buy one of " "external probe listed below.".format(**variables)) lines.append(""" .. list-table:: :header-rows: 1 * - Compatible Tools - On-board - Default""") for (tool_name, tool_data) in sorted(board["debug"]["tools"].items()): lines.append(""" * - :ref:`debugging_tool_{name}` - {onboard} - {default}""".format( name=tool_name, onboard="Yes" if tool_data.get("onboard") else "", default="Yes" if tool_name == default_debug_tool else "", )) if board["frameworks"]: lines.extend(generate_frameworks_contents(board["frameworks"])) with open(rst_path, "w") as f: f.write("\n".join(lines))
def is_compat_platform_and_framework(platform, framework): p = PlatformFactory.new(platform) return framework in (p.frameworks or {}).keys()
def generate_framework(type_, data, rst_dir=None): 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(RST_COPYRIGHT) lines.append(".. _framework_%s:" % type_) lines.append("") lines.append(data["title"]) lines.append("=" * len(data["title"])) lines.append("") lines.append(":Configuration:") lines.append(" :ref:`projectconf_env_framework` = ``%s``" % type_) lines.append("") lines.append(data["description"]) lines.append(""" For more detailed information please visit `vendor site <%s>`_. """ % campaign_url(data["url"])) lines.append(""" .. contents:: Contents :local: :depth: 1""") # Extra if isfile(join(rst_dir, "%s_extra.rst" % type_)): lines.append(".. include:: %s_extra.rst" % type_) # # Debugging # if compatible_boards: lines.extend( generate_debug_contents( compatible_boards, extra_rst="%s_debug.rst" % type_ if isfile(join(rst_dir, "%s_debug.rst" % type_)) else None, )) if compatible_platforms: # examples lines.append(""" Examples -------- """) for manifest in compatible_platforms: p = PlatformFactory.new(manifest["name"]) lines.append("* `%s for %s <%s>`_" % ( data["title"], manifest["title"], campaign_url( "%s/tree/master/examples" % p.repository_url[:-4]), )) # Platforms lines.extend( generate_platforms_contents( [manifest["name"] for manifest in compatible_platforms])) # # 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 <https://platformio.org/boards>`_ * For more detailed ``board`` information please scroll the tables below by horizontally. """) for vendor, boards in sorted(vendors.items()): lines.append(str(vendor)) lines.append("~" * len(vendor)) lines.extend(generate_boards_table(boards)) return "\n".join(lines)
def generate_platform(name, rst_dir): print("Processing platform: %s" % name) compatible_boards = [ board for board in BOARDS if name == board["platform"] ] lines = [] lines.append(RST_COPYRIGHT) p = PlatformFactory.new(name) assert p.repository_url.endswith(".git") github_url = p.repository_url[:-4] lines.append(".. _platform_%s:" % p.name) lines.append("") lines.append(p.title) lines.append("=" * len(p.title)) lines.append("") lines.append(":Configuration:") lines.append(" :ref:`projectconf_env_platform` = ``%s``" % p.name) lines.append("") lines.append(p.description) lines.append(""" For more detailed information please visit `vendor site <%s>`_.""" % campaign_url(p.homepage)) lines.append(""" .. contents:: Contents :local: :depth: 1 """) # # Extra # if isfile(join(rst_dir, "%s_extra.rst" % name)): 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("%s/tree/master/examples" % github_url))) examples_dir = join(p.get_dir(), "examples") if isdir(examples_dir): for eitem in os.listdir(examples_dir): example_dir = join(examples_dir, eitem) if not isdir(example_dir) or not os.listdir(example_dir): continue url = "%s/tree/master/examples/%s" % (github_url, eitem) lines.append("* `%s <%s>`_" % (eitem, campaign_url(url))) # # Debugging # if compatible_boards: lines.extend( generate_debug_contents( compatible_boards, skip_board_columns=["Platform"], extra_rst="%s_debug.rst" % name if isfile(join(rst_dir, "%s_debug.rst" % name)) else None, )) # # Development version of dev/platform # lines.append(""" Stable and upstream versions ---------------------------- You can switch between `stable releases <{github_url}/releases>`__ of {title} development platform and the latest upstream version using :ref:`projectconf_env_platform` option in :ref:`projectconf` as described below. Stable ~~~~~~ .. code-block:: ini ; Latest stable version [env:latest_stable] platform = {name} board = ... ; Custom stable version [env:custom_stable] platform = {name}@x.y.z board = ... Upstream ~~~~~~~~ .. code-block:: ini [env:upstream_develop] platform = {github_url}.git board = ... """.format(name=p.name, title=p.title, github_url=github_url)) # # Packages # _packages_content = generate_packages(name, p.packages.keys(), p.is_embedded()) if _packages_content: lines.append(_packages_content) # # Frameworks # compatible_frameworks = [] for framework in API_FRAMEWORKS: if is_compat_platform_and_framework(name, framework["name"]): compatible_frameworks.append(framework["name"]) lines.extend(generate_frameworks_contents(compatible_frameworks)) # # 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 <https://platformio.org/boards>`_ * For more detailed ``board`` information please scroll the tables below by horizontally. """) for vendor, boards in sorted(vendors.items()): lines.append(str(vendor)) lines.append("~" * len(vendor)) lines.extend( generate_boards_table(boards, skip_columns=["Platform"])) return "\n".join(lines)
def validate_debug_options(cmd_ctx, env_options): def _cleanup_cmds(items): items = ProjectConfig.parse_multi_values(items) return [ "$LOAD_CMDS" if item == "$LOAD_CMD" else item for item in items ] try: platform = PlatformFactory.new(env_options["platform"]) except UnknownPlatform: cmd_ctx.invoke( cmd_platform_install, platforms=[env_options["platform"]], skip_default_package=True, ) platform = PlatformFactory.new(env_options["platform"]) board_config = platform.board_config(env_options["board"]) tool_name = board_config.get_debug_tool_name(env_options.get("debug_tool")) tool_settings = board_config.get("debug", {}).get("tools", {}).get(tool_name, {}) server_options = None # specific server per a system if isinstance(tool_settings.get("server", {}), list): for item in tool_settings["server"][:]: tool_settings["server"] = item if util.get_systype() in item.get("system", []): break # user overwrites debug server if env_options.get("debug_server"): server_options = { "cwd": None, "executable": None, "arguments": env_options.get("debug_server"), } server_options["executable"] = server_options["arguments"][0] server_options["arguments"] = server_options["arguments"][1:] elif "server" in tool_settings: server_options = tool_settings["server"] server_package = server_options.get("package") server_package_dir = (platform.get_package_dir(server_package) if server_package else None) if server_package and not server_package_dir: platform.install_packages(with_packages=[server_package], skip_default_package=True, silent=True) server_package_dir = platform.get_package_dir(server_package) server_options.update( dict( cwd=server_package_dir if server_package else None, executable=server_options.get("executable"), arguments=[ a.replace("$PACKAGE_DIR", server_package_dir) if server_package_dir else a for a in server_options.get("arguments", []) ], )) extra_cmds = _cleanup_cmds(env_options.get("debug_extra_cmds")) extra_cmds.extend(_cleanup_cmds(tool_settings.get("extra_cmds"))) result = dict( tool=tool_name, upload_protocol=env_options.get( "upload_protocol", board_config.get("upload", {}).get("protocol")), load_cmds=_cleanup_cmds( env_options.get( "debug_load_cmds", tool_settings.get( "load_cmds", tool_settings.get( "load_cmd", ProjectOptions["env.debug_load_cmds"].default), ), )), load_mode=env_options.get( "debug_load_mode", tool_settings.get("load_mode", ProjectOptions["env.debug_load_mode"].default), ), init_break=env_options.get( "debug_init_break", tool_settings.get("init_break", ProjectOptions["env.debug_init_break"].default), ), init_cmds=_cleanup_cmds( env_options.get("debug_init_cmds", tool_settings.get("init_cmds"))), extra_cmds=extra_cmds, require_debug_port=tool_settings.get("require_debug_port", False), port=reveal_debug_port( env_options.get("debug_port", tool_settings.get("port")), tool_name, tool_settings, ), server=server_options, ) return result
def device_monitor(**kwargs): # pylint: disable=too-many-branches # load default monitor filters filters_dir = os.path.join(fs.get_source_dir(), "commands", "device", "filters") for name in os.listdir(filters_dir): if not name.endswith(".py"): continue device_helpers.load_monitor_filter(os.path.join(filters_dir, name)) project_options = {} try: with fs.cd(kwargs["project_dir"]): project_options = device_helpers.get_project_options( kwargs["environment"]) kwargs = device_helpers.apply_project_monitor_options( kwargs, project_options) except NotPlatformIOProjectError: pass platform = None if "platform" in project_options: with fs.cd(kwargs["project_dir"]): platform = PlatformFactory.new(project_options["platform"]) device_helpers.register_platform_filters(platform, kwargs["project_dir"], kwargs["environment"]) if not kwargs["port"]: ports = util.get_serial_ports(filter_hwid=True) if len(ports) == 1: kwargs["port"] = ports[0]["port"] elif "platform" in project_options and "board" in project_options: board_hwids = device_helpers.get_board_hwids( kwargs["project_dir"], platform, project_options["board"], ) for item in ports: for hwid in board_hwids: hwid_str = ("%s:%s" % (hwid[0], hwid[1])).replace("0x", "") if hwid_str in item["hwid"]: kwargs["port"] = item["port"] break if kwargs["port"]: break elif kwargs["port"] and (set(["*", "?", "[", "]"]) & set(kwargs["port"])): for item in util.get_serial_ports(): if fnmatch(item["port"], kwargs["port"]): kwargs["port"] = item["port"] break # override system argv with patched options sys.argv = ["monitor"] + device_helpers.options_to_argv( kwargs, project_options, ignore=("port", "baud", "rts", "dtr", "environment", "project_dir"), ) if not kwargs["quiet"]: click.echo("--- Available filters and text transformations: %s" % ", ".join(sorted(miniterm.TRANSFORMATIONS.keys()))) click.echo("--- More details at http://bit.ly/pio-monitor-filters") try: miniterm.main( default_port=kwargs["port"], default_baudrate=kwargs["baud"] or 9600, default_rts=kwargs["rts"], default_dtr=kwargs["dtr"], ) except Exception as e: raise exception.MinitermException(e)
def check_internal_updates(ctx, what): # pylint: disable=too-many-branches last_check = app.get_state_item("last_check", {}) interval = int(app.get_setting("check_%s_interval" % what)) * 3600 * 24 if (time() - interval) < last_check.get(what + "_update", 0): return last_check[what + "_update"] = int(time()) app.set_state_item("last_check", last_check) http.ensure_internet_on(raise_exception=True) outdated_items = [] pm = PlatformPackageManager() if what == "platforms" else LibraryPackageManager() for pkg in pm.get_installed(): if pkg.metadata.name in outdated_items: continue conds = [ pm.outdated(pkg).is_outdated(), what == "platforms" and PlatformFactory.new(pkg).are_outdated_packages(), ] if any(conds): outdated_items.append(pkg.metadata.name) if not outdated_items: return terminal_width, _ = click.get_terminal_size() click.echo("") click.echo("*" * terminal_width) click.secho( "There are the new updates for %s (%s)" % (what, ", ".join(outdated_items)), fg="yellow", ) if not app.get_setting("auto_update_" + what): click.secho("Please update them via ", fg="yellow", nl=False) click.secho( "`platformio %s update`" % ("lib --global" if what == "libraries" else "platform"), fg="cyan", nl=False, ) click.secho(" command.\n", fg="yellow") click.secho( "If you want to manually check for the new versions " "without updating, please use ", fg="yellow", nl=False, ) click.secho( "`platformio %s update --dry-run`" % ("lib --global" if what == "libraries" else "platform"), fg="cyan", nl=False, ) click.secho(" command.", fg="yellow") else: click.secho("Please wait while updating %s ..." % what, fg="yellow") if what == "platforms": ctx.invoke(cmd_platform_update, platforms=outdated_items) elif what == "libraries": ctx.meta[CTX_META_STORAGE_DIRS_KEY] = [pm.package_dir] ctx.invoke(cmd_lib_update, libraries=outdated_items) click.echo() telemetry.send_event(category="Auto", action="Update", label=what.title()) click.echo("*" * terminal_width) click.echo("")
def cli(ctx, project_dir, project_conf, environment, verbose, interface, __unprocessed): app.set_session_var("custom_project_conf", project_conf) # use env variables from Eclipse or CLion for sysenv in ("CWD", "PWD", "PLATFORMIO_PROJECT_DIR"): if is_platformio_project(project_dir): break if os.getenv(sysenv): project_dir = os.getenv(sysenv) with fs.cd(project_dir): config = ProjectConfig.get_instance(project_conf) config.validate(envs=[environment] if environment else None) env_name = environment or helpers.get_default_debug_env(config) env_options = config.items(env=env_name, as_dict=True) if not set(env_options.keys()) >= set(["platform", "board"]): raise ProjectEnvsNotAvailableError() try: platform = PlatformFactory.new(env_options["platform"]) except UnknownPlatform: ctx.invoke( cmd_platform_install, platforms=[env_options["platform"]], skip_default_package=True, ) platform = PlatformFactory.new(env_options["platform"]) debug_options = helpers.configure_initial_debug_options(platform, env_options) assert debug_options if not interface: return helpers.predebug_project(ctx, project_dir, env_name, False, verbose) ide_data = load_project_ide_data(project_dir, env_name) if not ide_data: raise DebugInvalidOptionsError("Could not load a build configuration") if "--version" in __unprocessed: result = proc.exec_command([ide_data["gdb_path"], "--version"]) if result["returncode"] == 0: return click.echo(result["out"]) raise exception.PlatformioException("\n".join([result["out"], result["err"]])) try: fs.ensure_udev_rules() except exception.InvalidUdevRules as e: click.echo( helpers.escape_gdbmi_stream("~", str(e) + "\n") if helpers.is_gdbmi_mode() else str(e) + "\n", nl=False, ) try: debug_options = platform.configure_debug_options(debug_options, ide_data) except NotImplementedError: # legacy for ESP32 dev-platform <=2.0.0 debug_options["load_cmds"] = helpers.configure_esp32_load_cmds( debug_options, ide_data ) rebuild_prog = False preload = debug_options["load_cmds"] == ["preload"] load_mode = debug_options["load_mode"] if load_mode == "always": rebuild_prog = preload or not helpers.has_debug_symbols(ide_data["prog_path"]) elif load_mode == "modified": rebuild_prog = helpers.is_prog_obsolete( ide_data["prog_path"] ) or not helpers.has_debug_symbols(ide_data["prog_path"]) else: rebuild_prog = not isfile(ide_data["prog_path"]) if preload or (not rebuild_prog and load_mode != "always"): # don't load firmware through debug server debug_options["load_cmds"] = [] if rebuild_prog: if helpers.is_gdbmi_mode(): click.echo( helpers.escape_gdbmi_stream( "~", "Preparing firmware for debugging...\n" ), nl=False, ) stream = helpers.GDBMIConsoleStream() with proc.capture_std_streams(stream): helpers.predebug_project(ctx, project_dir, env_name, preload, verbose) stream.close() else: click.echo("Preparing firmware for debugging...") helpers.predebug_project(ctx, project_dir, env_name, preload, verbose) # save SHA sum of newly created prog if load_mode == "modified": helpers.is_prog_obsolete(ide_data["prog_path"]) if not isfile(ide_data["prog_path"]): raise DebugInvalidOptionsError("Program/firmware is missed") # run debugging client inject_contrib_pysite() # pylint: disable=import-outside-toplevel from platformio.commands.debug.process.client import GDBClient, reactor client = GDBClient(project_dir, __unprocessed, debug_options, env_options) client.spawn(ide_data["gdb_path"], ide_data["prog_path"]) signal.signal(signal.SIGINT, lambda *args, **kwargs: None) reactor.run() return True