def BuildDependentLibraries(env, src_dir):  # pylint: disable=R0914

    INCLUDES_RE = re.compile(
        r"^\s*#include\s+(\<|\")([^\>\"\']+)(?:\>|\")", re.M)
    LIBSOURCE_DIRS = [env.subst(d) for d in env.get("LIBSOURCE_DIRS", [])]

    # start internal prototypes

    class IncludeFinder(object):

        def __init__(self, base_dir, name, is_system=False):
            self.base_dir = base_dir
            self.name = name
            self.is_system = is_system

            self._inc_path = None
            self._lib_dir = None
            self._lib_name = None

        def getIncPath(self):
            return self._inc_path

        def getLibDir(self):
            return self._lib_dir

        def getLibName(self):
            return self._lib_name

        def run(self):
            if not self.is_system and self._find_in_local():
                return True
            return self._find_in_system()

        def _find_in_local(self):
            if isfile(join(self.base_dir, self.name)):
                self._inc_path = join(self.base_dir, self.name)
                return True
            else:
                return False

        def _find_in_system(self):
            for lsd_dir in LIBSOURCE_DIRS:
                if not isdir(lsd_dir):
                    continue

                for ld in env.get("LIB_USE", []) + sorted(listdir(lsd_dir)):
                    if not isdir(join(lsd_dir, ld)):
                        continue

                    inc_path = normpath(join(lsd_dir, ld, self.name))
                    try:
                        lib_dir = inc_path[:inc_path.index(
                            sep, len(lsd_dir) + 1)]
                    except __HOLE__:
                        continue
                    lib_name = basename(lib_dir)

                    # ignore user's specified libs
                    if lib_name in env.get("LIB_IGNORE", []):
                        continue

                    if not isfile(inc_path):
                        # if source code is in "src" dir
                        lib_dir = join(lsd_dir, lib_name, "src")
                        inc_path = join(lib_dir, self.name)

                    if isfile(inc_path):
                        self._lib_dir = lib_dir
                        self._lib_name = lib_name
                        self._inc_path = inc_path
                        return True
            return False

    def _get_dep_libs(src_dir):
        state = {
            "paths": set(),
            "libs": set(),
            "ordered": set()
        }

        state = _process_src_dir(state, env.subst(src_dir))

        result = []
        for item in sorted(state['ordered'], key=lambda s: s[0]):
            result.append((item[1], item[2]))
        return result

    def _process_src_dir(state, src_dir):
        for root, _, files in walk(src_dir, followlinks=True):
            for f in files:
                if env.IsFileWithExt(f, SRC_BUILD_EXT + SRC_HEADER_EXT):
                    state = _parse_includes(state, env.File(join(root, f)))
        return state

    def _parse_includes(state, node):
        skip_includes = ("arduino.h", "energia.h")
        matches = INCLUDES_RE.findall(node.get_text_contents())
        for (inc_type, inc_name) in matches:
            base_dir = dirname(node.get_abspath())
            if inc_name.lower() in skip_includes:
                continue
            if join(base_dir, inc_name) in state['paths']:
                continue
            else:
                state['paths'].add(join(base_dir, inc_name))

            finder = IncludeFinder(base_dir, inc_name, inc_type == "<")
            if finder.run():
                _parse_includes(state, env.File(finder.getIncPath()))

                _lib_dir = finder.getLibDir()
                if _lib_dir and _lib_dir not in state['libs']:
                    state['ordered'].add((
                        len(state['ordered']) + 1, finder.getLibName(),
                        _lib_dir))
                    state['libs'].add(_lib_dir)

                    if env.subst("$LIB_DFCYCLIC").lower() == "true":
                        state = _process_src_dir(state, _lib_dir)
        return state

    # end internal prototypes

    deplibs = _get_dep_libs(src_dir)
    for l, ld in deplibs:
        env.Append(
            CPPPATH=[join("$BUILD_DIR", l)]
        )
        # add automatically "utility" dir from the lib (Arduino issue)
        if isdir(join(ld, "utility")):
            env.Append(
                CPPPATH=[join("$BUILD_DIR", l, "utility")]
            )

    libs = []
    for (libname, inc_dir) in deplibs:
        lib = env.BuildLibrary(
            join("$BUILD_DIR", libname), inc_dir)
        env.Clean(libname, lib)
        libs.append(lib)
    return libs
dataset/ETHPy150Open platformio/platformio/platformio/builder/tools/platformio.py/BuildDependentLibraries