mirror of
https://github.com/platformio/platformio-core.git
synced 2025-07-30 10:07:14 +02:00
Merge branch 'hotfix/v3.6.6'
This commit is contained in:
12
HISTORY.rst
12
HISTORY.rst
@ -4,6 +4,18 @@ Release Notes
|
|||||||
PlatformIO 3.0
|
PlatformIO 3.0
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
|
3.6.6 (2019-03-29)
|
||||||
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
* Project Generator: fixed a warning "Property !!! WARNING !!! is not allowed" for VSCode
|
||||||
|
(`issue #2243 <https://github.com/platformio/platformio-core/issues/2243>`_)
|
||||||
|
* Fixed an issue when PlatformIO Build System does not pick up "mbed_lib.json" files from libraries
|
||||||
|
(`issue #2164 <https://github.com/platformio/platformio-core/issues/2164>`_)
|
||||||
|
* Fixed an error with conflicting declaration of a prototype (Arduino sketch preprocessor)
|
||||||
|
* Fixed "FileExistsError" when `platformio ci <https://docs.platformio.org/en/latest/userguide/cmd_ci.html>`__ command is used in pair with ``--keep-build-dir`` option
|
||||||
|
* Fixed an issue with incorrect order of project "include" and "src" paths in ``CPPPATH``
|
||||||
|
(`issue #1914 <https://github.com/platformio/platformio-core/issues/1914>`_)
|
||||||
|
|
||||||
3.6.5 (2019-03-07)
|
3.6.5 (2019-03-07)
|
||||||
~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
2
docs
2
docs
Submodule docs updated: 768ccfd2b4...3a6c69a1ae
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
VERSION = (3, 6, 5)
|
VERSION = (3, 6, 6)
|
||||||
__version__ = ".".join([str(s) for s in VERSION])
|
__version__ = ".".join([str(s) for s in VERSION])
|
||||||
|
|
||||||
__title__ = "platformio"
|
__title__ = "platformio"
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
# pylint: disable=no-member, no-self-use, unused-argument
|
# pylint: disable=no-member, no-self-use, unused-argument, too-many-lines
|
||||||
# pylint: disable=too-many-instance-attributes, too-many-public-methods
|
# pylint: disable=too-many-instance-attributes, too-many-public-methods
|
||||||
|
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
@ -70,6 +70,8 @@ class LibBuilderFactory(object):
|
|||||||
|
|
||||||
# check source files
|
# check source files
|
||||||
for root, _, files in os.walk(path, followlinks=True):
|
for root, _, files in os.walk(path, followlinks=True):
|
||||||
|
if "mbed_lib.json" in files:
|
||||||
|
return ["mbed"]
|
||||||
for fname in files:
|
for fname in files:
|
||||||
if not env.IsFileWithExt(
|
if not env.IsFileWithExt(
|
||||||
fname, piotool.SRC_BUILD_EXT + piotool.SRC_HEADER_EXT):
|
fname, piotool.SRC_BUILD_EXT + piotool.SRC_HEADER_EXT):
|
||||||
@ -175,10 +177,11 @@ class LibBuilderBase(object):
|
|||||||
if isdir(join(self.path, "src")) else self.path)
|
if isdir(join(self.path, "src")) else self.path)
|
||||||
|
|
||||||
def get_include_dirs(self):
|
def get_include_dirs(self):
|
||||||
items = [self.src_dir]
|
items = []
|
||||||
include_dir = self.include_dir
|
include_dir = self.include_dir
|
||||||
if include_dir and include_dir not in items:
|
if include_dir and include_dir not in items:
|
||||||
items.append(include_dir)
|
items.append(include_dir)
|
||||||
|
items.append(self.src_dir)
|
||||||
return items
|
return items
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -260,7 +263,6 @@ class LibBuilderBase(object):
|
|||||||
|
|
||||||
def process_extra_options(self):
|
def process_extra_options(self):
|
||||||
with util.cd(self.path):
|
with util.cd(self.path):
|
||||||
self.env.ProcessUnFlags(self.build_unflags)
|
|
||||||
self.env.ProcessFlags(self.build_flags)
|
self.env.ProcessFlags(self.build_flags)
|
||||||
if self.extra_script:
|
if self.extra_script:
|
||||||
self.env.SConscriptChdir(1)
|
self.env.SConscriptChdir(1)
|
||||||
@ -270,6 +272,7 @@ class LibBuilderBase(object):
|
|||||||
"env": self.env,
|
"env": self.env,
|
||||||
"pio_lib_builder": self
|
"pio_lib_builder": self
|
||||||
})
|
})
|
||||||
|
self.env.ProcessUnFlags(self.build_unflags)
|
||||||
|
|
||||||
def process_dependencies(self):
|
def process_dependencies(self):
|
||||||
if not self.dependencies:
|
if not self.dependencies:
|
||||||
@ -588,6 +591,111 @@ class MbedLibBuilder(LibBuilderBase):
|
|||||||
def is_frameworks_compatible(self, frameworks):
|
def is_frameworks_compatible(self, frameworks):
|
||||||
return util.items_in_list(frameworks, ["mbed"])
|
return util.items_in_list(frameworks, ["mbed"])
|
||||||
|
|
||||||
|
def process_extra_options(self):
|
||||||
|
self._process_mbed_lib_confs()
|
||||||
|
return super(MbedLibBuilder, self).process_extra_options()
|
||||||
|
|
||||||
|
def _process_mbed_lib_confs(self):
|
||||||
|
mbed_lib_paths = [
|
||||||
|
join(root, "mbed_lib.json")
|
||||||
|
for root, _, files in os.walk(self.path)
|
||||||
|
if "mbed_lib.json" in files
|
||||||
|
]
|
||||||
|
if not mbed_lib_paths:
|
||||||
|
return None
|
||||||
|
|
||||||
|
mbed_config_path = None
|
||||||
|
for p in self.env.get("CPPPATH"):
|
||||||
|
mbed_config_path = join(self.env.subst(p), "mbed_config.h")
|
||||||
|
if isfile(mbed_config_path):
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
mbed_config_path = None
|
||||||
|
if not mbed_config_path:
|
||||||
|
return None
|
||||||
|
|
||||||
|
macros = {}
|
||||||
|
for mbed_lib_path in mbed_lib_paths:
|
||||||
|
macros.update(self._mbed_lib_conf_parse_macros(mbed_lib_path))
|
||||||
|
|
||||||
|
self._mbed_conf_append_macros(mbed_config_path, macros)
|
||||||
|
return True
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _mbed_normalize_macro(macro):
|
||||||
|
name = macro
|
||||||
|
value = None
|
||||||
|
if "=" in macro:
|
||||||
|
name, value = macro.split("=", 1)
|
||||||
|
return dict(name=name, value=value)
|
||||||
|
|
||||||
|
def _mbed_lib_conf_parse_macros(self, mbed_lib_path):
|
||||||
|
macros = {}
|
||||||
|
cppdefines = str(self.env.Flatten(self.env.subst("$CPPDEFINES")))
|
||||||
|
manifest = util.load_json(mbed_lib_path)
|
||||||
|
|
||||||
|
# default macros
|
||||||
|
for macro in manifest.get("macros", []):
|
||||||
|
macro = self._mbed_normalize_macro(macro)
|
||||||
|
macros[macro['name']] = macro
|
||||||
|
|
||||||
|
# configuration items
|
||||||
|
for key, options in manifest.get("config", {}).items():
|
||||||
|
if "value" not in options:
|
||||||
|
continue
|
||||||
|
macros[key] = dict(
|
||||||
|
name=options.get("macro_name"), value=options.get("value"))
|
||||||
|
|
||||||
|
# overrode items per target
|
||||||
|
for target, options in manifest.get("target_overrides", {}).items():
|
||||||
|
if target != "*" and "TARGET_" + target not in cppdefines:
|
||||||
|
continue
|
||||||
|
for macro in options.get("target.macros_add", []):
|
||||||
|
macro = self._mbed_normalize_macro(macro)
|
||||||
|
macros[macro['name']] = macro
|
||||||
|
for key, value in options.items():
|
||||||
|
if not key.startswith("target.") and key in macros:
|
||||||
|
macros[key]['value'] = value
|
||||||
|
|
||||||
|
# normalize macro names
|
||||||
|
for key, macro in macros.items():
|
||||||
|
if not macro['name']:
|
||||||
|
macro['name'] = key
|
||||||
|
if "." not in macro['name']:
|
||||||
|
macro['name'] = "%s.%s" % (manifest.get("name"),
|
||||||
|
macro['name'])
|
||||||
|
macro['name'] = re.sub(
|
||||||
|
r"[^a-z\d]+", "_", macro['name'], flags=re.I).upper()
|
||||||
|
macro['name'] = "MBED_CONF_" + macro['name']
|
||||||
|
if isinstance(macro['value'], bool):
|
||||||
|
macro['value'] = 1 if macro['value'] else 0
|
||||||
|
|
||||||
|
return {macro["name"]: macro["value"] for macro in macros.values()}
|
||||||
|
|
||||||
|
def _mbed_conf_append_macros(self, mbed_config_path, macros):
|
||||||
|
lines = []
|
||||||
|
with open(mbed_config_path) as fp:
|
||||||
|
for line in fp.readlines():
|
||||||
|
line = line.strip()
|
||||||
|
if line == "#endif":
|
||||||
|
lines.append(
|
||||||
|
"// PlatformIO Library Dependency Finder (LDF)")
|
||||||
|
lines.extend([
|
||||||
|
"#define %s %s" % (name,
|
||||||
|
value if value is not None else "")
|
||||||
|
for name, value in macros.items()
|
||||||
|
])
|
||||||
|
lines.append("")
|
||||||
|
if not line.startswith("#define"):
|
||||||
|
lines.append(line)
|
||||||
|
continue
|
||||||
|
tokens = line.split()
|
||||||
|
if len(tokens) < 2 or tokens[1] not in macros:
|
||||||
|
lines.append(line)
|
||||||
|
lines.append("")
|
||||||
|
with open(mbed_config_path, "w") as fp:
|
||||||
|
fp.write("\n".join(lines))
|
||||||
|
|
||||||
|
|
||||||
class PlatformIOLibBuilder(LibBuilderBase):
|
class PlatformIOLibBuilder(LibBuilderBase):
|
||||||
|
|
||||||
@ -701,10 +809,11 @@ class ProjectAsLibBuilder(LibBuilderBase):
|
|||||||
return self.env.subst("$PROJECTSRC_DIR")
|
return self.env.subst("$PROJECTSRC_DIR")
|
||||||
|
|
||||||
def get_include_dirs(self):
|
def get_include_dirs(self):
|
||||||
include_dirs = LibBuilderBase.get_include_dirs(self)
|
include_dirs = []
|
||||||
project_include_dir = self.env.subst("$PROJECTINCLUDE_DIR")
|
project_include_dir = self.env.subst("$PROJECTINCLUDE_DIR")
|
||||||
if isdir(project_include_dir):
|
if isdir(project_include_dir):
|
||||||
include_dirs.append(project_include_dir)
|
include_dirs.append(project_include_dir)
|
||||||
|
include_dirs.extend(LibBuilderBase.get_include_dirs(self))
|
||||||
return include_dirs
|
return include_dirs
|
||||||
|
|
||||||
def get_search_files(self):
|
def get_search_files(self):
|
||||||
@ -772,8 +881,9 @@ class ProjectAsLibBuilder(LibBuilderBase):
|
|||||||
|
|
||||||
def build(self):
|
def build(self):
|
||||||
self._is_built = True # do not build Project now
|
self._is_built = True # do not build Project now
|
||||||
|
result = LibBuilderBase.build(self)
|
||||||
self.env.PrependUnique(CPPPATH=self.get_include_dirs())
|
self.env.PrependUnique(CPPPATH=self.get_include_dirs())
|
||||||
return LibBuilderBase.build(self)
|
return result
|
||||||
|
|
||||||
|
|
||||||
def GetLibBuilders(env): # pylint: disable=too-many-branches
|
def GetLibBuilders(env): # pylint: disable=too-many-branches
|
||||||
|
@ -33,10 +33,10 @@ class InoToCPPConverter(object):
|
|||||||
PROTOTYPE_RE = re.compile(
|
PROTOTYPE_RE = re.compile(
|
||||||
r"""^(
|
r"""^(
|
||||||
(?:template\<.*\>\s*)? # template
|
(?:template\<.*\>\s*)? # template
|
||||||
([a-z_\d\&]+\*?\s+){1,2} # return type
|
([a-z_\d\&]+\*?\s+){1,2} # return type
|
||||||
([a-z_\d]+\s*) # name of prototype
|
([a-z_\d]+\s*) # name of prototype
|
||||||
\([a-z_,\.\*\&\[\]\s\d]*\) # arguments
|
\([a-z_,\.\*\&\[\]\s\d]*\) # arguments
|
||||||
)\s*\{ # must end with {
|
)\s*(\{|;) # must end with `{` or `;`
|
||||||
""", re.X | re.M | re.I)
|
""", re.X | re.M | re.I)
|
||||||
DETECTMAIN_RE = re.compile(r"void\s+(setup|loop)\s*\(", re.M | re.I)
|
DETECTMAIN_RE = re.compile(r"void\s+(setup|loop)\s*\(", re.M | re.I)
|
||||||
PROTOPTRS_TPLRE = r"\([^&\(]*&(%s)[^\)]*\)"
|
PROTOPTRS_TPLRE = r"\([^&\(]*&(%s)[^\)]*\)"
|
||||||
@ -162,7 +162,14 @@ class InoToCPPConverter(object):
|
|||||||
if not prototypes:
|
if not prototypes:
|
||||||
return contents
|
return contents
|
||||||
|
|
||||||
prototype_names = set([m.group(3).strip() for m in prototypes])
|
# skip already declared prototypes
|
||||||
|
declared = set(
|
||||||
|
m.group(1).strip() for m in prototypes if m.group(4) == ";")
|
||||||
|
prototypes = [
|
||||||
|
m for m in prototypes if m.group(1).strip() not in declared
|
||||||
|
]
|
||||||
|
|
||||||
|
prototype_names = set(m.group(3).strip() for m in prototypes)
|
||||||
split_pos = prototypes[0].start()
|
split_pos = prototypes[0].start()
|
||||||
match_ptrs = re.search(
|
match_ptrs = re.search(
|
||||||
self.PROTOPTRS_TPLRE % ("|".join(prototype_names)),
|
self.PROTOPTRS_TPLRE % ("|".join(prototype_names)),
|
||||||
|
@ -55,7 +55,6 @@ def validate_path(ctx, param, value): # pylint: disable=unused-argument
|
|||||||
"--build-dir",
|
"--build-dir",
|
||||||
default=mkdtemp,
|
default=mkdtemp,
|
||||||
type=click.Path(
|
type=click.Path(
|
||||||
exists=True,
|
|
||||||
file_okay=False,
|
file_okay=False,
|
||||||
dir_okay=True,
|
dir_okay=True,
|
||||||
writable=True,
|
writable=True,
|
||||||
@ -134,7 +133,8 @@ def _copy_contents(dst_dir, contents):
|
|||||||
if dst_dir_name == "src" and len(items['dirs']) == 1:
|
if dst_dir_name == "src" and len(items['dirs']) == 1:
|
||||||
copytree(list(items['dirs']).pop(), dst_dir, symlinks=True)
|
copytree(list(items['dirs']).pop(), dst_dir, symlinks=True)
|
||||||
else:
|
else:
|
||||||
makedirs(dst_dir)
|
if not isdir(dst_dir):
|
||||||
|
makedirs(dst_dir)
|
||||||
for d in items['dirs']:
|
for d in items['dirs']:
|
||||||
copytree(d, join(dst_dir, basename(d)), symlinks=True)
|
copytree(d, join(dst_dir, basename(d)), symlinks=True)
|
||||||
|
|
||||||
@ -145,7 +145,10 @@ def _copy_contents(dst_dir, contents):
|
|||||||
dst_dir = join(dst_dir, mkdtemp(dir=dst_dir))
|
dst_dir = join(dst_dir, mkdtemp(dir=dst_dir))
|
||||||
|
|
||||||
for f in items['files']:
|
for f in items['files']:
|
||||||
copyfile(f, join(dst_dir, basename(f)))
|
dst_file = join(dst_dir, basename(f))
|
||||||
|
if f == dst_file:
|
||||||
|
continue
|
||||||
|
copyfile(f, dst_file)
|
||||||
|
|
||||||
|
|
||||||
def _exclude_contents(dst_dir, patterns):
|
def _exclude_contents(dst_dir, patterns):
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
{
|
{
|
||||||
"!!! WARNING !!!": "PLEASE DO NOT MODIFY THIS FILE! USE https://docs.platformio.org/page/projectconf/section_env_build.html#build-flags",
|
|
||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
{
|
||||||
|
"name": "!!! WARNING !!! AUTO-GENERATED FILE, PLEASE DO NOT MODIFY IT AND USE https://docs.platformio.org/page/projectconf/section_env_build.html#build-flags"
|
||||||
|
},
|
||||||
|
{
|
||||||
% import platform
|
% import platform
|
||||||
% from os.path import commonprefix, dirname
|
% from os.path import commonprefix, dirname
|
||||||
%
|
%
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
from os.path import join
|
from os.path import isfile, join
|
||||||
|
|
||||||
from platformio.commands.ci import cli as cmd_ci
|
from platformio.commands.ci import cli as cmd_ci
|
||||||
from platformio.commands.lib import cli as cmd_lib
|
from platformio.commands.lib import cli as cmd_lib
|
||||||
@ -32,6 +32,36 @@ def test_ci_boards(clirunner, validate_cliresult):
|
|||||||
validate_cliresult(result)
|
validate_cliresult(result)
|
||||||
|
|
||||||
|
|
||||||
|
def test_ci_build_dir(clirunner, tmpdir_factory, validate_cliresult):
|
||||||
|
build_dir = str(tmpdir_factory.mktemp("ci_build_dir"))
|
||||||
|
result = clirunner.invoke(cmd_ci, [
|
||||||
|
join("examples", "wiring-blink", "src", "main.cpp"), "-b", "uno",
|
||||||
|
"--build-dir", build_dir
|
||||||
|
])
|
||||||
|
validate_cliresult(result)
|
||||||
|
assert not isfile(join(build_dir, "platformio.ini"))
|
||||||
|
|
||||||
|
|
||||||
|
def test_ci_keep_build_dir(clirunner, tmpdir_factory, validate_cliresult):
|
||||||
|
build_dir = str(tmpdir_factory.mktemp("ci_build_dir"))
|
||||||
|
result = clirunner.invoke(cmd_ci, [
|
||||||
|
join("examples", "wiring-blink", "src", "main.cpp"), "-b", "uno",
|
||||||
|
"--build-dir", build_dir, "--keep-build-dir"
|
||||||
|
])
|
||||||
|
validate_cliresult(result)
|
||||||
|
assert isfile(join(build_dir, "platformio.ini"))
|
||||||
|
|
||||||
|
# 2nd attempt
|
||||||
|
result = clirunner.invoke(cmd_ci, [
|
||||||
|
join("examples", "wiring-blink", "src", "main.cpp"), "-b", "metro",
|
||||||
|
"--build-dir", build_dir, "--keep-build-dir"
|
||||||
|
])
|
||||||
|
validate_cliresult(result)
|
||||||
|
|
||||||
|
assert "board: uno" in result.output
|
||||||
|
assert "board: metro" in result.output
|
||||||
|
|
||||||
|
|
||||||
def test_ci_project_conf(clirunner, validate_cliresult):
|
def test_ci_project_conf(clirunner, validate_cliresult):
|
||||||
project_dir = join("examples", "wiring-blink")
|
project_dir = join("examples", "wiring-blink")
|
||||||
result = clirunner.invoke(cmd_ci, [
|
result = clirunner.invoke(cmd_ci, [
|
||||||
|
@ -49,4 +49,12 @@ void fooCallback(){
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
void some_extern(const char *fmt, ...);
|
||||||
|
};
|
||||||
|
|
||||||
|
void some_extern(const char *fmt, ...) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// юнікод
|
// юнікод
|
||||||
|
Reference in New Issue
Block a user