Refactored lib_force and lib_ignore logic

This commit is contained in:
Ivan Kravets
2016-06-25 13:23:24 +03:00
parent bc30bf5566
commit 51a9565a72
6 changed files with 96 additions and 73 deletions

View File

@ -595,18 +595,19 @@ Example:
[env:depends_on_some_libs] [env:depends_on_some_libs]
lib_install = 1,13,19 lib_install = 1,13,19
``lib_use`` ``lib_force``
^^^^^^^^^^^ ^^^^^^^^^^^^^
Specify libraries which should be used by ``Library Dependency Finder (LDF)`` with Force Library Build System to build specified libraries if even they are not
the highest priority. included in the project source code. Also, these libraries will be processed
in the first order.
Example: Example:
.. code-block:: ini .. code-block:: ini
[env:libs_with_highest_priority] [env:myenv]
lib_use = OneWire_ID1,SPI lib_force = OneWire, SPI
``lib_ignore`` ``lib_ignore``
^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^
@ -618,7 +619,7 @@ Example:
.. code-block:: ini .. code-block:: ini
[env:ignore_some_libs] [env:ignore_some_libs]
lib_ignore = SPI,EngduinoV3_ID123 lib_ignore = SPI, Ethernet
``lib_deep_search`` ``lib_deep_search``
^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^

View File

@ -14,7 +14,7 @@
import sys import sys
VERSION = (3, 0, "0.dev2") VERSION = (3, 0, "0.dev3")
__version__ = ".".join([str(s) for s in VERSION]) __version__ = ".".join([str(s) for s in VERSION])
__title__ = "platformio" __title__ = "platformio"

View File

