mirror of
https://github.com/platformio/platformio-core.git
synced 2025-07-30 01:57:13 +02:00
Merge branch 'feature/refactor-project-options' into develop
This commit is contained in:
@ -21,7 +21,7 @@ matrix:
|
|||||||
install:
|
install:
|
||||||
- git submodule update --init --recursive
|
- git submodule update --init --recursive
|
||||||
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then curl -fsSL https://bootstrap.pypa.io/get-pip.py | sudo python; fi
|
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then curl -fsSL https://bootstrap.pypa.io/get-pip.py | sudo python; fi
|
||||||
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then sudo pip install "tox==3.0.0"; else pip install -U tox; fi
|
- pip install -U tox
|
||||||
|
|
||||||
# ChipKIT issue: install 32-bit support for GCC PIC32
|
# ChipKIT issue: install 32-bit support for GCC PIC32
|
||||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install libc6-i386; fi
|
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install libc6-i386; fi
|
||||||
|
15
.vscode/settings.json
vendored
15
.vscode/settings.json
vendored
@ -1,15 +0,0 @@
|
|||||||
{
|
|
||||||
"python.pythonPath": "${workspaceRoot}/.tox/develop/bin/python",
|
|
||||||
"python.formatting.provider": "yapf",
|
|
||||||
"files.exclude": {
|
|
||||||
"**/*.pyc": true,
|
|
||||||
"*.egg-info": true,
|
|
||||||
".cache": true,
|
|
||||||
"build": true,
|
|
||||||
"dist": true
|
|
||||||
},
|
|
||||||
"editor.rulers": [79],
|
|
||||||
"restructuredtext.builtDocumentationPath": "${workspaceRoot}/docs/_build/html",
|
|
||||||
"restructuredtext.confPath": "${workspaceRoot}/docs",
|
|
||||||
"restructuredtext.linter.executablePath": "${workspaceRoot}/.tox/docs/bin/restructuredtext-lint"
|
|
||||||
}
|
|
2
Makefile
2
Makefile
@ -10,7 +10,7 @@ yapf:
|
|||||||
yapf --recursive --in-place platformio/
|
yapf --recursive --in-place platformio/
|
||||||
|
|
||||||
test:
|
test:
|
||||||
py.test -v -s -n 3 --dist=loadscope tests --ignore tests/test_examples.py --ignore tests/test_pkgmanifest.py
|
py.test --verbose --capture=no --exitfirst -n 3 --dist=loadscope tests --ignore tests/test_examples.py --ignore tests/test_pkgmanifest.py
|
||||||
|
|
||||||
before-commit: isort yapf lint test
|
before-commit: isort yapf lint test
|
||||||
|
|
||||||
|
2
examples
2
examples
Submodule examples updated: 45ec933e28...89963fed9e
@ -16,7 +16,7 @@ import base64
|
|||||||
import json
|
import json
|
||||||
import sys
|
import sys
|
||||||
from os import environ
|
from os import environ
|
||||||
from os.path import expanduser, join
|
from os.path import join
|
||||||
from time import time
|
from time import time
|
||||||
|
|
||||||
from SCons.Script import ARGUMENTS # pylint: disable=import-error
|
from SCons.Script import ARGUMENTS # pylint: disable=import-error
|
||||||
@ -33,76 +33,29 @@ from platformio import util
|
|||||||
from platformio.compat import PY2, path_to_unicode
|
from platformio.compat import PY2, path_to_unicode
|
||||||
from platformio.proc import get_pythonexe_path
|
from platformio.proc import get_pythonexe_path
|
||||||
from platformio.project import helpers as project_helpers
|
from platformio.project import helpers as project_helpers
|
||||||
from platformio.project.config import ProjectConfig
|
|
||||||
|
|
||||||
AllowSubstExceptions(NameError)
|
AllowSubstExceptions(NameError)
|
||||||
|
|
||||||
# allow common variables from INI file
|
# append CLI arguments to build environment
|
||||||
commonvars = Variables(None)
|
clivars = Variables(None)
|
||||||
commonvars.AddVariables(
|
clivars.AddVariables(
|
||||||
("PLATFORM_MANIFEST",),
|
("PLATFORM_MANIFEST",),
|
||||||
("BUILD_SCRIPT",),
|
("BUILD_SCRIPT",),
|
||||||
("EXTRA_SCRIPTS",),
|
("PROJECT_CONFIG",),
|
||||||
("PIOENV",),
|
("PIOENV",),
|
||||||
("PIOTEST",),
|
("PIOTEST",),
|
||||||
("PIOPLATFORM",),
|
("UPLOAD_PORT",)
|
||||||
("PIOFRAMEWORK",),
|
|
||||||
|
|
||||||
# build options
|
|
||||||
("BUILD_FLAGS",),
|
|
||||||
("SRC_BUILD_FLAGS",),
|
|
||||||
("BUILD_UNFLAGS",),
|
|
||||||
("SRC_FILTER",),
|
|
||||||
|
|
||||||
# library options
|
|
||||||
("LIB_LDF_MODE",),
|
|
||||||
("LIB_COMPAT_MODE",),
|
|
||||||
("LIB_DEPS",),
|
|
||||||
("LIB_IGNORE",),
|
|
||||||
("LIB_EXTRA_DIRS",),
|
|
||||||
("LIB_ARCHIVE",),
|
|
||||||
|
|
||||||
# board options
|
|
||||||
("BOARD",),
|
|
||||||
# deprecated options, use board_{object.path} instead
|
|
||||||
("BOARD_MCU",),
|
|
||||||
("BOARD_F_CPU",),
|
|
||||||
("BOARD_F_FLASH",),
|
|
||||||
("BOARD_FLASH_MODE",),
|
|
||||||
# end of deprecated options
|
|
||||||
|
|
||||||
# upload options
|
|
||||||
("UPLOAD_PORT",),
|
|
||||||
("UPLOAD_PROTOCOL",),
|
|
||||||
("UPLOAD_SPEED",),
|
|
||||||
("UPLOAD_FLAGS",),
|
|
||||||
("UPLOAD_RESETMETHOD",),
|
|
||||||
|
|
||||||
# test options
|
|
||||||
("TEST_BUILD_PROJECT_SRC",),
|
|
||||||
|
|
||||||
# debug options
|
|
||||||
("DEBUG_TOOL",),
|
|
||||||
("DEBUG_SVD_PATH",),
|
|
||||||
|
|
||||||
) # yapf: disable
|
) # yapf: disable
|
||||||
|
|
||||||
MULTILINE_VARS = [
|
|
||||||
"EXTRA_SCRIPTS", "PIOFRAMEWORK", "BUILD_FLAGS", "SRC_BUILD_FLAGS",
|
|
||||||
"BUILD_UNFLAGS", "UPLOAD_FLAGS", "SRC_FILTER", "LIB_DEPS", "LIB_IGNORE",
|
|
||||||
"LIB_EXTRA_DIRS"
|
|
||||||
]
|
|
||||||
|
|
||||||
DEFAULT_ENV_OPTIONS = dict(
|
DEFAULT_ENV_OPTIONS = dict(
|
||||||
tools=[
|
tools=[
|
||||||
"ar", "gas", "gcc", "g++", "gnulink", "platformio", "pioplatform",
|
"ar", "gas", "gcc", "g++", "gnulink", "platformio", "pioplatform",
|
||||||
"piowinhooks", "piolib", "pioupload", "piomisc", "pioide"
|
"pioproject", "piowinhooks", "piolib", "pioupload", "piomisc", "pioide"
|
||||||
], # yapf: disable
|
],
|
||||||
toolpath=[join(util.get_source_dir(), "builder", "tools")],
|
toolpath=[join(util.get_source_dir(), "builder", "tools")],
|
||||||
variables=commonvars,
|
variables=clivars,
|
||||||
|
|
||||||
# Propagating External Environment
|
# Propagating External Environment
|
||||||
PIOVARIABLES=list(commonvars.keys()),
|
|
||||||
ENV=environ,
|
ENV=environ,
|
||||||
UNIX_TIME=int(time()),
|
UNIX_TIME=int(time()),
|
||||||
PROJECT_DIR=project_helpers.get_project_dir(),
|
PROJECT_DIR=project_helpers.get_project_dir(),
|
||||||
@ -136,38 +89,22 @@ if not int(ARGUMENTS.get("PIOVERBOSE", 0)):
|
|||||||
|
|
||||||
env = DefaultEnvironment(**DEFAULT_ENV_OPTIONS)
|
env = DefaultEnvironment(**DEFAULT_ENV_OPTIONS)
|
||||||
|
|
||||||
# decode common variables
|
|
||||||
for k in list(commonvars.keys()):
|
|
||||||
if k in env:
|
|
||||||
env[k] = base64.b64decode(env[k])
|
|
||||||
if isinstance(env[k], bytes):
|
|
||||||
env[k] = env[k].decode()
|
|
||||||
if k in MULTILINE_VARS:
|
|
||||||
env[k] = ProjectConfig.parse_multi_values(env[k])
|
|
||||||
|
|
||||||
if env.GetOption('clean'):
|
if env.GetOption('clean'):
|
||||||
env.PioClean(env.subst("$BUILD_DIR"))
|
env.PioClean(env.subst("$BUILD_DIR"))
|
||||||
env.Exit(0)
|
env.Exit(0)
|
||||||
elif not int(ARGUMENTS.get("PIOVERBOSE", 0)):
|
elif not int(ARGUMENTS.get("PIOVERBOSE", 0)):
|
||||||
print("Verbose mode can be enabled via `-v, --verbose` option")
|
print("Verbose mode can be enabled via `-v, --verbose` option")
|
||||||
|
|
||||||
# Handle custom variables from system environment
|
# Load variables from CLI
|
||||||
for var in ("BUILD_FLAGS", "SRC_BUILD_FLAGS", "SRC_FILTER", "EXTRA_SCRIPTS",
|
for key in list(clivars.keys()):
|
||||||
"UPLOAD_PORT", "UPLOAD_FLAGS", "LIB_EXTRA_DIRS"):
|
if key in env:
|
||||||
k = "PLATFORMIO_%s" % var
|
env[key] = base64.b64decode(env[key])
|
||||||
if k not in environ:
|
if isinstance(env[key], bytes):
|
||||||
continue
|
env[key] = env[key].decode()
|
||||||
if var in ("UPLOAD_PORT", ):
|
|
||||||
env[var] = environ.get(k)
|
|
||||||
continue
|
|
||||||
env.Append(**{var: ProjectConfig.parse_multi_values(environ.get(k))})
|
|
||||||
|
|
||||||
env.Prepend(LIBSOURCE_DIRS=env.get("LIB_EXTRA_DIRS", []))
|
env.GetProjectConfig().validate([env['PIOENV']], silent=True)
|
||||||
env['LIBSOURCE_DIRS'] = [
|
env.LoadProjectOptions()
|
||||||
expanduser(d) if d.startswith("~") else d for d in env['LIBSOURCE_DIRS']
|
env.LoadPioPlatform()
|
||||||
]
|
|
||||||
|
|
||||||
env.LoadPioPlatform(commonvars)
|
|
||||||
|
|
||||||
env.SConscriptChdir(0)
|
env.SConscriptChdir(0)
|
||||||
env.SConsignFile(
|
env.SConsignFile(
|
||||||
|
@ -113,7 +113,7 @@ def _dump_defines(env):
|
|||||||
|
|
||||||
|
|
||||||
def _get_svd_path(env):
|
def _get_svd_path(env):
|
||||||
svd_path = env.subst("$DEBUG_SVD_PATH")
|
svd_path = env.GetProjectOption("debug_svd_path")
|
||||||
if svd_path:
|
if svd_path:
|
||||||
return abspath(svd_path)
|
return abspath(svd_path)
|
||||||
|
|
||||||
@ -139,8 +139,7 @@ def DumpIDEData(env, projenv):
|
|||||||
LINTCXXCOM = "$CXXFLAGS $CCFLAGS $CPPFLAGS"
|
LINTCXXCOM = "$CXXFLAGS $CCFLAGS $CPPFLAGS"
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
"libsource_dirs":
|
"libsource_dirs": [env.subst(l) for l in env.GetLibSourceDirs()],
|
||||||
[env.subst(l) for l in env.get("LIBSOURCE_DIRS", [])],
|
|
||||||
"defines":
|
"defines":
|
||||||
_dump_defines(env),
|
_dump_defines(env),
|
||||||
"includes":
|
"includes":
|
||||||
|
@ -23,8 +23,8 @@ import os
|
|||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
from glob import glob
|
from glob import glob
|
||||||
from os.path import (basename, commonprefix, dirname, isdir, isfile, join,
|
from os.path import (basename, commonprefix, dirname, expanduser, isdir,
|
||||||
realpath, sep)
|
isfile, join, realpath, sep)
|
||||||
|
|
||||||
import SCons.Scanner # pylint: disable=import-error
|
import SCons.Scanner # pylint: disable=import-error
|
||||||
from SCons.Script import ARGUMENTS # pylint: disable=import-error
|
from SCons.Script import ARGUMENTS # pylint: disable=import-error
|
||||||
@ -207,17 +207,18 @@ class LibBuilderBase(object):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def lib_archive(self):
|
def lib_archive(self):
|
||||||
return self.env.get("LIB_ARCHIVE", "") != "false"
|
return self.env.GetProjectOption("lib_archive", True)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def lib_ldf_mode(self):
|
def lib_ldf_mode(self):
|
||||||
return self.validate_ldf_mode(
|
return self.validate_ldf_mode(
|
||||||
self.env.get("LIB_LDF_MODE", self.LDF_MODE_DEFAULT))
|
self.env.GetProjectOption("lib_ldf_mode", self.LDF_MODE_DEFAULT))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def lib_compat_mode(self):
|
def lib_compat_mode(self):
|
||||||
return self.validate_compat_mode(
|
return self.validate_compat_mode(
|
||||||
self.env.get("LIB_COMPAT_MODE", self.COMPAT_MODE_DEFAULT))
|
self.env.GetProjectOption("lib_compat_mode",
|
||||||
|
self.COMPAT_MODE_DEFAULT))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def depbuilders(self):
|
def depbuilders(self):
|
||||||
@ -867,7 +868,7 @@ class ProjectAsLibBuilder(LibBuilderBase):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def process_dependencies(self): # pylint: disable=too-many-branches
|
def process_dependencies(self): # pylint: disable=too-many-branches
|
||||||
uris = self.env.get("LIB_DEPS", [])
|
uris = self.env.GetProjectOption("lib_deps", [])
|
||||||
if not uris:
|
if not uris:
|
||||||
return
|
return
|
||||||
storage_dirs = []
|
storage_dirs = []
|
||||||
@ -907,6 +908,14 @@ class ProjectAsLibBuilder(LibBuilderBase):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def GetLibSourceDirs(env):
|
||||||
|
items = env.GetProjectOption("lib_extra_dirs", [])
|
||||||
|
items.extend(env['LIBSOURCE_DIRS'])
|
||||||
|
return [
|
||||||
|
expanduser(item) if item.startswith("~") else item for item in items
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
def GetLibBuilders(env): # pylint: disable=too-many-branches
|
def GetLibBuilders(env): # pylint: disable=too-many-branches
|
||||||
|
|
||||||
if "__PIO_LIB_BUILDERS" in DefaultEnvironment():
|
if "__PIO_LIB_BUILDERS" in DefaultEnvironment():
|
||||||
@ -920,7 +929,7 @@ def GetLibBuilders(env): # pylint: disable=too-many-branches
|
|||||||
|
|
||||||
def _check_lib_builder(lb):
|
def _check_lib_builder(lb):
|
||||||
compat_mode = lb.lib_compat_mode
|
compat_mode = lb.lib_compat_mode
|
||||||
if lb.name in env.get("LIB_IGNORE", []):
|
if lb.name in env.GetProjectOption("lib_ignore", []):
|
||||||
if verbose:
|
if verbose:
|
||||||
sys.stderr.write("Ignored library %s\n" % lb.path)
|
sys.stderr.write("Ignored library %s\n" % lb.path)
|
||||||
return None
|
return None
|
||||||
@ -939,7 +948,7 @@ def GetLibBuilders(env): # pylint: disable=too-many-branches
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
found_incompat = False
|
found_incompat = False
|
||||||
for libs_dir in env['LIBSOURCE_DIRS']:
|
for libs_dir in env.GetLibSourceDirs():
|
||||||
libs_dir = env.subst(libs_dir)
|
libs_dir = env.subst(libs_dir)
|
||||||
if not isdir(libs_dir):
|
if not isdir(libs_dir):
|
||||||
continue
|
continue
|
||||||
@ -1038,6 +1047,7 @@ def exists(_):
|
|||||||
|
|
||||||
|
|
||||||
def generate(env):
|
def generate(env):
|
||||||
|
env.AddMethod(GetLibSourceDirs)
|
||||||
env.AddMethod(GetLibBuilders)
|
env.AddMethod(GetLibBuilders)
|
||||||
env.AddMethod(ConfigureProjectLibBuilder)
|
env.AddMethod(ConfigureProjectLibBuilder)
|
||||||
return env
|
return env
|
||||||
|
@ -322,7 +322,7 @@ def ProcessTest(env):
|
|||||||
|
|
||||||
def GetExtraScripts(env, scope):
|
def GetExtraScripts(env, scope):
|
||||||
items = []
|
items = []
|
||||||
for item in env.get("EXTRA_SCRIPTS", []):
|
for item in env.GetProjectOption("extra_scripts", []):
|
||||||
if scope == "post" and ":" not in item:
|
if scope == "post" and ":" not in item:
|
||||||
items.append(item)
|
items.append(item)
|
||||||
elif item.startswith("%s:" % scope):
|
elif item.startswith("%s:" % scope):
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
|
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
import base64
|
|
||||||
import sys
|
import sys
|
||||||
from os.path import isdir, isfile, join
|
from os.path import isdir, isfile, join
|
||||||
|
|
||||||
@ -23,6 +22,7 @@ from SCons.Script import COMMAND_LINE_TARGETS # pylint: disable=import-error
|
|||||||
from platformio import exception, util
|
from platformio import exception, util
|
||||||
from platformio.compat import WINDOWS
|
from platformio.compat import WINDOWS
|
||||||
from platformio.managers.platform import PlatformFactory
|
from platformio.managers.platform import PlatformFactory
|
||||||
|
from platformio.project.config import ProjectOptions
|
||||||
|
|
||||||
# pylint: disable=too-many-branches, too-many-locals
|
# pylint: disable=too-many-branches, too-many-locals
|
||||||
|
|
||||||
@ -33,10 +33,10 @@ def initPioPlatform(name):
|
|||||||
|
|
||||||
|
|
||||||
def PioPlatform(env):
|
def PioPlatform(env):
|
||||||
variables = {}
|
variables = env.GetProjectOptions(as_dict=True)
|
||||||
for name in env['PIOVARIABLES']:
|
if "framework" in variables:
|
||||||
if name in env:
|
# support PIO Core 3.0 dev/platforms
|
||||||
variables[name.lower()] = env[name]
|
variables['pioframework'] = variables['framework']
|
||||||
p = initPioPlatform(env['PLATFORM_MANIFEST'])
|
p = initPioPlatform(env['PLATFORM_MANIFEST'])
|
||||||
p.configure_default_packages(variables, COMMAND_LINE_TARGETS)
|
p.configure_default_packages(variables, COMMAND_LINE_TARGETS)
|
||||||
return p
|
return p
|
||||||
@ -63,7 +63,7 @@ def GetFrameworkScript(env, framework):
|
|||||||
return script_path
|
return script_path
|
||||||
|
|
||||||
|
|
||||||
def LoadPioPlatform(env, variables):
|
def LoadPioPlatform(env):
|
||||||
p = env.PioPlatform()
|
p = env.PioPlatform()
|
||||||
installed_packages = p.get_installed_packages()
|
installed_packages = p.get_installed_packages()
|
||||||
|
|
||||||
@ -92,36 +92,25 @@ def LoadPioPlatform(env, variables):
|
|||||||
env.Prepend(LIBPATH=[join(p.get_dir(), "ldscripts")])
|
env.Prepend(LIBPATH=[join(p.get_dir(), "ldscripts")])
|
||||||
|
|
||||||
if "BOARD" not in env:
|
if "BOARD" not in env:
|
||||||
# handle _MCU and _F_CPU variables for AVR native
|
|
||||||
for key, value in variables.UnknownVariables().items():
|
|
||||||
if not key.startswith("BOARD_"):
|
|
||||||
continue
|
|
||||||
value = base64.b64decode(value)
|
|
||||||
if isinstance(value, bytes):
|
|
||||||
value = value.decode()
|
|
||||||
env.Replace(**{key.upper().replace("BUILD.", ""): value})
|
|
||||||
return
|
return
|
||||||
|
|
||||||
# update board manifest with a custom data
|
# update board manifest with overridden data from INI config
|
||||||
board_config = env.BoardConfig()
|
board_config = env.BoardConfig()
|
||||||
for key, value in variables.UnknownVariables().items():
|
for option, value in env.GetProjectOptions():
|
||||||
if not key.startswith("BOARD_"):
|
if option.startswith("board_"):
|
||||||
continue
|
board_config.update(option.lower()[6:], value)
|
||||||
value = base64.b64decode(value)
|
|
||||||
if isinstance(value, bytes):
|
|
||||||
value = value.decode()
|
|
||||||
board_config.update(key.lower()[6:], value)
|
|
||||||
|
|
||||||
# update default environment variables
|
# load default variables from board config
|
||||||
for key in list(variables.keys()):
|
for option_meta in ProjectOptions.values():
|
||||||
if key in env or \
|
if not option_meta.buildenvvar or option_meta.buildenvvar in env:
|
||||||
not any([key.startswith("BOARD_"), key.startswith("UPLOAD_")]):
|
|
||||||
continue
|
continue
|
||||||
_opt, _val = key.lower().split("_", 1)
|
data_path = (option_meta.name[6:]
|
||||||
if _opt == "board":
|
if option_meta.name.startswith("board_") else
|
||||||
_opt = "build"
|
option_meta.name.replace("_", "."))
|
||||||
if _val in board_config.get(_opt):
|
try:
|
||||||
env.Replace(**{key: board_config.get("%s.%s" % (_opt, _val))})
|
env[option_meta.buildenvvar] = board_config.get(data_path)
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
if "build.ldscript" in board_config:
|
if "build.ldscript" in board_config:
|
||||||
env.Replace(LDSCRIPT_PATH=board_config.get("build.ldscript"))
|
env.Replace(LDSCRIPT_PATH=board_config.get("build.ldscript"))
|
||||||
@ -165,7 +154,7 @@ def PrintConfiguration(env):
|
|||||||
|
|
||||||
data = [
|
data = [
|
||||||
"CURRENT(%s)" % board_config.get_debug_tool_name(
|
"CURRENT(%s)" % board_config.get_debug_tool_name(
|
||||||
env.subst("$DEBUG_TOOL"))
|
env.GetProjectOption("debug_tool"))
|
||||||
]
|
]
|
||||||
onboard = []
|
onboard = []
|
||||||
external = []
|
external = []
|
||||||
|
49
platformio/builder/tools/pioproject.py
Normal file
49
platformio/builder/tools/pioproject.py
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
# Copyright (c) 2014-present PlatformIO <contact@platformio.org>
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
from __future__ import absolute_import
|
||||||
|
|
||||||
|
from platformio.project.config import ProjectConfig, ProjectOptions
|
||||||
|
|
||||||
|
|
||||||
|
def GetProjectConfig(env):
|
||||||
|
return ProjectConfig.get_instance(env['PROJECT_CONFIG'])
|
||||||
|
|
||||||
|
|
||||||
|
def GetProjectOptions(env, as_dict=False):
|
||||||
|
return env.GetProjectConfig().items(env=env['PIOENV'], as_dict=as_dict)
|
||||||
|
|
||||||
|
|
||||||
|
def GetProjectOption(env, option, default=None):
|
||||||
|
return env.GetProjectConfig().get("env:" + env['PIOENV'], option, default)
|
||||||
|
|
||||||
|
|
||||||
|
def LoadProjectOptions(env):
|
||||||
|
for option, value in env.GetProjectOptions():
|
||||||
|
option_meta = ProjectOptions.get("env." + option)
|
||||||
|
if not option_meta or not option_meta.buildenvvar:
|
||||||
|
continue
|
||||||
|
env[option_meta.buildenvvar] = value
|
||||||
|
|
||||||
|
|
||||||
|
def exists(_):
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def generate(env):
|
||||||
|
env.AddMethod(GetProjectConfig)
|
||||||
|
env.AddMethod(GetProjectOptions)
|
||||||
|
env.AddMethod(GetProjectOption)
|
||||||
|
env.AddMethod(LoadProjectOptions)
|
||||||
|
return env
|
@ -163,22 +163,18 @@ def device_list( # pylint: disable=too-many-branches
|
|||||||
"--environment",
|
"--environment",
|
||||||
help="Load configuration from `platformio.ini` and specified environment")
|
help="Load configuration from `platformio.ini` and specified environment")
|
||||||
def device_monitor(**kwargs): # pylint: disable=too-many-branches
|
def device_monitor(**kwargs): # pylint: disable=too-many-branches
|
||||||
custom_monitor_flags = []
|
env_options = {}
|
||||||
try:
|
try:
|
||||||
env_options = get_project_options(kwargs['project_dir'],
|
env_options = get_project_options(kwargs['project_dir'],
|
||||||
kwargs['environment'])
|
kwargs['environment'])
|
||||||
if "monitor_flags" in env_options:
|
for k in ("port", "speed", "rts", "dtr"):
|
||||||
custom_monitor_flags = ProjectConfig.parse_multi_values(
|
k2 = "monitor_%s" % k
|
||||||
env_options['monitor_flags'])
|
if k == "speed":
|
||||||
if env_options:
|
k = "baud"
|
||||||
for k in ("port", "speed", "rts", "dtr"):
|
if kwargs[k] is None and k2 in env_options:
|
||||||
k2 = "monitor_%s" % k
|
kwargs[k] = env_options[k2]
|
||||||
if k == "speed":
|
if k != "port":
|
||||||
k = "baud"
|
kwargs[k] = int(kwargs[k])
|
||||||
if kwargs[k] is None and k2 in env_options:
|
|
||||||
kwargs[k] = env_options[k2]
|
|
||||||
if k != "port":
|
|
||||||
kwargs[k] = int(kwargs[k])
|
|
||||||
except exception.NotPlatformIOProject:
|
except exception.NotPlatformIOProject:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -187,12 +183,12 @@ def device_monitor(**kwargs): # pylint: disable=too-many-branches
|
|||||||
if len(ports) == 1:
|
if len(ports) == 1:
|
||||||
kwargs['port'] = ports[0]['port']
|
kwargs['port'] = ports[0]['port']
|
||||||
|
|
||||||
sys.argv = ["monitor"] + custom_monitor_flags
|
sys.argv = ["monitor"] + env_options.get("monitor_flags", [])
|
||||||
for k, v in kwargs.items():
|
for k, v in kwargs.items():
|
||||||
if k in ("port", "baud", "rts", "dtr", "environment", "project_dir"):
|
if k in ("port", "baud", "rts", "dtr", "environment", "project_dir"):
|
||||||
continue
|
continue
|
||||||
k = "--" + k.replace("_", "-")
|
k = "--" + k.replace("_", "-")
|
||||||
if k in custom_monitor_flags:
|
if k in env_options.get("monitor_flags", []):
|
||||||
continue
|
continue
|
||||||
if isinstance(v, bool):
|
if isinstance(v, bool):
|
||||||
if v:
|
if v:
|
||||||
|
@ -41,13 +41,11 @@ class ProjectRPC(object):
|
|||||||
def _get_project_data(project_dir):
|
def _get_project_data(project_dir):
|
||||||
data = {"boards": [], "envLibdepsDirs": [], "libExtraDirs": []}
|
data = {"boards": [], "envLibdepsDirs": [], "libExtraDirs": []}
|
||||||
config = ProjectConfig(join(project_dir, "platformio.ini"))
|
config = ProjectConfig(join(project_dir, "platformio.ini"))
|
||||||
config.validate(validate_options=False)
|
config.validate(silent=True)
|
||||||
libdeps_dir = get_project_libdeps_dir()
|
libdeps_dir = get_project_libdeps_dir()
|
||||||
|
|
||||||
if config.has_section("platformio") and \
|
data['libExtraDirs'].extend(
|
||||||
config.has_option("platformio", "lib_extra_dirs"):
|
config.get("platformio", "lib_extra_dirs", []))
|
||||||
data['libExtraDirs'].extend(
|
|
||||||
config.getlist("platformio", "lib_extra_dirs"))
|
|
||||||
|
|
||||||
for section in config.sections():
|
for section in config.sections():
|
||||||
if not section.startswith("env:"):
|
if not section.startswith("env:"):
|
||||||
@ -55,9 +53,8 @@ class ProjectRPC(object):
|
|||||||
data['envLibdepsDirs'].append(join(libdeps_dir, section[4:]))
|
data['envLibdepsDirs'].append(join(libdeps_dir, section[4:]))
|
||||||
if config.has_option(section, "board"):
|
if config.has_option(section, "board"):
|
||||||
data['boards'].append(config.get(section, "board"))
|
data['boards'].append(config.get(section, "board"))
|
||||||
if config.has_option(section, "lib_extra_dirs"):
|
data['libExtraDirs'].extend(
|
||||||
data['libExtraDirs'].extend(
|
config.get(section, "lib_extra_dirs", []))
|
||||||
config.getlist(section, "lib_extra_dirs"))
|
|
||||||
|
|
||||||
# skip non existing folders and resolve full path
|
# skip non existing folders and resolve full path
|
||||||
for key in ("envLibdepsDirs", "libExtraDirs"):
|
for key in ("envLibdepsDirs", "libExtraDirs"):
|
||||||
@ -232,11 +229,9 @@ class ProjectRPC(object):
|
|||||||
project_description = None
|
project_description = None
|
||||||
try:
|
try:
|
||||||
config = ProjectConfig(join(project_dir, "platformio.ini"))
|
config = ProjectConfig(join(project_dir, "platformio.ini"))
|
||||||
config.validate(validate_options=False)
|
config.validate(silent=True)
|
||||||
if config.has_section("platformio") and \
|
project_description = config.get("platformio",
|
||||||
config.has_option("platformio", "description"):
|
"description")
|
||||||
project_description = config.get(
|
|
||||||
"platformio", "description")
|
|
||||||
except exception.PlatformIOProjectException:
|
except exception.PlatformIOProjectException:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
@ -70,7 +70,6 @@ def cli(
|
|||||||
project_option,
|
project_option,
|
||||||
env_prefix,
|
env_prefix,
|
||||||
silent):
|
silent):
|
||||||
|
|
||||||
if not silent:
|
if not silent:
|
||||||
if project_dir == getcwd():
|
if project_dir == getcwd():
|
||||||
click.secho(
|
click.secho(
|
||||||
|
@ -109,9 +109,8 @@ def cli(ctx, **options):
|
|||||||
continue
|
continue
|
||||||
storage_dir = join(libdeps_dir, env)
|
storage_dir = join(libdeps_dir, env)
|
||||||
ctx.meta[CTX_META_STORAGE_DIRS_KEY].append(storage_dir)
|
ctx.meta[CTX_META_STORAGE_DIRS_KEY].append(storage_dir)
|
||||||
if config.has_option("env:" + env, "lib_deps"):
|
ctx.meta[CTX_META_STORAGE_LIBDEPS_KEY][storage_dir] = config.get(
|
||||||
ctx.meta[CTX_META_STORAGE_LIBDEPS_KEY][
|
"env:" + env, "lib_deps", [])
|
||||||
storage_dir] = config.getlist("env:" + env, "lib_deps")
|
|
||||||
|
|
||||||
|
|
||||||
@cli.command("install", short_help="Install library")
|
@cli.command("install", short_help="Install library")
|
||||||
@ -175,8 +174,7 @@ def lib_install( # pylint: disable=too-many-arguments
|
|||||||
if project_environments and env not in project_environments:
|
if project_environments and env not in project_environments:
|
||||||
continue
|
continue
|
||||||
config.expand_interpolations = False
|
config.expand_interpolations = False
|
||||||
lib_deps = (config.getlist("env:" + env, "lib_deps")
|
lib_deps = config.get("env:" + env, "lib_deps", [])
|
||||||
if config.has_option("env:" + env, "lib_deps") else [])
|
|
||||||
for library in libraries:
|
for library in libraries:
|
||||||
if library in lib_deps:
|
if library in lib_deps:
|
||||||
continue
|
continue
|
||||||
|
@ -1,352 +0,0 @@
|
|||||||
# Copyright (c) 2014-present PlatformIO <contact@platformio.org>
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
|
|
||||||
from os import getcwd, makedirs
|
|
||||||
from os.path import getmtime, isdir, isfile, join
|
|
||||||
from time import time
|
|
||||||
|
|
||||||
import click
|
|
||||||
|
|
||||||
from platformio import exception, telemetry, util
|
|
||||||
from platformio.commands.device import device_monitor as cmd_device_monitor
|
|
||||||
from platformio.commands.lib import (CTX_META_STORAGE_DIRS_KEY,
|
|
||||||
CTX_META_STORAGE_LIBDEPS_KEY)
|
|
||||||
from platformio.commands.lib import lib_install as cmd_lib_install
|
|
||||||
from platformio.commands.platform import \
|
|
||||||
platform_install as cmd_platform_install
|
|
||||||
from platformio.managers.platform import PlatformFactory
|
|
||||||
from platformio.project.config import ProjectConfig
|
|
||||||
from platformio.project.helpers import (
|
|
||||||
calculate_project_hash, find_project_dir_above, get_project_build_dir,
|
|
||||||
get_project_dir, get_project_libdeps_dir)
|
|
||||||
|
|
||||||
# pylint: disable=too-many-arguments,too-many-locals,too-many-branches
|
|
||||||
|
|
||||||
|
|
||||||
@click.command("run", short_help="Process project environments")
|
|
||||||
@click.option("-e", "--environment", multiple=True)
|
|
||||||
@click.option("-t", "--target", multiple=True)
|
|
||||||
@click.option("--upload-port")
|
|
||||||
@click.option(
|
|
||||||
"-d",
|
|
||||||
"--project-dir",
|
|
||||||
default=getcwd,
|
|
||||||
type=click.Path(
|
|
||||||
exists=True,
|
|
||||||
file_okay=True,
|
|
||||||
dir_okay=True,
|
|
||||||
writable=True,
|
|
||||||
resolve_path=True))
|
|
||||||
@click.option(
|
|
||||||
"-c",
|
|
||||||
"--project-conf",
|
|
||||||
type=click.Path(
|
|
||||||
exists=True,
|
|
||||||
file_okay=True,
|
|
||||||
dir_okay=False,
|
|
||||||
readable=True,
|
|
||||||
resolve_path=True))
|
|
||||||
@click.option("-s", "--silent", is_flag=True)
|
|
||||||
@click.option("-v", "--verbose", is_flag=True)
|
|
||||||
@click.option("--disable-auto-clean", is_flag=True)
|
|
||||||
@click.pass_context
|
|
||||||
def cli(ctx, environment, target, upload_port, project_dir, project_conf,
|
|
||||||
silent, verbose, disable_auto_clean):
|
|
||||||
# find project directory on upper level
|
|
||||||
if isfile(project_dir):
|
|
||||||
project_dir = find_project_dir_above(project_dir)
|
|
||||||
|
|
||||||
with util.cd(project_dir):
|
|
||||||
# clean obsolete build dir
|
|
||||||
if not disable_auto_clean:
|
|
||||||
try:
|
|
||||||
_clean_build_dir(get_project_build_dir())
|
|
||||||
except: # pylint: disable=bare-except
|
|
||||||
click.secho(
|
|
||||||
"Can not remove temporary directory `%s`. Please remove "
|
|
||||||
"it manually to avoid build issues" %
|
|
||||||
get_project_build_dir(force=True),
|
|
||||||
fg="yellow")
|
|
||||||
|
|
||||||
config = ProjectConfig.get_instance(
|
|
||||||
project_conf or join(project_dir, "platformio.ini"))
|
|
||||||
config.validate(environment)
|
|
||||||
|
|
||||||
_handle_legacy_libdeps(project_dir, config)
|
|
||||||
|
|
||||||
results = []
|
|
||||||
start_time = time()
|
|
||||||
default_envs = config.default_envs()
|
|
||||||
for envname in config.envs():
|
|
||||||
skipenv = any([
|
|
||||||
environment and envname not in environment, not environment
|
|
||||||
and default_envs and envname not in default_envs
|
|
||||||
])
|
|
||||||
if skipenv:
|
|
||||||
results.append((envname, None))
|
|
||||||
continue
|
|
||||||
|
|
||||||
if not silent and any(
|
|
||||||
status is not None for (_, status) in results):
|
|
||||||
click.echo()
|
|
||||||
|
|
||||||
options = config.items(env=envname, as_dict=True)
|
|
||||||
if "piotest" not in options and "piotest" in ctx.meta:
|
|
||||||
options['piotest'] = ctx.meta['piotest']
|
|
||||||
|
|
||||||
ep = EnvironmentProcessor(ctx, envname, options, target,
|
|
||||||
upload_port, silent, verbose)
|
|
||||||
result = (envname, ep.process())
|
|
||||||
results.append(result)
|
|
||||||
if result[1] and "monitor" in ep.get_build_targets() and \
|
|
||||||
"nobuild" not in ep.get_build_targets():
|
|
||||||
ctx.invoke(
|
|
||||||
cmd_device_monitor,
|
|
||||||
environment=environment[0] if environment else None)
|
|
||||||
|
|
||||||
found_error = any(status is False for (_, status) in results)
|
|
||||||
|
|
||||||
if (found_error or not silent) and len(results) > 1:
|
|
||||||
click.echo()
|
|
||||||
print_summary(results, start_time)
|
|
||||||
|
|
||||||
if found_error:
|
|
||||||
raise exception.ReturnErrorCode(1)
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
class EnvironmentProcessor(object):
|
|
||||||
|
|
||||||
DEFAULT_DUMP_OPTIONS = ("platform", "framework", "board")
|
|
||||||
|
|
||||||
IGNORE_BUILD_OPTIONS = [
|
|
||||||
"test_transport", "test_filter", "test_ignore", "test_port",
|
|
||||||
"test_speed", "debug_port", "debug_init_cmds", "debug_extra_cmds",
|
|
||||||
"debug_server", "debug_init_break", "debug_load_cmd",
|
|
||||||
"debug_load_mode", "monitor_port", "monitor_speed", "monitor_rts",
|
|
||||||
"monitor_dtr"
|
|
||||||
]
|
|
||||||
|
|
||||||
REMAPED_OPTIONS = {"framework": "pioframework", "platform": "pioplatform"}
|
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self, # pylint: disable=R0913
|
|
||||||
cmd_ctx,
|
|
||||||
name,
|
|
||||||
options,
|
|
||||||
targets,
|
|
||||||
upload_port,
|
|
||||||
silent,
|
|
||||||
verbose):
|
|
||||||
self.cmd_ctx = cmd_ctx
|
|
||||||
self.name = name
|
|
||||||
self.options = options
|
|
||||||
self.targets = targets
|
|
||||||
self.upload_port = upload_port
|
|
||||||
self.silent = silent
|
|
||||||
self.verbose = verbose
|
|
||||||
|
|
||||||
def process(self):
|
|
||||||
terminal_width, _ = click.get_terminal_size()
|
|
||||||
start_time = time()
|
|
||||||
env_dump = []
|
|
||||||
|
|
||||||
for k, v in self.options.items():
|
|
||||||
self.options[k] = self.options[k].strip()
|
|
||||||
if self.verbose or k in self.DEFAULT_DUMP_OPTIONS:
|
|
||||||
env_dump.append("%s: %s" % (k, ", ".join(
|
|
||||||
ProjectConfig.parse_multi_values(v))))
|
|
||||||
|
|
||||||
if not self.silent:
|
|
||||||
click.echo("Processing %s (%s)" % (click.style(
|
|
||||||
self.name, fg="cyan", bold=True), "; ".join(env_dump)))
|
|
||||||
click.secho("-" * terminal_width, bold=True)
|
|
||||||
|
|
||||||
result = self._run()
|
|
||||||
is_error = result['returncode'] != 0
|
|
||||||
|
|
||||||
if self.silent and not is_error:
|
|
||||||
return True
|
|
||||||
|
|
||||||
if is_error or "piotest_processor" not in self.cmd_ctx.meta:
|
|
||||||
print_header(
|
|
||||||
"[%s] Took %.2f seconds" % (
|
|
||||||
(click.style("ERROR", fg="red", bold=True) if is_error else
|
|
||||||
click.style("SUCCESS", fg="green", bold=True)),
|
|
||||||
time() - start_time),
|
|
||||||
is_error=is_error)
|
|
||||||
|
|
||||||
return not is_error
|
|
||||||
|
|
||||||
def get_build_variables(self):
|
|
||||||
variables = {"pioenv": self.name}
|
|
||||||
if self.upload_port:
|
|
||||||
variables['upload_port'] = self.upload_port
|
|
||||||
for k, v in self.options.items():
|
|
||||||
if k in self.REMAPED_OPTIONS:
|
|
||||||
k = self.REMAPED_OPTIONS[k]
|
|
||||||
if k in self.IGNORE_BUILD_OPTIONS:
|
|
||||||
continue
|
|
||||||
if k == "targets" or (k == "upload_port" and self.upload_port):
|
|
||||||
continue
|
|
||||||
variables[k] = v
|
|
||||||
return variables
|
|
||||||
|
|
||||||
def get_build_targets(self):
|
|
||||||
targets = []
|
|
||||||
if self.targets:
|
|
||||||
targets = [t for t in self.targets]
|
|
||||||
elif "targets" in self.options:
|
|
||||||
targets = self.options['targets'].split(", ")
|
|
||||||
return targets
|
|
||||||
|
|
||||||
def _run(self):
|
|
||||||
if "platform" not in self.options:
|
|
||||||
raise exception.UndefinedEnvPlatform(self.name)
|
|
||||||
|
|
||||||
build_vars = self.get_build_variables()
|
|
||||||
build_targets = self.get_build_targets()
|
|
||||||
|
|
||||||
telemetry.on_run_environment(self.options, build_targets)
|
|
||||||
|
|
||||||
# skip monitor target, we call it above
|
|
||||||
if "monitor" in build_targets:
|
|
||||||
build_targets.remove("monitor")
|
|
||||||
if "nobuild" not in build_targets:
|
|
||||||
# install dependent libraries
|
|
||||||
if "lib_install" in self.options:
|
|
||||||
_autoinstall_libdeps(self.cmd_ctx, self.name, [
|
|
||||||
int(d.strip())
|
|
||||||
for d in self.options['lib_install'].split(",")
|
|
||||||
if d.strip()
|
|
||||||
], self.verbose)
|
|
||||||
if "lib_deps" in self.options:
|
|
||||||
_autoinstall_libdeps(
|
|
||||||
self.cmd_ctx, self.name,
|
|
||||||
ProjectConfig.parse_multi_values(self.options['lib_deps']),
|
|
||||||
self.verbose)
|
|
||||||
|
|
||||||
try:
|
|
||||||
p = PlatformFactory.newPlatform(self.options['platform'])
|
|
||||||
except exception.UnknownPlatform:
|
|
||||||
self.cmd_ctx.invoke(
|
|
||||||
cmd_platform_install,
|
|
||||||
platforms=[self.options['platform']],
|
|
||||||
skip_default_package=True)
|
|
||||||
p = PlatformFactory.newPlatform(self.options['platform'])
|
|
||||||
|
|
||||||
return p.run(build_vars, build_targets, self.silent, self.verbose)
|
|
||||||
|
|
||||||
|
|
||||||
def _handle_legacy_libdeps(project_dir, config):
|
|
||||||
legacy_libdeps_dir = join(project_dir, ".piolibdeps")
|
|
||||||
if (not isdir(legacy_libdeps_dir)
|
|
||||||
or legacy_libdeps_dir == get_project_libdeps_dir()):
|
|
||||||
return
|
|
||||||
if not config.has_section("env"):
|
|
||||||
config.add_section("env")
|
|
||||||
lib_extra_dirs = []
|
|
||||||
if config.has_option("env", "lib_extra_dirs"):
|
|
||||||
lib_extra_dirs = config.getlist("env", "lib_extra_dirs")
|
|
||||||
lib_extra_dirs.append(legacy_libdeps_dir)
|
|
||||||
config.set("env", "lib_extra_dirs", lib_extra_dirs)
|
|
||||||
click.secho(
|
|
||||||
"DEPRECATED! A legacy library storage `{0}` has been found in a "
|
|
||||||
"project. \nPlease declare project dependencies in `platformio.ini`"
|
|
||||||
" file using `lib_deps` option and remove `{0}` folder."
|
|
||||||
"\nMore details -> http://docs.platformio.org/page/projectconf/"
|
|
||||||
"section_env_library.html#lib-deps".format(legacy_libdeps_dir),
|
|
||||||
fg="yellow")
|
|
||||||
|
|
||||||
|
|
||||||
def _autoinstall_libdeps(ctx, envname, libraries, verbose=False):
|
|
||||||
if not libraries:
|
|
||||||
return
|
|
||||||
libdeps_dir = join(get_project_libdeps_dir(), envname)
|
|
||||||
ctx.meta.update({
|
|
||||||
CTX_META_STORAGE_DIRS_KEY: [libdeps_dir],
|
|
||||||
CTX_META_STORAGE_LIBDEPS_KEY: {
|
|
||||||
libdeps_dir: libraries
|
|
||||||
}
|
|
||||||
})
|
|
||||||
try:
|
|
||||||
ctx.invoke(cmd_lib_install, silent=not verbose)
|
|
||||||
except exception.InternetIsOffline as e:
|
|
||||||
click.secho(str(e), fg="yellow")
|
|
||||||
|
|
||||||
|
|
||||||
def _clean_build_dir(build_dir):
|
|
||||||
# remove legacy ".pioenvs" folder
|
|
||||||
legacy_build_dir = join(get_project_dir(), ".pioenvs")
|
|
||||||
if isdir(legacy_build_dir) and legacy_build_dir != build_dir:
|
|
||||||
util.rmtree_(legacy_build_dir)
|
|
||||||
|
|
||||||
structhash_file = join(build_dir, "structure.hash")
|
|
||||||
proj_hash = calculate_project_hash()
|
|
||||||
|
|
||||||
# if project's config is modified
|
|
||||||
if (isdir(build_dir) and getmtime(
|
|
||||||
join(get_project_dir(), "platformio.ini")) > getmtime(build_dir)):
|
|
||||||
util.rmtree_(build_dir)
|
|
||||||
|
|
||||||
# check project structure
|
|
||||||
if isdir(build_dir) and isfile(structhash_file):
|
|
||||||
with open(structhash_file) as f:
|
|
||||||
if f.read() == proj_hash:
|
|
||||||
return
|
|
||||||
util.rmtree_(build_dir)
|
|
||||||
|
|
||||||
if not isdir(build_dir):
|
|
||||||
makedirs(build_dir)
|
|
||||||
|
|
||||||
with open(structhash_file, "w") as f:
|
|
||||||
f.write(proj_hash)
|
|
||||||
|
|
||||||
|
|
||||||
def print_header(label, is_error=False, fg=None):
|
|
||||||
terminal_width, _ = click.get_terminal_size()
|
|
||||||
width = len(click.unstyle(label))
|
|
||||||
half_line = "=" * int((terminal_width - width - 2) / 2)
|
|
||||||
click.secho(
|
|
||||||
"%s %s %s" % (half_line, label, half_line), fg=fg, err=is_error)
|
|
||||||
|
|
||||||
|
|
||||||
def print_summary(results, start_time):
|
|
||||||
print_header("[%s]" % click.style("SUMMARY"))
|
|
||||||
|
|
||||||
envname_max_len = 0
|
|
||||||
for (envname, _) in results:
|
|
||||||
if len(envname) > envname_max_len:
|
|
||||||
envname_max_len = len(envname)
|
|
||||||
|
|
||||||
successed = True
|
|
||||||
for (envname, status) in results:
|
|
||||||
status_str = click.style("SUCCESS", fg="green")
|
|
||||||
if status is False:
|
|
||||||
successed = False
|
|
||||||
status_str = click.style("ERROR", fg="red")
|
|
||||||
elif status is None:
|
|
||||||
status_str = click.style("SKIP", fg="yellow")
|
|
||||||
|
|
||||||
format_str = (
|
|
||||||
"Environment {0:<" + str(envname_max_len + 9) + "}\t[{1}]")
|
|
||||||
click.echo(
|
|
||||||
format_str.format(click.style(envname, fg="cyan"), status_str),
|
|
||||||
err=status is False)
|
|
||||||
|
|
||||||
print_header(
|
|
||||||
"[%s] Took %.2f seconds" % (
|
|
||||||
(click.style("SUCCESS", fg="green", bold=True) if successed else
|
|
||||||
click.style("ERROR", fg="red", bold=True)), time() - start_time),
|
|
||||||
is_error=not successed)
|
|
16
platformio/commands/run/__init__.py
Normal file
16
platformio/commands/run/__init__.py
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# Copyright (c) 2014-present PlatformIO <contact@platformio.org>
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
from platformio.commands.run.command import cli
|
||||||
|
from platformio.commands.run.helpers import print_header
|
119
platformio/commands/run/command.py
Normal file
119
platformio/commands/run/command.py
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
# Copyright (c) 2014-present PlatformIO <contact@platformio.org>
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
from os import getcwd
|
||||||
|
from os.path import isfile, join
|
||||||
|
from time import time
|
||||||
|
|
||||||
|
import click
|
||||||
|
|
||||||
|
from platformio import exception, util
|
||||||
|
from platformio.commands.device import device_monitor as cmd_device_monitor
|
||||||
|
from platformio.commands.run.helpers import (
|
||||||
|
_clean_build_dir, _handle_legacy_libdeps, print_summary)
|
||||||
|
from platformio.commands.run.processor import EnvironmentProcessor
|
||||||
|
from platformio.project.config import ProjectConfig
|
||||||
|
from platformio.project.helpers import (find_project_dir_above,
|
||||||
|
get_project_build_dir)
|
||||||
|
|
||||||
|
# pylint: disable=too-many-arguments,too-many-locals,too-many-branches
|
||||||
|
|
||||||
|
|
||||||
|
@click.command("run", short_help="Process project environments")
|
||||||
|
@click.option("-e", "--environment", multiple=True)
|
||||||
|
@click.option("-t", "--target", multiple=True)
|
||||||
|
@click.option("--upload-port")
|
||||||
|
@click.option(
|
||||||
|
"-d",
|
||||||
|
"--project-dir",
|
||||||
|
default=getcwd,
|
||||||
|
type=click.Path(
|
||||||
|
exists=True,
|
||||||
|
file_okay=True,
|
||||||
|
dir_okay=True,
|
||||||
|
writable=True,
|
||||||
|
resolve_path=True))
|
||||||
|
@click.option(
|
||||||
|
"-c",
|
||||||
|
"--project-conf",
|
||||||
|
type=click.Path(
|
||||||
|
exists=True,
|
||||||
|
file_okay=True,
|
||||||
|
dir_okay=False,
|
||||||
|
readable=True,
|
||||||
|
resolve_path=True))
|
||||||
|
@click.option("-s", "--silent", is_flag=True)
|
||||||
|
@click.option("-v", "--verbose", is_flag=True)
|
||||||
|
@click.option("--disable-auto-clean", is_flag=True)
|
||||||
|
@click.pass_context
|
||||||
|
def cli(ctx, environment, target, upload_port, project_dir, project_conf,
|
||||||
|
silent, verbose, disable_auto_clean):
|
||||||
|
# find project directory on upper level
|
||||||
|
if isfile(project_dir):
|
||||||
|
project_dir = find_project_dir_above(project_dir)
|
||||||
|
|
||||||
|
with util.cd(project_dir):
|
||||||
|
# clean obsolete build dir
|
||||||
|
if not disable_auto_clean:
|
||||||
|
try:
|
||||||
|
_clean_build_dir(get_project_build_dir())
|
||||||
|
except: # pylint: disable=bare-except
|
||||||
|
click.secho(
|
||||||
|
"Can not remove temporary directory `%s`. Please remove "
|
||||||
|
"it manually to avoid build issues" %
|
||||||
|
get_project_build_dir(force=True),
|
||||||
|
fg="yellow")
|
||||||
|
|
||||||
|
config = ProjectConfig.get_instance(
|
||||||
|
project_conf or join(project_dir, "platformio.ini"))
|
||||||
|
config.validate(environment)
|
||||||
|
|
||||||
|
_handle_legacy_libdeps(project_dir, config)
|
||||||
|
|
||||||
|
results = []
|
||||||
|
start_time = time()
|
||||||
|
default_envs = config.default_envs()
|
||||||
|
for envname in config.envs():
|
||||||
|
skipenv = any([
|
||||||
|
environment and envname not in environment, not environment
|
||||||
|
and default_envs and envname not in default_envs
|
||||||
|
])
|
||||||
|
if skipenv:
|
||||||
|
results.append((envname, None))
|
||||||
|
continue
|
||||||
|
|
||||||
|
if not silent and any(
|
||||||
|
status is not None for (_, status) in results):
|
||||||
|
click.echo()
|
||||||
|
|
||||||
|
ep = EnvironmentProcessor(ctx, envname, config, target,
|
||||||
|
upload_port, silent, verbose)
|
||||||
|
result = (envname, ep.process())
|
||||||
|
results.append(result)
|
||||||
|
|
||||||
|
if result[1] and "monitor" in ep.get_build_targets() and \
|
||||||
|
"nobuild" not in ep.get_build_targets():
|
||||||
|
ctx.invoke(
|
||||||
|
cmd_device_monitor,
|
||||||
|
environment=environment[0] if environment else None)
|
||||||
|
|
||||||
|
found_error = any(status is False for (_, status) in results)
|
||||||
|
|
||||||
|
if (found_error or not silent) and len(results) > 1:
|
||||||
|
click.echo()
|
||||||
|
print_summary(results, start_time)
|
||||||
|
|
||||||
|
if found_error:
|
||||||
|
raise exception.ReturnErrorCode(1)
|
||||||
|
return True
|
127
platformio/commands/run/helpers.py
Normal file
127
platformio/commands/run/helpers.py
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
# Copyright (c) 2014-present PlatformIO <contact@platformio.org>
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
from os import makedirs
|
||||||
|
from os.path import getmtime, isdir, isfile, join
|
||||||
|
from time import time
|
||||||
|
|
||||||
|
import click
|
||||||
|
|
||||||
|
from platformio import exception, util
|
||||||
|
from platformio.commands.lib import (CTX_META_STORAGE_DIRS_KEY,
|
||||||
|
CTX_META_STORAGE_LIBDEPS_KEY)
|
||||||
|
from platformio.commands.lib import lib_install as cmd_lib_install
|
||||||
|
from platformio.project.helpers import (
|
||||||
|
calculate_project_hash, get_project_dir, get_project_libdeps_dir)
|
||||||
|
|
||||||
|
|
||||||
|
def _handle_legacy_libdeps(project_dir, config):
|
||||||
|
legacy_libdeps_dir = join(project_dir, ".piolibdeps")
|
||||||
|
if (not isdir(legacy_libdeps_dir)
|
||||||
|
or legacy_libdeps_dir == get_project_libdeps_dir()):
|
||||||
|
return
|
||||||
|
if not config.has_section("env"):
|
||||||
|
config.add_section("env")
|
||||||
|
lib_extra_dirs = config.get("env", "lib_extra_dirs", [])
|
||||||
|
lib_extra_dirs.append(legacy_libdeps_dir)
|
||||||
|
config.set("env", "lib_extra_dirs", lib_extra_dirs)
|
||||||
|
click.secho(
|
||||||
|
"DEPRECATED! A legacy library storage `{0}` has been found in a "
|
||||||
|
"project. \nPlease declare project dependencies in `platformio.ini`"
|
||||||
|
" file using `lib_deps` option and remove `{0}` folder."
|
||||||
|
"\nMore details -> http://docs.platformio.org/page/projectconf/"
|
||||||
|
"section_env_library.html#lib-deps".format(legacy_libdeps_dir),
|
||||||
|
fg="yellow")
|
||||||
|
|
||||||
|
|
||||||
|
def _autoinstall_libdeps(ctx, envname, libraries, verbose=False):
|
||||||
|
if not libraries:
|
||||||
|
return
|
||||||
|
libdeps_dir = join(get_project_libdeps_dir(), envname)
|
||||||
|
ctx.meta.update({
|
||||||
|
CTX_META_STORAGE_DIRS_KEY: [libdeps_dir],
|
||||||
|
CTX_META_STORAGE_LIBDEPS_KEY: {
|
||||||
|
libdeps_dir: libraries
|
||||||
|
}
|
||||||
|
})
|
||||||
|
try:
|
||||||
|
ctx.invoke(cmd_lib_install, silent=not verbose)
|
||||||
|
except exception.InternetIsOffline as e:
|
||||||
|
click.secho(str(e), fg="yellow")
|
||||||
|
|
||||||
|
|
||||||
|
def _clean_build_dir(build_dir):
|
||||||
|
# remove legacy ".pioenvs" folder
|
||||||
|
legacy_build_dir = join(get_project_dir(), ".pioenvs")
|
||||||
|
if isdir(legacy_build_dir) and legacy_build_dir != build_dir:
|
||||||
|
util.rmtree_(legacy_build_dir)
|
||||||
|
|
||||||
|
structhash_file = join(build_dir, "structure.hash")
|
||||||
|
proj_hash = calculate_project_hash()
|
||||||
|
|
||||||
|
# if project's config is modified
|
||||||
|
if (isdir(build_dir) and getmtime(
|
||||||
|
join(get_project_dir(), "platformio.ini")) > getmtime(build_dir)):
|
||||||
|
util.rmtree_(build_dir)
|
||||||
|
|
||||||
|
# check project structure
|
||||||
|
if isdir(build_dir) and isfile(structhash_file):
|
||||||
|
with open(structhash_file) as f:
|
||||||
|
if f.read() == proj_hash:
|
||||||
|
return
|
||||||
|
util.rmtree_(build_dir)
|
||||||
|
|
||||||
|
if not isdir(build_dir):
|
||||||
|
makedirs(build_dir)
|
||||||
|
|
||||||
|
with open(structhash_file, "w") as f:
|
||||||
|
f.write(proj_hash)
|
||||||
|
|
||||||
|
|
||||||
|
def print_header(label, is_error=False, fg=None):
|
||||||
|
terminal_width, _ = click.get_terminal_size()
|
||||||
|
width = len(click.unstyle(label))
|
||||||
|
half_line = "=" * int((terminal_width - width - 2) / 2)
|
||||||
|
click.secho(
|
||||||
|
"%s %s %s" % (half_line, label, half_line), fg=fg, err=is_error)
|
||||||
|
|
||||||
|
|
||||||
|
def print_summary(results, start_time):
|
||||||
|
print_header("[%s]" % click.style("SUMMARY"))
|
||||||
|
|
||||||
|
succeeded_nums = 0
|
||||||
|
failed_nums = 0
|
||||||
|
envname_max_len = max(
|
||||||
|
[len(click.style(envname, fg="cyan")) for (envname, _) in results])
|
||||||
|
for (envname, status) in results:
|
||||||
|
if status is False:
|
||||||
|
failed_nums += 1
|
||||||
|
status_str = click.style("FAILED", fg="red")
|
||||||
|
elif status is None:
|
||||||
|
status_str = click.style("IGNORED", fg="yellow")
|
||||||
|
else:
|
||||||
|
succeeded_nums += 1
|
||||||
|
status_str = click.style("SUCCESS", fg="green")
|
||||||
|
|
||||||
|
format_str = "Environment {0:<%d}\t[{1}]" % envname_max_len
|
||||||
|
click.echo(
|
||||||
|
format_str.format(click.style(envname, fg="cyan"), status_str),
|
||||||
|
err=status is False)
|
||||||
|
|
||||||
|
print_header(
|
||||||
|
"%s%d succeeded in %.2f seconds" %
|
||||||
|
("%d failed, " % failed_nums if failed_nums else "", succeeded_nums,
|
||||||
|
time() - start_time),
|
||||||
|
is_error=failed_nums,
|
||||||
|
fg="red" if failed_nums else "green")
|
115
platformio/commands/run/processor.py
Normal file
115
platformio/commands/run/processor.py
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
# Copyright (c) 2014-present PlatformIO <contact@platformio.org>
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
from time import time
|
||||||
|
|
||||||
|
import click
|
||||||
|
|
||||||
|
from platformio import exception, telemetry
|
||||||
|
from platformio.commands.platform import \
|
||||||
|
platform_install as cmd_platform_install
|
||||||
|
from platformio.commands.run.helpers import _autoinstall_libdeps, print_header
|
||||||
|
from platformio.managers.platform import PlatformFactory
|
||||||
|
|
||||||
|
# pylint: disable=too-many-instance-attributes
|
||||||
|
|
||||||
|
|
||||||
|
class EnvironmentProcessor(object):
|
||||||
|
|
||||||
|
DEFAULT_PRINT_OPTIONS = ("platform", "framework", "board")
|
||||||
|
|
||||||
|
def __init__( # pylint: disable=too-many-arguments
|
||||||
|
self, cmd_ctx, name, config, targets, upload_port, silent,
|
||||||
|
verbose):
|
||||||
|
self.cmd_ctx = cmd_ctx
|
||||||
|
self.name = name
|
||||||
|
self.config = config
|
||||||
|
self.targets = targets
|
||||||
|
self.upload_port = upload_port
|
||||||
|
self.silent = silent
|
||||||
|
self.verbose = verbose
|
||||||
|
self.options = config.items(env=name, as_dict=True)
|
||||||
|
|
||||||
|
def process(self):
|
||||||
|
terminal_width, _ = click.get_terminal_size()
|
||||||
|
start_time = time()
|
||||||
|
env_dump = []
|
||||||
|
|
||||||
|
for k, v in self.options.items():
|
||||||
|
if self.verbose or k in self.DEFAULT_PRINT_OPTIONS:
|
||||||
|
env_dump.append(
|
||||||
|
"%s: %s" % (k, ", ".join(v) if isinstance(v, list) else v))
|
||||||
|
|
||||||
|
if not self.silent:
|
||||||
|
click.echo("Processing %s (%s)" % (click.style(
|
||||||
|
self.name, fg="cyan", bold=True), "; ".join(env_dump)))
|
||||||
|
click.secho("-" * terminal_width, bold=True)
|
||||||
|
|
||||||
|
result = self._run_platform()
|
||||||
|
is_error = result['returncode'] != 0
|
||||||
|
|
||||||
|
if self.silent and not is_error:
|
||||||
|
return True
|
||||||
|
|
||||||
|
if is_error or "piotest_processor" not in self.cmd_ctx.meta:
|
||||||
|
print_header(
|
||||||
|
"[%s] Took %.2f seconds" % (
|
||||||
|
(click.style("ERROR", fg="red", bold=True) if is_error else
|
||||||
|
click.style("SUCCESS", fg="green", bold=True)),
|
||||||
|
time() - start_time),
|
||||||
|
is_error=is_error)
|
||||||
|
|
||||||
|
return not is_error
|
||||||
|
|
||||||
|
def get_build_variables(self):
|
||||||
|
variables = {"pioenv": self.name, "project_config": self.config.path}
|
||||||
|
if "piotest" in self.cmd_ctx.meta:
|
||||||
|
variables['piotest'] = self.cmd_ctx.meta['piotest']
|
||||||
|
if self.upload_port:
|
||||||
|
# override upload port with a custom from CLI
|
||||||
|
variables['upload_port'] = self.upload_port
|
||||||
|
return variables
|
||||||
|
|
||||||
|
def get_build_targets(self):
|
||||||
|
if self.targets:
|
||||||
|
return [t for t in self.targets]
|
||||||
|
return self.config.get("env:" + self.name, "targets", [])
|
||||||
|
|
||||||
|
def _run_platform(self):
|
||||||
|
if "platform" not in self.options:
|
||||||
|
raise exception.UndefinedEnvPlatform(self.name)
|
||||||
|
|
||||||
|
build_vars = self.get_build_variables()
|
||||||
|
build_targets = self.get_build_targets()
|
||||||
|
|
||||||
|
telemetry.on_run_environment(self.options, build_targets)
|
||||||
|
|
||||||
|
# skip monitor target, we call it above
|
||||||
|
if "monitor" in build_targets:
|
||||||
|
build_targets.remove("monitor")
|
||||||
|
if "nobuild" not in build_targets and "lib_deps" in self.options:
|
||||||
|
_autoinstall_libdeps(
|
||||||
|
self.cmd_ctx, self.name,
|
||||||
|
self.config.get("env:" + self.name, "lib_deps"), self.verbose)
|
||||||
|
|
||||||
|
try:
|
||||||
|
p = PlatformFactory.newPlatform(self.options['platform'])
|
||||||
|
except exception.UnknownPlatform:
|
||||||
|
self.cmd_ctx.invoke(
|
||||||
|
cmd_platform_install,
|
||||||
|
platforms=[self.options['platform']],
|
||||||
|
skip_default_package=True)
|
||||||
|
p = PlatformFactory.newPlatform(self.options['platform'])
|
||||||
|
|
||||||
|
return p.run(build_vars, build_targets, self.silent, self.verbose)
|
@ -22,7 +22,7 @@ from time import time
|
|||||||
import click
|
import click
|
||||||
|
|
||||||
from platformio import exception, util
|
from platformio import exception, util
|
||||||
from platformio.commands.run import print_header
|
from platformio.commands.run.helpers import print_header
|
||||||
from platformio.commands.test.embedded import EmbeddedTestProcessor
|
from platformio.commands.test.embedded import EmbeddedTestProcessor
|
||||||
from platformio.commands.test.native import NativeTestProcessor
|
from platformio.commands.test.native import NativeTestProcessor
|
||||||
from platformio.project.config import ProjectConfig
|
from platformio.project.config import ProjectConfig
|
||||||
@ -107,9 +107,8 @@ def cli( # pylint: disable=redefined-builtin
|
|||||||
# filter and ignore patterns
|
# filter and ignore patterns
|
||||||
patterns = dict(filter=list(filter), ignore=list(ignore))
|
patterns = dict(filter=list(filter), ignore=list(ignore))
|
||||||
for key in patterns:
|
for key in patterns:
|
||||||
if config.has_option(section, "test_%s" % key):
|
patterns[key].extend(
|
||||||
patterns[key].extend(
|
config.get(section, "test_%s" % key, []))
|
||||||
config.getlist(section, "test_%s" % key))
|
|
||||||
|
|
||||||
skip_conditions = [
|
skip_conditions = [
|
||||||
environment and envname not in environment,
|
environment and envname not in environment,
|
||||||
@ -167,10 +166,11 @@ def cli( # pylint: disable=redefined-builtin
|
|||||||
passed_nums += 1
|
passed_nums += 1
|
||||||
status_str = click.style("PASSED", fg="green")
|
status_str = click.style("PASSED", fg="green")
|
||||||
|
|
||||||
|
format_str = "test/{:<%d} > {:<%d}\t[{}]" % (testname_max_len,
|
||||||
|
envname_max_len)
|
||||||
click.echo(
|
click.echo(
|
||||||
("test/{:<%d} > {:<%d}\t[{}]" %
|
format_str.format(testname, click.style(envname, fg="cyan"),
|
||||||
(testname_max_len, envname_max_len)).format(
|
status_str),
|
||||||
testname, click.style(envname, fg="cyan"), status_str),
|
|
||||||
err=status is False)
|
err=status is False)
|
||||||
|
|
||||||
print_header(
|
print_header(
|
||||||
|
@ -32,7 +32,8 @@ class EmbeddedTestProcessor(TestProcessorBase):
|
|||||||
target = ["__test"]
|
target = ["__test"]
|
||||||
if self.options['without_uploading']:
|
if self.options['without_uploading']:
|
||||||
target.append("checkprogsize")
|
target.append("checkprogsize")
|
||||||
self.build_or_upload(target)
|
if not self.build_or_upload(target):
|
||||||
|
return False
|
||||||
|
|
||||||
if not self.options['without_uploading']:
|
if not self.options['without_uploading']:
|
||||||
self.print_progress("Uploading... (2/3)")
|
self.print_progress("Uploading... (2/3)")
|
||||||
@ -41,7 +42,8 @@ class EmbeddedTestProcessor(TestProcessorBase):
|
|||||||
target.append("nobuild")
|
target.append("nobuild")
|
||||||
else:
|
else:
|
||||||
target.append("__test")
|
target.append("__test")
|
||||||
self.build_or_upload(target)
|
if not self.build_or_upload(target):
|
||||||
|
return False
|
||||||
|
|
||||||
if self.options['without_testing']:
|
if self.options['without_testing']:
|
||||||
return None
|
return None
|
||||||
|
@ -25,7 +25,8 @@ class NativeTestProcessor(TestProcessorBase):
|
|||||||
def process(self):
|
def process(self):
|
||||||
if not self.options['without_building']:
|
if not self.options['without_building']:
|
||||||
self.print_progress("Building... (1/2)")
|
self.print_progress("Building... (1/2)")
|
||||||
self.build_or_upload(["__test"])
|
if not self.build_or_upload(["__test"]):
|
||||||
|
return False
|
||||||
if self.options['without_testing']:
|
if self.options['without_testing']:
|
||||||
return None
|
return None
|
||||||
self.print_progress("Testing... (2/2)")
|
self.print_progress("Testing... (2/2)")
|
||||||
|
@ -21,7 +21,7 @@ import click
|
|||||||
|
|
||||||
from platformio import exception
|
from platformio import exception
|
||||||
from platformio.commands.run import cli as cmd_run
|
from platformio.commands.run import cli as cmd_run
|
||||||
from platformio.commands.run import print_header
|
from platformio.commands.run.helpers import print_header
|
||||||
from platformio.project.helpers import get_project_test_dir
|
from platformio.project.helpers import get_project_test_dir
|
||||||
|
|
||||||
TRANSPORT_OPTIONS = {
|
TRANSPORT_OPTIONS = {
|
||||||
@ -82,7 +82,7 @@ class TestProcessorBase(object):
|
|||||||
|
|
||||||
def __init__(self, cmd_ctx, testname, envname, options):
|
def __init__(self, cmd_ctx, testname, envname, options):
|
||||||
self.cmd_ctx = cmd_ctx
|
self.cmd_ctx = cmd_ctx
|
||||||
self.cmd_ctx.meta['piotest_processor'] = True
|
self.cmd_ctx.meta['piotest_processor'] = True # FIXME
|
||||||
self.test_name = testname
|
self.test_name = testname
|
||||||
self.options = options
|
self.options = options
|
||||||
self.env_name = envname
|
self.env_name = envname
|
||||||
@ -92,9 +92,10 @@ class TestProcessorBase(object):
|
|||||||
self._outputcpp_generated = False
|
self._outputcpp_generated = False
|
||||||
|
|
||||||
def get_transport(self):
|
def get_transport(self):
|
||||||
transport = self.env_options.get("framework")
|
|
||||||
if self.env_options.get("platform") == "native":
|
if self.env_options.get("platform") == "native":
|
||||||
transport = "native"
|
transport = "native"
|
||||||
|
elif "framework" in self.env_options:
|
||||||
|
transport = self.env_options.get("framework")[0]
|
||||||
if "test_transport" in self.env_options:
|
if "test_transport" in self.env_options:
|
||||||
transport = self.env_options['test_transport']
|
transport = self.env_options['test_transport']
|
||||||
if transport not in TRANSPORT_OPTIONS:
|
if transport not in TRANSPORT_OPTIONS:
|
||||||
@ -108,8 +109,9 @@ class TestProcessorBase(object):
|
|||||||
def print_progress(self, text, is_error=False):
|
def print_progress(self, text, is_error=False):
|
||||||
click.echo()
|
click.echo()
|
||||||
print_header(
|
print_header(
|
||||||
"[test/%s] %s" % (click.style(
|
"[test/%s > %s] %s" % (click.style(self.test_name, fg="yellow"),
|
||||||
self.test_name, fg="yellow", bold=True), text),
|
click.style(self.env_name, fg="cyan"),
|
||||||
|
text),
|
||||||
is_error=is_error)
|
is_error=is_error)
|
||||||
|
|
||||||
def build_or_upload(self, target):
|
def build_or_upload(self, target):
|
||||||
@ -118,19 +120,22 @@ class TestProcessorBase(object):
|
|||||||
self._outputcpp_generated = True
|
self._outputcpp_generated = True
|
||||||
|
|
||||||
if self.test_name != "*":
|
if self.test_name != "*":
|
||||||
self.cmd_ctx.meta['piotest'] = self.test_name
|
self.cmd_ctx.meta['piotest'] = self.test_name # FIXME
|
||||||
|
|
||||||
if not self.options['verbose']:
|
if not self.options['verbose']:
|
||||||
click.echo("Please wait...")
|
click.echo("Please wait...")
|
||||||
|
|
||||||
return self.cmd_ctx.invoke(
|
try:
|
||||||
cmd_run,
|
return self.cmd_ctx.invoke(
|
||||||
project_dir=self.options['project_dir'],
|
cmd_run,
|
||||||
upload_port=self.options['upload_port'],
|
project_dir=self.options['project_dir'],
|
||||||
silent=not self.options['verbose'],
|
upload_port=self.options['upload_port'],
|
||||||
environment=[self.env_name],
|
silent=not self.options['verbose'],
|
||||||
disable_auto_clean="nobuild" in target,
|
environment=[self.env_name],
|
||||||
target=target)
|
disable_auto_clean="nobuild" in target,
|
||||||
|
target=target)
|
||||||
|
except exception.ReturnErrorCode:
|
||||||
|
return False
|
||||||
|
|
||||||
def process(self):
|
def process(self):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
@ -29,6 +29,7 @@ from platformio.managers.core import get_core_package_dir
|
|||||||
from platformio.managers.package import BasePkgManager, PackageManager
|
from platformio.managers.package import BasePkgManager, PackageManager
|
||||||
from platformio.proc import (BuildAsyncPipe, copy_pythonpath_to_osenv,
|
from platformio.proc import (BuildAsyncPipe, copy_pythonpath_to_osenv,
|
||||||
exec_command, get_pythonexe_path)
|
exec_command, get_pythonexe_path)
|
||||||
|
from platformio.project.config import ProjectConfig
|
||||||
from platformio.project.helpers import (
|
from platformio.project.helpers import (
|
||||||
get_project_boards_dir, get_project_core_dir, get_project_packages_dir,
|
get_project_boards_dir, get_project_core_dir, get_project_packages_dir,
|
||||||
get_project_platforms_dir)
|
get_project_platforms_dir)
|
||||||
@ -358,7 +359,12 @@ class PlatformRunMixin(object):
|
|||||||
assert isinstance(variables, dict)
|
assert isinstance(variables, dict)
|
||||||
assert isinstance(targets, list)
|
assert isinstance(targets, list)
|
||||||
|
|
||||||
self.configure_default_packages(variables, targets)
|
config = ProjectConfig.get_instance(variables['project_config'])
|
||||||
|
options = config.items(env=variables['pioenv'], as_dict=True)
|
||||||
|
if "framework" in options:
|
||||||
|
# support PIO Core 3.0 dev/platforms
|
||||||
|
options['pioframework'] = options['framework']
|
||||||
|
self.configure_default_packages(options, targets)
|
||||||
self.install_packages(silent=True)
|
self.install_packages(silent=True)
|
||||||
|
|
||||||
self.silent = silent
|
self.silent = silent
|
||||||
@ -611,12 +617,9 @@ class PlatformBase( # pylint: disable=too-many-public-methods
|
|||||||
def get_package_type(self, name):
|
def get_package_type(self, name):
|
||||||
return self.packages[name].get("type")
|
return self.packages[name].get("type")
|
||||||
|
|
||||||
def configure_default_packages(self, variables, targets):
|
def configure_default_packages(self, options, targets):
|
||||||
# enable used frameworks
|
# enable used frameworks
|
||||||
frameworks = variables.get("pioframework", [])
|
for framework in options.get("framework", []):
|
||||||
if not isinstance(frameworks, list):
|
|
||||||
frameworks = frameworks.split(", ")
|
|
||||||
for framework in frameworks:
|
|
||||||
if not self.frameworks:
|
if not self.frameworks:
|
||||||
continue
|
continue
|
||||||
framework = framework.lower().strip()
|
framework = framework.lower().strip()
|
||||||
|
@ -21,6 +21,7 @@ from os.path import isfile
|
|||||||
import click
|
import click
|
||||||
|
|
||||||
from platformio import exception
|
from platformio import exception
|
||||||
|
from platformio.project.options import ProjectOptions
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import ConfigParser as ConfigParser
|
import ConfigParser as ConfigParser
|
||||||
@ -39,98 +40,6 @@ CONFIG_HEADER = """;PlatformIO Project Configuration File
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
KNOWN_PLATFORMIO_OPTIONS = [
|
|
||||||
"description",
|
|
||||||
"env_default",
|
|
||||||
"extra_configs",
|
|
||||||
|
|
||||||
# Dirs
|
|
||||||
"core_dir",
|
|
||||||
"globallib_dir",
|
|
||||||
"platforms_dir",
|
|
||||||
"packages_dir",
|
|
||||||
"cache_dir",
|
|
||||||
"workspace_dir",
|
|
||||||
"build_dir",
|
|
||||||
"libdeps_dir",
|
|
||||||
"lib_dir",
|
|
||||||
"include_dir",
|
|
||||||
"src_dir",
|
|
||||||
"test_dir",
|
|
||||||
"boards_dir",
|
|
||||||
"data_dir"
|
|
||||||
]
|
|
||||||
|
|
||||||
KNOWN_ENV_OPTIONS = [
|
|
||||||
# Generic
|
|
||||||
"platform",
|
|
||||||
"framework",
|
|
||||||
"board",
|
|
||||||
"targets",
|
|
||||||
|
|
||||||
# Build
|
|
||||||
"build_flags",
|
|
||||||
"src_build_flags",
|
|
||||||
"build_unflags",
|
|
||||||
"src_filter",
|
|
||||||
|
|
||||||
# Upload
|
|
||||||
"upload_port",
|
|
||||||
"upload_protocol",
|
|
||||||
"upload_speed",
|
|
||||||
"upload_flags",
|
|
||||||
"upload_resetmethod",
|
|
||||||
|
|
||||||
# Monitor
|
|
||||||
"monitor_port",
|
|
||||||
"monitor_speed",
|
|
||||||
"monitor_rts",
|
|
||||||
"monitor_dtr",
|
|
||||||
"monitor_flags",
|
|
||||||
|
|
||||||
# Library
|
|
||||||
"lib_deps",
|
|
||||||
"lib_ignore",
|
|
||||||
"lib_extra_dirs",
|
|
||||||
"lib_ldf_mode",
|
|
||||||
"lib_compat_mode",
|
|
||||||
"lib_archive",
|
|
||||||
|
|
||||||
# Test
|
|
||||||
"piotest",
|
|
||||||
"test_filter",
|
|
||||||
"test_ignore",
|
|
||||||
"test_port",
|
|
||||||
"test_speed",
|
|
||||||
"test_transport",
|
|
||||||
"test_build_project_src",
|
|
||||||
|
|
||||||
# Debug
|
|
||||||
"debug_tool",
|
|
||||||
"debug_init_break",
|
|
||||||
"debug_init_cmds",
|
|
||||||
"debug_extra_cmds",
|
|
||||||
"debug_load_cmd",
|
|
||||||
"debug_load_mode",
|
|
||||||
"debug_server",
|
|
||||||
"debug_port",
|
|
||||||
"debug_svd_path",
|
|
||||||
|
|
||||||
# Other
|
|
||||||
"extra_scripts"
|
|
||||||
]
|
|
||||||
|
|
||||||
RENAMED_OPTIONS = {
|
|
||||||
"lib_use": "lib_deps",
|
|
||||||
"lib_force": "lib_deps",
|
|
||||||
"extra_script": "extra_scripts",
|
|
||||||
"monitor_baud": "monitor_speed",
|
|
||||||
"board_mcu": "board_build.mcu",
|
|
||||||
"board_f_cpu": "board_build.f_cpu",
|
|
||||||
"board_f_flash": "board_build.f_flash",
|
|
||||||
"board_flash_mode": "board_build.flash_mode"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class ProjectConfig(object):
|
class ProjectConfig(object):
|
||||||
|
|
||||||
@ -191,11 +100,7 @@ class ProjectConfig(object):
|
|||||||
return
|
return
|
||||||
|
|
||||||
# load extra configs
|
# load extra configs
|
||||||
if (not self._parser.has_section("platformio")
|
for pattern in self.get("platformio", "extra_configs", []):
|
||||||
or not self._parser.has_option("platformio", "extra_configs")):
|
|
||||||
return
|
|
||||||
extra_configs = self.getlist("platformio", "extra_configs")
|
|
||||||
for pattern in extra_configs:
|
|
||||||
for item in glob.glob(pattern):
|
for item in glob.glob(pattern):
|
||||||
self.read(item)
|
self.read(item)
|
||||||
|
|
||||||
@ -212,6 +117,14 @@ class ProjectConfig(object):
|
|||||||
if option not in options:
|
if option not in options:
|
||||||
options.append(option)
|
options.append(option)
|
||||||
|
|
||||||
|
# handle system environment variables
|
||||||
|
scope = section.split(":", 1)[0]
|
||||||
|
for option_meta in ProjectOptions.values():
|
||||||
|
if option_meta.scope != scope or option_meta.name in options:
|
||||||
|
continue
|
||||||
|
if option_meta.sysenvvar and option_meta.sysenvvar in os.environ:
|
||||||
|
options.append(option_meta.name)
|
||||||
|
|
||||||
return options
|
return options
|
||||||
|
|
||||||
def has_option(self, section, option):
|
def has_option(self, section, option):
|
||||||
@ -239,39 +152,84 @@ class ProjectConfig(object):
|
|||||||
value = "\n" + value # start from a new line
|
value = "\n" + value # start from a new line
|
||||||
self._parser.set(section, option, value)
|
self._parser.set(section, option, value)
|
||||||
|
|
||||||
def get(self, section, option):
|
def getraw(self, section, option):
|
||||||
if not self.expand_interpolations:
|
if not self.expand_interpolations:
|
||||||
return self._parser.get(section, option)
|
return self._parser.get(section, option)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
value = self._parser.get(section, option)
|
value = self._parser.get(section, option)
|
||||||
except ConfigParser.NoOptionError:
|
except ConfigParser.NoOptionError as e:
|
||||||
|
if not section.startswith("env:"):
|
||||||
|
raise e
|
||||||
value = self._parser.get("env", option)
|
value = self._parser.get("env", option)
|
||||||
except ConfigParser.Error as e:
|
|
||||||
raise exception.InvalidProjectConf(self.path, str(e))
|
|
||||||
|
|
||||||
if "${" not in value or "}" not in value:
|
if "${" not in value or "}" not in value:
|
||||||
return value
|
return value
|
||||||
return self.VARTPL_RE.sub(self._re_sub_handler, value)
|
return self.VARTPL_RE.sub(self._re_interpolation_handler, value)
|
||||||
|
|
||||||
def _re_sub_handler(self, match):
|
def _re_interpolation_handler(self, match):
|
||||||
section, option = match.group(1), match.group(2)
|
section, option = match.group(1), match.group(2)
|
||||||
if section == "sysenv":
|
if section == "sysenv":
|
||||||
return os.getenv(option)
|
return os.getenv(option)
|
||||||
return self.get(section, option)
|
return self.getraw(section, option)
|
||||||
|
|
||||||
def getlist(self, section, option):
|
def get(self, section, option, default=None):
|
||||||
return self.parse_multi_values(self.get(section, option))
|
value = None
|
||||||
|
try:
|
||||||
|
value = self.getraw(section, option)
|
||||||
|
except (ConfigParser.NoSectionError, ConfigParser.NoOptionError):
|
||||||
|
pass # handle value from system environment
|
||||||
|
except ConfigParser.Error as e:
|
||||||
|
raise exception.InvalidProjectConf(self.path, str(e))
|
||||||
|
|
||||||
|
option_meta = ProjectOptions.get(
|
||||||
|
"%s.%s" % (section.split(":", 1)[0], option))
|
||||||
|
if not option_meta:
|
||||||
|
return value or default
|
||||||
|
|
||||||
|
if value and option_meta.multiple:
|
||||||
|
value = self.parse_multi_values(value)
|
||||||
|
|
||||||
|
if option_meta.sysenvvar:
|
||||||
|
envvar_value = os.getenv(option_meta.sysenvvar)
|
||||||
|
if not envvar_value and option_meta.oldnames:
|
||||||
|
for oldoption in option_meta.oldnames:
|
||||||
|
envvar_value = os.getenv("PLATFORMIO_" + oldoption.upper())
|
||||||
|
if envvar_value:
|
||||||
|
break
|
||||||
|
if envvar_value and option_meta.multiple:
|
||||||
|
value = value or []
|
||||||
|
value.extend(self.parse_multi_values(envvar_value))
|
||||||
|
elif envvar_value and not value:
|
||||||
|
value = envvar_value
|
||||||
|
|
||||||
|
# option is not specified by user
|
||||||
|
if value is None:
|
||||||
|
return default
|
||||||
|
|
||||||
|
return self._covert_value(value, option_meta.type)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _covert_value(value, to_type):
|
||||||
|
items = value
|
||||||
|
if not isinstance(value, (list, tuple)):
|
||||||
|
items = [value]
|
||||||
|
for i, v in enumerate(items):
|
||||||
|
if to_type == bool:
|
||||||
|
items[i] = v in ("1", "true", "yes", "y")
|
||||||
|
elif to_type == int:
|
||||||
|
items[i] = int(v)
|
||||||
|
elif to_type == float:
|
||||||
|
items[i] = float(v)
|
||||||
|
return items if isinstance(value, (list, tuple)) else items[0]
|
||||||
|
|
||||||
def envs(self):
|
def envs(self):
|
||||||
return [s[4:] for s in self._parser.sections() if s.startswith("env:")]
|
return [s[4:] for s in self._parser.sections() if s.startswith("env:")]
|
||||||
|
|
||||||
def default_envs(self):
|
def default_envs(self):
|
||||||
if not self._parser.has_option("platformio", "env_default"):
|
return self.get("platformio", "env_default", [])
|
||||||
return []
|
|
||||||
return self.getlist("platformio", "env_default")
|
|
||||||
|
|
||||||
def validate(self, envs=None, validate_options=True):
|
def validate(self, envs=None, silent=False):
|
||||||
if not isfile(self.path):
|
if not isfile(self.path):
|
||||||
raise exception.NotPlatformIOProject(self.path)
|
raise exception.NotPlatformIOProject(self.path)
|
||||||
# check envs
|
# check envs
|
||||||
@ -283,74 +241,65 @@ class ProjectConfig(object):
|
|||||||
if unknown:
|
if unknown:
|
||||||
raise exception.UnknownEnvNames(", ".join(unknown),
|
raise exception.UnknownEnvNames(", ".join(unknown),
|
||||||
", ".join(known))
|
", ".join(known))
|
||||||
return self.validate_options() if validate_options else True
|
return self.validate_options(silent)
|
||||||
|
|
||||||
def validate_options(self):
|
def validate_options(self, silent=False):
|
||||||
return (self._validate_platformio_options()
|
warnings = []
|
||||||
and self._validate_env_options())
|
# legacy `lib_extra_dirs` in [platformio]
|
||||||
|
if (self._parser.has_section("platformio")
|
||||||
def _validate_platformio_options(self):
|
and self._parser.has_option("platformio", "lib_extra_dirs")):
|
||||||
if not self._parser.has_section("platformio"):
|
|
||||||
return True
|
|
||||||
warnings = set()
|
|
||||||
|
|
||||||
# legacy `lib_extra_dirs`
|
|
||||||
if self._parser.has_option("platformio", "lib_extra_dirs"):
|
|
||||||
if not self._parser.has_section("env"):
|
if not self._parser.has_section("env"):
|
||||||
self._parser.add_section("env")
|
self._parser.add_section("env")
|
||||||
self._parser.set("env", "lib_extra_dirs",
|
self._parser.set("env", "lib_extra_dirs",
|
||||||
self._parser.get("platformio", "lib_extra_dirs"))
|
self._parser.get("platformio", "lib_extra_dirs"))
|
||||||
self._parser.remove_option("platformio", "lib_extra_dirs")
|
self._parser.remove_option("platformio", "lib_extra_dirs")
|
||||||
warnings.add(
|
warnings.append(
|
||||||
"`lib_extra_dirs` option is deprecated in section "
|
"`lib_extra_dirs` configuration option is deprecated in "
|
||||||
"`platformio`! Please move it to global `env` section")
|
"section [platformio]! Please move it to global `env` section")
|
||||||
|
|
||||||
unknown = set(k for k, _ in self.items("platformio")) - set(
|
warnings.extend(self._validate_unknown_options())
|
||||||
KNOWN_PLATFORMIO_OPTIONS)
|
|
||||||
if unknown:
|
|
||||||
warnings.add(
|
|
||||||
"Ignore unknown `%s` options in section `[platformio]`" %
|
|
||||||
", ".join(unknown))
|
|
||||||
|
|
||||||
for warning in warnings:
|
if not silent:
|
||||||
click.secho("Warning! %s" % warning, fg="yellow")
|
for warning in warnings:
|
||||||
|
click.secho("Warning! %s" % warning, fg="yellow")
|
||||||
|
|
||||||
return True
|
return warnings
|
||||||
|
|
||||||
def _validate_env_options(self):
|
def _validate_unknown_options(self):
|
||||||
warnings = set()
|
warnings = []
|
||||||
|
renamed_options = {}
|
||||||
|
for option in ProjectOptions.values():
|
||||||
|
if option.oldnames:
|
||||||
|
renamed_options.update(
|
||||||
|
{name: option.name
|
||||||
|
for name in option.oldnames})
|
||||||
|
|
||||||
for section in self._parser.sections():
|
for section in self._parser.sections():
|
||||||
if section != "env" and not section.startswith("env:"):
|
|
||||||
continue
|
|
||||||
for option in self._parser.options(section):
|
for option in self._parser.options(section):
|
||||||
# obsolete
|
# obsolete
|
||||||
if option in RENAMED_OPTIONS:
|
if option in renamed_options:
|
||||||
warnings.add(
|
warnings.append(
|
||||||
"`%s` option in section `[%s]` is deprecated and will "
|
"`%s` configuration option in section [%s] is "
|
||||||
"be removed in the next release! Please use `%s` "
|
"deprecated and will be removed in the next release! "
|
||||||
"instead" % (option, section, RENAMED_OPTIONS[option]))
|
"Please use `%s` instead" % (option, section,
|
||||||
|
renamed_options[option]))
|
||||||
# rename on-the-fly
|
# rename on-the-fly
|
||||||
self._parser.set(section, RENAMED_OPTIONS[option],
|
self._parser.set(section, renamed_options[option],
|
||||||
self._parser.get(section, option))
|
self._parser.get(section, option))
|
||||||
self._parser.remove_option(section, option)
|
self._parser.remove_option(section, option)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# unknown
|
# unknown
|
||||||
|
scope = section.split(":", 1)[0]
|
||||||
unknown_conditions = [
|
unknown_conditions = [
|
||||||
option not in KNOWN_ENV_OPTIONS,
|
("%s.%s" % (scope, option)) not in ProjectOptions,
|
||||||
not option.startswith("custom_"),
|
scope != "env" or
|
||||||
not option.startswith("board_")
|
not option.startswith(("custom_", "board_"))
|
||||||
] # yapf: disable
|
] # yapf: disable
|
||||||
if all(unknown_conditions):
|
if all(unknown_conditions):
|
||||||
warnings.add(
|
warnings.append("Ignore unknown configuration option `%s` "
|
||||||
"Detected non-PlatformIO `%s` option in `[%s]` section"
|
"in section [%s]" % (option, section))
|
||||||
% (option, section))
|
return warnings
|
||||||
|
|
||||||
for warning in warnings:
|
|
||||||
click.secho("Warning! %s" % warning, fg="yellow")
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
def to_json(self):
|
def to_json(self):
|
||||||
result = {}
|
result = {}
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
import os
|
import os
|
||||||
from hashlib import sha1
|
from hashlib import sha1
|
||||||
from os import walk
|
from os import walk
|
||||||
from os.path import (abspath, dirname, expanduser, isdir, isfile, join,
|
from os.path import (dirname, expanduser, isdir, isfile, join, realpath,
|
||||||
splitdrive)
|
splitdrive)
|
||||||
|
|
||||||
from platformio import __version__
|
from platformio import __version__
|
||||||
@ -44,46 +44,31 @@ def find_project_dir_above(path):
|
|||||||
|
|
||||||
|
|
||||||
def get_project_optional_dir(name, default=None):
|
def get_project_optional_dir(name, default=None):
|
||||||
paths = None
|
project_dir = get_project_dir()
|
||||||
|
config = ProjectConfig.get_instance(join(project_dir, "platformio.ini"))
|
||||||
|
optional_dir = config.get("platformio", name)
|
||||||
|
|
||||||
# check for system environment variable
|
if not optional_dir:
|
||||||
var_name = "PLATFORMIO_%s" % name.upper()
|
|
||||||
if var_name in os.environ:
|
|
||||||
paths = os.getenv(var_name)
|
|
||||||
|
|
||||||
config = ProjectConfig.get_instance(
|
|
||||||
join(get_project_dir(), "platformio.ini"))
|
|
||||||
if (config.has_section("platformio")
|
|
||||||
and config.has_option("platformio", name)):
|
|
||||||
paths = config.get("platformio", name)
|
|
||||||
|
|
||||||
if not paths:
|
|
||||||
return default
|
return default
|
||||||
|
|
||||||
items = []
|
if "$PROJECT_HASH" in optional_dir:
|
||||||
for item in paths.split(", "):
|
optional_dir = optional_dir.replace(
|
||||||
if item.startswith("~"):
|
|
||||||
item = expanduser(item)
|
|
||||||
items.append(abspath(item))
|
|
||||||
paths = ", ".join(items)
|
|
||||||
|
|
||||||
while "$PROJECT_HASH" in paths:
|
|
||||||
project_dir = get_project_dir()
|
|
||||||
paths = paths.replace(
|
|
||||||
"$PROJECT_HASH",
|
"$PROJECT_HASH",
|
||||||
sha1(project_dir if PY2 else project_dir.encode()).hexdigest()
|
sha1(project_dir if PY2 else project_dir.encode()).hexdigest()
|
||||||
[:10])
|
[:10])
|
||||||
|
|
||||||
return paths
|
if optional_dir.startswith("~"):
|
||||||
|
optional_dir = expanduser(optional_dir)
|
||||||
|
|
||||||
|
return realpath(optional_dir)
|
||||||
|
|
||||||
|
|
||||||
def get_project_core_dir():
|
def get_project_core_dir():
|
||||||
|
default = join(expanduser("~"), ".platformio")
|
||||||
core_dir = get_project_optional_dir(
|
core_dir = get_project_optional_dir(
|
||||||
"core_dir",
|
"core_dir", get_project_optional_dir("home_dir", default))
|
||||||
get_project_optional_dir("home_dir",
|
|
||||||
join(expanduser("~"), ".platformio")))
|
|
||||||
win_core_dir = None
|
win_core_dir = None
|
||||||
if WINDOWS:
|
if WINDOWS and core_dir == default:
|
||||||
win_core_dir = splitdrive(core_dir)[0] + "\\.platformio"
|
win_core_dir = splitdrive(core_dir)[0] + "\\.platformio"
|
||||||
if isdir(win_core_dir):
|
if isdir(win_core_dir):
|
||||||
core_dir = win_core_dir
|
core_dir = win_core_dir
|
||||||
@ -91,10 +76,12 @@ def get_project_core_dir():
|
|||||||
if not isdir(core_dir):
|
if not isdir(core_dir):
|
||||||
try:
|
try:
|
||||||
os.makedirs(core_dir)
|
os.makedirs(core_dir)
|
||||||
except: # pylint: disable=bare-except
|
except OSError as e:
|
||||||
if win_core_dir:
|
if win_core_dir:
|
||||||
os.makedirs(win_core_dir)
|
os.makedirs(win_core_dir)
|
||||||
core_dir = win_core_dir
|
core_dir = win_core_dir
|
||||||
|
else:
|
||||||
|
raise e
|
||||||
|
|
||||||
assert isdir(core_dir)
|
assert isdir(core_dir)
|
||||||
return core_dir
|
return core_dir
|
||||||
|
198
platformio/project/options.py
Normal file
198
platformio/project/options.py
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
# Copyright (c) 2014-present PlatformIO <contact@platformio.org>
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
# pylint: disable=redefined-builtin, too-many-arguments
|
||||||
|
|
||||||
|
from collections import OrderedDict, namedtuple
|
||||||
|
|
||||||
|
ConfigOptionClass = namedtuple("ConfigOption", [
|
||||||
|
"scope", "name", "type", "multiple", "sysenvvar", "buildenvvar", "oldnames"
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
def ConfigOption(scope,
|
||||||
|
name,
|
||||||
|
type=str,
|
||||||
|
multiple=False,
|
||||||
|
sysenvvar=None,
|
||||||
|
buildenvvar=None,
|
||||||
|
oldnames=None):
|
||||||
|
return ConfigOptionClass(scope, name, type, multiple, sysenvvar,
|
||||||
|
buildenvvar, oldnames)
|
||||||
|
|
||||||
|
|
||||||
|
def ConfigPlatformioOption(*args, **kwargs):
|
||||||
|
return ConfigOption("platformio", *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
def ConfigEnvOption(*args, **kwargs):
|
||||||
|
return ConfigOption("env", *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
ProjectOptions = OrderedDict([
|
||||||
|
("%s.%s" % (option.scope, option.name), option) for option in [
|
||||||
|
#
|
||||||
|
# [platformio]
|
||||||
|
#
|
||||||
|
ConfigPlatformioOption(name="description"),
|
||||||
|
ConfigPlatformioOption(
|
||||||
|
name="env_default",
|
||||||
|
multiple=True,
|
||||||
|
sysenvvar="PLATFORMIO_ENV_DEFAULT"),
|
||||||
|
ConfigPlatformioOption(name="extra_configs", multiple=True),
|
||||||
|
|
||||||
|
# Dirs
|
||||||
|
ConfigPlatformioOption(
|
||||||
|
name="core_dir",
|
||||||
|
oldnames=["home_dir"],
|
||||||
|
sysenvvar="PLATFORMIO_CORE_DIR"),
|
||||||
|
ConfigPlatformioOption(
|
||||||
|
name="globallib_dir", sysenvvar="PLATFORMIO_GLOBALLIB_DIR"),
|
||||||
|
ConfigPlatformioOption(
|
||||||
|
name="platforms_dir", sysenvvar="PLATFORMIO_PLATFORMS_DIR"),
|
||||||
|
ConfigPlatformioOption(
|
||||||
|
name="packages_dir", sysenvvar="PLATFORMIO_PACKAGES_DIR"),
|
||||||
|
ConfigPlatformioOption(
|
||||||
|
name="cache_dir", sysenvvar="PLATFORMIO_CACHE_DIR"),
|
||||||
|
ConfigPlatformioOption(
|
||||||
|
name="workspace_dir", sysenvvar="PLATFORMIO_WORKSPACE_DIR"),
|
||||||
|
ConfigPlatformioOption(
|
||||||
|
name="build_dir", sysenvvar="PLATFORMIO_BUILD_DIR"),
|
||||||
|
ConfigPlatformioOption(
|
||||||
|
name="libdeps_dir", sysenvvar="PLATFORMIO_LIBDEPS_DIR"),
|
||||||
|
ConfigPlatformioOption(name="lib_dir", sysenvvar="PLATFORMIO_LIB_DIR"),
|
||||||
|
ConfigPlatformioOption(
|
||||||
|
name="include_dir", sysenvvar="PLATFORMIO_INCLUDE_DIR"),
|
||||||
|
ConfigPlatformioOption(name="src_dir", sysenvvar="PLATFORMIO_SRC_DIR"),
|
||||||
|
ConfigPlatformioOption(
|
||||||
|
name="test_dir", sysenvvar="PLATFORMIO_TEST_DIR"),
|
||||||
|
ConfigPlatformioOption(
|
||||||
|
name="boards_dir", sysenvvar="PLATFORMIO_BOARDS_DIR"),
|
||||||
|
ConfigPlatformioOption(
|
||||||
|
name="data_dir", sysenvvar="PLATFORMIO_DATA_DIR"),
|
||||||
|
|
||||||
|
#
|
||||||
|
# [env]
|
||||||
|
#
|
||||||
|
|
||||||
|
# Generic
|
||||||
|
ConfigEnvOption(name="platform", buildenvvar="PIOPLATFORM"),
|
||||||
|
ConfigEnvOption(
|
||||||
|
name="framework", multiple=True, buildenvvar="PIOFRAMEWORK"),
|
||||||
|
ConfigEnvOption(name="targets", multiple=True),
|
||||||
|
|
||||||
|
# Board
|
||||||
|
ConfigEnvOption(name="board", buildenvvar="BOARD"),
|
||||||
|
ConfigEnvOption(
|
||||||
|
name="board_build.mcu",
|
||||||
|
oldnames=["board_mcu"],
|
||||||
|
buildenvvar="BOARD_MCU"),
|
||||||
|
ConfigEnvOption(
|
||||||
|
name="board_build.f_cpu",
|
||||||
|
oldnames=["board_f_cpu"],
|
||||||
|
buildenvvar="BOARD_F_CPU"),
|
||||||
|
ConfigEnvOption(
|
||||||
|
name="board_build.f_flash",
|
||||||
|
oldnames=["board_f_flash"],
|
||||||
|
buildenvvar="BOARD_F_FLASH"),
|
||||||
|
ConfigEnvOption(
|
||||||
|
name="board_build.flash_mode",
|
||||||
|
oldnames=["board_flash_mode"],
|
||||||
|
buildenvvar="BOARD_FLASH_MODE"),
|
||||||
|
|
||||||
|
# Build
|
||||||
|
ConfigEnvOption(
|
||||||
|
name="build_flags",
|
||||||
|
multiple=True,
|
||||||
|
sysenvvar="PLATFORMIO_BUILD_FLAGS",
|
||||||
|
buildenvvar="BUILD_FLAGS"),
|
||||||
|
ConfigEnvOption(
|
||||||
|
name="src_build_flags",
|
||||||
|
multiple=True,
|
||||||
|
sysenvvar="PLATFORMIO_SRC_BUILD_FLAGS",
|
||||||
|
buildenvvar="SRC_BUILD_FLAGS"),
|
||||||
|
ConfigEnvOption(
|
||||||
|
name="build_unflags",
|
||||||
|
multiple=True,
|
||||||
|
sysenvvar="PLATFORMIO_BUILD_UNFLAGS",
|
||||||
|
buildenvvar="BUILD_UNFLAGS"),
|
||||||
|
ConfigEnvOption(
|
||||||
|
name="src_filter",
|
||||||
|
multiple=True,
|
||||||
|
sysenvvar="PLATFORMIO_SRC_FILTER",
|
||||||
|
buildenvvar="SRC_FILTER"),
|
||||||
|
|
||||||
|
# Upload
|
||||||
|
ConfigEnvOption(
|
||||||
|
name="upload_port",
|
||||||
|
sysenvvar="PLATFORMIO_UPLOAD_PORT",
|
||||||
|
buildenvvar="UPLOAD_PORT"),
|
||||||
|
ConfigEnvOption(name="upload_protocol", buildenvvar="UPLOAD_PROTOCOL"),
|
||||||
|
ConfigEnvOption(name="upload_speed", buildenvvar="UPLOAD_SPEED"),
|
||||||
|
ConfigEnvOption(
|
||||||
|
name="upload_flags",
|
||||||
|
multiple=True,
|
||||||
|
sysenvvar="PLATFORMIO_UPLOAD_FLAGS",
|
||||||
|
buildenvvar="UPLOAD_FLAGS"),
|
||||||
|
ConfigEnvOption(
|
||||||
|
name="upload_resetmethod", buildenvvar="UPLOAD_RESETMETHOD"),
|
||||||
|
|
||||||
|
# Monitor
|
||||||
|
ConfigEnvOption(name="monitor_port"),
|
||||||
|
ConfigEnvOption(name="monitor_speed", oldnames=["monitor_baud"]),
|
||||||
|
ConfigEnvOption(name="monitor_rts"),
|
||||||
|
ConfigEnvOption(name="monitor_dtr"),
|
||||||
|
ConfigEnvOption(name="monitor_flags", multiple=True),
|
||||||
|
|
||||||
|
# Library
|
||||||
|
ConfigEnvOption(
|
||||||
|
name="lib_deps",
|
||||||
|
oldnames=["lib_use", "lib_force", "lib_install"],
|
||||||
|
multiple=True),
|
||||||
|
ConfigEnvOption(name="lib_ignore", multiple=True),
|
||||||
|
ConfigEnvOption(
|
||||||
|
name="lib_extra_dirs",
|
||||||
|
multiple=True,
|
||||||
|
sysenvvar="PLATFORMIO_LIB_EXTRA_DIRS"),
|
||||||
|
ConfigEnvOption(name="lib_ldf_mode"),
|
||||||
|
ConfigEnvOption(name="lib_compat_mode"),
|
||||||
|
ConfigEnvOption(name="lib_archive", type=bool),
|
||||||
|
|
||||||
|
# Test
|
||||||
|
ConfigEnvOption(name="test_filter", multiple=True),
|
||||||
|
ConfigEnvOption(name="test_ignore", multiple=True),
|
||||||
|
ConfigEnvOption(name="test_port"),
|
||||||
|
ConfigEnvOption(name="test_speed"),
|
||||||
|
ConfigEnvOption(name="test_transport"),
|
||||||
|
ConfigEnvOption(name="test_build_project_src"),
|
||||||
|
|
||||||
|
# Debug
|
||||||
|
ConfigEnvOption(name="debug_tool"),
|
||||||
|
ConfigEnvOption(name="debug_init_break"),
|
||||||
|
ConfigEnvOption(name="debug_init_cmds", multiple=True),
|
||||||
|
ConfigEnvOption(name="debug_extra_cmds", multiple=True),
|
||||||
|
ConfigEnvOption(name="debug_load_cmd"),
|
||||||
|
ConfigEnvOption(name="debug_load_mode"),
|
||||||
|
ConfigEnvOption(name="debug_server"),
|
||||||
|
ConfigEnvOption(name="debug_port"),
|
||||||
|
ConfigEnvOption(name="debug_svd_path"),
|
||||||
|
|
||||||
|
# Other
|
||||||
|
ConfigEnvOption(
|
||||||
|
name="extra_scripts",
|
||||||
|
oldnames=["extra_script"],
|
||||||
|
multiple=True,
|
||||||
|
sysenvvar="PLATFORMIO_EXTRA_SCRIPTS")
|
||||||
|
]
|
||||||
|
])
|
@ -310,12 +310,15 @@ def measure_ci():
|
|||||||
|
|
||||||
|
|
||||||
def on_run_environment(options, targets):
|
def on_run_environment(options, targets):
|
||||||
opts = [
|
non_sensative_values = ["board", "platform", "framework"]
|
||||||
"%s=%s" % (opt, value.replace("\n", ", ") if "\n" in value else value)
|
safe_options = []
|
||||||
for opt, value in sorted(options.items())
|
for key, value in sorted(options.items()):
|
||||||
]
|
if key in non_sensative_values:
|
||||||
|
safe_options.append("%s=%s" % (key, value))
|
||||||
|
else:
|
||||||
|
safe_options.append(key)
|
||||||
targets = [t.title() for t in targets or ["run"]]
|
targets = [t.title() for t in targets or ["run"]]
|
||||||
on_event("Env", " ".join(targets), "&".join(opts))
|
on_event("Env", " ".join(targets), "&".join(safe_options))
|
||||||
|
|
||||||
|
|
||||||
def on_event(category, action, label=None, value=None, screen_name=None):
|
def on_event(category, action, label=None, value=None, screen_name=None):
|
||||||
|
@ -20,7 +20,7 @@ from platformio.commands.lib import cli as cmd_lib
|
|||||||
|
|
||||||
def test_ci_empty(clirunner):
|
def test_ci_empty(clirunner):
|
||||||
result = clirunner.invoke(cmd_ci)
|
result = clirunner.invoke(cmd_ci)
|
||||||
assert result.exit_code == 2
|
assert result.exit_code != 0
|
||||||
assert "Invalid value: Missing argument 'src'" in result.output
|
assert "Invalid value: Missing argument 'src'" in result.output
|
||||||
|
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ import json
|
|||||||
from os import getcwd, makedirs
|
from os import getcwd, makedirs
|
||||||
from os.path import getsize, isdir, isfile, join
|
from os.path import getsize, isdir, isfile, join
|
||||||
|
|
||||||
from platformio import exception, util
|
from platformio import exception
|
||||||
from platformio.commands.boards import cli as cmd_boards
|
from platformio.commands.boards import cli as cmd_boards
|
||||||
from platformio.commands.init import cli as cmd_init
|
from platformio.commands.init import cli as cmd_init
|
||||||
from platformio.project.config import ProjectConfig
|
from platformio.project.config import ProjectConfig
|
||||||
@ -109,13 +109,13 @@ def test_init_special_board(clirunner, validate_cliresult):
|
|||||||
|
|
||||||
config = ProjectConfig(join(getcwd(), "platformio.ini"))
|
config = ProjectConfig(join(getcwd(), "platformio.ini"))
|
||||||
config.validate()
|
config.validate()
|
||||||
expected_result = [("platform", str(boards[0]['platform'])),
|
|
||||||
("framework",
|
|
||||||
str(boards[0]['frameworks'][0])), ("board", "uno")]
|
|
||||||
|
|
||||||
|
expected_result = dict(platform=str(boards[0]['platform']),
|
||||||
|
board="uno",
|
||||||
|
framework=[str(boards[0]['frameworks'][0])])
|
||||||
assert config.has_section("env:uno")
|
assert config.has_section("env:uno")
|
||||||
assert not set(expected_result).symmetric_difference(
|
assert sorted(config.items(env="uno", as_dict=True).items()) == sorted(
|
||||||
set(config.items("env:uno")))
|
expected_result.items())
|
||||||
|
|
||||||
|
|
||||||
def test_init_enable_auto_uploading(clirunner, validate_cliresult):
|
def test_init_enable_auto_uploading(clirunner, validate_cliresult):
|
||||||
@ -126,11 +126,13 @@ def test_init_enable_auto_uploading(clirunner, validate_cliresult):
|
|||||||
validate_pioproject(getcwd())
|
validate_pioproject(getcwd())
|
||||||
config = ProjectConfig(join(getcwd(), "platformio.ini"))
|
config = ProjectConfig(join(getcwd(), "platformio.ini"))
|
||||||
config.validate()
|
config.validate()
|
||||||
expected_result = [("platform", "atmelavr"), ("framework", "arduino"),
|
expected_result = dict(targets=["upload"],
|
||||||
("board", "uno"), ("targets", "upload")]
|
platform="atmelavr",
|
||||||
|
board="uno",
|
||||||
|
framework=["arduino"])
|
||||||
assert config.has_section("env:uno")
|
assert config.has_section("env:uno")
|
||||||
assert not set(expected_result).symmetric_difference(
|
assert sorted(config.items(env="uno", as_dict=True).items()) == sorted(
|
||||||
set(config.items("env:uno")))
|
expected_result.items())
|
||||||
|
|
||||||
|
|
||||||
def test_init_custom_framework(clirunner, validate_cliresult):
|
def test_init_custom_framework(clirunner, validate_cliresult):
|
||||||
@ -141,11 +143,13 @@ def test_init_custom_framework(clirunner, validate_cliresult):
|
|||||||
validate_pioproject(getcwd())
|
validate_pioproject(getcwd())
|
||||||
config = ProjectConfig(join(getcwd(), "platformio.ini"))
|
config = ProjectConfig(join(getcwd(), "platformio.ini"))
|
||||||
config.validate()
|
config.validate()
|
||||||
expected_result = [("platform", "teensy"), ("framework", "mbed"),
|
expected_result = dict(platform="teensy",
|
||||||
("board", "teensy31")]
|
board="teensy31",
|
||||||
|
framework=["mbed"])
|
||||||
assert config.has_section("env:teensy31")
|
assert config.has_section("env:teensy31")
|
||||||
assert not set(expected_result).symmetric_difference(
|
assert sorted(config.items(env="teensy31",
|
||||||
set(config.items("env:teensy31")))
|
as_dict=True).items()) == sorted(
|
||||||
|
expected_result.items())
|
||||||
|
|
||||||
|
|
||||||
def test_init_incorrect_board(clirunner):
|
def test_init_incorrect_board(clirunner):
|
||||||
|
@ -14,7 +14,9 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from platformio.project.config import ProjectConfig
|
import pytest
|
||||||
|
|
||||||
|
from platformio.project.config import ConfigParser, ProjectConfig
|
||||||
|
|
||||||
BASE_CONFIG = """
|
BASE_CONFIG = """
|
||||||
[platformio]
|
[platformio]
|
||||||
@ -26,7 +28,9 @@ extra_configs =
|
|||||||
# global options per [env:*]
|
# global options per [env:*]
|
||||||
[env]
|
[env]
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
lib_deps = Lib1, Lib2
|
lib_deps =
|
||||||
|
Lib1
|
||||||
|
Lib2
|
||||||
lib_ignore = ${custom.lib_ignore}
|
lib_ignore = ${custom.lib_ignore}
|
||||||
|
|
||||||
[custom]
|
[custom]
|
||||||
@ -46,6 +50,7 @@ build_flags = ${custom.lib_flags} ${custom.debug_flags}
|
|||||||
[env:extra_2]
|
[env:extra_2]
|
||||||
build_flags = ${custom.debug_flags} ${custom.extra_flags}
|
build_flags = ${custom.debug_flags} ${custom.extra_flags}
|
||||||
lib_ignore = ${env.lib_ignore}, Lib3
|
lib_ignore = ${env.lib_ignore}, Lib3
|
||||||
|
upload_port = /dev/extra_2/port
|
||||||
"""
|
"""
|
||||||
|
|
||||||
EXTRA_DEBUG_CONFIG = """
|
EXTRA_DEBUG_CONFIG = """
|
||||||
@ -58,7 +63,7 @@ build_flags = -Og
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
def test_parser(tmpdir):
|
def test_real_config(tmpdir):
|
||||||
tmpdir.join("platformio.ini").write(BASE_CONFIG)
|
tmpdir.join("platformio.ini").write(BASE_CONFIG)
|
||||||
tmpdir.join("extra_envs.ini").write(EXTRA_ENVS_CONFIG)
|
tmpdir.join("extra_envs.ini").write(EXTRA_ENVS_CONFIG)
|
||||||
tmpdir.join("extra_debug.ini").write(EXTRA_DEBUG_CONFIG)
|
tmpdir.join("extra_debug.ini").write(EXTRA_DEBUG_CONFIG)
|
||||||
@ -68,6 +73,16 @@ def test_parser(tmpdir):
|
|||||||
config = ProjectConfig(tmpdir.join("platformio.ini").strpath)
|
config = ProjectConfig(tmpdir.join("platformio.ini").strpath)
|
||||||
assert config
|
assert config
|
||||||
|
|
||||||
|
# unknown section
|
||||||
|
with pytest.raises(ConfigParser.NoSectionError):
|
||||||
|
config.getraw("unknown_section", "unknown_option")
|
||||||
|
# unknown option
|
||||||
|
with pytest.raises(ConfigParser.NoOptionError):
|
||||||
|
config.getraw("custom", "unknown_option")
|
||||||
|
# unknown option even if exists in [env]
|
||||||
|
with pytest.raises(ConfigParser.NoOptionError):
|
||||||
|
config.getraw("platformio", "monitor_speed")
|
||||||
|
|
||||||
# sections
|
# sections
|
||||||
assert config.sections() == [
|
assert config.sections() == [
|
||||||
"platformio", "env", "custom", "env:base", "env:extra_1", "env:extra_2"
|
"platformio", "env", "custom", "env:base", "env:extra_1", "env:extra_2"
|
||||||
@ -87,30 +102,76 @@ def test_parser(tmpdir):
|
|||||||
assert not config.has_option("custom", "monitor_speed")
|
assert not config.has_option("custom", "monitor_speed")
|
||||||
|
|
||||||
# sysenv
|
# sysenv
|
||||||
assert config.get("custom", "extra_flags") == ""
|
assert config.get("custom", "extra_flags") is None
|
||||||
|
assert config.get("env:base", "build_flags") == ["-D DEBUG=1"]
|
||||||
|
assert config.get("env:base", "upload_port") is None
|
||||||
|
assert config.get("env:extra_2", "upload_port") == "/dev/extra_2/port"
|
||||||
|
os.environ["PLATFORMIO_BUILD_FLAGS"] = "-DSYSENVDEPS1 -DSYSENVDEPS2"
|
||||||
|
os.environ["PLATFORMIO_UPLOAD_PORT"] = "/dev/sysenv/port"
|
||||||
os.environ["__PIO_TEST_CNF_EXTRA_FLAGS"] = "-L /usr/local/lib"
|
os.environ["__PIO_TEST_CNF_EXTRA_FLAGS"] = "-L /usr/local/lib"
|
||||||
assert config.get("custom", "extra_flags") == "-L /usr/local/lib"
|
assert config.get("custom", "extra_flags") == "-L /usr/local/lib"
|
||||||
|
assert config.get("env:base", "build_flags") == [
|
||||||
|
"-D DEBUG=1 -L /usr/local/lib", "-DSYSENVDEPS1 -DSYSENVDEPS2"
|
||||||
|
]
|
||||||
|
assert config.get("env:base", "upload_port") == "/dev/sysenv/port"
|
||||||
|
assert config.get("env:extra_2", "upload_port") == "/dev/extra_2/port"
|
||||||
|
|
||||||
|
# getraw
|
||||||
|
assert config.getraw("env:extra_1", "lib_deps") == "\nLib1\nLib2"
|
||||||
|
assert config.getraw("env:extra_1", "build_flags") == "-lc -lm -D DEBUG=1"
|
||||||
|
|
||||||
# get
|
# get
|
||||||
assert config.get("custom", "debug_flags") == "-D DEBUG=1"
|
assert config.get("custom", "debug_flags") == "-D DEBUG=1"
|
||||||
assert config.get("env:extra_1", "build_flags") == "-lc -lm -D DEBUG=1"
|
assert config.get("env:extra_1", "build_flags") == [
|
||||||
assert config.get("env:extra_2", "build_flags") == "-Og"
|
"-lc -lm -D DEBUG=1", "-DSYSENVDEPS1 -DSYSENVDEPS2"
|
||||||
|
]
|
||||||
|
assert config.get("env:extra_2", "build_flags") == [
|
||||||
|
"-Og", "-DSYSENVDEPS1 -DSYSENVDEPS2"]
|
||||||
assert config.get("env:extra_2", "monitor_speed") == "115200"
|
assert config.get("env:extra_2", "monitor_speed") == "115200"
|
||||||
assert config.get("env:base",
|
assert config.get("env:base", "build_flags") == ([
|
||||||
"build_flags") == ("-D DEBUG=1 -L /usr/local/lib")
|
"-D DEBUG=1 -L /usr/local/lib", "-DSYSENVDEPS1 -DSYSENVDEPS2"
|
||||||
|
])
|
||||||
|
|
||||||
# items
|
# items
|
||||||
assert config.items("custom") == [("debug_flags", "-D DEBUG=1"),
|
assert config.items("custom") == [
|
||||||
("lib_flags", "-lc -lm"),
|
("debug_flags", "-D DEBUG=1"),
|
||||||
("extra_flags", "-L /usr/local/lib"),
|
("lib_flags", "-lc -lm"),
|
||||||
("lib_ignore", "LibIgnoreCustom")]
|
("extra_flags", "-L /usr/local/lib"),
|
||||||
assert config.items(env="extra_1") == [("build_flags",
|
("lib_ignore", "LibIgnoreCustom")
|
||||||
"-lc -lm -D DEBUG=1"),
|
] # yapf: disable
|
||||||
("monitor_speed", "115200"),
|
assert config.items(env="extra_1") == [
|
||||||
("lib_deps", "Lib1, Lib2"),
|
("build_flags", ["-lc -lm -D DEBUG=1", "-DSYSENVDEPS1 -DSYSENVDEPS2"]),
|
||||||
("lib_ignore", "LibIgnoreCustom")]
|
("monitor_speed", "115200"),
|
||||||
assert config.items(env="extra_2") == [("build_flags", "-Og"),
|
("lib_deps", ["Lib1", "Lib2"]),
|
||||||
("lib_ignore",
|
("lib_ignore", ["LibIgnoreCustom"]),
|
||||||
"LibIgnoreCustom, Lib3"),
|
("upload_port", "/dev/sysenv/port")
|
||||||
("monitor_speed", "115200"),
|
] # yapf: disable
|
||||||
("lib_deps", "Lib1, Lib2")]
|
assert config.items(env="extra_2") == [
|
||||||
|
("build_flags", ["-Og", "-DSYSENVDEPS1 -DSYSENVDEPS2"]),
|
||||||
|
("lib_ignore", ["LibIgnoreCustom", "Lib3"]),
|
||||||
|
("upload_port", "/dev/extra_2/port"),
|
||||||
|
("monitor_speed", "115200"),
|
||||||
|
("lib_deps", ["Lib1", "Lib2"])
|
||||||
|
] # yapf: disable
|
||||||
|
|
||||||
|
# cleanup system environment variables
|
||||||
|
del os.environ["PLATFORMIO_BUILD_FLAGS"]
|
||||||
|
del os.environ["PLATFORMIO_UPLOAD_PORT"]
|
||||||
|
del os.environ["__PIO_TEST_CNF_EXTRA_FLAGS"]
|
||||||
|
|
||||||
|
|
||||||
|
def test_empty_config():
|
||||||
|
config = ProjectConfig("/non/existing/platformio.ini")
|
||||||
|
|
||||||
|
# unknown section
|
||||||
|
with pytest.raises(ConfigParser.NoSectionError):
|
||||||
|
config.getraw("unknown_section", "unknown_option")
|
||||||
|
|
||||||
|
assert config.sections() == []
|
||||||
|
assert config.get("section", "option") is None
|
||||||
|
assert config.get("section", "option", 13) == 13
|
||||||
|
|
||||||
|
# sysenv
|
||||||
|
os.environ["PLATFORMIO_HOME_DIR"] = "/custom/core/dir"
|
||||||
|
assert config.get("platformio", "core_dir") == "/custom/core/dir"
|
||||||
|
del os.environ["PLATFORMIO_HOME_DIR"]
|
||||||
|
Reference in New Issue
Block a user