diff --git a/docs/projectconf.rst b/docs/projectconf.rst index f88fc21e..77d72526 100644 --- a/docs/projectconf.rst +++ b/docs/projectconf.rst @@ -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`` ^^^^^^^^^^^^^^^^^^^ diff --git a/platformio/__init__.py b/platformio/__init__.py index facbf112..ca2ab2ae 100644 --- a/platformio/__init__.py +++ b/platformio/__init__.py @@ -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" diff --git a/platformio/builder/main.py b/platformio/builder/main.py index 37ad9648..0fdcc752 100644 --- a/platformio/builder/main.py +++ b/platformio/builder/main.py @@ -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()] diff --git a/platformio/builder/tools/piolib.py b/platformio/builder/tools/piolib.py index c11ceca4..e97f271c 100644 --- a/platformio/builder/tools/piolib.py +++ b/platformio/builder/tools/piolib.py @@ -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 diff --git a/platformio/builder/tools/piomisc.py b/platformio/builder/tools/piomisc.py index 6d0095f5..26ec5945 100644 --- a/platformio/builder/tools/piomisc.py +++ b/platformio/builder/tools/piomisc.py @@ -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 diff --git a/platformio/commands/run.py b/platformio/commands/run.py index e2d735d6..78591e2e 100644 --- a/platformio/commands/run.py +++ b/platformio/commands/run.py @@ -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