From b5bc5712b115b24822b32ff8bd6000434ca6213a Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Tue, 5 Sep 2017 14:05:19 +0300 Subject: [PATCH] Initial support for Project Templates --- .isort.cfg | 2 +- platformio/__init__.py | 2 +- platformio/commands/init.py | 317 +++----------- platformio/exception.py | 22 + platformio/ide/projectgenerator.py | 177 -------- platformio/ide/tpls/atom/.clang_complete.tpl | 6 - platformio/ide/tpls/atom/.gcc-flags.json.tpl | 8 - platformio/ide/tpls/atom/.gitignore.tpl | 4 - platformio/ide/tpls/clion/.gitignore.tpl | 3 - platformio/ide/tpls/clion/.idea/clion.iml.tpl | 8 - .../ide/tpls/clion/.idea/modules.xml.tpl | 9 - .../ide/tpls/clion/.idea/platformio.iml.tpl | 8 - .../ide/tpls/clion/.idea/watcherTasks.xml.tpl | 30 -- .../ide/tpls/clion/.idea/workspace.xml.tpl | 266 ------------ platformio/ide/tpls/clion/CMakeLists.txt.tpl | 54 --- .../ide/tpls/clion/CMakeListsPrivate.txt.tpl | 26 -- .../ide/tpls/codeblocks/platformio.cbp.tpl | 64 --- platformio/ide/tpls/eclipse/.cproject.tpl | 187 --------- platformio/ide/tpls/eclipse/.project.tpl | 27 -- .../.settings/PlatformIO Debugger.launch.tpl | 38 -- .../.settings/language.settings.xml.tpl | 18 - .../.settings/org.eclipse.cdt.core.prefs.tpl | 6 - platformio/ide/tpls/emacs/.clang_complete.tpl | 6 - platformio/ide/tpls/emacs/.gitignore.tpl | 3 - .../netbeans/nbproject/configurations.xml.tpl | 72 ---- .../nbproject/private/configurations.xml.tpl | 61 --- .../nbproject/private/launcher.properties.tpl | 40 -- .../nbproject/private/private.xml.tpl | 10 - .../tpls/netbeans/nbproject/project.xml.tpl | 26 -- .../ide/tpls/qtcreator/platformio.pro.tpl | 28 -- .../platformio.sublime-project.tpl | 104 ----- platformio/ide/tpls/vim/.clang_complete.tpl | 6 - platformio/ide/tpls/vim/.gcc-flags.json.tpl | 8 - platformio/ide/tpls/vim/.gitignore.tpl | 4 - .../platformio.vcxproj.filters.tpl | 29 -- .../tpls/visualstudio/platformio.vcxproj.tpl | 74 ---- platformio/ide/tpls/vscode/.gitignore.tpl | 3 - .../vscode/.vscode/c_cpp_properties.json.tpl | 37 -- .../ide/tpls/vscode/.vscode/launch.json.tpl | 15 - platformio/managers/core.py | 8 +- platformio/{ide => project}/__init__.py | 0 platformio/project/config.py | 183 ++++++++ platformio/project/generator.py | 279 +++++++++++++ platformio/project/template.py | 391 ++++++++++++++++++ platformio/projectconftpl.ini | 9 - setup.py | 1 + tests/commands/test_init.py | 4 + 47 files changed, 937 insertions(+), 1746 deletions(-) delete mode 100644 platformio/ide/projectgenerator.py delete mode 100644 platformio/ide/tpls/atom/.clang_complete.tpl delete mode 100644 platformio/ide/tpls/atom/.gcc-flags.json.tpl delete mode 100644 platformio/ide/tpls/atom/.gitignore.tpl delete mode 100644 platformio/ide/tpls/clion/.gitignore.tpl delete mode 100644 platformio/ide/tpls/clion/.idea/clion.iml.tpl delete mode 100644 platformio/ide/tpls/clion/.idea/modules.xml.tpl delete mode 100644 platformio/ide/tpls/clion/.idea/platformio.iml.tpl delete mode 100644 platformio/ide/tpls/clion/.idea/watcherTasks.xml.tpl delete mode 100644 platformio/ide/tpls/clion/.idea/workspace.xml.tpl delete mode 100644 platformio/ide/tpls/clion/CMakeLists.txt.tpl delete mode 100644 platformio/ide/tpls/clion/CMakeListsPrivate.txt.tpl delete mode 100644 platformio/ide/tpls/codeblocks/platformio.cbp.tpl delete mode 100644 platformio/ide/tpls/eclipse/.cproject.tpl delete mode 100644 platformio/ide/tpls/eclipse/.project.tpl delete mode 100644 platformio/ide/tpls/eclipse/.settings/PlatformIO Debugger.launch.tpl delete mode 100644 platformio/ide/tpls/eclipse/.settings/language.settings.xml.tpl delete mode 100644 platformio/ide/tpls/eclipse/.settings/org.eclipse.cdt.core.prefs.tpl delete mode 100644 platformio/ide/tpls/emacs/.clang_complete.tpl delete mode 100644 platformio/ide/tpls/emacs/.gitignore.tpl delete mode 100644 platformio/ide/tpls/netbeans/nbproject/configurations.xml.tpl delete mode 100644 platformio/ide/tpls/netbeans/nbproject/private/configurations.xml.tpl delete mode 100644 platformio/ide/tpls/netbeans/nbproject/private/launcher.properties.tpl delete mode 100644 platformio/ide/tpls/netbeans/nbproject/private/private.xml.tpl delete mode 100644 platformio/ide/tpls/netbeans/nbproject/project.xml.tpl delete mode 100644 platformio/ide/tpls/qtcreator/platformio.pro.tpl delete mode 100644 platformio/ide/tpls/sublimetext/platformio.sublime-project.tpl delete mode 100644 platformio/ide/tpls/vim/.clang_complete.tpl delete mode 100644 platformio/ide/tpls/vim/.gcc-flags.json.tpl delete mode 100644 platformio/ide/tpls/vim/.gitignore.tpl delete mode 100644 platformio/ide/tpls/visualstudio/platformio.vcxproj.filters.tpl delete mode 100644 platformio/ide/tpls/visualstudio/platformio.vcxproj.tpl delete mode 100644 platformio/ide/tpls/vscode/.gitignore.tpl delete mode 100644 platformio/ide/tpls/vscode/.vscode/c_cpp_properties.json.tpl delete mode 100644 platformio/ide/tpls/vscode/.vscode/launch.json.tpl rename platformio/{ide => project}/__init__.py (100%) create mode 100644 platformio/project/config.py create mode 100644 platformio/project/generator.py create mode 100644 platformio/project/template.py delete mode 100644 platformio/projectconftpl.ini diff --git a/.isort.cfg b/.isort.cfg index d63487e9..16306320 100644 --- a/.isort.cfg +++ b/.isort.cfg @@ -1,3 +1,3 @@ [settings] line_length=79 -known_third_party=arrow,bottle,click,lockfile,pytest,requests,SCons,semantic_version,serial +known_third_party=arrow,bottle,click,configobj,lockfile,pytest,requests,SCons,semantic_version,serial diff --git a/platformio/__init__.py b/platformio/__init__.py index 70be693d..cf0ed85b 100644 --- a/platformio/__init__.py +++ b/platformio/__init__.py @@ -14,7 +14,7 @@ import sys -VERSION = (3, 5, "0a8") +VERSION = (3, 5, "0a9") __version__ = ".".join([str(s) for s in VERSION]) __title__ = "platformio" diff --git a/platformio/commands/init.py b/platformio/commands/init.py index ac16bb7e..2deb8456 100644 --- a/platformio/commands/init.py +++ b/platformio/commands/init.py @@ -12,22 +12,16 @@ # See the License for the specific language governing permissions and # limitations under the License. -# pylint: disable=too-many-arguments,too-many-locals, too-many-branches - -from os import getcwd, makedirs -from os.path import isdir, isfile, join -from shutil import copyfile +from os import getcwd import click -from platformio import exception, util -from platformio.commands.platform import \ - platform_install as cli_platform_install -from platformio.ide.projectgenerator import ProjectGenerator +from platformio import exception from platformio.managers.platform import PlatformManager +from platformio.project.generator import ProjectGenerator -def validate_boards(ctx, param, value): # pylint: disable=W0613 +def validate_boards(ctx, param, value): # pylint: disable=unused-argument pm = PlatformManager() for id_ in value: try: @@ -53,21 +47,27 @@ def validate_boards(ctx, param, value): # pylint: disable=W0613 resolve_path=True)) @click.option( "-b", "--board", multiple=True, metavar="ID", callback=validate_boards) +@click.option("-p", "--platform") +@click.option("-f", "--framework") +@click.option("--ide", type=click.Choice(ProjectGenerator.get_supported_ide())) +@click.option("--vcs", type=click.Choice(ProjectGenerator.get_supported_vcs())) +@click.option("--ci", type=click.Choice(ProjectGenerator.get_supported_ci())) @click.option( - "--ide", type=click.Choice(ProjectGenerator.get_supported_ides())) -@click.option("-O", "--project-option", multiple=True) + "-L", "--list-templates", help="List available source code templates") +@click.option("-t", "--template") +@click.option("-T", "--template-var", multiple=True) @click.option("--env-prefix", default="") +@click.option("-E", "--env-option", multiple=True) +@click.option( + "-O", + "--project-option", + multiple=True, + help="Deprecated. Use `--env-option` instead") @click.option("-s", "--silent", is_flag=True) -@click.pass_context -def cli( - ctx, # pylint: disable=R0913 - project_dir, - board, - ide, - project_option, - env_prefix, +def cli( # pylint: disable=too-many-arguments,too-many-locals + project_dir, board, platform, framework, ide, vcs, ci, list_templates, + template, template_var, env_prefix, env_option, project_option, silent): - if not silent: if project_dir == getcwd(): click.secho( @@ -89,18 +89,37 @@ def cli( click.echo("%s - Put here project specific (private) libraries" % click.style("lib", fg="cyan")) - init_base_project(project_dir) - - if board: - fill_project_envs(ctx, project_dir, board, project_option, env_prefix, - ide is not None) + pg = ProjectGenerator( + project_dir, + dict( + boards=list(board), + platform=platform, + framework=framework, + ide=ide, + template=template, + template_vars=list(template_var), + env_prefix=env_prefix, + env_options=list(env_option) + list(project_option), + vcs=vcs, + ci=ci)) if ide: - env_name = get_best_envname(project_dir, board) - if not env_name: - raise exception.BoardNotDefined() - pg = ProjectGenerator(project_dir, ide, env_name) - pg.generate() + # install development platform before (show progress) + pm = PlatformManager() + for name in pg.project_config.get_env_names(): + platform = pg.project_config.env_get(name, "platform") + framework = pg.project_config.env_get(name, "framework") + if not platform: + continue + if framework: + pm.install( + platform, + with_packages=["framework-%s" % framework], + silent=True) + else: + pm.install(platform, silent=True) + + pg.generate() if not silent: click.secho( @@ -113,239 +132,3 @@ def cli( "files)\n" "`platformio run --help` - additional information", fg="green") - - -def get_best_envname(project_dir, boards=None): - config = util.load_project_config(project_dir) - env_default = None - if config.has_option("platformio", "env_default"): - env_default = config.get("platformio", - "env_default").split(", ")[0].strip() - if env_default: - return env_default - section = None - for section in config.sections(): - if not section.startswith("env:"): - continue - elif config.has_option(section, "board") and (not boards or config.get( - section, "board") in boards): - break - return section[4:] if section else None - - -def init_base_project(project_dir): - if not util.is_platformio_project(project_dir): - copyfile( - join(util.get_source_dir(), "projectconftpl.ini"), - join(project_dir, "platformio.ini")) - - lib_dir = join(project_dir, "lib") - src_dir = join(project_dir, "src") - config = util.load_project_config(project_dir) - if config.has_option("platformio", "src_dir"): - src_dir = join(project_dir, config.get("platformio", "src_dir")) - - for d in (src_dir, lib_dir): - if not isdir(d): - makedirs(d) - - init_lib_readme(lib_dir) - init_ci_conf(project_dir) - init_cvs_ignore(project_dir) - - -def init_lib_readme(lib_dir): - if isfile(join(lib_dir, "readme.txt")): - return - with open(join(lib_dir, "readme.txt"), "w") as f: - f.write(""" -This directory is intended for the project specific (private) libraries. -PlatformIO will compile them to static libraries and link to executable file. - -The source code of each library should be placed in separate directory, like -"lib/private_lib/[here are source files]". - -For example, see how can be organized `Foo` and `Bar` libraries: - -|--lib -| |--Bar -| | |--docs -| | |--examples -| | |--src -| | |- Bar.c -| | |- Bar.h -| |--Foo -| | |- Foo.c -| | |- Foo.h -| |- readme.txt --> THIS FILE -|- platformio.ini -|--src - |- main.c - -Then in `src/main.c` you should use: - -#include -#include - -// rest H/C/CPP code - -PlatformIO will find your libraries automatically, configure preprocessor's -include paths and build them. - -More information about PlatformIO Library Dependency Finder -- http://docs.platformio.org/page/librarymanager/ldf.html -""") - - -def init_ci_conf(project_dir): - if isfile(join(project_dir, ".travis.yml")): - return - with open(join(project_dir, ".travis.yml"), "w") as f: - f.write("""# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < http://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < http://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < http://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choice one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to by used as a library with examples -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N -""") - - -def init_cvs_ignore(project_dir): - ignore_path = join(project_dir, ".gitignore") - default = [".pioenvs\n", ".piolibdeps\n"] - current = [] - modified = False - if isfile(ignore_path): - with open(ignore_path) as fp: - current = fp.readlines() - if current and not current[-1].endswith("\n"): - current[-1] += "\n" - for d in default: - if d not in current: - modified = True - current.append(d) - if not modified: - return - with open(ignore_path, "w") as fp: - fp.writelines(current) - - -def fill_project_envs(ctx, project_dir, board_ids, project_option, env_prefix, - force_download): - content = [] - used_boards = [] - used_platforms = [] - - config = util.load_project_config(project_dir) - for section in config.sections(): - cond = [ - section.startswith("env:"), - config.has_option(section, "board") - ] - if all(cond): - used_boards.append(config.get(section, "board")) - - pm = PlatformManager() - for id_ in board_ids: - board_config = pm.board_config(id_) - used_platforms.append(board_config['platform']) - if id_ in used_boards: - continue - used_boards.append(id_) - - envopts = {"platform": board_config['platform'], "board": id_} - # find default framework for board - frameworks = board_config.get("frameworks") - if frameworks: - envopts['framework'] = frameworks[0] - - for item in project_option: - if "=" not in item: - continue - _name, _value = item.split("=", 1) - envopts[_name.strip()] = _value.strip() - - content.append("") - content.append("[env:%s%s]" % (env_prefix, id_)) - for name, value in envopts.items(): - content.append("%s = %s" % (name, value)) - - if force_download and used_platforms: - _install_dependent_platforms(ctx, used_platforms) - - if not content: - return - - with open(join(project_dir, "platformio.ini"), "a") as f: - content.append("") - f.write("\n".join(content)) - - -def _install_dependent_platforms(ctx, platforms): - installed_platforms = [ - p['name'] for p in PlatformManager().get_installed() - ] - if set(platforms) <= set(installed_platforms): - return - ctx.invoke( - cli_platform_install, - platforms=list(set(platforms) - set(installed_platforms))) diff --git a/platformio/exception.py b/platformio/exception.py index e190d7a4..ac59523e 100644 --- a/platformio/exception.py +++ b/platformio/exception.py @@ -127,6 +127,28 @@ class NotPlatformIOProject(PlatformioException): "please use `platformio init` command" +class UnknownProjectTemplate(PlatformioException): + + MESSAGE = "Unknown Project Template '{0}'" + + +class UnknownProjectTplVar(PlatformioException): + + MESSAGE = "Unknown Project Template Variable '{0}'" + + +class IncompatbileProjectTemplate(PlatformioException): + + MESSAGE = "Project Template '{0}' is not compatible with {1} '{2}'. "\ + "Valid candidates: {3}" + + +class InvalidProjectTplVar(PlatformioException): + + MESSAGE = "Project Template Variable: invalid value `{0}` for '{1}' "\ + "(type={2}, options={3})" + + class UndefinedEnvPlatform(PlatformioException): MESSAGE = "Please specify platform for '{0}' environment" diff --git a/platformio/ide/projectgenerator.py b/platformio/ide/projectgenerator.py deleted file mode 100644 index 1561bc6e..00000000 --- a/platformio/ide/projectgenerator.py +++ /dev/null @@ -1,177 +0,0 @@ -# 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 os -import re -from cStringIO import StringIO -from os.path import abspath, basename, expanduser, isdir, isfile, join, relpath - -import bottle -import click - -from platformio import exception, util -from platformio.commands.run import cli as cmd_run - - -class ProjectGenerator(object): - - def __init__(self, project_dir, ide, env_name): - 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 - def get_supported_ides(): - tpls_dir = join(util.get_source_dir(), "ide", "tpls") - return sorted( - [d for d in os.listdir(tpls_dir) if isdir(join(tpls_dir, d))]) - - @util.memoized - def get_project_env(self): - data = {} - config = util.load_project_config(self.project_dir) - for section in config.sections(): - if not section.startswith("env:"): - continue - if self.env_name != section[4:]: - continue - data = {"env_name": section[4:]} - for k, v in config.items(section): - data[k] = v - return data - - @util.memoized - def get_project_build_data(self): - data = {"defines": [], "includes": [], "cxx_path": None} - envdata = self.get_project_env() - if not envdata: - return data - - out = StringIO() - with util.capture_stdout(out): - click.get_current_context().invoke( - cmd_run, - project_dir=self.project_dir, - environment=[envdata['env_name']], - target=["idedata"]) - result = out.getvalue() - - if '"includes":' not in result: - raise exception.PlatformioException(result) - - for line in result.split("\n"): - line = line.strip() - if line.startswith('{"') and line.endswith("}"): - data = json.loads(line) - return data - - def get_project_name(self): - return basename(self.project_dir) - - def get_src_files(self): - result = [] - with util.cd(self.project_dir): - for root, _, files in os.walk(self.project_src_dir): - for f in files: - result.append(relpath(join(root, f))) - return result - - def get_tpls(self): - tpls = [] - tpls_dir = join(util.get_source_dir(), "ide", "tpls", self.ide) - for root, _, files in os.walk(tpls_dir): - for f in files: - if not f.endswith(".tpl"): - continue - _relpath = root.replace(tpls_dir, "") - if _relpath.startswith(os.sep): - _relpath = _relpath[1:] - tpls.append((_relpath, join(root, f))) - return tpls - - def generate(self): - for tpl_relpath, tpl_path in self.get_tpls(): - dst_dir = self.project_dir - if tpl_relpath: - dst_dir = join(self.project_dir, tpl_relpath) - if not isdir(dst_dir): - os.makedirs(dst_dir) - - file_name = basename(tpl_path)[:-4] - self._merge_contents( - join(dst_dir, file_name), - self._render_tpl(tpl_path).encode("utf8")) - - def _render_tpl(self, tpl_path): - content = "" - with open(tpl_path) as f: - content = f.read() - return bottle.template(content, **self._tplvars) - - @staticmethod - def _merge_contents(dst_path, contents): - file_name = basename(dst_path) - - # merge .gitignore - if file_name == ".gitignore" and isfile(dst_path): - modified = False - default = [l.strip() for l in contents.split("\n")] - with open(dst_path) as fp: - current = [l.strip() for l in fp.readlines()] - for d in default: - if d and d not in current: - modified = True - current.append(d) - if not modified: - return - contents = "\n".join(current) + "\n" - - with open(dst_path, "w") as f: - f.write(contents) - - 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")) - }) - - @staticmethod - def _fix_os_path(path): - return (re.sub(r"[\\]+", '\\' * 4, path) - if "windows" in util.get_systype() else path) diff --git a/platformio/ide/tpls/atom/.clang_complete.tpl b/platformio/ide/tpls/atom/.clang_complete.tpl deleted file mode 100644 index bc09ec0d..00000000 --- a/platformio/ide/tpls/atom/.clang_complete.tpl +++ /dev/null @@ -1,6 +0,0 @@ -% for include in includes: --I{{include}} -% end -% for define in defines: --D{{!define}} -% end \ No newline at end of file diff --git a/platformio/ide/tpls/atom/.gcc-flags.json.tpl b/platformio/ide/tpls/atom/.gcc-flags.json.tpl deleted file mode 100644 index 5af2ea3a..00000000 --- a/platformio/ide/tpls/atom/.gcc-flags.json.tpl +++ /dev/null @@ -1,8 +0,0 @@ -{ - "execPath": "{{ cxx_path.replace("\\", "/") }}", - "gccDefaultCFlags": "-fsyntax-only {{! cc_flags.replace(' -MMD ', ' ').replace('"', '\\"') }}", - "gccDefaultCppFlags": "-fsyntax-only {{! cxx_flags.replace(' -MMD ', ' ').replace('"', '\\"') }}", - "gccErrorLimit": 15, - "gccIncludePaths": "{{ ','.join(includes).replace("\\", "/") }}", - "gccSuppressWarnings": false -} diff --git a/platformio/ide/tpls/atom/.gitignore.tpl b/platformio/ide/tpls/atom/.gitignore.tpl deleted file mode 100644 index 5dac9f52..00000000 --- a/platformio/ide/tpls/atom/.gitignore.tpl +++ /dev/null @@ -1,4 +0,0 @@ -.pioenvs -.piolibdeps -.clang_complete -.gcc-flags.json diff --git a/platformio/ide/tpls/clion/.gitignore.tpl b/platformio/ide/tpls/clion/.gitignore.tpl deleted file mode 100644 index 081bde01..00000000 --- a/platformio/ide/tpls/clion/.gitignore.tpl +++ /dev/null @@ -1,3 +0,0 @@ -.pioenvs -.piolibdeps -CMakeListsPrivate.txt diff --git a/platformio/ide/tpls/clion/.idea/clion.iml.tpl b/platformio/ide/tpls/clion/.idea/clion.iml.tpl deleted file mode 100644 index bc2cd874..00000000 --- a/platformio/ide/tpls/clion/.idea/clion.iml.tpl +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/platformio/ide/tpls/clion/.idea/modules.xml.tpl b/platformio/ide/tpls/clion/.idea/modules.xml.tpl deleted file mode 100644 index 9ce81f04..00000000 --- a/platformio/ide/tpls/clion/.idea/modules.xml.tpl +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/platformio/ide/tpls/clion/.idea/platformio.iml.tpl b/platformio/ide/tpls/clion/.idea/platformio.iml.tpl deleted file mode 100644 index bc2cd874..00000000 --- a/platformio/ide/tpls/clion/.idea/platformio.iml.tpl +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/platformio/ide/tpls/clion/.idea/watcherTasks.xml.tpl b/platformio/ide/tpls/clion/.idea/watcherTasks.xml.tpl deleted file mode 100644 index b05b34a8..00000000 --- a/platformio/ide/tpls/clion/.idea/watcherTasks.xml.tpl +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/platformio/ide/tpls/clion/.idea/workspace.xml.tpl b/platformio/ide/tpls/clion/.idea/workspace.xml.tpl deleted file mode 100644 index 8cf4214f..00000000 --- a/platformio/ide/tpls/clion/.idea/workspace.xml.tpl +++ /dev/null @@ -1,266 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - % for file in src_files: - - - - % end - - - - - true - - - - - - - - - - - - - - - - - C/C++ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1435919971910 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/platformio/ide/tpls/clion/CMakeLists.txt.tpl b/platformio/ide/tpls/clion/CMakeLists.txt.tpl deleted file mode 100644 index 63274c43..00000000 --- a/platformio/ide/tpls/clion/CMakeLists.txt.tpl +++ /dev/null @@ -1,54 +0,0 @@ -cmake_minimum_required(VERSION 3.2) -project({{project_name}}) - -include(CMakeListsPrivate.txt) - -add_custom_target( - PLATFORMIO_BUILD ALL - COMMAND ${PLATFORMIO_CMD} -f -c clion run - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} -) - -add_custom_target( - PLATFORMIO_UPLOAD ALL - COMMAND ${PLATFORMIO_CMD} -f -c clion run --target upload - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} -) - -add_custom_target( - PLATFORMIO_CLEAN ALL - COMMAND ${PLATFORMIO_CMD} -f -c clion run --target clean - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} -) - -add_custom_target( - PLATFORMIO_TEST ALL - COMMAND ${PLATFORMIO_CMD} -f -c clion test - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} -) - -add_custom_target( - PLATFORMIO_PROGRAM ALL - COMMAND ${PLATFORMIO_CMD} -f -c clion run --target program - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} -) - -add_custom_target( - PLATFORMIO_UPLOADFS ALL - COMMAND ${PLATFORMIO_CMD} -f -c clion run --target uploadfs - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} -) - -add_custom_target( - PLATFORMIO_UPDATE_ALL ALL - COMMAND ${PLATFORMIO_CMD} -f -c clion update - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} -) - -add_custom_target( - PLATFORMIO_REBUILD_PROJECT_INDEX ALL - COMMAND ${PLATFORMIO_CMD} -f -c clion init --ide clion - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} -) - -add_executable(${PROJECT_NAME} ${SRC_LIST}) diff --git a/platformio/ide/tpls/clion/CMakeListsPrivate.txt.tpl b/platformio/ide/tpls/clion/CMakeListsPrivate.txt.tpl deleted file mode 100644 index ca27ad43..00000000 --- a/platformio/ide/tpls/clion/CMakeListsPrivate.txt.tpl +++ /dev/null @@ -1,26 +0,0 @@ -set(ENV{PATH} "{{env_path}}") -set(PLATFORMIO_CMD "{{platformio_path}}") - -SET(CMAKE_C_COMPILER "{{cc_path.replace("\\", "/")}}") -SET(CMAKE_CXX_COMPILER "{{cxx_path.replace("\\", "/")}}") -SET(CMAKE_CXX_FLAGS_DISTRIBUTION "{{cxx_flags}}") -SET(CMAKE_C_FLAGS_DISTRIBUTION "{{cc_flags}}") -set(CMAKE_CXX_STANDARD 11) - -% for define in defines: -add_definitions(-D{{!define}}) -% end - -% for include in includes: -% if include.startswith(user_home_dir): -% if "windows" in systype: -include_directories("$ENV{HOMEDRIVE}$ENV{HOMEPATH}{{include.replace(user_home_dir, '').replace("\\", "/")}}") -% else: -include_directories("$ENV{HOME}{{include.replace(user_home_dir, '').replace("\\", "/")}}") -% end -% else: -include_directories("{{include.replace("\\", "/")}}") -% end -% end - -FILE(GLOB_RECURSE SRC_LIST "{{project_src_dir.replace("\\", "/")}}/*.*") diff --git a/platformio/ide/tpls/codeblocks/platformio.cbp.tpl b/platformio/ide/tpls/codeblocks/platformio.cbp.tpl deleted file mode 100644 index fc182531..00000000 --- a/platformio/ide/tpls/codeblocks/platformio.cbp.tpl +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - diff --git a/platformio/ide/tpls/eclipse/.cproject.tpl b/platformio/ide/tpls/eclipse/.cproject.tpl deleted file mode 100644 index 3060a7bb..00000000 --- a/platformio/ide/tpls/eclipse/.cproject.tpl +++ /dev/null @@ -1,187 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - platformio - -f -c eclipse - run -t program - true - true - false - - - platformio - -f -c eclipse - run -t uploadfs - true - true - false - - - platformio - -f -c eclipse - run - true - true - false - - - platformio - -f -c eclipse - run -t upload - true - true - false - - - platformio - -f -c eclipse - run -t clean - true - true - false - - - platformio - -f -c eclipse - test - true - true - false - - - platformio - -f -c eclipse - update - true - true - false - - - platformio - -f -c eclipse - init --ide eclipse - true - true - false - - - - diff --git a/platformio/ide/tpls/eclipse/.project.tpl b/platformio/ide/tpls/eclipse/.project.tpl deleted file mode 100644 index ac49f548..00000000 --- a/platformio/ide/tpls/eclipse/.project.tpl +++ /dev/null @@ -1,27 +0,0 @@ - - - {{project_name}} - - - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/platformio/ide/tpls/eclipse/.settings/PlatformIO Debugger.launch.tpl b/platformio/ide/tpls/eclipse/.settings/PlatformIO Debugger.launch.tpl deleted file mode 100644 index e27a3061..00000000 --- a/platformio/ide/tpls/eclipse/.settings/PlatformIO Debugger.launch.tpl +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/platformio/ide/tpls/eclipse/.settings/language.settings.xml.tpl b/platformio/ide/tpls/eclipse/.settings/language.settings.xml.tpl deleted file mode 100644 index 53c9c72f..00000000 --- a/platformio/ide/tpls/eclipse/.settings/language.settings.xml.tpl +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - % if "windows" in systype: - - % else: - - % end - - - - - - diff --git a/platformio/ide/tpls/eclipse/.settings/org.eclipse.cdt.core.prefs.tpl b/platformio/ide/tpls/eclipse/.settings/org.eclipse.cdt.core.prefs.tpl deleted file mode 100644 index 8cac7fbd..00000000 --- a/platformio/ide/tpls/eclipse/.settings/org.eclipse.cdt.core.prefs.tpl +++ /dev/null @@ -1,6 +0,0 @@ -eclipse.preferences.version=1 -environment/project/0.910961921/PATH/delimiter={{env_pathsep.replace(":", "\\:")}} -environment/project/0.910961921/PATH/operation=replace -environment/project/0.910961921/PATH/value={{env_path.replace(":", "\\:")}} -environment/project/0.910961921/append=true -environment/project/0.910961921/appendContributed=true \ No newline at end of file diff --git a/platformio/ide/tpls/emacs/.clang_complete.tpl b/platformio/ide/tpls/emacs/.clang_complete.tpl deleted file mode 100644 index bc09ec0d..00000000 --- a/platformio/ide/tpls/emacs/.clang_complete.tpl +++ /dev/null @@ -1,6 +0,0 @@ -% for include in includes: --I{{include}} -% end -% for define in defines: --D{{!define}} -% end \ No newline at end of file diff --git a/platformio/ide/tpls/emacs/.gitignore.tpl b/platformio/ide/tpls/emacs/.gitignore.tpl deleted file mode 100644 index 18d8a15b..00000000 --- a/platformio/ide/tpls/emacs/.gitignore.tpl +++ /dev/null @@ -1,3 +0,0 @@ -.pioenvs -.piolibdeps -.clang_complete diff --git a/platformio/ide/tpls/netbeans/nbproject/configurations.xml.tpl b/platformio/ide/tpls/netbeans/nbproject/configurations.xml.tpl deleted file mode 100644 index 897d7451..00000000 --- a/platformio/ide/tpls/netbeans/nbproject/configurations.xml.tpl +++ /dev/null @@ -1,72 +0,0 @@ - - - - - platformio.ini - - - nbproject/private/launcher.properties - - - ^(nbproject|.pioenvs)$ - - . - - - - - - default - false - false - - - true - true - - - - . - {{platformio_path}} -f -c netbeans run - {{platformio_path}} -f -c netbeans run --target clean - - - - src - % for include in includes: - {{include}} - % end - - - % for define in defines: - {{define}} - % end - - - - - src - % for include in includes: - {{include}} - % end - - - % for define in defines: - {{define}} - % end - - - - - . - - - - - - - - diff --git a/platformio/ide/tpls/netbeans/nbproject/private/configurations.xml.tpl b/platformio/ide/tpls/netbeans/nbproject/private/configurations.xml.tpl deleted file mode 100644 index 2beef95a..00000000 --- a/platformio/ide/tpls/netbeans/nbproject/private/configurations.xml.tpl +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - platformio.ini - - - - - - - localhost - {{4 if "darwin" in systype else 2 if "linux" in systype else 3}} - - - - . - ${AUTO_FOLDER} - - ${AUTO_FOLDER} - - ${MAKE} ${ITEM_NAME}.o - ${AUTO_COMPILE} - - ${AUTO_COMPILE} - - - - - - - - - - - - - - - gdb - - - - "${OUTPUT_PATH}" - {{platformio_path}} -f -c netbeans run --target upload - - {{platformio_path}} -f -c netbeans run --target upload - . - false - 0 - 0 - - - - - - diff --git a/platformio/ide/tpls/netbeans/nbproject/private/launcher.properties.tpl b/platformio/ide/tpls/netbeans/nbproject/private/launcher.properties.tpl deleted file mode 100644 index 6cc2127d..00000000 --- a/platformio/ide/tpls/netbeans/nbproject/private/launcher.properties.tpl +++ /dev/null @@ -1,40 +0,0 @@ -# Launchers File syntax: -# -# [Must-have property line] -# launcher1.runCommand= -# [Optional extra properties] -# launcher1.displayName= -# launcher1.buildCommand= -# launcher1.runDir= -# launcher1.symbolFiles= -# launcher1.env.= -# (If this value is quoted with ` it is handled as a native command which execution result will become the value) -# [Common launcher properties] -# common.runDir= -# (This value is overwritten by a launcher specific runDir value if the latter exists) -# common.env.= -# (Environment variables from common launcher are merged with launcher specific variables) -# common.symbolFiles= -# (This value is overwritten by a launcher specific symbolFiles value if the latter exists) -# -# In runDir, symbolFiles and env fields you can use these macroses: -# ${PROJECT_DIR} - project directory absolute path -# ${OUTPUT_PATH} - linker output path (relative to project directory path) -# ${OUTPUT_BASENAME}- linker output filename -# ${TESTDIR} - test files directory (relative to project directory path) -# ${OBJECTDIR} - object files directory (relative to project directory path) -# ${CND_DISTDIR} - distribution directory (relative to project directory path) -# ${CND_BUILDDIR} - build directory (relative to project directory path) -# ${CND_PLATFORM} - platform name -# ${CND_CONF} - configuration name -# ${CND_DLIB_EXT} - dynamic library extension -# -# All the project launchers must be listed in the file! -# -# launcher1.runCommand=... -# launcher2.runCommand=... -# ... -# common.runDir=... -# common.env.KEY=VALUE - -# launcher1.runCommand= \ No newline at end of file diff --git a/platformio/ide/tpls/netbeans/nbproject/private/private.xml.tpl b/platformio/ide/tpls/netbeans/nbproject/private/private.xml.tpl deleted file mode 100644 index 4f3fdc62..00000000 --- a/platformio/ide/tpls/netbeans/nbproject/private/private.xml.tpl +++ /dev/null @@ -1,10 +0,0 @@ - - - - true - - - 0 - 0 - - diff --git a/platformio/ide/tpls/netbeans/nbproject/project.xml.tpl b/platformio/ide/tpls/netbeans/nbproject/project.xml.tpl deleted file mode 100644 index ad4ea18f..00000000 --- a/platformio/ide/tpls/netbeans/nbproject/project.xml.tpl +++ /dev/null @@ -1,26 +0,0 @@ - - - org.netbeans.modules.cnd.makeproject - - - {{project_name}} - - - - UTF-8 - - - . - - - - Default - 0 - - - - false - - - - diff --git a/platformio/ide/tpls/qtcreator/platformio.pro.tpl b/platformio/ide/tpls/qtcreator/platformio.pro.tpl deleted file mode 100644 index 2ae9d49d..00000000 --- a/platformio/ide/tpls/qtcreator/platformio.pro.tpl +++ /dev/null @@ -1,28 +0,0 @@ -win32 { - HOMEDIR += $$(USERPROFILE) -} -else { - HOMEDIR += $$(HOME) -} - -% for include in includes: -% if include.startswith(user_home_dir): -INCLUDEPATH += "$${HOMEDIR}{{include.replace(user_home_dir, "")}}" -% else: -INCLUDEPATH += "{{include}}" -% end -% end - -% for define in defines: -DEFINES += "{{define}}" -% end - -OTHER_FILES += platformio.ini - -% for file in src_files: -% if file.endswith((".h", ".hpp")): -HEADERS += {{file}} -% else: -SOURCES += {{file}} -% end -% end diff --git a/platformio/ide/tpls/sublimetext/platformio.sublime-project.tpl b/platformio/ide/tpls/sublimetext/platformio.sublime-project.tpl deleted file mode 100644 index bf27d97c..00000000 --- a/platformio/ide/tpls/sublimetext/platformio.sublime-project.tpl +++ /dev/null @@ -1,104 +0,0 @@ -{ - "build_systems": - [ - { - "cmd": - [ - "platformio", - "-f", "-c", "sublimetext", - "run" - ], - "name": "PlatformIO", - "variants": - [ - { - "cmd": - [ - "platformio", - "-f", "-c", "sublimetext", - "run" - ], - "name": "Build" - }, - { - "cmd": - [ - "platformio", - "-f", "-c", "sublimetext", - "run", - "--target", - "clean" - ], - "name": "Clean" - }, - { - "cmd": - [ - "platformio", - "-f", "-c", "sublimetext", - "test" - ], - "name": "Test" - }, - { - "cmd": - [ - "platformio", - "-f", "-c", "sublimetext", - "run", - "--target", - "upload" - ], - "name": "Upload" - }, - { - "cmd": - [ - "platformio", - "-f", "-c", "sublimetext", - "run", - "--target", - "program" - ], - "name": "Upload using Programmer" - }, - { - "cmd": - [ - "platformio", - "-f", "-c", "sublimetext", - "run", - "--target", - "uploadfs" - ], - "name": "Upload SPIFFS image" - }, - { - "cmd": - [ - "platformio", - "-f", "-c", "sublimetext", - "update" - ], - "name": "Update platforms and libraries" - } - ], - "working_dir": "${project_path:${folder}}", - "selector": "source.c, source.c++", - "path": "{{env_path}}" - } - ], - "folders": - [ - { - "path": "." - } - ], - "settings": - { - "sublimegdb_workingdir": "{{project_dir}}", - "sublimegdb_exec_cmd": "-exec-continue", - "sublimegdb_commandline": "{{platformio_path}} -f -c sublimetext debug --interface=gdb --interpreter=mi -x .pioinit" - - } -} diff --git a/platformio/ide/tpls/vim/.clang_complete.tpl b/platformio/ide/tpls/vim/.clang_complete.tpl deleted file mode 100644 index bc09ec0d..00000000 --- a/platformio/ide/tpls/vim/.clang_complete.tpl +++ /dev/null @@ -1,6 +0,0 @@ -% for include in includes: --I{{include}} -% end -% for define in defines: --D{{!define}} -% end \ No newline at end of file diff --git a/platformio/ide/tpls/vim/.gcc-flags.json.tpl b/platformio/ide/tpls/vim/.gcc-flags.json.tpl deleted file mode 100644 index 5af2ea3a..00000000 --- a/platformio/ide/tpls/vim/.gcc-flags.json.tpl +++ /dev/null @@ -1,8 +0,0 @@ -{ - "execPath": "{{ cxx_path.replace("\\", "/") }}", - "gccDefaultCFlags": "-fsyntax-only {{! cc_flags.replace(' -MMD ', ' ').replace('"', '\\"') }}", - "gccDefaultCppFlags": "-fsyntax-only {{! cxx_flags.replace(' -MMD ', ' ').replace('"', '\\"') }}", - "gccErrorLimit": 15, - "gccIncludePaths": "{{ ','.join(includes).replace("\\", "/") }}", - "gccSuppressWarnings": false -} diff --git a/platformio/ide/tpls/vim/.gitignore.tpl b/platformio/ide/tpls/vim/.gitignore.tpl deleted file mode 100644 index 5dac9f52..00000000 --- a/platformio/ide/tpls/vim/.gitignore.tpl +++ /dev/null @@ -1,4 +0,0 @@ -.pioenvs -.piolibdeps -.clang_complete -.gcc-flags.json diff --git a/platformio/ide/tpls/visualstudio/platformio.vcxproj.filters.tpl b/platformio/ide/tpls/visualstudio/platformio.vcxproj.filters.tpl deleted file mode 100644 index d66bb4be..00000000 --- a/platformio/ide/tpls/visualstudio/platformio.vcxproj.filters.tpl +++ /dev/null @@ -1,29 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;ino;pde - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;hm;inl;inc;xsd - - - - - - % for file in src_files: - - % if any([file.endswith(".%s" % e) for e in ("h", "hh", "hpp", "inc")]): - - Header Files - - % else: - - Source Files - - %end - - % end - diff --git a/platformio/ide/tpls/visualstudio/platformio.vcxproj.tpl b/platformio/ide/tpls/visualstudio/platformio.vcxproj.tpl deleted file mode 100644 index b27a7ab2..00000000 --- a/platformio/ide/tpls/visualstudio/platformio.vcxproj.tpl +++ /dev/null @@ -1,74 +0,0 @@ - - - - {{env_path}} - - - - Debug - Win32 - - - Release - Win32 - - - - {0FA9C3A8-452B-41EF-A418-9102B170F49F} - MakeFileProj - - - - Makefile - true - v120 - - - Makefile - false - v120 - - - - - - - - - - - - - platformio -f -c visualstudio run - platformio -f -c visualstudio run --target clean - {{!";".join(defines)}} - {{";".join(["$(HOMEDRIVE)$(HOMEPATH)%s" % i.replace(user_home_dir, "") if i.startswith(user_home_dir) else i for i in includes])}} - - - platformio run - platformio run --target clean - {{!";".join(defines)}} - {{";".join(["$(HOMEDRIVE)$(HOMEPATH)%s" % i.replace(user_home_dir, "") if i.startswith(user_home_dir) else i for i in includes])}} - - - - - - - - - - % for file in src_files: - - % if any([file.endswith(".%s" % e) for e in ("h", "hh", "hpp", "inc")]): - - Header Files - - % else: - - Source Files - - %end - - % end - diff --git a/platformio/ide/tpls/vscode/.gitignore.tpl b/platformio/ide/tpls/vscode/.gitignore.tpl deleted file mode 100644 index f39f7c9b..00000000 --- a/platformio/ide/tpls/vscode/.gitignore.tpl +++ /dev/null @@ -1,3 +0,0 @@ -.pioenvs -.piolibdeps -.vscode/c_cpp_properties.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 deleted file mode 100644 index 5fea5091..00000000 --- a/platformio/ide/tpls/vscode/.vscode/c_cpp_properties.json.tpl +++ /dev/null @@ -1,37 +0,0 @@ -{ - "configurations": [ - { -% import platform -% systype = platform.system().lower() -% if systype == "windows": - "name": "Win32", -% elif systype == "darwin": - "name": "Mac", -% else: - "name": "Linux", -% end - "includePath": [ -% for include in includes: - "{{include.replace('\\\\', '/').replace('\\', '/').replace('"', '\\"')}}", -% end - "" - ], - "browse": { - "limitSymbolsToIncludedHeaders": true, - "databaseFilename": "", - "path": [ -% for include in includes: - "{{include.replace('\\\\', '/').replace('\\', '/').replace('"', '\\"')}}", -% end - "" - ] - }, - "defines": [ -% for define in defines: - "{{!define.replace('"', '\\"')}}", -% end - "" - ] - } - ] -} \ No newline at end of file diff --git a/platformio/ide/tpls/vscode/.vscode/launch.json.tpl b/platformio/ide/tpls/vscode/.vscode/launch.json.tpl deleted file mode 100644 index 409c1b98..00000000 --- a/platformio/ide/tpls/vscode/.vscode/launch.json.tpl +++ /dev/null @@ -1,15 +0,0 @@ -% from os.path import dirname, join -{ - "version": "0.2.0", - "configurations": [ - { - "type": "gdb", - "request": "launch", - "cwd": "${workspaceRoot}", - "name": "PlatformIO Debugger", - "target": "{{prog_path.replace('\\\\', '/').replace('\\', '/').replace('"', '\\"')}}", - "gdbpath": "{{join(dirname(platformio_path), "piodebuggdb").replace('\\\\', '/').replace('\\', '/').replace('"', '\\"')}}", - "autorun": [ "source .pioinit" ] - } - ] -} \ No newline at end of file diff --git a/platformio/managers/core.py b/platformio/managers/core.py index abf8891e..4e124471 100644 --- a/platformio/managers/core.py +++ b/platformio/managers/core.py @@ -20,10 +20,12 @@ from os.path import join from platformio import __version__, exception, util from platformio.managers.package import PackageManager + CORE_PACKAGES = { - "contrib-piohome": ">=0.2.1,<2", - "pysite-pioplus": ">=0.4.2,<2", - "tool-pioplus": ">=0.10.6,<2", + "contrib-piohome": ">=0.2.1,<1", + "contrib-projecttpls": "<1", + "pysite-pioplus": ">=0.4.2,<1", + "tool-pioplus": ">=0.10.6,<1", "tool-unity": "~1.20302.1", "tool-scons": "~3.20501.2" } diff --git a/platformio/ide/__init__.py b/platformio/project/__init__.py similarity index 100% rename from platformio/ide/__init__.py rename to platformio/project/__init__.py diff --git a/platformio/project/config.py b/platformio/project/config.py new file mode 100644 index 00000000..d6fb7f7f --- /dev/null +++ b/platformio/project/config.py @@ -0,0 +1,183 @@ +# 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 os +import re +from os.path import isfile + +from configobj import ConfigObj + + +class ProjectConfig(object): + + INITIAL_COMMENT = """# PlatformIO Project Configuration File +# +# Build options: build flags, source filter +# Upload options: custom upload port, speed and extra flags +# Library options: dependencies, extra library storages +# Advanced options: extra scripting +# +# Please visit documentation for the other options and examples +# http://docs.platformio.org/page/projectconf.html +""" + + SEMICOLON_TO_SHARP_RE = re.compile(r"((^|\s+);)", re.M) + SHARP_TO_SEMICOLON_RE = re.compile(r"((^|\s+)#)", re.M) + STRIP_INLINE_COMMENT_RE = re.compile(r"(^|\s+)#.*", re.M) + MLOPTS_PRE_RE = re.compile(r"^([\w]+)(\s*=[ \t\r\f\v]*)(\n[ \t]+[^\n]+)+", + re.M) + MLOPTS_POST_RE = re.compile(r"^([\w]+)\s*=[ \t\r\f\v]*(''')([^\2]+)\2", + re.M) + VARTPL_RE = re.compile(r"\$\{([^\.\}]+)\.([^\}]+)\}") + + def __init__(self, path): + self.path = path + self._parser = ConfigObj( + self._load_lines(), + interpolation=False, + list_values=False, + raise_errors=True) + self._modified = False + + def _load_lines(self): + if not isfile(self.path): + return [] + content = "" + with open(self.path, "r") as fp: + content = fp.read() + # ConfigObj doesn't support semicolons + content = self.SEMICOLON_TO_SHARP_RE.sub(r"\2#", content) + # Convert Python's multi-lines to ConfigObj's + if "'''" not in content: + content = self.MLOPTS_PRE_RE.sub(self._re_sub_mloptspre_handler, + content) + return content.split("\n") + + @staticmethod + def _re_sub_mloptspre_handler(match): + name = match.group(1) + value = match.string[match.end(2):match.end(3)].strip() + return "%s = '''%s'''" % (name, value) + + def write(self): + if not self._modified: + return + self._parser.initial_comment = self.INITIAL_COMMENT.split("\n") + with open(self.path, "w") as fp: + self._parser.write(fp) + self._post_hooks() + + def _post_hooks(self): + with open(self.path, "r+") as fp: + content = fp.read() + fp.seek(0) + fp.truncate() + # ConfigObj doesn't support semicolons + content = self.SHARP_TO_SEMICOLON_RE.sub(r"\2;", content) + # convert ConfigObj's multi-lines to Python's + content = self.MLOPTS_POST_RE.sub(self._re_sub_mloptspost_handler, + content) + fp.write(content) + + @staticmethod + def _re_sub_mloptspost_handler(match): + name = match.group(1) + items = [i.strip() for i in match.group(3).split("\n") if i.strip()] + return "%s = \n %s" % (name, "\n ".join(items)) + + @property + def parser(self): + return self._parser + + def sections(self): + return self._parser.keys() + + def add_section(self, section): + self._parser[section] = {} + + def delete_section(self, section): + if self.has_section(section): + self._modified = True + del self._parser[section] + + def has_section(self, section): + return section in self._parser + + def options(self, section): + return self._parser[section] + + def items(self, section): + items = [] + for option in self.options(section): + items.append((option, self.get(section, option))) + return items + + def get(self, section, option): + value = self._parser[section][option] + if "${" in value and "}" in value: + value = self.VARTPL_RE.sub(self._re_sub_vartpl_handler, value) + # make a list from multi-lie values or which are separated via ", " + for separator in ("\n", ", "): + if separator not in value: + return value + result = [] + for line in value.split(separator): + if "#" in line: + line = self.STRIP_INLINE_COMMENT_RE.sub("", line) + line = line.strip() + if line: + result.append(line) + return result + + def _re_sub_vartpl_handler(self, match): + section, option = match.group(1), match.group(2) + if section == "env" and not self.has_section(section): + return os.getenv(option) + return self.get(section, option) + + def set(self, section, option, value): + if not self.has_section(section): + self.add_section(section) + if self._parser[section].get(option) != value: + self._modified = True + self._parser[section][option] = value + + def get_env_names(self): + return [s[4:] for s in self.sections() if s.startswith("env:")] + + def env_get(self, name, option, default=None): + section = "env:%s" % name + if self.has_section(section) and option in self._parser[section]: + return self.get(section, option) + return default + + def env_update(self, name, options): + for option, value in options: + self.set("env:%s" % name, option, value) + return True + + def env_replace(self, name, options): + self.delete_section("env:%s" % name) + return self.env_update(name, options) + + def dump_all_options(self): + result = {} + for section in self.sections(): + if not section.startswith("env:"): + continue + for option in self.options(section): + if option not in result: + result[option] = [] + result[option].append(self.get(section, option)) + return result diff --git a/platformio/project/generator.py b/platformio/project/generator.py new file mode 100644 index 00000000..3aab399f --- /dev/null +++ b/platformio/project/generator.py @@ -0,0 +1,279 @@ +# 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 os +import re +from os.path import (abspath, basename, dirname, expanduser, isdir, isfile, + join, relpath) + +from platformio import app, exception, util +from platformio.managers.platform import PlatformManager +from platformio.project.config import ProjectConfig +from platformio.project.template import ProjectTemplateFactory + + +class ProjectGenerator(object): + + CONFIG_NAME = "platformio.ini" + + def __init__(self, project_dir, options=None): + self.project_dir = project_dir + self.options = options or {} + + self._project_lib_dir = None + self._project_src_dir = None + + # Will be set to the first used env name + # Can be used later for IDE Generator + self._main_env_name = None + + self.project_config = self.init_config() + + def init_config(self): + config = ProjectConfig(join(self.project_dir, self.CONFIG_NAME)) + pm = PlatformManager() + env_prefix = str(self.options['env_prefix'] or "") + + for bid in self.options['boards']: + env_name = "%s%s" % (env_prefix, bid) + board_config = pm.board_config(bid, self.options['platform']) + env_options = [("platform", self.options['platform'] + or board_config['platform'])] + board_frameworks = board_config.get("frameworks", []) + env_framework = self.options['framework'] + if env_framework is None and board_frameworks: + env_framework = board_frameworks[0] + if env_framework and env_framework not in board_frameworks: + raise exception.PlatformioException( + "Board `%s` is not compatible with framework %s" % + (bid, env_framework)) + if env_framework: + env_options.append(("framework", env_framework)) + env_options.append(("board", bid)) + + # extra env options + for item in self.options['env_options']: + _name, _value = item.split("=", 1) + env_options.append((_name.strip(), _value.strip())) + + # FIXME: Check [platformio] -> env_default + if not self._main_env_name: + self._main_env_name = env_name + + config.env_update(env_name, env_options) + + if not self._main_env_name: + env_names = config.get_env_names() + if env_names: + self._main_env_name = env_names[0] + + return config + + @staticmethod + def get_supported_ide(): + return sorted([ + key[4:] for key in ProjectTemplateFactory.get_templates() + if key.startswith("ide.") + ]) + + @staticmethod + def get_supported_vcs(): + return sorted([ + key[4:] for key in ProjectTemplateFactory.get_templates() + if key.startswith("vcs.") + ]) + + @staticmethod + def get_supported_ci(): + return sorted([ + key[3:] for key in ProjectTemplateFactory.get_templates() + if key.startswith("ci.") + ]) + + @staticmethod + def fix_os_path(path): + return (re.sub(r"[\\]+", '\\' * 4, path) + if "windows" in util.get_systype() else path) + + def get_src_files(self): + assert self._project_src_dir + result = [] + with util.cd(self.project_dir): + for root, _, files in os.walk(self._project_src_dir): + for f in files: + result.append(relpath(join(root, f))) + + def generate(self): + lib_dir, src_dir = self._init_file_structure() + self._project_lib_dir = lib_dir + self._project_src_dir = src_dir + + self._init_lib_readme(lib_dir) + + if self.options['template']: + self._process_user_template(self.options['template'], + self.options['template_vars']) + + self.project_config.write() + + if self.options['vcs']: + self._process_vcs_template(self.options['vcs']) + if self.options['ci']: + self._process_ci_template(self.options['ci']) + if self.options['ide']: + self._process_ide_template(self.options['ide']) + + def _init_file_structure(self): + with util.cd(self.project_dir): + result = (util.get_projectlib_dir(), util.get_projectsrc_dir()) + for d in result: + if not isdir(d): + os.makedirs(d) + return result + + def _process_user_template(self, name, variables): + pt = ProjectTemplateFactory.new("src.%s" % name, self.project_config) + for variable in variables: + assert "=" in variable, \ + "Template Variable format is `name=value` pair" + pt.assign(*variable.split("=", 1)) + + assert pt.is_compatible(raise_errors=True) + assert pt.validate_variables() + + for location, content in pt.render(): + self.write_content(location, content) + + return True + + def _process_vcs_template(self, name): + pt = ProjectTemplateFactory.new("vcs.%s" % name, self.project_config) + assert pt.is_compatible(raise_errors=True) + for location, content in pt.render(): + self.write_content(location, content) + return True + + def _process_ci_template(self, name): + pt = ProjectTemplateFactory.new("ci.%s" % name, self.project_config) + assert pt.is_compatible(raise_errors=True) + for location, content in pt.render(): + self.write_content(location, content) + return True + + def _process_ide_template(self, ide): + if not self._main_env_name: + raise exception.BoardNotDefined() + + pt = ProjectTemplateFactory.new("ide.%s" % ide, self.project_config) + + # system + pt.assign("systype", util.get_systype()) + pt.assign("env_pathsep", os.pathsep) + pt.assign("env_path", self.fix_os_path(os.getenv("PATH"))) + pt.assign("user_home_dir", abspath(expanduser("~"))) + pt.assign("platformio_path", + self.fix_os_path(util.where_is_program("platformio"))) + # project + pt.assign("project_name", basename(self.project_dir)) + pt.assign("project_dir", self.project_dir) + pt.assign("project_src_dir", self._project_src_dir) + pt.assign("src_files", self.get_src_files()) + + # project build environment + for name, value in self._dump_build_env(self._main_env_name).items(): + pt.assign(name, value) + + assert pt.is_compatible(raise_errors=True) + assert pt.validate_variables() + + for location, content in pt.render(): + self.write_content(location, content) + + return True + + def _dump_build_env(self, env_name): + data = {"defines": [], "includes": [], "cxx_path": None} + cmd = [util.get_pythonexe_path(), "-m", "platformio", "-f"] + if app.get_session_var("caller_id"): + cmd.extend(["-c", app.get_session_var("caller_id")]) + cmd.extend(["run", "-t", "idedata", "-e", env_name]) + cmd.extend(["-d", self.project_dir]) + result = util.exec_command(cmd) + + if result['returncode'] != 0 or '"includes":' not in result['out']: + raise exception.PlatformioException( + "\n".join([result['out'], result['err']])) + + for line in result['out'].split("\n"): + line = line.strip() + if line.startswith('{"') and '"cxx_path"' in line: + data = json.loads(line[:line.rindex("}") + 1]) + return data + + def write_content(self, location, content): + for name in ("project_dir", "lib_dir", "src_dir"): + pattern = "%%%s%%" % name + if pattern not in location: + continue + location = location.replace(pattern, self.project_dir + if name == "project_dir" else getattr( + self, "_project_%s" % name)) + if not isdir(dirname(location)): + os.makedirs(dirname(location)) + with open(join(location), "w") as fp: + fp.write(content.encode("utf8")) + + @staticmethod + def _init_lib_readme(lib_dir): + if isfile(join(lib_dir, "readme.txt")): + return + with open(join(lib_dir, "readme.txt"), "w") as f: + f.write( + """This directory is intended for the project specific (private) libraries. +PlatformIO will compile them to static libraries and link to executable file. + +The source code of each library should be placed in separate directory, like +"lib/private_lib/[here are source files]". + +For example, see how can be organized `Foo` and `Bar` libraries: + +|--lib +| |--Bar +| | |--docs +| | |--examples +| | |--src +| | |- Bar.c +| | |- Bar.h +| |--Foo +| | |- Foo.c +| | |- Foo.h +| |- readme.txt --> THIS FILE +|- platformio.ini +|--src + |- main.cpp + +Then in `src/main.cpp` you should use: + +#include +#include + +// rest H/C/CPP code + +PlatformIO will find your libraries automatically, configure preprocessor's +include paths and build them. + +More information about PlatformIO Library Dependency Finder +- http://docs.platformio.org/page/librarymanager/ldf.html +""") diff --git a/platformio/project/template.py b/platformio/project/template.py new file mode 100644 index 00000000..9704bae4 --- /dev/null +++ b/platformio/project/template.py @@ -0,0 +1,391 @@ +# 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 inspect +import os +from imp import load_source +from os.path import dirname, isdir, isfile, join, relpath, sep + +import bottle + +from platformio import exception, util +from platformio.managers.core import get_core_package_dir + + +class ProjectTemplateFactory(object): + + MANIFEST_NAME = "template.py" + + @classmethod + @util.memoized + def get_templates(cls): + pkg_dir = get_core_package_dir("contrib-projecttpls") + assert pkg_dir + items = {} + for root, _, _ in os.walk(pkg_dir): + if isfile(join(root, cls.MANIFEST_NAME)): + key = relpath(root, pkg_dir).replace(sep, ".") + items[key] = root + return items + + @staticmethod + def load_module(key, path): + module = None + try: + module = load_source( + "platformio.project.template.%s" % key.replace(".", "_"), path) + except ImportError: + raise exception.UnknownProjectTemplate(key) + return module + + @classmethod + def new(cls, key, project_config): + if key not in cls.get_templates(): + raise exception.UnknownProjectTemplate(key) + template_py = join(cls.get_templates()[key], cls.MANIFEST_NAME) + for _, _class in inspect.getmembers( + cls.load_module(key, template_py), inspect.isclass): + if issubclass(_class, ProjectTemplateBase): + return _class(project_config) + + raise exception.UnknownProjectTemplate(key) + + +class ProjectTemplateBase(object): + + TITLE = None + DESCRIPTION = None + + COMPATIBLE_PLATFORMS = None + COMPATIBLE_BOARDS = None + COMPATIBLE_FRAMEWORKS = None + + VARIABLES = None + CONTENTS = None + + def __init__(self, project_config): + self.project_config = project_config + self.project_dir = dirname(project_config.path) + + def get_title(self): + return self.TITLE or self.__class__.__name__ + + def get_description(self): + return self.DESCRIPTION or self.get_title() + + def get_compatible_platforms(self): + return self.COMPATIBLE_PLATFORMS or [] + + def get_compatible_boards(self): + return self.COMPATIBLE_BOARDS or [] + + def get_compatible_frameworks(self): + return self.COMPATIBLE_FRAMEWORKS or [] + + def get_variables(self): + return self.VARIABLES or [] + + def get_contents(self): + return self.CONTENTS or [] + + def assign(self, name, value): + found = False + for var in self.get_variables(): + if var.name == name: + var.set_value(value) + found = True + if not found: + raise exception.UnknownProjectTplVar(name) + + def is_compatible(self, raise_errors=False): + options = self.project_config.dump_all_options() + name_candidates = dict( + platform=set(self.get_compatible_platforms()), + board=set(self.get_compatible_boards()), + framework=set(self.get_compatible_frameworks())) + for name, candidates in name_candidates.items(): + if not candidates: + continue + diff = set(options.get(name, [])) - candidates + if name not in options or diff: + if raise_errors: + raise exception.IncompatbileProjectTemplate( + self.get_title(), name, ", ".join(diff), + ", ".join(candidates)) + return False + return True + + def validate_variables(self): + return all([v.validate() for v in self.get_variables()]) + + def render(self): + items = [] + data = dict(__project_config=self.project_config) + data.update({v.name: v.get_value() for v in self.get_variables()}) + for item in self.get_contents(): + result = self.render_content(item, data) + if result: + items.append(result) + return items + + @staticmethod + def render_content(item, data): + return (item.location, item.render(data)) + + +# +# Template Contents +# + + +class ProjectTplContentBase(object): + + def __init__(self, content, location): + self.content = content + self.location = location + + def render(self, data): + content = self.content + if isfile(content): + with open(content) as fp: + content = fp.read() + return bottle.template(self.content, **data) + + +class ProjectTplRootContent(ProjectTplContentBase): + + def __init__(self, content, location): + super(ProjectTplRootContent, + self).__init__(content, join("%project_dir%", location)) + + +class ProjectTplSrcContent(ProjectTplContentBase): + + def __init__(self, content, location): + super(ProjectTplSrcContent, self).__init__(content, + join("%src_dir%", location)) + + +class ProjectTplLibContent(ProjectTplContentBase): + + def __init__(self, content, location): + super(ProjectTplLibContent, self).__init__(content, + join("%lib_dir%", location)) + + +# +# Template Variables +# + + +class ProjectTplVarBase(object): + + TYPE = None + + def __init__(self, # pylint: disable=too-many-arguments + name, + title=None, + description=None, + default=None, + options=None): + self.name = name + self.title = title + self.description = description + self.default = default + self.options = options or {} + self._value = None + + @property + def type(self): + return self.TYPE + + def set_value(self, value): + self._value = value + + def get_value(self): + return self._value or self.default + + def validate(self): + try: + value = self.get_value() + if "min" in self.options: + assert value >= self.options['min'] + if "max" in self.options: + assert value <= self.options['max'] + if "enum" in self.options: + assert value in self.options['enum'] + except AssertionError: + raise exception.InvalidProjectTplVar(self.get_value(), self.name, + self.type, self.options) + + +class ProjectTplVarString(ProjectTplVarBase): + + TYPE = "string" + + def validate(self): + try: + self.set_value(str(self.get_value())) + super(ProjectTplVarString, self).validate() + except ValueError: + raise exception.InvalidProjectTplVar(self.get_value(), self.name, + self.type, self.options) + return True + + +class ProjectTplVarInteger(ProjectTplVarBase): + + TYPE = "integer" + + def validate(self): + try: + self.set_value(int(self.get_value())) + super(ProjectTplVarInteger, self).validate() + except ValueError: + raise exception.InvalidProjectTplVar(self.get_value(), self.name, + self.type, self.options) + return True + + +class ProjectTplVarNumber(ProjectTplVarBase): + + TYPE = "number" + + def validate(self): + try: + self.set_value(float(self.get_value())) + super(ProjectTplVarNumber, self).validate() + except ValueError: + raise exception.InvalidProjectTplVar(self.get_value(), self.name, + self.type, self.options) + return True + + +class ProjectTplVarBoolean(ProjectTplVarBase): + + TYPE = "boolean" + + def validate(self): + try: + value = self.get_value() + if not isinstance(value, bool): + value = str(value).lower() + assert value in ("1", "0", "true", "false", "yes", "no") + value = bool(value in ("1", "true", "yes")) + self.set_value(value) + super(ProjectTplVarBoolean, self).validate() + except (AssertionError, ValueError): + raise exception.InvalidProjectTplVar(self.get_value(), self.name, + self.type, self.options) + return True + + +class ProjectTplVarArray(ProjectTplVarBase): + + TYPE = "array" + + def validate(self): + try: + value = self.get_value() + if not isinstance(value, list): + value = str(value).split(", ") + self.set_value(value) + if "enum" in self.options: + assert set(self.options['enum']) >= set(value) + except (AssertionError, ValueError): + raise exception.InvalidProjectTplVar(self.get_value(), self.name, + self.type, self.options) + return True + + +class ProjectTplVarFilePath(ProjectTplVarBase): + + TYPE = "file" + + def validate(self): + if isfile(self.get_value()): + return True + raise exception.InvalidProjectTplVar(self.get_value(), self.name, + self.type, self.options) + + +class ProjectTplVarDirPath(ProjectTplVarBase): + + TYPE = "directory" + + def validate(self): + if isdir(self.get_value()): + return True + raise exception.InvalidProjectTplVar(self.get_value(), self.name, + self.type, self.options) + + +# +# Base IDE template +# + + +class IDEProjectTemplateBase(ProjectTemplateBase): + + VARIABLES = [ + # system + ProjectTplVarString("systype"), + ProjectTplVarString("env_pathsep"), + ProjectTplVarString("env_path"), + ProjectTplVarDirPath("user_home_dir"), + ProjectTplVarFilePath("platformio_path"), + + # project + ProjectTplVarString("project_name"), + ProjectTplVarDirPath("project_dir"), + ProjectTplVarDirPath("project_src_dir"), + ProjectTplVarArray("src_files"), + + # project build environment + ProjectTplVarString("prog_path"), + ProjectTplVarFilePath("cc_path"), + ProjectTplVarFilePath("cxx_path"), + ProjectTplVarFilePath("gdb_path"), + ProjectTplVarArray("defines"), + ProjectTplVarArray("libsource_dirs"), + ProjectTplVarArray("includes"), + ProjectTplVarString("cc_flags"), + ProjectTplVarString("cxx_flags") + ] + + def render_content(self, item, data): + dst_path = item.location.replace("%project_dir%", self.project_dir) + conds = [ + item.location.endswith(".gitignore"), + isfile(item.content), + isfile(dst_path) + ] + if not all(conds): + return super(IDEProjectTemplateBase, self).render_content( + item, data) + # merge .gitignore + assert isfile(item.content) + with open(item.content) as fp: + content = fp.read() + modified = False + default = [l.strip() for l in content.split("\n")] + with open(dst_path) as fp: + current = [l.strip() for l in fp.readlines()] + for d in default: + if d and d not in current: + modified = True + current.append(d) + if not modified: + return + return (item.location, "\n".join(current) + "\n") diff --git a/platformio/projectconftpl.ini b/platformio/projectconftpl.ini deleted file mode 100644 index dae59074..00000000 --- a/platformio/projectconftpl.ini +++ /dev/null @@ -1,9 +0,0 @@ -; PlatformIO Project Configuration File -; -; Build options: build flags, source filter -; Upload options: custom upload port, speed and extra flags -; Library options: dependencies, extra library storages -; Advanced options: extra scripting -; -; Please visit documentation for the other options and examples -; http://docs.platformio.org/page/projectconf.html diff --git a/setup.py b/setup.py index 116656cc..3a133a91 100644 --- a/setup.py +++ b/setup.py @@ -22,6 +22,7 @@ install_requires = [ "bottle<0.13", "click>=5,<6", "colorama", + "configobj", "lockfile>=0.9.1,<0.13", "pyserial>=3,<4,!=3.3", "requests>=2.4.0,<3", diff --git a/tests/commands/test_init.py b/tests/commands/test_init.py index 4b7c0a94..aef3cdc0 100644 --- a/tests/commands/test_init.py +++ b/tests/commands/test_init.py @@ -20,6 +20,10 @@ from platformio import exception, util from platformio.commands.boards import cli as cmd_boards from platformio.commands.init import cli as cmd_init +# test dynamic ${env.VAR} in option value +# test incompatible framework/platform for a board +# test dynamic vars in INI + def validate_pioproject(pioproject_dir): pioconf_path = join(pioproject_dir, "platformio.ini")