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

View File

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

View File

@ -43,7 +43,7 @@ commonvars.AddVariables(
("SRC_FILTER",),
("LIB_DEEP_SEARCH",),
("LIB_IGNORE",),
("LIB_USE",),
("LIB_FORCE",),
# board options
("BOARD",),
@ -104,7 +104,7 @@ for k in commonvars.keys():
env.LoadDevPlatform(commonvars)
# Parse library names
for opt in ("LIB_IGNORE", "LIB_USE"):
for opt in ("LIB_IGNORE", "LIB_FORCE"):
if opt not in env:
continue
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
# limitations under the License.
# pylint: disable=no-member
from __future__ import absolute_import
import os
@ -73,6 +75,7 @@ class LibBuilderBase(object):
self.env = env
self.path = path
self._is_built = False
self._manifest = self.load_manifest()
def __repr__(self):
return "%s(%r)" % (self.__class__, self.path)
@ -82,7 +85,11 @@ class LibBuilderBase(object):
@property
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
def src_filter(self):
@ -105,13 +112,25 @@ class LibBuilderBase(object):
def is_built(self):
return self._is_built
def load_manifest(self): # pylint: disable=no-self-use
return {}
def get_path_dirs(self, use_build_dir=False):
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):
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
self._is_built = True
self.append_to_cpppath()
return self.env.BuildLibrary(self.build_dir, self.src_dir)
@ -121,33 +140,43 @@ class UnknownLibBuilder(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):
path_dirs = LibBuilderBase.get_path_dirs(self, use_build_dir)
if not isdir(join(self.src_dir, "utility")):
return path_dirs
path_dirs.append(join(self.build_dir if use_build_dir
else self.src_dir, "utility"))
path_dirs.append(
join(self.build_dir if use_build_dir else self.src_dir, "utility"))
return path_dirs
class MbedLibBuilder(LibBuilderBase):
def __init__(self, env, path):
self.module_json = {}
if isfile(join(path, "module.json")):
self.module_json = util.load_json(join(path, "module.json"))
LibBuilderBase.__init__(self, env, path)
def load_manifest(self):
if not isfile(join(self.path, "module.json")):
return {}
return util.load_json(join(self.path, "module.json"))
@property
def src_dir(self):
if isdir(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):
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/"):
p = p[7:]
path_dirs.append(
@ -157,12 +186,11 @@ class MbedLibBuilder(LibBuilderBase):
class PlatformIOLibBuilder(LibBuilderBase):
def __init__(self, env, path):
self.library_json = {}
if isfile(join(path, "library.json")):
self.library_json = util.load_json(join(path, "library.json"))
LibBuilderBase.__init__(self, env, path)
def load_manifest(self):
assert isfile(join(self.path, "library.json"))
manifest = util.load_json(join(self.path, "library.json"))
assert "name" in manifest
return manifest
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
libs = []
# add build dirs to global CPPPATH
# append PATH directories to global CPPPATH before build starts
for lb in target_lbs:
env.Append(
CPPPATH=lb.get_path_dirs(use_build_dir=True)
)
lb.append_to_cpppath()
# start builder
for lb in target_lbs:
libs.append(lb.build())
@ -212,24 +238,45 @@ def find_and_build_deps(env, lib_builders, scanner,
return libs
def BuildDependentLibraries(env, src_dir):
lib_builders = []
def GetLibBuilders(env):
items = []
libs_dirs = [env.subst(d) for d in env.get("LIBSOURCE_DIRS", [])
if isdir(env.subst(d))]
for libs_dir in libs_dirs:
if not isdir(libs_dir):
continue
for item in sorted(os.listdir(libs_dir)):
if isdir(join(libs_dir, item)):
lib_builders.append(
LibBuilderFactory.new(env, join(libs_dir, item)))
if item == "__cores__" or not isdir(join(libs_dir, item)):
continue
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 "Collecting %d libraries" % len(lib_builders)
return find_and_build_deps(
env, lib_builders, SCons.Scanner.C.CScanner(),
src_dir, env.get("SRC_FILTER"))
built_lib_names = []
for lib_name in env.get("LIB_FORCE", []):
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(_):
@ -237,5 +284,6 @@ def exists(_):
def generate(env):
env.AddMethod(GetLibBuilders)
env.AddMethod(BuildDependentLibraries)
return env

View File

@ -145,7 +145,7 @@ def DumpIDEData(env):
def get_includes(env_):
includes = []
# includes from used framework and libs
# includes from used frameworks and libs
for item in env_.get("VARIANT_DIRS", []):
if "$BUILDSRC_DIR" in item[0]:
continue
@ -158,9 +158,8 @@ def DumpIDEData(env):
includes.append(env_.subst(item))
# installed libs
for d in env_.get("LIBSOURCE_DIRS", []):
lsd_dir = env_.subst(d)
_append_lib_includes(env_, lsd_dir, includes)
for lb in env.GetLibBuilders():
includes.extend(lb.get_path_dirs())
# includes from toolchains
p = env.DevPlatform()
@ -177,30 +176,6 @@ def DumpIDEData(env):
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_):
defines = []
# global symbols

View File

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