Skip to content

Commit

Permalink
Improved handling of library dependencies specified in ``library.json…
Browse files Browse the repository at this point in the history
…`` manifest // Resolve #814
  • Loading branch information
ivankravets committed Oct 26, 2016
1 parent 2ec0bbb commit c2bf38f
Show file tree
Hide file tree
Showing 8 changed files with 68 additions and 47 deletions.
2 changes: 2 additions & 0 deletions HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ PlatformIO 3.0
* Improved detecting of ARM mbed media disk for uploading
* Improved Project Generator for CLion IDE when source folder contains nested items
* Changed default exit combination for Device Monitor from ``Ctrl+]`` to ``Ctrl+C``
* Improved handling of library dependencies specified in ``library.json`` manifest
(`issue #814 <https://github.com/platformio/platformio/issues/814>`_)
* Fixed issue with ``PATH`` auto-configuring for upload tools
* Fixed ``99-platformio-udev.rules`` checker for Linux OS

Expand Down
2 changes: 1 addition & 1 deletion platformio/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

import sys

VERSION = (3, 2, "0a8")
VERSION = (3, 2, "0a9")
__version__ = ".".join([str(s) for s in VERSION])

__title__ = "platformio"
Expand Down
2 changes: 1 addition & 1 deletion platformio/builder/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@
env[var] = environ.get(k)

# Parse comma separated items
for opt in ("LIB_DEPS", "LIB_IGNORE", "LIB_EXTRA_DIRS"):
for opt in ("PIOFRAMEWORK", "LIB_DEPS", "LIB_IGNORE", "LIB_EXTRA_DIRS"):
if opt not in env:
continue
env[opt] = [l.strip() for l in env[opt].split(", ") if l.strip()]
Expand Down
86 changes: 50 additions & 36 deletions platformio/builder/tools/piolib.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,9 @@ def new(env, path):
if isfile(join(path, "library.json")):
clsname = "PlatformIOLibBuilder"
else:
env_frameworks = [
f.lower().strip()
for f in env.get("PIOFRAMEWORK", "").split(",")
]
used_frameworks = LibBuilderFactory.get_used_frameworks(env, path)
common_frameworks = set(env_frameworks) & set(used_frameworks)
common_frameworks = (set(env.get("PIOFRAMEWORK", [])) &
set(used_frameworks))
if common_frameworks:
clsname = "%sLibBuilder" % list(common_frameworks)[0].title()
elif used_frameworks:
Expand Down Expand Up @@ -166,10 +163,24 @@ def depbuilders(self):
def dependent(self):
return self._is_dependent

def is_platform_compatible(self, platform):
@staticmethod
def items_in_list(items, ilist):

def _items_to_list(items_):
if not isinstance(items_, list):
items_ = [i.strip() for i in items_.split(",")]
return [i.lower() for i in items_ if i]

items = _items_to_list(items)
ilist = _items_to_list(ilist)
if "*" in items or "*" in ilist:
return True
return set(items) & set(ilist)

def is_platforms_compatible(self, platforms):
return True

def is_framework_compatible(self, framework):
def is_frameworks_compatible(self, frameworks):
return True

def load_manifest(self):
Expand All @@ -189,24 +200,37 @@ def process_extra_options(self):
if self.extra_script:
self.env.SConscript(
realpath(self.extra_script),
exports={"env": self.env,
"pio_lib_builder": self})
exports={
"env": self.env,
"pio_lib_builder": self
})

def _process_dependencies(self, lib_builders):
if not self.dependencies:
return
verbose = (int(ARGUMENTS.get("PIOVERBOSE", 0)) and
not self.env.GetOption('clean'))
for item in self.dependencies:
skip = False
for key in ("platforms", "frameworks"):
if (key in item and not self.items_in_list(
self.env["PIO" + key.upper()[:-1]], item[key])):
if verbose:
sys.stderr.write("Skip %s incompatible dependency %s\n"
% (key[:-1], item))
skip = True
if skip:
continue

found = False
for lb in lib_builders:
if item['name'] != lb.name:
continue
elif "frameworks" in item and \
not any([lb.is_framework_compatible(f)
for f in item["frameworks"]]):
not lb.is_frameworks_compatible(item["frameworks"]):
continue
elif "platforms" in item and \
not any([lb.is_platform_compatible(p)
for p in item["platforms"]]):
not lb.is_platforms_compatible(item["platforms"]):
continue
found = True
self.depend_recursive(lb, lib_builders)
Expand Down Expand Up @@ -383,8 +407,8 @@ def src_filter(self):
src_filter.append("+<utility%s*.%s>" % (sep, ext))
return src_filter

def is_framework_compatible(self, framework):
return framework.lower() in ("arduino", "energia")
def is_frameworks_compatible(self, frameworks):
return self.items_in_list(frameworks, ["arduino", "energia"])


class MbedLibBuilder(LibBuilderBase):
Expand All @@ -408,8 +432,8 @@ def get_inc_dirs(self):
inc_dirs.append(join(self.path, p))
return inc_dirs

def is_framework_compatible(self, framework):
return framework.lower() == "mbed"
def is_frameworks_compatible(self, frameworks):
return self.items_in_list(frameworks, ["mbed"])