@ -43,7 +43,7 @@ commonvars.AddVariables(
("SRC_FILTER",), ("SRC_FILTER",),
("LIB_DEEP_SEARCH",), ("LIB_DEEP_SEARCH",),
("LIB_IGNORE",), ("LIB_IGNORE",),
("LIB_USE",), ("LIB_FORCE",),
# board options # board options
("BOARD",), ("BOARD",),
@ -104,7 +104,7 @@ for k in commonvars.keys():
env.LoadDevPlatform(commonvars) env.LoadDevPlatform(commonvars)
# Parse library names # Parse library names
for opt in ("LIB_IGNORE", "LIB_USE"): for opt in ("LIB_IGNORE", "LIB_FORCE"):
if opt not in env: if opt not in env:
continue continue
env[opt] = [l.strip() for l in env[opt].split(",") if l.strip()] env[opt] = [l.strip() for l in env[opt].split(",") if l.strip()]

View File

@ -12,6 +12,8 @@
# 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
from __future__ import absolute_import from __future__ import absolute_import
import os import os
@ -73,6 +75,7 @@ class LibBuilderBase(object):
self.env = env self.env = env
self.path = path self.path = path
self._is_built = False self._is_built = False
self._manifest = self.load_manifest()
def __repr__(self): def __repr__(self):
return "%s(%r)" % (self.__class__, self.path) return "%s(%r)" % (self.__class__, self.path)
@ -82,7 +85,11 @@ class LibBuilderBase(object):
@property @property
def name(self): def name(self):
return basename(self.path) return self._manifest.get("name", basename(self.path))
@property
def version(self):
return self._manifest.get("version")
@property @property
def src_filter(self): def src_filter(self):
@ -105,13 +112,25 @@ class LibBuilderBase(object):
def is_built(self): def is_built(self):
return self._is_built return self._is_built
def load_manifest(self): # pylint: disable=no-self-use
return {}
def get_path_dirs(self, use_build_dir=False): def get_path_dirs(self, use_build_dir=False):
return [self.build_dir if use_build_dir else self.src_dir] return [self.build_dir if use_build_dir else self.src_dir]
def append_to_cpppath(self):
self.env.AppendUnique(
CPPPATH=self.get_path_dirs(use_build_dir=True)
)
def build(self): def build(self):
print "Depends on <%s>" % self.name if self.version:
print "Depends on <%s> v%s" % (self.name, self.version)
else:
print "Depends on <%s>" % self.name
assert self._is_built is False assert self._is_built is False
self._is_built = True self._is_built = True
self.append_to_cpppath()
return self.env.BuildLibrary(self.build_dir, self.src_dir) return self.env.BuildLibrary(self.build_dir, self.src_dir)
@ -121,33 +140,43 @@ class UnknownLibBuilder(LibBuilderBase):
class ArduinoLibBuilder(LibBuilderBase): class ArduinoLibBuilder(LibBuilderBase):
def load_manifest(self):
manifest = {}
if not isfile(join(self.path, "library.properties")):
return manifest
with open(join(self.path, "library.properties")) as fp:
for line in fp.readlines():
if "=" not in line:
continue
key, value = line.split("=", 1)
manifest[key.strip()] = value.strip()
return manifest
def get_path_dirs(self, use_build_dir=False): def get_path_dirs(self, use_build_dir=False):
path_dirs = LibBuilderBase.get_path_dirs(self, use_build_dir) path_dirs = LibBuilderBase.get_path_dirs(self, use_build_dir)
if not isdir(join(self.src_dir, "utility")): if not isdir(join(self.src_dir, "utility")):
return path_dirs return path_dirs
path_dirs.append(join(self.build_dir if use_build_dir path_dirs.append(
else self.src_dir, "utility")) join(self.build_dir if use_build_dir else self.src_dir, "utility"))
return path_dirs return path_dirs
class MbedLibBuilder(LibBuilderBase): class MbedLibBuilder(LibBuilderBase):
def __init__(self, env, path): def load_manifest(self):
self.module_json = {} if not isfile(join(self.path, "module.json")):
if isfile(join(path, "module.json")): return {}
self.module_json = util.load_json(join(path, "module.json")) return util.load_json(join(self.path, "module.json"))
LibBuilderBase.__init__(self, env, path)
@property @property
def src_dir(self): def src_dir(self):
if isdir(join(self.path, "source")): if isdir(join(self.path, "source")):
return join(self.path, "source") return join(self.path, "source")
return LibBuilderBase.src_dir.fget(self) # pylint: disable=no-member return LibBuilderBase.src_dir.fget(self)
def get_path_dirs(self, use_build_dir=False): def get_path_dirs(self, use_build_dir=False):
path_dirs = LibBuilderBase.get_path_dirs(self, use_build_dir) path_dirs = LibBuilderBase.get_path_dirs(self, use_build_dir)
for p in self.module_json.get("extraIncludes", []): for p in self._manifest.get("extraIncludes", []):
if p.startswith("source/"): if p.startswith("source/"):
p = p[7:] p = p[7:]
path_dirs.append( path_dirs.append(
@ -157,12 +186,11 @@ class MbedLibBuilder(LibBuilderBase):
class PlatformIOLibBuilder(LibBuilderBase): class PlatformIOLibBuilder(LibBuilderBase):
def __init__(self, env, path): def load_manifest(self):
self.library_json = {} assert isfile(join(self.path, "library.json"))
if isfile(join(path, "library.json")): manifest = util.load_json(join(self.path, "library.json"))
self.library_json = util.load_json(join(path, "library.json")) assert "name" in manifest
return manifest
LibBuilderBase.__init__(self, env, path)
def find_deps(env, scanner, path_dirs, src_dir, src_filter): def find_deps(env, scanner, path_dirs, src_dir, src_filter):
@ -195,11 +223,9 @@ def find_and_build_deps(env, lib_builders, scanner,
break break
libs = [] libs = []
# add build dirs to global CPPPATH # append PATH directories to global CPPPATH before build starts
for lb in target_lbs: for lb in target_lbs:
env.Append( lb.append_to_cpppath()
CPPPATH=lb.get_path_dirs(use_build_dir=True)
)
# start builder # start builder
for lb in target_lbs: for lb in target_lbs:
libs.append(lb.build()) libs.append(lb.build())
@ -212,24 +238,45 @@ def find_and_build_deps(env, lib_builders, scanner,
return libs return libs
def BuildDependentLibraries(env, src_dir): def GetLibBuilders(env):
lib_builders = [] items = []
libs_dirs = [env.subst(d) for d in env.get("LIBSOURCE_DIRS", []) libs_dirs = [env.subst(d) for d in env.get("LIBSOURCE_DIRS", [])
if isdir(env.subst(d))] if isdir(env.subst(d))]
for libs_dir in libs_dirs: for libs_dir in libs_dirs:
if not isdir(libs_dir):
continue
for item in sorted(os.listdir(libs_dir)): for item in sorted(os.listdir(libs_dir)):
if isdir(join(libs_dir, item)): if item == "__cores__" or not isdir(join(libs_dir, item)):
lib_builders.append( continue
LibBuilderFactory.new(env, join(libs_dir, item))) lb = LibBuilderFactory.new(env, join(libs_dir, item))
if lb.name in env.get("LIB_IGNORE", []):
continue
items.append(lb)
return items
def BuildDependentLibraries(env, src_dir):
libs = []
scanner = SCons.Scanner.C.CScanner()
lib_builders = env.GetLibBuilders()
print "Looking for dependencies..." print "Looking for dependencies..."
print "Collecting %d libraries" % len(lib_builders) print "Collecting %d libraries" % len(lib_builders)
return find_and_build_deps( built_lib_names = []
env, lib_builders, SCons.Scanner.C.CScanner(), for lib_name in env.get("LIB_FORCE", []):
src_dir, env.get("SRC_FILTER")) for lb in lib_builders:
if lb.name != lib_name or lb.name in built_lib_names:
continue
built_lib_names.append(lb.name)
libs.extend(find_and_build_deps(
env, lib_builders, scanner, lb.src_dir, lb.src_filter))
if not lb.is_built:
libs.append(lb.build())
# process project source code
libs.extend(find_and_build_deps(
env, lib_builders, scanner, src_dir, env.get("SRC_FILTER")))
return libs
def exists(_): def exists(_):
@ -237,5 +284,6 @@ def exists(_):
def generate(env): def generate(env):
env.AddMethod(GetLibBuilders)
env.AddMethod(BuildDependentLibraries) env.AddMethod(BuildDependentLibraries)
return env return env

View File

@ -145,7 +145,7 @@ def DumpIDEData(env):
def get_includes(env_): def get_includes(env_):
includes = [] includes = []
# includes from used framework and libs # includes from used frameworks and libs
for item in env_.get("VARIANT_DIRS", []): for item in env_.get("VARIANT_DIRS", []):
if "$BUILDSRC_DIR" in item[0]: if "$BUILDSRC_DIR" in item[0]:
continue continue
@ -158,9 +158,8 @@ def DumpIDEData(env):
includes.append(env_.subst(item)) includes.append(env_.subst(item))
# installed libs # installed libs
for d in env_.get("LIBSOURCE_DIRS", []): for lb in env.GetLibBuilders():
lsd_dir = env_.subst(d) includes.extend(lb.get_path_dirs())
_append_lib_includes(env_, lsd_dir, includes)
# includes from toolchains # includes from toolchains
p = env.DevPlatform() p = env.DevPlatform()
@ -177,30 +176,6 @@ def DumpIDEData(env):
return includes return includes
def _append_lib_includes(env_, libs_dir, includes):
if not isdir(libs_dir):
return
for name in env_.get("LIB_USE", []) + sorted(listdir(libs_dir)):
if not isdir(join(libs_dir, name)):
continue
# ignore user's specified libs
if name in env_.get("LIB_IGNORE", []):
continue
if name == "__cores__":
board_core = env_.BoardConfig().get("build.core")
if isdir(join(libs_dir, name, board_core)):
_append_lib_includes(
env_, join(libs_dir, name, board_core), includes)
return
include = (
join(libs_dir, name, "src")
if isdir(join(libs_dir, name, "src"))
else join(libs_dir, name)
)
if include not in includes:
includes.append(include)
def get_defines(env_): def get_defines(env_):
defines = [] defines = []
# global symbols # global symbols

View File

@ -100,9 +100,8 @@ class EnvironmentProcessor(object):
RENAMED_OPTIONS = { RENAMED_OPTIONS = {
"INSTALL_LIBS": "LIB_INSTALL", "INSTALL_LIBS": "LIB_INSTALL",
"IGNORE_LIBS": "LIB_IGNORE", "IGNORE_LIBS": "LIB_IGNORE",
"USE_LIBS": "LIB_USE", "LIB_USE": "LIB_FORCE",
"LIB_DFCYCLIC": "LIB_DEEP_SEARCH", "LIB_DFCYCLIC": "LIB_DEEP_SEARCH"
"SRCBUILD_FLAGS": "SRC_BUILD_FLAGS"
} }
def __init__(self, cmd_ctx, name, options, # pylint: disable=R0913 def __init__(self, cmd_ctx, name, options, # pylint: disable=R0913