class PlatformIOLibBuilder(LibBuilderBase):
Expand Down Expand Up @@ -461,24 +485,17 @@ def lib_ldf_mode(self):
return int(self._manifest.get("build").get("libLDFMode"))
return LibBuilderBase.lib_ldf_mode.fget(self)

def is_platform_compatible(self, platform):
def is_platforms_compatible(self, platforms):
items = self._manifest.get("platforms")
if not items:
return LibBuilderBase.is_platform_compatible(self, platform)
return self._item_in_list(platform, items)
return LibBuilderBase.is_platforms_compatible(self, platforms)
return self.items_in_list(platforms, items)

def is_framework_compatible(self, framework):
def is_frameworks_compatible(self, frameworks):
items = self._manifest.get("frameworks")
if not items:
return LibBuilderBase.is_framework_compatible(self, framework)
return self._item_in_list(framework, items)

def _item_in_list(self, item, ilist):
if ilist == "*":
return True
if not isinstance(ilist, list):
ilist = [i.strip() for i in ilist.split(",")]
return item.lower() in [i.lower() for i in ilist]
return LibBuilderBase.is_frameworks_compatible(self, frameworks)
return self.items_in_list(frameworks, items)

def get_inc_dirs(self):
inc_dirs = LibBuilderBase.get_inc_dirs(self)
Expand All @@ -497,9 +514,6 @@ def get_inc_dirs(self):

def GetLibBuilders(env):
items = []
env_frameworks = [
f.lower().strip() for f in env.get("PIOFRAMEWORK", "").split(",")
]
compat_mode = int(env.get("LIB_COMPAT_MODE", 1))
verbose = (int(ARGUMENTS.get("PIOVERBOSE", 0)) and
not env.GetOption('clean'))
Expand All @@ -509,14 +523,14 @@ def _check_lib_builder(lb):
if verbose:
sys.stderr.write("Ignored library %s\n" % lb.path)
return
if compat_mode > 1 and not lb.is_platform_compatible(env[
if compat_mode > 1 and not lb.is_platforms_compatible(env[
'PIOPLATFORM']):
if verbose:
sys.stderr.write("Platform incompatible library %s\n" %
lb.path)
return False
if compat_mode > 0 and not any([lb.is_framework_compatible(f)
for f in env_frameworks]):
if compat_mode > 0 and "PIOFRAMEWORK" in env and \
not lb.is_frameworks_compatible(env.get("PIOFRAMEWORK", [])):
if verbose:
sys.stderr.write("Framework incompatible library %s\n" %
lb.path)
Expand Down
2 changes: 1 addition & 1 deletion platformio/builder/tools/pioupload.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ def _look_for_serial_port():
print env.subst("Use manually specified: $UPLOAD_PORT")
return

if env.subst("$PIOFRAMEWORK") == "mbed":
if "mbed" in env.subst("$PIOFRAMEWORK"):
env.Replace(UPLOAD_PORT=_look_for_mbed_disk())
else:
if (system() == "Linux" and not any([
Expand Down
5 changes: 1 addition & 4 deletions platformio/builder/tools/platformio.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,7 @@ def _append_pio_macros():
# apply user flags
env.ProcessFlags(env.get("BUILD_FLAGS"))

if env.get("PIOFRAMEWORK"):
env.BuildFrameworks([
f.lower().strip() for f in env['PIOFRAMEWORK'].split(",")
])
env.BuildFrameworks(env.get("PIOFRAMEWORK"))

# restore PIO macros if it was deleted by framework
_append_pio_macros()
Expand Down
11 changes: 8 additions & 3 deletions platformio/managers/lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.

# pylint: disable=too-many-arguments, too-many-locals, too-many-branches

import json
import os
from hashlib import md5
Expand Down Expand Up @@ -185,7 +187,9 @@ def _get_pkg_id_by_name(self,
if "id" in manifest:
return int(manifest['id'])
return int(
self.search_for_library({"name": name}, silent, interactive)['id'])
self.search_for_library({
"name": name
}, silent, interactive)['id'])

def _install_from_piorepo(self, name, requirements):
assert name.startswith("id=")
Expand All @@ -203,7 +207,7 @@ def _install_from_piorepo(self, name, requirements):
name, dl_data['url'].replace("http://", "https://")
if app.get_setting("enable_ssl") else dl_data['url'], requirements)

def install(self, # pylint: disable=too-many-arguments, too-many-locals
def install(self,
name,
requirements=None,
silent=False,
Expand Down Expand Up @@ -247,7 +251,8 @@ def install(self, # pylint: disable=too-many-arguments, too-many-locals
lib_info = self.search_for_library(filters, silent,
interactive)
except exception.LibNotFound as e:
click.secho("Warning! %s" % e, fg="yellow")
if not silent:
click.secho("Warning! %s" % e, fg="yellow")
continue

if filters.get("version"):
Expand Down
5 changes: 4 additions & 1 deletion platformio/managers/platform.py
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,10 @@ def pkg_types_to_names(self, types):

def configure_default_packages(self, variables, targets):
# enable used frameworks
for framework in variables.get("pioframework", "").split(","):
frameworks = variables.get("pioframework", [])
if not isinstance(frameworks, list):
frameworks = frameworks.split(", ")
for framework in frameworks:
if not self.frameworks:
continue
framework = framework.lower().strip()
Expand Down

0 comments on commit c2bf38f

Please sign in to comment.